sending all sensor read in one time via xbee (my home monitor project)

hi

hmmm last what i want to know it is "there is no way to do what with serial port and XBee)

i want to make my own project or home monitor and control (whatever you call it just want it

to run)

first time i work on Arduino i find it something cool and more easier than Parallax Quickstart

Microcontroller board

.. it's have more example more project open source and a lots of things

i decide to spend all my budget for several month to buy my kit and working on Arduino to make

some cool project for beginner and do that just for fun and learn more thinks about electronic

and programming

i but many kit form Aliexpress it's cost me 120 $ us and form Seeedstudio 186.40 $ us and from Sparkfun 175 $ us

maybe someone say that's too much (he is right i agree with him but i prefer to spend my budget

for several month of work to buy this things to learn from it instead of buying Playstation4 or

Xbox One )

i buy many sensor for gas and motion and vibration and buzzer also i buy lcd screen an Arduino board 2 XBee wireless series 1 pro and a lots of sensors

this picture is for some of my kits

i success to work with all sensor and kits and make good mini project for sensor with screen

and many other project with my kits

i want to make something more advance like connect all this sensor together and use the XBee to

send the sensors values form one Arduino to the other Arduino with XBee in my room to receive

the sensors read and control other kits connected to arduino mega (use mega because it contain

a lots of pin and it's have bigger EEPROM)

but i surprise when i find that i cant send multi value by XBee in the same time i need to send every sensor read as single then receive it what about the other sensor and controlling the servo motor and other things

i want to make it in one sending mode send all the sensors values and the controlling value in one code and receive it then split

every read value

so my question is can i send mutli sensor value by XBee to collect all sensors read from another Arduino

i try to write my own code as test

this code for transmitter

char test='Hello World';
void setup(){
 // Start up our serial port, we configured our XBEE devices for 9600 bps.
 Serial.begin(9600);

}

void loop(){
     
     

     Serial.write(test);
  


   

}

and this code for receiver

String sensorvalue;

void setup()
{

 Serial.begin(9600);

}

void loop()
{
   
 if(Serial.available() > 0)
{
 while(Serial.available() > 0)
 {
     sensorvalue += char( Serial.read());
   delay(5);
     }
     
     Serial.println(sensorvalue);
    
 sensorvalue ="";
   
     
   
}
}

but when i open the serial monitor i didn't see the sent data why this happened

when i use the receiver code with Arduino UNO without using XBee just one Arduino connected to

PC and then open serial monitor then write "Hello World" i receive it in one world not h e l l o ...etc

so why when i connect two Arduino via XBee and send the same world i didn't receive it as i

receive it from serial monitor in PC

that the first problem i fail to solve it how about sending all sensor read in the same time

please some help some advice about this

this problem made me frustrated because I haven't found any solution to it

my regards

Maybe String is the same as char array but you can use

char dataPacket[64];

for (int i = 0; i < 64; i++)
{
  dataPacket[i] = Serial.read();
}

on the receiving end and sprintf on the transmitting end for example:

sprintf(dataPacket, "X%dX%dX%dX%dX%dX%dX%dX%dX%dX%dX%dX%dX%dX%d", motorSpeed, motorTemp, controllerTemp, motorCurrent, batteryVoltage, gx, gy, gz, ax, ay, az, mx, my, mz);

Serial.println(dataPacket);

Where X is the divider. Could be nice to have individual dividers for each sensor value depending on the rest of your code.

thanks martin for reply i;ll try this and tell you the results :)

i could compile the receiver code as you with edit

void setup(){
	// Start up our serial port, we configured our XBEE devices for 9600 bps.
	Serial.begin(9600);
	
}

void loop()
{
   
	if(Serial.available() > 0)
{
 	 while(Serial.available() > 0)
 {
    	char dataPacket[64];

for (int i = 0; i < 64; i++)
{
  dataPacket[i] = Serial.read();
}
    	
    	

   	 
    	
   
}
}

}

but what about the transmitter code i dont know how to edit it and compile it with no error
what is sprintf its the first time i hear about it

char dataPacket;

int gx;

void setup(){
	// Start up our serial port, we configured our XBEE devices for 9600 bps.
	Serial.begin(9600);
	
}

