For the most part this lab about two-way serial communication is fairly straightforward and basically the same as the serial communication lab. Since I was using the on board IMU I needed to adapt the code to access the data it produces.
For the most part this lab about two-way serial communication is fairly straightforward and basically the same as the serial communication lab. Since I was using the on board IMU I needed to adapt the code to access the data it produces. Easily done by adding begin.imu()
in the setup and instead of analogRead()
using accelerometerRead()
. The interesting part about using the internal IMU is how the library is written, the function always looks for three variables when executing the read. This was not made clear until I opened the library file in a text editor to find what the function was looking for. After that, the Arduino code performed as expected.
const int buttonPin = 2; // digital input int sensorValue0; int sensorValue1; int sensorValue2; void setup() { Serial.begin(9600);// configure the serial connection: pinMode(buttonPin, INPUT);// configure the digital input: while (Serial.available() <= 0) { Serial.println("hello"); // send a starting message delay(300); // wait 1/3 second } } void loop() { if (Serial.available() > 0) { int inByte = Serial.read(); sensorValue0 = analogRead(A0); Serial.print(sensorValue0); Serial.print(","); sensorValue1 = analogRead(A1); Serial.print(sensorValue1); Serial.print(","); // read the button: sensorValue2 = digitalRead(buttonPin); // print the results: Serial.println(sensorValue2); // Serial.print('\r\n'); } }
On the p5.js side the code was no issue at all. Straightforward and easy to understand. Until adding the handshake portion of the code. Everything populated as expected but selecting the port from the drop down menu did nothing. Nada. Zilch. Zero. So on to troubleshooting this. My thought was since the menu has had only one option and it is pre-selected the portSelector.changed(openPort)
call did nothing. So I plugged in a second Nano thinking this would help. It did not at first. The next thing I tried was to switch the boards since the board with the two-waySerialRead shows up as COM3, which is the first port on the list. So now if you’re still following, two Nano’s are plugged in the board with the correct code on it is connected to COM4 and the secondary board is connected at COM3. This enables me to select COM4 from the drop down and causes the portSelector.changed(openPort)
function to be called and bam!!! It works! I’m still playing with the code to see if I can have a null value populate the list before the first active COM in order to force the portSelector.changed(openPort)
function to be called.
var serial; // variable to hold an instance of the serialport library var portSelector; // a select menu for the port list var vert = 0; var horiz = 0; function setup() { frameRate(120); createCanvas(640, 480); // make canvas background(0); // black background smooth(); // antialias drawing lines 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.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 } // get the list of ports: function printList(portList) { // make a select menu and position it: portSelector = createSelect(); portSelector.position(10, 500); // 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]); // add item to the select menu: portSelector.option(portList[i]); } // set a handler for when a port is selected from the menu: portSelector.changed(openPort); } function openPort() { var thisPort = portSelector.value(); if (thisPort != null) { serial.open(thisPort); } } function serverConnected() { print('connected to server.'); } function portOpen() { console.log('the serial port opened.') // send a byte to prompt the microcontroller to send: serial.write('x'); } function serialError(err) { print('Something went wrong with the serial port. ' + err); } function portClose() { print('The serial port closed.'); } function serialEvent() { // read a string from the serial port // until you get carriage return and newline: var inString = serial.readStringUntil('\r\n'); //check to see that there's actually a string there: if (inString.length > 0) { if (inString !== 'hello') { // if you get hello, ignore it var sensors = split(inString, ','); // split the string on the commas if (sensors.length > 2) { // if there are three elements vert = map(sensors[0], 0, 1023, width, 0); horiz = map(sensors[1], 0, 1023, 0, height); if (sensors[2] != 0) { noStroke(); fill(0); rect(0, 0, width, height) } } } serial.write('x'); // send a byte requesting more serial data } } function draw() { fill(r, vert /2, horiz /2); noStroke(); ellipseMode(CENTER); ellipse(vert, horiz, 10, 10); // draw the circle // } // } }
The above code is to generate an Etch-A-Sketch with a color gradient of blue and green mapped to the x, y location of the ellipse()
The internal IMU has a fairly low range, as stated in the literature it is -4-4, which gives a low resolution but works nonetheless. I’m going to try and map the value from the IMU in a different way to combat this issue.