How to send numbers from one Arduino to another using Serial

This question must come up every day, so here goes ...

To send a number (greater than 0 to 9) from one Arduino to another reliably you need to do a couple of things.

  • Send some sort of "start number" delimiter (in this example, the "<" character).
  • "Print" the number, which turns it into a string of ASCII characters.
  • Send some sort of "end number" delimiter (in this example, the ">" character).

Example sketch, sending 10 random numbers out the serial port:

// Example of sending numbers by Serial
// Author: Nick Gammon
// Date: 31 March 2012

const char startOfNumberDelimiter = '<';
const char endOfNumberDelimiter   = '>';

void setup ()
  { 
  srand (42);
  Serial.begin (115200);
  } // end of setup
  
void loop ()
  {
  Serial.println ("Starting ...");
  for (int i = 0; i < 10; i++)
    {
    Serial.print (startOfNumberDelimiter);    
    Serial.print (rand ());    // send the number
    Serial.print (endOfNumberDelimiter);  
    Serial.println ();
    }  // end of for

  delay (5000);
  }  // end of loop

Output:

Starting ...
<17766>
<11151>
<23481>
<32503>
<7018>
<25817>
<28529>
<9160>
<16666>
<13513>

To receive the numbers we need to detect in our main loop whether or not anything has arrived in the serial port. If so, we can check for the special "start" and "end" characters. These tell us whether to start a new number, and when it has finished arriving.

// Example of receiving numbers by Serial
// Author: Nick Gammon
// Date: 31 March 2012

const char startOfNumberDelimiter = '<';
const char endOfNumberDelimiter   = '>';

void setup ()
  { 
  Serial.begin (115200);
  Serial.println ("Starting ...");
  } // end of setup
  
void processNumber (const long n)
  {
  Serial.println (n);
  }  // end of processNumber
  
void processInput ()
  {
  static long receivedNumber = 0;
  static boolean negative = false;
  
  byte c = Serial.read ();
  
  switch (c)
    {
      
    case endOfNumberDelimiter:  
      if (negative) 
        processNumber (- receivedNumber); 
      else
        processNumber (receivedNumber); 

    // fall through to start a new number
    case startOfNumberDelimiter: 
      receivedNumber = 0; 
      negative = false;
      break;
      
    case '0' ... '9': 
      receivedNumber *= 10;
      receivedNumber += c - '0';
      break;
      
    case '-':
      negative = true;
      break;
      
    } // end of switch  
  }  // end of processInput
  
void loop ()
  {
  
  if (Serial.available ())
    processInput ();
    
  // do other stuff here
  } // end of loop

Output:

Starting ...
17766
11151
23481
32503
7018
25817
28529
9160
16666
13513

You will note that the receiving sketch does not have any delay calls in it. It runs at full speed, detecting incoming numbers as fast as it can. When a complete number has arrived it is processed (in processNumber).

You can choose different delimiters, just make sure that the sending and the receiving end use the same ones. The receiving sketch is designed so that you can omit the starting delimiter between numbers, as an ending delimiter is assumed to start a new number.


More tips about handling serial communications here:

There are other ways of doing it (eg. by sending raw data) but this is probably the easiest to understand, and has the advantage that the start/end number delimiters keep the sending and receiving end in sync.

thanks! this algorithm was very useful!

Is there a way to save each number in a different variable on the receiver-Arduino ?
I'm trying to do that but just can't get it done.

thanks in advance!

Sure. Maybe post what you have? (Your code).

Lets see, i have two arduinos connected through xbee, from one i have a sensor RHT03 and a dust sensor sharp. The thing is i must send the data using serial like this:

#include <DHT22.h>
#include <stdio.h>
#include <LiquidCrystal.h>   

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);


int dustValenvio = 0;
int dustPin=3;
int dustVal=0;
 
int ledPower=2;
int delayTime=280;
int delayTime2=40;
float offTime=9680;


// Cable de datos conectado en pin 4 de Arduino

#define DHT22_PIN 4

// Inicio de Setup DHT22
DHT22 myDHT22(DHT22_PIN);

const char inicionumero = '<';
const char finnumero = '>';


float enviodatosT = 0;
float enviodatosH = 0;


void setup(void)
{
  Serial.begin(9600);
  lcd.begin(16, 2);
  pinMode(ledPower,OUTPUT);

}

