Mein Arduino Nano liefert falschen Werten!!

Hi,

ich möchte ein drahtloses voc Messgerät entwickeln. Dafür benutze ich einen TGS 2602 Sensor, Arduino Nano und XBee Pro S1 als sender und ein XBee pro S1 ist am Computer als Empfänger angeschlossen. My Arduino Code:

int value ;       
const int gasSensor = A0;

void setup() {

  Serial.begin(9600);

   }

void loop() {
 


  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("40B7DEF1");            // Sensorname
  //Serial.print("\t");                  // Tabulator

  
  // 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};
 
     
if (Rs1 >= Rs [0])
{
    float ppm = ppmValue [0];
    //Serial.print ("ppm: ");
    Serial.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println(ppm);  
    delay(30000);
} 
  // 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.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm);  
    delay(30000);
}
// 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.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);
  } 
  
  // 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.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);
  }
    // 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.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);
  }
  
  // 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.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);
  }
  
   // 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.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);
   }
   
  // 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.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);
  }
  
  // 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.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);
  }
  
  // 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.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);    
  }
   // 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]); 
  
  //PPM Ausgabe
    //Serial.print ("ppm: ");
    Serial.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);
  }
  
 // 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]); 
  
  //PPM Ausgabe
    //Serial.print ("ppm: ");
    Serial.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);
  }
 
  // 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]); 
  
  //PPM Ausgabe
    //Serial.print ("ppm: ");
    Serial.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);
  }
 
  // 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]); 
  
  //PPM Ausgabe
    //Serial.print ("ppm: ");
    Serial.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);
  }
  
   // 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]); 
  
  //PPM Ausgabe
    //Serial.print ("ppm: ");
    Serial.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);
  }

 // 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]); 
  
  //PPM Ausgabe
    //Serial.print ("ppm: ");
    Serial.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);
  }
  
  else    if( Rs[16] < Rs1 && Rs1 < Rs[15]){
   
   float ppm = ppmValue [15] + ((-Rs1 + Rs [15])/(Rs[15] - Rs [16] ))*(ppmValue [16] - ppmValue[15]); 
  
  //PPM Ausgabe
    //Serial.print ("ppm: ");
    Serial.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm); 
    delay(30000);}

    else    if (Rs1 >= Rs [16])
{
    float ppm = ppmValue [16];
  
    //Serial.print ("ppm: ");
    Serial.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm);  
    delay(30000);
} 
  
   else    if (Rs1 < Rs [16])
{
    float ppm = 80;
  
    //Serial.print ("ppm: ");
    Serial.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm);  
    delay(30000);    
} 
delay(3000);    
  }

Leider sind die Werte, die ich bekomme falsch. Der Analogpin wird nicht wirklich gelesen. Was mache ich falsch?
Ich würde mich sehr freuen wenn jemand mir helfen kann.
VG
Thanks

Du musst den Pin im Setup initialisieren: pinMode(gasSensor, INPUT)

gloob:
Du musst den Pin im Setup initialisieren: pinMode(gasSensor, INPUT)

Analoge Eingänge müssen-dürfen nicht so initialisiert werden.

@florianagr
Die 5V Versorgungsspannung ist nicht immer geneu 5V. Eine Abweichung führt zur Falschmessung.

Wie Sieht der Spannungsteiler aus? Welche Werte bekommst Du bei der Messung?

Grüße Uwe

Die dürfen so nicht initialisiert werden? Hat das einen Hintergrund? Hab das bisher immer so gemacht.

gloob:
Die dürfen so nicht initialisiert werden? Hat das einen Hintergrund? Hab das bisher immer so gemacht.

Sagen wir es mal so:
Die sind sowieso schon, beim Start, als INPUT definiert.
Tut also keine Not das nochmal zu tun.

http://arduino.cc/en/Tutorial/AnalogInputPins

Dass sie nicht müssen wusste ich, dass sie nicht dürfen ist mir aber neu, würde mich auch interessieren.

