Send command for RC Car

Hi,

I´m making one R/C Car with two xbee and two arduinos UNO, in one side i´m using 4 buttons for front, left, right and back. On other side i have the car.

I just want to know if i´m using the best programming pratice: from the side of buttons i send in hexadecimal bytes for each state of my 4 buttons, if is on or off:

0x1 Left On
0x2 Right On
0x3 Back On
0x4 Front On
0x5 Left Off
0x6 Right Off
0x7 Back Off
0x8 Front Off

i send this byte to other arduino and im using if conditions for each byte to activate the diferent outputs (Servo, motors). do you know a better way to do this.

In future i want use one joystick to control my car.

Thanks for your advices:)

0x1 = 1
0x2 - 2
0x3 = 3
.
.
.
0x8 = 8

It makes sense to use the base this is most appropriate to the problem. In this case, I see no reason to use hex notation.

ok, i understand your point.

But with my last experiences i have a problem with number bigger than 9.

For exemple if i want make a diference between my buttons and the values from my joystick (not implemented yet) in serial comunication, how can i do this?

Send a letter + a number like "L0"-> for Left Off and "L1"-> for Left On for my buttons and send my joystick value in int type?

I try to send this but i only receive the last characther it why i try with hexadecimal numbers

For exemple if i want make a diference between my buttons and the values from my joystick (not implemented yet) in serial comunication, how can i do this?

First, I don't see this as a logical thing to do. How can the difference between a joystick value, on a scale of 0 to 1023 and a switch state, 0 or 1, be meaningful.

I think it would be best if you explained what you want to do, rather than how you think you should do it.

Ok sorry,

I want control my car with 4 buttons and on joystick (I have joystick shield from sparkfun).

My idea is send commands from my 4 buttons and joystick (with arduino and xbee) to another arduino with xbee in my car.

The communication between xbee is working great, i have no problem with this.

My only problem is the method to use for comunication between my two arduino. do you understand?

for exemple how can i send and read the value L0 or L1, i have try some code but don´t work, give me the last character ( 0 or 1) or working only from 0 to 9.

The communication between xbee is working great, i have no problem with this.

Great. That puts you one up on a lot of people here.

My only problem is the method to use for comunication between my two arduino. do you understand?

Yes. You are struggling to define a protocol.

A protocol is an agreed upon method for the exchange of information. Both sides (the sender and the receiver) need to understand how the data is going to be presented, and both sides need to present, or interpret, data the same way.

for exemple how can i send and read the value L0 or L1, i have try some code but don´t work, give me the last character ( 0 or 1) or working only from 0 to 9.

I would prefer to see the code that does not work for you.

Sending "L1" is quite simple. Having the receiver know that the packet is complete is hard. I prefer the use of start and end of packet markers for this very reason.

If the sender sends "" instead, this code:

#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';
  }
}

can read the packet, and KNOW that the packet consists of the characters "L1".

Where it says "Process the packet", you could put:

char ltr = inData[0];
inData[0] = '0';

This would make inData "01". Then:

int val = atoi(inData);

would make val 1.

So, now you have the letter, in ltr, and the value, in val. You can easily do what you need to with this data.

If the sender sent , that code would result in ltr = 'X' and val = 908, which is perfect for whatever you need to do with the data.

So, now, you have a protocol. Commands consist of a singe letter followed by an integer value of any number of digits, enclosed in angle brackets.

thanks very much PaulS, i will try this now!

I have some problems to understand some questions about data type in C, do know a good book about this?

I give you the feedback about the experiments, thanks for your useful help

I have some problems to understand some questions about data type in C, do know a good book about this?

There are only a handful of data types that are native - int, float, long, char, bool, etc. Any C book will talk about these basic types. Even the reference page covers them.

can you explain this line:

if(index < 79)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }

I don´t understand the part inData[index]

can you explain this line:

inData is an array. It can hold 80 elements, in positions 0 to 79. If the position to insert the value in the array, stored in index, is less than 79 (should really be 78), then add the character at that position in the array. Then, increment the position to insert (the index++ part), and then insert a NULL at that position.

Ok thanks for the explanation,

I add like you say this line:
char ltr = inData[0];
inData[0] = '0';
int val = atoi(inData);
Serial.println(val);

after // The end of packet marker arrived. Process the packet

end send in serial monitor of other arduino this line: "<Arduino!>"

But i don´t receive anything in serial port of my receiver.

on the sender i have this:

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


void loop() {
 //val="<Hello Arduino!>";
    Serial.write ("<Arduino!>"); //sends an "On" message
 
delay(1000);
  
}

and on the receiver i have this:

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

bool started = false;
bool ended = false;

char inData[80];
byte index;

