Go Down

Topic: Xbee communication Error (Read 2192 times) previous topic - next topic

Gfast

I just work on a project that use Processing control a small robot drived by Arduino Dumelianove with 2 Xbee. This robot have 4 steppers, 4LEDs and two relays. Every 5 Second will the Processing send a message "#1001001000", after the beginning '#' every 3 charactor means the info. for each stepper,'1' means direction of the stepper and the following 2 means the steps. The last charactor means the control of two relays. With cable works the robot pretty good. But if I try to use two xbee the Stepper moved weird.most time work each step right, but about each 10 Time will a Error step appear. sometimes moved more sometimes the relays didn't work and so on.

I used paar "XBee 2mW Series 2.5 Wire Antenna" and a "XBee Explorer USB" from sparkfun to connect one xbee to my MAC. I think must be something wrong with the xbee part.

Code: [Select]

//Here is the prototype of the Communication between MAC and robot, Processing part

import processing.serial.*;
Serial arduinoPort;

long previousMillis = 0;

int i = 0;

void setup(){
    arduinoPort = new Serial(this , Serial.list()[0], 9600);
    delay(2000);
}

void draw(){
 
  long currentMillis = millis();
 
  //port.available() can direct store the value when possible
  //then the value of the port is once more empty
//  while (arduinoPort.available() > 0){
//  int inByte = arduinoPort.read();
//  println(inByte);
   
    if(currentMillis - previousMillis > 5000){
      arduinoPort.write("#0101001001001");     
      previousMillis = currentMillis;
      print("Now is ");
      println(i);
      i++;
    }
  //} 
// arduinoPort.clear();
}


than Arduino part
Code: [Select]

#define ST1 2  //ST1 means "Steppermotor 1's step number"
#define DI1 3  //DI1 means "Steppermotor 1's step direction"
#define ST2 4
#define DI2 5
#define ST3 7
#define DI3 8
#define ST4 12
#define DI4 13
int SL1 = A1;  //SL1 means "Steppermoto 1's sleep mode"
int SL2 = A2;
int SL3 = A3;
int SL4 = A4;

#define LED1 6  //LED1 is the control Pin of one of four LED that put on the Robot
#define LED2 9
#define LED3 10
#define LED4 11

int FOCUS = A0;  //the control Pin of the Focus function on the camera
int SHUTTER = A5;  //the control Pin of the Shutter on the camera

char buffer[14];  //store the Sequence that followed by "#" as the input from the Serial port
byte inByte = 0;  //detect if the input is the "#"
int  pointer = 0;  //to store the number of the buffers' arrays

int motor1 = 0;  //store the move amount for each motor from Serial
int motor2 = 0;
int motor3 = 0;
int motor4 = 0;


///////////////////////////////////////////////////////////////

void setup(){
  pinMode(ST1, OUTPUT);
  pinMode(DI1, OUTPUT);
  pinMode(ST2, OUTPUT);
  pinMode(DI2, OUTPUT);
  pinMode(ST3, OUTPUT);
  pinMode(DI3, OUTPUT);
  pinMode(ST4, OUTPUT);
  pinMode(DI4, OUTPUT);
  pinMode(SL1, OUTPUT);
  pinMode(SL2, OUTPUT);
  pinMode(SL3, OUTPUT);
  pinMode(SL4, OUTPUT);
 
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(LED4, OUTPUT);
 
  pinMode(SHUTTER, OUTPUT);
  pinMode(FOCUS, OUTPUT);
 
  Serial.begin(9600);
  //Serial.println("OK, all Pins' define are done"); 
 
  digitalWrite(SL1, 0);
  digitalWrite(SL2, 0);
  digitalWrite(SL3, 0);
  digitalWrite(SL4, 0);
 
  digitalWrite(FOCUS,0);
  digitalWrite(SHUTTER,0);
 
  //this part let Smaker warm up
  for(int k=0; k<256; k+=5){
    analogWrite(LED1, k);
    delay(30);
  }
  for(int k=0; k<256; k+=5){
    analogWrite(LED2, k);
    delay(30);
  }
  for(int k=0; k<256; k+=5){
    analogWrite(LED3, k);
    analogWrite(LED4, k);
    delay(30);
  }
 
}

///////////////////////////////////////////////////////////////

