Using Processing to Send Values using the Serial Port to Arduino

LEDs

In this write-up, I’ll show how to create a value in Processing and then send this value over the serial port to the Arduino. In the example I’m setting values of LEDs making them brighter or dimmed but this example can be extended to control other items – which I plan to do later!

Basically I’m going to set a value between 0 and 255 and then send this value to Arduino which will then use the analogWrite() function to alter the brightness of the LED using PWM (Pulse Width Modulation). I’ve already done a bit of work with LEDs and PWM.

For the communication between Processing and Arduino I’ll be using the serial port – in other work previously I’ve sent information from Arduino to Processing so this is how to do it the other way around. There are a couple of things to note though. Firstly when using Arduino to read a string from the serial port we have to look at it at a byte level, in my example it’s just easier to ignore using strings and send 1 character at a time and then store it in an array. Secondly when debugging your code you can’t read the serial values in Arduinos serial monitor as you’ll already be using the port in Processing so sometimes this can be trial and error although you can at least preview the values your sending in Processing.

Of course you can also extend this code to write values from Arduino back to Processing. There are already plenty of examples online of how to do serial port communication between Arduino and Processing and vice versa and setting an LED to on or off but I’ve done a few extra things to show some basic work with interaction and user interfaces to set the LEDs.

We’re going to set 3 LED’s – Red, Green and Blue and rather than just on or off we’ll be setting the PWM/ levels of brightness. Also the sketches deal with setting an RGB LED (RGBL) with the combined values.

I’ve written 2 visualisations to achive the above.

The first is a set of sliders like a mixing desk – when sliding a slider it will set the value of the LED it’s assigned to and the combined value will set the RGB LED. The second is a triangle shape that you can move around to create the colours, so where ever you drag each point of the triangle it will set the brightness of the LED accordingly.

The Arduino circuit and sketch is very simple and remains the same no matter which visualisation is used. So starting with the circuit…

Arduino Serial Parts

Arduino Deumilanova w/ ATMEGA328
Breadboard/ Prototyping board
Jumper/ Connector wires
3x LED (Red, Green, Blue)
1x RGB LED
6x 270 Ohm resistors

Arduino Serial Circuit

Very simple: 3 LEDs each with a common ground back to the Arduino board, the positive pins (the longer pin) has a 270 Ohm resistor between it and a connection to a digital pin. The RGB LED has 4 pins – 1 is for the power supply – some RGB LEDs instead may connect to GND so check before doing so. The other 3 pins each connect to a digital pin on the Arduino board.

LEDs

Arduino Serial Code – Receiving Values from Processing

The Arduino code is very simple as well – we set the the digital pins all as outputs, we setup the serial port we wish to use and then we read the values from the serial port and store them in an array, each item in the array corresponds to a value for an LED. There is a small catch however – it seems my RGB LED sees the value 255 as off and 0 as on so I have had to write some code to take this into account.

/* Sets LED values based on values sent on the serial port from Processing application.
   luckylarry.co.uk

*/

// create an array of LED pins - need to be the PWM digital pins
int ledPin[] = {9,10,11};
// an array to store the pins for the RGB LED
int RGBLpins[] = {3,5,6};
// array to store the 3 values from the serial port
int incomingByte[3]; 

void setup() {
  // initialize serial communication - make sure its the same as expected in the processing code
  Serial.begin(9600);
  // loop through and set the pins as outputs
  for (int i=0; i<3; i++) {
    pinMode(ledPin[i], OUTPUT);
    pinMode(RGBLpins[i], OUTPUT);
  }
}

/*  3 pins are stored in an array, 3 values from the serial buffer
are stored in an array, by looping through both we can light up the LEDs
using the values sent from the Processing sketch. NOTE: the values sent over
the serial port didn't seem to be in order, rather than RGB I got GBR so it
looks like it misses the first byte - so its just trial and error matching
the correct pin to the correct value.
*/

void loop() {
  // check to make sure there's 3 bytes of data waiting
  if (Serial.available() >= 3) {
    // read the oldest byte in the serial buffer:
    for (int i=0; i<3; i++) {
      // read each byte
      incomingByte[i] = Serial.read();
      // pass the value to each pin
      // analogWrite is used to write a value between 0 and 255 to the PWM pin.
      // lightup the separate LED's
      analogWrite(ledPin[i], incomingByte[i]);
      // seems that my RGB LED sees the values differently - it sees 255 as nothing and 0 as full colour!
      int val = 255 - int(incomingByte[i]);
      analogWrite(RGBLpins[i], val);
    }
  }

}

