Меню на LCD Keypad Shield

Now
Offline
Зарегистрирован: 13.09.2013
Пытаюсь сделать меню, вот пример:
#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х уровневого меню?
Now
Offline
Зарегистрирован: 13.09.2013

Точнее даже не 1-2 минуты, а 20 секунд постоянно, а потом скидываеь, как будето происходит рестарт.

Еще один вопрос: 3) Как можно вывести примерно такую конструкцию, вроде в c++ так работает, а тут нет:

int key1=23;
int key2=4;
 
lcd.print("Prim"+key1+"bahbax"+key2);

Ну и еще один: 4) Можно ли среду ардуины подключить к MSVSC++? Существую ли отладчики, для прогонки кода ардуины на выявление косяков?

leshak
Offline
Зарегистрирован: 29.09.2011

>1) Почему выводит вместо "NaNaNaNaNa" 10 первых ячеек, весь дисплей заполняется этими буквами?

А сколько раз у вас вызвается " lcd.print("NaNaNaNaNa"); ?  Куда по вашему должны выводится все последующие вызовы?

посмотрите на функцию printTimeToLCD(), там же этой проблемы нет. Сыграйте в игру "найди 10-ть отличий". Разберите построчно что происходит в этой функции.

Кстати ответ на этот вопрос поможет вам и с 

> Как можно вывести примерно такую конструкцию

Только тут как раз наоборот нужно воспользоватся этим эффектом, а не устранять его.

>вроде в c++ так работает,

Нет у нас тут конкатенации сишных строк. 

P.S. Отформатируйте код отступами, невозможно же читать где какой if начался, где закончился. Ну хотя-бы ctrl+T нажмите в ArdinoIDE

 

 

Now
Offline
Зарегистрирован: 13.09.2013

С этим понятно, разберусь. А вот почему выкидывает обратно на часы? это наверное главная для меня загадка

Now
Offline
Зарегистрирован: 13.09.2013

С этим понятно, разберусь. А вот почему выкидывает обратно на часы? это наверное главная для меня загадка

leshak
Offline
Зарегистрирован: 29.09.2011

>А вот почему выкидывает обратно на часы

А хрен его знает. Может действитель перегружается.

Добавте в 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

 

Now
Offline
Зарегистрирован: 13.09.2013

Прикол получается в том, что добавив действие в 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 секунд... 

Клапауций
Offline
Зарегистрирован: 10.02.2013

Now пишет:

 надпись начинает мерцать очень сильно (что понятно из-за lcd.clear) и выкидыват на время:

применяйте lcd.clear только для lcd.print нового значения - смысл лупить в индикатор одно и то же значение?

Now
Offline
Зарегистрирован: 13.09.2013

Дак я например могу вообще заменять clear на допустим  lcd.setCursor(0,0). Мерцать перестает. А вот из меню выкидыват точно также.

Цитата:

смысл лупить в индикатор одно и то же значение?

В этом смысла нету, но как иначе? Мне надо выводить на экран строки меню и ждать нжатий кнопки.

Клапауций
Offline
Зарегистрирован: 10.02.2013

Now пишет:

Дак я например могу вообще заменять clear на допустим  lcd.setCursor(0,0). Мерцать перестает. А вот из меню выкидыват точно также.

Я не особо вникал в ваш код, но в принципе не могу понять вкуда вас может выкидывать - меню есть переменная, которую вы печатаете на экран, какое бы значение ваша переменная не приняла, должно отображаться хоть что-то.

Клапауций
Offline
Зарегистрирован: 10.02.2013

Now пишет:

В этом смысла нету, но как иначе? Мне надо выводить на экран строки меню и ждать нжатий кнопки.

меню экрана есть реакция на изменение или сама переменная - нет изменения, нет print, нет мигания.

Now
Offline
Зарегистрирован: 13.09.2013

Можно сказать хочу сделать часы с настройками. По дефолту на экране отображается только время. При нажатии на кнопку Select открывается текстовое меню. В нём хочу переключаться между пунктами и заходить в нужный.. Это цель.

 Время выводит нормльно. Когда я жму кнопку Select меня как бы забрасывает в меню (в примере выше, просто на текстовое поле "Na.."), дальше мне нужно ждать дальнейших нажатий клавишь, попросту ничего не делать. Дак вот, отсюда меня и выкидывает обратно на время (по видемому рестартится ардуина).

---

А существуют ли функции ожидания ответа (нажатия клавиши)? т.е. цикл останавливается и ждет пока на пин придет заданное значение... 

Возможно с помощью прерываний это делается?

Клапауций
Offline
Зарегистрирован: 10.02.2013

изменения состояния кнопок нужно писать в переменные - тогда и не будет выбрасывать.

считайте, что у вас есть консольная прога без гуя вообще, прога реагирует на нажания кнопок, что делают кнопки? - изменяют своё состояние и, если это состояние зависит от количества нажатий, копбинаций, прочего, то это состояние не просто LOW/HIGH, а 0, 1, 2, 3, ...

Значит - кнопка Select должна менять переменную Select с "0" на "1" при первом нажатии и обратно при повторном нажатии.

Кнопы DOWN, UP и прочие навигационные изменять переменную, допустим, "menu" с "0" до "5"(если у вас шесть строк меню)

т.е. DOWN увеличивает переменную menu на 1, UP - уменьшает.

все новые значения обновляются и запоминаются, изменения сравниваются с предыдущими, если выявляется разница - печатается в индикатор.

в итоге - Select вас будет забрасывать/выбрасывать из меню, DOWN/UP - навигация вверх/вниз по меню, может понадобится кнопа типо "ENTER" для запоминания/ввода значения.

Это типо концептуальный набросок логики.

 

Now
Offline
Зарегистрирован: 13.09.2013

Вопрос не в логике (с ней думаю сам разберусь), а совсем в другом. Посмотрите повнимательнее.

Клапауций
Offline
Зарегистрирован: 10.02.2013

Now пишет:

А существуют ли функции ожидания ответа (нажатия клавиши)? т.е. цикл останавливается и ждет пока на пин придет заданное значение... 

Не нужно ничего ждать - контроллер гоняет программу по кругу, вам остаётся только рулить на поворотах на полной скорости.

примерно так:

// int b = 0; в начале инициализировано

void BUTTON() {
int nb = digitalRead(3);
if (nb != b) {
b = nb;
if (digitalRead(3) == LOW) {что то делаем один раз при нажатии;}
if (digitalRead(3) == HIGH) {что то делаем один раз при отпускании;}
}
}

 

*Лешак раскритикует, но я это так понимаю.

leshak
Offline
Зарегистрирован: 29.09.2011

>*Лешак раскритикует, но я это так понимаю.

А то :)  Где отступы? Зачем же новичков учить так писать? Так - он уже умеет :)

>А существуют ли функции ожидания ответа (нажатия клавиши)?

Не существует. Зато существует прикрепленная ветка Работа с кнопками. В помощь новичку.

>А вот если без вашего кода, которые вызывает большую задержку

Не вызывает он большой задержки. Ну несколько микросекунд на вызов millis() и раз в секунду на выполенение println

Можете попробовыть выкинуть мой код еще сделать lcd.print("RESET"); delaa(2000) в самом setup(). Тогда никаких "задержке" не будет, зато будет видно когда контроллер перегрузился.

>Можно сказать хочу сделать часы с настройками.

Хе-хе... я тоже тем же занимаюсь... с описанием процесса в блоге. Только ОЧЕНЬ медленно. Только по выходным, да и то не каждым удается продвинутся по чуть-чуть... :(  Мне вообще-то даже что-то знакомое/родное почудилось в функции printTimeToLCD()  ;)

Now
Offline
Зарегистрирован: 13.09.2013

Вот кусок дальнейшей моей логики прикинул:

#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; 
  }
}


