top of page

MQ7 SENSÖR PROJESİ

  • Yazarın fotoğrafı: muhammed ali balkaya
    muhammed ali balkaya
  • 29 Kas 2018
  • 5 dakikada okunur

Bu proje ile CO gazlarını tespit eden proje yapacağız. Bu verileri ayrıca ekrandan kontrol edeceğiz.


Devre Şeması


Sistem için gerekli olan ilk kod ekran kodu olaaktır. Ekran Kodu aşağıdaki gibidir.

Kod

int time_scale = 8; //time scale: we altered main system timer, so now all functions like millis(), delay() etc

//will think that time moves 8 times faster than it really is

//to correct that, we use time_scale variable:

//in order to make delay for 1 second, now

//we call delay(1000*time_scale)


void setTimer0PWM(byte chA, byte chB) //pins D5 and D6

{

TCCR0A = 0b10110011; //OCA normal,OCB inverted, fast pwm

TCCR0B = 0b010; //8 prescaler - instead of system's default 64 prescaler - thus time moves 8 times faster

OCR0A = chA; //0..255

OCR0B = chB;

}



void setTimer2PWM(byte chA, byte chB) //pins D11 and D3

{

TCCR2A = 0b10100011; //OCA,OCB, fast pwm

TCCR2B = 0b001; //no prescaler

OCR2A = chA; //0..255

OCR2B = chB;

}


void setTimer1PWM(int chA, int chB) //pins D9 and D10

{

TCCR1A = 0b10100011; //OCA,OCB, fast pwm

TCCR1B = 0b1001; //no prescaler

OCR1A = chA; //0..1023

OCR1B = chB;

}


float opt_voltage = 0;

byte opt_width = 240; //default reasonable value


void pwm_adjust()

//this function tries various PWM cycle widths and prints resulting

//voltage for each attempt, then selects best fitting one and

//this value is used in the program later

{

float previous_v = 5.0; //voltage at previous attempt

float raw2v = 5.0 / 1024.0;//coefficient to convert Arduino's

//analogRead result into voltage in volts

for(int w = 0; w < 250; w++)

{

setTimer2PWM(0, w);

float avg_v = 0;

for(int x = 0; x < 100; x ++) //measure over about 100ms to ensure stable result

{

avg_v += analogRead(A1);

delay(time_scale);

}

avg_v *= 0.01;

avg_v *= raw2v;

Serial.print("adjusting PWM w=");

Serial.print(w);

Serial.print(", V=");

Serial.println(avg_v);

if(avg_v < 3.6 && previous_v > 3.6) //we found optimal width

{

float dnew = 3.6 - avg_v; //now we need to find if current one

float dprev = previous_v - 3.6;//or previous one is better

if(dnew < dprev) //if new one is closer to 1.4 then return it

{

opt_voltage = avg_v;

opt_width = w;

return;

}

else //else return previous one

{

opt_voltage = previous_v;

opt_width = w-1;

return;

}

}

previous_v = avg_v;

}

}


float alarm_ppm_threshold = 100; //threshold CO concentration for buzzer alarm to be turned on,

float red_threshold = 40; //threshold when green LED is turned on red turns on

float reference_resistor_kOhm = 10.0; //fill correct resisor value if you are using not 10k reference


float sensor_reading_clean_air = 620; //fill raw sensor value at the end of measurement phase (before heating starts) in clean air here! That is critical for proper calculation

float sensor_reading_100_ppm_CO = -1; //if you can measure it

//using some CO meter or precisely calculated CO sample, then fill it here

//otherwise leave -1, default values will be used in this case


float sensor_100ppm_CO_resistance_kOhm; //calculated from sensor_reading_100_ppm_CO variable

float sensor_base_resistance_kOhm; //calculated from sensor_reading_clean_air variable


byte phase = 0; //1 - high voltage, 0 - low voltage, we start from measuring

unsigned long prev_ms = 0; //milliseconds in previous cycle

unsigned long sec10 = 0; //this timer is updated 10 times per second,

//when it will overflow, program might freeze or behave incorrectly.

//It will happen only after ~13 years of operation. Still,

//if you'll ever use this code in industrial application,

//please take care of overflow problem

unsigned long high_on = 0; //time when we started high temperature cycle

unsigned long low_on = 0; //time when we started low temperature cycle

unsigned long last_print = 0; //time when we last printed message in serial


float sens_val = 0; //current smoothed sensor value

float last_CO_ppm_measurement = 0; //CO concentration at the end of previous measurement cycle


float raw_value_to_CO_ppm(float value)

{

if(value < 1) return -1; //wrong input value

sensor_base_resistance_kOhm = reference_resistor_kOhm * 1023 / sensor_reading_clean_air - reference_resistor_kOhm;

if(sensor_reading_100_ppm_CO > 0)

{

sensor_100ppm_CO_resistance_kOhm = reference_resistor_kOhm * 1023 / sensor_reading_100_ppm_CO - reference_resistor_kOhm;

}

else

{

sensor_100ppm_CO_resistance_kOhm = sensor_base_resistance_kOhm * 0.5;

//This seems to contradict manufacturer's datasheet, but for my sensor it

//looks quite real using CO concentration produced by CH4 flame according to


//my experiments were very rough though, so I could have overestimated CO concentration significantly

//if you have calibrated sensor to produce reference 100 ppm CO, then

//use it instead

}

float sensor_R_kOhm = reference_resistor_kOhm * 1023 / value - reference_resistor_kOhm;

float R_relation = sensor_100ppm_CO_resistance_kOhm / sensor_R_kOhm;

float CO_ppm = 100 * (exp(R_relation) - 1.648);

if(CO_ppm < 0) CO_ppm = 0;

return CO_ppm;

}


void startMeasurementPhase()

