Помогите с циклом do...wile

Surama
Offline
Зарегистрирован: 17.05.2016

Не могу написать условие для программы, выполняется цикл установки температуры, но как написать условие (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();
    
  }

}
Surama
Offline
Зарегистрирован: 17.05.2016
kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

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));

 

Surama
Offline
Зарегистрирован: 17.05.2016

А как мне тогда переписать эту строку , я не совсем понимаю, этот цикл в новинку для меня.

Когда меняю while ((BUTTON_SELECT != 0) && (BUTTON_RIGHT != 0)) на while ((BUTTON_SELECT != 5) && (BUTTON_RIGHT != 1)) , то он сразу выходит из цикла.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Нужно сравнивать переменную с константой, а не константу с константой. Если я непонятно говорю, то помочь не смогу, придется тебе учить язык, смотреть примеры.

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Внутри do-while необходимо получать данные которые в последствии Вы будите использовать для выхода из цикла

do
{
//тут опрашиваем
}
while (тут проверяем, (do-while будет вычислять в цикле непрерывно и бесконечно до тех пор, пока выражение в скобках, не станет равно логическому ЛОЖНО));

В этом месте программа зацикливается, и никакие ранее по тексту кода опросы кнопок производится не будут. Поэтому необходимо вызывать функцию опроса кнопок внутри цикла.

inspiritus
Offline
Зарегистрирован: 17.12.2012

Если сравнивать одно и то же результат будет неизменным.

Не лезьте сразу, если это для Вас дебри, попробуйте поиграться с чем нибудь попроще ( a&b сидели вместе там , а конкатенировалось, b - сдвинулось влево на два) .

я понимаю, что "сильнонада", но пути только два:

- научиться самому

- ищу исполнителя

rusww
Offline
Зарегистрирован: 17.12.2016

В этом цикле как раз есть функция опроса кнопок 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;
}

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Попробуйте такой код. Всю программу я не прверял но с кнопками попробовал решить. Прочитайте коментарий в 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();
    }

}