Не используем delay
- Войдите на сайт для отправки комментариев
Ср, 18/04/2012 - 01:40
Доброго времени суток.
затеял проект прогенератора.
железки простые
датчик давления mpx 5050
пару тэнов через медленый шим
клапан на долив воды ( пока нет )
простенький кодик
#include <LiquidCrystal.h> //бибилиотека экрана LiquidCrystal lcd(78, 79, 80, 81, 82, 83); //распиновка дисплея /* распиновка */ int mpxPin = 9; //вход MPX // переменные int mpx; // датчик давления int mpx_a[2] = {120,130}; // массив для мин и макс значений int temp; // pt 100 float pkPa; // Давление в kPa unsigned long currentTime; unsigned long loopTime; void setup() { lcd.begin(16, 2); // подключаем дисплей (col,row): Serial.begin(9600); // подключаем серийый порт pinMode(9, OUTPUT); // устанавливаем 9 ногу как выход тэна pinMode(10, OUTPUT); // устанавливаем 10 ногу как выход тэна } void loop() { // Время задерки и круга currentTime = millis(); // считываем время, прошедшее с момента запуска программы if(currentTime >= (loopTime + 500)){ // задержа на 0.5 mc loopTime = currentTime; /* считываем датчики */ mpx = (float)analogRead(mpxPin); // читаем данные с MPX pkPa = (mpx/(float)1023-0.04)/0.018;//персчитываем в kPa digitalWrite(9, LOW); // устанавливаем значение на 9 ножке digitalWrite(10, HIGH); // устанавливаем постоянный выход на 10 ножке /* управление нагревом */ if (mpx < mpx_a[0]){ // если на датчике меньше чем в первое значение массива full_power(); //полный газ } if (mpx >= mpx_a[0] && mpx < mpx_a[1]){ //если на датчике больше второго значения массива low_power(); //даём ограничение по времени } if (mpx > mpx_a[1]){ //если на датчике больше третьего значения массива off_power(); // отключаем тен } /* показываем значения на экране */ lcd.clear(); lcd.setCursor(0,0); lcd.print(pkPa + ' kPa ' + mpx); lcd.setCursor(0,1); //lcd.setCursor(9,1); //lcd.print(power); //lcd.print(" br"); /* Шлём в серийник */ //Serial.print(pkPa + 'kPa ' + mpx + 'mpx ' + power); //Serial.println(' '); Serial.print(pkPa); Serial.print("kPa "); Serial.print(mpx); Serial.println("mpx "); //Serial.println(temp); } } void full_power() { digitalWrite(9, HIGH); } void low_power(){ digitalWrite(9, HIGH); delay(700); digitalWrite(9, LOW); delay(300); } void off_power() { digitalWrite(9, LOW); }
вродебы всё работает но не нравится использование функции delay
void low_power(){ digitalWrite(9, HIGH); delay(700); digitalWrite(9, LOW); delay(300); }
система подвисает. в данном конкретном случее вроде-бы не важно.
но если установить долив воды задержки могут быть по 3-5 секунд.
все найденные примеры с использованием millis имеют равную длинну вкл и выкл, а это не мой случай.
Чутье вас не обмануло :) delay хорош в простеньких системах, когда не нужно "изображать многозадачность".
Без delay() это делается примерно так:
1. Объявлем глобальную переменную unsigned long offTime; // время когда датчик нужно выключить
2. Когда включили нагрев, делаем offTime=millis()+700; // высчитали время когда датчик нужно будет выключить. Через 700 милисекунд
3. Между строчкой 31 и 32 вставляем if(currentTime>=offTime){digitalWrite(9, LOW);} // время пришло - выключаем
В функции full_power, кроме digitalWrite(9, HIGH) делаем offTime=4294967295; // выключить в далеком будущем
Что-бы не происходило выключения "по времени".
Ну и в функции off_power, можно, но не обязательно вместо digitalWrite(9,LOW) написать просто offTime=0;// давно пора выключить
Ну или, опять-таки, по вкусу, я бы вместо трех функций full_power(), low_power(),off_power()
написал одну, принимающую параметр на сколько времени нужно включить power.
Что-то типа такого
Ну и еще, если устройство будет работать, не выключаясь долго. Нужно не забыть предусмотреть переполнение millis(). Примерно 49 дней и он переполнится. Логика "поломается". Так что где-то на 40-вой - нужно думать как его ресетить, или усложнять логику для "перехода через 0".
Большое спасибо за ответ
по первому варианту скеч получался рабочий но есть нюанс
offTome не может быть больше или равно loopTime
иначе не работает
может я не правильно строки расположил?
со вторым вариантом пока пытаюсь понять
>offTome не может быть больше или равно loopTime
Честно говоря, не вижу для этого причин. Они друг-друга вообще никак не касаются. Нигде не сравниваются. If-ы зависящие от них - не вложены друг в друга.
>может я не правильно строки расположил?
Да нет. Вроде правильно, только в low_power(), ради которой все и затевалось, вы включили нагреватель, а установить время "когда его нужно будет выключить" - забыли (второй пункт моих объяснений). Следовательно, если перед ней вызывался full_power - нагреватель включится "навсегда", а если предыдущим вызовом был off_power() - выключится сразу, при следующем же проходе loop().
Туда (в 68-ю строку) еще нужно добавить строку
offTime=millis()+700; // высчитали время когда датчик нужно будет выключить. Через 700 милисекунд
offTime=millis()+700; // высчитали время когда датчик нужно будет выключить. Через 700 милисекунд
добавил, работает красиво
но
low_Power срабатывает правильно только если offTime меньше loopTime
чудеса
"и кроме мордобития - никаких чудес" (С) В.С.Высоцкий ;)
Все должно работать правильно.
Смотрите что происходит.
Если вы ставите задержку 300. А датчики у вас опрашиваются раз в 500. То нагреватель успевает отработать положенное ему время до следующего опроса датчиков.
Если же вы задержку выставили в 3000. То он включится. Но через 500 милисекунд, произойдет опрос датчиков, и, например, например сработает условие в строчке 55. Произойдет вызов power_off(), который "затрет" наше предыдущие решение "греть 3000". Он скажет "уже пора выключать, температура слишком большая".
IMHO это наиболее правильно-безопастное поведение. Текущие состоянии датчиков имеет приоритет над "прошлыми решениями".
Ну можно, разве что добавить в строчку 51 условие, что-бы она срабатывала только если нагреватель выключен, и не "обновляла время" если он уже включен.
if (offTime==0 && (mpx >= mpx_a[0] && mpx < mpx_a[1]))
Если же вы хотите "раз решили греть 3000, то греем 3000 что-бы не происходило на датчиках", вам нужно будет завести еще одну переменную "флаг". Которой можно временно отключать опрос датчиков. В lowpower ее "взводить" offMpx=1
в строчке 34 сбрасывать ее offMpx=0, а в строчке 35 добавить еще одно условие if(!offMpx && .....