RTC set up with rotary encoder

18 Nov 2011

Hello forum,

I have written a program that displays time on a LCD screen by using the RTC in mbed library and TextLCD library.

What I would like to do now is to using a rotary encoder to set time on the LCD screen. I'm using a nice guy, Karl's rotary encoder library. http://mbed.org/users/charly/libraries/mRotaryEncoder/lmcj2u

Can anyone give me tips on how to get started?

Here's the RTC code with LCD screen;

#include "mbed.h"
#include "TextLCD.h"


TextLCD lcd(p15, p16, p17, p18, p19, p20); // rs, e, d4-d7
InterruptIn plus(p6);

void set_time(time_t t);


int main() {

    struct tm t;
    t.tm_sec = 40;    // 0-59
    t.tm_min = 22;    // 0-59
    t.tm_hour = 3;   // 0-23
    t.tm_mday = 17;   // 1-31
    t.tm_mon = 10;     // 0-11
    t.tm_year = 111;  // year since 1900


    time_t seconds = mktime(&t);
    set_time(seconds); // Set time to Thu, 17 Nov 2011 03:22:40
    lcd.cls();
    while (1) {
        time_t seconds = time(NULL);

        char buffer[32];
        strftime(buffer, 32, "%a %d/%m/%Y\n%I:%M:%S %p\n", localtime(&seconds));
        lcd.locate(0,0);
        lcd.printf("%s", buffer);

    }


}
20 Nov 2011

Maybe this one is easier to use:

http://mbed.org/cookbook/QEI

05 Dec 2011

Did you get any further with this ?

08 Jan 2014

Hi i can propose one solution to this old post. Because for one of my project, i have write something similar . But i use mRotaryEncoder Library in place of QEI (more stable with low quality encoder). When you run my code, "OK" blink, if you push the rotary encoder you quit the Time Update function and go to the end of program (led blinking), but if you turn rotary," NON" Blink and if you push now you can modify Date and Time.(sorry for French comments)

include the mbed,mRotaryEncoder.h,TextLCD.h libraries with this snippet

/* Ce programme est un exemple permettant de mettre à l'heure et à la date une RTC à l'aide d'un bouton encodeur quadratique.
Ce programme , après une demande d'initialisation su de l'heure via un programme type hyper terminal (Ex:Hterm)sur PC,
permet de modifier chacun des paramètres de la date et de l'heure en utilisant le bouton encodeur et d'afficher le résultat sur un afficheur 2X20.
Chaque champ à modifier se met à clignoter pour indiquer qu'il est modifiable. une rotation du bouton permet alors de modifier
cette valeur , puis un appui sur le bouton permet de valider son choix. Le clignotement passe alors au paramètre suivant.
Nota: L'appui lorsque l'affichage clignote sur "OK" permet de quitter la fonction de mise à l'heure. Alors que l'appui sur"NON", permet de passer
à la modification des paramètres de dates et heures. 
*/
#include "mbed.h"
#include "mRotaryEncoder.h"
#include "TextLCD.h"
#include <time.h>
// prototype
void Define_Date (char *Buff_Afficheur);
void BlinkLcdText (char *buffer_Lcd,int Index_1erChar, int Nb_Char);
//I/O
DigitalOut myled(LED1);
TextLCD lcd(p26, p24, p23, p22, p20, p19, TextLCD::LCD20x4); // rs, e, d4-d7TextLCD lcd(p26, p24, p23, p22, p20, p19, TextLCD::LCD20x4); // rs, e, d4-d7
//mRotaryEncoder(PinName pinA, PinName pinB, PinName pinSW, PinMode pullMode=PullUp, int debounceTime_us=1000)
mRotaryEncoder  wheel(p11, p12, p13); // Défini les entrées associées au Bouton  encodeur (A,B,Bp)