Цитата:
Можете попробовыть выкинуть мой код еще сделать lcd.print("RESET"); delaa(2000) в самом setup(). Тогда никаких "задержке" не будет, зато будет видно когда контроллер перегрузился.

Имелось ввиду вот так:

#include <LiquidCrystal.h> // библиотека экрана
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);


void setup(){
  delay(2000);
  lcd.print("RES");
}

void loop(){
}

Точно также рестарт происходит, раз в 20-30 секунд.. я так понимаю от бездействия.. 

Цитата:
Мне вообще-то даже что-то знакомое/родное почудилось в функции printTimeToLCD()  ;)

Так и есть, у меня второй день знакомства с ардуиной пошел) 

leshak
Offline
Зарегистрирован: 29.09.2011

>Имелось ввиду вот так:

Нет. Смысл в таком коде? Что вы сделали: при включении задержку (вместо того что-бы запустить библиотеку). Вывели надпись... и все.

Какую дополнительную информацию, для размышления вы получили в результате этого кода?  А никакой.

вам нужно было.

#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(){
  ..... тут ваш остальной код....
}

Тогда при старте - будет выводится надпись. Если она выводится один раз, при включении - все нормально. Если она будет повторно выводится, перед тем как "оно выскочело из меню" - значит происходят перезагрузки.

Now
Offline
Зарегистрирован: 13.09.2013

Цитата:
Какую дополнительную информацию, для размышления вы получили в результате этого кода?  А никакой.

Что всётаки ардуина точно также рестартится, если ничего не происходит в лупе.

Цитата:
вам нужно было.

Тогда при старте - будет выводится надпись. Если она выводится один раз, при включении - все нормально. Если она будет повторно выводится, перед тем как "оно выскочело из меню" - значит происходят перезагрузки.

Точно также рестартится и таким образом тоже. Причина вроде как одна - бездействие в лупе.

А вот как решить такую проблему, я хз.

leshak
Offline
Зарегистрирован: 29.09.2011

Now пишет:

Точно также рестарт происходит, раз в 20-30 секунд.. я так понимаю от бездействия.. 

Цитата:
Мне вообще-то даже что-то знакомое/родное почудилось в функции printTimeToLCD()  ;)

Так и есть, у меня второй день знакомства с ардуиной пошел) 

Ну значит "я не ошибся" :)  Но явно "чуток под себя подпилии" ее ;)

Я тоже буду делать (возможно сегодня) выставление времени с помощью кнопок.

Только... вначале хочу вообще по другому чтение кнопок сделать. С антидребезгом, что-бы кнопки читались не толкько шилдовые, но и еще добавлять можно было. На A1,A0, обычные цифровые кнопки и т.п.. И что-бы "стиль" чтения кнопок был похожим на обычный digitalRead. Тогда все "приемы" которые описаны в ветках типа "учимся работать с кнопками" - можно будет применять "в лоб". Ну и еще хочется ловить вещи типа "длинное нажатие/удержание" и т.п. Вообщем - наполеоновские планы ;)

 

leshak
Offline
Зарегистрирован: 29.09.2011

Now пишет:

Цитата:
Какую дополнительную информацию, для размышления вы получили в результате этого кода?  А никакой.

Что всётаки ардуина точно также рестартится, если ничего не происходит в лупе.

Тот код что вы привели - не может ничего сказать о рестартах. Он выводит надпись при СТАРТЕ и все. Надпись висит. В момент РЕСТАРТА - ничего видимого происходить у вас не будет.

Now пишет:

Цитата:
вам нужно было.

Тогда при старте - будет выводится надпись. Если она выводится один раз, при включении - все нормально. Если она будет повторно выводится, перед тем как "оно выскочело из меню" - значит происходят перезагрузки.

Точно также рестартится и таким образом тоже. Причина вроде как одна - бездействие в лупе.

А вот как решить такую проблему, я хз.

Учитывая что "рестартится" вы диагностировали не верно. Сделайте две вещи:

1. Дайте код с моей добавкой которую вы запускали
2. Постарайтесь детально описать "что вы видите/делаете": "вывелась надпись.... повисела 2 сек... исчезла... нажал кнопку.... увидел то-то..... через какое-то время.... увидел то-то...".

Постарайтесь ничего не упускать, типа "открыл сериал монитор" и т.п.

Now
Offline
Зарегистрирован: 13.09.2013

Цитата:
Тот код что вы привели - не может ничего сказать о рестартах. Он выводит надпись при СТАРТЕ и все. Надпись висит. В момент РЕСТАРТА - ничего видимого происходить у вас не будет.

Будет пропадать надпись на 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; 
  }
}



Бред (

leshak
Offline
Зарегистрирован: 29.09.2011

Я в #17 зачем-то взял и написал кусок кода. Наверное от нефиг делать. Вы же вставили "что-то свое". Которое оставляет гореть надпись ST, следовательно узнать о том произошел или нет рестарт микроконтроллера может телепатически. Вы так уверено говорите "происходит рестарт" - а с чего вы это взяли?  Я такими методами диагностики - не владею.

>1) Ничего не делаю - показывает время

Все. Дальше можете ничего не говорить. Либо у вас ардуина работает на каких-то квантовых эффектах и почему-то не выполняет setup(), либо вы пускаете какой-то другой скетч. Ваш код и "как вы описываете его поведение" - явно не совпадают. А через плечо - вам никто заглянуть не может. Следовательно - и помочь тоже. Остается только причитать "не знаю что делать".

Now
Offline
Зарегистрирован: 13.09.2013

Ахаха, да просто не допонимаем друг друга... Залей скетч этот и посмотри что будет.

ps: в 17 посте просмотрел строчку lcd.clear().. но даже так видно будет там..

leshak
Offline
Зарегистрирован: 29.09.2011

Now пишет:

Ахаха, да просто не допонимаем друг друга... Залей скетч этот и посмотри что будет.

Ну так это же еще модуль часов нужно подключать.... лениво.... эх, ну ладно....

Залил. Вообще в меню не выходит. Как выяснилось неправильно детектится кнопка SELECT. Опознается как LEFT.

Поправил на 

if (adc_key_in < 550)  return btnLEFT; 

Все заработало. Меню нарисовало. Ушел пить кофе. Вернулся через 5-ть минут - меню на месте. Подождал еще 10-ть минут - без изменений.

