П`ятниця, 29.03.2024, 18:44
Приветствую Вас Гість | RSS

Radiomanoff+

Меню сайта
Форма входа
Календарь
«  Березень 2024  »
ПнВтСрЧтПтСбНд
    123
45678910
11121314151617
18192021222324
25262728293031

Меню для Arduino(Atmega32)

The menu for the Arduino (Atmega32).



Заинтересовался вопросом : меню для Arduino.На помощь пришел всемогущий Google.На его бескрайних просторах нашелся и источник для вдохновения www.coagula.org .

Структура меню :

Главное меню
             |
     Меню_1 -------------------------------------------------- Меню_2 ------------------------------------------------------------------ Меню_3
          |                                                                   |
Подменю 1_1 ---- Подменю 1_2           Подменю 2_1 ---- Подменю 2_2 ---- Подменю 2_3

Используется LCD MTC-16204X  на контролере HD44780,совместимый с обычным LCD 1602 и поддерживающий кирилицу.

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

     

Cхема подключений :


Фото собраной схемы :



Скетч.

Библиотека MenuBackend для Arduino IDE 1.0.4 - cкачать .

Первым делом я занялся переводом статьи и скетча с www.coagula.org .Оказалось что для нормальной компиляции и работы скетча необходимо вносить изменения в файл MenuBackend.h. 
Добавляются следующие строки в линии 195 MenuBackend.h файла, непосредственно перед строкой "private" :

void toRoot ( ) {
       

        setCurrent ( &getRoot ( ) );
   } 


Это сделано для того, чтобы иметь возможность легко вернуться c любого подменю в корень меню, нажатием кнопки ESC.
В самом скетче организована програмная реализация "антидребезга" кнопок. Для LCD применяется библиотека LiquidCrystalRus -  скачать .

Немного русифициррованый скетч скачать :

/*
IMPORTANT: to use the menubackend library by Alexander Brevig download it at http://www.arduino.cc/playground/uploads/Profiles/MenuBackend_1-4.zip and add the next code at line 195
    void toRoot() {
        setCurrent( &getRoot() );
    }
*/
#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystalRus.h>  //this library is included in the Arduino IDE

const int buttonPinLeft = 12;      // pin for the Up button
                                  // контакт для кнопки "Вверх"
const int buttonPinRight = 11;    // pin for the Down button     "вниз"
const int buttonPinEsc = 14;     // pin for the Esc button      "выход"
const int buttonPinEnter = 15;   // pin for the Enter button    "вход"

int lastButtonPushed = 0;

int lastButtonEnterState = LOW;   // the previous reading from the Enter input pin
int lastButtonEscState = LOW;   // the previous reading from the Esc input pin
int lastButtonLeftState = LOW;   // the previous reading from the Left input pin
int lastButtonRightState = LOW;   // the previous reading from the Right input pin


long lastEnterDebounceTime = 0;  // the last time the output pin was toggled
long lastEscDebounceTime = 0;  // the last time the output pin was toggled
long lastLeftDebounceTime = 0;  // the last time the output pin was toggled
long lastRightDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 500;    // the debounce time

// LiquidCrystal display with:
LiquidCrystalRus lcd(9, 6, 5, 4, 3, 2);

//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
//инициализации пунктов меню
    MenuItem menu1Item1 = MenuItem("меню_1");
      MenuItem menuItem1SubItem1 = MenuItem("подменю1_1");
      MenuItem menuItem1SubItem2 = MenuItem("подменю1_2");
    MenuItem menu1Item2 = MenuItem("меню_2");
      MenuItem menuItem2SubItem1 = MenuItem("подменю2_1");
      MenuItem menuItem2SubItem2 = MenuItem("подменю2_2");
      MenuItem menuItem3SubItem3 = MenuItem("подменю2_3");
    MenuItem menu1Item3 = MenuItem("меню_3");


void setup()
{
  pinMode(buttonPinLeft, INPUT);
  pinMode(buttonPinRight, INPUT);
  pinMode(buttonPinEnter, INPUT);
  pinMode(buttonPinEsc, INPUT);
  
  lcd.begin(16, 2);

  //configure menu
  //настроить меню
  menu.getRoot().add(menu1Item1);
  menu1Item1.addRight(menu1Item2).addRight(menu1Item3);
  menu1Item1.add(menuItem1SubItem1).addRight(menuItem1SubItem2);
  menu1Item2.add(menuItem2SubItem1).addRight(menuItem2SubItem2).addRight(menuItem3SubItem3);
  menu.toRoot();
  lcd.setCursor(0,0);  
  lcd.print("Меню для Arduino");

}  // setup()...


void loop()
{

  readButtons();  //I splitted button reading and navigation in two procedures because 
                  //Я разделил чтения и навигации кнопки в двух процедур, поскольку
  navigateMenus();  //in some situations I want to use the button for other purpose (eg. to change some settings)
                    //В некоторых ситуациях я хочу использовать кнопки для других целей (например, для изменения настроек)
                  
} //loop()... 


void menuChanged(MenuChangeEvent changed){
  
  MenuItem newMenuItem=changed.to; //get the destination menu
  
  lcd.setCursor(0,1); //set the start position for lcd printing to the second row
  
  if(newMenuItem.getName()==menu.getRoot()){
      lcd.print("Главное меню      ");
  }else if(newMenuItem.getName()=="меню_1"){
      lcd.print("меню_1            ");
  }else if(newMenuItem.getName()=="подменю1_1"){
      lcd.print("подменю1_1        ");
  }else if(newMenuItem.getName()=="подменю1_2"){
      lcd.print("подменю1_2        ");
  }else if(newMenuItem.getName()=="меню_2"){
      lcd.print("меню_2             ");
  }else if(newMenuItem.getName()=="подменю2_1"){
      lcd.print("подменю2_1   ");
  }else if(newMenuItem.getName()=="подменю2_2"){
      lcd.print("подменю2_2   ");
  }else if(newMenuItem.getName()=="подменю2_3"){
      lcd.print("подменю2_3   ");
  }else if(newMenuItem.getName()=="меню_3"){
      lcd.print("меню_3             ");
  }
}

void menuUsed(MenuUseEvent used){
  lcd.setCursor(0,0);  
  lcd.print("Вы использовали        ");
  lcd.setCursor(0,1); 
  lcd.print(used.item.getName());
  delay(3000);  //delay to allow message reading - чтобы задержать чтении сообщение
  lcd.setCursor(0,0);  
  lcd.print("Меню для Arduino");
  menu.toRoot();  //back to Main
}


void  readButtons(){  //read buttons status
  int reading;
  int buttonEnterState=LOW;             // the current reading from the Enter input pin
  int buttonEscState=LOW;             // the current reading from the input pin
  int buttonLeftState=LOW;             // the current reading from the input pin
  int buttonRightState=LOW;             // the current reading from the input pin

  //Enter button - кнопка Enter
                  // read the state of the switch into a local variable:
                  // читать состояние переключателя в локальную переменную:
                  reading = digitalRead(buttonPinEnter);

                  // check to see if you just pressed the enter button 
                  // (i.e. the input went from LOW to HIGH),  and you've waited 
                  // long enough since the last press to ignore any noise:  
                
                  // Проверяем, если вы только что нажал на кнопку ввода
                  // (Т.е. входные пошел от низкой до высокой), а вы ждали
                  // Достаточно долго, с момента последней пресс игнорировать любые шумы:
                
                  // If the switch changed, due to noise or pressing:
                  // Если переключатель изменилась, из-за шума или нажатие:
                  if (reading != lastButtonEnterState) {
                    // reset the debouncing timer
                    // Сброс таймера дребезга
                    lastEnterDebounceTime = millis();
                  } 
                  
                  if ((millis() - lastEnterDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    // Все, что показания на, он был там дольше
                    // Чем дребезга задержки, так что принять его в качестве фактического текущего состояния:
                    buttonEnterState=reading;
                    lastEnterDebounceTime=millis();
                  }
                  
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  // Сохранить чтении. В следующий раз через loop,
                  // Это будет lastButtonState:
                  lastButtonEnterState = reading;
                  

    //Esc button               
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinEsc);

                  // check to see if you just pressed the Down button 
                  // (i.e. the input went from LOW to HIGH),  and you've waited 
                  // long enough since the last press to ignore any noise:  
                
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonEscState) {
                    // reset the debouncing timer
                    lastEscDebounceTime = millis();
                  } 
                  
                  if ((millis() - lastEscDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonEscState = reading;
                    lastEscDebounceTime=millis();
                  }
                  
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonEscState = reading; 
                  
                     
   //Down button               
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinRight);

                  // check to see if you just pressed the Down button 
                  // (i.e. the input went from LOW to HIGH),  and you've waited 
                  // long enough since the last press to ignore any noise:  
                
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonRightState) {
                    // reset the debouncing timer
                    lastRightDebounceTime = millis();
                  } 
                  
                  if ((millis() - lastRightDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonRightState = reading;
                   lastRightDebounceTime =millis();
                  }
                  
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonRightState = reading;                  
                  
                  
    //Up button               
                  // read the state of the switch into a local variable:
                  reading = digitalRead(buttonPinLeft);

                  // check to see if you just pressed the Down button 
                  // (i.e. the input went from LOW to HIGH),  and you've waited 
                  // long enough since the last press to ignore any noise:  
                
                  // If the switch changed, due to noise or pressing:
                  if (reading != lastButtonLeftState) {
                    // reset the debouncing timer
                    lastLeftDebounceTime = millis();
                  } 
                  
                  if ((millis() - lastLeftDebounceTime) > debounceDelay) {
                    // whatever the reading is at, it's been there for longer
                    // than the debounce delay, so take it as the actual current state:
                    buttonLeftState = reading;
                    lastLeftDebounceTime=millis();;
                  }
                  
                  // save the reading.  Next time through the loop,
                  // it'll be the lastButtonState:
                  lastButtonLeftState = reading;  

                  //records which button has been pressed
                  //запись, какая кнопка была нажата
                  if (buttonEnterState==HIGH){
                    lastButtonPushed=buttonPinEnter;

                  }else if(buttonEscState==HIGH){
                    lastButtonPushed=buttonPinEsc;

                  }else if(buttonRightState==HIGH){
                    lastButtonPushed=buttonPinRight;

                  }else if(buttonLeftState==HIGH){
                    lastButtonPushed=buttonPinLeft;

                  }else{
                    lastButtonPushed=0;
                  }                  
}

void navigateMenus() {
  MenuItem currentMenu=menu.getCurrent();
  
  switch (lastButtonPushed){
    case buttonPinEnter:
      if(!(currentMenu.moveDown())){  //if the current menu has a child and has been pressed enter then menu navigate to item below
                                      //Если в текущем меню есть подменю, и была нажата, то введите меню перейдите к пункту ниже
        menu.use();
      }else{  //otherwise, if menu has no child and has been pressed enter the current menu is used
              //Иначе, если меню не имеет подменю и была нажата Enter текущее меню используется
        menu.moveDown();
       } 
      break;
    case buttonPinEsc:
      menu.toRoot();  //back to main - Вернуться на главную
      break;
    case buttonPinRight:
      menu.moveRight();
      break;      
    case buttonPinLeft:
      menu.moveLeft();
      break;      
  }
  
  lastButtonPushed=0; //reset the lastButtonPushed variable
                      //сбросить переменную lastButtonPushed
}



Архив записей
Статистика

Онлайн всього: 1
Гостей: 1
Користувачів: 0