Pages: [1]   Go Down
Author Topic: Delucidazioni display lcd 16x2 + encoder  (Read 1571 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Buon giorno ragazzi.
In questi giorni sono alle prese con un display lcd 16x2 compatibile con i driver hitachi collegato al mio arduino uno.
Dunque, quello che dovrei farci è un uso piuttosto semplice, almeno in teoria; avrei bisogno di disporre di un menu' con tre soli elementi, ognuno dei quali, selezionandolo, possa cambiare il valore di una variabile o fare un'operazione differente.
La struttura dovrebbe essere le seguente.
Nel menu', dispongo di tre oggetti:
Se seleziono il primo oggetto -> fai questo
Se seleziono il secondo oggetto -> fai quest'altro
Se seleziono il terzo oggetto -> fai quest'altro.
Inoltre, cosa interessante, sarebbe memorizzare lo stato precedente. Ad esempio, se l'oggetto selezionato attualmente è il secondo e se l'oggetto che selezioneremo sarà il terzo, allora fai questa cosa quì.

Ora, vorrei pilotare lo scroll degli elementi e la loro selezione uno e uno solo alla volta, con un encoder rotativo dotato di click centrale per la selezione.

Spulciando per il forum mi è saltato fuori questo:

http://arduino.cc/forum/index.php?topic=53265.0

A quanto ho capito anche il ragazzo utilizza un encoder con click ma non ho ben capito il codice; tra l'altro, credo che il suo menu' sia parecchio più complesso, cosa che a me non occorre.

Quindi, avete qualche idea semplice semplice per fare qualcosa del genere senza ricorrere a centinaia di righe di codice?

Se volete posto postarvi le immagini degli articoli, ma credo che quelli che circolano sono più o meno sempre gli stessi.


Grazie ragazzi.
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 327
Posts: 22651
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Non vorrei deluderti ma la prassi comune è quella di non scrivere il codice al posto degli altri.
Al massimo possiamo aiutarti a correggere il tuo ma difficilmente troverai qualcuno che te lo scrive da zero.

Vedo che le idee su cosa vuoi fare ce l'hai chiare, dovresti quindi iniziare ad elaborare qualcosa per conto tuo e poi pubblicarlo qui per suggerimenti/correzioni.

PS:
il thread che hai citato mi pare faccia al caso tuo: devi solo togliere le voci in più ed adattare quel codice alle tue esigenze.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ti ringrazio!
No vabbè non sono in cerca di pappa pronta!
Certamente mi metterò a buttare giu' un pò di codice e poi lo sottoporrò alla vostra attenzione.
Per il momento quello che volevo era semplicemente una linea guida (in italiano scritto) seppure generica per fare quello che devo fare, insomma, un piccolo aiuto per capire meglio come organizzare il progetto.

Comunque adesso cerco un pò di scrivere qualcosa di testa mia e poi magari ne discutiamo.

Grazie!
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salve ragazzi.
Sulla scia del codice che vi posterò quì sotto, potete darmi un aiuto su un paio di punti?
Non capisco dove vengono definiti i pin utilizzati dall'lcd, e in più non riesco a capire a quali pin bisogna collegare l'encoder.
Avete qualche schema che possa farmi luce su questa faccenda?


Non mi è chiaro poi, come possa esemplificare il codice facendo una cosa del tipo:
C'è un unico menu' con x oggetti selezionabile solo uno per volta.
Quando ne seleziono uno, se diverso dal precedente, tutti gli altri devono deselezionarsi.

E' possibile farlo?

Il codice lo piazzerò nel prossimo post, perchè ci sono problemi con il valore limite di caratteri ammessi.

Grazie mille ragazzi.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
/*
MENU ROUTINE
 */
void basicMenu(){

  byte topItemDisplayed = 0;  // stores menu item displayed at top of LCD screen
  byte cursorPosition = 0;  // where cursor is on screen, from 0 --> totalRows.

  // redraw = 0  - don't redraw
  // redraw = 1 - redraw cursor
  // redraw = 2 - redraw list
  byte redraw = MOVELIST;  // triggers whether menu is redrawn after cursor move.
  byte i=0; // temp variable for loops.
  byte totalMenuItems = 0;  //a while loop below will set this to the # of menu items.

// Put the menu items here. Remember, the first item will have a 'position' of 0.
  char* menuItems[]={
    "Set Timer 1",
    "Set Timer 2",
    "Set Probe 1 Temp",
    "Set Probe 2 Temp",
    "Probe 1 Controller",
    "Probe 2 Controller",
    "Advanced Settings",
    "",
  };

  while (menuItems[totalMenuItems] != ""){
    totalMenuItems++;  // count how many items are in list.
  }
  totalMenuItems--;  //subtract 1 so we know total items in array.

  lcd.clear();  // clear the screen so we can paint the menu.

  boolean stillSelecting = true;  // set because user is still selecting.

  timeoutTime = millis() + menuTimeout; // set initial timeout limit.

  do   // loop while waiting for user to select.
  {

    /*
    IF YOU WANT OTHER CODE GOING ON IN THE BACKGROUND
    WHILE WAITING FOR THE USER TO DO SOMETHING, PUT IT HERE
    */
   
    /*
    my code uses a rotary encoder for input.
    You should obviously change the code to meet your needs.
    For a button, you could do something like this, but note that
    it does not have ANY debouncing and will scroll for as long as
    the button is being pushed. This is not a button tutorial,
    so you should look elsewhere on how to implement that. Just
    remember that ALL of the code between the corresponding 'case'
    and 'break' should be moved to each button push routine.
   
   
    buttonState = digitalRead(buttonPin);
    if (buttonState == HIGH) {     
      AND THEN PUT THE CORRESPONDING CODE
      FROM BELOW HERE
  }
  */
    switch(read_encoder())
    {  // analyze encoder response. Default is 0.


    case 1:  // ENCODER ROTATED UP. EQUIVALENT OF 'UP' BUTTON PUSHED

      timeoutTime = millis()+menuTimeout;  // reset timeout timer
      //  if cursor is at top and menu is NOT at top
      //  move menu up one.
      if(cursorPosition == 0 && topItemDisplayed > 0)  //  Cursor is at top of LCD, and there are higher menu items still to be displayed.
      {
        topItemDisplayed--;  // move top menu item displayed up one.
        redraw = MOVELIST;  // redraw the entire menu
      }

      // if cursor not at top, move it up one.
      if(cursorPosition>0)
      {
        cursorPosition--;  // move cursor up one.
        redraw = MOVECURSOR;  // redraw just cursor.
      }
      break;

    case 2:    // ENCODER ROTATED UP. EQUIVALENT OF 'DOWN' BUTTON PUSHED

      timeoutTime = millis()+menuTimeout;  // reset timeout timer
      // this sees if there are menu items below the bottom of the LCD screen & sees if cursor is at bottom of LCD
      if((topItemDisplayed + (totalRows-1)) < totalMenuItems && cursorPosition == (totalRows-1))
      {
        topItemDisplayed++;  // move menu down one
        redraw = MOVELIST;  // redraw entire menu
      }
      if(cursorPosition<(totalRows-1))  // cursor is not at bottom of LCD, so move it down one.
      {
        cursorPosition++;  // move cursor down one
        redraw = MOVECURSOR;  // redraw just cursor.
      }
      break;

    case 4:  // ENCODER BUTTON PUSHED FOR SHORT PERIOD & RELEASED.
             // EQUIVALENT TO 'SELECT' OR 'OKAY' BEING PUSHED

      timeoutTime = millis()+menuTimeout;  // reset timeout timer
      switch(topItemDisplayed + cursorPosition) // adding these values together = where on menuItems cursor is.
      {
      //  put code to be run when specific item is selected in place of the Serial.print filler.
      // the Serial.print code can be removed, but DO NOT change the case & break structure.
      // (Obviously, you should have as many case instances as you do menu items.)
      case 0:  // menu item 1 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        // there is no menuSubMenu1() function. BUT, to have nested menus,
        // copy this function(i.e. all of basicMenu) into a new function named
        // whatever you want for your sub menu items and repeat.
//        menuSubMenu1();
        break;

      case 1:  // menu item 2 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        break;

      case 2:  // menu item 3 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        break;

      case 3:  // menu item 4 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        break;

      case 4:  // menu item 5 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        break;

      case 5:  // menu item 6 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        break;


      case 6:  // menu item 7 selected
        Serial.print("Menu item ");
        Serial.print(topItemDisplayed + cursorPosition);
        Serial.print(" selected - ");
        Serial.println(menuItems[topItemDisplayed + cursorPosition]);
        break;
       
        // add as many "case #:" as items you have. You could put
        //  line separators in menuList and leave out the
        //  corresponding case, which would mean that nothing
        // would be triggered when user selected the line separator. 
      }
      break;
     
    case 8:  // encoder button was pushed for long time. This corresponds to "Back" or "Cancel" being pushed.
      stillSelecting = false;
      Serial.println("Button held for a long time");
      break;

    }

    switch(redraw){  //  checks if menu should be redrawn at all.
    case MOVECURSOR:  // Only the cursor needs to be moved.
      redraw = false;  // reset flag.
      if (cursorPosition > totalMenuItems) // keeps cursor from moving beyond menu items.
        cursorPosition = totalMenuItems;
      for(i = 0; i < (totalRows); i++){  // loop through all of the lines on the LCD
        lcd.setCursor(0,i);
        lcd.print(" ");                      // and erase the previously displayed cursor
        lcd.setCursor((totalCols-1), i);
        lcd.print(" ");
      }
      lcd.setCursor(0,cursorPosition);      // go to LCD line where new cursor should be & display it.
      lcd.print(">");
      lcd.setCursor((totalCols-1), cursorPosition);
      lcd.print("<");
      break;  // MOVECURSOR break.

    case MOVELIST:  // the entire menu needs to be redrawn
      redraw=MOVECURSOR;  // redraw cursor after clearing LCD and printing menu.
      lcd.clear(); // clear screen so it can be repainted.
      if(totalMenuItems>((totalRows-1))){  // if there are more menu items than LCD rows, then cycle through menu items.
        for (i = 0; i < (totalRows); i++){
          lcd.setCursor(1,i);
          lcd.print(menuItems[topItemDisplayed + i]);
        }
      }
      else{  // if menu has less items than LCD rows, display all available menu items.
        for (i = 0; i < totalMenuItems+1; i++){
          lcd.setCursor(1,i);
          lcd.print(menuItems[topItemDisplayed + i]);
        }
      }
      break;  // MOVELIST break
    }

    if (timeoutTime<millis()){  // user hasn't done anything in awhile
      stillSelecting = false;  // tell loop to bail out.
      /*
      in my main code, I had a function that
       displayed a default screen on the LCD, so
       I would put that function here, and it would
       bail out to the default screen.
       defaultScreen();
       */
    }
  }


  while (stillSelecting == true);  //
}
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Giusto un piccolo UP.
Grazie in anticipo a chi potrà aiutarmi!
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 327
Posts: 22651
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Non è uno sketch completo, ecco perché non vedi le definizioni dei pin: non ci sono le inclusioni delle librerie, le istanze delle stesse, non c'è la funzione setup() né la loop(). Questa è solo la funzione per gestire un menu, mi par di capire.
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 19
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ho capito leo.
Ragion per cui dovrei richiamare soltanto la funzione nella struttura del programma per avere la gestione del menu'?
I pin dell'lcd li imposto nel setup insomma, e in base a come collego il display.
Ma poi, sapresti aiutarmi nella configurazione e connessione dei pin dell'encoder? Occorrerebbero due pin o mi sbaglio? (uno per il button centrale e l'altro per gli impulsi/giro)

Grazie!
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 327
Posts: 22651
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Il display immagino sia un classico parallelo compatibile HD44780, quindi userai la libreria LiquidCrystal: essa necessita di 7 pin minimo, che imposterai quando istanzi la lib. Apriti comunque un esempio allegato all'IDE della LIquidCrystal e guarda come si istanzia la lib con la definizione dei pin relativi.
 
L'encoder mi pare richieda 3 pin. Un esempio con arduino è qui:
http://www.circuitsathome.com/mcu/reading-rotary-encoder-on-arduino
Logged


napoli
Offline Offline
Full Member
***
Karma: 0
Posts: 167
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ti rispondo io sul rotary encoder, ti posso dire che e semplicissimo il rotary encoder ha il pin centrale il 2 che va alimentato  e gli altri due pin  ti daranno degli impulsi in uscita in base  se giri a destra o sinistra,
esempio: se giri a destra  lui ti dara due impulsi il primo sul pin 3 e il secondo sul pin uno , se invece giri a sinistra  lui ti dara sempre due impulsi ma il primo questa voltra lo avrai sul pin 1 e il secondo sul pin 3 .

io non uso c ma basic e la cosa mi viene cosi

if pin1=1 then
  delay_ms(5)
  if pin3=1 then

  bla bla bla

  end if
end if
if pin3=1 then
  delay_ms(5)
  if pin1=1 then

  bla bla bla

  end if
end if
Logged

Pages: [1]   Go Up
Jump to: