Pages: [1]   Go Down
Author Topic: MQ-4 sensore metano  (Read 712 times)
0 Members and 1 Guest are viewing this topic.
Rome
Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Salve,
sono riuscito a collegare il sensore MQ-4 ad arduino tramite la porta analogica...
solo che ora non riesco a interpretare i valori che mi da... dovrebbero chiaramente essere tra 0 e 1024 ma in qualche modo dovrei rimapparli.
Nel datasheet c'è scritto che il sensore è in grado di captare dai 200 ai 10000 ppm così ho mappato il valore di lettura così:

Code:
valoreReale =map(valoreSensore, 0, 1024, 200, 10000);

solo che ora non so se i risultati hanno davvero un senso...
Come faccio a calibrarlo?
Grazie!
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21657
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Il sensore restituisce una tensione proporzionale al valore letto.
Intanto devi far riscaldare il sensore per il tempo prefissato sul datasheet. Dopodiché esegui una lettura e controlli il valore ambientale del gas. A questo punto devi impostare tu una soglia oltre la quale far scattare l'allarme. Più la forbice tra lettura ambientale normale e soglia di allarme è alta e meno sensibilità avrà il tuo sistema.
Logged


Rome
Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Però in questo modo non è un valore reale... è una sorta di proporzione.
Io vorrei un valore che sia (con un certo errore) rappresentativo della realtà.
Il valore che mi da normalmente senza fonti di gas accanto è circa 158.
Mettendolo vicino al gas sale sopra i 300.
Ma io non vorrei utilizzarlo come allarme ma come misuratore. E' possibile?
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 104
Posts: 6620
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quella che hai fatto è una mappatura lineare.
Dai datasheet visti in rete (non so quale sia il tuo) il sensore sembra logaritmico. Inoltre dovrai compensare le variazioni dovute a temperatura ed umidità che mi sembrano consistenti.
Lo schema della curva mostra che a 1000ppm le due resistenze (quella del sensore e quella imposta dal circuto) sono equivalenti, quindi, se non dico castronerie, il valore centrale è 512. (pari a 1000ppm)

EDIT:
Nel playground ho trovato una funzione per la mappatura logaritmica.
--> http://arduino.cc/playground/Main/Fscale

Code:
/* fscale
 Floating Point Autoscale Function V0.1
 Paul Badger 2007
 Modified from code by Greg Shakar

 This function will scale one set of floating point numbers (range) to another set of floating point numbers (range)
 It has a "curve" parameter so that it can be made to favor either the end of the output. (Logarithmic mapping)

 It takes 6 parameters

 originalMin - the minimum value of the original range - this MUST be less than origninalMax
 originalMax - the maximum value of the original range - this MUST be greater than orginalMin

 newBegin - the end of the new range which maps to orginalMin - it can be smaller, or larger, than newEnd, to facilitate inverting the ranges
 newEnd - the end of the new range which maps to originalMax  - it can be larger, or smaller, than newBegin, to facilitate inverting the ranges

 inputValue - the variable for input that will mapped to the given ranges, this variable is constrained to originaMin <= inputValue <= originalMax
 curve - curve is the curve which can be made to favor either end of the output scale in the mapping. Parameters are from -10 to 10 with 0 being
          a linear mapping (which basically takes curve out of the equation)

 To understand the curve parameter do something like this:

 void loop(){
  for ( j=0; j < 200; j++){
    scaledResult = fscale( 0, 200, 0, 200, j, -1.5);

    Serial.print(j, DEC);  
    Serial.print("    ");  
    Serial.println(scaledResult, DEC);
  }  
}

And try some different values for the curve function - remember 0 is a neutral, linear mapping

To understand the inverting ranges, do something like this:

 void loop(){
  for ( j=0; j < 200; j++){
    scaledResult = fscale( 0, 200, 200, 0, j, 0);

    //  Serial.print lines as above

  }  
}

*/


#include <math.h>

int j;
float scaledResult;

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

void loop(){
  for ( j=0; j < 200; j++){
    scaledResult = fscale( 0, 200, 0, 200, j, -1.5);

    Serial.print(j, DEC);  
    Serial.print("    ");  
    Serial.println(scaledResult , DEC);
  }  
}

