Pages: [1]   Go Down
Author Topic: Aggiornare temperatura letta su LCD shield nokia 5110 (3310)  (Read 1202 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Salve a tutti,

da diversi mesi mi sto divertendo con arduino e sono stato un osservatore silente del forum...per lo meno fino ad ora  smiley
Sto provando a visualizzare la temperatura letta da un sensore DS18B20 sullo schermo LCD shield nokia 5110 (3310), di facile reperibilità su internet http://www.nuelectronics.com/estore/index.php?main_page=product_info&cPath=1&products_id=12. Il problema è che entrando nel menù corrispondente alla temperatura riesco a visualizzare quella istantanea, poi non si aggiorna. Se esco dal menù e rientro, la temperatura è cambiata.
Immagino sia dovuto alla mia scarsa capacità di programmare, in tutti i modi allego il codice che può essere da spunto per altri, sperando che qualcuno possa darmi una dritta su come migliorarlo. Aggiungo che se elimino i menù e faccio visualizzare solo la temperatura sull'LCD, questa si aggiorna tranquillamente, tuttavia la presenza del joystick sarebbe sprecata...
Un ulteriore problema è che ogni tanto appaiono temperature assurde, ma questa è un'altra storia... smiley-grin
Code:
#include "nokia_3310_lcd.h"
#include "avr_bmp.h"
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// Bus 1-wire - sensore Dallas Ds18B20 su pin D2
#define ONE_WIRE_BUS 2   // Dallas su D2

//keypad debounce parameter
#define DEBOUNCE_MAX 15
#define DEBOUNCE_ON  10
#define DEBOUNCE_OFF 3

#define NUM_KEYS 5

#define NUM_MENU_ITEM 4

// joystick number
#define UP_KEY 3
#define LEFT_KEY 0
#define CENTER_KEY 1
#define DOWN_KEY 2
#define RIGHT_KEY 4

// menu starting points

#define MENU_X 10 // 0-83
#define MENU_Y 1 // 0-5

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire              oneWireBus(ONE_WIRE_BUS);
DallasTemperature    sensors(&oneWireBus);

int Temperatura;   // contiene la temperatura letta dal sensore

// adc preset value, represent top value,incl. noise & margin,that the adc reads, when a key is pressed
// set noise & margin = 30 (0.15V@5V)
int  adc_key_val[5] ={30, 150, 360, 535, 760 };

// debounce counters
byte button_count[NUM_KEYS];
// button status - pressed/released
byte button_status[NUM_KEYS];
// button on flags for user program
byte button_flag[NUM_KEYS];

unsigned long time_next_blink;
boolean flag;
int count;

// menu definition
char menu_items[NUM_MENU_ITEM][12]={
"TEMPERATURA",
"IMMAGINE",
"ABOUT"
};

void (*menu_funcs[NUM_MENU_ITEM])(void) = {
show_temperature,
immagine,
about
};

char current_menu_item;


Nokia_3310_lcd lcd=Nokia_3310_lcd();

void setup()
{
     Serial.begin(19200);
  // inizializzo il sensore DS1820
  sensors.begin();
  // Inizializzo Seriale - Serial Monitor

   // setup interrupt-driven keypad arrays 
   // reset button arrays
   for(byte i=0; i<NUM_KEYS; i++){
     button_count[i]=0;
     button_status[i]=0;
     button_flag[i]=0;
   }
 
  // Setup timer2 -- Prescaler/256
  TCCR2A &= ~((1<<WGM21) | (1<<WGM20));
  TCCR2B &= ~(1<<WGM22);
  TCCR2B = (1<<CS22)|(1<<CS21);     
 
  ASSR |=(0<<AS2);

   // Use normal mode 
   TCCR2A =0;   
     //Timer2 Overflow Interrupt Enable 
     TIMSK2 |= (0<<OCIE2A);
     TCNT2=0x6;  // counting starts from 6; 
   TIMSK2 = (1<<TOIE2);   
   
                 
 
  SREG|=1<<SREG_I;
 
  lcd.LCD_3310_init();
lcd.LCD_3310_clear();
 
   //menu initialization
   init_MENU();
   current_menu_item = 0;
   
   time_next_blink=millis()+500;
    flag=true;
    count=0;

}


/* loop */




void loop()
{
    byte i;
    for(i=0; i<NUM_KEYS; i++){
       if(button_flag[i] !=0){
           
            button_flag[i]=0;  // reset button flag
switch(i){

case UP_KEY:
// current item to normal display
lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_NORMAL );
current_menu_item -=1;
if(current_menu_item <0)  current_menu_item = NUM_MENU_ITEM -1;
// next item to highlight display
lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_HIGHLIGHT );
break;
case DOWN_KEY:
// current item to normal display
lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_NORMAL );
current_menu_item +=1;
if(current_menu_item >(NUM_MENU_ITEM-1))  current_menu_item = 0;
// next item to highlight display
lcd.LCD_3310_write_string(MENU_X, MENU_Y + current_menu_item, menu_items[current_menu_item], MENU_HIGHLIGHT );
break;
case LEFT_KEY:
          init_MENU();
current_menu_item = 0;
break;   
case RIGHT_KEY:
        lcd.LCD_3310_clear();
(*menu_funcs[current_menu_item])();
          lcd.LCD_3310_clear();
init_MENU();
current_menu_item = 0;           
break;
}

}
    }
 
  sensors.requestTemperatures();  // invia il comando leggi temperatura
  Temperatura= sensors.getTempCByIndex(0); //estrai la temperature letta

      }