[ad#Google Ad in content]

Processing Sketch to Send Values via Serial Port to Arduino

Whilst both sketches visually look different they use pretty much the same methods. The main thing is that for each point, shape or item we wish to click and drag we rely on detecting where the mouse is, if its been clicked and if we're dragging the mouse. We can use Processings inbuilt functions mousePressed() and mouseDragged() but we still need to write conditional statements depending on where the mouse is.

To do this we can get the X and Y co-ordinates of the mouse using mouseX and mouseY and to compare these values we need to store the X and Y co-ordinates of any shape as variables - the easiest way is to use the PVector variable type which in its simplest use is an array that stores an X and Y value. Now we can mathematically compare the values and limit the movement of our shapes only moving when the mouse is in the correct area.

In the second sketch, the RGB triangle, I also wanted to test to make sure that the triangles points/vertices we're dragging remain inside a triangular area, to do this there is no Processing code as such its much easier to extend a class and use Javas polygon class (java.awt.Polygon) which will do all the work for us. In order to set the values we have to work out the distance we are from the original points, for which we can use the dist() method which allows us to draw a radius from a point and check to see how far our second point is from the original - we can also use this to create a circular detection area.

When getting the X, Y values from the mouse position we need to make sure these are converted to integers, for which we first use the round() method to convert our float to 1 decimal place and then use the int() method to cast the value as an integer. We also need integer values as it makes it much easier to send ints over the serial port as the libraries allow for these values.

The rest of the processing code is fairly straight forward we use text(), rect(), ellipse(), line(), fill() and stroke() functions to create our visualisation.

The only other thing to note is that in draw() method we always write the values to the serial port.

Visualisation One: RGB Sliders/ Mixing Desk
We have 3 sliders which each can set a value between 0 and 255, the Processing sketch writes each value separately to the serial port and displays the current mixed colour along with each slider value. You can download the sketch You can download the sketch here and try out the application below here and try out the application below. If you download the code please quickly do a find and replace to change //myPort to myPort - it's done just so you can see the app running in this webpage.

/*
    Code by Lucky Larry: www.luckylarry.co.uk

    RGB visualisation to control LED's by dragging sliders to define colour
    Copyright (C) 2009 Pete Dainty aka 'Lucky Larry'

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see .

    Also makes use of gradient drawing code found at: http://processing.org/learning/basics/lineargradient.html

*/

// import the serial library to allow us to send data via the serial ports (USB in this case)
import processing.serial.*;
// create a new instance of the serial classes and assign it to 'myPort'
Serial myPort;
// create set of variables to store vector infomation (X nd Y co-oordinates)
PVector redSlider,greenSlider,blueSlider,whichSlider,lockSliders;
// create an arry to store the vectors of each slider
PVector sliders[];
// boolean value (true or false) to store if lock sliders button has been clicked
boolean locked;
// values needed for gradient code
int Y_AXIS = 1;
int X_AXIS = 2;
// setup our font
PFont myFont;

void setup() {
  // screen size
  size(300,315);
  // setup my font type and size
  myFont = createFont("verdana", 10);
  textFont(myFont);
  // specifiy the co-ordinates for each slider, the lock sliders button
  redSlider = new PVector(50,150);
  greenSlider = new PVector(110,150);
  blueSlider = new PVector(170,150);
  lockSliders = new PVector(12,27);
  // setup an array to store the values of each slider
  sliders = new PVector[] {redSlider,greenSlider,blueSlider};
  // smooth shapes
  smooth();
    /* define which port to use mine is COM10 and is 2nd in the array list.
       you can print out to the screen which ports are accessible by using this code line below
       set the baud rate to the same as in your Arduino code so mine is 9600
    */
    // println(Serial.list());
    myPort = new Serial(this, Serial.list()[1], 9600);
} // end setup

void draw() {
  // set background colour to grey in case the setGradient code fails
  background(50);
  // set outlines of shapes to be black
  stroke(0);
  /* creates a rectangle shape based up on X and Y co-ords,
     width and height, 2 RGB values to the colours to mix and which
     axis to apply the gradient.
  */
  color b1 = color(130, 130, 130);
  color b2 = color(70, 70, 70);
  setGradient(0, 0, width, height, b1, b2, Y_AXIS);
  // set the backgrounds of our slider columns
  color sliderGrad1 = color(120, 120, 120);
  color sliderGrad2 = color(50, 50, 50);
  setGradient(25, 20, 50, 275, sliderGrad1, sliderGrad2, Y_AXIS);
  setGradient(85, 20, 50, 275, sliderGrad1, sliderGrad2, Y_AXIS);
  setGradient(145, 20, 50, 275, sliderGrad1, sliderGrad2, Y_AXIS);
  noFill();
  rectMode(CENTER);
  // draw the outlines of each column and a guide line in the center
  rect(50,160,50,275);
  rect(110,160,50,275);
  rect(170,160,50,275);
  line(50,30,50,285);
  line(110,30,110,285);
  line(170,30,170,285);
  // loop through 25 times to produce 25 measurement lines and measurements
  for (int i=0; i<=25; i++) {
    stroke(30);
    // first column
    line(46,30+(i*10),54,30+(i*10));
    // second column
    line(106,30+(i*10),114,30+(i*10));
    // third column
    line(166,30+(i*10),174,30+(i*10));
    // right hand gauge and measurement numbers
    fill(40);
    stroke(40);
    line(196,30+(i*10),201,30+(i*10));
    text(Integer.toString(i*10),216,35+(i*10),25,25);
  }
  // draw the sliders - one for each item in the sliders array
  for (int i=0; i< mouseX &&
            sliders[i].x+20 > mouseX &&
            sliders[i].y-10 < mouseY &&
            sliders[i].y+10 > mouseY) {
              whichSlider = sliders[i];
            }
    }
    // check to see if the mouse is clicked inside the lock sliders button
    if (lockSliders.x-5 < mouseX &&
        lockSliders.x+5 > mouseX &&
        lockSliders.y-5 < mouseY &&
        lockSliders.y+5 > mouseY) {
          // if so then check the current state and set our boolean to the opposite value
          if(locked) {
          locked = false;
          } else {
          locked = true;
          }
       }
}