void loop(void)
{ 
  
 LCD();
 
  valorsensor();
  DHT22_ERROR_t errorCode;
  
  // El sensor solo puede leer cada 2 segundos y requiere un tiempo de inico de 2 segundos al menos.
  delay(3000);
  
  errorCode = myDHT22.readData();
  switch(errorCode)
  {
    case DHT_ERROR_NONE:
      
      
      enviodatosT = myDHT22.getTemperatureC()/1.0;
      enviodatosH = myDHT22.getHumidity()/1.0;
      
      
      break;
    case DHT_BUS_HUNG:
      Serial.println("BUS Hung ");
      break;
    case DHT_ERROR_NOT_PRESENT:
      Serial.println("Not Present ");
      break;
    case DHT_ERROR_ACK_TOO_LONG:
      Serial.println("ACK time out ");
      break;
    case DHT_ERROR_SYNC_TIMEOUT:
      Serial.println("Sync Timeout ");
      break;
    case DHT_ERROR_DATA_TIMEOUT:
      Serial.println("Data Timeout ");
      break;
    case DHT_ERROR_TOOQUICK:
      break;
  }
   Serial.print(inicionumero);
   Serial.print(enviodatosT);   
   Serial.print(finnumero);
   Serial.println();
   Serial.print(inicionumero);
   Serial.print(enviodatosH);   
   Serial.print(finnumero);
   Serial.println();
   Serial.print(inicionumero);
   Serial.print(dustValenvio);   
   Serial.print(finnumero);
   Serial.println();


}

void LCD()
{
  lcd.setCursor(0, 0);
  lcd.print("T/H ");
  lcd.print(enviodatosT);
  lcd.print(" ");
  lcd.print(enviodatosH);
  lcd.setCursor(0, 1);
  lcd.print(dustVal);
  lcd.print("              ");
  
}

void valorsensor()
{
      digitalWrite(ledPower,LOW); // power on the LED
      delayMicroseconds(delayTime);
      dustVal=analogRead(dustPin); // read the dust value via pin 5 on the sensor
      delayMicroseconds(delayTime2);
      digitalWrite(ledPower,HIGH); // turn the LED off
      delayMicroseconds(offTime);
      dustValenvio=dustVal*100;
}

And the receiver Arduino has this code (using your algorithm):

const char inicionumero = '<';
const char finnumero = '>';


void setup ()
  { 
  Serial.begin (9600);
  } 
  
void processNumber (const long n)
  {
  float x = n/100.0;  
  Serial.println (x);
  }  
  
void processInput ()
  {
  static float receivedNumber = 0;
  static boolean negative = false;
  
  byte c = Serial.read ();
  
  switch (c)
    {
      
    case finnumero:  
      if (negative) 
        processNumber (- receivedNumber); 
      else
        processNumber (receivedNumber); 

    // fall through to start a new number
    case inicionumero: 
      receivedNumber = 0; 
      negative = false;
      break;
      
    case '0' ... '9': 
      receivedNumber *= 10;
      receivedNumber += c - '0';
      break;
      
    case '-':
      negative = true;
      break;
      
    } 
  }  
  
void loop ()
  {
  if (Serial.available ())
    processInput ();
  }

So my problem is, when i receive the three numbers in the monitor serial (temperature, humidity and dust) your algorithm prints the three numbers fine, but i would like to separate one variable for each type of data, i mean temperature, humidity and dust as well, all of that because the code later on storage the data on a microSD card...

sorry for my bad english, im a Chilean engineering student.

Well, keep track of which is which.

eg.

const char inicionumero = '<';
const char finnumero = '>';

enum { getTemperature, getHumidity, getDust };

int whichNumber = getTemperature;

float  temperature, humidity, dust;

void setup ()
  { 
  Serial.begin (9600);
  } 
  
void processNumber (const long n)
  {
  float x = n/100.0;  
  
  switch (whichNumber)
    {
    case getTemperature: 
      temperature = x;
      whichNumber = getHumidity;
      Serial.print ("Temperature = ");
      break;
      
    case getHumidity: 
      humidity = x;
      whichNumber = getDust;
      Serial.print ("Humidity = ");
      break;

    case getDust: 
      dust = x;
      whichNumber = getTemperature;
      Serial.print ("Dust = ");
      break;
    }
    
  Serial.println (x);
  }  
  
