The Picoboard and Processing
The sparkfun Picoboard is a great little device that lets you add some physical input to Scratch. It allows you to measure 4 resistance values, has a button, detect sound and light, and also has a slider. All of these send 10-bit analogue data back to the computer via a USB port. In Scratch the inputs are available on the “Sensing” tab, see below.
But, I wondered, could you use the board with Processing? It turns out you can if you know how to talk to the board. Fortunately, the wonderful people at Scratch have published this information here.
To get information from the Picoboard you have to set up a serial port and send a request for data. This is done by sending a value 1 (not the digit). The board responds by sending 18 bytes as a series of high/low pairs from which the sensor data can be reconstructed. If you’re interested in the details, please see the tech info on the above Scratch link.
The Processing code I produced to communicate with the board is given below. When experimenting, I found that operation is more reliable if you ensure you read complete 18-byte packets of data at a time, otherwise some confusion arose if values were changing quickly and/or data was being requested at too high a rate.
import processing.serial.*;
Serial port; // Create object from Serial class
int b1,b2; // byte pairs from the data packet
int i; // general loop counter
int[] ChanValues={0,0,0,0,0,0,0,0}; // the 8 channel values
int[] ValBuffer=new int[18]; // the 18 byte data packet from the Picoboard
int Channel; // used to identify the channel the data corresponds to
int Val; // the value of the channel
void setup() {
size(1035, 245);
// SERIAL SET UP EXTRACT FROM:
// Example 11-07 from "Getting Started with Processing"
// by Reas & Fry. O'Reilly / Make 2010
//
// see Ex_11_07 in Chapter 11 of Books->Getting Started in the Examples menu (File->Examples)
//
// IMPORTANT NOTE:
// The first serial port retrieved by Serial.list()
// should be your Arduino. If not, uncomment the next
// line by deleting the // before it. Run the sketch
// again to see a list of serial ports. Then, change
// the 0 in between [ and ] to the number of the port
// that your Arduino is connected to.
// println(Serial.list());
String arduinoPort = Serial.list()[0];
port = new Serial(this, arduinoPort, 38400); // Picoboard works at 38.4k
// set up a frame rate
frameRate(50);
// send a request to the board to supply values
port.write(1);
}
void draw()
{
// reading from the picoboard requires a bit of care to get a full packet
// read when at least 18 bytes of data are available
if(port.available()>=18)
{
// take the first 18 bytes
// these are 2-byte hi/lo pairs for 8 input channels + firmware version (channel 15)
for (i=0;i<18;i++)
{
ValBuffer[i]=port.read();
}
// find the 10-bit values for channels 0-7
// channel Sensor
// 0 D
// 1 C
// 2 B
// 3 Button
// 4 A
// 5 Light
// 6 Sound
// 7 Slider
for (i=0;i<18;i+=2)
{
b1=ValBuffer[i];
b2=ValBuffer[i+1];
Channel=(b1&120)>>3;
Val=((b1&7)<<7)+(b2&127); //channel value is bits 0-2 of hi byte and bits 0-6 of lo byte
if (Channel<8) ChanValues[Channel]=Val; // only store value if channel is in range 0-7
}
// sometimes there's extra data if things change fast and the FPS value is high
// better performance is obtained if you ignore these partials and get a full set,
// so read anything left in the buffer to flush it.
while(port.available()>0)
{
b1=port.read();
}
// buffer now empty - ask for more data
port.write(1);
}
// show values in monitor
println(ChanValues[0]+", "+ChanValues[1]+", "+ChanValues[2]+", "+ChanValues[3]+", "+ChanValues[4]+", "+ChanValues[5]+", "+ChanValues[6]+", "+ChanValues[7]);
// plot bars to represent values
background(0);
fill(255,0,0); rect(5,5,ChanValues[0],25); // D
fill(235,30,0); rect(5,35,ChanValues[1],25); // C
fill(215,60,0); rect(5,65,ChanValues[2],25); // B
fill(195,90,0); rect(5,95,ChanValues[3],25); // Button
fill(175,120,0); rect(5,125,ChanValues[4],25); // A
fill(1555,150,0); rect(5,155,ChanValues[5],25); // Light
fill(135,180,0); rect(5,185,ChanValues[6],25); // Sound
fill(115,210,0); rect(5,215,ChanValues[7],25); // Slider
}