/* menu functions */

void init_MENU(void){

  byte i;
 
  lcd.LCD_3310_clear();

    lcd.LCD_3310_write_string(MENU_X, MENU_Y, menu_items[0], MENU_HIGHLIGHT );

  for (i=1; i<NUM_MENU_ITEM; i++){
    lcd.LCD_3310_write_string(MENU_X, MENU_Y+i, menu_items[i], MENU_NORMAL);
  }


}

// waiting for center key press
void waitfor_OKkey(){
  byte i;
  byte key = 0xFF;
while (key!= CENTER_KEY){
    for(i=0; i<NUM_KEYS; i++){
       if(button_flag[i] !=0){
           button_flag[i]=0;  // reset button flag
           if(i== CENTER_KEY) key=CENTER_KEY;
        }
     }
   }

}

void show_temperature(){
float i,  x;
int ii;
char temperature[10];
sensors.requestTemperatures();
x = sensors.getTempCByIndex(0);
i = (x);
dtostrf(i, 5, 1, temperature);
 
lcd.LCD_3310_write_string(6,0,"Temp.: ",MENU_NORMAL);
        lcd.LCD_3310_write_string_big(10, 1, temperature, MENU_NORMAL);
        lcd.LCD_3310_write_string(78, 2, "C", MENU_NORMAL);
        lcd.LCD_3310_write_string(38, 5, "OK", MENU_HIGHLIGHT );
waitfor_OKkey();
lcd.LCD_3310_clear();
}



void immagine(){
  lcd.LCD_3310_draw_bmp_pixel(20,1, AVR_bmp, 48,24);
  lcd.LCD_3310_write_string(38, 5, "OK", MENU_HIGHLIGHT );
waitfor_OKkey();
}


void about(){
 
  lcd.LCD_3310_write_string( 0, 1, "Codice by", MENU_NORMAL);
  lcd.LCD_3310_write_string( 0, 2, "Stefano", MENU_NORMAL);
  lcd.LCD_3310_write_string( 0, 3, "Staccone", MENU_NORMAL);
lcd.LCD_3310_write_string(38, 5, "OK", MENU_HIGHLIGHT );
waitfor_OKkey();


}



// The followinging are interrupt-driven keypad reading functions
//  which includes DEBOUNCE ON/OFF mechanism, and continuous pressing detection


// Convert ADC value to key number
char get_key(unsigned int input)
{
char k;
   
for (k = 0; k < NUM_KEYS; k++)
{
if (input < adc_key_val[k])
{
           
    return k;
        }
}
   
    if (k >= NUM_KEYS)
        k = -1;     // No valid key pressed
   
    return k;
}

void update_adc_key(){
  int adc_key_in;
  char key_in;
  byte i;
 
  adc_key_in = analogRead(0);
  key_in = get_key(adc_key_in);
  for(i=0; i<NUM_KEYS; i++)
  {
    if(key_in==i)  //one key is pressed
    {
      if(button_count[i]<DEBOUNCE_MAX)
      {
        button_count[i]++;
        if(button_count[i]>DEBOUNCE_ON)
        {
          if(button_status[i] == 0)
          {
            button_flag[i] = 1;
            button_status[i] = 1; //button debounced to 'pressed' status
          }
 
        }
      }

    }
    else // no button pressed
    {
      if (button_count[i] >0)
      { 
button_flag[i] = 0;
button_count[i]--;
        if(button_count[i]<DEBOUNCE_OFF){
          button_status[i]=0;   //button debounced to 'released' status
        }
      }
    }
   
  }
}

// Timer2 interrupt routine -
// 1/(160000000/256/(256-6)) = 4ms interval

ISR(TIMER2_OVF_vect) { 
  TCNT2  = 6;
  update_adc_key();
}



Grazie a tutti,
Stefano.
Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10498
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ogni loop() leggi la temperatura, ma non controlli se l'utente sta visualizzando la temperatura: se vero, aggiorni la scitta del led con la nuova temperatura, se falso non far nulla (rimane la vecchia scritta).

Occhio a non aggiornare la temperatura troppo spesso o LCD sfarfallerà
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

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

Grazie per la risposta.
Questo significa che dovrei creare un ciclo if che, attraverso una variabile legata al tempo, mi aggiorni la temperatura letta ogni tot millisecondi?
Oppure non ci ho capito nulla?   smiley-yell
Logged

0
Offline Offline
Shannon Member
****
Karma: 132
Posts: 10498
:(){:|:&};:
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

quella è la soluzione spicciola.
La soluzione secondo me migliore è creare delle stutture, con schema ad albero, una rappresenta il menu principale con la scelta attuale e contiene anche le varie strutture di sottomenu. Anche quelle contengono l'eventuale selezione e/o i valori da visualizzare. Poi crei una funzione update() che in base alle selezioni "disegni" il menu. Questa funzione la chiami una volta ogni tanto (1/2 volte al secondo, per evitare lo sfarfallio, poi vedi te il valore ideale).
poi crei un altra funzione (o usi il loop) che riceve i dati dall'utente e sensori e aggiorna la struttura.

In questo modo diversifichi la parte del codice che usa l'LCD dal codice vero e proprio... volendo puoi facilmente sostituire la funzione update() con del codice che manda i valori via seriale ( quant'altro), e volendo, ciliegina sulla torta, puoi anche diversificare il codice input utente dall'input sensori(per lo stesso motivo... se leggi i valori via seriale, vorrai pure selezionare il menu via seriale).

Questo metodo è più sbatti perchè richiede forse più codice e quasi sicuramentte una riscrittura dello stesso, ma poi ogni funzione è più o meno utilizzabile anche in altri progetti (riusabilità del codice, ottenuta in modo molto migliore usando le classi, ma quello è un altro discorso.)

direi che sono stato abbastanza logorroico ma esaustivo, a te la scelta  smiley-mr-green
Logged

sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

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

Sei stato decisamente esaustivo, ti ringrazio!
Ora sta a me modificare il codice, probabilmente ne dovrò riscrivere buona parte ma impostando il lavoro come dici tu renderà il tutto riutilizzabile. Grazie ancora!
Stefano.
Logged

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

Ciao, ho appena ordinato anche il lo stesso shield.
Una unica domanda, non riesco bene a capire quanti e quali PIN utilizza..
Chi mi può aiutare dal datashet non capisco molto..
Logged

0
Offline Offline
Edison Member
*
Karma: 24
Posts: 2315
Have you mooed today?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao,
eventualmente per la gestione del menu, girava un bel lavoro fatto da Calamaro e Federico:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1241310950/30
Logged

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

Ciao, grazie x il link!Avevo bisogno di quel tipo di informazioni. Anch'io ho fatto un menù sulla base dei suggerimenti che mi avete dato, appena posso posto il codice. Grazie ancora!
Logged

Pages: [1]   Go Up
Jump to: