Помогите с циклом 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 необходимо получать данные которые в последствии Вы будите использовать для выхода из цикла
do { //тут опрашиваем } while (тут проверяем, (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 строке и выполните проверку
// Подключаем библиотеку для работы с шиной 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; int BUTTON_NONE = 0; int BUTTON_RIGHT = 0;//1; int BUTTON_UP = 0;//2; int BUTTON_DOWN = 0;//3; int BUTTON_LEFT = 0;//4; int BUTTON_SELECT = 0;//5; int getPressedButton() { int buttonValue = analogRead(0); // Считываем значения с аналогового входа(A0) if (buttonValue > 0) /////////***Здесь надо посмотреть какое значение не нажатой кнопки и поставить >0 или >23, иначе не будет сброса при отпускании кнопки { if (buttonValue < 100) { BUTTON_RIGHT = 1; } else if (buttonValue < 200) { BUTTON_UP = 2; } else if (buttonValue < 400) { BUTTON_DOWN = 3; } else if (buttonValue < 600) { BUTTON_LEFT = 4; } else if (buttonValue < 800) { BUTTON_SELECT = 5; } } else BUTTON_NONE = 1; if (BUTTON_NONE) { BUTTON_NONE = 0; BUTTON_RIGHT = 0; BUTTON_UP = 0; BUTTON_DOWN = 0; BUTTON_LEFT = 0; BUTTON_SELECT = 0; } } 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 { getPressedButton(); if (BUTTON_UP) { setTmp++; delay(200); lcd.setCursor(7, 1); lcd.print(setTmp); } if(BUTTON_DOWN) { setTmp--; delay(200); lcd.setCursor(7, 1); lcd.print(setTmp); } } while (!BUTTON_SELECT || !BUTTON_RIGHT); delay(200); //По клавише Select – созраняем в EEPROM измененное значение //По клавише Right – восстанавливаем старое значение if(BUTTON_SELECT)EEPROM_write_byte(0, setTmp); if(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); } // Опрос клавиатуры getPressedButton(); if(BUTTON_UP){ backlightStatus=1; delay(200); digitalWrite(BACKLIGHT_PIN, backlightStatus); } if(BUTTON_DOWN){ backlightStatus=0; delay(200); digitalWrite(BACKLIGHT_PIN, backlightStatus); } if(BUTTON_SELECT){ delay(200); setTemperature(); } }