void loop(){
    	 
    	

    	sprintf(dataPacket, "X%dX%dX%dX%dX%dX%dX%dX%dX%dX%dX%dX%dX%dX%d" ,gx);

Serial.println(dataPacket);
  
	
}

i with is will be the solution to my problem to send all the sensor value by xbee
(i don’t want to feel like someone spend more that 480 $ without make what he want :grin: )

To simplify, sprintf concatenates a "string" from different datatypes.

For an integer variable use %d in the sprintf second parameter.

In your example:

char dataPacket[64];

int gx = 123;

void setup(){
 // Start up our serial port, we configured our XBEE devices for 9600 bps.
 Serial.begin(9600);

}

void loop(){
     
     

     sprintf(dataPacket, "X%d" ,gx);

Serial.println(dataPacket);
  

}

would transmit "X123" through the serial port. But remember that you have to send 64 bytes of data if you want to use the code on the receiver unaltered.

Google "arduino sprintf" for more info.

thanks martin the code is work also i make some edit to test it if i can send more than one string but I have a small problem

first this is my edited transmitter code

char dataPacket[64];

int gx = 125;
int gy = 321;
int gz = 456;
int ax = 654;
int ay = 789;
int az = 987; 
int mx = 147; 
int my = 258; 
int mz = 369;

void setup(){
 // Start up our serial port, we configured our XBEE devices for 9600 bps.
 Serial.begin(9600);

}

void loop(){
     
     



    // sprintf(dataPacket, "X%d" ,gx);
     sprintf(dataPacket, "X%dX%dX%dX%dX%dX%dX%dX%dX%dX%d", gx, gy, gz, ax, ay, az, mx, my, mz);
Serial.println(dataPacket);
  

}

so if i want to send 9 sensor value i get this results

why at the end there is 5888

and if i edit the code like this

i'll get different results

why after edit the code i got different number i didn't define it in the code (256 from where they come)

can you explain me that and how to fix it

and one more question in the receiver Arduino how to split the values from together in order to put every value in its right memory variable

like 123 = DHR22

321 = gas sensor

other is ...etc

It looks like you have one to many "X%d"s. I count to ten.

As for sorting an array, there are many ways. Using while loops and comparators for example. Try googling “sort array arduino” or something similar. It’s a good knowledge to have if you want to use all your stuff.

i search in the internet but i didn't find anything clear

