مجله اینترنتی تحلیلک

سه شنبه/ 29 اسفند / 1402
Search
Close this search box.
ساخت آلارم مونوکسید کربن به وسیله برد آردوینو

ساخت آلارم مونوکسید کربن به وسیله برد آردوینو

در این مقاله نحوه ساخت یک سنسور تشخیص و آلارم گاز مونوکسید کربن نشان داده شده است. این تجهیزات با قیمتی کمتر از 10 دلار قابل تهیه و نصب خواهد بود.

مرگ خاموش واژه ناخوشایند ولی آشنا است که با شروع فصل سرد هرساله به گوش می‌رسد. مونوکسید کربن گازی بی‌رنگ و بی‌بو است که در اثر ناقص سوختن مواد سوختی، نقص سیستم گرمایشی و دودکش باعث مرگ بسیاری از هم‌وطنان می‌شود. هرچند در سالیان اخیر نیروهای آتش‌نشانی و سازمان‌هایی مانند صداوسیما با شروع فصول سرد شروع به آموزش می‌کنند، اما باز هم شماری از هم‌وطنان در اثر حوادثی ناخواسته دچار گازگرفتگی می‌شوند. اگر چه سهم این حوادث باز هم از نقص‌ها و بی‌احتیاطی‌ها کمتر است، اما مرگ یک انسان هم در این مورد قابل‌ قبول نیست.

سالیان گذشته معدن کاوها به همراه خود یک پرنده مانند قناری به عمق معدن می‌بردند تا در صورت وجود گاز آن‌ها را هوشیار نماید. این پرندگان در واقع یک حس‌گر طبیعی برای گازها بودند. امروزه با توجه به رشد فناوری شرکت‌های منازل هوشمند اقدام به ساخت آلارم های گاز نموده‌اند. نمونه این دستگاه‌ها در مارکت های اروپایی و آمریکایی در حدود ۵۰ دلار قابل خرید است.

در این مقاله سعی بر آن شده تا با مبلغی کمتر از صد و پنجاه‌ هزار تومان بتوانید یک دستگاه آلارم مونوکسید کربن به وسیله برد آردوینو را برای خود تهیه کنید و بتوانید از جان خود و نزدیکانتان در مقابل گاز مونوکسید کربن نگهبانی و مراقبت نمایید.

 

تجهیزات لازم برای آلارم مونوکسید کربن به وسیله برد آردوینو

"تجهیزات

  • برد آردوینو نانو
  • سنسور MQ-7 CO
  • ترانزیستور NPN در واقع هر ترانزیستوری که بتواند ۳۰۰ میلی آمپر و یا بیشتر کار کند
  • مقاومت یک کیلو اهمی ۲ عدد
  • مقاومت ده کیلو اهمی یک عدد
  • خازن ۱۰ میکرو فارادی ۲ عدد
  • ال ای دی قرمز و سبز یک عدد
  • بازر پیزو الکتریک یک عدد
  • برِد بُرد یک عدد

آشنایی با تجهیزات آلارم مونوکسید کربن

سنسور MQ-7 CO نوعی سنسور الکتروشیمی است که بایستی گرم شود و بعد از آن داده‌ها را دریافت کند. این سنسور دارای یک هیتر داخلی است. این سنسور توانایی تشخیص غلظت CO موجود در هوا را دارد. محدوده غلظت قابل‌ سنجش این سنسور بین ۲۰ppm تا ۲۰۰۰ppm است. حساسیت بالا، پاسخ‌گویی در کمترین زمان ممکن و خروجی آنالوگ از خصوصیات این سنسور است. راه‌اندازی این سنسور آسان است و شما به‌راحتی می‌توانید با اتصال خروجی آنالوگ سنسور به ADC آردوینو، آن را راه‌اندازی کنید. برای دریافت اطلاعات مراحل زیر رعایت شود:

سنسور اندازه گیری مونوکسید کربن
سنسور اندازه گیری مونوکسید کربن

  • برق ورودی ۵ ولت به میزان ۶۰ ثانیه اعمال شود ولی داده‌ای از میزان CO یادداشت نشود.
  • برق ورودی ۱.۴ ولت به میزان ۹۰ ثانیه اعمال گردد و داده‌های مقدار CO یادداشت شود.
  • رفتن به مرحله ۱

واضح است که برد آردوینو نمی‌تواند ولتاژ ۵ ولت منقطع را برای آلارم مونوکسید کربن مستقیماً تأمین کند و همچنین حداکثر جریان تولیدی آن نیز ۴۰ میلی آمپر است. در حالی‌که هیتر این سنسور نیازمند ۱۵۰ میلی آمپر جریان ۵ ولت است. برای مقدار ۱.۴ ولت نیز می‌بایست از پایه PWM با پالس‌های متفاوت استفاده نمود.

آردوینو نانو
آردوینو نانو

استفاده از ترانزیسور NPN می‌تواند دو مشکل قبل را حل نماد. اگر ترانزیستور باز باشد جریان ۵ ولت اعمال می‌شود و بعد از یک دقیقه پالس اعمالی به پایه‌ی ترانزیستور ولتاژ ۱.۴ را تولید می‌نماید. این ولتاژ پالسی توسط خازن‌ها صاف می‌شوند.

نحوه اتصالات برد آردوینو برای آلارم مونوکسید کربن

تجهیزات تهیه‌ شده را مانند شکل زیر به هم متصل می‌کنیم. از پایه ۵ ولت برد آردوینو به مقاومت یک کیلو اهمی وصل و بعد از آن به ال ای دی های قرمز و سبز نصب می‌کنیم. خروجی ال ای دی قرمز به پایه دیجیتال ۱۰ و خروجی ال ای دی سبز به پایه ۹ دیجیتال برد آردوینو وصل می‌شود.

نحوه اتصال میکرو کنترل به سنسور و تجهیزات
نحوه اتصال میکرو کنترل به سنسور و تجهیزات

پایه شماره ‌یک بازر به پایه ۶ دیجیتال و پایه ۲ بازر نیز به پایه ۵ دیجیتال متصل می شود. از پایه ۵ ولت یک انشعاب به پایه VIN سنسور متصل نمایید و به‌صورت موازی به مثبت دو خازن ۱۰ میکرو فارادی متصل نمایید. پایه منفی خازن اول را به پایه‌ یک آنالوگ برد آردوینو متصل نموده و همین‌گونه به خروجی زمین در سنسور و از پایه صفر آنالوگ به ورود AO سنسور متصل نمایید و سپس به منفی خازن دوم و یک اتصال نیز به مقاوت ۱۰ کیلو آهمی. خروجی مقاوت کیلو اهمی را به زمین متصل نمایید. از پایه GND به ورودی ترانزیستور متصل نمایید. خروجی ترانزیستور به زمین و ورودی گیت را به پایه دیجیتال سوم بعد از مقاومت یک کیلو اهمی متصل نمایید.

نحوه اتصال روی برِد برُد
نحوه اتصال روی برِد برُد

کالیبراسیون

سنسور برای هرگونه استفاده عملی نیاز به کالیبراسیون دستی دارد. بدون کالیبراسیون پارامترهای سنسور در این طرح ممکن است آلارم را در هوای تمیز نیز روشن شود یا غلظت مونوکسید کربن زیاد را کشف نکند.

کالیبراسیون حدسی می‌تواند بسیار آسان ولی پیچیده باشد. مراحل کالیبره نمودن سنسور مونوکسید کربن در ادامه آورده شده است. ابتدا PWM خود را جهت تولید پایدار ۱.۴ ولت مورد نیاز سنسور کالیبره می‌کنیم (عرض مناسب PWM به پارامترهای زیادی از جمله مقاومت دقیق، مقاومت این سنسور خاص، منحنی VA ترانزیستور و غیره بستگی دارد) بنابراین بهترین راه امتحان مقادیر مختلف است. به این صورت که یک حد بالا و یک حد پایین را می‌یابیم و با میان یابی به مقدار دقیق می‌رسیم. سپس، ما دائماً چرخه گرمایش ۶۰ ثانیه‌ای و اندازه‌گیری ۹۰ ثانیه‌ای را طی می‌کنیم.

این اجرا تا حدودی پیچیده است. ما باید از تایمرهای سخت افزاری استفاده کنیم، زیرا همه مواردی که در اینجا داریم برای عملکرد صحیح به PWM با فرکانس بالا و پایدار نیازمند است. کد در اینجا لینک ضمیمه شده است و می‌توانید از GitHub همچنین منبع شماتیک در Fritzing بارگیری نمایید.

در برنامه ۳ عملکرد وجود دارد که تایمرها را کنترل می‌کنند: setTimer0PWM ،setTimer1PWM ،setTimer2PWM.

هر یک از آن‌ها تایمر را در حالت PWM با پارامترهای داده‌ شده تنظیم می‌کنند (در کد توضیح داده‌ شده است) و عرض پالس را با توجه به مقادیر ورودی تنظیم می­ نمایند.

فازهای اندازه‌گیری با استفاده از توابع startMeasurementPhase و startHeatingPhase تغییر می‌یابند، آن‌ها همه‌ چیز را در داخل کنترل می‌کنند و مقادیر تایمر مناسب را برای جابجایی بین گرمایش ۵ ولت و ۱.۴ ولت تنظیم کنید.

حالت LED ها توسط عملکردها تنظیم می شود. شدت روشنایی سبز و قرمز LED ها از روی مقادیر ورودی خود تعیین خواهد شد (در مقیاس ۱-۱۰۰ به‌صورت خطی).

حالت بازر با استفاده از توابع buzz_on ،buzz_off ،buzz_beep کنترل می شود. این توابع صدا را روشن و خاموش می‌کند، اگر به‌طور دوره‌ای فراخوانی شوند، عملکرد توالی بوق را به مدت‌ زمان ۱.۵ ثانیه تولید می‌کند. این توالی صدایی شبیه بیپ-بیپ و یا آژیر خواهد داشت.

برنامه ابتدا عملکرد pwm_adjust را اجرا می‌کند، که عرض چرخه PWM مناسب برای دستیابی به ۱.۴ ولت در مرحله اندازه‌گیری مطلع شوید. سپس چند بار بوق می‌زند تا نشان دهد که سنسور آماده است، به مرحله اندازه‌گیری می‌رود و حلقه اصلی را شروع می‌کند.

در حلقه اصلی، برنامه بررسی می‌کند که آیا ما زمان کافی را در فاز فعلی گذرانده‌ایم (۹۰ ثانیه برای فاز اندازه‌گیری، ۶۰ ثانیه برای فاز گرم کردن) و اگر بله بود، سپس فاز فعلی را تغییر می‌دهد. همچنین به‌ طور مداوم با استفاده از هموارسازی نمایی، قرائت حسگر را به‌روز می‌کند: new_value = 0.999 * old_value + 0.001 * new_reading با چنین پارامترهایی و چرخه اندازه‌گیری، میانگین سیگنال تقریباً در حدود ۳۰۰ میلی‌ثانیه خواهد بود.

در ادامه کد برنامه قرار دارد. توجه شود که کالیبره نمودن سنسور اندازه گیری برای آلارم مونوکسید کربن تنها با کالیبره نمودن مقادیر PWM خواهد بود. البته اگر یک امکان اندازه گیری و صحه گذاری بر مقدار مونوکسید کربن موجود باشد صحت این محصول دو چندان خواهد شد.

 

 

/*
This code was developed by the_3d6 from Ultimate Robotics (http://ultimaterobotics.com.ua).
License: you can use it for any purpose as long as you don’t claim that you are its author and
you don’t alter License terms and formulations (lines 1-10 of this file).
You can share modifications of the code if you have properly tested their functionality,
including confirming correct sensor response on CO concentrations of 0-30ppm, 100-300ppm and 1000-10000ppm.

If you can improve this code, please do so!
You can contact me at [email protected]
*/

//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!

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.25;
//UPDATED: when checked on a CO meter, it seems that sensor corresponds to
//the datasheet pretty well
}
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 = 134 * R_relation – 35;
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);
}
}

 

 

امیدواریم نحوه ساخت آلارم مونوکسید کربن به وسیله برد آردوینو برای شما مفید بوده باشد.

مجله اینترنتی تحلیلک

0 0 رای ها
امتیازدهی به مقاله
اشتراک در
اطلاع از
0 نظرات
بازخورد (Feedback) های اینلاین
مشاهده همه دیدگاه ها
0
افکار شما را دوست داریم، لطفا نظر دهید.x