Переход с аналоговых кнопок на цифровые, помогите!
- Войдите на сайт для отправки комментариев
Сб, 25/07/2015 - 23:53
Переход с аналоговых кнопок на цифровые не получается, кнопка на пине 7 работает, вхожу в установочное меню, а вот дальше все останавсливается. Подскажите пожалуйста, что я делаю неправильно?
На аналоговых кнопках все работало, в коде закоменторованые остатки обработки аналоговых кнопок.
// термостат, один датчик DS18B20 // // #include <EEPROM.h> #include <OneWire.h> #include <LiquidCrystal.h> #include <OLED_I2C.h> #define OUT1 13 // выход для реле OneWire ds(15); // 15 вход датчика 18b20 LiquidCrystal lcd(8, 9, 4, 5, 6, 7); OLED myOLED(SDA, SCL, 8); extern uint8_t SmallFont[]; extern uint8_t BigNumbers[]; // constants won't change //int analogPin = 2; //int val = 0; // variable for reading the pushbutton status long previousMillis = 0; int flag1=0; int flag2=0; int flag3=0; // variables will change: float tempON; // ГРАФИЧАСКИЕ СИМВОЛЫ ДЛЯ ЭКРАНА byte gradus[8] = { 0b00110, 0b01001, 0b01001, 0b00110, 0b00000, 0b00000, 0b00000, 0b00000 }; byte on[8] = { 0b00000, 0b00000, 0b10001, 0b01110, 0b01110, 0b10001, 0b00000, 0b00000 }; // ОБРАБОТКА ОШИБОК void erorr(){ // останавливает работу программы и показываем ошибку digitalWrite(OUT1, LOW); // выключаем реле while(1){ // крутим бесконечный цикл digitalWrite(13, !digitalRead(13)); delay(100); } } // ОПИСАНИ КНОПОК byte key() { // int val = analogRead(analogPin); // Serial.print(val); // if (val < 50) return 1; // else if (val < 500) return 2; //Left Button // else if (val < 900) return 3; //Right Button // else return 0; //"SETUP" Button connected to 7 if(digitalRead(7)==LOW&&flag1==0) //если кнопка нажата и перемення flag равна 0 , то ... { if (millis() -previousMillis >500) return 1; { previousMillis = millis(); flag1=1; //это нужно для того что бы с каждым нажатием кнопки происходило только одно действие } } if (digitalRead(7)==HIGH&&flag1==1) //если кнопка НЕ нажата и переменная flag равна - 1 ,то ... { flag1=0;//обнуляем переменную flag } //"DOWN" Button connected to 4 if(digitalRead(4)==LOW&&flag2==0) //если кнопка нажата и перемення flag равна 0 , то ... { if (millis() -previousMillis >500) return 2; { previousMillis = millis(); flag2=1; //это нужно для того что бы с каждым нажатием кнопки происходило только одно действие } } if (digitalRead(4)==HIGH&&flag2==1) //если кнопка НЕ нажата и переменная flag равна - 1 ,то ... { flag2=0;//обнуляем переменную flag } // else return 0; } // ВЫВОД НА ЭКРАН В РЕЖИМЕ УСТАНОВКИ ТЕМПЕРАТУРЫ И ЗАДАНИЯ ТЕМПАРАТУРЫ (SV) void setMenu() { byte pos; digitalWrite(OUT1, LOW); // выключаем реле while(1) { // крутим бесконечный цикл byte KEY = key(); // читаем состояние кнопок lcd.clear(); lcd.setCursor(1, 0); lcd.print("SV: "); lcd.blink(); lcd.setCursor(4, 0); // выводим на экран lcd.print(tempON); //установленное знанчение температуры lcd.write(1); //символ градуса lcd.print("C "); lcd.setCursor(0, 0); //TEST OLED myOLED.clrScr(); myOLED.setFont(SmallFont); myOLED.print("SV", 10, 20); myOLED.setFont(BigNumbers); myOLED.printNumF(tempON, 2, 30, 20); myOLED.drawCircle(110, 23, 2); // hor, ver ,size myOLED.setFont(SmallFont); myOLED.print("C", 114, 22); myOLED.update(); // обработка кнопок if (KEY == 2) // если кнопка DOWN нажата { tempON-= 0.5; // изменяем значение if (tempON < 20) tempON = 95; //проверяем пределы } else if (KEY == 3) // если правая кнопка нажата { tempON+= 0.5; // изменяем значение if (tempON > 95) tempON = 20; //проверяем пределы } else if (KEY == 1) // если правая кнопка нажата { EEPROM.put(0, tempON); // сохраняем в eeprom //return; } // delay(100); } } // ОПРОС ДАТЧИКА float getTemp(){ // возвращает температуру с датчика byte data[12]; // и останавливает программу на секунду byte addr[8]; if (!ds.search(addr)) { //если адрес датчика не получен сообщаем об ошибке lcd.clear(); lcd.print("No sensor"); //OLED TEST myOLED.begin(); myOLED.setFont(SmallFont); myOLED.print("NO SENSOR", 37, 30); myOLED.update(); erorr(); } ds.reset_search(); if (OneWire::crc8(addr, 7) != addr[7]) { lcd.clear(); lcd.print("Sensor CRC erorr"); //OLED TEST myOLED.begin(); myOLED.setFont(SmallFont); myOLED.print("SENSOR CRC ERROR", 30, 30); myOLED.update(); erorr(); } ds.reset(); ds.select(addr); ds.write(0x44); delay(500); ds.reset(); ds.select(addr); ds.write(0xBE); for (int i = 0; i < 9; i++) data[i] = ds.read(); int raw = (data[1] << 8) | data[0]; // Переводим в температуру if (data[7] == 0x10) raw = (raw & 0xFFF0) + 12 - data[6]; return raw / 16.0; } void setup() { Serial.begin(9600); //digitalWrite(2, HIGH); // Button pin pinMode(13, OUTPUT); // Buttons setup pinMode(7, INPUT); // устанавливает режим работы - вход для 7го вход/выхода it is "SETUP" pin digitalWrite(7, HIGH); pinMode(4, INPUT); // устанавливает режим работы - вход для 4го вход/выхода it is "DOWN" pin digitalWrite(4, HIGH); pinMode(2, INPUT); // устанавливает режим работы - вход для 2го вход/выхода it is "UP" pin digitalWrite(2, HIGH); lcd.createChar(1, gradus); lcd.createChar(2, on); lcd.begin(16, 2); lcd.clear(); myOLED.begin(); pinMode(13, OUTPUT); pinMode(OUT1, OUTPUT); tempON = EEPROM.get(0 , tempON); // читаем настройки из еепром } void loop() { if (key() == 1) setMenu(); // если нажата кнопка SETUP, уходим в меню задания температуры float temperature = getTemp(); // читаем температуру if (temperature < tempON) digitalWrite(OUT1, HIGH); // сверяем температуру else digitalWrite(OUT1, LOW); // и управляем выходами // ВЫВОД ИНФОРМАЦИИ НА ЭКРАН В РАБОЧЕМ РЕЖИМЕ lcd.setCursor(0, 1); /// вывод на экран заданной температуры lcd.print("SV:"); lcd.print(tempON); lcd.write(1); lcd.print("C "); if (digitalRead(OUT1)) lcd.write(2); // вывод на экран состояние выхода else lcd.print(" "); lcd.setCursor(0, 0); // вывод на экран текущей температуры lcd.print("PV:"); lcd.print(temperature); lcd.write(1); lcd.print("C"); lcd.setCursor(9, 1); // TEST OLED myOLED.setFont(SmallFont); myOLED.print("PV", 10, 05); myOLED.print("SV", 10, 39); myOLED.print("C", 115, 05); myOLED.print("C", 115, 39); if (digitalRead(OUT1)) myOLED.print("*", 13, 16); // вывод на экран состояние выхода else myOLED.print(" ", 13, 16); myOLED.setFont(BigNumbers); myOLED.printNumF(temperature, 2, 30, 03); myOLED.printNumF(tempON, 2, 30, 37); myOLED.drawCircle(111, 06, 2); // hor, ver ,size myOLED.drawCircle(111, 40, 2); // hor, ver ,size myOLED.update(); }
Переход с аналоговых кнопок на цифровые...
не бывает ни тех , ни других :(
...ставьте галочку - "свернуть код" при размещении , а не только - "пронумеровать"....
пины 4 и 7 отведены под LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
а ты читаешь их как кнопки :(
задефайнь под кнопки другие пины , с подтяжкой пинов к VСС , а кнопки на GND ( резисторов будет меньше )
переход с резистивной клавы на две кнопки по одному аналоговому пину
приведёт к использованию двух пинов в цифровом режиме....
нуууу , и обработка нажатий кнопок изменится :)
Переход с аналоговых кнопок на цифровые...
не бывает ни тех , ни других :(
...ставьте галочку - "свернуть код" при размещении , а не только - "пронумеровать"....
пины 4 и 7 отведены под LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
а ты читаешь их как кнопки :(
задефайнь под кнопки другие пины , с подтяжкой пинов к VСС , а кнопки на GND ( резисторов будет меньше )
переход с резистивной клавы на две кнопки по одному аналоговому пину
приведёт к использованию двух пинов в цифровом режиме....
нуууу , и обработка нажатий кнопок изменится :)
Спасибо! Уже и сам понял :) Заработало!
Пины подтянуты к VCC и сажаются на ноль кнопкой.
Второй диспелей не используется, это остатки экспериментов, закоментировал все относящиеся к LED, отключил библиотеку и заработали кнопки. Но при одном нажатии кнопки установки темепературы (прибавить/отнять) идет быстрая прокрутка, так как пробавление идет в цикле, как это побороть бед delay?
Не подскажете, как сделать чтоб после повторного нажания (при этом новое значение темепературы записыавется в память) программа перезапускалась сначала? Сейчас для этого надо надавить ресет.
код покажи :)
Не подскажете, как сделать чтоб после повторного нажания (при этом новое значение темепературы записыавется в память) программа перезапускалась сначала? Сейчас для этого надо надавить ресет.
В даташите ATmega48PA/88PA/168PA/328P описано как программно вызвать Reset через Watch Dog Timer. Почитайте главу 10 даташита, там даже есть примеры на С и на ассемблере.
Не подскажете, как сделать чтоб после повторного нажания (при этом новое значение темепературы записыавется в память) программа перезапускалась сначала? Сейчас для этого надо надавить ресет.
...для этого надо правильно написать ЛУУП , а не ресетить !
см. #3
строки 36...45 - это стандартный символ , зачем ещё один определять ?
код покажи :)
Вот. Работает приемлемо, но хотелось бы от delay избавится при обработке кнопок, почему идет прокрутка при нажатой кнопке? Получается flag не реботает?
Ну и выход из меню установки темепературы пока не знаю как правильно сделать.
строки 36...45 - это стандартный символ , зачем ещё один определять ?
В библитеке шрифтов мало, нужного размера вроде там нет, ну или я не увидел :) проверю еще раз.
Не подскажете, как сделать чтоб после повторного нажания (при этом новое значение темепературы записыавется в память) программа перезапускалась сначала? Сейчас для этого надо надавить ресет.
...для этого надо правильно написать ЛУУП , а не ресетить !
Попробовал то что нашел здесь на форуме
Вставил вызов функции после:
При входе в меню сразу срабатыавет ресет, значит флаги у меня не работают и кнопка выдат сигнал все время пока нажата :(
строки 18...20 - зачем три флага да ещё по 4 байта ?
хватит и одного - см. enum
В библитеке шрифтов мало, нужного размера вроде там нет, ну или я не увидел :) проверю еще раз.
не проверяй... я тупанул не зная что за дисплей....
почему идет прокрутка при нажатой кнопке? Получается flag не реботает?
кроме события "нажатие на кнопку" нужно ещё следить за событием "отпускание кнопки"
и кнопка выдат сигнал все время пока нажата :(
дык , у неё работа такая ! выдавать или не выдавать....
...независимо от того что происходит в программе :)-
в лупе в строке 265 при нажатии попадаем в setMenu() , и как оттуда выбраться если там while(1) ?
или я что-то просмотрел...
162...180 будет читаемееееее если сделать через switch-case .....
key() возвращает 0....3 , а обрабатываешь почему только 1....3 ?
key() возвращает 0....3 , а обрабатываешь почему только 1....3 ?
возврат 0 наследие из использованного примера :) если если убрать ничего вроде не меняется. Обрабатывается нажание трех кнопок т.е. 1, 2, 3
а где это в коде
EEPROM.put(0, tempON);
// сохраняем в eeprom
?в лупе в строке 265 при нажатии попадаем в setMenu() , и как оттуда выбраться если там while(1) ?
или я что-то просмотрел...
162...180 будет читаемееееее если сделать через switch-case .....
Из лупа выбираемся ресетом. Я только осваиваю программирование, так что модифицирую подходящие примеры найденные в интернете и по ходу разбираюсь, выбиратся из этого лупа пока не научился, сижу, изучаю документацию.
как "сделать через switch-case" я пока не знаю
а где это в коде
EEPROM.put(0, tempON);
// сохраняем в eeprom
?строка 183
183
}
162.....180
switch ( KEY )
{
case 1 :
{
делаем раз
break;
}
case 2 :
{
делаем два
break;
}
case 3 :
{
делаем три
break;
}
}
так удобнее чем через ифы
#5 ...для этого надо правильно написать ЛУУП , а не ресетить !
:)
183
}
162.....180
switch ( KEY )
{
case 1 :
{
делаем раз
break;
}
case 2 :
{
делаем два
break;
}
case 3 :
{
делаем три
break;
}
}
так удобнее чем через ифы
Спасибо! Сейяас буду пробовать.
183
}
дык , если что-то дописал-изменил в коде - обновляй здесь ! :)
завтра в отпуск....
там тырнета ваааааще нет :(
пока-пока....
http://arduino.ru/Reference/SwitchCase
162.....180
switch ( KEY )
{
case 1 :
{
делаем раз
break;
}
case 2 :
{
делаем два
break;
}
case 3 :
{
делаем три
break;
}
}
так удобнее чем через ифы
Так компилятор ругается :(
Arduino: 1.6.5 (Mac OS X), Board: "Arduino Uno"
TEMP_Digital_Button_Thermostat_V2.ino: In function 'void setMenu()':
TEMP_Digital_Button_Thermostat_V2.ino:152:30: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
TEMP_Digital_Button_Thermostat_V2.ino:157:30: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
TEMP_Digital_Button_Thermostat_V2.ino:214:18: error: a function-definition is not allowed here before '{' token
TEMP_Digital_Button_Thermostat_V2.ino:319:2: error: expected '}' at end of input
TEMP_Digital_Button_Thermostat_V2.ino:319:2: error: expected '}' at end of input
a function-definition is not allowed here before '{' token
Со скобками вроде не напутал
Ошибку нашел, код поправил, теперь работатет Switch вместо If
51...53 - выкинь из кода и из головы :)
где же выход из цикла 143....217 ?
или + , или - , или запись в епром.... а остальное ?
51...53 - выкинь из кода и из головы :)
Это остатки экспериментов, убрал.
Добавил delay в обработкю кнопок, без этого значения крутятся слишком быстро при нажатии кнопки
Но попрежнему не понятно, как выйти из цикла после записэ измененного значения темепературы в eeprom?
где же выход из цикла 143....217 ?
или + , или - , или запись в епром.... а остальное ?
Так пока еще не понял, как правильно выход сделать :(
не while ( 1 ) , а пока код кнопки не равен 1
while ( KEY !=1 )
при 2 или 3 - + или -
при 1 - запись и выход из "бесконечного цикла" в ЛУУП
И остается не понятная для меня проблема, почему не работают флаги? кнопки плюс и монус не важно, с delay они работают приемлемо и даже удобно, но кнопка SETUP каждый раз многократно переписывает EEPROM при вызове меню, а это по моему не хорошо так как количество циклов перезаписи ограничено.
274...276 переделать под гистерезис....
если меньше чем tempON-1 то включить
если больше чем tempON+1 то выключить
или можешь попасть на прослушивание реле в режиме тик-так-тик-так-тик.....
не while ( 1 ) , а пока код кнопки не равен 1
while ( KEY !=1 )
при 2 или 3 - + или -
при 1 - запись и выход из "бесконечного цикла" в ЛУУП
Чего то не работает, компилятор ругается.
------
'KEY' was not declared in this scope
-----
Но так по моему работать не будет. так как при нажатии кнопки происходит повторяющееся событие (флаг не работает) принажатии будет сразу и вход в меню и выход.
274...276 переделать под гистерезис....
если меньше чем tempON-1 то включить
если больше чем tempON+1 то выключить
или можешь попасть на прослушивание реле в режиме тик-так-тик-так-тик.....
С этим позже буду разбиратся, как раз по алгоритму управления идеи есть, буду эксперементировать, но хочу сначала с кнопками разобратся.
кусок кода с флагами никогда не выполняется !!!!!!!
сетап - бла , бла - читаем из епрома
запуск - крутим лопинг :
270 - ждём кнопку Сетап ( нет - дальше )
272 - опрашиваем датчик
274...298 - управление реле и отображение
из 270 по Сетап-кнопке попадаем на + , - , или запись в епром - И снова крутим лопинг :(
ВСЁ - больше код ничё не делает ( не умеет ) :)
не while ( 1 ) , а пока код кнопки не равен 1
while ( KEY !=1 )
при 2 или 3 - + или -
при 1 - запись и выход из "бесконечного цикла" в ЛУУП
Разобрался, заработало вот так:
while ( (key()) !=1 );
НО сразу вылетает из меню так как флаги не работают и кнопка при однократном нажатии генерит серию событий (дребезг контактов или просто очень быстро обрабатывается кнопка) :( а delay в основной цикл я вставлять очень не хочу.
не while ( 1 ) , а пока код кнопки не равен 1
while ( KEY !=1 )
при 2 или 3 - + или -
при 1 - запись и выход из "бесконечного цикла" в ЛУУП
Чего то не работает, компилятор ругается.
------
'KEY' was not declared in this scope
-----
Но так по моему работать не будет. так как при нажатии кнопки происходит повторяющееся событие (флаг не работает) принажатии будет сразу и вход в меню и выход.
139А -
byte
KEY = 0;
144 -
KEY = key();
KEY был определён внутри while() - вот и ругается , что нет такой переменной
Добавил delay в обработкю кнопок, без этого значения крутятся слишком быстро при нажатии кнопки
на велосипед - нажатия/отпускания обрабатываются один раз.
Но попрежнему не понятно, как выйти из цикла после записэ измененного значения темепературы в eeprom?
а, зачем оно у тебя в цикле?
прочитал из еепром, сравнил с актуальным значением, если есть разница, то перезаписал в еепром - если часто будешь перезаписывать, то сотрёшь еепром за год или раньше.
кусок кода с флагами никогда не выполняется !!!!!!!
сетап - бла , бла - читаем из епрома
запуск - крутим лопинг :
270 - ждём кнопку Сетап ( нет - дальше )
272 - опрашиваем датчик
274...298 - управление реле и отображение
из 270 по Сетап-кнопке попадаем на + , - , или запись в епром - И снова крутим лопинг :(
ВСЁ - больше код ничё не делает ( не умеет ) :)
Ну как же он не выполняется? Я ведь могу из режима показа температуры войти в меню?
А это вот этот кусок как я понимаю:
По крайней мере программа
получает, без этого я бы не воешел в меню установки темепературы.
return 2;return 3; Программа тоже получает, так как я могу менять темепературу в меню установки, значит код работает? Но флаги при этом не работают...
Добавил delay в обработкю кнопок, без этого значения крутятся слишком быстро при нажатии кнопки
на велосипед - нажатия/отпускания обрабатываются один раз.
Но попрежнему не понятно, как выйти из цикла после записэ измененного значения темепературы в eeprom?
а, зачем оно у тебя в цикле?
прочитал из еепром, сравнил с актуальным значением, если есть разница, то перезаписал в еепром - если часто будешь перезаписывать, то сотрёшь еепром за год или раньше.
Спасибо, буду разбиратся и пробовать, уже завтра наверное.
В цикле оно так как фактически есть два режима, контроль температуры и установка темепературы, переход в режим установки по кнопке SETUP , return 1; из основного цикла, во вторм цикле считвание кнопок для корррекции температуры и запись в EEPROM вот из него я и не умею пока организовать выход.
Надеюсь заработатет когда поправлю обработку кнопок и они будут давать только по одному срабатыванию. Перепишу обработку кнопок завтра на свежую голову.
Спасибо огромное за помощь!
получает 1 , но раз в полсекунды - не быстрее...
и флаги меняются , но в коде ( который компилится ) нигде не анализируются ( флаги )
покрути код в голове вместо МК - сам всё увидишь :)
вот из него я и не умею пока организовать выход.
#39
вот из него я и не умею пока организовать выход.
#39
Да, спасибо, так сейчас и сделано, но надо переписать обработку кнопок, чтоб заработало корректно, сейчас входит в меню и сразу вываливается (так как кнопка не корректно работатет), при этом еще экран не обновляется, мусор, с этим разберусь
Сейчас вот так
получает 1 , но раз в полсекунды - не быстрее...
и флаги меняются , но в коде ( который компилится ) нигде не анализируются ( флаги )
покрути код в голове вместо МК - сам всё увидишь :)
Потихоньку разбираюсь, к сожалениу на это только 3-4 часа по вечерам возможно использовать. Воображение у меня на HW натренировано, на SW никогда времени не было, вот сейчас решил освоить.
в key() в конце добавь delay( 200 ) , например 200 - и от дребезга поможет и темп опроса кнопок снизится...
delay( 200.....500 )
Добавил delay в обработкю кнопок, без этого значения крутятся слишком быстро при нажатии кнопки
на велосипед - нажатия/отпускания обрабатываются один раз.
Но попрежнему не понятно, как выйти из цикла после записэ измененного значения темепературы в eeprom?
а, зачем оно у тебя в цикле?
прочитал из еепром, сравнил с актуальным значением, если есть разница, то перезаписал в еепром - если часто будешь перезаписывать, то сотрёшь еепром за год или раньше.
Я не понимаю как программа понимает, что input 3 это именно BUTTON_00 ? Какая строчка из примера это описывает?
в key() в конце добавь delay( 200 ) , например 200 - и от дребезга поможет и темп опроса кнопок снизится...
delay( 200.....500 )
Я очень хочу избавится от delay в основном цикле, т.е. убрать дребезг и сделать все остальное программно, без delay.
Я не понимаю как программа понимает, что input 3 это именно BUTTON_00 ? Какая строчка из примера это описывает?
ты считываешь состояние пина 3 в локальную переменную nb00
boolean nb00 = digitalRead(3);
если это состояние изменилось
if
(nb00 != b00) {}
то, что-то делаешь
что бы это делать один раз, то обновляешь переменную состояния пина
b00 = nb00;
далее, что-то делаешь при нажатии или отпускании
или я не понял вопроса - назови кнопку не BUTTON_00 , а как тебе захочется, но это будет пин 3.
Добавил delay в обработкю кнопок, без этого значения крутятся слишком быстро при нажатии кнопки
на велосипед - нажатия/отпускания обрабатываются один раз.
Но попрежнему не понятно, как выйти из цикла после записэ измененного значения темепературы в eeprom?
а, зачем оно у тебя в цикле?
прочитал из еепром, сравнил с актуальным значением, если есть разница, то перезаписал в еепром - если часто будешь перезаписывать, то сотрёшь еепром за год или раньше.
Я не понимаю как программа понимает, что input 3 это именно BUTTON_00 ? Какая строчка из примера это описывает?
Торможу, понял:
boolean nb00 = digitalRead(3);
Но все разво не понимаю, почему не будет обработам дребезг контактов как многократное нажатие отпускание?