Arduino Xbee serial communication with potentiometers

Dear all.

I have the following problem. I want to control with one arduino with 3 potentiometers, 3 other arduino with RGB leds. I want to do this with use of XBee pro. So far i managed to control with one potentiometer, one arduino. But i have no idea how to make it work with more than one receiving point.

I used this code for the sender:

int potPin = 3; // Potentiometer output connected to analog pin 3
int potVal = 0; // Variable to store the input from the potentiometer
int prevpotVal= -1; //stabilizing the values by establishing a difference and by making the system check
void setup()
{
  Serial.begin(9600);

}

void loop() {
  potVal = analogRead(potPin)/4 ;

  if (potVal!= prevpotVal){  
    

    Serial.write(potVal); // read the potentiometer value at the input pin

    prevpotVal= potVal; //
  }


  delay(50); //limit how fast we update
}

and this code for the receiver:

int MaxPotVal= 0; //storing the MaxPotVal

int redPin = 9;   // Red LED,   connected to digital pin 9
int grnPin = 10;  // Green LED, connected to digital pin 10

int redVal = 0;   // Variables to store the values to send to the pins
int grnVal = 0;
int DEBUG = 1; 


void setup()
{
Serial.begin(9600);
pinMode(redPin, OUTPUT); // sets the pins as output
pinMode(grnPin, OUTPUT);

}

void process_incoming_command(int value)  //fading function 
{
  value = map(value,0, MaxPotVal, 0, 255); //map the value coming from the potentiometer and translate them in a range from 0 to 255 - RGB values) 
  redVal = 255-value;
  grnVal = value;
  

  analogWrite(redPin, redVal);   // Write values to LED pins
  analogWrite(grnPin, grnVal); 

//Debugging code taken from http://www.arduino.cc/en/Tutorial/LEDCross-fadesWithPotentiometer
  if (DEBUG) { // If we want to read the output 
    DEBUG += 1;      // Increment the DEBUG counter
    if (DEBUG > 100) // Print every hundred loops
    {
      DEBUG = 1;     // Reset the counter
                              // Serial output using 0004-style functions
      Serial.print("R:");    // Indicate that output is red value
      Serial.print(redVal);  // Print red value
      Serial.print("\t");    // Print a tab
      Serial.print("G:");    // Repeat for grn and blu...
      Serial.print(grnVal);
      Serial.print("\t");    
    }
  }

}

void loop() {
  
if (Serial.available()) //if the serial communication is available...
{
int potVal = Serial.read();  //read the value 

if (potVal > MaxPotVal){  //check the value 
  
  MaxPotVal= potVal; 
}

int value = potVal; // state potVal equal to value

process_incoming_command(potVal); //execute the function 
}

}

They work perfectly. I was thinking to use potVal1new = "AA" + potVal; potVal2new = "BB" + potVal2; and so on.. but that wont work.

Has somebody any idea how to solve this problem?

I use arduino uno.

Thanks in advance!

Has somebody any idea how to solve this problem?

Stop sending binary data.

You could send “<2, R, 126>” to tell device #2 to turn it’s red pin to level 126. Each receiver would read the data. Each would start storing the code when the SOP (start of packet) character (’<’) arrived. Each would stop storing the data, and would parse and maybe use it, when the EOP (end of packet) marker (’>’) arrived.

Parsing the packet involves using strtok() and possibly atoi().

Each device would have a unique ID. If the ID of the packet matched the Arduino’s ID, it would parse the rest of the data and use it. Otherwise, it would simply discard the packet.

I would use a state machine driven by serial input. Every time through loop() it would check for serial available and read the char if there is, do nothing if not.

What it does with the char depends on the process State.

State 0 would be waiting for a 1st char. If it is 'A' then set state to 10. If 'B' then set state to 20. If neither then set state to 200, the error state.

State 10 would be looking for another 'A'. if the char is 'A', change state to 12 else change it to 200. State 12 would save the char in an int, 1st or 2nd byte depends on the order you send them, and set state to 14. State 14 would save the char in the other byte of the int and then do whatever is desired with the pot read data and then set state to 0.

State 20-24 are pretty much the same as states 10-14. This should suggest that with a little more code, both values could be handled by the same code but for now just learn this much.

