Posts Tagged ‘Serial port’

Arduino: Controlling the Robot Arm

arduino processing robot arm pt2

So the arm is wired into Arduino as per the previous post, Arduino: Modifying a Robot Arm and hopefully this has worked. In this next part I alter the Arduino sketch slightly and write the first Processing sketch to test control of the arm – video at the bottom.

To control the robot arm we’ll be sending a byte value over the serial port and then reading that in the Arduino code. Depending upon the value sent different motors will be activated.

For the processing sketch I’ve made a few buttons for each motor and also coded the use of the keyboard for another control method. Using either arbitrarily moves the arms motors.

This sketch is the basis for all the further work as well as testing the arm, from this I will move to inverse kinematics as well as programming repeat actions for the arm to perform. Ultimately leading to the arm responding to sensors and other stimuli – eventually! (I have a lot to write up).

For a basic example of working with controlling Arduino using Processing please read my tutorial “Using Processing to Send Values to Arduino” which explains about sending data over the serial port.

The Arduino Sketch
Nothing much has changed from the sketch in the previous post, the main difference is that now you can see we’re reading values from the serial port and acting accordingly. All the logic happens in the Processing code.

/* controls each motor in an Edge Robotic Arm using data sent from 
    a Processing Sketch
    luckylarry.co.uk
 
*/
// set the output pins
// 14-18 are actually analog pins 0-4
int baseMotorEnablePin = 2;
int baseMotorPin1 = 3;                             
int baseMotorPin2 = 4;                           
int shoulderMotorEnablePin = 14;
int shoulderMotorPin1 = 15;                             
int shoulderMotorPin2 = 16; 
int elbowMotorEnablePin = 8;
int elbowMotorPin1 = 9;                             
int elbowMotorPin2 = 10;                           
int wristMotorEnablePin = 5;
int wristMotorPin1 = 6;                             
int wristMotorPin2 = 7; 
int handMotorEnablePin = 11;
int handMotorPin1 = 17;                             
int handMotorPin2 = 18; 
// set a variable to store the byte sent from the serial port
int incomingByte;

void setup() {
  // set the SN754410 pins as outputs:
  pinMode(baseMotorPin1, OUTPUT);
  pinMode(baseMotorPin2, OUTPUT);
  pinMode(baseMotorEnablePin, OUTPUT);
  digitalWrite(baseMotorEnablePin, HIGH);
  pinMode(shoulderMotorPin1, OUTPUT);
  pinMode(shoulderMotorPin2, OUTPUT);
  pinMode(shoulderMotorEnablePin, OUTPUT);
  digitalWrite(shoulderMotorEnablePin, HIGH);
  pinMode(elbowMotorPin1, OUTPUT);
  pinMode(elbowMotorPin2, OUTPUT);
  pinMode(elbowMotorEnablePin, OUTPUT);
  digitalWrite(elbowMotorEnablePin, HIGH);
  pinMode(wristMotorPin1, OUTPUT);
  pinMode(wristMotorPin2, OUTPUT);
  pinMode(wristMotorEnablePin, OUTPUT);
  digitalWrite(wristMotorEnablePin, HIGH);
  pinMode(handMotorPin1, OUTPUT);
  pinMode(handMotorPin2, OUTPUT);
  pinMode(handMotorEnablePin, OUTPUT);
  digitalWrite(handMotorEnablePin, HIGH);
  // start sending data at 9600 baud rate
  Serial.begin(9600);
}