void loop(){
  inByte = Serial.read();
  if(Serial.available() > 0){
    if(inByte == '#'){
      //store the info. from Serial
      //Structure is #0FF0FF0FF0FF, 0s are the direction of each motor, 0 = LOW
      //FFs are the amount of the steps that stepper should go
      while(pointer < 13){
        buffer[pointer] = Serial.read();
        pointer ++;
      }
 
    motor1 = hex2dec(buffer[2]) + hex2dec(buffer[1]) * 16;
    motor2 = hex2dec(buffer[5]) + hex2dec(buffer[4]) * 16;
    motor3 = hex2dec(buffer[8]) + hex2dec(buffer[7]) * 16;
    motor4 = hex2dec(buffer[11]) + hex2dec(buffer[10]) * 16;
   
   
    pointer = 0;  //reset the pointer so can be reuse the buffer
    }
  }else if(Serial.available() == 0){  //when there is no input, set all value to zero
    motor1 = 0;
    motor2 = 0;
    motor3 = 0;
    motor4 = 0;
    buffer[12] = 0;  //when there is no Serial input, take no foto
  }
 
  if(buffer[0] == '0'){    //this part can set the direction of each motor
    digitalWrite(DI1, LOW);
  }else if(buffer[0] == '1'){
    digitalWrite(DI1, HIGH);
  }
  if(buffer[3] == '0'){
    digitalWrite(DI2, LOW);
  }else if(buffer[3] == '1'){
    digitalWrite(DI2, HIGH);
  }
  if(buffer[6] == '0'){
    digitalWrite(DI3, LOW);
  }else if(buffer[6] == '1'){
    digitalWrite(DI3, HIGH);
  }
  if(buffer[9] == '0'){
    digitalWrite(DI4, LOW);
  }else if(buffer[9] == '1'){
    digitalWrite(DI4, HIGH);
  }
 
  //take the Photo first than make the movement
  if(buffer[12] == '1'){
    //cause the structur is not very stable,
    //so wait a moment till the vibration stop
    delay(2000);
    foto();
    //write something to tell processing give the next info Data
    delay(500);  //time for the camera's exposure 
  }else if(buffer[12] == '3'){
    delay(2000);
    foto();
    delay(500);
    foto();
    delay(500);
    foto();
    delay(500);
   
  }
 
  go(1, motor1, 1);  //this part can give each motor steps number
  go(2, motor2, 1);
  go(3, motor3, 1);
  go(4, motor4, 1);
 
  delay(50);  //balance the Arduino's speed to save battery
  Serial.print('?');
  led();  //blink the LED on board 
   
}

///////////////////////////////////////////////////////////////
int hex2dec(byte c){
  if(c>= '0' && c<= '9'){
    return c - '0';
  }else if(c >= 'A' && c <= 'F'){
    return c - 'A' + 10;
  }
}

///////////////////////////////////////////////////////////////

void go(int stNumber,int stAmout,int stSpeed){
 
  int selected = 0;  //to assign the StPin's number
  int i = 0;   //to Set the counter variable
  /*
  Serial.print("Stepper ");
  Serial.print(stNumber);
  Serial.print(" is moving: ");
  Serial.print(stAmout);
  Serial.println(" steps");  //show all movements of four motors, println = print+return+newline meaning
  */
 
  switch(stNumber){
    case 1:
      //digitalWrite(DI1,stDir);  //set the direction of the rotation of the Stepper
      selected = ST1;  //assign the ST1 as aimed operate object
      digitalWrite(SL1,HIGH);  //awake the aimed Stepper
      while(i < stAmout){  //in full step situation, stAmout means how many rotate
        digitalWrite(selected,LOW);
        digitalWrite(selected,HIGH);
        delayMicroseconds(1600/stSpeed);
        i++;
      }
      digitalWrite(SL1,LOW);  //let the stepper go to sleep
      break;
   
   
    case 2:
      //digitalWrite(DI2,stDir);
      selected = ST2; 
      digitalWrite(SL2,HIGH); 
      while(i < stAmout){ 
        digitalWrite(selected,LOW);
        digitalWrite(selected,HIGH);
        delayMicroseconds(1600/stSpeed);
        i++;
      }
      digitalWrite(SL2,LOW);   
      break;
     
   
    case 3:
      //digitalWrite(DI3,stDir);
      selected = ST3; 
      digitalWrite(SL3,HIGH); 
      while(i < stAmout){ 
        digitalWrite(selected,LOW);
        digitalWrite(selected,HIGH);
        delayMicroseconds(1600/stSpeed);
        i++;
      }
      digitalWrite(SL3,LOW); 
      break;
     
   
    case 4:
      //digitalWrite(DI4,stDir);
      selected = ST4; 
      digitalWrite(SL4,HIGH); 
      while(i < stAmout){ 
        digitalWrite(selected,LOW);
        digitalWrite(selected,HIGH);
        delayMicroseconds(1600/stSpeed);
        i++;
      }
      digitalWrite(SL4,LOW); 
      break;
  }
 
}

///////////////////////////////////////////////////////////////

