arduino and XBEE Pro S2B

i have a arduino uno, xbee pro series 2 b and a voc-sensor: tgs 2602. i want to send the resistance´s value of the sensor through xbee to the serial monitor from arduino. tgs2602–> xbee - xbee–>xbee shield–>arduino uno

i configure my first xbee as a router in AT Modus with sample rate 1000ms and my coordinator in API. the sketch i used look like this

//Remote XBee:AT, Base XBee:API
float voc;
void setup(){
Serial.begin(9600);
};

void loop(){

if(Serial.available() >=21){ //Makesure the frame is all there
if (Serial.read()== 0x7E){ //7E is the start byte
for (int i = 1; i<18; i++) { //Skip ahead to the analog data
 byte discardByte = Serial.read();

}
int analogMSB = Serial.read(); // Read the first analog byte data
int analogLSB = Serial.read(); //Read the second byte
int analogReading = analogLSB + (analogMSB * 256);

float volt = analogReading/1023.0 * 5 ;    // Rechne die von ADC ausgegebenen Werten in Volt um
float Rs1 = 10*(5-volt)/volt;        //Rechne den Widerstandswert


Serial.println(Rs1);
}
}
}

The data i received in the serial monitor is 5105. This value doesn´t change even when i touch the sensor.

What Am i doing something wrong?.

The “discardByte = 0 18 146 0 125 51 162 0 64 173 23 24 85 236 1 1 0”

analogMSB = 2, analogLSB=0, they don´t vary.the sensor is connected to the 2nd analog input.

I need help

Thanks

Can you show us the 64 bit adress and 16 bit adress of the Xbee that has the sensor connected? I have trouble analyzing the API packet.

What you also did not show is how the sensor is attached electronically to the Xbee. According to the datasheet of the sensor it needs to be used together with a load resistor to make a voltage divider. What resistor did you use for this?

You are using an entirely different formula than in the datasheet:

http://www.figarosensor.com/products/2602pdf.pdf

The sensor also needs a heater current applied to 2 of the pins to make it work. Did you consider this? Is this current in the proper range? And what kind of voltage is applied to the Analog reference input of the Xbee? (Vref)

Can you exchange S2 for S1’s? Far simpler as S2’s are ZIgbee only.

Hi stevech,thanks for your answer. I try to exchange the S2 for S1, but for me it´s more difficult and i didn´t get any result.

Hi Valen, what do you mean by 64 Bit adress? Where can i read that?

For the sensor i used a 10k ohm resitor. i used this sensor without Xbee and it worked very well, but when i attached it to the xbee i have this error 5105. What do you mean by “Kind of voltage”, i´m using a xbee regulated that convert a 5 v in 3.3v for the xbee module. thank you for your answer.

Hi valen,

the 64 Bit address for the router: 0013A20040AD1718

You can find attached this circuit for tgs 2602 (A1 is attach to xbee analog input 2)

Hope you can help

florianagr:
Hi Valen, what do you mean by 64 Bit adress? Where can i read that?

As you obviously found out already: there is a sticker on the bottom of the module with the serial number found in the SH and SL register. This can be considered the unique 64bit hardware adress. The adress of the router that you stated last does not match exactly what I find in the partial API packet that you initially posted. But after further consideration, it can be explained.

You state that:

The “discardByte = 0 18 146 0 125 51 162 0 64 173 23 24 85 236 1 1 0”

These seem all decimal values, confirmed by your code.

First of all, it is risky to pick out specific bytes out of a packet that can change in length. You should really analyze each part of the packet and group the bytes received. Only afterwards can you decide which bytes you do not care about. If the 3rd byte in discardByte wasn’t 146 (or 0x92 in hexadecimal), for some unexpected reason, then your program would produce faulty output values as it picked the wrong bytes as analog measurements. (which it does anyway) In this case you seem to be lucky as it is a “ZigBee IO Data Sample Rx” packet. Another reason, and this seems to happen in this particular case, is that Escape characters may be injected in the stream, to not interfere with the dataframe sequencing. See page 55 of the Manual, 6.0.1 Api Frame Specifications.