void setup()
{
   Serial.begin(9600);
   // 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
char ltr = inData[0];
inData[0] = '0';
int val = atoi(inData);
Serial.println(val);
    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
}

But nothing appear in serial monitor of receiver, where is my mistake?my xbee comunication is Ok, i have tested with a last program and data is sending and receive is ok

But nothing appear in serial monitor of receiver, where is my mistake?

I don't know. So, add some more Serial.print() statements to the receiver.

Do the transmit and receive lights on the XBee shields blink appropriately?

The protocol we defined was <. letter, value, >. How is rduino! supposed to be converted to a value?

lol sorry, i make a mistake; it´s working great:)

one more time thanks PaulS for your help.

Hi,

i want add a timeout if the communication have lost some package in the <>, do you knows what is time for that?im thinking about 20ms per package : ""?

after receive "<" if the time is more than 20ms, the receiver send a byte to sender to send the same package one more time.

What do you think?

i have make some test with millis() between i receive < and > and when i send for exemple "<255>", he give 5ms «, i think 20ms is good for a timeout...

i have make some test with millis() between i receive < and > and when i send for exemple "<255>", he give 5ms «, i think 20ms is good for a timeout...

Once again, I thought the protocol was <, letter, value, >...

9600 baud is approximately 1 character per millisecond. With a packet that can be 7 characters long, the largest packet should arrive in 7 milliseconds, so 20 milliseconds is probably not a bad time limit.

You can record when the < arrives, using millis.You can record when the > arrives, again using millis. If the difference in times if greater than 20, ask that the value be sent again.

However, I don't see the benefit of this. The long delay you have on the sender will make it wait 1 second before it sees the request to resend the packet.

Something more like a standard RC transmitter, where the sender sends data at close intervals, even of the data is the same as what was sent last time, might be a better idea.

Something more like a standard RC transmitter, where the sender sends data at close intervals, even of the data is the same as what was sent last time, might be a better idea.

Ok great ideia, i will try apply your advice.

Once again, I thought the protocol was <, letter, value, >...

Sorry, i try now with only letters for my buttons...it´s working, for joystick i use only the number but is not for now.

But now i have another problem:

See my code:

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

bool started = false;                
bool ended = false;                  

char inData[80];
byte index;
unsigned long time=0;               
unsigned long time2=0;              
unsigned long time3=0;               
long timeout=20;
int led = 13;

const char turn_right_On[6]="EON";
const char turn_right_Off[6]="EOF";
cons tchar turn_lft_On[6]="DON";
const char turn_lft_Off[6]="DOF";
const char front_On[6]="FON";
const char front_Off[6]="FOF";
const char back_On[6]="RON";
const char back_Off[6]="ROF";
//----------------------------------------------------------
void setup()
{
   Serial.begin(9600);                // opens serial port
 pinMode(led,OUTPUT);
}
//-----------------------------------------------------------


void loop()
{
while(Serial.available() > 0)         
{
  char inChar = Serial.read();       
  
  
  if(inChar == SOP)                   
  {
  time = millis();                   
  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';
   }
  }
}


if(started== true && ended==false)
{
time2 = millis(); 
time3=(time2-time);

 if (time3>=timeout)
 {
 Serial.println("timeout");
 goto reset; 
 }
}
  
if(started && ended)
{
 
Serial.println(inData);
if (inData==turn_lft_On){
led==HIGH;
}

if (inData==turn_lft_Off){
led==LOW;
}  
  




 reset: 
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
    time=0;
    time2=0;
    time3=0;

}
}

I try when i receive the turn_lft_On turn led on and turn_lft_Off turn led off but nothing appears with the led...

I receive in serial comunication corrects data (in the line Serial.println(inData); i see in serial monitor DON (stored in turn_lft_On turn).

I´m thinking about a problem in data type between turn_lft_On turn and inData...

led==HIGH;

Wrong. == is a comparison operator. = is an assignment operator.

 goto reset;

Wrong. You do not need a goto. I've been doing C and C++ programming for 25+ years and have not type goto since I quit doing FORTRAN programming.

if (inData==turn_lft_On){

inData is the address of an array. turn_lft_On is the address of an array. It should be obvious that the addresses are not the same. strcmp() bears looking at.

Code:
led==HIGH;
Wrong. == is a comparison operator. = is an assignment operator.

About this i make this mistake during write the code.

inData is the address of an array. turn_lft_On is the address of an array. It should be obvious that the addresses are not the same. strcmp() bears looking at.

Thanks for your advice, i use the strcmp()function and it´s working great.

One more time thank you very much, if you need something i can help.

I learning arduino and C programming, i want to buy a good for this, what is your advice, i see arduino cookbook like a good choice?