State 200 is for errors. Should it shut the operation down or just ignore that part of the message? And how does it do that unless your data has delimiters/separators between AA## and BB##?

Code to run the state machine is usually done with a switch-case statement but could be some other ways.

Parsing these packets requires comparing chars for == or loading them into int variables. That's it, no text processing/conversion functions required.

Nick Gammon explains State Machines in the second blog page I have addressed in my signature space at the bottom of this post. He includes code.

I have the following problem. I want to control with one arduino with 3 potentiometers, 3 other arduino with RGB leds. I want to do this with use of XBee pro. So far i managed to control with one potentiometer, one arduino. But i have no idea how to make it work with more than one receiving point.

I can’t speak to the xbee part, but the below servo control code might have a useful setup. The basic operation is to send a data packet with a numeric value, a device identifier, and an end of packet marker. This particular code was written for sending joystick servo commands over a wireless network. It is setup to send commands only when there is a command change to reduce network data churn. On the receiving end all receivers will capture all data packets, look for the device identifier in the captured data packet, and act on the numeric data if it is for this device.

//zoomkat multi pot/servo test 3-23-13
//includes dead band for testing and limit servo hunting
//view output using the serial monitor

#include <Servo.h> 
Servo myservo1;  //declare servos
Servo myservo2;
Servo myservo3;
Servo myservo4;
Servo myservo5;

int potpin1 = 0;  //analog input pin A0
int potpin2 = 1;
int potpin3 = 2;
int potpin4 = 3;
int potpin5 = 4;

int newval1, oldval1;  //pot input values
int newval2, oldval2;
int newval3, oldval3;
int newval4, oldval4;
int newval5, oldval5;

void setup() 
{
  Serial.begin(9600);  
  myservo1.attach(2);  
  myservo2.attach(3);
  myservo3.attach(4);
  myservo4.attach(5);
  myservo5.attach(6);
  Serial.println("testing multi pot servo");  
}

void loop()
{ 
  newval1 = analogRead(potpin1);           
  newval1 = map(newval1, 0, 1023, 0, 179); 
  if (newval1 < (oldval1-2) || newval1 > (oldval1+2)){ //dead band 
    myservo1.write(newval1); //position the servo
    Serial.print("1- ");
    Serial.println(newval1); //print the new value for testing 
    oldval1=newval1; //set the current old value
  }

  newval2 = analogRead(potpin2);
  newval2 = map(newval2, 0, 1023, 0, 179);
  if (newval2 < (oldval2-2) || newval2 > (oldval2+2)){  
    myservo2.write(newval2);
    Serial.print("2- ");    
    Serial.println(newval2);
    oldval2=newval2;
  }

  newval3 = analogRead(potpin3);           
  newval3 = map(newval3, 0, 1023, 0, 179); 
  if (newval1 < (oldval1-2) || newval3 > (oldval3+2)){  
    myservo1.write(newval3);
    Serial.print("3- ");
    Serial.println(newval3);
    oldval3=newval3;
  }

  newval4 = analogRead(potpin4);           
  newval4 = map(newval4, 0, 1023, 0, 179); 
  if (newval1 < (oldval1-2) || newval4 > (oldval4+2)){  
    myservo1.write(newval4);
    Serial.print("4- ");
    Serial.println(newval4);
    oldval4=newval4;
  }

  newval5 = analogRead(potpin5);           
  newval5 = map(newval5, 0, 1023, 0, 179); 
  if (newval1 < (oldval5-2) || newval5 > (oldval5+2)){  
    myservo1.write(newval5);
    Serial.print("5- ");
    Serial.println(newval5);
    oldval5=newval5;
  } 
  delay(50);  //to slow loop for testing
}

Thanks guys! I will work on it tomorrow again and try your advices. I will let you know!

(btw I am a newbie in arduino serial communication, so it may take some time)

PaulS:
Stop sending binary data.

You could send “<2, R, 126>” to tell device #2 to turn it’s red pin to level 126. Each receiver would read the data. Each would start storing the code when the SOP (start of packet) character (’<’) arrived. Each would stop storing the data, and would parse and maybe use it, when the EOP (end of packet) marker (’>’) arrived.

