Помогите с циклом do...wile
- Войдите на сайт для отправки комментариев
Чт, 19/05/2016 - 11:45
Не могу написать условие для программы, выполняется цикл установки температуры, но как написать условие (wile) выход из цикла и сохранение уставки температуры EEPROM.
Текст программы:
// Подключаем библиотеку для работы с шиной OneWire // Термометр будет подключен на Pin2 #include <OneWire.h> #include <Wire.h> OneWire oneWire(2); //Подключаем библиотеку для работы с термометром #include <DallasTemperature.h> //Создаем объект sensors, подключенный по OneWire DallasTemperature sensors(&oneWire); //Создаем переменные для работы с термометром DeviceAddress tempDeviceAddress; //переменная для хранения адреса датчика float temp1=0; //переменная для текущего значения температуры int setTmp=0; // переменная для заданного значения температуры //Подключаем LCD-дисплей #include <LiquidCrystal_I2C.h> LiquidCrystal_I2C lcd(0x20,16,2); // Задаем адрес и размерность дисплея. //Подсветка управляется через пин D11 #define BACKLIGHT_PIN 11 //Создаем переменную для хранения состояния подсветки boolean backlightStatus = 1; // Подключаем библиотеку для работы с ARDUINO EEPROM //Заданная температура будет храниться по адресу 0 #include <EEPROM2.h> //Реле подключено к пину D10 #define RELAY_PIN 10 //Объявим переменную для хранения состояния реле boolean relayStatus1=LOW; //Объявим переменные для задания задержки long previousMillis1 = 0; long interval1 = 1000; // интервал опроса датчиков температуры //Аналоговая клавиатура подключена к пину A0 #define KEYPAD_PIN A0 //Определим значения на аналоговом входе для клавиатуры int button; const int BUTTON_NONE = 0; const int BUTTON_RIGHT = 1; const int BUTTON_UP = 2; const int BUTTON_DOWN = 3; const int BUTTON_LEFT = 4; const int BUTTON_SELECT = 5; int getPressedButton() { int buttonValue = analogRead(0); // Считываем значения с аналогового входа(A0) if (buttonValue < 100) { return BUTTON_RIGHT; } else if (buttonValue < 200) { return BUTTON_UP; } else if (buttonValue < 400){ return BUTTON_DOWN; } else if (buttonValue < 600){ return BUTTON_LEFT; } else if (buttonValue < 800){ return BUTTON_SELECT; } return BUTTON_NONE; } void setup() { //Настроим пин для управления реле pinMode(RELAY_PIN,OUTPUT); digitalWrite(RELAY_PIN,LOW); //Считаем из постоянной памяти заданную температуру setTmp=EEPROM_read_byte(0); //Инициализируем термодатчик и установим разрешающую способность 12 бит (обычно она установлена по умолчанию, так что последнюю строчку можно опустить) sensors.begin(); sensors.getAddress(tempDeviceAddress, 0); sensors.setResolution(12); //Настроим подсветку дисплея pinMode(BACKLIGHT_PIN, OUTPUT); digitalWrite(BACKLIGHT_PIN, backlightStatus); //Выведем на дисплей стартовое сообщение на 2 секунды lcd.init(); lcd.setCursor(0, 0); lcd.print("Temp. Controller"); lcd.setCursor(0, 1); lcd.print(" v1.0 "); delay(2000); // выведем на дисплей заданное значение температуры на 2 секунды lcd.setCursor(0, 1); lcd.print(" Set temp: "); lcd.setCursor(12,1); lcd.print(setTmp); delay(2000); //Очистим дисплей lcd.begin(16, 2); } //Определим функцию для опроса аналоговой клавиатуры //Функция опроса клавиатуры, принимает адрес пина, к которому подключена клавиатура, и возвращает код клавиши: int ReadKey(int keyPin) { int KeyNum=0; int KeyValue1=0; int KeyValue2=0; //Читаем в цикле аналоговый вход, для подавления дребезга и нестабильности читаем по два раза подряд, пока значения не будут равны. //Если значения равны 1023 – значит не была нажата ни одна клавиша. do { KeyValue1=analogRead(keyPin); KeyValue2=analogRead(keyPin); } while (KeyValue1==KeyValue2&&KeyValue2!=1023); //Интерпретируем полученное значение и определяем код нажатой клавиши //Возвращаем код нажатой клавиши return KeyNum; } //Определим процедуру редактирования заданной температуры //Вызывается по нажатию клавиши Select, отображает на дисплее заданную температуру и позволяет изменять ее клавишами Up и Down void setTemperature() { int keyCode=0; //выводим на дисплей заданное значение температуры lcd.begin(16,2); lcd.setCursor(0, 0); lcd.print(" Setting temp "); lcd.setCursor(7, 1); lcd.print(setTmp); //Опрашиваем клавиатуру, если нажата клавиша Up увеличиваем значение на 1, если Down – уменьшаем на 1 //Если нажаты клавиши Select или Right – цикл опроса прерывается //Задержки введены для борьбы с дребезгом, если клавиши срабатывают четко – можно уменьшить время задержек или вообще их убрать do { button = getPressedButton(); switch (button) { case BUTTON_UP: setTmp++;delay(200);lcd.setCursor(7, 1);lcd.print(setTmp); break; case BUTTON_DOWN: setTmp--;delay(200);lcd.setCursor(7, 1);lcd.print(setTmp); break; } }while (BUTTON_SELECT && BUTTON_RIGHT); delay(200); //По клавише Select – созраняем в EEPROM измененное значение //По клавише Right – восстанавливаем старое значение button = getPressedButton(); switch (button) { case BUTTON_SELECT: EEPROM_write_byte(0, setTmp); break; case BUTTON_RIGHT: setTmp = EEPROM_read_byte(0); } } void loop() { //Модуль опроса датчиков и получения сведений о температуре //Вызывается 1 раз в секунду unsigned long currentMillis1 = millis(); if(currentMillis1 - previousMillis1 > interval1) { previousMillis1 = currentMillis1; //Запуск процедуры измерения температуры sensors.setWaitForConversion(false); sensors.requestTemperatures(); sensors.setWaitForConversion(true); delay(750); // задержка для обработки информации внутри термометра, в данном случае можно не задавать //Считывание значения температуры sensors.getAddress(tempDeviceAddress, 0); temp1=sensors.getTempC(tempDeviceAddress); // Вывод текущего значения температуры на дисплей lcd.setCursor(0, 0); lcd.print(" Current temp "); lcd.setCursor(5, 1); lcd.print(temp1); // Serial.println(temp1,4); } //Проверка условия включения/выключения нагревателя if (temp1<setTmp&&relayStatus1==LOW){relayStatus1=HIGH; digitalWrite(RELAY_PIN,HIGH);} if (temp1>setTmp&&relayStatus1==HIGH){relayStatus1=LOW; digitalWrite(RELAY_PIN,LOW);} // Опрос клавиатуры button = getPressedButton(); switch (button) { case BUTTON_UP: backlightStatus=1;delay(200);digitalWrite(BACKLIGHT_PIN, backlightStatus); break; case BUTTON_DOWN: backlightStatus=0;delay(200);digitalWrite(BACKLIGHT_PIN, backlightStatus); break; case BUTTON_SELECT: delay(200);setTemperature(); } }
Проблемный участок:
void setTemperature() { int keyCode=0; //выводим на дисплей заданное значение температуры lcd.begin(16,2); lcd.setCursor(0, 0); lcd.print(" Setting temp "); lcd.setCursor(7, 1); lcd.print(setTmp); //Опрашиваем клавиатуру, если нажата клавиша Up увеличиваем значение на 1, если Down – уменьшаем на 1 //Если нажаты клавиши Select или Right – цикл опроса прерывается //Задержки введены для борьбы с дребезгом, если клавиши срабатывают четко – можно уменьшить время задержек или вообще их убрать do { button = getPressedButton(); switch (button) { case BUTTON_UP: setTmp++;delay(200);lcd.setCursor(7, 1);lcd.print(setTmp); break; case BUTTON_DOWN: setTmp--;delay(200);lcd.setCursor(7, 1);lcd.print(setTmp); break; } } //По клавише Select – созраняем в EEPROM измененное значение //По клавише Right – восстанавливаем старое значение while (BUTTON_SELECT && BUTTON_RIGHT); delay(200); button = getPressedButton(); switch (button) { case BUTTON_SELECT: EEPROM_write_byte(0, setTmp); break; case BUTTON_RIGHT: setTmp = EEPROM_read_byte(0); } } void loop() { //Модуль опроса датчиков и получения сведений о температуре //Вызывается 1 раз в секунду unsigned long currentMillis1 = millis(); if(currentMillis1 - previousMillis1 > interval1) { previousMillis1 = currentMillis1; //Запуск процедуры измерения температуры sensors.setWaitForConversion(false); sensors.requestTemperatures(); sensors.setWaitForConversion(true); delay(750); // задержка для обработки информации внутри термометра, в данном случае можно не задавать //Считывание значения температуры sensors.getAddress(tempDeviceAddress, 0); temp1=sensors.getTempC(tempDeviceAddress); // Вывод текущего значения температуры на дисплей lcd.setCursor(0, 0); lcd.print(" Current temp "); lcd.setCursor(5, 1); lcd.print(temp1); // Serial.println(temp1,4); } //Проверка условия включения/выключения нагревателя if (temp1<setTmp&&relayStatus1==LOW){relayStatus1=HIGH; digitalWrite(RELAY_PIN,HIGH);} if (temp1>setTmp&&relayStatus1==HIGH){relayStatus1=LOW; digitalWrite(RELAY_PIN,LOW);} // Опрос клавиатуры button = getPressedButton(); switch (button) { case BUTTON_UP: backlightStatus=1;delay(200);digitalWrite(BACKLIGHT_PIN, backlightStatus); break; case BUTTON_DOWN: backlightStatus=0;delay(200);digitalWrite(BACKLIGHT_PIN, backlightStatus); break; case BUTTON_SELECT: delay(200);setTemperature(); } }
Оригинал программы: http://arduino.ru/forum/proekty/upravlenie-obogrevom-komnaty-pri-pomoshchi-arduino-i-dallas18b20
while
(BUTTON_SELECT && BUTTON_RIGHT);
Это строка всегда будет выполняться, поскольку
BUTTON_RIGHT и BUTTON_SELECT константы, суть числа, например 5 и 6. Потому while(5 && 6) всегда true. Оно будет false только в одном случае, если одно из чисел будет равно 0.Сравнивать нужно всё таки значение переменной button с BUTTON_SELECT, а не просто BUTTON_SELECT.
while
(BUTTON_SELECT && BUTTON_RIGHT); эквивалентно
while
((BUTTON_SELECT != 0) && (BUTTON_RIGHT != 0));
А как мне тогда переписать эту строку , я не совсем понимаю, этот цикл в новинку для меня.
Когда меняю
while
((BUTTON_SELECT != 0) && (BUTTON_RIGHT != 0)) на
while
((BUTTON_SELECT != 5) && (BUTTON_RIGHT != 1)) , то он сразу выходит из цикла.
Нужно сравнивать переменную с константой, а не константу с константой. Если я непонятно говорю, то помочь не смогу, придется тебе учить язык, смотреть примеры.
Внутри do-while необходимо получать данные которые в последствии Вы будите использовать для выхода из цикла
В этом месте программа зацикливается, и никакие ранее по тексту кода опросы кнопок производится не будут. Поэтому необходимо вызывать функцию опроса кнопок внутри цикла.
Если сравнивать одно и то же результат будет неизменным.
Не лезьте сразу, если это для Вас дебри, попробуйте поиграться с чем нибудь попроще ( a&b сидели вместе там , а конкатенировалось, b - сдвинулось влево на два) .
я понимаю, что "сильнонада", но пути только два:
- научиться самому
- ищу исполнителя
В этом цикле как раз есть функция опроса кнопок getPressedButton()
Ошибка элементарная: while (BUTTON_SELECT && BUTTON_RIGHT);
Должно быть: while (keyCode!=5 && keyCode!=4);
где keyCode - сигнла кнопок.
А вообще, главный косяк в самой функции считывания сигнала кнопок, нажимаешь на правую кнопку, buttonValue <100 , что соответствует условию всех кнопок, получается, жмём на правую кнопку, а программа думает, что мы нажали на все кнопки одновременно.
int getPressedButton()
{
int buttonValue = analogRead(0); // Считываем значения с аналогового входа(A0)
if (buttonValue < 100) {
return BUTTON_RIGHT;
}
else if (buttonValue < 200) {
return BUTTON_UP;
}
else if (buttonValue < 400){
return BUTTON_DOWN;
}
else if (buttonValue < 600){
return BUTTON_LEFT;
}
else if (buttonValue < 800){
return BUTTON_SELECT;
}
return BUTTON_NONE;
}
Попробуйте такой код. Всю программу я не прверял но с кнопками попробовал решить. Прочитайте коментарий в 62 строке и выполните проверку