void loop() {
  // check that there's something in the serial buffer
  if (Serial.available() > 0) {
    // read the byte and store it in our variable 
    // the byte sent is actually an ascii value
    incomingByte = Serial.read();
    // note the upper casing of each letter!
    // each letter turns a motor different way.
    if (incomingByte == 'Q') {
    digitalWrite(baseMotorPin1, LOW);   
    digitalWrite(baseMotorPin2, HIGH);  
    } 
    if (incomingByte == 'W') {
    digitalWrite(baseMotorPin1, HIGH);   
    digitalWrite(baseMotorPin2, LOW);  
    }
    if (incomingByte == 'E') {
    digitalWrite(shoulderMotorPin1, LOW);   
    digitalWrite(shoulderMotorPin2, HIGH);  
    } 
    if (incomingByte == 'R') {
    digitalWrite(shoulderMotorPin1, HIGH);   
    digitalWrite(shoulderMotorPin2, LOW);  
    }
    if (incomingByte == 'A') {
    digitalWrite(elbowMotorPin1, LOW);   
    digitalWrite(elbowMotorPin2, HIGH);  
    } 
    if (incomingByte == 'S') {
    digitalWrite(elbowMotorPin1, HIGH);   
    digitalWrite(elbowMotorPin2, LOW);  
    }
    if (incomingByte == 'D') {
    digitalWrite(wristMotorPin1, LOW);   
    digitalWrite(wristMotorPin2, HIGH);  
    } 
    if (incomingByte == 'F') {
    digitalWrite(wristMotorPin1, HIGH);   
    digitalWrite(wristMotorPin2, LOW);  
    }
    if (incomingByte == 'Z') {
    digitalWrite(handMotorPin1, LOW);   
    digitalWrite(handMotorPin2, HIGH);  
    } 
    if (incomingByte == 'X') {
    digitalWrite(handMotorPin1, HIGH);   
    digitalWrite(handMotorPin2, LOW);  
    }
    // if a O is sent make sure the motors are turned off
    if (incomingByte == 'O') {
    digitalWrite(baseMotorPin1, LOW);   
    digitalWrite(baseMotorPin2, LOW);  
    digitalWrite(shoulderMotorPin1, LOW);   
    digitalWrite(shoulderMotorPin2, LOW); 
    digitalWrite(elbowMotorPin1, LOW);   
    digitalWrite(elbowMotorPin2, LOW);  
    digitalWrite(wristMotorPin1, LOW);   
    digitalWrite(wristMotorPin2, LOW); 
    digitalWrite(handMotorPin1, LOW);   
    digitalWrite(handMotorPin2, LOW); 
    }
  }
}