void processInput ()
  {
  static float receivedNumber = 0;
  static boolean negative = false;
  
  byte c = Serial.read ();
  
  switch (c)
    {
      
    case finnumero:  
      if (negative) 
        processNumber (- receivedNumber); 
      else
        processNumber (receivedNumber); 

    // fall through to start a new number
    case inicionumero: 
      receivedNumber = 0; 
      negative = false;
      break;
      
    case '0' ... '9': 
      receivedNumber *= 10;
      receivedNumber += c - '0';
      break;
      
    case '-':
      negative = true;
      break;
      
    } 
  }  
  
void loop ()
  {
  if (Serial.available ())
    processInput ();
  }

That's one way you could do it.

well, again Mr. Nick, thanks! works like a charm! now i can continue with my project, i was stucked for several days figuring a way how to do this.
I'm very grateful

thanks again

Sincerely

Ignacio.

I don't know what I (or anyone else) is supposed to answer without seeing any code.

The code for sending the numbers is

#include <DHT22.h>
#include <stdio.h>
#include <LiquidCrystal.h>   

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);


int dustValenvio = 0;
int dustPin=0;
int dustVal=0;
 
int ledPower=2;
int delayTime=280;
int delayTime2=40;
float offTime=9680;


// Cable de datos conectado en pin 4 de Arduino

#define DHT22_PIN 4

// Inicio de Setup DHT22
DHT22 myDHT22(DHT22_PIN);

const char inicionumero = '<';
const char finnumero = '>';


float enviodatosT = 0;
float enviodatosH = 0;


void setup(void)
{
  Serial.begin(9600);
  lcd.begin(16, 2);
  pinMode(ledPower,OUTPUT);
 
}

void loop(void)
{ 

 
  valorsensor();
  DHT22_ERROR_t errorCode;
  
  
  
  
  errorCode = myDHT22.readData();
  switch(errorCode)
  {
    case DHT_ERROR_NONE:
      
      
      enviodatosT = myDHT22.getTemperatureC()/1.0;
      enviodatosH = myDHT22.getHumidity()/1.0;
      
      
      break;
    case DHT_BUS_HUNG:
      Serial.println("BUS Hung ");
      break;
    case DHT_ERROR_NOT_PRESENT:
      Serial.println("Not Present ");
      break;
    case DHT_ERROR_ACK_TOO_LONG:
      Serial.println("ACK time out ");
      break;
    case DHT_ERROR_SYNC_TIMEOUT:
      Serial.println("Sync Timeout ");
      break;
    case DHT_ERROR_DATA_TIMEOUT:
      Serial.println("Data Timeout ");
      break;
    case DHT_ERROR_TOOQUICK:
      break;
  }
  if(enviodatosT>0)
  {
   LCD();
   Serial.print(inicionumero);
   Serial.print(enviodatosT);   
   Serial.print(finnumero);
   Serial.println();
   Serial.print(inicionumero);
   Serial.print(enviodatosH);   
   Serial.print(finnumero);
   Serial.println();
   Serial.print(inicionumero);
   Serial.print(dustValenvio);   
   Serial.print(finnumero);
   Serial.println();
  }
   delay(2000);
  
}

void LCD()
{
  if(enviodatosT>0)
  {
  lcd.setCursor(0, 0);
  lcd.print("T/H ");
  lcd.print(enviodatosT);
  lcd.print(" ");
  lcd.print(enviodatosH);
  lcd.setCursor(0, 1);
  lcd.print(dustVal);
  lcd.print("              ");
  }
}

void valorsensor()
{
      digitalWrite(ledPower,LOW); // power on the LED
      delayMicroseconds(delayTime);
      dustVal=analogRead(dustPin); // read the dust value via pin 5 on the sensor
      delayMicroseconds(delayTime2);
      digitalWrite(ledPower,HIGH); // turn the LED off
      delayMicroseconds(offTime);
      dustValenvio=dustVal;
}

The sending number code works very well, but when i receive the numbers it's strange because it keeps showing the same old numbers all over.

this is the code for the receiver:

#include <SD.h>
#include <Wire.h>
#include "Rtc.h"
#include <DHT22.h>
#include <stdio.h>

enum { getTemperature, getHumedad, getDust };

int whichNumber = getTemperature;
float  temperature, humidity, dust;
const char inicionumero = '<';
const char finnumero = '>';
char temperatura[10];
char humedad[10];
char polvo[10];
char temperatura2[10];
char humedad2[10];
char polvo2[10];

float dustValenvio = 0.0;
float a = 0.0;
int dustPin=0;
float dustVal=0.0;
 
int ledPower=2;
int delayTime=280;
int delayTime2=40;
float offTime=9680;


// Cable de datos conectado en pin 4 de Arduino

#define DHT22_PIN 4

// Inicio de Setup DHT22
DHT22 myDHT22(DHT22_PIN);



float enviodatosT = 0;
float enviodatosH = 0;

const int chipSelect = 8;

char time[20];
char date[20];

Rtc rtc;

void setup()
{ 
  Serial.begin(9600);
  pinMode(ledPower,OUTPUT);
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
//    Serial.println("FAILED");
    // don't do anything more:
    return;
  }
  Rtc rtc = Rtc(0,0,0,1,1,1,11,0xAA);
 }

void processNumber (const long n)
  {
  float x = n/100.0;  
  
  switch (whichNumber)
    {
    case getTemperature: 
      temperature = x;
      
      whichNumber = getHumedad;
      break;
      
    case getHumedad: 
      humidity = x;
     
      whichNumber = getDust;
      break;

    case getDust: 
      dust = x;
      
      whichNumber = getTemperature;
      break;
    }
    dtostrf(temperature,1,2,temperatura2);
    dtostrf(humidity,1,2,humedad2);
    dtostrf(dust,1,2,polvo2);
    }  
  
void processInput ()
  {
  static float receivedNumber = 0;
  static boolean negative = false;
  
  byte c = Serial.read ();
  
  switch (c)
    {
      
    case finnumero:  
      if (negative) 
        processNumber (- receivedNumber); 
      else
        processNumber (receivedNumber); 

    // fall through to start a new number
    case inicionumero: 
      receivedNumber = 0; 
      negative = false;
      break;
      
    case '0' ... '9': 
      receivedNumber *= 10;
      receivedNumber += c - '0';
      break;
      
    case '-':
      negative = true;
      break;
      
    } 
  }  

  void loop()
{
  if(Serial.available())
  {
  processInput();
  }
  valorsensor();
  DHT22_ERROR_t errorCode;
  
  // El sensor solo puede leer cada 2 segundos y requiere un tiempo de inico de 2 segundos al menos.
  
  
  errorCode = myDHT22.readData();
  switch(errorCode)
  {
    case DHT_ERROR_NONE:
      
 
      enviodatosT = myDHT22.getTemperatureC()/1.0;
      dtostrf(enviodatosT,1,2,temperatura);
      enviodatosH = myDHT22.getHumidity()/1.0;
      dtostrf(enviodatosH,1,2,humedad);
      break;
    
  }
  
  loggerMode();
  
 
}

void loggerMode(){
  // make a string for assembling the data to log:
  String dataString = "";

  
for (int i=0;i<20;i++){

  switch (i) {
    case 1:    
dataString += String(temperatura);
dataString += ";"; 
      break;
    
    case 2:    
dataString += String(temperatura2);
dataString += ";"; 
      break;    
      
    case 3:  
dataString += String(humedad);
dataString += ";"; 
      break;

    case 4:    
dataString += String(humedad2);
dataString += ";"; 
      break;

    case 5:
dataString += String(polvo);
dataString += ";"; 
      break;
    
     case 6:
dataString += String(polvo2);
      break;
}
}
 
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.csv", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    // get Time and Date
    rtc.GetDate();
    rtc.Time(time);
    rtc.Date(date);
    // add them to dataString
    dataString += ";";
    dataString += String(date);
    dataString += ";";    
    dataString += String(time);
    // write file
    if(enviodatosT>0 && temperature>0 && humidity>0 && dust>0)
    {
    dataFile.println(dataString);

    dataFile.close();
   // print to the serial port too:
    }
    if(enviodatosT>0 && temperature>0 && humidity>0 && dust>0)
    {
   Serial.println(dataString);
    }
 }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.csv");
  } 
}

void valorsensor()
{
      digitalWrite(ledPower,LOW); // power on the LED
      delayMicroseconds(delayTime);
      dustVal=analogRead(dustPin); // read the dust value via pin 5 on the sensor
      delayMicroseconds(delayTime2);
      digitalWrite(ledPower,HIGH); // turn the LED off
      delayMicroseconds(offTime);
      if(dustVal<125)
      {
       dustValenvio = 0.0;
      }
     else { 
      a=(dustVal*5)/1023;
      dustValenvio=(a-0.611)/5.1720;
     }
     dtostrf(dustValenvio,1,2,polvo);
}