i'll try to write splitting array code to extract the sensor read from the array and post the code hope you help me by optimize it and improve it

 	 while(Serial.available() > 0)
 {
    	char dataPacket[64];

for (int i = 0; i < 64; i++)
{
  dataPacket[i] = Serial.read();
}

If there is one byte available, read all 64 of them. How’s that working for you? Never mind, I already know.

im starting to split the array in receiving station

i use this code to send sensor read and control value as example

char dataPacket[64];

int gx = 123;
int gy = 321;
int gz = 456;
int ax = 654;
int ay = 789;
int az = 987; 
int mx = 147; 
int my = 258; 
int mz = 369;

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

void loop(){
     
     



   // sprintf(dataPacket, "X%d" ,gx);
      sprintf(dataPacket, "A%dB%dC%dD%dE%dF%dG%dH%dI%d", gx, gy, gz, ax, ay, az, mx, my, mz);
Serial.println(dataPacket);
  
 
}

and in receiving arduino i use this code

void setup(){
	// Start up our serial port, we configured our XBEE devices for 9600 bps.
	Serial.begin(9600);
	
}

void loop()
{
   
	if(Serial.available() > 0)
{
 	 while(Serial.available() > 0)
 {
    	char dataPacket[64];

for (int i = 0; i < 64; i++)
{
  dataPacket[i] = Serial.read();
 
  
}

 // Serial.println(dataPacket[0]);
String show = Serial.readStringUntil('C') ;
Serial.println(show);

delay(1000);
    	

   	 
    	

}
}

}

but i got this results

why the number F987G147H258I369 show in serial monitor and some time show to me 321

i try to fix this by make sum delay up to

delay(500);

but i got this results

why the number change and show to me 96 and sometime show to me 58I369


i use delay to see the results slowly not more so why i got un expected number in serial monitor

also readStringUntil() does not help me to split my array as i want
because if i write readStringUntil(‘c’)
this will give me all the value before c
and the same for other divider
i want to split the value between the divider

A123B456C789D000

temp=123
humb=456
speed=789
light=000

readStringUntil() will not give me this

spend all day work on this code …

i want to see what is the first value that store in the first element of array

i send from transmitter this stream

A123B321C456D654E789F987G147H258I369

i think i should receive it sequential

so the first element should contain A1

(every element store 1 byte )

so if i want to make some code in receiver arduino to show is my kit work correct

Serial.println(dataPacket[0])

to print the first element

i got this results

6
6
6
6
6
6
6
6
6
6
6
…etc

and then

4
4
4
4
4
4
4
4
…etc

and then

4ýH
H
H
H
H
H
H
H
H
H
H
H

…etc

and then the serial monitor contain show to me between 6 and 4

why that happen this mean i don’t receive the data sequential and storage in in array

this is the code what i use in receiver arduino

void setup(){
	// Start up our serial port, we configured our XBEE devices for 9600 bps.
	Serial.begin(9600);	
}

void loop()
{
   
	if(Serial.available() > 0)
{
 	 while(Serial.available() > 0)
 {
    	char dataPacket[64];

for (int i = 0; i < 64; i++)
{
  dataPacket[i] = Serial.read();
 Serial.println(dataPacket[0]);
 
}
 // Serial.println(dataPacket[0]);
String show = Serial.readStringUntil('C') ;
//delay(500);
    
}
}
}

You are STILL trying to read all 64 bytes as soon as the first one arrives. Can’t you see that that is WRONG?

You should have the sender send some kind of start of packet marker. You should have the sender send some kind of end of packet marker. I would make it send something like:

      sprintf(dataPacket,
                "<%d,%d,%d,%d,%d,%d,%d,%d,%d>",
                gx, gy, gz, ax, ay, az, mx, my, mz);
      Serial.println(dataPacket);

Then, on the receiving end, use some code like this:

#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”, use strtok() and atoi() to get the tokens, separated by commas, and convert them to ints, storing the values in an array.

thanks for that Pauls

i have two question

why u use (57600) instead of 9600

and when you write inData[index] = ‘\0’;

what is ‘\0’ mean and what is the purpose of it

i edit the code as you told me

the transmitter code is

char dataPacket[64];

int gx = 123;
int gy = 321;
int gz = 456;
int ax = 654;
int ay = 789;
int az = 987; 
int mx = 147; 
int my = 258; 
int mz = 369;

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

void loop(){
     
     



   //sprintf(dataPacket, "X%d" ,gx);
    sprintf(dataPacket,"<%d,%d,%d,%d,%d,%d,%d,%d,%d>",gx, gy, gz, ax, ay, az, mx, my, mz);
      Serial.println(dataPacket);
 
}

and the receiver code is

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

bool started = false;
bool ended = false;

char inData[64];
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 < 63)
      {
        inData[index] = inChar;
        index++;
        inData[index] = '\0';
      }
    }
  }
  Serial.println(inData);

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

i only change in receiver code the baud rate from 57600 to 9600
and the array size from 80 to 64 and i got this results form serial monitor

but i didn’t stop because of this after that i try to learn how to split the array as you told me to use strtok()

i google it but didn’t find clear lesson about it

i cand use these example and i can’t got what i want from it

because i don’t want copy paste the code i want to understand how it work :disappointed_relieved:

http://forum.arduino.cc/index.php/topic,41389.0.html

the best code i found it about this function is

its clear and split more than one value but is complex code look to me because the code contain functions and … i need to read more and more about c++ to understand this code

so i visit my favorite site again :grin:

www.cplusplus.com

i try to edit it and make my code from it

and this is my last editing of this code (marriage it you receiver’s code that you give it to me)

the code will be

#define SOP '<'
#define EOP '>'
#include <string.h>
#define MAX_STRING_LEN 100

//char *inputstring1 = "one,two,three,four,five,six,seven,eight,nine,ten"; //this is the string that will be split. this can be changed!
char *p, *i;

bool started = false;
bool ended = false;