/* If the mouse is pressed and the value of whichSlider is not null - it will be null if the mouse is outside the slider area.
   Then look to see if the mouseY is in range, so we dont want it to exceed a scale of 255
   Then look to see if the sliders are locked, if they are then set all sliders to the mouse Y
*/
void mouseDragged() {
    if (whichSlider != null)
    {
        if(mouseY > 30 && mouseY < 287 ) {
          // set the Y value of the slider
          if(!locked) {
            whichSlider.y = mouseY;
          } else {
            for(int i=0; i<3; i++) {
              sliders[i].y = mouseY;
            }
          }
        }
    }
}

/* following gradient code taken from:
   http://processing.org/learning/basics/lineargradient.html
*/

void setGradient(int x, int y, float w, float h, color c1, color c2, int axis ){
  // calculate differences between color components
  float deltaR = red(c2)-red(c1);
  float deltaG = green(c2)-green(c1);
  float deltaB = blue(c2)-blue(c1);

  // choose axis
  if(axis == Y_AXIS){
    /*nested for loops set pixels
     in a basic table structure */
    // column
    for (int i=x; i<=(x+w); i++){
      // row
      for (int j = y; j<=(y+h); j++){
        color c = color(
        (red(c1)+(j-y)*(deltaR/h)),
        (green(c1)+(j-y)*(deltaG/h)),
        (blue(c1)+(j-y)*(deltaB/h))
          );
        set(i, j, c);
      }
    }
  }
  else if(axis == X_AXIS){
    // column
    for (int i=y; i<=(y+h); i++){
      // row
      for (int j = x; j<=(x+w); j++){
        color c = color(
        (red(c1)+(j-x)*(deltaR/h)),
        (green(c1)+(j-x)*(deltaG/h)),
        (blue(c1)+(j-x)*(deltaB/h))
          );
        set(j, i, c);
      }
    }
  }
}