[ad#Google Ad in content]

The Processing Sketch
I’ve drawn some fancy arrows for my buttons in this sketch but otherwise the code is pretty simple – if I press Q or q on the keyboard or if I press an arrow button then send the ascii value of Q (note the uppercase) over the serial port for the Arduino to pick up and turn the motor on. There is nothing here really complicated just a fair few lines of code for the user interface.

/* 
   Processing sketch that send a ascii byte character to Arduino which
   then subsquentally controls a motor
   luckylarry.co.uk
 
*/

// load the serial library for Processing
import processing.serial.*; 
// instance of the serial class
Serial port;
// values to store X, Y for each button
int M1LX, M1RX, M2LX, M2RX, M3LX, M3RX, M4LX, M4RX, M5LX, M5RX;
int M1LY, M1RY, M2LY, M2RY, M3LY, M3RY, M4LY, M4RY, M5LY, M5RY;
// stores the width/height of the box
int boxSize = 64;
// 2 new instances of my arrow class
// also set an array of coordinates for each arrow
arrow myRightArrow;
int[]rightArrowxpoints={30,54,30,30,0,0,30}; 
int[]rightArrowypoints={0,27,54,40,40,15,15};
arrow myLeftArrow;
int[]leftArrowxpoints={0,24,24,54,54,24,24}; 
int[]leftArrowypoints={27,0,15,15,40,40,54};
// set the font
PFont myFont;

void setup()  {
  // screen size of the program
  size(145, 455);
  // set the coordinates of each button box
  // base motor M1LX = Motor 1 Left X  etc..
  M1LX = 5;
  M1LY = 25;
  M1RX = 75;
  M1RY = 25;  
  // shoulder motor
  M2LX = 5;
  M2LY = 115;
  M2RX = 75;
  M2RY = 115;
  // elbow motor
  M3LX = 5;
  M3LY = 205;
  M3RX = 75;
  M3RY = 205;
  // wrist motor
  M4LX = 5;
  M4LY = 295;
  M4RX = 75;
  M4RY = 295;
  // hand motor
  M5LX = 5;
  M5LY = 385;
  M5RX = 75;
  M5RY = 385;
  
  // List all the available serial ports in the output pane. 
  // You will need to choose the port that the Arduino board is 
  // connected to from this list. The first port in the list is 
  // port #0 and the third port in the list is port #2. 
  println(Serial.list()); 
  // set the font to use
  myFont = createFont("verdana", 12);
  textFont(myFont);
  // Open the port that the Arduino board is connected to (in this case #0) 
  // Make sure to open the port at the same speed Arduino is using (9600bps)
  port = new Serial(this, Serial.list()[1], 9600); 
  // create the base arrow
  myRightArrow = new arrow(rightArrowxpoints,rightArrowypoints,7);
  myLeftArrow = new arrow(leftArrowxpoints,leftArrowypoints,7);
}

void draw() 
{ 
  background(0);
  noStroke();
  fill(150);
  // draw each box/ button with a label above each    
  text("Base Motor (Q/W)", 5, 5, 200, 75); 
  text("Shoulder Motor (E/R)", 5, 95, 200, 75);
  text("Elbow Motor (A/S)", 5, 185, 200, 75);
  text("Wrist Motor (D/F)", 5, 275, 200, 75);     
  text("Hand Motor (Z/X)", 5, 365, 200, 75);

  // start looking to see whats pressed and send a value
  // over the serial port
  if(keyPressed) {
    if (key == 'q' || key == 'Q') {
      port.write('Q');
    }
    if (key == 'w' || key == 'W') {
      port.write('W');
    }
    if (key == 'e' || key == 'E') {
      port.write('E');
    }
    if (key == 'r' || key == 'R') {
      port.write('R');
    }
    if (key == 'a' || key == 'A') {
      port.write('A');
    }
    if (key == 's' || key == 'S') {
      port.write('S');
    }
    if (key == 'd' || key == 'D') {
      port.write('D');
    }
    if (key == 'f' || key == 'F') {
      port.write('F');
    }
    if (key == 'z' || key == 'Z') {
      port.write('Z');
    }
    if (key == 'x' || key == 'X') {
      port.write('X');
    }
  } 
  // if no key is pressed check to see if the mouse button is pressed
  else if (mousePressed == true) {
    // check to see if the mouse is inside each box/ button if so send the value
    if (mouseX > M1LX-boxSize && mouseX < M1LX+boxSize && 
      mouseY > M1LY-boxSize && mouseY < M1LY+boxSize) {
        port.write('Q'); 
    } 
    else if(mouseX > M1RX-boxSize && mouseX < M1RX+boxSize && 
      mouseY > M1RY-boxSize && mouseY < M1RY+boxSize) {
        port.write('W'); 
    } 
    else if(mouseX > M2LX-boxSize && mouseX < M2LX+boxSize && 
      mouseY > M2LY-boxSize && mouseY < M2LY+boxSize) {
        port.write('E'); 
    } 
    else if(mouseX > M2RX-boxSize && mouseX < M2RX+boxSize && 
      mouseY > M2RY-boxSize && mouseY < M2RY+boxSize) {
        port.write('R'); 
    } 
    else if(mouseX > M3LX-boxSize && mouseX < M3LX+boxSize && 
      mouseY > M3LY-boxSize && mouseY < M3LY+boxSize) {
        port.write('A');   
    } 
    else if(mouseX > M3RX-boxSize && mouseX < M3RX+boxSize && 
      mouseY > M3RY-boxSize && mouseY < M3RY+boxSize) {
        fill(200);
        port.write('S');     
    }
    else if (mouseX > M4LX-boxSize && mouseX < M4LX+boxSize && 
      mouseY > M4LY-boxSize && mouseY < M4LY+boxSize) {
        port.write('D');     
    } 
    else if(mouseX > M4RX-boxSize && mouseX < M4RX+boxSize && 
      mouseY > M4RY-boxSize && mouseY < M4RY+boxSize) {
        port.write('F');  
    } 
    else if (mouseX > M5LX-boxSize && mouseX < M5LX+boxSize && 
      mouseY > M5LY-boxSize && mouseY < M5LY+boxSize) {
        port.write('Z'); 
    }
    else if(mouseX > M5RX-boxSize && mouseX < M5RX+boxSize && 
      mouseY > M5RY-boxSize && mouseY < M5RY+boxSize) {
        port.write('X');    
    }
    else {
      // if the mouse is pressed but not with in a box make sure nothings moving
      port.write('O');   
    } 
  } else {
    // no key or mouse press then make sure nothings moving.
    port.write('O');   
  } 
  
  // draw the buttons
  myRightArrow.drawArrow(80,30);
  myRightArrow.drawArrow(80,120);
  myRightArrow.drawArrow(80,210);
  myRightArrow.drawArrow(80,300);
  myRightArrow.drawArrow(80,390);
  myLeftArrow.drawArrow(10,30);
  myLeftArrow.drawArrow(10,120);
  myLeftArrow.drawArrow(10,210);
  myLeftArrow.drawArrow(10,300);
  myLeftArrow.drawArrow(10,390);
}

class arrow extends java.awt.Polygon { 
  /* our 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 arrow(int[] xpoints,int[] ypoints, int npoints) {
    // super invokes the java.awt.Polygon class
    super(xpoints,ypoints,npoints);
    
  } 
    // supply offsets to draw the arrow, means I don't need to set points for each one
    void drawArrow(int xOffset, int yOffset){
    fill(150);
    rect(xOffset-5, yOffset-5, boxSize, boxSize);
    fill(255);
    beginShape();
    for(int i=0;i

[ad#Google Ad in content]

Does it work?
Hopefully the sketch is working and you can control the arm via your computer. If not then first check that all motors are wired in properly and your batteries are not flat. If you arrow moves the arm the wrong way then you can either switch the motor pins on the circuit or change the Arduino sketch to alter the motors direction.

Calibrating the arm
We need to set start positions for the arm and note the positions and counts in order to later calculate the positions for the next parts of this work. This is where we'll look to more benefits of Arduino and possibly PID (Proportional, Integral, Derivative) control, PWM or someother way to get accurate positions for the motor. The only catch is each motor is in a gearbox so using an encoder or other device to measure motor rotations is not an option. But for now we can control our arm from the computer at least - check out the video below.


Arduino: Modifying a Robot Arm: How to wire up the robot arm to Arduino.

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]

Arduino & Processing – Getting values from SRF05 ultrasound sensor & serial port

arduino processing

I’ve started to delve into Processing and passing values between Processing and Arduino. If you’re wondering what Processing is, basically its an open source programming language for vizualising data that can interface with Arduino either by reading values/ pins or by setting them. Just remember that they are 2 very different things and require 2 different sketches!

This is very cool if you want to display information from Arduino in a graphical way, or if you want to have a physical input device for your computer, for instance a Flash application that takes inputs from switches and potentiometers.

So anyway, it’s really very easy to get this installed and working, just do the following steps here: http://www.arduino.cc/playground/Interfacing/Processing

Now, I’ve had a bit of an issue getting values from my SRF05 from Arduino to Processing. In Arduino it works fine and the serial port shows the values correctly but in Processing I couldn’t get the values. Some people suggest using Firmata but the trouble with this is that it has very few of the functions that I need for example delayMicroseconds() is not available when using Firmata.

Also I saw alot of people trying to get this working using different mode settings for the SRF05 but to be honest I like my code so I want to use that – I use separate echo and trigger pins rather than a singular pin. I reckon this may also help you out should you be having problems getting other values.

Another issue I ran across was converting serial port output to an integer, it just didn’t like this at all so I found a quick solution into fixing this. Although this introduces another error which we have to catch but now I think I have a set of code that works pretty well for what I need.

So first of all take a look at my Arduino SRF05 tutorial.

Arduino SRF05 Sketch

Now you’ve got the circuit and parts use the following sketch on the Arduino board:

const int numReadings = 10;
int readings[numReadings];      // the readings from the analog input
int index = 0;                  // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average
int echoPin = 2;             // the SRF05's echo pin
int initPin = 3;             // the SRF05's init pin
unsigned long pulseTime = 0;  // variable for reading the pulse
unsigned long distance = 0;  // variable for storing the distance

void setup() {

  // make the init pin an output:
  pinMode(initPin, OUTPUT);
  // make the echo pin an input:
  pinMode(echoPin, INPUT);
  // initialize the serial port:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
     readings[thisReading] = 0;
  }
  // set the serial port to begin logging values which Processing will later read.
  Serial.begin(9600);
}

void loop() {
  // send the sensor a 10microsecond pulse:
  digitalWrite(initPin, HIGH);
  delayMicroseconds(50);
  digitalWrite(initPin, LOW);

  // wait for the pulse to return. The pulse
  // goes from low to HIGH to low, so we specify
  // that we want a HIGH-going pulse below:

  // converts the microsecond time to distance in CM
  pulseTime = pulseIn(echoPin, HIGH);
  distance = pulseTime/58;

  // subtract the last reading:
  total= total - readings[index];
  // read from the sensor:
  readings[index] = distance;
  // add the reading to the total:
  total= total + readings[index];
  // advance to the next position in the array:
  index = index + 1;                    

  // if we're at the end of the array...
  if (index >= numReadings)  {
    // ...wrap around to the beginning:
    index = 0;
  }
  // calculate the average:
  average = total / numReadings;  

  // print out an A character to set the start of the value and help us
  // cast this value to a string and integer later on in Processing.
  Serial.print('A');

  // now write out our value from the sensor.
  Serial.print(average);
  // delay must be the same as the delay in the processing code
  delay(100);
}

[ad#Google Ad in content]

It’s not too different from the previous tutorial, just gets rid of the LED and the main thing to note is the serial port output at the bottom. We add an A to mark the beginning of the value in the serial output and we use this later on to help cast ou value as a string and then integer, for some reason trying to pass the serial value as an integer or trying to parse it as such fails.

SRF05 Processing Sketch

Now for the Processing code we just need this bit and that’s it – we’re just looking in the log file here to see the values being read correctly. Basically we do a few checks to make sure we have no null values, that the output we’re reading is of expected length and has the correct identifying symbol at the front, you don’t have to use ‘A’, this can actually be anything you want.

// import the serial libary for Processing
import processing.serial.*; 

// define a new port object
Serial port;

// setup the port, this referes to the port object above
// COM8 is my USB port that I use, your's maybe anythign like COM1, etc..
// 9600 is the baud rating (how much data is transferred over a set time)
// it is important to make sure your Arduino is outputting to the same baud rating!!

void setup(){
     port = new Serial(this, "COM8", 9600);
}

// begin our output for Processing
void draw(){

  // delay 100 milliseconds - this must be the same delay used in the Arduino sketch.
  delay(100);

  // create a string to store the value from reading the serial port
  String serialBuffer = port.readString();

  // check if the value is not null, that the value is greater that 2 and no more than 4 characters
  if (serialBuffer != null && serialBuffer.length() >= 2 && serialBuffer.length() <= 4) {

    // check that the first character in the string is A
    // we add A to our output to cast the serial value to a string type.
    // Its also handy as the A is doubled up as a marker for a new value in the serial log
    if (serialBuffer.indexOf("A") == 0) {
      // if this is true then remove A
      serialBuffer =  serialBuffer.substring(1,serialBuffer.length());
    }
    // double check to make sure there are no more A's in our string - otherwise we can't convert to a number
    if (serialBuffer.indexOf("A") == -1) {
      // convert the string to an integer
      int i = Integer.parseInt(serialBuffer);
      // print our integer
      println(i);
    }
  }

}

[ad#Google Ad in content]

Make sure...

Make sure that your serial port is set to the same baud rating in both the Arduino and Processing sketch.

Make sure that the delay used in both executable methods matches.

Make sure that the correct port is being read.