P.S. По поводу "неправильно кнопка". Думал что вы где-то "отсебятину сделали". Ан нет - все точно как в примере производителя те же значения. Загрузил пример производителя - тоже нерпавильно детектит кнопки SELECT,LEFT. Причем, пару недель назад - все правильно он у меня детектил. Это не приятно. Значит эти цифры - сильно зависят от погоды (была жара, а сейчас прохладно и дождь давно идет). Значит этот шилд - требуют рекалибровки время от времени :(  Менять цифры в read_LCD_buttons

Now
Offline
Зарегистрирован: 13.09.2013

Кароче, я вроде понял в чём у меня баг был... В питании, походу не хватает от usb. От внешнего блока запитал и перестало ресетится. Так что надо взять на заметку это дело. 

leshak
Offline
Зарегистрирован: 29.09.2011

Вообщем дайте не свою умозаключение "происходит рестарт", а симптомы дайте (у меня они не воспроизводятся).

Происходит у вас повторый вывод RST перед тем как "выкидывает на время" или нет?

"выкидывает на время" - это результат. мы ищем причину. пытаемся понять почему это происходит. Поэтому когда вы ставите знак равно между "выкидавает на время"=="рестартанулось" - это нулевая информация. Факт рестарта - нужно доказать. Вот если мы увидим что RST выводится повторно  перед тем как "выкинуло на время" - вот только тогда можно сделать вывод "выкидывание на время означает рестарт". И искать причину рестарта. А до этого... это не более чем голословное утверждение. И боротся с рестартом если его нет... потеря времени. Точно так же как и "искать ошибку в логике", когда происходят рестарты. Вообщем мы на развилке, и пока вы не дадите намеков "куда идти нужно..." - шансы что-то поправить - малы.

Now
Offline
Зарегистрирован: 13.09.2013

100% это были рестарты и на 90% уверен что из-за питания. Т.к. переключил на чуть мощнее блок, чем usb и всё гладко. Так что вопрос снимается. Думаю стоит взять это на заметку, кто собирается работать на этом шилде.

Еслиб можно было залить видео для примера, показал бы.

Клапауций
Offline
Зарегистрирован: 10.02.2013

leshak пишет:

Значит эти цифры - сильно зависят от погоды (была жара, а сейчас прохладно и дождь давно идет). Значит этот шилд - требуют рекалибровки время от времени :(  Менять цифры в read_LCD_buttons

Это партнёры из оплота демократии под покровом ночи коды запуска сменили - так, чисто противотеррористическая профилактика.

Что там такого с плывущими параметрами интересно?

leshak
Offline
Зарегистрирован: 29.09.2011

Клапауций пишет:

Что там такого с плывущими параметрами интересно?

Да я думал что вы бы уже по тому куску кода которыя я дал в качестве "поправил" - уже могли бы понять.

analogRead - начал возвращать чуть-чуть другие значения. "Поплыли" характеристики делителя напряжения видимо.

Now
Offline
Зарегистрирован: 13.09.2013

Ну вот набросал часть меню, еще таймер доделать надо.. Жду советов, багов.. 

#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: кнопки конечно не очень мягко говоря, поэтому приходится нажимать четко, не торопясь.

Клапауций
Offline
Зарегистрирован: 10.02.2013

leshak пишет:

Да я думал что вы бы уже по тому куску кода которыя я дал в качестве "поправил" - уже могли бы понять.

analogRead - начал возвращать чуть-чуть другие значения. "Поплыли" характеристики делителя напряжения видимо.

У меня иногда случается слепое пятно, если увижу явно странное - считаю, что это я не так понял мудрый замысел.

Рулетка какая-то получается с кнопками на analogRead.

Ведь кнопка при таком подключении может отработать все значения в диапазоне подтяжки, заставляя срабатывать другие кнопки, попадающие в этот диапазон... даже, если считать, что ничего не плывёт.

Просто из-за неидеальности механического контакта, т.е.:

разомкнуто - сопротивление всегда стремится к бесконечности.

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

*может чего не понимаю, но не могу себе представить мгновенной телепортации из adc_key_in > 1000 в adc_key_in < 50

leshak
Offline
Зарегистрирован: 29.09.2011

Клапауций пишет:

*может чего не понимаю, но не могу себе представить мгновенной телепортации из adc_key_in > 1000 в adc_key_in < 50

Да все правильно вы поняли. Конечно у кнопки есть и дребезг, есть и время срабатывания. И фронт изменения никогда не будет абсолютно вертикальным. Но это не так смертельно. Вертикальных фронтов - их почти нигде никогда нет. В принципе - работают же эти кнопки. Довольно стабильно. Проблема возникла только когда СУЩЕСТВЕННО поменялись внешние условия. Причем начало не "принимать любые значения в диапазоне", а "стало принимать другие значения". Значит время сработки кнопки существенно меньше чем время замера АЦП (он же тоже - не моментальный). Ну а станет ощутимо - ну так "антидребезг" ничего не мешает прикрутить :) Думаю в любом случае буду его делать. Вероятность что описываемая вами проблема "вылезет" с износом кнопок - далеко не нулевая.

leshak
Offline
Зарегистрирован: 29.09.2011

leshak пишет:

......

Как выяснилось неправильно детектится кнопка SELECT. Опознается как LEFT.

Поправил на 

if (adc_key_in < 550)  return btnLEFT; 

......

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() он у него намерял. Хочу все это в види библиотеки оформить и нужны дефолтные значения, которые подходят как можно большему количеству людей.