Arduino + Mémoire + Deuligne = Horloge

Parlez nous de vos projets et de vos idées, imaginez des applications

Arduino + Mémoire + Deuligne = Horloge

Message non lude SesechXP » Lun 30 Avr 2012 12:07

Bonjour,

Ayant acheté les shields Snootlab Mémoire et Deuligne, c'est tout naturellement que j'ai développé une petite horloge LCD sans prétention à base d'Arduino Uno...

Le fonctionnement est simple :
- Au démarrage le shield Deuligne affiche la date et l'heure de la RTC du shield Mémoire.
- Un appui sur la touche Select du Deuligne permet d'entrer en mode réglage. Le rafraîchissement de l'heure est suspendu et un curseur apparaît sur le jour.
- Un appui sur Up ou Down permet d'incrémenter ou de décrémenter le membre sélectionné.
- Un appui sur Left ou Right permet de changer le membre à régler.
- Un appui sur Select permet de valider le réglage et de mettre à jour l'heure de la RTC.

Matériel :
- Arduino Uno R2 ;
- Mémoire v1.0 ;
- Deuligne v1.1.

Logiciel :
- Arduino 1.0 ;
- RTClib ;
- Deuligne.



Sketch Clock.ino :
Code: Tout sélectionner
/**************************************************************************//**
 * \file clock.ino
 ******************************************************************************/

/******************************************************************************
 * Header file inclusions.
 ******************************************************************************/

#include "Keyboard.h"
 
#include <Deuligne.h>
#include <RTClib.h>

#include <Arduino.h>
#include <Wire.h>

#include <stdio.h>

/******************************************************************************
 * Private macro definitions.
 ******************************************************************************/

#define CLOCK__DAY_MIN     1
#define CLOCK__DAY_MAX     31
#define CLOCK__MONTH_MIN   1
#define CLOCK__MONTH_MAX   12
#define CLOCK__YEAR_MIN    2000
#define CLOCK__YEAR_MAX    2099
#define CLOCK__HOUR_MIN    0
#define CLOCK__HOUR_MAX    23
#define CLOCK__MINUTE_MIN  0
#define CLOCK__MINUTE_MAX  59
#define CLOCK__SECOND_MIN  0
#define CLOCK__SECOND_MAX  59

/******************************************************************************
 * Private type definitions.
 ******************************************************************************/

/**************************************************************************//**
 * \enum clock__members
 * \brief
 *
 * \type clock__member_t
 * \brief
 ******************************************************************************/
typedef enum clock__members
{
    clock__MemberDay,
    clock__MemberMonth,
    clock__MemberYear,
    clock__MemberHour,
    clock__MemberMinute,
    clock__MemberSecond
} clock__member_t;

/******************************************************************************
 * Private function prototypes.
 ******************************************************************************/

/**************************************************************************//**
 * \fn static void clock__handleKey(Keyboard::Key_t key)
 *
 * \brief Handle pressed key.
 *
 * \param   key Pressed key.
 ******************************************************************************/
static
void
clock__handleKey
(
    Keyboard::Key_t key
);

/**************************************************************************//**
 * \fn static void clock__setCursor()
 *
 * \brief Set cursor position.
 ******************************************************************************/
static
void
clock__setCursor();

/**************************************************************************//**
 * \fn static clock__incrementMember()
 *
 * \brief Increment current member: day, month, year, hour, minute or second.
 ******************************************************************************/
static
void
clock__incrementMember();

/**************************************************************************//**
 * \fn static void clock__decrementMember()
 *
 * \brief Decrement current member: day, month, year, hour, minute or second.
 ******************************************************************************/
static
void
clock__decrementMember();

/**************************************************************************//**
 * \fn static void clock__printDatetime()
 *
 * \brief Print current datetime.
 ******************************************************************************/
static
void
clock__printDatetime();
 
/******************************************************************************
 * Private variable declarations.
 ******************************************************************************/

static Deuligne clock__lcd;
static RTC_DS1307 clock__rtc;