{

phase = 0;

low_on = sec10;

setTimer2PWM(0, opt_width);

}


void startHeatingPhase()

{

phase = 1;

high_on = sec10;

setTimer2PWM(0, 255);

}

void setLEDs(int br_green, int br_red)

{

if(br_red < 0) br_red = 0;

if(br_red > 100) br_red = 100;

if(br_green < 0) br_green = 0;

if(br_green > 100) br_green = 100;


float br = br_red;

br *= 0.01;

br = (exp(br)-1) / 1.7183 * 1023.0;

float bg = br_green;

bg *= 0.01;

bg = (exp(bg)-1) / 1.7183 * 1023.0;

if(br < 0) br = 0;

if(br > 1023) br = 1023;

if(bg < 0) bg = 0;

if(bg > 1023) bg = 1023;


setTimer1PWM(1023-br, 1023-bg);

}

void buzz_on()

{

setTimer0PWM(128, 128);

}

void buzz_off()

{

setTimer0PWM(255, 255);

}

void buzz_beep()

{

byte sp = sec10%15;

if(sp == 0)

buzz_on();

if(sp == 1)

buzz_off();

if(sp == 2)

buzz_on();

if(sp == 3)

buzz_off();

if(sp == 4)

buzz_on();

if(sp == 5)

buzz_off();

}


void setup() {


//WARNING! Each sensor is different!

//You MUST calibrate sensor manually and

//set proper sensor_reading_clean_air value before using

//it for any practical purpose!


pinMode(5, OUTPUT);

pinMode(6, OUTPUT);

pinMode(3, OUTPUT);

pinMode(9, OUTPUT);

pinMode(10, OUTPUT);

pinMode(A0, INPUT);

pinMode(A1, INPUT);

setTimer1PWM(1023, 0);

analogReference(DEFAULT);

Serial.begin(9600);


pwm_adjust();


Serial.print("PWM result: width ");

Serial.print(opt_width);

Serial.print(", voltage ");

Serial.println(opt_voltage);

Serial.println("Data output: raw A0 value, heating on/off (0.1 off 1000.1 on), CO ppm from last measurement cycle");

//beep buzzer in the beginning to indicate that it works

buzz_on();

delay(100*time_scale);

buzz_off();

delay(100*time_scale);

buzz_on();

delay(100*time_scale);

buzz_off();

delay(100*time_scale);

buzz_on();

delay(100*time_scale);

buzz_off();

delay(100*time_scale);


startMeasurementPhase(); //start from measurement

}


void loop()

{


//WARNING! Each sensor is different!

//You MUST calibrate sensor manually and

//set proper sensor_reading_clean_air value before using

//it for any practical purpose!


unsigned long ms = millis();

int dt = ms - prev_ms;


//this condition runs 10 times per second, even if millis()

//overflows - which is required for long-term stability

//when millis() overflows, this condition will run after less

//than 0.1 seconds - but that's fine, since it happens only once

//per several days

if(dt > 100*time_scale || dt < 0)

{

prev_ms = ms; //store previous cycle time

sec10++; //increase 0.1s counter

if(sec10%10 == 1) //we want LEDs to blink periodically

{

setTimer1PWM(1023, 1023); //blink LEDs once per second

//use %100 to blink once per 10 seconds, %2 to blink 5 times per second

}

else //all other time we calculate LEDs and buzzer state

{

int br_red = 0, br_green = 0; //brightness from 1 to 100, setLEDs function handles converting it into timer settings

if(last_CO_ppm_measurement <= red_threshold) //turn green LED if we are below 30 PPM

{//the brighter it is, the lower concentration is

br_red = 0; //turn off red

br_green = (red_threshold - last_CO_ppm_measurement)*100.0/red_threshold; //the more negative is concentration, the higher is value

if(br_green < 1) br_green = 1; //don't turn off completely

}

else //if we are above threshold, turn on red one

{

br_green = 0; //keep green off

br_red = (last_CO_ppm_measurement-red_threshold)*100.0/red_threshold; //the higher is concentration, the higher is this value

if(br_red < 1) br_red = 1; //don't turn off completely

}


if(last_CO_ppm_measurement > alarm_ppm_threshold) //if at 50 seconds of measurement cycle we are above threshold

buzz_beep();

else

buzz_off();


setLEDs(br_green, br_red); //set LEDs brightness

}

}

if(phase == 1 && sec10 - high_on > 600) //60 seconds of heating ended?

startMeasurementPhase();

if(phase == 0 && sec10 - low_on > 900) //90 seconds of measurement ended?

{

last_CO_ppm_measurement = raw_value_to_CO_ppm(sens_val);

startHeatingPhase();

}


float v = analogRead(A0); //reading value

sens_val *= 0.999; //applying exponential averaging using formula

sens_val += 0.001*v; // average = old_average*a + (1-a)*new_reading

if(sec10 - last_print > 9) //print measurement result into serial 2 times per second

{

last_print = sec10;

Serial.print(sens_val);

Serial.print(" ");

Serial.print(0.1 + phase*1000);

Serial.print(" ");

Serial.println(last_CO_ppm_measurement);

}

}




Bu kodları processing programına yükledikten sonra uno içinde ayrıca kod gerekecektir. Bu kodda aşağıda mevcuttur.


Proje Kodu


 
 
 

2 comentários


turan2002
02 de dez. de 2018

efffffffffffffffffffffffffffffffssssssssssssssssssssssssssssaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaannnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnneeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee

Curtir

turan2002
02 de dez. de 2018

süppppeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeerrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr

Curtir

© 2023 by Parenting Blog

Proudly created with MAB.com

  • YouTube Sosyal Simge
  • Facebook Black Round
  • Twitter Black Round

BURSA / OSMANGAZİ

Mail listemize katılın

bottom of page