So, the receiver code works like this...it stores data to a microSD card in order. I have one module with a temperature/humidity sensor and a dust sensor, the other module (receiver one has them too), so in the datastring the data stores like this:

tempvalue1;tempvalue2;humidity1;humidity2;dust1;dust2;date;time

tempvalue1 = temperature from sensor in receiver module
tempvalue2 = temperature from sensor in sender module
humidity1 = humidity from sensor in receiver module
humidity2= humidity from sensor in sender module
dust1 = dust from sensor in receiver module
dust2 = dust from sensor in sender module

An image speak for itself...in the image you can see that the sender values don't update with time.

Sorry for my bad english, hoping you can help me,
regards.

Aren't you writing thousands of not hundreds of thousands of times a second? Where are you slowing it down to write every few seconds?

The temperature won't change in a millisecond will it? Also:

Please note that, at present, the String library has bugs as discussed here and here.

In particular, the dynamic memory allocation used by the String class may fail and cause random crashes.

I recommend reworking your code to manage without String. Use C-style strings instead (strcpy, strcat, strcmp, etc.).

Yeah, about the slowing time i've already try changing it, from 30 seconds to even 1 or 2, but still the same, i was just trying to see what happen, but ill take a look at those links you wrote and see what can i do, i didn't knew strings could fail.

thanks mr Nick,

regards

Ignacio.

I managed to rebuild the writing code with strcpy and strcat, it works very well but im having the same problem, now i know something else, the switch for the received numbers is functioning way too slow, first it prints the temperature value and then the program keeps running and storing, after 45 sec aprox the switch shows the value of humidity and so...

the code for this:

#include <SD.h>
#include <Wire.h>
#include "Rtc.h"
#include <DHT22.h>
#include <stdio.h>
#include <string.h>

char temperatura[10];
char humedad[10];
char polvo[10];
char temperatura2[10];
char humedad2[10];
char polvo2[10];
const char inicionumero = '<';
const char finnumero = '>';

enum { getTemperature, getHumedad, getDust };

int whichNumber = getTemperature;

float  temperature, humidity, dust;

float dustValenvio = 0.0;
float a = 0.0;
int dustPin=0;
float dustVal=0.0;
 
int ledPower=2;
int delayTime=280;
int delayTime2=40;
float offTime=9680;


// Cable de datos conectado en pin 4 de Arduino

#define DHT22_PIN 4

// Inicio de Setup DHT22
DHT22 myDHT22(DHT22_PIN);



float enviodatosT = 0;
float enviodatosH = 0;

const int chipSelect = 8;

char time[20];
char date[20];

Rtc rtc;

void setup()
{ 
  Serial.begin(9600);
  pinMode(ledPower,OUTPUT);
  pinMode(10, OUTPUT);
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
//    Serial.println("FAILED");
    // don't do anything more:
    return;
  }
  Rtc rtc = Rtc(0,0,0,1,1,1,11,0xAA);
 }

void processNumber (const long n)
  {
  float x = n/100.0;  
  
  switch (whichNumber)
    {
    case getTemperature: 
      temperature = x;
      whichNumber = getHumedad;
      Serial.print ("Temperature = ");
      break;
      
    case getHumedad: 
      humidity = x;
      whichNumber = getDust;
      Serial.print ("Humidity = ");
      break;

    case getDust: 
      dust = x;
      whichNumber = getTemperature;
      Serial.print ("Dust = ");
      break;
    }
    
  Serial.println (x);
  }  
  
void processInput ()
  {
  static float receivedNumber = 0;
  static boolean negative = false;
  
  byte c = Serial.read ();
  
  switch (c)
    {
      
    case finnumero:  
      if (negative) 
        processNumber (- receivedNumber); 
      else
        processNumber (receivedNumber); 

    // fall through to start a new number
    case inicionumero: 
      receivedNumber = 0; 
      negative = false;
      break;
      
    case '0' ... '9': 
      receivedNumber *= 10;
      receivedNumber += c - '0';
      break;
      
    case '-':
      negative = true;
      break;
      
    } 
  }  
  
  void loop()
{
  if (Serial.available ())
  {
    processInput ();
  }
  valorsensor();
  DHT22_ERROR_t errorCode;
  
  // El sensor solo puede leer cada 2 segundos y requiere un tiempo de inico de 2 segundos al menos.
  
  
  errorCode = myDHT22.readData();
  switch(errorCode)
  {
    case DHT_ERROR_NONE:
      
 
      enviodatosT = myDHT22.getTemperatureC()/1.0;
      enviodatosH = myDHT22.getHumidity()/1.0;
      break;
    
  }
  
  loggerMode();
  delay(5000);
 
}

