DeviceScript - TypeScript for microcontrollers
Tags: esp32, raspberrypi, iot, typescript
Published: 2023-05-17 03:26:27

> If you are familiar with TypeScript, but could never really catch on with embedded programming, this article is for you!

## TypeScript for microcontrollers

[DeviceScript ](https://microsoft.github.io/devicescript/) brings a professional TypeScript developer experience to low-resource microcontroller-based devices, like the [ESP32](https://microsoft.github.io/devicescript/devices/esp32) or [Raspberry Pi Pico](https://microsoft.github.io/devicescript/devices/rp2040).

Think of DeviceScript as a way to write TypeScript applications, not for the web or a backend or a phone but for a device that has only 64kb of RAM, runs on battery for months and can interface with tons of sensors and actuators.

## How does it work

The DeviceScript language is a [subset of TypeScript](https://microsoft.github.io/devicescript/language) designed to run efficiently on tiny microcontrollers with very limited storage and memory. Because it is TypeScript, you still benefit from the great developer experience in Visual Studio; on top of additional features provided by the DeviceScript extension.

The DeviceScript compiler then turns your code into a bytecode that is executed in a [virtual machine (written in C)](https://github.com/microsoft/devicescript/tree/main/runtime) on the microcontroller. The bytecode is designed to be compact and memory efficient.

From your point of view, it's just like you coding in TypeScript , yay!

## Blinky

Every embedded journey starts with a blinking LED and DeviceScript is no different. We will use a Raspberry Pi Pico in this example and we will flip a GPIO pin between high and low.

![A pico on a breadboard with an LED](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ow2sc0awar2076ecbzyr.png)

According to the [pico pinout diagram](https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html#pinout-and-design-files), the LED in the picture above is connected from pin 2, labelled **GP1** to ground.

> The full guide is available at https://microsoft.github.io/devicescript/getting-started/samples/blinky. Shorter version inlined.

### New project

After installing the DeviceScript [extension](https://microsoft.github.io/devicescript/getting-started/vscode) (there is also a [cli](https://microsoft.github.io/devicescript/getting-started/cli)), you can use the **DeviceScript: Create New Project...** option to start a new project.

The project looks very much like a npm-project with a package.json, a few helper files for IDEs and a ``main.ts`` file.


![Screenshot of file explorer with main.ts opened](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qvc0pbjade1h7e1lzjh6.png)


### A first (simulated) run

Open ``main.ts`` and click the **run** menu item on the file to start a debugging session.

The extension will look for a connected device and, if not found, will default to a simulator (which happens to be the [wasmed C runtime](https://microsoft.github.io/devicescript/api/vm)).


![Screenshot of device tree](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1yc83eaawmrp5rjf4bgz.png)


### Configuring hardware

Since we know the target microcontroller, we can click on the **wand** icon and import the pin mapping for the pico as well as starting a [lightbulb](https://microsoft.github.io/devicescript/api/servers/lightbulb) **server** on pin **P1**.

```ts
import { pins } from "@dsboard/pico"
import { startLightBulb } from "@devicescript/servers"

// start a lightbulb server on pin GP1
// and store client in `lightBulb` variable
const lightBulb = startLightBulb({
    pin: pins.P1,
})
```

> In DeviceScript, hardware is virtualized as [services](https://microsoft.github.io/devicescript/api/servers/lightbulb) where sensors are servers that clients in application can interact with him... just like servers and clients in the web.

### Read and write registers

To blink the LED, we call `toggle` on the ligh bulb client every second. `toggle` is async so we also add the `await` keyboard. 

```ts
import { pins } from "@dsboard/pico"
import { startLightBulb } from "@devicescript/servers"

const lightBulb = startLightBulb({
    pin: pins.P1,
})

// start interval timer every 1000ms
setInterval(async () => {
    // toggle brightness
    await lightBulb.toggle()
}, 1000)
```

Run this program. Since the program uses a light bulb service, the extension will suggest you to start a light bulb simulator (server) so that the client can be bound and send commands.

![Running with simulators](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sft83yohhfpnzyhv7m0m.png)


### Connecting the pico

So far, we've developed the code using simulators. It's time to hit the metal. Connect your [Raspberry Pi Pico](https://microsoft.github.io/devicescript/devices/rp2040) ( [ESP32](https://microsoft.github.io/devicescript/devices/esp32) is also supported), and flash the DeviceScript runtime firmware. Once this is done, it is ready to run the bytecode.

Click on the connect button again to connect your device and run your file... and blink the LED!

## Beyond Blinky

Obviously Blinky is just the start. DeviceScript opens the door to embedded programming for developer who are already familiar with TypeScript. Stay tuned for more articles or [dive into the docs](https://microsoft.github.io/devicescript/developer).