processing+arduino+servo without firmata

Hi everybody

I have bought an dagu rover 5 and some micro servo's, and have been playing around with them since.
i can now control the motors from my iphone, and the servo's from my iphone, but only separated (so only the motors or only a servo).
I already tried a lot myself but could not find anything to make it work.

if somebody could help me out i would be very happy.

i used these codes for that.

this one is from projectallusion.com
the arduino code (this controls the motors)

//-----------Start Arduino code ---------------

// Test program for SparkFun Ardumoto board
// Copyright (c) 2009 mechomaniac.com
 
// To use, connect the Arduino to a computer and send commands using a serial terminal.
// eg AR40#   motor A forwards with a speed of 40
 
#define PwmPinMotorA 10
#define PwmPinMotorB 11
#define DirectionPinMotorA 12
#define DirectionPinMotorB 13
#define SerialSpeed 9600
#define BufferLength 16
#define LineEnd '#'
 
char inputBuffer[BufferLength];
 
void setup()
{
  // motor pins must be outputs
  pinMode(PwmPinMotorA, OUTPUT);
  pinMode(PwmPinMotorB, OUTPUT);
  pinMode(DirectionPinMotorA, OUTPUT);
  pinMode(DirectionPinMotorB, OUTPUT);
 
  Serial.begin(SerialSpeed); 
}
 
// process a command string
void HandleCommand(char* input, int length)
{
  Serial.println(input);
  if (length < 2) { // not a valid command
    return;
  }
  int value = 0;
  // calculate number following command
  if (length > 2) {
    value = atoi(&input[2]);
  }
  int* command = (int*)input;
  // check commands
  // note that the two bytes are swapped, ie 'RA' means command AR
  switch(*command) {
    case 'FA':
      // motor A forwards
      analogWrite(PwmPinMotorA, value);
      digitalWrite(DirectionPinMotorA, HIGH);
      break;
    case 'RA':
      // motor A reverse
      analogWrite(PwmPinMotorA, value);
      digitalWrite(DirectionPinMotorA, LOW);
      break;
    case 'FB':
      // motor B forwards
      analogWrite(PwmPinMotorB, value);
      digitalWrite(DirectionPinMotorB, LOW);
      break;
    case 'RB':
      // motor B reverse
      analogWrite(PwmPinMotorB, value);
      digitalWrite(DirectionPinMotorB, HIGH);
      break;
    default:
      break;
  }  
} 
 
void loop()
{ 
  // get a command string form the serial port
  int inputLength = 0;
  do {
    while (!Serial.available()); // wait for input
    inputBuffer[inputLength] = Serial.read(); // read it in
  } while (inputBuffer[inputLength] != LineEnd && ++inputLength < BufferLength);
  inputBuffer[inputLength] = 0; //  add null terminator
  HandleCommand(inputBuffer, inputLength);
}

//----------- End Arduino code ---------------

the processing code

//----------- Start Processing code ----------------

import oscP5.*;
import netP5.*;
import processing.serial.*;
Serial arduinoPort;
OscP5 oscP5;

float [] fader = new float [3];

void setup() {
  oscP5 = new OscP5(this,8000);
  arduinoPort = new Serial(this, Serial.list()[0], 9600);
}

void oscEvent(OscMessage theOscMessage) {

    String addr = theOscMessage.addrPattern();
    
       if(addr.indexOf("/1/fader") !=-1){ 
       String list[] = split(addr,'/');
     int  xfader = int(list[2].charAt(5) - 0x30);
     if(theOscMessage.get(0).floatValue() !=0){
     fader[xfader]  = theOscMessage.get(0).floatValue();
     }   
    }
}

void draw() {
//---------------------------------Motor A
 if(fader[1] > 0.65){
    arduinoPort.write("AF100#");
  }
   if(fader[1] < 0.35){
    arduinoPort.write("AR100#");
  }
  //--------------------------------Motor B
   if(fader[2] > 0.65){
    arduinoPort.write("BF100#");
  }
   if(fader[2] < 0.35){
    arduinoPort.write("BR100#");
  }
  //----------------------------stop commands
     if(fader[1] < 0.65 && fader[1] > 0.35 ){
    arduinoPort.write("AF0#");
  }
       if(fader[2] < 0.65 && fader[2] > 0.35 ){
    arduinoPort.write("BF0#");
  }
  
}

//---------------------- End Processing Code ------------------

and I used these for the servo (i want to be able to control more then one later on)

from: GitHub - jaxzin/arduino_touchosc_servo_controller: Control a servo from an on-screen iOS dial

arduino code:

// Sweep
// by BARRAGAN <http://barraganstudio.com> 
// This example code is in the public domain.

// Range appears to be 0-171, and 600-2300 micros, 1350 midpoint


#include <Servo.h> 
 
#define LED_PIN 13
 
Servo myservo;  // create servo object to control a servo 
                // a maximum of eight servo objects can be created 
 
int pos = 0;    // variable to store the servo position 
 
void setup() 
{ 
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object 
  Serial.begin(9600);
  digitalWrite(LED_PIN, LOW);
  //Serial.println("Enter the servo position in degrees (0 - 180), followed by a period.");
} 
 
 
void loop() 
{ 
  boolean update = false;
  while(Serial.available() > 0) {
    byte temp = Serial.read();
    if(temp == '.') {
      update = true;
      break;
    } else {
      pos *= 10; // shift the currently stored position
      pos += (temp - '0'); // Add the new digit;
    }
  }

  if(update && pos >= 0 && pos <= 180) {
    int temp = map(pos, 0, 180, 550, 2300); // Map degrees (0-180) to Futaba servo microseconds...
    myservo.writeMicroseconds(temp);
    //Serial.print("Moving to position ");
    //Serial.println(pos, DEC);
    pos = 0;
    
    // Blink LED as a sign of movement, twice over a quarter-second
    //blinkLed(LED_PIN, 2, 250);
  }
  // Warn on invalid data
  else if(update) {
    //Serial.print("Invalid position [");
    //Serial.print(pos, DEC);
    //Serial.println("]. Please enter a position between 0 and 180 degrees");
    pos = 0;
  }
}

void blinkLed(int pin, int times, int duration) {
  // The length of being on or off (total duration devided by the number of blinks + spaces in between)
  int pulseDuration = duration / ((times * 2) - 1);
  
  for(int i = 0; i < times; i++) {
    digitalWrite(pin, HIGH);
    delay(pulseDuration);
    digitalWrite(pin, LOW);
    // if its not the last blink...
    if(i != times - 1) {
      delay(pulseDuration);
    }
  }
  
}

processing code:

import oscP5.*;        //  Load OSC P5 library
import netP5.*;        //  Load net P5 library
import processing.serial.*;    //  Load serial library

Serial arduinoPort;        //  Set arduinoPort as serial connection
OscP5 oscP5;            //  Set oscP5 as OSC connection

int redLED = 0;        //  redLED lets us know if the LED is on or off
int [] led = new int [2];    //  Array allows us to add more toggle buttons in TouchOSC
int currentPos = 0;
int desiredPos = 0;

void setup() {
  size(100,100);        // Processing screen size
  noStroke();            //  We don’t want an outline or Stroke on our graphics
    oscP5 = new OscP5(this,8000);  // Start oscP5, listening for incoming messages at port 8000
   arduinoPort = new Serial(this, Serial.list()[0], 9600);    // Set arduino to 9600 baud
}

void oscEvent(OscMessage theOscMessage) {   //  This runs whenever there is a new OSC message

    String addr = theOscMessage.addrPattern();  //  Creates a string out of the OSC message
    if(addr.indexOf("/1/servo") !=-1){   // Filters out any toggle buttons
      //int i = int((addr.charAt(9) )) - 0x30;   // returns the ASCII number so convert into a real number by subtracting 0x30
      desiredPos  = int(theOscMessage.get(0).floatValue());     //  Puts button value into led[i]
    // Button values can be read by using led[0], led[1], led[2], etc.
     
    }
}

void draw() {
 background(50);        // Sets the background to a dark grey, can be 0-255

  if(currentPos != desiredPos) {
    String pos = str(desiredPos);
    println("Moving to position " + pos);
    arduinoPort.write(pos);
    arduinoPort.write('.');
    currentPos = desiredPos;
  }

  redLED = int(map(desiredPos, 0, 180, 0, 255));
  fill(redLED,0,0);            // Fill rectangle with redLED amount
  ellipse(50, 50, 50, 50);    // Created an ellipse at 50 pixels from the left...
                // 50 pixels from the top and a width of 50 and height of 50 pixels
}
    case 'FA':

The 'FA' is a multi-byte character constant. There is no way to send a multi-byte character constant via the serial port. So, this case will never be matched. Nor will any of the others.

I already tried a lot myself but could not find anything to make it work.

I'd be happy to help you fix what you wrote. Post the Arduino sketch and the Processing sketch.