[ad#Google Ad in content]

Visualisation Two: RGB Triangle
A bit more complex we have triangle this time to control the mixing of colours/ setting of values - it works the same way pretty much as the first one. The only real difference is how the mouse is detected and movement is limited to a triangle. You can download the sketch here and try out the application below. Like the previous sketch the downloadable version has the serial port code commented out so it will work in this webpage. Do a find and replace to change //myPort to myPort and that should sort it out.

/*
    Code by Lucky Larry: www.luckylarry.co.uk

    RGB visualisation to control LED's by dragging shapes to define colour
    Copyright (C) 2009 Pete Dainty aka 'Lucky Larry'

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see .
*/

// import the serial library to allow us to send data via the serial ports (USB in this case)
import processing.serial.*;
// create a new instance of the serial classes and assign it to 'myPort'
Serial myPort;
// create set of variables to store vector infomation (X nd Y co-oordinates)
PVector areaPointA,areaPointB,areaPointC,pointA,pointB,pointC,pointDrag;
// create an arry to store the vectors of each point of our shape in this case a triangle
PVector[] rgbTriangle;
/* the next 3 lines uses a custom class at the bottom of this code.
   the class extends java.awt.polygon which means I can use this to create a triangle to test if the
   mouse is in side the shape. */
// new instance of our class
DragArea area;
// these lines specify the X value and Y value for each point of our triangle {xpoint1, xpoint2, xpoint3} etc..
int[]xpoints={152,23,284};
int[]ypoints={23,248,248};
// set 3 variables to store the colour values.
int R, G, B;
// setup our font
PFont myFont;
/* setup our background and variables */
void setup () {
    // screen size
    size(305,271);
    // setup my font type and size
    myFont = createFont("verdana", 12);
    textFont(myFont);
    // define our new instance of the custom class. (X points, Y points, Number of points in the shape) more info below by the class
    area = new DragArea(xpoints,ypoints,3);
    // define the area vectors - we use these to see how far our point is from its original source, needed to calculate the value between 0 and 255
    areaPointA = new PVector(152,25);
    areaPointB = new PVector(25,246);
    areaPointC = new PVector(280,246);
    // specifiy the starting co-ordinates for the triangle that we can move
    pointA = new PVector(152,40);
    pointB = new PVector(40,230);
    pointC = new PVector(265,230);
    // set the array with the new points.
    rgbTriangle = new PVector[]{pointA,pointB,pointC};
    // center our shapes
    ellipseMode(CENTER);
    rectMode(CENTER);
    // set smoothing for our shapes edges
    smooth();
    /* define which port to use mine is COM10 and is 2nd in the array list.
       you can print out to the screen which ports are accessible by using this code line below
       set the baud rate to the same as in your Arduino code so mine is 9600
    */
    // println(Serial.list());
    myPort = new Serial(this, Serial.list()[1], 9600);
} // end setup

/* begin our animation/ interaction */
void draw () {
    // set background to black
    background(50);
    // set the colours and positions of the large colour circles to indentify where red is 100% etc...
    // fill(R, G, B);
    fill(255,0,0);
    // ellipse(X co-ordinate, Y co-ordinate,width, height)
    ellipse(areaPointA.x, areaPointA.y, 15,15);
    fill(0,255,0);
    ellipse(areaPointB.x, areaPointB.y, 15,15);
    fill(0,0,255);
    ellipse(areaPointC.x, areaPointC.y, 15,15);
    // create our background triangle to show the area in which we can move.
    fill(100);
    beginShape(TRIANGLES);
      vertex(areaPointA.x,areaPointA.y);
      vertex(areaPointB.x,areaPointB.y);
      vertex(areaPointC.x,areaPointC.y);
    endShape();
    /* set the fill of our coloured triangle we work out the values by
       getting the current points co-ordinates and working out the distance
       from the original point. These distances are actually calculated on a
       circular area so it draws an elliptical area from the origin point from
       the 2 adjacent sides of the triangle. First set the values to our variables
       R, G, B and round them so that they'll be integers and parse them using the int() method
    */
    R = int(round(255-dist(areaPointA.x,areaPointA.y,pointA.x,pointA.y)));
    G = int(round(255-dist(areaPointB.x,areaPointB.y,pointB.x,pointB.y)));
    B = int(round(255-dist(areaPointC.x,areaPointC.y,pointC.x,pointC.y)));
    fill(R,G,B);
    /* we need to send this fill value to the Arduino to light up the LED's accordingly
       we do this by writing a value to the serial port.
       You can write values to the serial port using bytes, integers and chars.
       I'm going to send the 3 values separately and store them in an array on the Arduino
    */
    myPort.write(R);
    myPort.write(G);
    myPort.write(B);
    // create our RGB triangle from the draggable points
    beginShape(TRIANGLES);
      vertex(pointA.x,pointA.y);
      vertex(pointB.x,pointB.y);
      vertex(pointC.x,pointC.y);
    endShape();
    // create the drag handles for each point in the draggable shape.
    for (int i=0; i< mouseX &&
            rgbTriangle[i].x+5 > mouseX &&
            rgbTriangle[i].y-5 < mouseY &&
            rgbTriangle[i].y+5 > mouseY) {
              pointDrag = rgbTriangle[i];
            }
    }
} 

