Детектор сигаретного дыма на ATtiny13A и MQ-2
- Войдите на сайт для отправки комментариев
Вс, 31/03/2013 - 18:49
Простенький детектор сигаретного дыма на ATtiny13A и датчике и MQ-2.
При запахе сигаретного дыма, загораются светодиоды. При слабом уровне горит 1, среднем - 2 и максимальном 3, если воздух чист --- ничего не горит ))).
void setup() {
DDRB = 0b10111;
}
void loop() {
int sensorValue = ADC_READ();
int range = map(sensorValue, 100, 135, 0, 3);
switch (range) {
case 1:
PORTB &= ~(1<<0);
PORTB &= ~(1<<1);
PORTB &= ~(1<<2);
break;
case 2:
PORTB |= (1<<0);
PORTB &= ~(1<<1);
PORTB &= ~(1<<2);
break;
case 3:
PORTB |= (1<<0);
PORTB |= (1<<1);
PORTB &= ~(1<<2);
break;
case 4:
PORTB |= (1<<0);
PORTB |= (1<<1);
PORTB |= (1<<2);
break;
}
}
int ADC_READ()
{
ADMUX = 3; // ADC pin
ADCSRA |= 1<<ADEN;
ADCSRA |= 1<<ADSC;
while(!(ADCSRA & (1<<ADIF)));
ADCSRA |= 1<<ADIF;
byte low = ADCL;
byte high = ADCH;
ADCSRA &= ~(1 << ADEN);
return (high << 8) | low;
}
За оптимизацию кода отдельное спасибо HWman
Binary sketch size: 802 bytes
Забавно, range мапится в значение от 0 до 3, а switch от 1 до 4 работает, неувязочка, однако.
Так ещё меньше весить будет:
int main( void ) { DDRB = 0b10111; while(1){ int sensorValue = ADC_READ(); int range = ((sensorValue - 79) / 14); //int range = map(sensorValue, 100, 135, 1, 4); switch (range) { case 1: // your hand is on the sensor PORTB &= ~(1<<0); PORTB &= ~(1<<1); PORTB &= ~(1<<2); break; case 2: // your hand is close to the sensor PORTB |= (1<<0); PORTB &= ~(1<<1); PORTB &= ~(1<<2); break; case 3: // your hand is a few inches from the sensor PORTB |= (1<<0); PORTB |= (1<<1); PORTB &= ~(1<<2); break; case 4: // your hand is nowhere near the sensor PORTB |= (1<<0); PORTB |= (1<<1); PORTB |= (1<<2); break; } return 0; } } int ADC_READ() { ADMUX = 3; // ADC pin ADCSRA |= 1<<ADEN; ADCSRA |= 1<<ADSC; while(!(ADCSRA & (1<<ADIF))); ADCSRA |= 1<<ADIF; byte low = ADCL; byte high = ADCH; ADCSRA &= ~(1 << ADEN); // отключаем АЦП return (high << 8) | low; }Размер скетча в двоичном коде: 268 байт (из 1 024 байт максимум)
сорри, правильно так
не тот скетч залил ...
Вот интересно, если я определил тип данных int, целое число вроде, ну и по расчётах должно выйти 1.5 тогда какое число запишется в переменную 1 или 2? В школе помню учили что 1.5 это равно 2, а как же микропроцессоров учили в школе?
Вот интересно, если я определил тип данных int, целое число вроде, ну и по расчётах должно выйти 1.5 тогда какое число запишется в переменную 1 или 2? В школе помню учили что 1.5 это равно 2, а как же микропроцессоров учили в школе?
"микропроцессоров" учили целочисленной двоичной арифметике.
Грубо:
29/5=5 и 4 в остатке (а не 5,8 -> 6)
Ясно, спасибо :)
Ардуино IDE оптимизирует код? Вычисляет константы при компиляции? Если нет, то можно ещё с десяток байт флеш памяти съэкономить если их вычислить все, то есть заменить:
~(1<<0) на 0b11111110
~(1<<1) на 0b11111101 и так далее. Наглядность пострадает, хотя с какой стороны смотреть.
В case 4 можно написать одной строкой: PORTB |= 0b00000111;
и в 1 тоже по аналогии.
Спасибо, информативно ...
int main( void ) { DDRB = 0b10111; while(1){ unsigned int sensorValue = ADC_READ(); unsigned int range = ((sensorValue - 79) / 14); //int range = map(sensorValue, 100, 135, 1, 4); switch (range) { case 1: // your hand is on the sensor PORTB &= ~0b111; break; case 2: // your hand is close to the sensor PORTB |= (1<<0); PORTB &= ~(1<<1); PORTB &= ~(1<<2); break; case 3: // your hand is a few inches from the sensor PORTB |= (1<<0); PORTB |= (1<<1); PORTB &= ~(1<<2); break; case 4: // your hand is nowhere near the sensor PORTB |= 0b111; break; } return 0; } } int ADC_READ() { ADMUX = 3; // ADC pin ADCSRA |= 1<<ADEN; ADCSRA |= 1<<ADSC; while(!(ADCSRA & (1<<ADIF))); ADCSRA |= 1<<ADIF; byte low = ADCL; byte high = ADCH; ADCSRA &= ~(1 << ADEN); // отключаем АЦП return (high << 8) | low; }Размер скетча в двоичном коде: 232 байт (из 1 024 байт максимум).
Как-то так? Или чёт напартачил, я засветил что изменил
если заказчик согласен изменить схему, то можно ещё значительно уменьшить объём программы, заменив весь блок swith на две строки.
всего два светодиода л1 и л2. при нулевом уровне все выключены. уровень 1 включён л1, уровень 2 включён л2, уровень 3 включены оба.
byte range = ..... // тут допустимые значения 0..3
PORTB &= 0b11111100; // обнулили 2 бита
PORTB |= range; // включили светодиодики
вариант для схемы с тремя светиками
byte range = ..... // тут допустимые значения 0..3
PORTB &= 0b11111000; // обнулили 3 бита
while(range--)
PORTB |= 1<<range; // включили светодиодики
Я вот что думаю, а есть ли смысл делать код неузнаваемым для ардуиновцев? памяти ещё ого-го остаётся...
Ну для наглядности - не спорю, хорошо, оптимизация это всегда хорошо, на нужно же думать и о других...
Всем привет. Помогите, пожалуйста, чайнику! Нужно собрать детектор табачного дыма, есть платформа Arduino Uno и датчик MQ2. Как мне доработать данный код, чтоб на выходи получить аналоговый сигнал (или загорался диод) при среднем и максимальном уровни дыма. Так же, просьба объяснить к каким контактам нужно подключать диод? Спасибо!
#define led1 10 // 1 светодиод #define led2 11 // 2 светодиод #define led3 12 // 3 светодиод #define analogInPin A0 // датчик void setup() { pinMode(analogInPin, INPUT); pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); pinMode(led3, OUTPUT); } void loop() { int sensorValue = analogRead(analogInPin); int range = map(sensorValue, 100, 135, 1, 4); switch (range) { case 1: digitalWrite(led1, LOW); digitalWrite(led2, LOW); digitalWrite(led3, LOW); break; case 2: digitalWrite(led1, HIGH); digitalWrite(led2, LOW); digitalWrite(led3, LOW); break; case 3: digitalWrite(led1, HIGH); digitalWrite(led2, HIGH); digitalWrite(led3, LOW); break; case 4: digitalWrite(led1, HIGH); digitalWrite(led2, HIGH); digitalWrite(led3, HIGH); break; } }сорри, правильно так
не тот скетч залил ...
Спасибо большое. А еще вопросик, вот выше писали, что значение int range надо поменять, это критично или можно оставить как вы прислали?
Честно говоря нет времени разбираться, но смысл в том, что если range, от 0 до 3, то и switch, должен работать от 0 до 3, а если использовать switch от 1 до 4 то достаточно к range добавить 1. Но как правильно - Вам виднее
Интересный и очень актуальный проект. Но интересна чуствительность данного устройства.
У нас в офисе курят в туалете (хотя и ЗАПРЕЩЕНО), высота потолка под 3 метра. Если устройство будет под потолком, сработает ли оно?
Интересный и очень актуальный проект. Но интересна чуствительность данного устройства.
У нас в офисе курят в туалете (хотя и ЗАПРЕЩЕНО), высота потолка под 3 метра. Если устройство будет под потолком, сработает ли оно?
Однозначно сработает. Правда есть нюанс : на свежевыкрашенную дверь тоже сработает, на определенную концентрацию туалеточистящей химии тоже. Даже на хороший перегар сработает :)
С избирательностью у датчиков серии MQ не очень, хотя за такие деньги что бы мы хотели ?
И еще, просто мерять абсолютный уровень загрязненности воздуха - не лучший подход. Утром и вечером, летом и зимой, до и после уборки, и т.д. - он будет разный. Лучше мерять относительные изменения уровня в течение, например, последней минуты (пяти, десяти минут) и отслеживать резкие колебания уровня от некой средней величины.
И еще, просто мерять абсолютный уровень загрязненности воздуха - не лучший подход. Утром и вечером, летом и зимой, до и после уборки, и т.д. - он будет разный. Лучше мерять относительные изменения уровня в течение, например, последней минуты (пяти, десяти минут) и отслеживать резкие колебания уровня от некой средней величины.
Возможно для данного случая так лучше, практика покажет.
#define led1 10 // 1 светодиод #define led2 11 // 2 светодиод #define led3 12 // 3 светодиод #define analogInPin A0 // датчик void setup() { pinMode(analogInPin, INPUT); pinMode(led1, OUTPUT); pinMode(led2, OUTPUT); pinMode(led3, OUTPUT); } void loop() { int sensorValue = analogRead(analogInPin); int range = map(sensorValue, 100, 135, 1, 4); switch (range) { case 1: digitalWrite(led1, LOW); digitalWrite(led2, LOW); digitalWrite(led3, LOW); break; case 2: digitalWrite(led1, HIGH); digitalWrite(led2, LOW); digitalWrite(led3, LOW); break; case 3: digitalWrite(led1, HIGH); digitalWrite(led2, HIGH); digitalWrite(led3, LOW); break; case 4: digitalWrite(led1, HIGH); digitalWrite(led2, HIGH); digitalWrite(led3, HIGH); break; } }Привет, подскажите, а можно настроить датчик чтоб он был еще более чувствительным? Сейчас диод, подключенный к выходу 10, загорается если на него выдыхать дым в течении пол минуты. Какие значения поменять для эксперимента с чувствительностью? Спасибо!
Выведите в окно терминала Serial.println(analogRead(analogInPin)); и посмотрите, как значения меняются в присутствии дыма, поэкспериментируйте, посмотрите, какие идут цифры с пина (датчика). А дальше сами увидите.
Подключи датчик к дуинке и подключи датчик, и смотри что показывает датчик в разных ситуациях:
void setup() { Serial.begin(9600); } void loop() { // read the input on analog pin 0: int Value = analogRead(A0); Serial.println(Value); delay(500); }Потом выставишь сколько тебе нужно в:
Какой резистор у Вас подключен к датчику, если переменный то в каком положении ??? От этого и зависит чуствительность...
Постоянный резистор на 220 Ом, поэксперементировал с значениями датчика, вроде стало чувствительней, всем большое спасибо за помощь
Пожалуйста, удачных проектов :)
А кто-нибудь сделал хотя бы прототип ? Хотелось бы ознакомиться.
Кроме датчика MQ, есть ли другие?
Можно схему подключения?