I don't have my sketches any more :~
it would have been smart'er to have saved them.

Would using firmata be much easier ? and does it also work if i want to use a bluetooth module.
I also saw your reply on this topic http://arduino.cc/forum/index.php/topic,74653.0.html this seems to work but could it be used with an iphone using touchOSC and two extra motors as in the motor code above?

BTW i am not asking if somebody could write a complete code for me, a some tips or a little guidens would be very help full

so far this is my code for using a servo from my iphone
it uses firmata (maybe it is just easier to use servo firmata)

import oscP5.; // Load OSC P5 library
import netP5.
; // Load net P5 library
import processing.serial.;
import cc.arduino.
;
OscP5 oscP5;
Arduino arduino;
int pos=0; //servo position in degrees (0..180)
int desiredPos = 0;
void setup()
{
size(360, 200);
oscP5 = new OscP5(this,8000);
arduino = new Arduino(this, Arduino.list()[3], 57600); //your offset may vary
arduino.pinMode(9, 5);
}

void oscEvent(OscMessage theOscMessage) { // This runs whenever there is a new OSC message

String addr = theOscMessage.addrPattern(); // Creates a string out of the OSC message
if(addr.indexOf("/1/servo") !=-1){ // Filters out any toggle buttons
//int i = int((addr.charAt(9) )) - 0x30; // returns the ASCII number so convert into a real number by subtracting 0x30
desiredPos = int(theOscMessage.get(0).floatValue()); // Puts button value into led

  • // Button values can be read by using led[0], led[1], led[2], etc.*
  • }}*
    void draw()
    {
    // read mouseX coordinate
  • int newPos = constrain(desiredPos,10,150); // update bg & servo position if mouseX changed*
  • if(newPos != pos)*
  • {*
  • background(newPos);*
  • arduino.analogWrite(9, newPos);*
  • println (" newPos = " + newPos );*
  • pos=newPos; //update servo position storage variable*
  • }*
    *} *

Would using firmata be much easier ?

Find a concrete wall. Stand about 6 inches from the wall. Spend 30 minutes pounding your head against the wall. THAT was easier than using firmata.

hhhmmm i don't think i am going to try that :stuck_out_tongue:

what would you suggest ?

Processing is able to send data to the Arduino. Make it send something like <S1,45> to move servo 1 to position 45. Make the Arduino read the data sent to it, parse the data, and do what it is it's supposed to do.

i have tried what you said so i came up with this:
but it doesn't work could you might help me ? the motors dont work and the servo doesn't work either.
also i am getting a nullpointerexception error.
could it also be possible to use something like a virtual pot meter so i can set the position as i want instead of program the arduino and then only can choose of a few positions

import oscP5.*;        //  Load OSC P5 library
import netP5.*;        //  Load net P5 library
import processing.serial.*;
import cc.arduino.*;
OscP5 oscP5;
Arduino arduino;
Serial arduinoPort;
float [] fader = new float [3];
int [] led = new int [2];   
void setup()
{
  size(360, 200);
  oscP5 = new OscP5(this,8000);  
  arduino = new Arduino(this, Arduino.list()[3], 57600); //your offset may vary

  arduino.pinMode(9, 5);
  println("klaar voor gebruik");
}