Ich hatte schon mal das Problem dass er das 'A' vor der pin Nummer nicht wollte. Ohne 'A' funktionierte es. Ich weiß nicht ob das bei einer bestimmten IDE Version war, oder nur bei einem bestimmten Arduino Typen, normalerweise geht es ja auch mit 'A0'.

Am Rande: viel Text für wenig code. :wink: Ich habs mir jetzt nicht im Detail durchgelesen, vielleicht habe ich etwas übersehen, aber du prüfst doch eigentlich nur zwischen welchen beiden Array Feldern der Messwert liegt, oder ob er oben oder unten aus dem Messbereich fällt, und führst dann immer die gleiche Berechnung aus. Das geht auch so:

float ppm;

if (Rs1 < Rs [16]) 
  ppm = ppmValue [16];
else if (Rs1 > RS[0])
  ppm = 80;
} else {
  for (int i = 0; i < 17; i++) {
    if( Rs[i+1] < Rs1 && Rs1 < Rs[i]){
      ppm = ppmValue [i] + ((-Rs1 + Rs [i])/(Rs[i] - Rs [i+1] ))*(ppmValue [i+1] - ppmValue[i]); 
    }
  }
}

//Serial.print ("ppm: ");
    Serial.print("1");            // Sensorname
    Serial.print("\t");                  // Tabulator

    Serial.println (ppm);  
    delay(30000);

Danke gsezz für deine Antwort. Ich versuche mein Code zu reduzieren.

Danke auch gloob für deine Antwort. Die Werte die ich bekomme sind zufälligen Werten, aber definitiv nicht vom Sensor. Beim Testen (Messung eines alkoholreichen Gegenstand) verändern sich die Werte nicht. Ich habe die Werte vom Analogeingang überprüft und sie scheinen in Ordnung zu sein. Aber die ppm Werte die ich am Monitor bekommen entsprechen nicht, die Werten vom analogen Eingang.

Was mache ich falsch?

VG

Nur eine Vermutung, aber könnte es Probleme mit den vielen float Variablen auf dem kleinen Nano geben?

Du solltest grundsätzlich versuchen float zu vermeiden wo es nicht unbedingt nötig ist. Meistens braucht man nur 1-3 Nachkommastellen, dann kann man auch integer nehmen und mit um 10-1000 multiplizierten Werten arbeiten. Teile der Berechnung, eigentlich alle für die man hier wirklich float braucht, musst du gar nicht auf dem Arduino durchführen. Anstelle verschiedene Widerstandswerte in dem Array abzulegen, und jeden Messwert erst in einen Widerstand umzurechnen, kannst du mit dem Taschenrechner (oder Excel ;)) auch gleich die entsprechenden Digitalwerte ausrechnen und ins Array schreiben. Deine beiden Arrays könnten dann ungefähr so aussehen:

int Rs [17] = {0, 128, 256,... , 512, 1023}; //Phantasiewerte!
int ppmValue [17] = {0, 500, 1000, 1500, 2000, 2400, 2825, 3250, 3775, 4325, 4875, 5325, 5775, 6250, 6750, 7550, 7750};

//Für die Ausgabe kann man den int Wert dann mal kurz zum float machen:
float value = ppm/100.00;
Serial. print(value);

//Man kann float aber auch hier komplett vermeiden, indem man die Vor- und Nachkommastellen separat ausgibt:
int Ganzzahl = ppm/100;
Serial.print(Ganzzahl);
Serial.print('.');
Serial.print(ppm-(Ganzzahl*100));

Ist nur eine Idee, ich weiß nicht ob das wirklich etwas mit den falschen Werten zu tun hat.

Der Trick nennt sich Festkommaarithmetik
http://www.mikrocontroller.net/articles/Festkommaarithmetik
und ist sinnvoll, da man sowie nur int Werte erhält.

