This post consists of 3 different labs all focused on serial communication between the computer and Nano 33IoT
Code used to obtain data from the onboard IMU of the Arduino Nano IoT
Lab: Intro to Asynchronous Serial Communications
#include <Arduino_LSM6DS3.h> void setup() { Serial.begin(9600); IMU.begin(); while (Serial.available() <= 0) { //while (IMU.accelerationAvailable() <= 0) { Serial.println("hello"); // send a starting message delay(300); // wait 1/3 second } } void loop () { float aX, aY, aZ; float gX, gY, gZ; const char * comma = ", "; if (IMU.accelerationAvailable() && IMU.gyroscopeAvailable() && Serial.available()); int inByte = Serial.read(); IMU.readAcceleration(aX, aY, aZ); IMU.readGyroscope(gX, gY, gZ); Serial.print(aX); Serial.print(comma); Serial.print("aX"); Serial.print(comma); Serial.print(aY); Serial.print(comma); Serial.print("aY"); Serial.print(comma); Serial.print(aZ); Serial.print(comma); Serial.print("aZ"); Serial.print(comma); Serial.print(gX); Serial.print(comma); Serial.print("gX"); Serial.print(comma); Serial.print(gY); Serial.print(comma); Serial.print("gY"); Serial.print(comma); Serial.println(gZ); Serial.println("gZ"); }
Lab: Serial Input to p5.js
I started with a sketch to enable communication from the Nano 33IoT to the computer, this communication enabled the computer to know which port the Nano was connected to. Using an intermediary program called P5.serialcontrol I was able to find the port that the Nano was connected to, in my case it was COM4. The code below is for the Nano.
void setup() { Serial.begin(9600); // initialize serial communications } void loop() { int potentiometer = analogRead(A0); // read the input pin int mappedPot = map(potentiometer, 0, 1023, 0, 255); // remap the pot value to fit in 1 byte Serial.write(mappedPot); // print it out the serial port delay(1); // slight delay to stabilize the ADC }
This next code is from p5.js.
let serial; // variable to hold an instance of the serialport library function setup() { serial = new p5.SerialPort(); // make a new instance of the serialport library serial.on('list', printList); // set a callback function for the serialport list event serial.list(); // list the serial ports } // get the list of ports: function printList(portList) { // portList is an array of serial port names for (var i = 0; i < portList.length; i++) { // Display the list the console: console.log(i + portList[i]); } }
After the I knew the port, the next task was communication between the Nano and the p5.js web editor, this is no easy task luckily the aforementioned program , P5.serialcontrol comes to the rescue again. This is especially important for this communication to work since the p5.js environment and the Nano cannot natively communicate. The code is rather complex and includes a library file.
The library file is very long find it at the link below.
https://github.com/p5-serial/p5.serialport/blob/master/lib/p5.serialport.js
Here is the code to interface with the potentiometer connected to the Nano.
// let serial; // variable to hold an instance of the serialport library // function setup() { // serial = new p5.SerialPort(); // make a new instance of the serialport library // serial.on('list', printList); // set a callback function for the serialport list event // serial.list(); // list the serial ports // } // // get the list of ports: // function printList(portList) { // // portList is an array of serial port names // for (var i = 0; i < portList.length; i++) { // // Display the list the console: // console.log(i + portList[i]); // } // } let xPos = 0; let serial; // variable to hold an instance of the serialport library let portName = 'COM4'; // fill in your serial port name here let inData; // for incoming se function setup() { createCanvas(1200, 500); background(0x08, 0x16, 0x40); serial = new p5.SerialPort(); // make a new instance of the serialport library serial.list(); serial.open('COM4'); serial.on('list', printList); // set a callback function for the serialport list event serial.on('connected', serverConnected); // callback for connecting to the server serial.on('open', portOpen); // callback for the port opening serial.on('data', serialEvent); // callback for when new data arrives serial.on('error', serialError); // callback for errors serial.on('close', portClose); // callback for the port closing // serial.list(); // list the serial ports // serial.open(portName); // open a serial port } function graphData(newData) { // map the range of the input to the window height: var yPos = map(newData, 0, 255, 0, height); // draw the line in a pretty color: stroke(0xA8, 0xD9, 0xA7); line(xPos, height, xPos, height - yPos); // at the edge of the screen, go back to the beginning: if (xPos >= width) { xPos = 0; // clear the screen by resetting the background: background(0x08, 0x16, 0x40); } else { // increment the horizontal position for the next reading: xPos++; } } // get the list of ports: function printList(portList) { // portList is an array of serial port names for (var i = 0; i < portList.length; i++) { // Display the list the console: console.log(i + portList[i]); } } function serverConnected() { console.log('connected to server.'); } function portOpen() { console.log('the serial port opened.') } function serialEvent() { inData = Number(serial.read()); } function serialError(err) { console.log('Something went wrong with the serial port. ' + err); } function portClose() { console.log('The serial port closed.'); } function draw(){ // background(0); // fill(255); // text("sensor value: " + inData, 2, 10); graphData(inData); }
Lab: Serial Output From p5.js
Here I some input happening in p5.js and need to have the Nano do something, in this case light a red LED.
Here is the code for the Nano.
const int ledPin = 5; // the pin that the LED is attached to int incomingByte; // a variable to read incoming serial data into void setup() { Serial.begin(9600); // initialize serial communication pinMode(ledPin, OUTPUT); // initialize the LED pin as an output } void loop() { if (Serial.available() > 0) { // see if there's incoming serial data incomingByte = Serial.read(); // read it if (incomingByte == 'H') { // if it's a capital H (ASCII 72), digitalWrite(ledPin, HIGH); // turn on the LED // if you're using a speaker instead of an LED, uncomment line below and comment out the previous line: // tone(5, 440); // play middle A on pin 5 } if (incomingByte == 'L') { // if it's an L (ASCII 76) digitalWrite(ledPin, LOW); // turn off the LED // if you're using a speaker instead of an LED, uncomment line below and comment out the previous line: // noTone(5); } } }
Again we need to include the library file for P5.serialcontrol
The library file is very long find it at the link below.
https://github.com/p5-serial/p5.serialport/blob/master/lib/p5.serialport.js
And here is the p5.js code to turn on the red LED
var serial; // variable to hold an instance of the serialport library var portName = 'COM3'; // fill in your serial port name here var inData; // for incoming serial data var outByte = 0; // for outgoing data function setup() { createCanvas(400, 300); // make the canvas serial = new p5.SerialPort(); // make a new instance of the serialport library serial.on('data', serialEvent); // callback for when new data arrives serial.on('error', serialError); // callback for errors serial.open(portName); // open a serial port } function serialEvent() { // read a byte from the serial port: var inByte = serial.read(); // store it in a global variable: inData = inByte; } function serialError(err) { println('Something went wrong with the serial port. ' + err); } function draw() { // black background, white text: background(0); fill(255); // display the incoming serial data as a string: text("incoming value: " + inData, 30, 30); } function mouseDragged() { // map the mouseY to a range from 0 to 255: outByte = int(map(mouseY, 0, height, 0, 255)); // send it out the serial port: serial.write(outByte); } function keyPressed() { if (key >= 0 && key <= 9) { // if the user presses 0 through 9 outByte = byte(key * 25); // map the key to a range from 0 to 225 } serial.write(outByte); // send it out the serial port }
The previous five videos show various different interactions with the Nano using serial communication. Once I understood what was happening and how to alter the code inside p5.js to communicate the way I wanted it to this process wasn’t too bad, now if I had to write that library file…I’m not sure if I’d know where to start.