Lets analyze this. Have you done this yourself, using the Zigbee 2.5 series 2 manual? Page 67 internal page count (68 PDF page count)

http://ftp1.digi.com/support/documentat … 0976_S.pdf

The next two bytes after the header byte 0x7E is “0 18” is the length of the packet, excluding the header byte, length and Checksum. This means the following 18 bytes contain the message. But you only show 15 of them.

Next comes the API Frame type identifier “146”. In hexadecimal this is 0x92. Which means it is infact a Zigbee IO Data Sample Receive packet.

Next comes the 64 bit hardware adress/SH SL serial number . This does not seem to match to your stated serial number, as it contains partially ‘faulty’ numbers. These 9 bytes from the discardByte stream suggest they are the SH and SL adress: "0 125 51 162 0 64 173 23 24 " As the end of them match pretty closely. The first byte seems ok also, as the most significant byte of SH is also 0. Next comes 125, or 0x7D. This happens to be the token for starting an escaped character. The next byte bitwise-eXclusiveOR-ed with 0x20 should result in the right byte of the adress. (use the Programmer function of the Windows calculator to perform this yourself) 51 decimal is 0x33. 0x33 XOR 0x20= 0x13 (which is 19 in decimal) And this byte with the remaining 6 confirms the 64 bit adress.

Next comes the 16 bit network adress, 2 bytes: 85 236. Which would be 0x55EC. I cannot say anything about it’s validity because I know nothing about this Zigbee network adressing protocol routing business. I only know about the series 1 modules. I’ll assume this is correct. (and not very important in this case, since the 64 bit hardware adress is verified)

Next should follow a byte called Receive Options. Being 1 for Packet Acknowledged, and 2 for if it was broadcast packet. Your next byte is 1, so it is acknowledged. Fine.

Next is 1 byte, number of samples. Also as expected, as it is also 1.

Then comes 2 bytes representing the Digital Channel Mask, showing which digital IO lines are sampled. This is not of any concern to you, but it is part of the frame. It is 0, so no digital line samples in the frame.

Now your code expects to read the analog values. But because of the Escaped character this is offset further away. And you decided to ignore any later bytes of the frame. So nothing can be said now about what the analog value should be. Even then, you are a few bytes too early with expecting the analog values. First comes the Analog channel mask (1 byte), and the Digital samples (2 bytes). Since there are no digital lines selected the last is probably not part of the packet. The analog sample of 2 bytes would make the 18 bytes in the frame complete. (The escape token is not part of it apparently, need to test that) And to confirm the integrity of the entire packet it should end with the checksum value. That should prove if you have all the bytes of the packet received. If not, it should be ignored.

TL/DR: Analyze the entire API packet, or use a Xbee/Zigbee API library for Arduino to do it for you. You picked the wrong bytes. And ignored the part of the frame that contains them.

For the sensor i used a 10k ohm resitor. i used this sensor without Xbee and it worked very well, but when i attached it to the xbee i have this error 5105. What do you mean by “Kind of voltage”, i´m using a xbee regulated that convert a 5 v in 3.3v for the xbee module. thank you for your answer.

The analog to digital converter inside the Xbee module doesn’t know that you applied (approximately!!) 5 volt to the sensor. In order to measure the voltage on it’s analog pin it needs to compare this to a reference voltage. Most microcontrollers have a built-in reference, but sometimes also a pin into which the designer can apply an external voltage which would resemble the value 1023 (or whatever the max resolution can be). For the XBees S2, according to the manual, this seems to be fixed to an internal reference of 1.2 volt. (Series 1 needs an external reference) So you do not need to apply a voltage to the Vref pin (14). But is important to know that the voltage to be measured needs to be lower than this. Or else all you get it 0x3FF, or 1023 as a result.

I do not know what voltage your sensor is supposed to output in it’s voltage divider configuration with the 10 K resistor. [edit: Datasheet of sensor: Rs is between 10k and 100k in air, so with 10k resistor it would be around halve of 5 volt or lower.) Did you measure it yourself with a multimeter? And did it change by blowing into it with your breath? It should respond to humidity changes.What ‘analog’ value would you have expected from the Xbee, knowing the real voltage of the sensor? Do realize that the Xbee cannot handle more than 3.6 volt on it’s pins. 5 volt from the sensor output is too much. It might break down. And definitely too high to make a useful measurement. Instead of using the voltage above the 10K load resistor, you may reduce the output voltage even more by replacing it (the load resistor) with another voltage divider resistor set (totaling 10 K). Just so the ultimate output it is less than 1.2 volt.

Hi Valen,

thanks for your explanation. It´s really helpful.

You are right when you say that the output voltage is too high. I´m trying to divide it.

For your questions:

  • yes, i measure with a multimeter myself

  • i find out that the voltage really change by blowing over the sensor, but the voltage is over 3 V and more

  • i expected a variable value from xbee between: 57 (low voltage value) - 0.2 (high voltage value)

I will try to divide the voltage and tell you the result

thanks

Hi Valen,

i divided the voltage without success. That´s why i decided to change the circuit.

I have the Arduino + Xbee shield+Xbeemodul pro series 2b as the router (in AT) and the Xbee modul pro series 2b (with xbee explorer) as the coordinator in API mode. It ´s working fine. I´m getting the data, but i have some funny character in the terminal, i don´t know what that is. see the picture below.

Do you know how i can remove it?

Thanks

florianagr:
Hi Valen,

thanks for your explanation. It´s really helpful.

You are right when you say that the output voltage is too high. I´m trying to divide it.

For your questions:

  • yes, i measure with a multimeter myself

  • i find out that the voltage really change by blowing over the sensor, but the voltage is over 3 V and more

  • i expected a variable value from xbee between: 57 (low voltage value) - 0.2 (high voltage value)

Which units are these numbers in ? It is not the number in the API packet. As the XBee analog to digital converter (ADC) only give round (integer) numbers. No fractions. And it would be interesting to know which voltages these correspond to. I mean multimeter values. Not from a formula inside your arduino! That comes later. And what was the exact voltage of the 5 volt regulator output. As it never is exactly 5.000 volt.

Anyway, you say that the voltage at the point between the load-resistor and the sensor is 3 volts, and rises. It is probably due to temperature of your breadth, and less due to humidity. Taking the formula in the datasheet the output voltage of 3 volt on a 10k resistor on a 5 volt supply means that the resistance of the sensor Rs must be around 6666 Ohm (in your ambient air condition). Rs= 5.0*10k/3.0 -10k This is just to get a rough idea on how big it is under normal conditions. It does seem strange though, as it is outside of the expected resistance range 10k-100k ohm for air.

This voltage rise can be explained as the resistance of the sensor drops with increasing temperature. When the top resistor drops in value over the fixed resistor, the output voltage rises. If the top resistor (the sensor) is a short (no resistance) then the output of the divider is extremely close to the 5 volt. It should never be higher. For example a high concentration of Toluene (30 ppm) would make the resistance of the sensor drop to 4% of nominal (no contamination of air). Nearly nothing. This would be around 266 ohm (based on your measured voltage). A 266 ohm on top of a 10kohm resistor makes a divider of 0.974, or 4.87 out of 5 volt. Not good for an Xbee input!! Neither is simple hot air of 50 degree C. Then the resistance of the sensor is about 2kohm, and the resistor divider becomes 0.833 of 5 Volt, or 4.167 Volt. Not good also! Far above the 1.2 volt range of the Xbee ADC. (Al this is in the charts in the datasheet)

I would replace the 10k resistor by a 6.8 Kohm on top of a 2.2 kOhm resistor. The 6.8 Kohm between the sensor and the 2.2Kohm resistor. The 2.2Kohm is connected to ground with it’s other lead. The analog input of the Xbee would be connected between the 2 resistors. With high gas-concentration this circuit should reduce the sensor output to just around below the 1.2 volt that the Xbee can measure. Lower gas concentration result in lower analog voltage/ADC values. But you have not said anything about which gas concentration you wish to measure. So which divider ratio is most appropriate for best sensitivity is hard to say.