char inData[64];
byte index;

char* gx ;
char* gy ;
char* gz ;
char* ax ;
char* ay ;
char* az ;
char* mx ;
char* my ;
char* mz ;

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 < 63)
      {
        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';
    
  }
gx = subStr(inData, ",", 1);
gy = subStr(inData, ",", 2);
gz = subStr(inData, ",", 3);
ax = subStr(inData, ",", 4);
ay = subStr(inData, ",", 5);
az = subStr(inData, ",", 6);
mx = subStr(inData, ",", 7);
my = subStr(inData, ",", 8);
mz = subStr(inData, ",", 9);
 delay(1000);
 Serial.println("---------------");
 Serial.println(gx);
 Serial.println(gy);
 Serial.println(gz);
 Serial.println(ax);
 Serial.println(ay);
 Serial.println(az);
 Serial.println(mx);
 Serial.println(my);
 Serial.println(mz);

}

  char* subStr (char* input_string, char *separator, int segment_number)
  {
 char *act, *sub, *ptr;
 static char copy[MAX_STRING_LEN];
 int i;
 
 strcpy(copy, input_string);
 
for (i = 1, act = copy; i <= segment_number; i++, act = NULL) {
 
 sub = strtok_r(act, separator, &ptr);
 if (sub == NULL) break;
 }
 return sub;
}

i uploaded it to receiver arduino and run xbee

i receive this results from serial monitor

and this

…offffffffffffffffffffffffffff

working with string in arduino is really hard as many people say
i spend more than 10 hours per day siting in front of my pc and working in this problem for over than 5 days

working with string in arduino is really hard as many people say

No, working with strings is not hard.

Parsing the data you are getting (or should be; I can't see your picture) is easy.

int values[9]; // Array to hold the values
byte index = 0; // index into array

char *token = strtok(inData, ","); // Get the first token
while(token)
{
   values[index] = atoi(token); // convert the token to an int and store it in the array
   index++; // Increment the index

   token = strtok(NULL, ","); // Keep parsing the same string
}

When the while loop ends, index tells you how many tokens were extracted from the string - should be 9 in your case. If it is, the 9 values are in the array called values.

Looks like the code is working as you coded it. What you do not realize is the bee is dropping characters and that explains why the output looks unusual.

thanks pauls it write your code and tell you the results

George thanks for advise that you suggest to me to fix that

i use edit the code to be like 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

    // Reset for the next packet
    started = false;
    ended = false;
    index = 0;
    inData[index] = '\0';
  }
  int values[9]; // Array to hold the values
byte index = 0; // index into array

char *token = strtok(inData, ","); // Get the first token
while(token)
{
   values[index] = atoi(token); // convert the token to an int and store it in the array
   index++; // Increment the index

   token = strtok(NULL, ","); // Keep parsing the same string
}
Serial.println("---------");
Serial.println(values[0]);
Serial.println(values[1]);
Serial.println(values[2]);
Serial.println(values[3]);
Serial.println(values[4]);
Serial.println(values[5]);
Serial.println(values[6]);
Serial.println(values[7]);
Serial.println(values[8]);
delay(1000);
}

and the results from receiver arduino is

some time the results changes to this

:’( :’( :’( :’( :’( :’( :’( :’( :’( :’(

when i test the first arduino without xbee to see the results in serial monitor
this is what i see

When you declare local “int values[9];” it simply assigns 9 bytes or RAM for the array. The array can and will contain anything.

So “while(token)” fills the array of received tokens, and the balance of missing tokens (values) are garbage. That is what in fact what you see.

I suggest a global array “int values[9]” , which will also contain garbage when declared, but it will retain values for each run.

Also it may be best to null the inData array before each receive to avoid the garbage using your current parsing protocol.

One final point… it seems more work to receive the entire inData string and parse it for tokens that may also be missing. Less error prone to send and receive one token at a time with identifier and convert that single value to integer. In that way you can send only values that have changed and not the entire set.

“<0,123>” would be values[0]
“<5,987>” would be values[5]

You should also test that the identifier is within a valid range!

You were supposed to paste that code into the if(started && ended) block, where it says "Process the data", NOT at the end of the code.