Господа, подскажите пожалуйста как программно реализовать следующую задумку: Есть: DHT11, QuadDisplay Нужно: по нажатию на кнопку менять на дисплее температуру или влажность, а при нажатии на кнопку нужно еще и моргнуть светодиодом на 150мс. Вроде бы все очень просто, но никак не могу придумать, как это правильно реализовать. Либо через прерывания (что плохо т.к. кнопку с прерываниями использовать вроде-бы как не хорошо, т.к. любой дребезг будет портить картину), либо еще как.
Вот, с кнопкой разобрался, теперь бы еще понять, как моргать светодиодом при нажатии кнопки: Код (C++): #include "DHT.h" //библиотека для термометра #include "QuadDisplay2.h" //библиотека для дисплея #define BUTTONPIN 2 //кнопка подключена через подягивающий резистор к 2 пину #define DHTPIN 4 //DHT11 подключен к 4 пину #define DHTTYPE DHT11 //да-да, DHT11, никакой другой DHT dht(DHTPIN, DHTTYPE); //ну вы поняли, DHT11 к 4 пину подключили QuadDisplay qd(9); //А дисплей к 9 пину и к аппаратному SPI int buttonState; //сюда мы будем записывать состояние кнопки (нажата или нет) int previous; //предыдущее состояние кнопки bool whatToDisplay; //если true - отображаем температуру, если false - влажность long deltaTime; //разница во времени (нужна для подавления дребезга) long debounce = 200; //время на подавление дребезга float humidity; //сюда пишем влажность float temperature; //сюда - температуру void setup() { qd.begin(); //инициализация дисплея dht.begin(); //инициализация датчика pinMode(BUTTONPIN, INPUT); //кнопка на вход } void loop() { humidity = dht.readHumidity(); //читаем влажность temperature = dht.readTemperature(); //читаем температуру buttonState = digitalRead(BUTTONPIN); //проверяем нажата ли кнопка if (buttonState == HIGH && previous == LOW && millis() - deltaTime > debounce) { //если нажали кнопку, и в прошлом цикле ее не нажимали, и прошло 200мс if (whatToDisplay == false) { //если до этого показывали влажность, то whatToDisplay = true; //показываем температуру } else { //иначе whatToDisplay = false; //показываем влажность } deltaTime = millis(); //фиксируем разницу во времени } if (whatToDisplay == true) { //если нужно показать температуру, то qd.displayTemperatureC(temperature); //берем и показываем } else if (whatToDisplay == false) { //если нужно показать влажность, то qd.displayHumidity(humidity); //тож показываем, чо нет? } previous = buttonState; //фиксируем положение кнопки }
Как вариант можно взять этот прием. Но пролистайте всю тему.http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-chainikov
Это очень здорово, спасибо, я долго вникал, и думаю вникать буду еще долго. Правда здорово! Но, хотелось бы понять, как можно сделать это на Wiring, неужели нельзя сделать это обычной средой Arduino IDE. Буду сверх благодарен, если Вы найдете решение. Заранее спасибо
Ну все в обычной среде Ардуино. Вот только этот рецепт не афишируется Спойлер: код Код (C++): //**/ unsigned long mill;// переменная для millis() typedef void (*pDo)() ;// тип -функция обработчик //------Cl_Led---------------------- // класс светодиод class Cl_Led { protected: const byte pin; bool led; unsigned long past, time; byte state; //0 выкл/ 1 вкл / 2 мигать /*установить в состояние*/ void stand(byte state_) { past = mill; state = state_; switch (state) { case 0: // выкл digitalWrite(pin, led = LOW); break; case 1: // вкл digitalWrite(pin, led = HIGH); break; case 2:// мигать digitalWrite(pin, led = !led); break; case 3:// короткое выключение digitalWrite(pin, led = LOW); break; case 4:// короткое включение digitalWrite(pin, led = HIGH); break; } } public: /*конструктор*/ Cl_Led(byte pin_): pin(pin_) {} /*инициализация-вставить в setup()*/ void init() { pinMode(pin, OUTPUT); OFF(); } /*работа-вставить в loop()*/ void run() { if (state == 2 && mill - past >= time)stand(2); if (state == 3 && mill - past >= time)stand(1); if (state == 4 && mill - past >= time)stand(0); } /*включить*/ void ON() { stand(1); } /*коротко включить*/ void ON(unsigned long time_) { time = time_; stand(4); } /*выключить*/ void OFF() { stand(0); } /*коротко выключить*/ void OFF(unsigned long time_) { time = time_; stand(3); } /*мигать*/ void blink(unsigned long time_ = 200) { time = time_; stand(2); } }; //------Cl_Btn---------------------- // класс кнопка class Cl_Btn { protected: const byte pin; pDo Do;//обработчик bool bounce = 0; bool btn = 1, oldBtn; unsigned long past; public: /*конструктор*/ Cl_Btn(byte pin_, pDo Do_): pin(pin_), Do(Do_) {} /*инициализация-вставить в setup()*/ void init() { pinMode(pin, INPUT_PULLUP); } /*работа-вставить в loop()*/ void run() { bool newBtn = digitalRead(pin); if (!bounce && newBtn != btn) { bounce = 1; past = mill; } if (bounce && mill - past >= 10) { bounce = 0 ; oldBtn = btn; btn = newBtn; if (!btn && oldBtn) Do(); } } }; //-----компоновка---------------------- Cl_Led Led(/*пин*/13); void DoBtn1() { Led.ON(200); Serial.println("DoBtn1"); } void DoBtn2() { Led.OFF(200); Serial.println("DoBtn2"); } void DoBtn3() { Led.blink(); Serial.println("DoBtn3"); } Cl_Btn Btn1(/*пин*/2,/*обработчик*/DoBtn1); Cl_Btn Btn2(/*пин*/3,/*обработчик*/DoBtn2); Cl_Btn Btn3(/*пин*/4,/*обработчик*/DoBtn3); //-----main----------------------- int main() { init(); // setup() Serial.begin(9600); Led.init(); Btn1.init(); Btn2.init(); Btn3.init(); for (;;) { // loop() mill = millis(); Led.run(); Btn1.run(); Btn2.run(); Btn3.run(); } return 0; } /*Скетч использует 2814 байт (9%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 251 байт (12%) динамической памяти, оставляя 1797 байт для локальных переменных. Максимум: 2048 байт. */ ПС: Это обычный Wiring в отличии от "честного Си" (деалект недалеких новичков Ардунистов)
Спасибо, решил проблему значительно проще, боюсь, что сильно на кривокодил, но работает... Спойлер Код (C++): #include "DHT.h" //библиотека для термометра #include "QuadDisplay2.h" //библиотека для дисплея #define BUTTONPIN 2 //кнопка подключена через подягивающий резистор к 2 пину #define LEDPIN 10 //светодиод к 10 пину #define BUZZERPIN 3 //пищалка к 3 пину #define DHTPIN 4 //цифровой пин DHT11 подключен к 4 пину #define DHTTYPE DHT11 //да-да, DHT11, никакой другой DHT dht(DHTPIN, DHTTYPE); //ну вы поняли, DHT11 к 4 пину подключили QuadDisplay qd(9); //а дисплей к 9 пину и к аппаратному SPI int buttonState; //сюда мы будем записывать состояние кнопки (нажата или нет) int previous; //предыдущее состояние кнопки bool whatToDisplay; //если true - отображаем температуру, если false - влажность long deltaTime; //разница во времени (нужна для подавления дребезга) long debounce = 200; //время на подавление дребезга float humidity; //сюда пишем влажность float temperature; //сюда - температуру void setup() { qd.begin(); //инициализация дисплея dht.begin(); //инициализация датчика pinMode(BUTTONPIN, INPUT); //кнопка на вход pinMode(LEDPIN, OUTPUT); //светодиод на выход (хотя хз зачем, там же дальше analogWrite); pinMode(BUZZERPIN, OUTPUT); //тоже не выход (опять хз нужно ли для tone) } void loop() { humidity = dht.readHumidity(); //читаем влажность temperature = dht.readTemperature(); //читаем температуру buttonState = digitalRead(BUTTONPIN); //проверяем нажата ли кнопка if (buttonState == HIGH && previous == LOW && millis() - deltaTime > debounce) { //если нажали кнопку, и в прошлом цикле ее не нажимали, и прошло 200мс if (whatToDisplay == false) { //если до этого показывали влажность, то whatToDisplay = true; //показываем температуру } else { //иначе whatToDisplay = false; //показываем влажность } deltaTime = millis(); //фиксируем разницу во времени blinkSqueak(); //мигаем-пищим, че нет то? } if (whatToDisplay == true) { //если нужно показать температуру, то qd.displayTemperatureC(temperature); //берем и показываем } else if (whatToDisplay == false) { //если нужно показать влажность, то qd.displayHumidity(humidity); //тож показываем, чо нет? } previous = buttonState; //фиксируем положение кнопки } void blinkSqueak() { //мигалка-пищалка analogWrite(LEDPIN, 40); //светодиод на 16 процентов яроксти tone(BUZZERPIN, 4500); //пищим с частотой 4500 delay(50); //продолжаем пищать и светить 50мс analogWrite(LEDPIN, 0); //не светим noTone(BUZZERPIN); //и не пищим }
Почему? В даташите ничего про это не написано. И как это исправить в коде? Спойлер: Так правильно? Код (C++): #include "DHT.h" //библиотека для термометра #include "QuadDisplay2.h" //библиотека для дисплея #define BUTTONPIN 2 //кнопка подключена через подягивающий резистор к 2 пину #define LEDPIN 10 //светодиод к 10 пину #define BUZZERPIN 3 //пищалка к 3 пину #define DHTPIN 4 //цифровой пин DHT11 подключен к 4 пину #define DHTTYPE DHT11 //да-да, DHT11, никакой другой DHT dht(DHTPIN, DHTTYPE); //ну вы поняли, DHT11 к 4 пину подключили QuadDisplay qd(9); //а дисплей к 9 пину и к аппаратному SPI int buttonState; //сюда мы будем записывать состояние кнопки (нажата или нет) int previous; //предыдущее состояние кнопки bool whatToDisplay; //если true - отображаем температуру, если false - влажность long deltaTime1; //разница во времени (нужна для подавления дребезга) long deltaTime2; //для того, чтобы опрашивать датчик реже long debounce = 200; //время на подавление дребезга float humidity; //сюда пишем влажность float temperature; //сюда - температуру void setup() { qd.begin(); //инициализация дисплея dht.begin(); //инициализация датчика Serial.begin(9600); pinMode(BUTTONPIN, INPUT); //кнопка на вход pinMode(LEDPIN, OUTPUT); //светодиод на выход (хотя хз зачем, там же дальше analogWrite); pinMode(BUZZERPIN, OUTPUT); //тоже не выход (опять хз нужно ли для tone) } void loop() { if (millis() - deltaTime2 > 3000) { //если читали данные из датчика больше 3 секунд назад humidity = dht.readHumidity(); //читаем влажность temperature = dht.readTemperature(); //читаем температуру Serial.print(temperature); Serial.print(" "); Serial.println(humidity); deltaTime2 = millis(); //фиксируем разницу во времени } buttonState = digitalRead(BUTTONPIN); //проверяем нажата ли кнопка if (buttonState == HIGH && previous == LOW && millis() - deltaTime1 > debounce) { //если нажали кнопку, и в прошлом цикле ее не нажимали, и прошло 200мс if (whatToDisplay == false) { //если до этого показывали влажность, то whatToDisplay = true; //показываем температуру } else { //иначе whatToDisplay = false; //показываем влажность } deltaTime1 = millis(); //фиксируем разницу во времени blinkSqueak(); //мигаем-пищим, че нет то? } if (whatToDisplay == true) { //если нужно показать температуру, то qd.displayTemperatureC(temperature); //берем и показываем } else if (whatToDisplay == false) { //если нужно показать влажность, то qd.displayHumidity(humidity); //тож показываем, чо нет? } previous = buttonState; //фиксируем положение кнопки } void blinkSqueak() { //мигалка-пищалка analogWrite(LEDPIN, 40); //светодиод на 16 процентов яроксти tone(BUZZERPIN, 4500); //пищим с частотой 4500 delay(50); //продолжаем пищать и светить 50мс analogWrite(LEDPIN, 0); //не светим noTone(BUZZERPIN); //и не пищим } Теперь кнопка тупит, может быть это из-за Serial?
открываем datasheet, там родным по белому написано 3. Each read out the temperature and humidity values are the results of the last measurement For real-time data, sequential read twice, but is not recommended to repeatedly read the sensors, each read sensor interval is greater than 5 seconds can be obtainedaccurate data.
Код (C++): void loop(void) { static long prevTime = 0; long now = millis(); if ((now - prevTime)>5000) { ReadDHT11(); doSomeThing(); prevTime = now; } }
Я бы даже раз в пол минуты-минуту опрашивал датчик. Врятли значение влажности и температуры в помещении существенно меняется за такое время.
я с Вами категорически согласен. Мои уличные температурные датчики (BMP, правда) опрашиваюца раз в 10 минут, вапще. Никакой рояли там это не играет. А в ванной, где от влажности должна включаться вытяжка, то раз в 10 секунд. Всё зависит от задачи.