xxxxxxxxxx
142
var serial; // variable to hold an instance of the serialport library
var portName = '/dev/tty.usbmodem1101'; // fill in your serial port name here
//These global variables will hold incoming serial data.
//They'll be updated in serialEvent and referenced in draw.
var xAccel, yAccel, zAccel,
xGyro, yGyro, zGyro;
var freshData = false; //When new data comes in, we'll set this flag. If we see this flag is set in the draw loop, we'll set it back to false and request new data.
var lastData = -1; //We'll also request new data if a whole second goes by without data.
var dataTimeOut = 1000;
function setup() {
createCanvas(400, 300);
//All this is the standard serial stuff.
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
serial.open(portName); // open a serial port
}
function draw() {
//dark background, white text:
background(32);
fill(255);
noStroke();
// display the incoming serial data text on screen:
var xPos = 10, yPos = 10, yStep = 11; //these are just handy temporary variables for positioning the text on scree. This way if I want to move where the text is, or the spacing, I can adjust these instead of all 6 lines below
text("xAccel: " + xAccel, xPos, yPos+=yStep);
text("yAccel: " + yAccel, xPos, yPos+=yStep);
text("zAccel: " + zAccel, xPos, yPos+=yStep);
text("xGyro: " + xGyro, xPos, yPos+=yStep);
text("yGyro: " + yGyro, xPos, yPos+=yStep);
text("zGyro: " + zGyro, xPos, yPos+=yStep);
//XYZ traditionally mapped to RGB. We'll reuse xPos and yPos to position the axis symbol
xPos = width/2 - 50, yPos = height/2;
strokeWeight(10); //with a side stroke weight we can draw lines instead of think about rects.
var scale = 40; //The accelerometer reports values as multiples of earth's gravity (1g). So the range is ~-10-10 and it would be nive to scale it up enough to see clearly on the screen
//Draw Accelerometer so each axis grows acoording to the reported value.
stroke(255, 0, 0);
line(xPos, yPos, xPos+scale*yAccel, yPos); //I'm drawing the accelerometer's Y value on the X axis and vise versa because I think of the USB port as the "top" of the board
stroke(0,255,0);
line(xPos, yPos, xPos, yPos+scale*xAccel);
stroke(0,0,255);
strokeWeight(5);
line(xPos, yPos, xPos+scale*zAccel/2, yPos+scale*zAccel/2); //draw z on a diagonal
//Draw Gyro to the right of the accelerometer
xPos = width/2 + 50
scale = .5; //These values are much larger (degrees/second maybe?) so we'll shrink to fit
stroke(255, 0, 0);
strokeWeight(10);
line(xPos, yPos, xPos+scale*yGyro, yPos);
stroke(0,255,0);
line(xPos, yPos, xPos, yPos+scale*xGyro);
stroke(0,0,255);
strokeWeight(5);
line(xPos, yPos, xPos+scale*zGyro/2, yPos+scale*zGyro/2);
//Handle the freshData flag.
//Note - I'm doing this here because I was unable to write data out from within serial event. I suspect this is a change from a previous version where this was possible.
if (freshData || millis() - lastData > dataTimeOut) { //Having a timeout is useful because unlike previous Arduinos, the Nano doesn't reset upon serial connection, so it might no longer be waiting for a handshake to get started.
freshData = false;
lastData = millis();
serial.write('x');
}
}
// 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]); //bonus points: use javascripts "indexOf" string funtion to automatically find the port that's probably the arduino
}
}
let byteCount = 0;
function serialEvent() {
byteCount++;
var inString = serial.readLine();
//check that we got a whole line, because this could be called as often as once PER BYTE of incoming data
if (inString.length>0) {
console.log("Got " + byteCount + " bytes: ");
console.log(inString);
byteCount = 0;
//At this point, we've isolated one 'line' of data
freshData = true; //set this flag, for processing in the draw loop.
//serial.write('x'); //Just asking for new data here doesn't seem to work, I suspect p5serial was updated in a way that broke previous examples.
var temp = inString.split(","); //P5 also has a split() function that I'm guessing is a renamed version of this.
//print("Got " + temp.length + " elements");
if (temp.length==6) { //looks like a good packet, so let's assign the contents to our global variables
xAccel = Number(temp[0]);
yAccel = Number(temp[1]);
zAccel = Number(temp[2]);
xGyro = Number(temp[3]);
yGyro = Number(temp[4]);
zGyro = Number(temp[5]);
}
}
}
//Send r or g keystrokes to the Arduino to toggle the red and green LEDs:
function keyPressed() {
if (key=='b') serial.write('b');
else if (key=='g') serial.write('g');
else serial.write('x'); //this way, if the handshaking doesn't work, I can force a request for new data by hitting any key other than 'r' or 'g'
}
//Not much here, just report the event in the console:
function serverConnected() {
console.log('Connected to server.');
}
function portOpen() {
console.log('The serial port opened.');
serial.write('x'); //initiate data transfer
}
function serialError(err) {
console.log('Something went wrong with the serial port. ' + err);
}
function portClose() {
console.log('The serial port closed.');
}