//Variables Globales utilisées par la bibliothèque mRotaryEncoder
int lastGet;
int thisGet;
bool enc_pressed = false;      // Button of rotaryencoder was pressed
bool enc_rotated = false;      // rotary encoder was totaded left or right
//Variables Globales utilisées pour définir le buffer d'affichage 
char Buff_Afficheur[41];
//Variables Globales utilisées pour stocker le temps de la RTC
struct tm t;                // Structure stockant le temps

//interrup-Handler for button on rotary-encoder
void trigger_sw() {
    enc_pressed = true;               // just set the flag, rest is done outside isr
}

//interrup-Handler for rotary-encoder rotation
void trigger_rotated() {
    enc_rotated = true;               // just set the flag, rest is done outside isr
}

int main() {
    // Initialisation de la structure de temps pour la RTC:
    time_t seconds = time(NULL);

    
    if ((seconds < 1388534400)|| (seconds == -1)){           // si la RTC à été reseter sans sauvegarde, elle peut renvoyer -1 ou une faible valeur
    t.tm_year = 2014-1900;        // Donc on la force avec la date 1.1.2014 00:00:00
    t.tm_mon = 1-1;
    t.tm_mday = 1;
    t.tm_hour = 0;
    t.tm_min = 0;
    t.tm_sec = 0;
    set_time(mktime(&t));          // Crée et défini la valeurs de temps à partir de la structure de temps t
    }
    else tm t= *localtime(&seconds);                // Met à jour la structure tm.t avec la valeur de la RTC.// Initialisation de la structure de temps pour la RTC:
   
    
    //Int-Handler Déclare les vecteur d'interruption lorsque l'on touche le bouton encodeur
    // call trigger_sw() when button of rotary-encoder is pressed
    wheel.attachSW(&trigger_sw);

    // call trigger_rot() when the shaft is rotaded left or right
    wheel.attachROT(&trigger_rotated);
    lastGet = 0;  
      
    // display the time update menu
    Define_Date(Buff_Afficheur);
 // Fait clignoter les leds pour indiquer que la fin du programme est atteind.
  while(1) {
        myled = 1;
        wait(0.2);
        myled = 0;
        wait(0.2);
    }   
}

//Clignotement de certaine zone de l'afficheur.
void BlinkLcdText (char *buffer_Lcd,int Index_1erChar, int Nb_Char){
    char Buff_copy[41];
    int i=0;
    strcpy(Buff_copy,buffer_Lcd);  // recopie la chaine originale dans le tampon Buff_copy
    for (i = Index_1erChar; i<(Nb_Char + Index_1erChar);i++) Buff_copy[i]= ' '; // Efface les caractères indiqués   
    //pc.printf ("%s",Buff_copy);
    lcd.locate(0,0);
    lcd.printf("%s",Buff_copy);
    wait(0.2);
    strcpy(Buff_copy,buffer_Lcd);  // recopie la chaine originale dans le tampon Buff_copy
    lcd.locate(0,0);
    lcd.printf("%s",Buff_copy);
    wait(0.2);
    }
//Fonction modification de l'heure.
void Define_Date (char *Buff_Afficheur){
    bool Again = true;
    int Modif_selection = 0;
    enc_rotated = false;
    enc_pressed = false;
    wheel.Set(0);                               // Reset du compteur du bouton encodeur pour repartir propre 
    lcd.cls();
    while(Again) {
        lcd.locate (0,0);
        wait(0.1);                      // Indispensable: permet de laissé au µp Le temps pour la mise à jour de la RTC et d'éviter ainsi la mise en défaut de celle-ci.    
        time_t seconds = time(NULL);        // Récupère dans seconds la valeur de la RTC 
        tm t= *localtime(&seconds);  //met à jour la structure de temps tm à partir de l'heure courante     
        strftime(Buff_Afficheur, 41, "Date:%d-%m-%Y          %H:%M    NON/OK", localtime(&seconds)); // construit la chaine à afficher en intégrant une structure de temps (d'ou le strftime)
        lcd.printf("%s", Buff_Afficheur); // Affiche cette chaine
        switch (Modif_selection)
            {
                case 0 : BlinkLcdText ( Buff_Afficheur,38,2);            //Fait clignoter le "OK"
                        if (enc_rotated) {                              // Test si bouton encodeur tourné
                            enc_rotated = false;                        // Reset le flag de rotation
                            Modif_selection = 1;                        // Force le menu Modif sélection à revenir dans ce case aprés avoir effectuer ce test
                            wheel.Set(0);                               // Reset du compteur du bouton encodeur pour repartir propre 
                            }
                        if (enc_pressed) {                              // Test si bouton encodeur enfoncé
                        enc_pressed = false;                            // si oui reset le flag de Bouton enfoncé
                        // mettre ici Quitter la fonction
                        Again = false;
                        }
                        break;
                case 1 : BlinkLcdText ( Buff_Afficheur,34,3);            //Fait clignoter le "NON"
                        if (enc_rotated) {
                            enc_rotated = false;
                            Modif_selection = 0;
                            }
                        if (enc_pressed) {
                            enc_pressed = false;
                            Modif_selection = 5;                        // si appuyer va modifier les minutes
                            wheel.Set(0);
                            }
                        break;
                case 2 : BlinkLcdText ( Buff_Afficheur,5,2);            //Fait clignoter le "Jour"
                      if (enc_rotated) {
                            enc_rotated = false;
                            Modif_selection = 2;
                            t.tm_mday = t.tm_mday + wheel.Get();        // Met à jour le Jour en ajoutant ou retranchant la valeur de rotation du bouton encodeur
                            set_time(mktime(&t));                       // Met à jour la RTC interne pour tenir compte du changement
                            } 
                        if (enc_pressed) {
                            enc_pressed = false;
                            Modif_selection = 3;                        // si appuyé va modifier les Mois
                            }
                        wheel.Set(0);
                        break;
                case 3 : BlinkLcdText ( Buff_Afficheur,8,2);            //Fait clignoter le "Mois"
                      if (enc_rotated) {
                            enc_rotated = false;
                            Modif_selection = 3;
                            t.tm_mon = t.tm_mon + wheel.Get();
                            set_time(mktime(&t));
                            
                            } 
                        if (enc_pressed) {
                            enc_pressed = false;
                            Modif_selection = 4;                        // si appuyé va modifier les années
                            }
                        wheel.Set(0);
                        break;
                  case 4 : BlinkLcdText ( Buff_Afficheur,11,4);            //Fait clignoter l' "Année"
                      if (enc_rotated) {
                            enc_rotated = false;
                            Modif_selection = 4;
                            t.tm_year = t.tm_year + wheel.Get();
                            set_time(mktime(&t));
                            
                            } 
                        if (enc_pressed) {
                            enc_pressed = false;
                            Modif_selection = 1;                           // si appuyé retour en "NON"
                            }
                        wheel.Set(0);
                        break;
                    case 5 : BlinkLcdText ( Buff_Afficheur,28,2);            //Fait clignoter les "minutes"
                      if (enc_rotated) {
                            enc_rotated = false;
                            Modif_selection = 5;
                            t.tm_sec = 0;
                            t.tm_min = t.tm_min + wheel.Get();
                            set_time(mktime(&t));                     
                            } 
                        if (enc_pressed) {
                            enc_pressed = false;                            // si appuyé va modifier les heures
                            Modif_selection = 6;
                            }
                        wheel.Set(0);
                        break;
                    case 6 : BlinkLcdText ( Buff_Afficheur,25,2);            //Fait clignoter les "heures"
                      if (enc_rotated) {
                            enc_rotated = false;
                            Modif_selection = 6;
                            t.tm_hour = t.tm_hour + wheel.Get();
                            set_time(mktime(&t));                     
                            } 
                        if (enc_pressed) {
                            enc_pressed = false;
                            Modif_selection = 2;                        // si appuyé va modifier les jours
                            }
                        wheel.Set(0);
                        break;
                }   
    }
}