static DateTime clock__currentTime;

static bool clock__adjustMode = false;
static clock__member_t clock__currentMember = clock__MemberDay;

/******************************************************************************
 * Public function definitions.
 ******************************************************************************/

/**************************************************************************//**
 * \fn void setup()
 *
 * \brief System initialization.
 ******************************************************************************/
void setup()
{
    // Initialize TWI bus.
    Wire.begin();
   
    // Initialize RTC.
    clock__rtc.begin();

    // Initialize LCD.
    clock__lcd.init();
    clock__lcd.clear();
    clock__lcd.backLight(true);

    // Get current time and print it.
    clock__currentTime = clock__rtc.now();
    clock__printDatetime();
}

/**************************************************************************//**
 * \fn void loop()
 *
 * \brief Infinite loop.
 ******************************************************************************/
void loop()
{
    // Get pressed key and process it.
    Keyboard::Key_t key = (Keyboard::Key_t)(clock__lcd.get_key());
    if (key > Keyboard::KeyNone)
    {
        clock__handleKey(key);
    }
   
    // If we aren't in adjust mode, get current time and print it.
    if (!clock__adjustMode)
    {
        clock__currentTime = clock__rtc.now();
        clock__printDatetime();
    }
   
    delay(200);
}

/******************************************************************************
 * Private function definitions.
 ******************************************************************************/

/**************************************************************************//**
 * \fn static void clock__handleKey(Keyboard::Key_t key)
 *
 * \brief Handle pressed key.
 *
 * \param   key Pressed key.
 ******************************************************************************/
static
void
clock__handleKey
(
    Keyboard::Key_t key
){
    switch (key)
    {
        case Keyboard::KeyRight:
        {
            if (clock__adjustMode)
            {
                if (clock__currentMember < clock__MemberSecond)
                {
                    byte tmpMember = (byte)clock__currentMember;
                    tmpMember++;
                    clock__currentMember = (clock__member_t)tmpMember;
                }
                else
                {
                    clock__currentMember = clock__MemberDay;
                }
                clock__setCursor();
            }
        }
        break;

        case Keyboard::KeyUp:
        {
            if (clock__adjustMode)
            {
                clock__incrementMember();
                clock__setCursor();
            }
        }
        break;

        case Keyboard::KeyDown:
        {
            if (clock__adjustMode)
            {
                clock__decrementMember();
                clock__setCursor();
            }
        }
        break;

        case Keyboard::KeyLeft:
        {
            if (clock__adjustMode)
            {
                if (clock__currentMember > clock__MemberDay)
                {
                    byte tmpMember = (byte)clock__currentMember;
                    tmpMember--;
                    clock__currentMember = (clock__member_t)tmpMember;
                }
                else
                {
                    clock__currentMember = clock__MemberSecond;
                }
                clock__setCursor();
            }
        }
        break;

        case Keyboard::KeySelect:
        {
            if (clock__adjustMode)
            {
                // If we are in adjust mode, update RTC time.
                clock__rtc.adjust(clock__currentTime);
                clock__lcd.noBlink();
                clock__lcd.noCursor();
                clock__currentMember = clock__MemberDay;
                clock__adjustMode = false;
            }
            else
            {
                // Enter adjust mode.
                clock__adjustMode = true;
                clock__lcd.setCursor(1, 0);
                clock__lcd.blink();
                clock__lcd.cursor();
            }
        }
        break;

        case Keyboard::KeyNone:
        case Keyboard::KeyInvalid:
        default:
        break;
    }
}

/**************************************************************************//**
 * \fn static void clock__setCursor()
 *
 * \brief Set cursor position.
 ******************************************************************************/
static
void
clock__setCursor()
{
    switch (clock__currentMember)
    {
        case clock__MemberDay:
            clock__lcd.setCursor(1, 0);
        break;
       
        case clock__MemberMonth:
            clock__lcd.setCursor(4, 0);
        break;
       
        case clock__MemberYear:
            clock__lcd.setCursor(9, 0);
        break;
       
        case clock__MemberHour:
            clock__lcd.setCursor(1, 1);
        break;
       
        case clock__MemberMinute:
            clock__lcd.setCursor(4, 1);
        break;
       
        case clock__MemberSecond:
            clock__lcd.setCursor(7, 1);
        break;
       
        default:
        break;
    }
}

/**************************************************************************//**
 * \fn static void clock__incrementMember()
 *
 * \brief Increment current member: day, month, year, hour, minute or second.
 ******************************************************************************/
static
void
clock__incrementMember()
{
    switch (clock__currentMember)
    {
        case clock__MemberDay:
        {
            byte day = clock__currentTime.day();
            day = (day + 1 <= CLOCK__DAY_MAX) ? (day + 1) : CLOCK__DAY_MIN;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                day,
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
       
        case clock__MemberMonth:
        {
            byte month = clock__currentTime.month();
            month = (month + 1 <= CLOCK__MONTH_MAX) ? (month + 1) : CLOCK__MONTH_MIN;
            DateTime tempTime
            (
                clock__currentTime.year(),
                month,
                clock__currentTime.day(),
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
       
        case clock__MemberYear:
        {
            word year = clock__currentTime.year();
            year = (year + 1 <= CLOCK__YEAR_MAX) ? (year + 1) : CLOCK__YEAR_MIN;
            DateTime tempTime
            (
                year,
                clock__currentTime.month(),
                clock__currentTime.day(),
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
       
        case clock__MemberHour:
        {
            byte hour = clock__currentTime.hour();
            hour = (hour + 1 <= CLOCK__HOUR_MAX) ? (hour + 1) : CLOCK__HOUR_MIN;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                clock__currentTime.day(),
                hour,
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }   
        break;
       
        case clock__MemberMinute:
        {
            byte minute = clock__currentTime.minute();
            minute = (minute + 1 <= CLOCK__MINUTE_MAX) ? (minute + 1) : CLOCK__MINUTE_MIN;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                clock__currentTime.day(),
                clock__currentTime.hour(),
                minute,
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
       
        case clock__MemberSecond:
        {
            byte second = clock__currentTime.second();
            second = (second + 1 <= CLOCK__SECOND_MAX) ? (second + 1) : CLOCK__SECOND_MIN;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                clock__currentTime.day(),
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                second
            );
            clock__currentTime = tempTime;
        }
        break;
       
        default:
        break;
    }
    clock__printDatetime();
}

/**************************************************************************//**
 * \fn static void clock__decrementMember()
 *
 * \brief Decrement current member: day, month, year, hour, minute or second.
 ******************************************************************************/
static
void
clock__decrementMember()
{
    switch (clock__currentMember)
    {
        case clock__MemberDay:
        {
            byte day = clock__currentTime.day();
            day = (day - 1 >= CLOCK__DAY_MIN) ? (day - 1) : CLOCK__DAY_MAX;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                day,
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
       
        case clock__MemberMonth:
        {
            byte month = clock__currentTime.month();
            month = (month - 1 >= CLOCK__MONTH_MIN) ? (month - 1) : CLOCK__MONTH_MAX;
            DateTime tempTime
            (
                clock__currentTime.year(),
                month,
                clock__currentTime.day(),
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
       
        case clock__MemberYear:
        {
            word year = clock__currentTime.year();
            year = (year - 1 >= CLOCK__YEAR_MIN) ? (year - 1) : CLOCK__YEAR_MAX;
            DateTime tempTime
            (
                year,
                clock__currentTime.month(),
                clock__currentTime.day(),
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
       
        case clock__MemberHour:
        {
            byte hour = clock__currentTime.hour();
            hour = (hour - 1 >= CLOCK__HOUR_MIN) ? (hour - 1) : CLOCK__HOUR_MIN;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                clock__currentTime.day(),
                hour,
                clock__currentTime.minute(),
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }   
        break;
       
        case clock__MemberMinute:
        {
            byte minute = clock__currentTime.minute();
            minute = (minute - 1 >= CLOCK__MINUTE_MIN) ? (minute - 1) : CLOCK__MINUTE_MAX;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                clock__currentTime.day(),
                clock__currentTime.hour(),
                minute,
                clock__currentTime.second()
            );
            clock__currentTime = tempTime;
        }
        break;
       
        case clock__MemberSecond:
        {
            byte second = clock__currentTime.second();
            second = (second - 1 >= CLOCK__SECOND_MIN) ? (second - 1) : CLOCK__SECOND_MAX;
            DateTime tempTime
            (
                clock__currentTime.year(),
                clock__currentTime.month(),
                clock__currentTime.day(),
                clock__currentTime.hour(),
                clock__currentTime.minute(),
                second
            );
            clock__currentTime = tempTime;
        }
        break;
       
        default:
        break;
    }
    clock__printDatetime();
}

/**************************************************************************//**
 * \fn static void clock__printDatetime()
 *
 * \brief Print current datetime.
 ******************************************************************************/
static
void
clock__printDatetime()
{
    // Build date string.
    char date[] = "01/01/2000";
    snprintf
    (
        date,
        strlen(date) + 1,
        "%02d/%02d/%04d",
        clock__currentTime.day(),
        clock__currentTime.month(),
        clock__currentTime.year()
    );
   
    // Build time string.
    char time[] = "00:00:00";
    snprintf
    (
        time,
        strlen(time) + 1,
        "%02d:%02d:%02d",
        clock__currentTime.hour(),
        clock__currentTime.minute(),
        clock__currentTime.second()
    );
   
    // Print date.
    clock__lcd.setCursor(0, 0);
    clock__lcd.print(date);
   
    // Print time.
    clock__lcd.setCursor(0, 1);
    clock__lcd.print(time);
}


Classe Keyboard :
Code: Tout sélectionner
#ifndef H__IDREAMMICRO__KEYBOARD__H
#define H__IDREAMMICRO__KEYBOARD__H

class Keyboard
{
    public:

        typedef enum Keys
        {
            KeyNone = -1,
            KeyRight,
            KeyUp,
            KeyDown,
            KeyLeft,
            KeySelect,
            KeyInvalid
        } Key_t;
};

#endif // H__IDREAMMICRO__KEYBOARD__H


Télécharger le projet

Enjoy!
SesechXP
 
Messages: 209
Inscription: Sam 28 Mai 2011 09:09
Localisation: 35

Re: Arduino + Mémoire + Deuligne = Horloge

Message non lude john_lenfr » Dim 6 Jan 2013 12:25

Bonjour,

Belle réalisation et très pratique!

J'aimerais insérer ce code dans un menu pour pouvoir régler l'heure quand j'en ai besoin .
Comment transformer ce code en fonction que je peux appeler quand je le veux?

Serait-il également possible d'avoir plus de commentaires sur le code car je suis débutant en programmation et je ne comprends pas tout...

Merci,
John

Windows XP SP3
IDE 0.22 ou 1.0
Arduino Uno/Mini v4/Mini Pro/Nano
Deuligne/Mémoire/XBee/Ethernet/Stalker/Sablier/Rotoshield
john_lenfr
 
Messages: 32
Inscription: Jeu 3 Jan 2013 19:36

Re: Arduino + Mémoire + Deuligne = Horloge

Message non lude SesechXP » Lun 7 Jan 2013 12:09

Content que ça puisse servir ;)

Avec quelques modifications, ça devrait le faire. j'avais commencé à y réfléchir mais je n'avais pas trouvé de bibliothèque de gestion de menu à mon goût :oops:

As-tu déjà un projet existant dans lequel insérer l'horloge ? Je pense que ce sera plus simple en prenant le problème dans ce sens...

Pas de souci pour les commentaires, quelles parties te posent problème au juste ?
SesechXP
 
Messages: 209
Inscription: Sam 28 Mai 2011 09:09
Localisation: 35

Re: Arduino + Mémoire + Deuligne = Horloge

Message non lude john_lenfr » Lun 7 Jan 2013 13:38

Pour le menu je compte m'inspirer du travail de tasos:
http://www.hw2sw.com/2012/04/29/circular-menu-in-arduino-redux/
Après pour lancer la fonction je pense qu'un IF bien placé suffit.
Et pour les commentaires ben tout en fait.
J'ai juste remarqué qu'il y a des structures de définies, le reste ne me parle pas trop.
Mais par exemple, si à la place du joystick j'ai des boutons poussoirs branchés sur les pins 7, 8, 9, 10 comment j'adapte le code?
;)

Windows XP SP3
IDE 0.22 ou 1.0
Arduino Uno/Mini v4/Mini Pro/Nano
Deuligne/Mémoire/XBee/Ethernet/Stalker/Sablier/Rotoshield
john_lenfr
 
Messages: 32
Inscription: Jeu 3 Jan 2013 19:36

Re: Arduino + Mémoire + Deuligne = Horloge

Message non lude SesechXP » Mar 8 Jan 2013 18:33

Pour ce qui est des définitions, je n'ai créé que deux énumérations : Keyboard::Keys et clock__members. Elles sont juste là pour éviter d'avoir des nombres magiques à traîner dans le code.

Chaque fonction a un rôle précis, et ne réalise qu'une tâche.

La fonction loop lit en permanence la touche du joystick.
Si une touche est appuyée, on la transmet à la fonction clock__handle_key qui la traite en conséquence. Si on est en mode "réglage de l'heure", les appuis sur les touches permettent de régler les différents membres (jour, mois, année, heure, minute, seconde).

Les fonctions clock__incrementMember et clock__decrementMember permettent d'incrémenter ou de décrémenter le membre sélectionné.

Enfin il y a une clock__printDatetime dont le rôle est d'afficher la date et l'heure sur l'écran.

Si tu veux changer de clavier, il suffit de changer, dans la fonction loop, la ligne :
Code: Tout sélectionner
Keyboard::Key_t key = (Keyboard::Key_t)(clock__lcd.get_key());

par la lecture de touche spécifique à ton clavier.

Ensuite tout le traitement de la touche est générique, c'est l'avantage de représenter les touches par le type Keyboard::Key_t.
SesechXP
 
Messages: 209
Inscription: Sam 28 Mai 2011 09:09
Localisation: 35

Re: Arduino + Mémoire + Deuligne = Horloge

Message non lude john_lenfr » Mar 8 Jan 2013 22:12

ok, c'est très clair comme explications.

Je vais sans doute me tourner vers l'utilisation d'un encodeur rotatif avec un poussoir quand on appuie dessus (encodeur)

Je n'ai pas encore testé l'utilisation d'un encodeur donc je vais d'abord me familiariser avec et si je ne trouve pas comment l'insérer dans ton code je reviendrais ici avec quelque chose de concret ce sera plus simple pour avancer.

Merci pour les explications ;)

Windows XP SP3
IDE 0.22 ou 1.0
Arduino Uno/Mini v4/Mini Pro/Nano
Deuligne/Mémoire/XBee/Ethernet/Stalker/Sablier/Rotoshield
john_lenfr
 
Messages: 32
Inscription: Jeu 3 Jan 2013 19:36

Re: Arduino + Mémoire + Deuligne = Horloge

Message non lude SesechXP » Mer 9 Jan 2013 07:45

Bonne méthode, il faut y aller progressivement en prenant le temps de comprendre comment fonctionne chaque élément. Une fois que c'est fait, on assemble le tout. Vouloir tout faire en même temps, c'est le meilleur moyen de se noyer :!:
SesechXP
 
Messages: 209
Inscription: Sam 28 Mai 2011 09:09
Localisation: 35


Retourner vers Vos projets, vos idées

Qui est en ligne

Utilisateurs parcourant ce forum: Google Feedfetcher et 1 invité

cron