void loggerMode(){
   char datos[100];
    rtc.GetDate();
    rtc.Time(time);
    rtc.Date(date);
    dtostrf(enviodatosT,1,2,temperatura);
    dtostrf(enviodatosH,1,2,humedad);
    dtostrf(dustValenvio,1,2,polvo);
    dtostrf(temperature,1,2,temperatura2);
    dtostrf(humidity,1,2,humedad2);
    dtostrf(dust,1,2,polvo2);
    strcpy (datos, temperatura);
    strcat (datos, ";");
    strcat (datos, temperatura2);
    strcat (datos, ";");
    strcat (datos, humedad);
    strcat (datos, ";");
    strcat (datos, humedad2);
    strcat (datos, ";");
    strcat (datos, polvo);
    strcat (datos, ";");
    strcat (datos, polvo2);
    strcat (datos, ";");
    strcat (datos, date);
    strcat (datos, ";");
    strcat (datos, time);
 
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.csv", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
   
    // write file
    if(enviodatosT>0 && temperature > 0)
    {
    dataFile.println(datos);

    dataFile.close();
   // print to the serial port too:
    }
    if(enviodatosT>0 &&  temperature > 0)
    {
   Serial.println(datos);
    }
 }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.csv");
  } 
}

void valorsensor()
{
      digitalWrite(ledPower,LOW); // power on the LED
      delayMicroseconds(delayTime);
      dustVal=analogRead(dustPin); // read the dust value via pin 5 on the sensor
      delayMicroseconds(delayTime2);
      digitalWrite(ledPower,HIGH); // turn the LED off
      delayMicroseconds(offTime);
      if(dustVal<125)
      {
       dustValenvio = 0.0;
      }
     else { 
      a=(dustVal*5)/1023;
      dustValenvio=(a-0.611)/5.1720;
     }
    }

An image of how is it working...
Is there a way to fix this?

You haven't really answered my question about how fast you write the data. Where in the code do you throttle it down so you store figures a second or so apart?

The data writes when i call the function "loggermode" with a delay of 5 seconds just below it

...

loggermode();
delay(5000);
...

In the image above is stated that the measurings/storing data it's done every 5 seconds.
Is this done it right?

void loop()
{
  if (Serial.available ())
  {
    processInput ();
  }
 
...

  loggerMode();
  delay(5000);

}

Serial data tends to come in one byte at a time. After each byte you have a 5 second delay. And you are asking why it is slow?

In other words, set a flag or something when all the figures have arrived (at a newline or something). Then do the logging, and the delay, once, and clear that flag for next time.

I managed to get it working, the thing was the switch code for the received numbers as you said it...i rewrote the code and put everything in the last case, that worked.

like this:

#include <SD.h>
#include <Wire.h>
#include "Rtc.h"
#include <DHT22.h>



const char inicionumero = '<';
const char finnumero = '>';
char temperatura[10];
char humedad[10];
char polvo[10];
char temperatura2[10];
char humedad2[10];
char polvo2[10];
char datos[100];

float dustValenvio = 0.0;
float a = 0.0;
int dustPin=0;
float dustVal=0.0;
 
int ledPower=2;
int delayTime=280;
int delayTime2=40;
float offTime=9680;


enum { getTemperature, getHumedad, getDust };

int whichNumber = getTemperature;

float  temperature, humidity, dust;

#define DHT22_PIN 4

// Inicio de Setup DHT22
DHT22 myDHT22(DHT22_PIN);



float enviodatosT = 0;
float enviodatosH = 0;

const int chipSelect = 8;

char time[20];
char date[20];

Rtc rtc;


void setup ()
  { 
  Serial.begin (9600);
    pinMode(ledPower, OUTPUT);
    pinMode(10, OUTPUT);
    
    
     if (!SD.begin(chipSelect)) {
       return;
     }
  Rtc rtc = Rtc(0,0,0,1,1,1,11,0xAA);
  } 
  