float fscale( float originalMin, float originalMax, float newBegin, float
newEnd, float inputValue, float curve){

  float OriginalRange = 0;
  float NewRange = 0;
  float zeroRefCurVal = 0;
  float normalizedCurVal = 0;
  float rangedValue = 0;
  boolean invFlag = 0;


  // condition curve parameter
  // limit range

  if (curve > 10) curve = 10;
  if (curve < -10) curve = -10;

  curve = (curve * -.1) ; // - invert and scale - this seems more intuitive - postive numbers give more weight to high end on output
  curve = pow(10, curve); // convert linear scale into lograthimic exponent for other pow function

  /*
   Serial.println(curve * 100, DEC);   // multply by 100 to preserve resolution  
   Serial.println();
   */

  // Check for out of range inputValues
  if (inputValue < originalMin) {
    inputValue = originalMin;
  }
  if (inputValue > originalMax) {
    inputValue = originalMax;
  }

  // Zero Refference the values
  OriginalRange = originalMax - originalMin;

  if (newEnd > newBegin){
    NewRange = newEnd - newBegin;
  }
  else
  {
    NewRange = newBegin - newEnd;
    invFlag = 1;
  }

  zeroRefCurVal = inputValue - originalMin;
  normalizedCurVal  =  zeroRefCurVal / OriginalRange;   // normalize to 0 - 1 float

  /*
  Serial.print(OriginalRange, DEC);  
   Serial.print("   ");  
   Serial.print(NewRange, DEC);  
   Serial.print("   ");  
   Serial.println(zeroRefCurVal, DEC);  
   Serial.println();  
   */

  // Check for originalMin > originalMax  - the math for all other cases i.e. negative numbers seems to work out fine
  if (originalMin > originalMax ) {
    return 0;
  }

  if (invFlag == 0){
    rangedValue =  (pow(normalizedCurVal, curve) * NewRange) + newBegin;

  }
  else     // invert the ranges
  {  
    rangedValue =  newBegin - (pow(normalizedCurVal, curve) * NewRange);
  }

  return rangedValue;
}

quindi, inserendo la funzione nel tuo codice e l'include della libreria math, dovresti avere:
Quote
valoreReale =fscale(0, 1023, 200, 10000, valoresensore, 10);

Devi controllare se il valore centrale è rispettato. 512 = 1000ppm
« Last Edit: October 11, 2012, 08:37:43 am by PaoloP » Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

Rome
Offline Offline
Newbie
*
Karma: 0
Posts: 21
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie mille!
questa sera provo!
ma non ho capito dove controllare:
 512 = 1000ppm
Logged

Cagliari, Italy
Offline Offline
Tesla Member
***
Karma: 104
Posts: 6620
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Grazie mille!
questa sera provo!
ma non ho capito dove controllare:
 512 = 1000ppm

Forse meglio fare così
Code:
int valorecentrale = 512; //valore che corrisponde a 1000ppm - da ricavare in base allo schema elettrico
if (valoresensore>valorecentrale) {
  valoreReale =fscale(valorecentrale, 1023, 1000, 10000, valoresensore, 10);
}
 else
{
 valoreReale =fscale(0, valorecentrale, 200, 1000, valoresensore, 10);
}

infine dovresti fare
Code:
valoreReale = valoreReale * CorrezioneTH;
CorrezioneTH lo calcoli in base alle curve del datasheet o con una funzione apposita conoscendo l'umidità e la temperatura dell'ambiente dove si trova il sensore.
« Last Edit: October 11, 2012, 08:58:27 am by PaoloP » Logged

Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

BZ (I)
Offline Offline
Brattain Member
*****
Karma: 236
Posts: 20281
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Il sensore siccuramente non é tarato. Devi tararlo con dei gas di prova a concentrazione nota.
Secondo le specifiche del sensore devi ritaralo a intervalli fissi.
Il sensore di metano é influezato anche da altri gas e materili. Per esempio legge anche alcool (bevande alcooliche) ed é come scrive PaoloP sensibile a cambi di temperatura. percui anche temperature ambientali diverse fanno necessario una calibrazione.
Ciao Uwe
« Last Edit: October 11, 2012, 04:38:18 pm by uwefed » Logged

Pages: [1]   Go Up
Jump to: