Меню на LCD Keypad Shield
- Войдите на сайт для отправки комментариев
Пт, 13/09/2013 - 20:03
Пытаюсь сделать меню, вот пример:
#include <Wire.h>//для часов
#include <DS1307new.h>//для часов
#include <LiquidCrystal.h> // библиотека экрана
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
int lcd_key = 0;
int adc_key_in = 0;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
bool key_menu=false;
void setup(){
lcd.begin(16, 2); // запускаем библиотеку
}
void loop(){
if (key_menu==false)
{
printTimeToLCD(); // выводим время на экран
lcd_key=read_LCD_buttons();
if (lcd_key==btnSELECT)
{
key_menu=true;
}
}
else
{
lcd.print("NaNaNaNaNa");
}
}
int read_LCD_buttons()
{
adc_key_in = analogRead(0);
if (adc_key_in > 1000) return btnNONE;
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 250) return btnUP;
if (adc_key_in < 450) return btnDOWN;
if (adc_key_in < 650) return btnLEFT;
if (adc_key_in < 850) return btnSELECT;
return btnNONE;
}
void printTimeToLCD(){
RTC.getTime();
byte static prevSecond=0;
if(RTC.second!=prevSecond){
lcd.setCursor(4,0);
if (RTC.hour<10) lcd.print("0");
lcd.print(RTC.hour);
lcd.print(":");
if (RTC.minute<10) lcd.print("0");
lcd.print(RTC.minute);
lcd.print(":");
if (RTC.second<10) lcd.print("0");
lcd.print(RTC.second);
prevSecond=RTC.second;
}
}
При нажатии на кнопку "Select" заходит в меню (пока для примера выводится надпись).
Вопросы:
1) Почему выводит вместо "NaNaNaNaNa" 10 первых ячеек, весь дисплей заполняется этими буквами?
2) Почему спустя 1-2 минуты (обычно даже меньше) выкидывает из меню обратно на время? (вроде переменная key_menu не должна позволить сделать это, она ведь жестко устанавливается в значение true при нажатии)
ps: есть примеры 2х-3х уровневого меню?
Точнее даже не 1-2 минуты, а 20 секунд постоянно, а потом скидываеь, как будето происходит рестарт.
Еще один вопрос: 3) Как можно вывести примерно такую конструкцию, вроде в c++ так работает, а тут нет:
int key1=23; int key2=4; lcd.print("Prim"+key1+"bahbax"+key2);Ну и еще один: 4) Можно ли среду ардуины подключить к MSVSC++? Существую ли отладчики, для прогонки кода ардуины на выявление косяков?
>1) Почему выводит вместо "NaNaNaNaNa" 10 первых ячеек, весь дисплей заполняется этими буквами?
А сколько раз у вас вызвается " lcd.print("NaNaNaNaNa"); ? Куда по вашему должны выводится все последующие вызовы?
посмотрите на функцию printTimeToLCD(), там же этой проблемы нет. Сыграйте в игру "найди 10-ть отличий". Разберите построчно что происходит в этой функции.
Кстати ответ на этот вопрос поможет вам и с
> Как можно вывести примерно такую конструкцию
Только тут как раз наоборот нужно воспользоватся этим эффектом, а не устранять его.
>вроде в c++ так работает,
Нет у нас тут конкатенации сишных строк.
P.S. Отформатируйте код отступами, невозможно же читать где какой if начался, где закончился. Ну хотя-бы ctrl+T нажмите в ArdinoIDE
С этим понятно, разберусь. А вот почему выкидывает обратно на часы? это наверное главная для меня загадка
С этим понятно, разберусь. А вот почему выкидывает обратно на часы? это наверное главная для меня загадка
>А вот почему выкидывает обратно на часы
А хрен его знает. Может действитель перегружается.
Добавте в loop() что-то такое:
void loop(){ static unsigned long prev=0; if(millis()-prev>1000){ Serial.println(millis()); // про Serial.begin в setup() не забудте prev=millis(); } .... дальше ваш код ..... }И смотрите в сериал монитор. Если цифры сбрасываются на ноль - значит таки перезагрузки. Заодно увидите и "через какое время" точно.
Можете еще попробовать
lcd.print("NaNaNaNaNa");закоментить. возможно этот беконечный print сносит башню библиотеке, она где-то выскакивает за границу памяти своей и перетирает вам значение key_menu
Прикол получается в том, что добавив действие в loop (например, ваш счетчик выше) из меню перестает выкидывать. Возможно дело в том, что если в loop ничего не меняется, ардуина думает что повисла и перезагружается? Хотя бред..
Вот таким образом из меню не выкидывает, а надпись чуть заметно мерцает (добавил lcd.clear()):
#include <Wire.h>//для часов #include <DS1307new.h>//для часов #include <LiquidCrystal.h> // библиотека экрана LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int lcd_key = 0; int adc_key_in = 0; #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 bool key_menu=false; void setup(){ Serial.begin(9600); lcd.begin(16, 2); // запускаем библиотеку } void loop(){ static unsigned long prev=0; if(millis()-prev>1000){ Serial.println(millis()); // про Serial.begin в setup() не забудте prev=millis(); if (key_menu==false) { printTimeToLCD(); // выводим время на экран lcd_key=read_LCD_buttons(); if (lcd_key==btnSELECT) { key_menu=true; } } else { lcd.clear(); lcd.print("NaNaNaNaNa"); } } } int read_LCD_buttons() { adc_key_in = analogRead(0); if (adc_key_in > 1000) return btnNONE; if (adc_key_in < 50) return btnRIGHT; if (adc_key_in < 250) return btnUP; if (adc_key_in < 450) return btnDOWN; if (adc_key_in < 650) return btnLEFT; if (adc_key_in < 850) return btnSELECT; return btnNONE; } void printTimeToLCD(){ RTC.getTime(); byte static prevSecond=0; if(RTC.second!=prevSecond){ lcd.setCursor(4,0); if (RTC.hour<10) lcd.print("0"); lcd.print(RTC.hour); lcd.print(":"); if (RTC.minute<10) lcd.print("0"); lcd.print(RTC.minute); lcd.print(":"); if (RTC.second<10) lcd.print("0"); lcd.print(RTC.second); prevSecond=RTC.second; } }А вот если без вашего кода, которые вызывает большую задержку (или я хз), надпись начинает мерцать очень сильно (что понятно из-за lcd.clear) и выкидыват на время:
#include <Wire.h>//для часов #include <DS1307new.h>//для часов #include <LiquidCrystal.h> // библиотека экрана LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int lcd_key = 0; int adc_key_in = 0; #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 bool key_menu=false; void setup(){ Serial.begin(9600); lcd.begin(16, 2); // запускаем библиотеку } void loop(){ if (key_menu==false) { printTimeToLCD(); // выводим время на экран lcd_key=read_LCD_buttons(); if (lcd_key==btnSELECT) { key_menu=true; } } else { lcd.clear(); lcd.print("NaNaNaNaNa"); } } int read_LCD_buttons() { adc_key_in = analogRead(0); if (adc_key_in > 1000) return btnNONE; if (adc_key_in < 50) return btnRIGHT; if (adc_key_in < 250) return btnUP; if (adc_key_in < 450) return btnDOWN; if (adc_key_in < 650) return btnLEFT; if (adc_key_in < 850) return btnSELECT; return btnNONE; } void printTimeToLCD(){ RTC.getTime(); byte static prevSecond=0; if(RTC.second!=prevSecond){ lcd.setCursor(4,0); if (RTC.hour<10) lcd.print("0"); lcd.print(RTC.hour); lcd.print(":"); if (RTC.minute<10) lcd.print("0"); lcd.print(RTC.minute); lcd.print(":"); if (RTC.second<10) lcd.print("0"); lcd.print(RTC.second); prevSecond=RTC.second; } }Если например добавить задержку delay(100), то мерцание становится не таким сильным (почти как в первом случае, еле заметное), но из меню попрежнему выкидывает спустя 25 секунд...
надпись начинает мерцать очень сильно (что понятно из-за lcd.clear) и выкидыват на время:
применяйте lcd.clear только для lcd.print нового значения - смысл лупить в индикатор одно и то же значение?
Дак я например могу вообще заменять clear на допустим lcd.setCursor(0,0). Мерцать перестает. А вот из меню выкидыват точно также.
смысл лупить в индикатор одно и то же значение?
В этом смысла нету, но как иначе? Мне надо выводить на экран строки меню и ждать нжатий кнопки.
Дак я например могу вообще заменять clear на допустим lcd.setCursor(0,0). Мерцать перестает. А вот из меню выкидыват точно также.
Я не особо вникал в ваш код, но в принципе не могу понять вкуда вас может выкидывать - меню есть переменная, которую вы печатаете на экран, какое бы значение ваша переменная не приняла, должно отображаться хоть что-то.
В этом смысла нету, но как иначе? Мне надо выводить на экран строки меню и ждать нжатий кнопки.
меню экрана есть реакция на изменение или сама переменная - нет изменения, нет print, нет мигания.
Можно сказать хочу сделать часы с настройками. По дефолту на экране отображается только время. При нажатии на кнопку Select открывается текстовое меню. В нём хочу переключаться между пунктами и заходить в нужный.. Это цель.
Время выводит нормльно. Когда я жму кнопку Select меня как бы забрасывает в меню (в примере выше, просто на текстовое поле "Na.."), дальше мне нужно ждать дальнейших нажатий клавишь, попросту ничего не делать. Дак вот, отсюда меня и выкидывает обратно на время (по видемому рестартится ардуина).
---
А существуют ли функции ожидания ответа (нажатия клавиши)? т.е. цикл останавливается и ждет пока на пин придет заданное значение...
Возможно с помощью прерываний это делается?
изменения состояния кнопок нужно писать в переменные - тогда и не будет выбрасывать.
считайте, что у вас есть консольная прога без гуя вообще, прога реагирует на нажания кнопок, что делают кнопки? - изменяют своё состояние и, если это состояние зависит от количества нажатий, копбинаций, прочего, то это состояние не просто LOW/HIGH, а 0, 1, 2, 3, ...
Значит - кнопка Select должна менять переменную Select с "0" на "1" при первом нажатии и обратно при повторном нажатии.
Кнопы DOWN, UP и прочие навигационные изменять переменную, допустим, "menu" с "0" до "5"(если у вас шесть строк меню)
т.е. DOWN увеличивает переменную menu на 1, UP - уменьшает.
все новые значения обновляются и запоминаются, изменения сравниваются с предыдущими, если выявляется разница - печатается в индикатор.
в итоге - Select вас будет забрасывать/выбрасывать из меню, DOWN/UP - навигация вверх/вниз по меню, может понадобится кнопа типо "ENTER" для запоминания/ввода значения.
Это типо концептуальный набросок логики.
Вопрос не в логике (с ней думаю сам разберусь), а совсем в другом. Посмотрите повнимательнее.
А существуют ли функции ожидания ответа (нажатия клавиши)? т.е. цикл останавливается и ждет пока на пин придет заданное значение...
Не нужно ничего ждать - контроллер гоняет программу по кругу, вам остаётся только рулить на поворотах на полной скорости.
примерно так:
// int b = 0; в начале инициализировано void BUTTON() { int nb = digitalRead(3); if (nb != b) { b = nb; if (digitalRead(3) == LOW) {что то делаем один раз при нажатии;} if (digitalRead(3) == HIGH) {что то делаем один раз при отпускании;} } }*Лешак раскритикует, но я это так понимаю.
>*Лешак раскритикует, но я это так понимаю.
А то :) Где отступы? Зачем же новичков учить так писать? Так - он уже умеет :)
>А существуют ли функции ожидания ответа (нажатия клавиши)?
Не существует. Зато существует прикрепленная ветка Работа с кнопками. В помощь новичку.
>А вот если без вашего кода, которые вызывает большую задержку
Не вызывает он большой задержки. Ну несколько микросекунд на вызов millis() и раз в секунду на выполенение println
Можете попробовыть выкинуть мой код еще сделать lcd.print("RESET"); delaa(2000) в самом setup(). Тогда никаких "задержке" не будет, зато будет видно когда контроллер перегрузился.
>Можно сказать хочу сделать часы с настройками.
Хе-хе... я тоже тем же занимаюсь... с описанием процесса в блоге. Только ОЧЕНЬ медленно. Только по выходным, да и то не каждым удается продвинутся по чуть-чуть... :( Мне вообще-то даже что-то знакомое/родное почудилось в функции printTimeToLCD() ;)
Вот кусок дальнейшей моей логики прикинул:
#include <Wire.h>//для часов #include <DS1307new.h>//для часов #include <LiquidCrystal.h> // библиотека экрана LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int lcd_key = 0; int adc_key_in = 0; #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 bool key_menu=false; void setup(){ Serial.begin(9600); lcd.begin(16, 2); // запускаем библиотеку } void loop(){ if (key_menu==false) { printTimeToLCD(); // выводим время на экран lcd_key=read_LCD_buttons(); if (lcd_key==btnSELECT) { key_menu=true; lcd.clear(); //очищаем экран //выводим два пункта lcd.print("-> T1"); lcd.setCursor(0,1); lcd.print(" T2"); } } else { //При нажатии на кнопку key_menu стало =true //Теперь лупим по этй части кода, подругому быть не может //Никаких действий сдесь не происходит, пока //я не нажму дальше на нужную кнопку //В данный момент именно отсюда меня и выкидывает на время //если я ничего не нажимаю некоторое количество секунд //А вот так происходит переключение между пунктами //и дальнейшее действие при нажатии кнопки Select (вход в один из пунктов) lcd_key=read_LCD_buttons(); switch (lcd_key) { case btnSELECT: { //Сдесь будет дальнейшее действие break; } case btnUP: //переключение между двумя пунктами { lcd.clear(); //очищаем экран lcd.print("-> T1"); lcd.setCursor(0,1); lcd.print(" T2"); break; } case btnDOWN: //переключение между двумя пунктами { lcd.clear(); //очищаем экран lcd.print(" T1"); lcd.setCursor(0,1); lcd.print("-> T2"); break; } } delay(100); //от случайного двойного нажатия и залипания кнопки } } int read_LCD_buttons() { adc_key_in = analogRead(0); if (adc_key_in > 1000) return btnNONE; if (adc_key_in < 50) return btnRIGHT; if (adc_key_in < 250) return btnUP; if (adc_key_in < 450) return btnDOWN; if (adc_key_in < 650) return btnLEFT; if (adc_key_in < 850) return btnSELECT; return btnNONE; } void printTimeToLCD(){ RTC.getTime(); byte static prevSecond=0; if(RTC.second!=prevSecond){ lcd.setCursor(4,0); if (RTC.hour<10) lcd.print("0"); lcd.print(RTC.hour); lcd.print(":"); if (RTC.minute<10) lcd.print("0"); lcd.print(RTC.minute); lcd.print(":"); if (RTC.second<10) lcd.print("0"); lcd.print(RTC.second); prevSecond=RTC.second; } }Имелось ввиду вот так:
#include <LiquidCrystal.h> // библиотека экрана LiquidCrystal lcd(8, 9, 4, 5, 6, 7); void setup(){ delay(2000); lcd.print("RES"); } void loop(){ }Точно также рестарт происходит, раз в 20-30 секунд.. я так понимаю от бездействия..
Так и есть, у меня второй день знакомства с ардуиной пошел)
>Имелось ввиду вот так:
Нет. Смысл в таком коде? Что вы сделали: при включении задержку (вместо того что-бы запустить библиотеку). Вывели надпись... и все.
Какую дополнительную информацию, для размышления вы получили в результате этого кода? А никакой.
вам нужно было.
#include <LiquidCrystal.h> // библиотека экрана LiquidCrystal lcd(8, 9, 4, 5, 6, 7); void setup(){ lcd.begin(16,2); lcd.setCursor(0,0); lcd.print("STARTED"); delay(2000); // показываем надпись один раз lcd.clear(); } void loop(){ ..... тут ваш остальной код.... }Тогда при старте - будет выводится надпись. Если она выводится один раз, при включении - все нормально. Если она будет повторно выводится, перед тем как "оно выскочело из меню" - значит происходят перезагрузки.
Что всётаки ардуина точно также рестартится, если ничего не происходит в лупе.
Тогда при старте - будет выводится надпись. Если она выводится один раз, при включении - все нормально. Если она будет повторно выводится, перед тем как "оно выскочело из меню" - значит происходят перезагрузки.
Точно также рестартится и таким образом тоже. Причина вроде как одна - бездействие в лупе.
А вот как решить такую проблему, я хз.
Точно также рестарт происходит, раз в 20-30 секунд.. я так понимаю от бездействия..
Так и есть, у меня второй день знакомства с ардуиной пошел)
Ну значит "я не ошибся" :) Но явно "чуток под себя подпилии" ее ;)
Я тоже буду делать (возможно сегодня) выставление времени с помощью кнопок.
Только... вначале хочу вообще по другому чтение кнопок сделать. С антидребезгом, что-бы кнопки читались не толкько шилдовые, но и еще добавлять можно было. На A1,A0, обычные цифровые кнопки и т.п.. И что-бы "стиль" чтения кнопок был похожим на обычный digitalRead. Тогда все "приемы" которые описаны в ветках типа "учимся работать с кнопками" - можно будет применять "в лоб". Ну и еще хочется ловить вещи типа "длинное нажатие/удержание" и т.п. Вообщем - наполеоновские планы ;)
Что всётаки ардуина точно также рестартится, если ничего не происходит в лупе.
Тот код что вы привели - не может ничего сказать о рестартах. Он выводит надпись при СТАРТЕ и все. Надпись висит. В момент РЕСТАРТА - ничего видимого происходить у вас не будет.
Тогда при старте - будет выводится надпись. Если она выводится один раз, при включении - все нормально. Если она будет повторно выводится, перед тем как "оно выскочело из меню" - значит происходят перезагрузки.
Точно также рестартится и таким образом тоже. Причина вроде как одна - бездействие в лупе.
А вот как решить такую проблему, я хз.
Учитывая что "рестартится" вы диагностировали не верно. Сделайте две вещи:
1. Дайте код с моей добавкой которую вы запускали
2. Постарайтесь детально описать "что вы видите/делаете": "вывелась надпись.... повисела 2 сек... исчезла... нажал кнопку.... увидел то-то..... через какое-то время.... увидел то-то...".
Постарайтесь ничего не упускать, типа "открыл сериал монитор" и т.п.
Будет пропадать надпись на 2 секунды)) она это и делает...
Ну вот по твоему:
#include <Wire.h>//для часов #include <DS1307new.h>//для часов #include <LiquidCrystal.h> // библиотека экрана LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int lcd_key = 0; int adc_key_in = 0; #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 bool key_menu=false; void setup(){ Serial.begin(9600); lcd.begin(16, 2); // запускаем библиотеку lcd.print("ST"); delay(2000); } void loop(){ if (key_menu==false) { printTimeToLCD(); // выводим время на экран lcd_key=read_LCD_buttons(); if (lcd_key==btnSELECT) { key_menu=true; lcd.clear(); //очищаем экран //выводим два пункта lcd.print("-> T1"); lcd.setCursor(0,1); lcd.print(" T2"); } } else { //При нажатии на кнопку key_menu стало =true //Теперь лупим по этй части кода, подругому быть не может //Никаких действий сдесь не происходит, пока //я не нажму дальше на нужную кнопку //В данный момент именно отсюда меня и выкидывает на время //если я ничего не нажимаю некоторое количество секунд //А вот так происходит переключение между пунктами //и дальнейшее действие при нажатии кнопки Select (вход в один из пунктов) lcd_key=read_LCD_buttons(); switch (lcd_key) { case btnSELECT: { //Сдесь будет дальнейшее действие break; } case btnUP: //переключение между двумя пунктами { lcd.clear(); //очищаем экран lcd.print("-> T1"); lcd.setCursor(0,1); lcd.print(" T2"); break; } case btnDOWN: //переключение между двумя пунктами { lcd.clear(); //очищаем экран lcd.print(" T1"); lcd.setCursor(0,1); lcd.print("-> T2"); break; } } delay(100); //от случайного двойного нажатия и залипания кнопки } } int read_LCD_buttons() { adc_key_in = analogRead(0); if (adc_key_in > 1000) return btnNONE; if (adc_key_in < 50) return btnRIGHT; if (adc_key_in < 250) return btnUP; if (adc_key_in < 450) return btnDOWN; if (adc_key_in < 650) return btnLEFT; if (adc_key_in < 850) return btnSELECT; return btnNONE; } void printTimeToLCD(){ RTC.getTime(); byte static prevSecond=0; if(RTC.second!=prevSecond){ lcd.setCursor(4,0); if (RTC.hour<10) lcd.print("0"); lcd.print(RTC.hour); lcd.print(":"); if (RTC.minute<10) lcd.print("0"); lcd.print(RTC.minute); lcd.print(":"); if (RTC.second<10) lcd.print("0"); lcd.print(RTC.second); prevSecond=RTC.second; } }1) Ничего не делаю - показывает время
2) Нажал на кнопку Селект - открылось меню с двумя пунктами: Т1 и Т2
3) Жду 20-30 сек и рестарт происходит (на время выкидывает)
---
Кароче, рестарт происходит даже когда время на экране идет.. не заходя в меню..
А вот при просмотре порта перезагрузка не происходит (об этом я уже писал выше):
#include <Wire.h>//для часов #include <DS1307new.h>//для часов #include <LiquidCrystal.h> // библиотека экрана LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int lcd_key = 0; int adc_key_in = 0; #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 bool key_menu=false; void setup(){ Serial.begin(9600); lcd.begin(16, 2); // запускаем библиотеку lcd.print("ST"); delay(2000); } void loop(){ static unsigned long prev=0; if(millis()-prev>1000){ Serial.println(millis()); // про Serial.begin в setup() не забудте prev=millis(); } if (key_menu==false) { printTimeToLCD(); // выводим время на экран lcd_key=read_LCD_buttons(); if (lcd_key==btnSELECT) { key_menu=true; lcd.clear(); //очищаем экран //выводим два пункта lcd.print("-> T1"); lcd.setCursor(0,1); lcd.print(" T2"); } } else { //При нажатии на кнопку key_menu стало =true //Теперь лупим по этй части кода, подругому быть не может //Никаких действий сдесь не происходит, пока //я не нажму дальше на нужную кнопку //В данный момент именно отсюда меня и выкидывает на время //если я ничего не нажимаю некоторое количество секунд //А вот так происходит переключение между пунктами //и дальнейшее действие при нажатии кнопки Select (вход в один из пунктов) lcd_key=read_LCD_buttons(); switch (lcd_key) { case btnSELECT: { //Сдесь будет дальнейшее действие break; } case btnUP: //переключение между двумя пунктами { lcd.clear(); //очищаем экран lcd.print("-> T1"); lcd.setCursor(0,1); lcd.print(" T2"); break; } case btnDOWN: //переключение между двумя пунктами { lcd.clear(); //очищаем экран lcd.print(" T1"); lcd.setCursor(0,1); lcd.print("-> T2"); break; } } delay(100); //от случайного двойного нажатия и залипания кнопки } } int read_LCD_buttons() { adc_key_in = analogRead(0); if (adc_key_in > 1000) return btnNONE; if (adc_key_in < 50) return btnRIGHT; if (adc_key_in < 250) return btnUP; if (adc_key_in < 450) return btnDOWN; if (adc_key_in < 650) return btnLEFT; if (adc_key_in < 850) return btnSELECT; return btnNONE; } void printTimeToLCD(){ RTC.getTime(); byte static prevSecond=0; if(RTC.second!=prevSecond){ lcd.setCursor(4,0); if (RTC.hour<10) lcd.print("0"); lcd.print(RTC.hour); lcd.print(":"); if (RTC.minute<10) lcd.print("0"); lcd.print(RTC.minute); lcd.print(":"); if (RTC.second<10) lcd.print("0"); lcd.print(RTC.second); prevSecond=RTC.second; } }Бред (
Я в #17 зачем-то взял и написал кусок кода. Наверное от нефиг делать. Вы же вставили "что-то свое". Которое оставляет гореть надпись ST, следовательно узнать о том произошел или нет рестарт микроконтроллера может телепатически. Вы так уверено говорите "происходит рестарт" - а с чего вы это взяли? Я такими методами диагностики - не владею.
>1) Ничего не делаю - показывает время
Все. Дальше можете ничего не говорить. Либо у вас ардуина работает на каких-то квантовых эффектах и почему-то не выполняет setup(), либо вы пускаете какой-то другой скетч. Ваш код и "как вы описываете его поведение" - явно не совпадают. А через плечо - вам никто заглянуть не может. Следовательно - и помочь тоже. Остается только причитать "не знаю что делать".
Ахаха, да просто не допонимаем друг друга... Залей скетч этот и посмотри что будет.
ps: в 17 посте просмотрел строчку lcd.clear().. но даже так видно будет там..
Ахаха, да просто не допонимаем друг друга... Залей скетч этот и посмотри что будет.
Ну так это же еще модуль часов нужно подключать.... лениво.... эх, ну ладно....
Залил. Вообще в меню не выходит. Как выяснилось неправильно детектится кнопка SELECT. Опознается как LEFT.
Поправил на
Все заработало. Меню нарисовало. Ушел пить кофе. Вернулся через 5-ть минут - меню на месте. Подождал еще 10-ть минут - без изменений.
P.S. По поводу "неправильно кнопка". Думал что вы где-то "отсебятину сделали". Ан нет - все точно как в примере производителя те же значения. Загрузил пример производителя - тоже нерпавильно детектит кнопки SELECT,LEFT. Причем, пару недель назад - все правильно он у меня детектил. Это не приятно. Значит эти цифры - сильно зависят от погоды (была жара, а сейчас прохладно и дождь давно идет). Значит этот шилд - требуют рекалибровки время от времени :( Менять цифры в read_LCD_buttons
Кароче, я вроде понял в чём у меня баг был... В питании, походу не хватает от usb. От внешнего блока запитал и перестало ресетится. Так что надо взять на заметку это дело.
Вообщем дайте не свою умозаключение "происходит рестарт", а симптомы дайте (у меня они не воспроизводятся).
Происходит у вас повторый вывод RST перед тем как "выкидывает на время" или нет?
"выкидывает на время" - это результат. мы ищем причину. пытаемся понять почему это происходит. Поэтому когда вы ставите знак равно между "выкидавает на время"=="рестартанулось" - это нулевая информация. Факт рестарта - нужно доказать. Вот если мы увидим что RST выводится повторно перед тем как "выкинуло на время" - вот только тогда можно сделать вывод "выкидывание на время означает рестарт". И искать причину рестарта. А до этого... это не более чем голословное утверждение. И боротся с рестартом если его нет... потеря времени. Точно так же как и "искать ошибку в логике", когда происходят рестарты. Вообщем мы на развилке, и пока вы не дадите намеков "куда идти нужно..." - шансы что-то поправить - малы.
100% это были рестарты и на 90% уверен что из-за питания. Т.к. переключил на чуть мощнее блок, чем usb и всё гладко. Так что вопрос снимается. Думаю стоит взять это на заметку, кто собирается работать на этом шилде.
Еслиб можно было залить видео для примера, показал бы.
Значит эти цифры - сильно зависят от погоды (была жара, а сейчас прохладно и дождь давно идет). Значит этот шилд - требуют рекалибровки время от времени :( Менять цифры в read_LCD_buttons
Это партнёры из оплота демократии под покровом ночи коды запуска сменили - так, чисто противотеррористическая профилактика.
Что там такого с плывущими параметрами интересно?
Что там такого с плывущими параметрами интересно?
Да я думал что вы бы уже по тому куску кода которыя я дал в качестве "поправил" - уже могли бы понять.
analogRead - начал возвращать чуть-чуть другие значения. "Поплыли" характеристики делителя напряжения видимо.
Ну вот набросал часть меню, еще таймер доделать надо.. Жду советов, багов..
#include <Wire.h>//для часов #include <DS1307new.h>//для часов #include <LiquidCrystal.h> // библиотека экрана #define btnRIGHT 0 #define btnUP 1 #define btnDOWN 2 #define btnLEFT 3 #define btnSELECT 4 #define btnNONE 5 LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int lcd_key = 0; int adc_key_in = 0; bool key_menu=false; bool clock_set=false; bool timer_set=false; int choice; int temp; int hours; int minutes; int seconds; int offsetLR; int offsetHMS; int UPDW; void setup(){ lcd.begin(16, 2); lcd.print("Loading..."); delay(500); lcd.clear(); } void loop(){ if (key_menu==false) { printTimeToLCD(); // выводим время на экран lcd_key=read_LCD_buttons(); if (lcd_key==btnSELECT) { tone(53, 250, 200); key_menu=true; choice=0; lcd.clear(); //очищаем экран lcd.print("-> Clock"); lcd.setCursor(0,1); lcd.print(" Timer"); } } else { if (clock_set==false&&timer_set==false) { delay(200); lcd_key=read_LCD_buttons(); switch (lcd_key) { case btnSELECT: { tone(53, 250, 200); if (choice==0) { lcd.clear(); lcd.print("--ClockSetting--"); lcd.setCursor(3,1); lcd.print("00h:00m:00s"); clock_set=true; temp=0; hours=0; minutes=0; seconds=0; offsetLR=0; offsetHMS=0; UPDW=0; Clock_Setting(); } else { if (choice==1) Timer_Setting(); else { key_menu=false; delay(200); } } break; } case btnUP: //переключение между пунктами { tone(53, 250, 200); choice--; if (choice>=0) { if (choice==0) { lcd.clear(); lcd.print("-> Clock"); lcd.setCursor(0,1); lcd.print(" Timer"); } else { lcd.clear(); lcd.print("-> Timer"); lcd.setCursor(0,1); lcd.print(" Exit"); } } else choice++; break; } case btnDOWN: //переключение между пунктами { tone(53, 250, 200); choice=choice+1; if (choice<=2) { if (choice==1) { lcd.clear(); lcd.print("-> Timer"); lcd.setCursor(0,1); lcd.print(" Exit"); } else { lcd.clear(); lcd.print(" Timer"); lcd.setCursor(0,1); lcd.print("-> Exit"); } } else choice--; break; } } } else { if (clock_set==true) Clock_Setting(); else Timer_Setting(); } } } void Clock_Setting() { delay(200); lcd_key=read_LCD_buttons(); switch (lcd_key) { case btnSELECT: { tone(53, 250, 200); RTC.stopClock(); RTC.fillByHMS(hours,minutes,seconds); RTC.setTime(); RTC.startClock(); key_menu=false; clock_set=false; delay(200); break; } case btnUP: { tone(53, 250, 200); if(temp<10) lcd.setCursor(4+offsetLR,1); else lcd.setCursor(3+offsetLR,1); lcd.print(temp); if (offsetLR==0) hours=temp; else { if (offsetLR==4) minutes=temp; else seconds=temp; } if(temp>23+offsetHMS) { lcd.setCursor(3+offsetLR,1); lcd.print("00"); temp=0; } temp++; UPDW=0; break; } case btnDOWN: { tone(53, 250, 200); if (temp!=0) { if (temp<11) { if (temp==10) { lcd.setCursor(3+offsetLR,1); lcd.print("00"); } lcd.setCursor(4+offsetLR,1); } else lcd.setCursor(3+offsetLR,1); temp--; } else { lcd.setCursor(3+offsetLR,1); temp=23+offsetHMS; } lcd.print(temp); if (offsetLR==0) hours=temp; else { if (offsetLR==4) minutes=temp; else seconds=temp; } UPDW=1; break; } case btnLEFT: { tone(53, 250, 200); if (offsetLR>0&&8>=offsetLR) { offsetLR=offsetLR-4; if (offsetLR==0) { offsetHMS=0; temp=hours; } else { offsetHMS=36; if (offsetLR==4) { seconds=temp; temp=minutes; } else temp=seconds; } } break; } case btnRIGHT: { tone(53, 250, 200); if (offsetLR>=0&&8>offsetLR) { offsetLR=offsetLR+4; if (offsetLR==0) { offsetHMS=0; temp=hours; } else { offsetHMS=36; if (offsetLR==4) temp=minutes; else temp=seconds; } } break; } } } void Timer_Setting() { } int read_LCD_buttons() { adc_key_in = analogRead(0); if (adc_key_in > 1000) return btnNONE; if (adc_key_in < 50) return btnRIGHT; if (adc_key_in < 250) return btnUP; if (adc_key_in < 450) return btnDOWN; if (adc_key_in < 650) return btnLEFT; if (adc_key_in < 850) return btnSELECT; return btnNONE; } void printTimeToLCD(){ RTC.getTime(); byte static prevSecond=0; if(RTC.second!=prevSecond) { lcd.clear(); lcd.setCursor(4,0); if (RTC.hour<10) lcd.print("0"); lcd.print(RTC.hour); lcd.print(":"); if (RTC.minute<10) lcd.print("0"); lcd.print(RTC.minute); lcd.print(":"); if (RTC.second<10) lcd.print("0"); lcd.print(RTC.second); prevSecond=RTC.second; } }ps: кнопки конечно не очень мягко говоря, поэтому приходится нажимать четко, не торопясь.
Да я думал что вы бы уже по тому куску кода которыя я дал в качестве "поправил" - уже могли бы понять.
analogRead - начал возвращать чуть-чуть другие значения. "Поплыли" характеристики делителя напряжения видимо.
У меня иногда случается слепое пятно, если увижу явно странное - считаю, что это я не так понял мудрый замысел.
Рулетка какая-то получается с кнопками на analogRead.
Ведь кнопка при таком подключении может отработать все значения в диапазоне подтяжки, заставляя срабатывать другие кнопки, попадающие в этот диапазон... даже, если считать, что ничего не плывёт.
Просто из-за неидеальности механического контакта, т.е.:
разомкнуто - сопротивление всегда стремится к бесконечности.
замкнуто - сопротивление уменьшается от бесконечности к нулю за определённый промежуток времени, но не мгновенно и не всегда к нулю... в процессе дребезга может принимать любые значения в диапазоне подтяжки.
*может чего не понимаю, но не могу себе представить мгновенной телепортации из adc_key_in > 1000 в adc_key_in < 50
*может чего не понимаю, но не могу себе представить мгновенной телепортации из adc_key_in > 1000 в adc_key_in < 50
Да все правильно вы поняли. Конечно у кнопки есть и дребезг, есть и время срабатывания. И фронт изменения никогда не будет абсолютно вертикальным. Но это не так смертельно. Вертикальных фронтов - их почти нигде никогда нет. В принципе - работают же эти кнопки. Довольно стабильно. Проблема возникла только когда СУЩЕСТВЕННО поменялись внешние условия. Причем начало не "принимать любые значения в диапазоне", а "стало принимать другие значения". Значит время сработки кнопки существенно меньше чем время замера АЦП (он же тоже - не моментальный). Ну а станет ощутимо - ну так "антидребезг" ничего не мешает прикрутить :) Думаю в любом случае буду его делать. Вероятность что описываемая вами проблема "вылезет" с износом кнопок - далеко не нулевая.
......
Как выяснилось неправильно детектится кнопка SELECT. Опознается как LEFT.
Поправил на
......
P.S. По поводу "неправильно кнопка". Думал что вы где-то "отсебятину сделали". Ан нет - все точно как в примере производителя те же значения. Загрузил пример производителя - тоже нерпавильно детектит кнопки SELECT,LEFT. Причем, пару недель назад - все правильно он у меня детектил. Это не приятно. Значит эти цифры - сильно зависят от погоды (была жара, а сейчас прохладно и дождь давно идет). Значит этот шилд - требуют рекалибровки время от времени :( Менять цифры в read_LCD_buttons
Как выяснилось - я сам себе злобный буратино. Дожди, фаза луны.... все оказалось банальней. Версия шилда. V1.0 и V1.1 - отличаются тем какие значение возвращает analogRead()
На самом шилде - не написана версия :(. Видимо когда купил его - проверил (и в чеке увидел правильную версию), а потом - забыл :( Был уверен что у меня V1.1. До тех пор пока не померял.
Самое интерестно, что по схеме - номиналы резисторов у V1.0 и V1.1 - не отличаются. Должны вести себя идентично. Мне кажется просто при производстве хомутнули - и поставили не те резисторы. Отличные от указаных в схематике. Потом спохватились и "правильную" партию решили назвать "V1.1" :)
Кстати, возможно будет интерестно. Я тут нагрофоманил как эти кнопки работают, почему именно такие цифры в коде Леший в мире Ардуины: Читаем аналоговые кнопки. Часть 1, свои танцы с выяснением какая версия шилда, ну и описание альтернативного подхода к чтению этих кнопок. Не как "в примере от производителя", а максимально близко к тому как мы читаем обычные цифровые кнопки с помощью digitalRead()
P.S. Кстати буду благодарен, если кто-то запустит у себя "калибровочный" скетч из статьи, и скажет какие показания на analogRead() он у него намерял. Хочу все это в види библиотеки оформить и нужны дефолтные значения, которые подходят как можно большему количеству людей.