วันอาทิตย์ที่ 13 มีนาคม พ.ศ. 2559

ตัวอย่างการใช้ menubackend library กับ arduino

/*
    Copyright Giuseppe Di Cillo (www.coagula.org)
    Contact: dicillo@coagula.org
   
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/



/*
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 "DHT.h"
#include <EEPROM.h>
#include <MenuBackend.h>    //MenuBackend library - copyright by Alexander Brevig
#include <LiquidCrystal.h>  //this library is included in the Arduino IDE

#define DHTPIN 10     // what digital pin we're connected to

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11
//#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
//#define DHTTYPE DHT21   // DHT 21 (AM2301)
DHT dht(DHTPIN, DHTTYPE);

unsigned long previousMillis=0;
int intervalDHT = 1000;

const int buttonPinLeft = 6;      // pin for the Up button
const int buttonPinRight = 7;    // pin for the Down button
const int buttonPinEsc = 8;     // pin for the Esc button
const int buttonPinEnter = 9;   // pin for the Enter button

const int PinRelay = 13;   // pin for the Relay

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

int flag1 = 0;
const int addrMinNote=5;    //address in EEPROM to store minimum note
const int addrMaxNote=6;    //address in EEPROM to store maximum note
const int addrPlayMode=8;  //address in EEPROM to store the play mode

//constants to identify different status
const int statusPlayMode1=1;
const int statusRun=2;

//constants to identify different status
const int statusSetMinNote=7;
const int statusSetMaxNote=8;

char strSetMinimumNote[17] = "Set minimum     ";
char strSetMaximumNote[17] = "Set maximum     ";

int currentStatusMode;
int lastPlayingMode;

int minNoteSetting;
int maxNoteSetting;

int minNote=0;
int maxNote=100;
// LiquidCrystal display with:
// rs on pin 7
// rw on ground
// enable on pin 6
// d4, d5, d6, d7 on pins 5, 4, 3, 2
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

//Menu variables
MenuBackend menu = MenuBackend(menuUsed,menuChanged);
//initialize menuitems
    MenuItem menu1Item1 = MenuItem("Item1");
      MenuItem menuItem1SubItem1 = MenuItem("Item1SubItem1");
      MenuItem menuItem1SubItem2 = MenuItem("Item1SubItem2");
    MenuItem menu1Item2 = MenuItem("Item2");
      MenuItem menuItemMinNote = MenuItem("menuItemMinNote");
      MenuItem menuItemMaxNote = MenuItem("menuItemMaxNote");
      MenuItem menuItem3SubItem3 = MenuItem("Item2SubItem3");
    MenuItem menu1Item3 = MenuItem("Item3");


void setup()
{
  pinMode(PinRelay,OUTPUT);
  digitalWrite(PinRelay, HIGH);
 
 
  pinMode(buttonPinLeft, INPUT);
  pinMode(buttonPinRight, INPUT);
  pinMode(buttonPinEnter, INPUT);
  pinMode(buttonPinEsc, INPUT);
 
  dht.begin();
 
  lcd.begin(16, 2);

 minNoteSetting=EEPROM.read(addrMinNote);
 if (minNoteSetting==255){
        currentStatusMode=statusPlayMode1;//default
        EEPROM.write(addrMinNote, minNote);
        EEPROM.write(addrMaxNote, maxNote);
       
        EEPROM.write(addrPlayMode, currentStatusMode);
 }else{
        minNote=EEPROM.read(addrMinNote); //read fromm EEPROM the stored minimum note
        maxNote=EEPROM.read(addrMaxNote); //read fromm EEPROM the stored maximum note

        currentStatusMode=EEPROM.read(addrPlayMode); //read fromm EEPROM the stored play mode
  }
 
  //configure menu
  menu.getRoot().add(menu1Item1);
  menu1Item1.addRight(menu1Item2).addRight(menu1Item3);
  menu1Item1.add(menuItem1SubItem1).addRight(menuItem1SubItem2);
  menu1Item2.add(menuItemMinNote).addRight(menuItemMaxNote).addRight(menuItem3SubItem3);
  //menu.toRoot();
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("LOADING..");
  lcd.noDisplay();
  delay(500);
  lcd.display();
  delay(500);
  lcd.noDisplay();
  delay(500);
  lcd.display();
  delay(500);
  lcd.noDisplay();
  delay(500);
  lcd.display();
  delay(500);
 
  currentStatusMode = statusRun;

}  // setup()...


void loop()
{
unsigned long currentMillis = millis();

          // Read temperature as Fahrenheit (isFahrenheit = true)
readButtons();  //I splitted button reading and navigation in two procedures because
char strSetting[21] = "CC ";
  char sett[4];
  switch(currentStatusMode){
      case statusPlayMode1: //playing mode 1
        navigateMenus();  //in some situations I want to use the button for other purpose (eg. to change some settings)            
        break;
      case statusRun: //playing mode 1
          // time to toggle LED on Pin 12?
         if ((unsigned long)(currentMillis - previousMillis) >= intervalDHT) {
              float h1;
              h1 =dht.readHumidity();
              // Read temperature as Celsius (the default)
              float t1;
              t1 = dht.readTemperature();
                // save current time to pin 12's previousMillis
              if(t1<=minNote){
                digitalWrite(PinRelay, HIGH);
              }
              if(t1>=maxNote){
                digitalWrite(PinRelay, LOW);
              }
              lcd.clear();
              lcd.setCursor(0,0);
              lcd.print("Hum: ");
              lcd.setCursor(8,0);
              lcd.print(h1);
              lcd.setCursor(0,1);
              lcd.print("Temp: ");
              lcd.setCursor(8,1);
              lcd.print(t1);
               
              previousMillis = currentMillis;
         }
          // Wait a few seconds between measurements.
         // delay(2000);
          // Reading temperature or humidity takes about 250 milliseconds!
          // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)

         

               
        if(lastButtonPushed==buttonPinEsc){
            currentStatusMode = statusPlayMode1;
            menu.toRoot();
        }      
        break;    
      case statusSetMinNote:    //set min note
        switch (lastButtonPushed){
            case buttonPinEnter://set the new minimum note and go back to the main screen
              minNote=minNoteSetting;
              currentStatusMode=lastPlayingMode;
              EEPROM.write(addrMinNote, minNote);
              menu.toRoot();
              break;
            case buttonPinEsc://go back to the main screen
              minNoteSetting=minNote;
              currentStatusMode=lastPlayingMode;
              menu.toRoot();
              break;
            case buttonPinRight://increase minimum note
              if(minNoteSetting<100&&minNoteSetting<maxNote){
                minNoteSetting=minNoteSetting+1;
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print(strSetMinimumNote);
                lcd.setCursor(0,1);
                lcd.print(minNoteSetting);
              }
              break;    
            case buttonPinLeft://decrease minimum note
              if(minNoteSetting>0){
                minNoteSetting=minNoteSetting-1;
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print(strSetMinimumNote);
                lcd.setCursor(0,1);
                lcd.print(minNoteSetting);
              }
              break;
          }
     
          break;
      case statusSetMaxNote:    //set max note
       switch (lastButtonPushed){  
            case buttonPinEnter://set the new maximum note and go back to the main screen
              maxNote=maxNoteSetting;
              currentStatusMode=lastPlayingMode;
              EEPROM.write(addrMaxNote, maxNote);
              menu.toRoot();
              break;
            case buttonPinEsc://go back to the main screen
              maxNoteSetting=maxNote;
              currentStatusMode=lastPlayingMode;
              menu.toRoot();
              break;
            case buttonPinRight://increase maximum note
              if(maxNoteSetting<100){
                maxNoteSetting=maxNoteSetting+1;
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print(strSetMaximumNote);
                lcd.setCursor(0,1);
                lcd.print(maxNoteSetting);            
              }
              break;    
            case buttonPinLeft://decrease maximum note
              if(maxNoteSetting>0&&maxNoteSetting>minNote){
                maxNoteSetting=maxNoteSetting-1;
                lcd.clear();
                lcd.setCursor(0,0);
                lcd.print(strSetMaximumNote);
                lcd.setCursor(0,1);
                lcd.print(maxNoteSetting);
              }
              break;
          }

          break;        
  }
                 
} //loop()...


void menuChanged(MenuChangeEvent changed){
 
MenuItem newMenuItem=changed.to; //get the destination menu
  lcd.clear();
  lcd.setCursor(0,0);
 // lcd.setCursor(0,1); //set the start position for lcd printing to the second row
 
  if(newMenuItem.getName()==menu.getRoot()){
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Main Menu       ");
  }else if(newMenuItem.getName()=="Item1"){
      lcd.print("Item1          <");
      lcd.setCursor(0,1);
      lcd.print("Item2           ");    
  }else if(newMenuItem.getName()=="Item1SubItem1"){
      lcd.print("Item1SubItem1  <");
      lcd.setCursor(0,1);
      lcd.print("Item1SubItem2   ");      
  }else if(newMenuItem.getName()=="Item1SubItem2"){
      lcd.print("Item1SubItem1   ");
      lcd.setCursor(0,1);  
      lcd.print("Item1SubItem2  <");
  }else if(newMenuItem.getName()=="Item2"){
      lcd.print("Item2          <");
      lcd.setCursor(0,1);
      lcd.print("Run..           ");      
  }else if(newMenuItem.getName()=="menuItemMinNote"){
      lcd.print("Set minimum    <");
      lcd.setCursor(0,1);
      lcd.print(strSetMaximumNote);      
  }else if(newMenuItem.getName()=="menuItemMaxNote"){
      lcd.print(strSetMinimumNote);
      lcd.setCursor(0,1);
      lcd.print("Set maximum    <");      
  }else if(newMenuItem.getName()=="Item2SubItem3"){
      lcd.print("Item2SubItem3  <");
  }else if(newMenuItem.getName()=="Item3"){

      lcd.print("Run..          <");
  }
}

void menuUsed(MenuUseEvent used){
if( used.item == menu1Item1 ){
    currentStatusMode = statusPlayMode1;
    EEPROM.write(addrPlayMode, statusPlayMode1);
    menu.toRoot();
  }else if(  used.item == menuItemMinNote ){
    minNoteSetting=minNote;
    lastPlayingMode=currentStatusMode;
    currentStatusMode = statusSetMinNote;
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(strSetMinimumNote);
    lcd.setCursor(0,1);
    lcd.print(minNote);
  }else if(  used.item == menuItemMaxNote ){
    maxNoteSetting=maxNote;
    lastPlayingMode=currentStatusMode;
    currentStatusMode = statusSetMaxNote;
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print(strSetMaximumNote);
    lcd.setCursor(0,1);
    lcd.print(maxNote);
  }
  else if(  used.item == menu1Item3 ){
    currentStatusMode = statusRun;
  //  menu.toRoot();
  }
}


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
                  // 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:
                  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
        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
}



ไม่มีความคิดเห็น:

แสดงความคิดเห็น