Alternatively you could use a 10k potentiometer with the middle lead to the Xbee input. Then you can set the dividing ratio as needed by shorting the sensor output (to 5 volt) and adjusting the wiper voltage to under 1.2 volt. (disconnect the Xbee input for safety) It must be noted however that potentiometers do not have very stable resistances over time, and in different environment conditions. Keeping it calibrated will be a serious problem, but it is easy to experiment with sensitivity. Better use fixed resistors of at least 1% accuracy if it needs to stay calibrated.

florianagr:
Hi Valen,

i divided the voltage without success. That´s why i decided to change the circuit.

I have the Arduino + Xbee shield+Xbeemodul pro series 2b as the router (in AT) and the Xbee modul pro series 2b (with xbee explorer) as the coordinator in API mode.

And where is the sensor now? still on the router? How did you try to divide the voltage? By hardware (different resistor divider circuit) or in the formula in your sketch? I hope the first.

It ´s working fine. I´m getting the data, but i have some funny character in the terminal, i don´t know what that is. see the picture below.

Do you know how i can remove it?

Thanks

The bytes in the API packet that the Xbee sends are just numbers, between 0 and 255. And should only be interpreted in that way, unless the packet content does happen to include a character-string somewhere in it. This “IO receive sample” packet that you expect is only numbers though.

The screenshot that you posted of the terminal looks like it receives one or more API packets between the sending of the ppm and Rs calculated values. At least it is a sequence of bytes in a regular format. The terminal cannot (or maybe just does not) show these bytes as numbers. It prints them as ASCII characters on your screen, since that is most commonly used. And numbers that do not have a symbol assigned to them get printed as a dot on the screen. This is very unfortunate. As you need to see both the number-bytes and the character-bytes in that stream. Maybe that option button can provide ways to display the bytes decimal, hexadecimal, ASCII or even binary format (for pin selection bitmasks).

If this is generated by the Arduino then you must have more code in your sketch that plays a part in this. And since you haven’t shown that it is difficult to tell what happens here in more detail.

If the Arduino does pass-through the received API packet bytes from the Xbee to the Serial monitor/Terminal, then you might consider changing the sketch-code to translate these API byte numbers into separate hexadecimal numbers and print that as text. Then you can better understand what numbers they are, and what the Rs and ppm text says. So in hexadecimal format 000 decimal becomes “0x0”. 001 decimal becomes “0x1”, 009 decimal becomes “0x9”, 010 decimal becomes “0xA”, 015 decimal becomes “0xF” and 016 decimal becomes “0x10”. (Und so weiter. :wink: )

Hi Valen, thanks for your response. Danke :wink:

for your question: (arduino+arduino shield+ xbee router at + sensor tgs 2602 → xbee explorer+ xbee modul) my sensor is connected with a resistor 10kohm.

  • my arduino code look like
 const int gasSensor = A0; // Nummer  von Ausgangspin: Sensor

void setup() {

  Serial.begin(9600);

   }

