Can I send serial data from Snap! to a USB connected microcontroller

I've got the new RaspberryPi Pico and I just want to control the pins by simply sending micropython commands to it over its REPL

Just for proof of concept to switch the onboard LED off and on

I've got Node-RED sending stuff

but I'd like to do it from Snap!

Yes. Use the Serial API:

I think that way beyond my pay grade to be the 1st person to implement that in Snap! :slight_smile:
But I am making progress having enabled web-platform experimetal thing in my browser :slight_smile:

const port = navigator.serial.requestPort();
You can't do this, the Serial API is asynchronous.
Here's how you would do it:

function encodeString(str) {
  const buffer = new Uint8Array(str.length);
  for (let i = 0; i < str.length; ++i) buffer[i] = str[i].charCodeAt(0);
  return buffer;
async function writeString(writer, str) {
  const buffer = encodeString(str);
  await writer.write(buffer);
(async () => {
  const port = await navigator.serial.requestPort();
  await{ baudRate: 9600 });
  const writer = port.writable.getWriter();
  await writeString(writer, 'from machine import Pin');

This is way beyond my JavaScript knowledge
webserial script pic

There was a typo, try running the code now.

No error but what I need to do is send 3 strings one after each other so I tried this but my LED didn't light


I believe you need to add a newline (\r\n), but I'm not sure.

Your right - my NodeRED solution adds \r to each string
Tried it with this but is didn't make any difference :frowning:

I think I'll need to replace the Pico with a Pi so I can see if any serial data is going out


function encodeString(str) {
return buffer;

We have a LED on :slight_smile:
webserial script pic (1)

Eureka - 1st block sets it up
2nd and third switch the LED on and off

Many thanks @programmer_user (and @dardoro for his crucial addition) :slight_smile:


How did I not notice that? Thanks, I've edited my post.

You should probably encapsulate the functionality into a block that sends Python code to the Pi.

yep - that's the ultimate plan
Block to select and open the port
Block to close it

Then parameterised blocks to setup and read and write to the pins.

I've hit a bit of a problem (presumably due to the async code)

If I try to wrap the opening function in a custom block - my browser just starts eating up memory and have have to kill it using task manager :frowning:

Any ideas on how to get around this?

Where's your code?

I tried creating a simple custom command block to simply wrap the call block reporter

In general I worry about using await in Snap! blocks. The reason it was designed to be asynchronous is that it might take a long time to work. While it is waiting nothing else can happen.

While more complex, I prefer passing in a command to the custom block (in this case the one that is opening a port) and calling it when the asynchronous function (navigator.serial.requestPort in this case) returns a value.