# DeviceScript, TypeScript for Microcontrollers

## What is DeviceScript?

[DeviceScript](https://microsoft.github.io/devicescript) is a project that aims at bringing a [TypeScript](https://www.typescriptlang.org/) development experience to microcontrollers. 

TypeScript is JavaScript with syntax for types. DeviceScript supports [a subset of TypeScript](https://microsoft.github.io/devicescript/language). The TypeScript sources are compiled to a compact bytecode which is executed on the microcontroller by a native runtime. It is in many ways similar to CircuitPython, but for TypeScript instead.

_DeviceScript is an **incubation** project from Microsoft Research by the same team that started MakeCode._


![](https://cdn-learn.adafruit.com/assets/assets/000/123/089/medium800/microcontrollers_hero.png?1690464796)

## Blinky

To get started, this little program blinks the onboard LED on your device. It can be run on a simulator or on a physical device. Follow this guide to learn more.

```javascript
// A blinking animation on the onboard LED
import { delay } from "@devicescript/core"
import { setStatusLight } from "@devicescript/runtime"

// start an interval time every 10ms
setInterval(async () =&gt; { // async, await!
    // turn off
    await setStatusLight(0)
    await delay(1000)
    // turn on
    await setStatusLight(0x0f0f0f)
    await delay(1000)
}, 10)
```

## Supported Hardware

DeviceScript is current supported on ESP32 and RP2040 ([full list](https://microsoft.github.io/devicescript/devices)). In particular, DeviceScript already provides the pinout configuration for various Adafruit boards such as the [QT Py ESP32-C3 WiFi](https://microsoft.github.io/devicescript/devices/esp32/adafruit-qt-py-c3). More can be [added...](https://microsoft.github.io/devicescript/devices/add-board)



## Guides

This guide will build a program that collects sensor data (temperature) and uploads it to Adafruit IO. A few aspects of DeviceScript are covered that are relevant to Adafruit hardware, and Adafruit IO. 


For more in-depth information, refer to the [DeviceScript documentation](https://microsoft.github.io/devicescript).

# DeviceScript, TypeScript for Microcontrollers

## Development Experience

The best developer experience is found by [installing the extension](https://microsoft.github.io/devicescript/getting-started) in [Visual Studio Code](https://code.visualstudio.com/download). A command line interface is also available, but a lot of work was done with the extension to improve the developer experience.

The extension bundles the compiler, firmware flasher, debugger, simulators, console log and other goodies.

![](https://cdn-learn.adafruit.com/assets/assets/000/123/112/medium800/microcontrollers_hero.png?1690465580)

## Console Logging

You can use `console` to log message as in your usual JavaScript projects. DeviceScript will automitcally collect the message sent to `console.log` (and `debug`, ...) and show them in the Visual Studio Code terminal.

```javascript
console.debug("debug")
console.log("log")
console.warn("warn")
console.error("error")
```

![](https://cdn-learn.adafruit.com/assets/assets/000/123/081/medium800/microcontrollers_consolelog.png?1690463939)

DeviceScript also introduce a new logging function, `console.data`, that specializes on logging and collecting numerical values. Data streams collected with `console.data` can be exported to CSV files and Jupyter notebooks.

```javascript
const temp = 20
const humi = 60

console.data({ temp, humi })
```

![](https://cdn-learn.adafruit.com/assets/assets/000/123/100/medium800/microcontrollers_jupyter.png?1690465003)

## Simulation

Before testing your code on hardware, you can use simulators. Simulators will run on your computer (even on containers) and can greatly help with the development experience.

In Visual Studio Code, when you try to start this sample, DeviceScript will first try to use any connected microcontrollers. If it does not find any, it will launch a [device simulator](https://microsoft.github.io/devicescript/getting-started/vscode/simulation). The device simulator runs the DeviceScript native runtime compiled to [Web assembly](https://microsoft.github.io/devicescript/api/vm). Simulated sensors can also be spun up using the simulator dashboard so that the entire system runs virtually on your computer (this also works if you are developing from a container).

![](https://cdn-learn.adafruit.com/assets/assets/000/123/082/medium800/microcontrollers_simexplorer.png?1690464139)

When you start running a program, the DeviceScript simulator view will start. If it detects that you need a service that is not available, for example you need a temperature sensor but it is not detected, the view will sugest to start one for you. Make sure to click **AUTO START** to spin off a temperature sensor since you need one to run this program.

```javascript
import { Temperature } from "@devicescript/core"
// needs a simulator
const temperature = new Temperature()

setInterval(async () =&gt; {
    // blocks until a temperature server is found
    const temp = await temperature.reading.read()
    console.data({ temp })
}, 1000)
```

![](https://cdn-learn.adafruit.com/assets/assets/000/123/083/medium800/microcontrollers_autostart.png?1690464406)

Once the simulated sensors are running, you will typically have a slider or other interaction UI to change the values.

![](https://cdn-learn.adafruit.com/assets/assets/000/123/084/medium800/microcontrollers_data.png?1690464470)

## Debugging

You can set breakpoints, step and inspect variables in the [debugger](https://microsoft.github.io/devicescript/getting-started/vscode/debugging)... As long as your program is not too time sensitive, this can aid with debugging your programs.

You can also use console.log. DeviceScript also provides [`console.data`](https://microsoft.github.io/devicescript/developer/console) which is a specialized logging function for sensor data, which can be exported to a Jupyter Notebook for later analysis. 

## Running on Hardware

You can run and debug the code running on the physical device as well. Click on the **connect** (plug) button in the DeviceScript view and select Serial. The device will be automatically discovered and the simulator will be stopped. Make sure to flash the firmware before this step.

The developer experience is pretty much the same from there. You can set breakpoints, use `console.log`, etc... Unlike the simulated sensors, you cannot drag a slider to change the sensor data... you might have to blow on it or put it in the fridge!

![](https://cdn-learn.adafruit.com/assets/assets/000/123/110/medium800/microcontrollers_connect.png?1690465388)

## Remote workspaces

DeviceScript also supporting developing in remote workspaces, like Docker, GitHub Codespaces, Windows WSL or other virtualization frameworks.

The Visual Studio Code extension runs in the container and does not have access to serial or USB on the host operating system; so it launches a seperate browser page to handle the connection to the physical device through WebSerial/WebUSB. Other than that, the experience is pretty much the same.

![](https://cdn-learn.adafruit.com/assets/assets/000/123/114/medium800/microcontrollers_remote.png?1690466503)

# DeviceScript, TypeScript for Microcontrollers

## Flash Firmware

Before being able to download DeviceScript programs to your microcontrollers, you will need to flash the native runtime. The native runtime is currently available for ESP32 and RP2040. 

Of course, reality is a bit more complicated at the [support table](https://microsoft.github.io/devicescript/devices) gives you a rundown of which features is enable for the various SKUs of those chipsets.




### Adafruit QT Py ESP32-C3 WiFi Dev Board with STEMMA QT

[Adafruit QT Py ESP32-C3 WiFi Dev Board with STEMMA QT](https://www.adafruit.com/product/5405)
What's life without a little RISC? This miniature dev board is perfect for small projects: it comes with&nbsp;[our favorite connector - the STEMMA QT](http://adafruit.com/stemma), a chainable I2C port, WiFi, Bluetooth® LE, and plenty of FLASH and RAM memory for many IoT...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5405)
[Related Guides to the Product](https://learn.adafruit.com/products/5405/guides)
![Angled shot of an Adafruit QT Py ESP32-C3 WiFi Dev Board with STEMMA QT.](https://cdn-shop.adafruit.com/640x480/5405-00.jpg)

### Adafruit ESP32-S2 Feather - 4 MB Flash + 2 MB PSRAM

[Adafruit ESP32-S2 Feather - 4 MB Flash + 2 MB PSRAM](https://www.adafruit.com/product/5000)
What's Feather-shaped and has an ESP32-S2 WiFi module? What has a STEMMA QT connector for I2C devices? What has your favorite Espressif WiFi microcontroller and lots of Flash and RAM memory for your next IoT project? What will make your next IoT project flyyyyy?

That's right -...

In Stock
[Buy Now](https://www.adafruit.com/product/5000)
[Related Guides to the Product](https://learn.adafruit.com/products/5000/guides)
![Angled shot of rectangular microcontroller.](https://cdn-shop.adafruit.com/640x480/5000-12.jpg)

## Flash Firmware

In Visual Studio Code, you will run the **Flash Firmware...** command that will drive through choosing the correct board, downloading the firmware and launching the appropriate tool to flash it.
This is typically a one-time experience, until you have a need to update the runtime.

For ESP32, you will need to have esptool installed. For RP2040, it is a UF2 file copy to the bootloader drive so you don't need any tool.

## Board configuration

After this step, you will need to import the board configuration to setup the pins, I2C and SPI services.
DeviceScript maintains a list of [known devices](https://microsoft.github.io/devicescript/devices) for which it has a configuration, including the QT Py ESP32-C3 or the Feather ESP32-S2. It is also possible to fork pinout configurations (and contribute them back).

The configuration is loaded by imported the module for your board.

```javascript
import { pins, board } from "@dsboard/adafruit_qt_py_c3"
```

# DeviceScript, TypeScript for Microcontrollers

## Using Sensors

## Temperature and Humidity sensing

DeviceScript provides a driver for the [SHTC3](https://microsoft.github.io/devicescript/api/drivers/shtc3) temperature and humidity sensor. 

The driver handles the low-level I2C communication protocol to the hardware and exposes a [temperature](https://microsoft.github.io/devicescript/api/clients/temperature) and humidity service to DeviceScript. The [services](https://microsoft.github.io/devicescript/api/clients) are the abstraction layer to interact with hardware.


```javascript
import { startSHTC3 } from "@devicescript/drivers"

// temperature and humidity are clients for the sensor servers
const { temperature, humidity } = await startSHTC3()
```

### Adafruit Sensirion SHTC3 Temperature & Humidity Sensor

[Adafruit Sensirion SHTC3 Temperature & Humidity Sensor](https://www.adafruit.com/product/4636)
Sensirion Temperature/Humidity sensors are some of the finest & highest-accuracy devices you can get. And&nbsp;finally, we have some that have a true I2C interface for easy reading. The&nbsp; **SHTC3** &nbsp;sensor has an excellent ±2% relative humidity and ±0.2...

In Stock
[Buy Now](https://www.adafruit.com/product/4636)
[Related Guides to the Product](https://learn.adafruit.com/products/4636/guides)
![Angled shot of small, black, rectangular humidity and temperature sensor breakout.](https://cdn-shop.adafruit.com/640x480/4636-05.jpg)

A temperature service has a `reading` register that can be `read` to retreive the temperature in Celcius, regardless of the underlying hardware. Registers, like the servo angle, are also writeable.

In the example below, we read the temperature and print it to the console. The console output will automatically be displayed.





```javascript
import { startSHTC3 } from "@devicescript/drivers"

const { temperature, humidity } = await startSHTC3()

// run every 5 seconds
setInterval(async () =&gt; {
    // read data from temperature sensor
    const value = await temperature.reading.read()
    // print sensor value
    console.log({ value })
}, 5000)
```

![](https://cdn-learn.adafruit.com/assets/assets/000/123/113/medium800/microcontrollers_remote.png?1690465941)

# DeviceScript, TypeScript for Microcontrollers

## Settings and Secrets

Before we start uploading data to the cloud, we need a way to store the connection secrets (WiFi password, Adafruit IO key) to the device... without hardcoding it into our source code. This is done with [settings files (.env)](https://microsoft.github.io/devicescript/developer/settings) in DeviceScript.

## .env files

Click on the **configure** icon (wand) and select **Add Settings** to add two files to the project:

-  `.env.default`, contains publich settings such as your Adafruit username. This file can be added to your source control system.
-  `.env.local`, contains your secrets. This file should **NOT** be added to your source control system

```python
# env.defaults
# public settings, commit to source control
WIFI_SSID=your-wifi-ssid
IO_USERNAME=your_adafruit_io_user
IO_FEED=your_adafruit_io_feed
```

```auto
# env.local
# secrets, don't commit to source control
IO_KEY=your_secret_key
WIFI_PWD=your_wifi_password
```

## Using Settings

When DeviceScript uploads your program to the device, it will also communicate and send the settings to be stored in flash. The settings can be read on the device using `readSetting`.

The `WIFI_SSID` and `WIFI_PWD` are automatically used by the native WiFi service when trying to connect.

```auto
import { readSetting } from "@devicescript/settings"

const key = await readSetting("IO_KEY")
const user = await readSetting("IO_USERNAME")
const feed = await readSetting("IO_FEED")
```

# DeviceScript, TypeScript for Microcontrollers

## Publish to Adafruit IO

Next is to add code to upload the sensor data to an Adafruit IO feed. DeviceScript supports the HTTPS and MQTT endpoints.

## Post data to Adafruit IO

Adafruit IO supports a [POST HTTPS endpoint](https://io.adafruit.com/api/docs/#create-data) to add a data entry to a feed. 

First the program collects the Adafruit IO feed information `user` and `feed`, the Adafruit.io key `key` and reads the temperature from the sensor `value`; then to use the `fetch` function to issue an HTTP POST request to the secure endpoint of Adafruit.io.

```auto
import { fetch } from "@devicescript/net"

// collect connection info and data
const user = ...
const feed = ...
const key = ...
const value = await temperature.reading.read()

// craft Adafruit.io payload and send POST request
await fetch(`https://io.adafruit.com/api/v2/${user}/feeds/${feed}/data`, { 
    method: "POST", 
    headers: { "X-AIO-Key": key, "Content-Type": "application/json" }, 
    body: JSON.stringify({ value }),
})
```

## devicescript-adafruit-io package

The [devicescript-adafruit-io](https://github.com/pelikhan/devicescript-adafruit-io) package on GitHub may be used to simplify using Adafruit IO. 

DeviceScript supports sharing code and libraries through [npm](https://microsoft.github.io/devicescript/developer/packages/custom) or GitHub. It also supports MQTT.

Use the command below to install the package in your project.



```terminal
npm install --save pelikhan/devicescript-adafruit-io#v0.0.4
```

The package provides `createData` which wraps reading the settings and secrets, crafting a POST request and analyzing the results.

```javascript
import { createData } from "devicescript-adafruit-io"
const value = await temperature.reading.read()
const status = await createData(value)
console.log({ status })
```

## Final snippet on QT Py ESP32-C3

On the QT Py ESP32-C3 board, the full sample looks as follows.

There is also a `schedule` helper that starts an interval where the first delay is configurable (great for debugging).

```javascript
import { pins, board } from "@dsboard/adafruit_qt_py_c3"
import { startSHTC3 } from "@devicescript/drivers"
import { schedule } from "@devicescript/runtime"
import { createData } from "devicescript-adafruit-io"

const { temperature, humidity } = await startSHTC3()

schedule(async () =&gt; {
    const value = await temperature.reading.read()
    await createData(value)
}, { timeout: 1000, interval: 60000 })
```

### Adafruit QT Py ESP32-C3 WiFi Dev Board with STEMMA QT

[Adafruit QT Py ESP32-C3 WiFi Dev Board with STEMMA QT](https://www.adafruit.com/product/5405)
What's life without a little RISC? This miniature dev board is perfect for small projects: it comes with&nbsp;[our favorite connector - the STEMMA QT](http://adafruit.com/stemma), a chainable I2C port, WiFi, Bluetooth® LE, and plenty of FLASH and RAM memory for many IoT...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5405)
[Related Guides to the Product](https://learn.adafruit.com/products/5405/guides)
![Angled shot of an Adafruit QT Py ESP32-C3 WiFi Dev Board with STEMMA QT.](https://cdn-shop.adafruit.com/640x480/5405-00.jpg)

### Adafruit Sensirion SHTC3 Temperature & Humidity Sensor

[Adafruit Sensirion SHTC3 Temperature & Humidity Sensor](https://www.adafruit.com/product/4636)
Sensirion Temperature/Humidity sensors are some of the finest & highest-accuracy devices you can get. And&nbsp;finally, we have some that have a true I2C interface for easy reading. The&nbsp; **SHTC3** &nbsp;sensor has an excellent ±2% relative humidity and ±0.2...

In Stock
[Buy Now](https://www.adafruit.com/product/4636)
[Related Guides to the Product](https://learn.adafruit.com/products/4636/guides)
![Angled shot of small, black, rectangular humidity and temperature sensor breakout.](https://cdn-shop.adafruit.com/640x480/4636-05.jpg)


## Featured Products

### Adafruit QT Py ESP32-C3 WiFi Dev Board with STEMMA QT

[Adafruit QT Py ESP32-C3 WiFi Dev Board with STEMMA QT](https://www.adafruit.com/product/5405)
What's life without a little RISC? This miniature dev board is perfect for small projects: it comes with&nbsp;[our favorite connector - the STEMMA QT](http://adafruit.com/stemma), a chainable I2C port, WiFi, Bluetooth® LE, and plenty of FLASH and RAM memory for many IoT...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5405)
[Related Guides to the Product](https://learn.adafruit.com/products/5405/guides)
### Adafruit QT Py ESP32-S3 WiFi Dev Board with STEMMA QT

[Adafruit QT Py ESP32-S3 WiFi Dev Board with STEMMA QT](https://www.adafruit.com/product/5426)
The ESP32-S3 has arrived in QT Py format - and what a great way to get started with this powerful new chip from Espressif! With dual 240 MHz cores, WiFi and BLE support, and native USB, this QT Py is great for powering your IoT projects.

The ESP32-S3&nbsp;is a highly-integrated,...

In Stock
[Buy Now](https://www.adafruit.com/product/5426)
[Related Guides to the Product](https://learn.adafruit.com/products/5426/guides)
### Adafruit QT Py ESP32-S2 WiFi Dev Board with STEMMA QT

[Adafruit QT Py ESP32-S2 WiFi Dev Board with STEMMA QT](https://www.adafruit.com/product/5325)
What has your favorite Espressif WiFi microcontroller, comes with&nbsp;[our favorite connector - the STEMMA QT](http://adafruit.com/stemma), a chainable I2C port, and has lots of Flash and RAM memory for your next IoT project? What will make your next IoT project flyyyyy? What a...

In Stock
[Buy Now](https://www.adafruit.com/product/5325)
[Related Guides to the Product](https://learn.adafruit.com/products/5325/guides)
### Adafruit Feather RP2040

[Adafruit Feather RP2040](https://www.adafruit.com/product/4884)
A new chip means a new Feather, and the Raspberry Pi RP2040 is no exception. When we saw this chip we thought "this chip is going to be awesome when we give it the Feather Treatment" and so we did! This Feather features the&nbsp; **RP2040** , and all niceties you know and...

In Stock
[Buy Now](https://www.adafruit.com/product/4884)
[Related Guides to the Product](https://learn.adafruit.com/products/4884/guides)
### Raspberry Pi Pico RP2040

[Raspberry Pi Pico RP2040](https://www.adafruit.com/product/4864)
The Raspberry Pi foundation changed single-board computing [when they released the Raspberry Pi computer](https://www.raspberrypi.org/archives/723), now they're ready to do the same for microcontrollers with the release of the brand new **Raspberry Pi Pico**. This...

In Stock
[Buy Now](https://www.adafruit.com/product/4864)
[Related Guides to the Product](https://learn.adafruit.com/products/4864/guides)
### USB Type A to Type C Cable - approx 1 meter / 3 ft long

[USB Type A to Type C Cable - approx 1 meter / 3 ft long](https://www.adafruit.com/product/4474)
As technology changes and adapts, so does Adafruit. This&nbsp;&nbsp; **USB Type A to Type C** cable will help you with the transition to USB C, even if you're still totin' around a USB Type A hub, computer or laptop.

USB C is the latest industry-standard connector for...

In Stock
[Buy Now](https://www.adafruit.com/product/4474)
[Related Guides to the Product](https://learn.adafruit.com/products/4474/guides)
### USB cable - USB A to Micro-B

[USB cable - USB A to Micro-B](https://www.adafruit.com/product/592)
This here is your standard A to micro-B USB cable, for USB 1.1 or 2.0. Perfect for connecting a PC to your Metro, Feather, Raspberry Pi or other dev-board or microcontroller

Approximately 3 feet / 1 meter long

Out of Stock
[Buy Now](https://www.adafruit.com/product/592)
[Related Guides to the Product](https://learn.adafruit.com/products/592/guides)

## Related Guides

- [Introducing Adafruit Feather RP2040](https://learn.adafruit.com/adafruit-feather-rp2040-pico.md)
- [Adafruit QT Py ESP32-S2 and QT Py ESP32-S2 with uFL Antenna](https://learn.adafruit.com/adafruit-qt-py-esp32-s2.md)
- [Adafruit QT Py ESP32-C3 WiFi Dev Board](https://learn.adafruit.com/adafruit-qt-py-esp32-c3-wifi-dev-board.md)
- [Adafruit QT Py ESP32-S3](https://learn.adafruit.com/adafruit-qt-py-esp32-s3.md)
- [Cheekmate - a Wireless Haptic Communication System](https://learn.adafruit.com/cheekmate-wireless-haptic-communication.md)
- [Desk Calculator with CircuitPython](https://learn.adafruit.com/desk-calculator-with-circuitpython.md)
- [MIDI for Makers](https://learn.adafruit.com/midi-for-makers.md)
- [Discord and Slack Connected Smart Plant with Adafruit IO Actions](https://learn.adafruit.com/discord-and-slack-connected-smart-plant-with-adafruit-io-triggers.md)
- [Mini GIF Players](https://learn.adafruit.com/mini-gif-players.md)
- [MIDI Laser Harp with Time of Flight Distance Sensors](https://learn.adafruit.com/midi-laser-harp-time-of-flight-sensors.md)
- [Super Simple Sunrise Lamp](https://learn.adafruit.com/super-simple-sunrise-lamp.md)
- [Touch Deck: DIY Customizable TFT Control Pad](https://learn.adafruit.com/touch-deck-diy-tft-customized-control-pad.md)
- [Optical Sensor Drum Track Sequencer](https://learn.adafruit.com/drum-track-sequencer.md)
- [CircuitPython Web Workflow Code Editor Quick Start](https://learn.adafruit.com/getting-started-with-web-workflow-using-the-code-editor.md)
- [Edit CircuitPython Code on iOS with Runestone](https://learn.adafruit.com/editing-circuitpython-on-ios-with-runestone.md)
- [Motorized POV LED Display](https://learn.adafruit.com/motorized-pov-led-display.md)
- [Scrolling Countdown Timer](https://learn.adafruit.com/scrolling-countdown-timer.md)
- [Cooperative Multitasking in CircuitPython with asyncio](https://learn.adafruit.com/cooperative-multitasking-in-circuitpython-with-asyncio.md)
- [LED Matrix Alarm Clock](https://learn.adafruit.com/led-matrix-alarm-clock.md)