void loop() {
 
  // Kalibrierungsarray der Länge N = 17
 float Rs [17] = {57.84260516,  2.200081335,  1.606762875,  1.178596714,  0.944910617,  0.865628395,  0.764262648,  0.687566798,  0.626992561,  0.567101091,  0.544815465,  0.496850952,  0.474860336,  0.474860336,  0.442046642,  0.423905489,  0.402219139};
 float ppmValue [17] = {0,  5,  10,  15,  20,  24,  28.25,  32.5,  37.75,  43.25,  48.75,  53.25,  57.75,  62.50,  67.50,  75.5,  77.5};
 

 // Lese den Wert von dem Sensor ab
  int value = analogRead (gasSensor);
     
  float volt = (value/1023.0)*5.0 ;    // Rechne die von ADC ausgegebenen Werten in Volt um
  float Rs1 = 10*(5-volt)/volt;        //Rechne den Widerstandswert
  Serial.print ("Rs: ");
  Serial.println (Rs1);
    Serial.print ("Value: ");
  Serial.println (value);
  
  delay (2000);
     
if (Rs1 >= Rs [0])
{
    float ppm = ppmValue [0];
    Serial.print ("ppm: ");
    Serial.println (ppm);  
    delay(3000);    // gib 10 Werte pro Sekunde
} 
  // Interpolation: ppm [0;5]
 
  if ( Rs[1] < Rs1 && Rs1 < Rs[0]){

    float ppm = ppmValue [0] + ((-Rs1 + Rs [0])/(Rs[0] - Rs [1] ))*(ppmValue [1] - ppmValue[0]);
    Serial.print ("ppm: ");
    Serial.println (ppm);  
    delay(3000);    // gib 10 Werte pro Sekunde
}
// Interpolation: ppm [5;10]
  else if ( Rs[2] < Rs1 && Rs1 < Rs[1]){
   
   float ppm = ppmValue [1] + ((-Rs1 + Rs [1])/(Rs[1] - Rs [2] ))*(ppmValue [2] - ppmValue[1]);
    
    //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  } 
  
  // Interpolation: ppm [10;15]
  else if ( Rs[3] < Rs1 && Rs1 < Rs[2]){
   
    float ppm = ppmValue [2] + ((-Rs1 + Rs [2])/(Rs[2] - Rs [3] ))*(ppmValue [3] - ppmValue[2]);
    
    //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  }
    // Interpolation: ppm [15;24]
  else  if ( Rs[4] < Rs1 && Rs1 < Rs[3]){
   
 float ppm = ppmValue [3] + ((-Rs1 + Rs [3])/(Rs[3] - Rs [4] ))*(ppmValue [4] - ppmValue[3]);
   
    //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  }
  
  // Interpolation: ppm [24;28.25]
  
 else if ( Rs[5] < Rs1 && Rs1 < Rs[4]){
   
   float ppm = ppmValue [4] + ((-Rs1 + Rs [4])/(Rs[4] - Rs [5] ))*(ppmValue [5] - ppmValue[4]);
  
  //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  }
  
   // Interpolation: ppm [28.25;32.5]
   else  if ( Rs[6] < Rs1 && Rs1 < Rs[5]){
   
  float  ppm = ppmValue [5] + ((-Rs1 + Rs [5])/(Rs[5] - Rs [6] ))*(ppmValue [6] - ppmValue[5]);
     
     //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
   }
   
  // Interpolation: ppm [32.5;37.75]
else  if ( Rs[7] < Rs1 && Rs1 < Rs[6]){
   
  float  ppm = ppmValue [6] + ((-Rs1 + Rs [6])/(Rs[6] - Rs [7] ))*(ppmValue [7] - ppmValue[6]);
   
   //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  }
  
  // Interpolation: ppm [37.75;43.25]
  else  if ( Rs[8] < Rs1 && Rs1 < Rs[7]){
   
  float  ppm = ppmValue [7] + ((-Rs1 + Rs [7])/(Rs[7] - Rs [8] ))*(ppmValue [8] - ppmValue[7]);
     
     //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  }
  
  // Interpolation: ppm [43.25;48.75]
  else if ( Rs[9] < Rs1 && Rs1 < Rs[8]){
   
   float ppm = ppmValue [8] + ((-Rs1 + Rs [8])/(Rs[8] - Rs [9] ))*(ppmValue [9] - ppmValue[8]);
     
     //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  }
   // Interpolation: ppm [48.75;53.25]
  else  if ( Rs[10] < Rs1 && Rs1 < Rs[9]){
   
  float  ppm = ppmValue [9] + ((-Rs1 + Rs [9])/(Rs[9] - Rs [10] ))*(ppmValue [10] - ppmValue[9]); // set the cursor to column 0, line 0
  
  //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  }
  
 // Interpolation: ppm [53.25;57.75]
 else  if ( Rs[11] < Rs1 && Rs1 < Rs[10]){
   
   float ppm = ppmValue [10] + ((-Rs1 + Rs [10])/(Rs[10] - Rs [11] ))*(ppmValue [11] - ppmValue[10]); // set the cursor to column 0, line 0
  
  //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  }
 
  // Interpolation: ppm [57.75;62.5] 
 else if ( Rs[12] < Rs1 && Rs1 < Rs[11]){
   
  float  ppm = ppmValue [11] + ((-Rs1 + Rs [11])/(Rs[11] - Rs [12] ))*(ppmValue [12] - ppmValue[11]); // set the cursor to column 0, line 0
  
  //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  }
 
  // Interpolation: ppm [62.5;67.5]
  
 else  if ( Rs[13] < Rs1 && Rs1 < Rs[12]){
   
  float  ppm = ppmValue [12] + ((-Rs1 + Rs [12])/(Rs[12] - Rs [13] ))*(ppmValue [13] - ppmValue[12]); // set the cursor to column 0, line 0
  
  //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  }
  
   // Interpolation: ppm [67.5;75.5]
 else  if ( Rs[14] < Rs1 && Rs1 < Rs[13]){
   
   float ppm = ppmValue [13] + ((-Rs1 + Rs [13])/(Rs[13] - Rs [14] ))*(ppmValue [14] - ppmValue[13]); // set the cursor to column 0, line 0
  
  //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  }

 // Interpolation: ppm [75.5;77.5]

else    if( Rs[15] < Rs1 && Rs1 < Rs[14]){
   
   float ppm = ppmValue [14] + ((-Rs1 + Rs [14])/(Rs[14] - Rs [15] ))*(ppmValue [15] - ppmValue[14]); // set the cursor to column 0, line 0
  
  //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  }
  
  else    if( Rs[16] < Rs1 && Rs1 < Rs[15]){
   
   float ppm = ppmValue [15] + ((-Rs1 + Rs [15])/(Rs[15] - Rs [16] ))*(ppmValue [16] - ppmValue[15]); // set the cursor to column 0, line 0
  
  //PPM Ausgabe
    Serial.print ("ppm: ");
    Serial.println (ppm); 
    delay(3000);    // gib 10 Werte pro Sekunde
  }

    else    if (Rs1 >= Rs [16])
{
    float ppm = ppmValue [16];
  
    Serial.print ("ppm: ");
    Serial.println (ppm);  
    delay(3000);    // gib 10 Werte pro Sekunde
} 
    delay(3000);    // gib 10 Werte pro Sekunde
  }

i used this tutorial: http://tronixstuff.com/2010/08/06/

i wonder why he´s not getting those funny characters… :shock:

Unfortunately, i calibrated the Sensor in the Code of arduino. I don´t how to calibrate with hardware :?

the values will be reading by python and insert in mySQL, but i get some errors because of this funny Characters.

Hi Valen,

i find out how to remove those funny characters.

My Xbee Coordinator was configured in API mode and i change it in AT Mode. Since then i get only the value in the terminal.(yeah thanks God i found it) :clap:

But my sensorvalue do not change very much even when i blow over it :roll:

May be the sensor is broken?

florianagr:
Hi Valen,

i find out how to remove those funny characters.

My Xbee Coordinator was configured in API mode and i change it in AT Mode. Since then i get only the value in the terminal.(yeah thanks God i found it) :clap:

After having seen your code I came to this conclusion also. And you repeatedly said you had the router in AT mode, and the Coordinator in API mode. So that it would send API packets to the terminal is rather obvious.

But my sensorvalue do not change very much even when i blow over it :roll:

May be the sensor is broken?

Please be more specific. Since you no longer measure with the Xbee, my lengthy explanation of the sensor response is useless now. Give values that are directly measured by the Arduino. How much do they change? And is this comparable with your multimeter results? Your ppm calibration code is rather complex. Avoid this (complexity) while trying to get a response from the sensor. You can’t tell if it is a hardware failure, or if there is a bug in your calibration code. Let’s try to get raw values first, and rule the hardware failure out. Please give numbers from Analogread, between 0 and 1023. Once that works, you can worry about making a ppm value from it.

Hi Valen,

i solved the problem. i don´t realy know where was the problem, i just change my resistor (10kohm) with a poti (10kohm) and its working.

i thank you for the precious time you take and answers my questions.

thank you very much.