void oscEvent(OscMessage theOscMessage) {   //  This runs whenever there is a new OSC message

    String addr = theOscMessage.addrPattern();  //  Creates a string out of the OSC message

  if(addr.indexOf("/1/toggle") !=-1){   // Filters out any toggle buttons
      int i = int((addr.charAt(9) )) - 0x30;   // returns the ASCII number so convert into a real number by subtracting 0x30
      led[i]  = int(theOscMessage.get(0).floatValue());     //  Puts button value into led[i]
    // Button values can be read by using led[0], led[1], led[2], etc.
     
    }
    
       if(addr.indexOf("/1/fader") !=-1){ 
       String list[] = split(addr,'/');
     int  xfader = int(list[2].charAt(5) - 0x30);
     if(theOscMessage.get(0).floatValue() !=0){
     fader[xfader]  = theOscMessage.get(0).floatValue();
     }   
    }
}
void draw()
{
  
   if(fader[1] > 0.65){
    arduinoPort.write("AF100#");
  }
   if(fader[1] < 0.35){
    arduinoPort.write("AR100#");
  }
  //--------------------------------Motor B
   if(fader[2] > 0.65){
    arduinoPort.write("BF100#");
  }
   if(fader[2] < 0.35){
    arduinoPort.write("BR100#");
  }
  //----------------------------stop commands
     if(fader[1] < 0.65 && fader[1] > 0.35 ){
    arduinoPort.write("AF0#");
  }
       if(fader[2] < 0.65 && fader[2] > 0.35 ){
    arduinoPort.write("BF0#");
  }
  

if(led[1] == 0){        //  If led button 1 if off do....
    arduinoPort.write("U");    // Sends the character “r” to Arduino

  }
 if(led[1] == 1){        // If led button 1 is ON do...
  arduinoPort.write("P");    // Send the character “R” to Arduino

  }

and

#include <Servo.h>

// Test program for SparkFun Ardumoto board
// Copyright (c) 2009 mechomaniac.com
 
// To use, connect the Arduino to a computer and send commands using a serial terminal.
// eg AR40#   motor A forwards with a speed of 40
Servo myservo;
#define PwmPinMotorA 10
#define PwmPinMotorB 11
#define DirectionPinMotorA 12
#define DirectionPinMotorB 13
#define SerialSpeed 9600
#define BufferLength 16
#define LineEnd '#'
int message = 0;    
int redLED = 0;  
char inputBuffer[BufferLength];
 
void setup()
{
  // motor pins must be outputs
  pinMode(PwmPinMotorA, OUTPUT);
  pinMode(PwmPinMotorB, OUTPUT);
  pinMode(DirectionPinMotorA, OUTPUT);
  pinMode(DirectionPinMotorB, OUTPUT);
  myservo.attach(9);
  Serial.begin(SerialSpeed); 
}
 
// process a command string
void HandleCommand(char* input, int length)
{
  Serial.println(input);
  if (length < 2) { // not a valid command
    return;
  }
  int value = 0;
  // calculate number following command
  if (length > 2) {
    value = atoi(&input[2]);
  }
  int* command = (int*)input;
  // check commands
  // note that the two bytes are swapped, ie 'RA' means command AR
  switch(*command) {
    case 'FA':
      // motor A forwards
      analogWrite(PwmPinMotorA, value);
      digitalWrite(DirectionPinMotorA, HIGH);
      break;
    case 'RA':
      // motor A reverse
      analogWrite(PwmPinMotorA, value);
      digitalWrite(DirectionPinMotorA, LOW);
      break;
    case 'FB':
      // motor B forwards
      analogWrite(PwmPinMotorB, value);
      digitalWrite(DirectionPinMotorB, LOW);
      break;
    case 'RB':
      // motor B reverse
      analogWrite(PwmPinMotorB, value);
      digitalWrite(DirectionPinMotorB, HIGH);
      break;
    default:
      break;
  }  
} 
 
void loop()
{ 
  // get a command string form the serial port
  int inputLength = 0;
  do {
    while (!Serial.available()); // wait for input
    inputBuffer[inputLength] = Serial.read(); // read it in
  } while (inputBuffer[inputLength] != LineEnd && ++inputLength < BufferLength);
  inputBuffer[inputLength] = 0; //  add null terminator
  HandleCommand(inputBuffer, inputLength);
   

  
  
if (Serial.available() > 0) { //  Check if there is a new message
      message = Serial.read();    //  Put the serial input into the message

   if (message == 'U'){  //  If a capitol R is received...
      myservo.write(160);       //  Set redLED to 255 (on)
   }
   if (message == 'P'){  //  If a lowercase r is received...
     myservo.write(10);        //  Set redLED to 0 (off)
   }


  
}
}
//----------- End Arduino code ---------------

i have tried what you said so i came up with this:

import cc.arduino.*;
Arduino arduino;
  arduino = new Arduino(this, Arduino.list()[3], 57600); //your offset may vary

  arduino.pinMode(9, 5);

This is all still Firmata crap.

just some stupid thing i forgot i am a newbie.

I have changed my coding and it now works almost as it should.
except for the servo, when i try to control it via processing it doesnt work but when i control it from the serial monitor in the arduino IDE it works but i can only send it once a command and after that it doesn´t work any more.

these ar my code:

#include <Servo.h>

Servo myservo;
#define PwmPinMotorA 10
#define PwmPinMotorB 11
#define DirectionPinMotorA 12
#define DirectionPinMotorB 13
#define SerialSpeed 9600
#define BufferLength 16
#define LineEnd '#'
int message = 0;    
int redLED = 0;  
char inputBuffer[BufferLength];
 
void setup()
{
  // motor pins must be outputs
  pinMode(PwmPinMotorA, OUTPUT);
  pinMode(PwmPinMotorB, OUTPUT);
  pinMode(DirectionPinMotorA, OUTPUT);
  pinMode(DirectionPinMotorB, OUTPUT);
  myservo.attach(9);
  Serial.begin(SerialSpeed); 
}
 
// process a command string
void HandleCommand(char* input, int length)
{
  Serial.println(input);
  if (length < 2) { // not a valid command
    return;
  }
  int value = 0;
  // calculate number following command
  if (length > 2) {
    value = atoi(&input[2]);
  }
  int* command = (int*)input;
  // check commands
  // note that the two bytes are swapped, ie 'RA' means command AR
  switch(*command) {
    case 'FA':
      // motor A forwards
      analogWrite(PwmPinMotorA, value);
      digitalWrite(DirectionPinMotorA, HIGH);
      break;
    case 'RA':
      // motor A reverse
      analogWrite(PwmPinMotorA, value);
      digitalWrite(DirectionPinMotorA, LOW);
      break;
    case 'FB':
      // motor B forwards
      analogWrite(PwmPinMotorB, value);
      digitalWrite(DirectionPinMotorB, LOW);
      break;
    case 'RB':
      // motor B reverse
      analogWrite(PwmPinMotorB, value);
      digitalWrite(DirectionPinMotorB, HIGH);
      
     case 'PU':
         myservo.write(value);  
         
     case 'DW':
        myservo.write(value);
        
      break;
    default:
      break;
  }  
} 
 
void loop()
{ 
  // get a command string form the serial port
  int inputLength = 0;
  do {
    while (!Serial.available()); // wait for input
    inputBuffer[inputLength] = Serial.read(); // read it in
  } while (inputBuffer[inputLength] != LineEnd && ++inputLength < BufferLength);
  inputBuffer[inputLength] = 0; //  add null terminator
  HandleCommand(inputBuffer, inputLength);
   

  

}
import oscP5.*;        //  Load OSC P5 library
import netP5.*;        //  Load net P5 library
import processing.serial.*;
Serial arduinoPort; 
OscP5 oscP5;
float [] fader = new float [3];
int [] led = new int [2];   

void setup()
{
  arduinoPort = new Serial(this, Serial.list()[3], 9600);
  size(360, 200);
  oscP5 = new OscP5(this,8000);  
  println("klaar voor gebruik");
}

void oscEvent(OscMessage theOscMessage) {   //  This runs whenever there is a new OSC message
String addr = theOscMessage.addrPattern();  //  Creates a string out of the OSC message

  if(addr.indexOf("/1/toggle") !=-1){   // Filters out any toggle buttons
      int i = int((addr.charAt(9) )) - 0x30;   // returns the ASCII number so convert into a real number by subtracting 0x30
      led[i]  = int(theOscMessage.get(0).floatValue());     //  Puts button value into led[i]
    // Button values can be read by using led[0], led[1], led[2], etc.
     }
       if(addr.indexOf("/1/fader") !=-1){ 
       String list[] = split(addr,'/');
     int  xfader = int(list[2].charAt(5) - 0x30);
     if(theOscMessage.get(0).floatValue() !=0){
     fader[xfader]  = theOscMessage.get(0).floatValue();
     }   
    }
}
void draw()
{
  // -------------------------------- Motor A
   if(fader[1] > 0.65){
    arduinoPort.write ("AF200#");
  }
   if(fader[1] < 0.35){
    arduinoPort.write ("AR200#");
  }
  //--------------------------------Motor B
   if(fader[2] > 0.65){
    arduinoPort.write ("BF200#");
  }
   if(fader[2] < 0.35){
    arduinoPort.write ("BR200#");
  }
  //----------------------------stop commands
     if(fader[1] < 0.65 && fader[1] > 0.35 ){
   arduinoPort.write ("AF0#");
  }
       if(fader[2] < 0.65 && fader[2] > 0.35 ){
    arduinoPort.write ("BF0#");
  }
  //--------------------------------- Servo

if(led[1] == 0){        
    arduinoPort.write ("UP160#");    
 
  }
 if(led[1] == 1){        
  arduinoPort.write ("DW10#");     

  }}
    case 'FA':

Please define how you are sending these multi-byte characters to the Arduino. The Serial Monitor can not send them.

well my code works now!!! :smiley: :smiley: :smiley:
i can control a servo and two motors now from my iphone.

and i didn't change anything to the "FA" (i dont say that it can't improve my code)