Parsing the packet involves using strtok() and possibly atoi().

Each device would have a unique ID. If the ID of the packet matched the Arduino’s ID, it would parse the rest of the data and use it. Otherwise, it would simply discard the packet.

Dear PaulS, could you explain it somemore? I forgot to mention that the three RGB should work separately. I used binary data because it didnt work with sending other values over serial communication.

GoForSmoke: I would use a state machine driven by serial input. Every time through loop() it would check for serial available and read the char if there is, do nothing if not.

What it does with the char depends on the process State.

State 0 would be waiting for a 1st char. If it is 'A' then set state to 10. If 'B' then set state to 20. If neither then set state to 200, the error state.

State 10 would be looking for another 'A'. if the char is 'A', change state to 12 else change it to 200. State 12 would save the char in an int, 1st or 2nd byte depends on the order you send them, and set state to 14. State 14 would save the char in the other byte of the int and then do whatever is desired with the pot read data and then set state to 0.

State 20-24 are pretty much the same as states 10-14. This should suggest that with a little more code, both values could be handled by the same code but for now just learn this much.

State 200 is for errors. Should it shut the operation down or just ignore that part of the message? And how does it do that unless your data has delimiters/separators between AA## and BB##?

Code to run the state machine is usually done with a switch-case statement but could be some other ways.

Parsing these packets requires comparing chars for == or loading them into int variables. That's it, no text processing/conversion functions required.

Nick Gammon explains State Machines in the second blog page I have addressed in my signature space at the bottom of this post. He includes code.

Hey GoForSmoke, Thanks for your reply. I am currently trying to get it work with your state suggestion. I think I do understand your suggestion but does this work with the 0 till 1053 input of the potentiometer? Your suggestion is about the receiver side right? How can I make a variable with AA + potentiometer value? Any idea? I am sorry, I am really new in the arduino/xbee world. I am trying to finish it before friday because of a deadline for school.

Thanks in advance

If you use code like this:

#define SOP '<'
#define EOP '>'

bool started = false;
bool ended = false;

char inData[80];
byte index = 0;

void setup()
{
   Serial.begin(9600);
}

void loop()
{
  while(Serial.available() > 0)
  {
    char inChar = Serial.read();
    if(inChar == SOP)
    {
       index = 0;
       inData[index] = '\0';
       started = true;
       ended = false;
    }
    else if(inChar == EOP)
    {
       ended = true;
       break;
    }
    else
    {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
    }
  }
   
  if(started && ended)
  {
     // Process the packet

     started = false;
     ended = false;
  }
}

and send “<2, R, 36>”, where is says "Process the packet, inData will contain “2, R, 36”. The strtok() function can be used to extract the tokens “2”, “R”, and “36”. Since the first and third tokens are numeric representations of values, atoi() can convert them to values.

You can modify your sending code like below to use a comma as an end of packet marker. and use code like bottom serial servo code to receive parse the serial packet transmissions.

  newval1 = analogRead(potpin1);           
  newval1 = map(newval1, 0, 1023, 0, 255);
  if (newval1 < (oldval1-2) || newval1 > (oldval1+2)){ //dead band
    //myservo1.write(newval1); //position the servo
    Serial.print(newval1); //numeric value
    Serial.print(','); //end of packet delimiter
    oldval1=newval1; //set the current old value
//zoomkat 3-5-12 simple delimited ',' string parse 
//from serial port input (via serial monitor)
//and print result out serial port

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

void setup() {
  Serial.begin(9600);

  myservo.writeMicroseconds(1500); //set initial servo position if desired
  myservo.attach(7);  //the pin for the servo control 
  Serial.println("servo-delomit-test-22-dual-input"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like 700, or 1500, or 2000,
  //or like 30, or 90, or 180,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >0) {
        Serial.println(readString); //prints string to serial port out

        int n = readString.toInt();  //convert readString into a number

        // auto select appropriate value, copied from someone elses code.
        if(n >= 500)
        {
          Serial.print("writing Microseconds: ");
          Serial.println(n);
          myservo.writeMicroseconds(n);
        }
        else
        {   
          Serial.print("writing Angle: ");
          Serial.println(n);
          myservo.write(n);
        }

        //do stuff with the captured readString 
        readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}