Zumal sich bei der Verbesserung auch ein Fehler eingeschlichen hat.

  for (int i = 0; i < 17; i++) {
    if( Rs[i+1] < Rs1 && Rs1 < Rs[i]){

Bei i = 16 greifst du auf einen falschen index von Rs zu. i =17, jedoch ist der max Index von Rs [17-1]

Teste den Sensor erst einmal mit einem einfacheren Sketch. Zwischen jeder Messung ein delay von 1000ms. Ausgabe auf die Serielle Schnittstelle.

Zum Programm nochmal selber, besser angehen kann man das wie folgt, da du nach jeder Aktion sowieso 30s den Sketch anhältst.

// Pseudo
loop:
Sensor einlesen(jede 1s oder 5s oder ... ) und in einen Fifo-Buffer speichern.

Alle 30s den Mittelwert vom Fifo-Buffer berechnen.

Entscheiden, was passiert

hi gsezz,
Hi sschultewoler,
danke für die Antworten. Es hat mir viel geholfen.
Ich habe sowohl die float-werten in integer umgeschrieben als auch den Code verkürzt.
Hier entstandener Code:

 float Rs1 = 10*(1023-value)/value;        //Rechne den Widerstandswert
  int Rs [17] = {150790,  838524,  881440,  915141,  934680,  941501,  950367,  957187,  962643,  968099,  970145,  974578,  976624,  976624,  979693,  981398,  983444};
  int ppmValue [17] = {0,  500,  1000,  1500,  2000,  2400,  2825,  3250,  3775,  4325,  4875,  5325,  5775,  6250,  6750,  7550,  7750};
 

 
  float ppm;
  if (Rs1 > Rs [16]){ 
    ppm = ppmValue [16];
  }
    else {
  for (int i = 0; i < 16; i++) {
    if( Rs[i+1] < Rs1 && Rs1 < Rs[i]){
      ppm = ppmValue [i] + ((-Rs1 + Rs [i])/(Rs[i] - Rs [i+1] ))*(ppmValue [i+1] - ppmValue[i]); 
    }
  }
}

//Serial.print ("ppm: ");
    Serial.print("1");            // Sensorname
    Serial.print("\t");     // Tabulator
    
  float ppmvalue = ppm/100.00;
 // Serial.print(ppmvalue); 
    Serial.println (ppmvalue);  
    delay(30000);

Aber leider bekomme ich nur den Wert 12.50 am Serial Monitor. und dieser Wert ändert sich nicht.

Ich möchte auch gern den Mittelwert bilden und habe mir gedacht ich kann es so machen:

 float i;
  float value;
  for (i=0; i<10;i++){
 // Lese den Wert von dem Sensor ab
  value = analogRead (analogPin);
  }
  value = value/10; // average

Wäre es richtig?

LG

Wäre fast richtig.

Musst nur zehn mal aufaddieren, bevor du die Summe durch 10 teilst.

int sumvalue= 0;
for (int i = 0; i < 10; i++)
  sumvalue += analogRead (analogPin);

float value = sumvalue/10.0;

Nachtrag:Mal abgesehen davon, dass du so nur den Mittelwert uber ca. 1 ms bildest

Ahem, ein int geht bis max 32767 bei 8bit Arduinos wie dem nano.

probier mal :

 long Rs [17] = {150790,  838524,  881440,  915141,  934680,  941501,  950367 /* ... */ };

Am besten gleich an Standart Typen gewöhnen und benutzen: uint8_t, uint16_t, uint32_t für Werte ohne Vorzeichen, bzw int8_t, int_16t, int32_t für Werte mit Vorzeichen. Dann weiß man auch sofort mit wie viel Bit man es zu tun hat. long, double, etc finde ich recht verwirrend, und dass die Interpretation von int Plattformabhängig ist hatte ich auch schon wieder verdrängt.

Zurück zum eigentlichen Problem, dein digitaler Wert von analogRead() stimmt also, er variiert nachvollziehbar mit dem was der Sensor misst?
Ich verstehe nicht ganz welche Werte du nun in das Array RS[] gelegt hast. Schreib doch einfach die entsprechenden analogRead() Werte in das Array. Die kannst du ein mal alle manuell berechnen, dann muss der Arduino nicht bei jedem einzelnen Messvorgang irgendwas umrechnen.

float Rs1 = 10*(1023-value)/value;
Diese Rechnung ist merkwürdig. zu aller erst einmal kann es dabei zur Division durch Null kommen, der Supergau. :wink: Aber ich kann auch nicht nachvollziehen was da berechnet werden soll. Ich denke da wird sicher ein fehler drin sein.
Mit (1023-value) willst du vermutlich die Skala des Messbereichs umkehren. (Ein klitzekleiner Schritt den du dem Arduino ersparen kannst indem du die Werte einfach in umgekehrter Reihenfolge ins Array schreibst.) Aber vor allem dann noch einmal durch value zu teilen ergibt für mich keinen Sinn. Rechne mal von Hand aus was für verschiedene Werte value=0-1023 heraus kommt, dann siehst du schon dass das nichts mit den Zahlen im Array RS[] zu tun haben kann.
Alles was bei der Berechnung von RS1 heraus kommen kann ist deutlich kleiner als alle Werte im Array. Dieser Fall wird ja durch keinen if-Zweig erfüllt, deshalb wird ppm niemals definiert. Also enthält ppm irgend einen Wert der zufällig noch an der Speicheradresse steht die dafür reserviert ist.
Solange du nach Fehlern suchst kannst du Werte die nur deklariert sind ruhig mal mit einem erkennbaren Wert definieren, z.b. float ppm = 1234 dann weißt du, wenn dieser Wert am Ende ausgegeben wird dass die Variable niemals bearbeitet wurde.

Hi michael_x,
Hi gsezz,

tut mir Leid, dass ich so spät antworte.
ich habe schon mal die Widerstandswerten umgerechnet, aber es hilft nicht weiter.
Jetzt habe ich das Problem, dass der Analogeingang nicht richtig gelesen wird (ich bekomme nur Zufallszahlen).
Ich habe auch einen einfachen Code ausgeführt ("AnalogRead"), trotzdem bekomme ich weiter komische Zahlen.
Ist mein Nano vielleicht kaputt?

LG

Wie hast du dieses Tutorial/AnalogReadSerial mit dem Nano nachgebaut, dass es nicht funktioniert?

Ist mein Nano vielleicht kaputt?

Kann man nicht ganz ausschliessen, aber meist ist was falsch angeschlossen.

Hi michael_x,

ich habe mit dem Poti geprüft. UNd alles funktioniert soweit gut.
Aber sobald ich meinem Sensor anschließe funktioniert es nicht mehr.

Anschluß von TGS 2602:
pin 4+ 3 = 5 V
pin 1= Ground
pin 2 = + Eingang von Poti

Ist es falsch?

LG

"+ Eingang von Poit" keine Ahnung was du damit meinst.
An Pin 2 des Sensors gehört ein Widerstand gegen GND um einen Spannungsteiler zu schaffen. Analog In vom Arduino greift dann zwischen Widerstand und Sensor die Spannung im Spannungsteiler ab. Vom Verhältnis abgegriffener Spannung(als digitaler Wert) zur Versorgungsspannung kannst du das Verhältnis gemessener Sensorwert : maximaler Sensorwert berechnen. Mit absoluten Widerstands- und Spannungswerten brauchst du auf dem µC gar nicht rechnen, einfach in Excel die Verhältnisse zuordnen und per map() mappen.

Vorsicht falls du vor hast die Heizspannung mit einem digitalpin zu steuern, die braucht zu viel Strom.

Hallo,

ich habe es geschafft alles funktioniert einwandfrei.
Danke, Danke!!