void foto(){
  digitalWrite(LED1,LOW);
  digitalWrite(LED2,LOW);
  digitalWrite(LED3,LOW);
  digitalWrite(LED4,LOW);
 
  digitalWrite(FOCUS, HIGH);
  delay(50);
  digitalWrite(SHUTTER,HIGH);
  delay(500);
  digitalWrite(FOCUS, LOW);
  digitalWrite(SHUTTER,LOW);
   
}

boolean ledState = LOW;
long previousMillis = 0;
long interval = 900;

void led(){
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval){
    previousMillis = currentMillis;
   
    if(ledState == LOW)
      ledState = HIGH;
     else
     ledState = LOW;
     
     //ledState = LOW ? HIGH : LOW;
   
    digitalWrite(LED1, ledState);
    digitalWrite(LED2, ledState);
    digitalWrite(LED3, ledState);
    digitalWrite(LED4, ledState);
  }
}

PaulS

Quote
I think must be something wrong with the xbee part.

No, it is not the XBee's fault.

Code: [Select]
  if(Serial.available() > 0){
    if(inByte == '#'){
      //store the info. from Serial
      //Structure is #0FF0FF0FF0FF, 0s are the direction of each motor, 0 = LOW
      //FFs are the amount of the steps that stepper should go
      while(pointer < 13){
        buffer[pointer] = Serial.read();

If there is a byte available, read all 13 of them. Most of the time, you can probably get away with this, but now and then, it will bite you.

You are sending a start of packet marker. Add an end of packet marker, too. Then, something like this can be used to read the data:
Code: [Select]

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

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(57600);
   // Other stuff...
}

void loop()
{
  // Read all serial data available, as fast as possible
  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
    {
      if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }

  // We are here either because all pending serial
  // data has been read OR because an end of
  // packet marker arrived. Which is it?
  if(started && ended)
  {
    // The end of packet marker arrived. Process the packet

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

Where it says "Process the packet" is where you put your code to use the incoming data.
The art of getting good answers lies in asking good questions.

nescivi

XBee Series 2 is notoriously bad at sending data from a coordinator to a node.
Did you hook up an LED to the XBee to see whether it is receiving the message from the coordinator at all?

Gfast

Wow,for me is that really a great new solution! Pauls, thank you so much.
As a program starter I still don't understand the meaning of " inData[index] = '\0'; ", Is that means make the "inData[index]" as the end of the Array,but the value is still the "inChar" or something?
and you said I should speed up the Serial port. But I do care about the power consumption of different speed of the Serial port. Cause I just plan to let the Robot take "Time-lapse". So I have to do all you can to save the Batteries.By the way, is there any one can give me a input about the power consumption of the Serial port and the Xbee in different speed?

Thank you so much!! XD

Gfast

to nescivi:

LED? not yet, but I've tried to see the LEDs of RX and TX. And I'm sure I've seen something happened when new Data comed. Just as Pauls said, perhaps I just need to rewrite part of my code to fit the "Wireless Control". :)

PaulS

Quote
As a program starter I still don't understand the meaning of " inData[index] = '\0'; ",

A string is a character array that is NULL terminated. That statement is NULL terminating the array.

Quote
By the way, is there any one can give me a input about the power consumption of the Serial port and the Xbee in different speed?

Baud rate has no relationship to power consumption.
The art of getting good answers lies in asking good questions.

Gfast

Ok Pauls,thanks so much. But I have to ask, "That statement is NULL terminating the array " means the "NULL" is actually equal to "inData[index+1] = 0" ?

PaulS

NULL is a value, usually written as '\0' to distinguish it from 0. Not that there really is anything to distinguish it, but since NULL is stored in a character array, it is used to visually provide a clue.

That value is being placed in the array after the index is incremented, so it immediately follows the last character.
The art of getting good answers lies in asking good questions.

Gfast

Thank you so much Pauls. Now my Robot works wirelessly really really sweet! ; )

But some part of the Serial communication I still can't understand. I mean, I just let arduino give a feedback to processing(just character "?" each loop), in oder to tell processing that the process in Arduino is over.if I use a cable, the "arduinoport.read();" can get the number "63",but if I use one pair Xbee. It can be "63","13","10". At the same time, If I turn off the Power of Arduino, Processing can still feed back these numbers, even if I've get off the Xbee from my MAC. What kind of reason can it be?

Thanks

Jack Christensen


XBee Series 2 is notoriously bad at sending data from a coordinator to a node.
Did you hook up an LED to the XBee to see whether it is receiving the message from the coordinator at all?


Really?? It's odd that I haven't noticed this. Would you provide a reference or an example demonstrating said problem, please?

PaulS

Quote
It can be "63","13","10".

This happens when you use println() instead of print(). The 10 and 13 are the carriage return and line feed values that println() adds.
The art of getting good answers lies in asking good questions.

Go Up