void processNumber (const long n)
  {
  DHT22_ERROR_t errorCode;
  errorCode = myDHT22.readData();
  if(errorCode == DHT_ERROR_NONE)
  {
  enviodatosT = myDHT22.getTemperatureC()/1.0;
  enviodatosH = myDHT22.getHumidity()/1.0;
  }
  
  float x = n/100.0;  
  
  switch (whichNumber)
    {
    case getTemperature: 
      temperature = x;
      dtostrf(temperature,1,2,temperatura);
      strcpy(datos, temperatura);
      strcat(datos, ";");
      whichNumber = getHumedad;
      Serial.print ("Temperature = ");
      Serial.println(temperatura);
      break;
      
    case getHumedad: 
      humidity = x;
      dtostrf(humidity,1,2,humedad);
      strcat(datos, humedad);
      strcat(datos, ";");
      whichNumber = getDust;
      Serial.print ("Humidity = ");
      Serial.println(humedad);
      break;

    case getDust: 
      dust = x;
      dtostrf(dust,1,2,polvo);
      strcat(datos, polvo);
      strcat(datos, ";");
      whichNumber = getTemperature;
      Serial.print ("Dust = ");
      Serial.println(polvo);
           
                dtostrf(enviodatosT,1,2,temperatura2);
                dtostrf(enviodatosH,1,2,humedad2);
                strcat(datos, temperatura2);
                strcat(datos, ";");
                strcat(datos, humedad2);
                strcat(datos, ";");
                      digitalWrite(ledPower,LOW); // power on the LED
                      delayMicroseconds(delayTime);
                      dustVal=analogRead(dustPin); // read the dust value via pin 5 on the sensor
                      delayMicroseconds(delayTime2);
                      digitalWrite(ledPower,HIGH); // turn the LED off
                      delayMicroseconds(offTime);
                      if(dustVal<125)
                        {
                        dustValenvio = 0.0;
                        dtostrf(dustValenvio,1,2,polvo2);
                        }
                       else { 
                        a=(dustVal*5)/1023;
                        dustValenvio=(a-0.611)/5.1720;
                        dtostrf(dustValenvio,1,2,polvo2);
                           }
                  strcat(datos, polvo2);
                  strcat(datos, ";");
                  rtc.GetDate();
                  rtc.Time(time);
                  rtc.Date(date);
                  strcat(datos, date);
                  strcat(datos, ";");
                  strcat(datos, time);
     
                  File dataFile = SD.open("datalog.csv", FILE_WRITE);

                  // if the file is available, write to it:
                  if (dataFile) {
   
                  // write file
                  if(enviodatosT>0 && enviodatosH>0 && dustValenvio>0)
                    {
                      dataFile.println(datos);
                      dataFile.close();
                     }
                  }
      Serial.println(datos);
      delay(5000);
      break;
          }
          }  

void processInput ()
  {
  static float receivedNumber = 0;
  static boolean negative = false;
  
  byte c = Serial.read ();
  
  switch (c)
    {
      
    case finnumero:  
      if (negative) 
        processNumber (- receivedNumber); 
      else
        processNumber (receivedNumber); 

    // fall through to start a new number
    case inicionumero: 
      receivedNumber = 0; 
      negative = false;
      break;
      
    case '0' ... '9': 
      receivedNumber *= 10;
      receivedNumber += c - '0';
      break;
      
    case '-':
      negative = true;
      break;
      
    } 
  }  
 
void loop ()
  {
  
  if (Serial.available ())
  {
      processInput ();
        }   
              
  }

So again, thanks mr. Nick, im not so experienced in this stuff, but you always come with great ideas and patience, now my project is almost finished and that could not be achieved without your help.

greetings.

Ignacio.

Good tutorial Nick, but there is a small flaw in your example parser

if you receive <43-21> what will be the number? -4321? [case can happen when 2 chars "><" are lost due to buffer overrun whatever]

To solve this the parser need to check that the '-' sign comes directly after the '<' start char.

Good point, although for sake of clarity it didn't do a lot of error checking. By the same token it would accept "<>" as the number zero.

You could modify it to include floats, for example, and then you need to check you only get a single decimal point.

I've added a note to my page to point out the problem you raised. (I haven't changed the code, just pointed out the possibility of that problem).

OK, you 're right not to complicate the tutorial code by error handling, that is left as an exercise for the reader :wink: