Прерывания, му
- Войдите на сайт для отправки комментариев
Сб, 27/02/2016 - 18:49
Добрый день! Пилю девайс, который должен каждые полчаса включать реле на 10 минут. При этом он ещё и пишет в лог данные с датчиков каждые 5 минут.
Вопрос вот какой - как правильно реализовать регулярное включение каждые полчаса на 10 минут? Есть RTC подключенное, может через него как-то ещё можно? Прочитал ряд статей с использованием millis(), но одну потерял, там использовалась библиотека Thread, может кто видел - поделится линком? Там похожее организовывалось.
Спасибо!
Здесь на форуме dimax предложил очень хороший код часов. Так вот на его основе можно реализовать посуточное Вк/Вык чего завгодно и в любое время. В Вшем случае это будет вот так
volatile uint8_t minut=0; volatile uint8_t chas=0; volatile uint8_t sec=0; byte op_dat;//Переменная для опроса датчиков byte rele;// Переменная ВК/Вык реле void setup(){ Serial.begin(9600); TCCR1A=(1<<WGM11); //режим14 FAST PWM TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256 ICR1=62499; // (16000000MHz /div256) -1 = 1 раз в секунду TIMSK1=(1<<TOIE1); //разрешить прерывание } ISR (TIMER1_OVF_vect) { sec++ ; //инкремент переменной каждую секунду if (sec>59){ sec=0; minut++; op_dat++; rele++; } if (minut>59){minut=0; chas++; } if (chas>23){chas=0;} } void loop(){ if (op_dat>=5) { op_dat=0; // Здесь опрашуем датчики каждые 5 минут } if (rele>=30) { rele = 0; //Здесь включаем РЕЛЕ на 10 минут } if (rele==10) { // Здесь выключаем Реле через 10 минут } }Добрый день! запустил скетч, но честно говоря не работает.
volatile uint8_t minut=0; volatile uint8_t chas=0; volatile uint8_t sec=0; byte op_dat;//Переменная для РѕРїСЂРѕСЃР° датчиков byte rele;// Переменная Р’Рљ/Вык реле void setup(){ Serial.begin(9600); TCCR1A=(1<<WGM11); //режим14 FAST PWM TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU РЅР° 256 ICR1=62499; // (16000000MHz /div256) -1 = 1 раз РІ секунду TIMSK1=(1<<TOIE1); //разрешить прерывание } ISR (TIMER1_OVF_vect) { sec++ ; //инкремент переменной каждую секунду if (sec>59){ sec=0; minut++; op_dat++; rele++; } if (minut>59){minut=0; chas++; } if (chas>23){chas=0;} } void loop(){ if (op_dat>=5) { op_dat=0; // Здесь опрашуем датчики каждые 5 РјРёРЅСѓС‚ } if (rele>=5) { rele = 0; digitalWrite(3, 0); Serial.println("rele on"); } if (rele==1) { digitalWrite(3, 1); Serial.println("rele run and off"); } }Попробовал вот так, но ни реле не щёлкает, первого вывода в серийный порт нету, а второй постоянно выскакивает, вместо того, чтобы сделать это один раз. Маленькие временные задержки поставил для теста, чтобы не ждать.
Проверил в симуляторе все работает, только задержки выставил на секунды через 5 вк. через 1 вык. для проверки а Вы себе поставте как надо
volatile uint8_t minut=0; volatile uint8_t chas=0; volatile uint8_t sec=0; byte op_dat;//Переменная для опроса датчиков byte rele;// Переменная ВК/Вык реле bool f_rele = 0; #define LEDpin 3 void setup(){ pinMode(LEDpin, OUTPUT); Serial.begin(9600); TCCR1A=(1<<WGM11); //режим14 FAST PWM TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256 ICR1=62499; // (16000000MHz /div256) -1 = 1 раз в секунду TIMSK1=(1<<TOIE1); //разрешить прерывание } ISR (TIMER1_OVF_vect) { sec++ ; //инкремент переменной каждую секунду rele++; if (sec>59){ sec=0; minut++; op_dat++; } if (minut>59){minut=0; chas++; } if (chas>23){chas=0;} } void loop(){ if (op_dat>=5) { op_dat=0; // Здесь опрашуем датчики каждые 5 минут } if (rele>=5) { rele = 0; f_rele = 1; digitalWrite(LEDpin, 1); Serial.println("rele on"); //Здесь включаем РЕЛЕ на 10 минут } if (rele==1 && f_rele==1) { f_rele = 0; digitalWrite(LEDpin, 0); Serial.println("rele run and off"); // Здесь выключаем Реле через 10 минут } }Зачем Вы в преравания полезли? Это вещи не того масштаба, как Ваша задача. Про RTC - забыть, у Вас же нет требования произвести действие в заданное время. Про Thread тоже забыть, если вспомните где читали - напишите сюда шоб другие туда случайно не зашли.
Читать стати про millis() до просветления, чередовать с чтением тем про применение millis() для отсчета промежутков с этого форума. Их тут легион.
В общем всё равно не получается :(
#include <DHT.h> #include <BH1750.h> #include <DallasTemperature.h> #include <OneWire.h> #include <RTC.h> #include <SD.h> #include <SPI.h> #include <Wire.h> DHT sensor; int result; BH1750 lightMeter; RTC time; //relay section #define RELAY_ON 0 #define RELAY_OFF 1 // #define PUMP_1 3 // Arduino Digital I/O pin number #define PUMP_2 4 #define LIGHT 5 #define Relay_4 6 //Thread logThread = Thread(); // создаём поток управления логом //Thread pumpThread = Thread(); // создаём поток управления поливом #define ONE_WIRE_BUS 10 // номер пина к которому подключен DS18B20 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); volatile uint8_t minut=0; volatile uint8_t chas=0; volatile uint8_t sec=0; byte op_dat;//Переменная для опроса датчиков byte rele;// Переменная ВК/Вык реле bool f_rele = 0; void setup(){ pinMode(53, OUTPUT); lightMeter.begin(); Serial.begin(9600); SD.begin(53); delay(1000); time.begin(RTC_DS1307); Serial.println("pump checking start"); pinMode(PUMP_1, OUTPUT); delay(1000); pinMode(PUMP_2, OUTPUT); delay(1000); pinMode(LIGHT, OUTPUT); delay(1000); pinMode(Relay_4, OUTPUT); delay(1000); digitalWrite(PUMP_1, RELAY_OFF); delay(1000); digitalWrite(PUMP_2, RELAY_OFF); delay(1000); digitalWrite(LIGHT, RELAY_OFF); delay(1000); digitalWrite(Relay_4, RELAY_OFF); // ////---( THEN set pins as outputs )---- Serial.println("pump checking complete"); //pinMode(Relay_4, OUTPUT); delay(4000); //Check that all relays are inactive at Reset // logThread.onRun(logging); // назначаем потоку задачу // logThread.setInterval(1000); // задаём интервал срабатывания, мсек // // pumpThread.onRun(pump); // назначаем потоку задачу // pumpThread.setInterval(20); // задаём интервал срабатывания, м Serial.println("timer setup start"); sensors.begin(); TCCR1A=(1<<WGM11); //режим14 FAST PWM TCCR1B=(1<<CS12)|(1<<WGM13)|(1<<WGM12); //делить частоту CPU на 256 ICR1=62499; // (16000000MHz /div256) -1 = 1 раз в секунду TIMSK1=(1<<TOIE1); //разрешить прерывание Serial.println("timer setup complete"); } ISR (TIMER1_OVF_vect) { sec++ ; //инкремент переменной каждую секунду Serial.println(sec); rele++; if (sec>59){ sec=0; minut++; op_dat++; } if (minut>59){minut=0; chas++; } if (chas>23){chas=0;} } void loop(){ if (op_dat>=3) { Serial.println("sensor read start"); sensors.requestTemperatures(); Serial.println(String(sensors.getTempCByIndex(0) , 1)); String dataString = ""; result = sensor.read(2); // нужно указать № вывода (сейчас 2pin) uint16_t lux = lightMeter.readLightLevel(); dataString = ";"+String(sensor.tem)+";"+String(sensor.hum)+";"+String(lux); Serial.print(time.gettime("d-m-Y, H:i:s")); File dataFile = SD.open("datalog.txt", FILE_WRITE); if (dataFile) { dataFile.println(dataString); dataFile.close(); // print to the serial port too: Serial.println(dataString); } // if the file isn't open, pop up an error: else { Serial.println("error opening datalog.txt"); } op_dat=0; } if (rele>=24) { rele = 0; f_rele = 1; Serial.println("rele on"); digitalWrite(PUMP_1, RELAY_ON); } if (rele==1 && f_rele==1) { f_rele = 0; digitalWrite(PUMP_1, RELAY_OFF); Serial.println("rele runned and off"); // Здесь выключаем Реле через 10 минут } //if (lux <= 150 && time.Hours > 9 && time.Hours < 22 ) //{ digitalWrite(LIGHT, RELAY_ON);} //else {digitalWrite(LIGHT, RELAY_OFF);} }Срабатывает каждые 24 секунды и через секунду отключается...
Вроде с реле разобрадся, а вот опрос датчиков не срабатывает...
Да-да-да, разобрался, в том числе и с опросом датчиков, спасибо!
Апну тему (( переделал под RTC, но блин, оно не включается в нужное время ((( почему так? Модуль рабочий, батарейку поменял, после вкл-выкл не сбрасывает время тоже. Но не срабатывает(( Вот листинг (что-то закоментировано, это под дальнейшее развитие):
#include <DallasTemperature.h> #include <OneWire.h> #include <BH1750.h> #include <RTC.h> #include <SD.h> #include <SPI.h> #include <DHT.h> #include <Wire.h> DHT sensor; int result; BH1750 lightMeter; RTC time; //relay section #define RELAY_ON 0 #define RELAY_OFF 1 // #define PUMP_1 3 // Arduino Digital I/O pin number #define PUMP_2 4 #define LIGHT 5 #define Relay_4 6 #define ONE_WIRE_BUS 10 // номер пина к которому подключен DS18B20 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); volatile uint8_t minut = 0; volatile uint8_t sec = 0; byte op_dat;//Переменная для опроса датчиков void setup() { pinMode(53, OUTPUT); lightMeter.begin(); Serial.begin(9600); SD.begin(53); delay(1000); time.begin(RTC_DS1307); //time.settime(0,49,16,18,06,16,5); // 0 сек, 17 мин, 15 час, 1, октября, 2015 года, четверг Serial.println(time.gettime("d.m.Y H:i")); pinMode(PUMP_1, OUTPUT); delay(1000); pinMode(PUMP_2, OUTPUT); delay(1000); pinMode(LIGHT, OUTPUT); delay(1000); pinMode(Relay_4, OUTPUT); delay(1000); digitalWrite(PUMP_1, RELAY_OFF); delay(1000); digitalWrite(PUMP_2, RELAY_OFF); delay(1000); digitalWrite(LIGHT, RELAY_OFF); delay(1000); digitalWrite(Relay_4, RELAY_OFF); // ////---( THEN set pins as outputs )---- //pinMode(Relay_4, OUTPUT); delay(4000); //Check that all relays are inactive at Reset TCCR1A = (1 << WGM11); //режим14 FAST PWM TCCR1B = (1 << CS12) | (1 << WGM13) | (1 << WGM12); //делить частоту CPU на 256 ICR1 = 62499; // (16000000MHz /div256) -1 = 1 раз в секунду TIMSK1 = (1 << TOIE1); //разрешить прерывание Serial.println("timer setup complete"); } ISR (TIMER1_OVF_vect) { sec++ ; //инкремент переменной каждую секунду if (sec > 59) { sec = 0; minut++; op_dat++; } if (minut > 59) { minut = 0; } } void loop() { if (op_dat >= 5) { Serial.println("sensor read start"); //sensors.requestTemperatures(); // Serial.println(String(sensors.getTempCByIndex(0) , 1)); String dataString = ""; // result = sensor.read(2); // нужно указать № вывода (сейчас 2pin) uint16_t lux = lightMeter.readLightLevel(); dataString = String(time.gettime("d.m.Y H:i")) + ";" + String(sensor.tem) + ";" + String(sensor.hum) + ";" + String(lux); File dataFile = SD.open("datalog.txt", FILE_WRITE); if (dataFile) { dataFile.println(dataString); dataFile.close(); // print to the serial port too: Serial.println(dataString); } // if the file isn't open, pop up an error: else { Serial.println("error opening datalog.txt"); } op_dat = 0; } // if (sensor.tem >= 25) { digitalWrite(PUMP_1, RELAY_ON);} else if (sensor.tem < 23) {digitalWrite(PUMP_1, RELAY_OFF);} //тест реле на температуру // // if (lux >= 150) { digitalWrite(LIGHT, RELAY_ON);} else {digitalWrite(LIGHT, RELAY_OFF);} // //включение света в нужное время при отсутствии достаточной освещённости и при времени с 8 до 20 (работает)! // if (lux <= 150 && time.Hours > 9 && time.Hours < 22 ) if (time.Hours == 9 && time.minutes == 00 || time.Hours == 12 && time.minutes == 45 || time.Hours == 17 && time.minutes == 25 || time.Hours == 20 && time.minutes == 00) { digitalWrite(PUMP_1, RELAY_ON); Serial.println("rele on"); } if (time.Hours == 9 && time.minutes == 15 || time.Hours == 13 && time.minutes == 00 || time.Hours == 17 && time.minutes == 40 || time.Hours == 20 && time.minutes == 15) { digitalWrite(PUMP_1, RELAY_OFF); Serial.println("rele off"); } //Serial.println(time.gettime("d-m-Y, H:i:s, D")); }