/* If the mouse is pressed and the value of pointDrag is not null - it will be null if the mouse is outside the handle area.
   We then do another check to see if our mouse pointer is inside our polygon area. In Processing we can use the .contains() method
   that we get from the custom class at the bottom to check if an XY value is inside the polygons area.
*/
void mouseDragged() {
    if ( pointDrag != null )
    {
      if(area.contains(mouseX,mouseY) ) {
        // set the XY values of the point we're dragging to the values of the mouse
        pointDrag.x = mouseX;
        pointDrag.y = mouseY;
      }
    }
} 

/* This doesnt look like much code but what we're doing is extending a class with another class.
   By extending our class with java.awt.Polygon we then inherit that classes methods to use as our own.
   Since Processing is based upon Java there are many classes that we can import to extend Processing.
   The functions of java.awt.Polygon can be found here: http://java.sun.com/j2se/1.4.2/docs/api/java/awt/Polygon.html
   This makes it much easier to do collision detection with shapes - Processing can handle rectangles and circles fine
   but for triangles this saves alot of effort.
*/
class DragArea extends java.awt.Polygon {
  /* our DragArea class is basically an instance of java.awt.Polygons and this class expects and array of X points, Y points and the number of
     points in our shape. The variable names also have to be direct references to what this class expects, so xpoints, ypoints and npoints are all
     set/defined in the java class.
  */
  public DragArea(int[] xpoints,int[] ypoints, int npoints) {
    // super invokes the java.awt.Polygon class
    super(xpoints,ypoints,npoints);
  }
}

[ad#Google Ad in content]

8 Comments

  • You’re doing a great job! I really enjoyed the radar, and now the programs that is in processing are great! Congratulations

    • Cheers Bruno – The LED applications are just a warmup to doing some other stuff – I got a robotic arm that i’m going to wire in 🙂

  • The files you offer to download do not work, but the code you have to copy paste does. I’m pretty sure you //commented the serial port setting and the actual output lines of code.

    • Do’h! I’ll have a look at that – cheers for letting me know though.

    • Ah I know why… its so the apps run in the page so the serial port code is turned off. So anything with a reference to myPort will be commented out.

  • Larry
    Have got slider sketch working but cannot compile sketch for arduino, “lt” not declared, “gt” not declared etc. Looks so good I have to get it working, please help.
    Pete

    • Arse! that would be my blog replacing ‘< ' '>‘ with ‘& lt;’ and ‘& gt;’ I’ll fix that now

  • Hey Larry, thank you for your great post and explanation. I managed to do some small changes, reverse the sliders (so UP is 255, and DOWN is 0), and added matching color gradients to the slider background itself. However, I’m stuck on figuring out what I’d like to do next and wondered if you have any pointers.

    Right now, the sliders lock will lock all the sliders to MouseY. However, I’d like to lock them in place as they relate to each other. So for example, if I set the sliders to a specific color, I’d like to lock that and then slide all of them up and down based on that, as opposed to resetting them to MouseY.

    I realize when any of the sliders hit the minimum or maximum threshold, something needs to be done and I think what I’d like to do is keep whichever slider his the threshold at that location till the other sliders move back out of it. For example, let’s say I have the sliders set at 200, 150, 100. So the difference between red and green is 50 points, and the same between green and blue. I’d like to lock them at that setting, then slide everything up and down. When the red slider hits 255, it quits moving, but allowing the other two to continue to move up. When I start moving down again, keep the red at 255 until it’s relation with the green reaches the 50 points difference and then start moving it down with the rest.

    Not sure if that makes any sense to you. Any suggestions you can give?

You must be logged in to post a comment.