Partage
  • Partager sur Facebook
  • Partager sur Twitter

Arduino Projet Débutant

Sujet résolu
1 février 2015 à 21:31:41

Bonjour, je suis débutant sur Arduino Uno et je dois pour un projet développer une horloge en temps réel. A ma disposition j'ai le logiciel Arduino de programmation, un Arduino Uno et un composant qui est le DS1307 (http://tiptopboards.free.fr/arduino_forum/viewtopic.php?f=2&t=5)

Tout mon codage doit être en bus I2C et j'ai l'autorisation au bibliothèque de code. Mais j'ai réussi à programmer mon horloge mais malheureusement je dois être capable de pouvoir régler l'heure via un clavier 12 touches. Quelqu'un pourrait m'aider avec un code simple à comprendre ?

  • Partager sur Facebook
  • Partager sur Twitter
1 février 2015 à 22:24:28

Bonjour Frage,

On ne va quand même pas te donner la solution prête à copier/coller.

Donnes nous ce que tu as testé, on te diras ce qui ne va pas et comment corriger ça.

  • Partager sur Facebook
  • Partager sur Twitter
1 février 2015 à 23:36:02

Actuellement j'ai testé deux solutions, une trouvé sur internet mais je ne comprends pas tout et je n'ai pas le choix du réglage de l'heure via un clavier, je peux juste imposé l'heure de départ.

CODE SUPPRIME POUR EVITER LES COPIES CAR PROJET BAC



Le clavier est un EC83 http://www.lextronic.fr/P737-clavier-12-touches-ec83.html

-
Edité par Frage 11 février 2015 à 23:27:24

  • Partager sur Facebook
  • Partager sur Twitter
1 février 2015 à 23:38:06

J'ai oublier de sauvegarder mon travail mais je pourrai le refaire facilement pour que dans le premier programme il y ai un 0 quand le jours, mois est inférieur à 10
  • Partager sur Facebook
  • Partager sur Twitter
1 février 2015 à 23:47:53

Sans les balises code, c'est illisible...

Il faut vraiment que tu utilises le petit bouton </>

  • Partager sur Facebook
  • Partager sur Twitter
1 février 2015 à 23:52:23

Voila désolé je suis nouveau sur le forum :)
  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 0:21:57

Cela m'a tout l'air d'être un clavier matriciel ;)

Du coup, tu dois pouvoir utiliser cette lib : http://playground.arduino.cc/Code/Keypad

Je te propose donc de tester ce code :

#include <Keypad.h>

const byte ROWS = 4;
const byte COLS = 3;

char keys[ROWS][COLS] = {
	{'1','2','3'},
	{'4','5','6'},
	{'7','8','9'},
	{'#','0','*'}
};

byte rowPins[ROWS] = {R0, R1, R2, R3};
byte colPins[COLS] = {C0, C1, C2};

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup() {
	Serial.begin(9600);
}

void loop(){
	char key = keypad.getKey();
	if (key != NO_KEY){
		Serial.println(key);
	}
}

Avec ce branchement :

Tu noteras que j'ai mis R0, R1, R2, R3, C0, C1, C2 dans le code et sur la photo.

Il faut que tu relies ces fils sur des pins numérique de l'arduino et que tu mettes à jour le code.

Tu peux prendre les pins que tu veux, sauf celles qui ont une fonction précise (du genre, pas les pins 0 et 1 car elles servent de Tx/Rx).

Sur l'arduino uno, tu peux utiliser les pins 2,3,4,5,6,7,8,9,10,11,12 et 13.

Par exemple, si tu décides de mettre R0, R1, R2, R3 sur les pins 2,3,4,5, alors le code ligne 13 devient alors :

byte rowPins[ROWS] = {2, 3, 4, 5};

 Si tout se passe bien, tu devrais donc voir s'afficher les touches dans le moniteur série de ton IDE ;)

-
Edité par lorrio 2 février 2015 à 0:22:56

  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 0:36:42

Merci de ta réponse. En effet j'avais vu cette portion de code mais le probleme va être la configuration de l'heure c'est la oû je suis en recherche.
  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 0:37:55

Et aussi la comprehension complète du code.*
  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 8:12:03

En programmation, il y a un principe de base qu'il faut toujours respecter quand on découvre quelque chose de nouveau : ne jamais foncer tête baissée en voulant faire l'application finale dès le début.

Il faut toujours procédé en se fixant des objectifs intermédiaire de façon à bien comprendre.

Dans ton cas, cela peut être :

- réussir à afficher l'heure du DS1307RTC toutes les secondes (sans l'avoir paramétré)

- réussir à paramétrer l'heure du DS1307RTC avec une valeur brute (du genre 1er janvier 2010).

- réussir à afficher les boutons appuyé sur le clavier

- réussir à sauvegarder les boutons appuyés et les afficher lorsque l'utilisateur appuis sur "#" (par exemple, l'utilisateur va taper "02*02*2015*14*10" puis # et tu devras afficher 02*02*2015*14*10 d'un coup)

- réussir à décomposer ce qu'à écrit l'utilisateur et lui afficher quand il appuis sur "#" (dans l'exemple précédant, tu devrais donc afficher 02/02/2015 14h10")

Une fois que tout cela est fait, alors tu pourras combiner ces différents programmes pour faire ton application finale.

Je te laisse donc essayer les premières étapes et poster les codes correspondants avec des commentaires ;)

Si tu as des questions, n'hésites pas.

-
Edité par lorrio 2 février 2015 à 8:15:55

  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 11:20:42

Premiere etape : avec code incrementé ou avec la bibliothèque wire ? Car je ne comprends pas les wire.transmission etc. (Je commencerai se soir quand je rentrerai)
  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 12:56:34

Le DS1307RTC est un périphérique en I2C.

Pour y accéder, tu as donc 2 façons :

- soit tu fais directement des lecture/écriture I2C en te basant sur la datasheet et Wiring.h de façon à écrire les bonnes choses au bon endroit.

- soit tu utilises la lib DS1307RTC.h qui propose une interface bien plus conviviale pour l'utilisateur avec des fonction toute prête telle que RTC.read par exemple.

Je te conseille vivement d'utiliser DS1307RTC.h ;)

  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 13:25:53

Mon code doit être en I2C donc si j'utilise la lib DS1307 il faudra que je le convertisse à la fin. Je verai se soir en rentrant.
  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 14:09:44

Pourquoi faut-il qu'il soit en I2C ?

Ton prof t'interdit d'utiliser la lib DS1307RTC.h ?

Si tu regardes le code source de cette lib, tu verras qu'elle utilise Wire.h en interne alors pourquoi se priver ?

  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 14:39:57

Car mon heure va être utilisée par d'autres  fonctions sur un même arduino qui seront aussu en I2C
  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 17:20:47

Je ne vois absolument pas le rapport.

Comme je te l'ai dis, DS1307RTC utilise Wire en interne.

Vu que tu ne me crois pas, voici la preuve en exemple pour paramétrer l'heure :

Dans ton code avec Wire.h, tu fais ceci :

void setDateTime()
{

    byte seconde = 00; //0-59
    byte minute = 05; //0-59
    byte heure = 11; //0-23
    byte nomjour = 3; //1-7
    byte jour = 14; //1-31
    byte mois = 2; //1-12
    byte annee = 15; //0-99

    Wire.beginTransmission(DS1307_ADDRESS);
    Wire.write(zero);

    Wire.write(decToBcd(seconde));
    Wire.write(decToBcd(minute));
    Wire.write(decToBcd(heure));
    Wire.write(decToBcd(nomjour));
    Wire.write(decToBcd(jour));
    Wire.write(decToBcd(mois));
    Wire.write(decToBcd(annee));
 
    Wire.endTransmission();

}

Bref, tu fais un Wire.beginTransmission suivie de plusieurs Wire.write pour finir avec un Wire.endTransmission.

Maintenant, imaginons que tu utilises RTC.write de la lib DS1307RTC.h, voici le code de cette fonction :

void DS1307RTC::write(tmElements_t &tm)
{
	Wire.beginTransmission(DS1307_CTRL_ID);
	Wire.write((uint8_t)0x00); // reset register pointer
	Wire.write(dec2bcd(tm.Second)) ;
	Wire.write(dec2bcd(tm.Minute));
	Wire.write(dec2bcd(tm.Hour)); // sets 24 hour format
	Wire.write(dec2bcd(tm.Wday));
	Wire.write(dec2bcd(tm.Day));
	Wire.write(dec2bcd(tm.Month));
	Wire.write(dec2bcd(tmYearToY2k(tm.Year)));
	Wire.endTransmission();
}

Là aussi, c'est un Wire.beginTransmission suivie de plusieurs Wire.write pour finir avec un Wire.endTransmission.

Bref, c'est exactement la même chose !

Sauf qu'avec ton code qui n'est pas commenté, on ne comprend rien alors qu'avec un appel à RTC.write, on comprend tout de suite que l'on vient écrire l'heure dans le RTC (et donc l'initialiser).


  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 19:39:20

Je peux pas tester via un arduino pour l'instant, mais je viens de finir ceci ce qui normalement affiche l'heure + date de façon correct.

CODE SUPPRIME POUR EVITER LES COPIES CAR PROJET BAC

-
Edité par Frage 11 février 2015 à 23:25:47

  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 20:03:13

Wire ou RTC_DS1307, il faut choisir.

Si tu fais des appels à RTC.now, RTC.write ... tu n'as pas besoin de Wire, sauf pour faire un Wire.begin().

Du coup, ta ligne 67 n'a stricement rien à faire là.


Veilles aussi à bien faire des initialisations dans setup et non dans loop.

Les appels de Wire.begin(); et RTC.begin();, ça va dans le setup.


Petite astuce que je te donne pour éviter les gros switch/case qui se suivent (du genre case1, case2, case3, case4...) : faire un tableau ;)

Cf le code que je te propose plus bas.


Et surtout, le plus important : DES COMMENTAIRES.


Au final, ton code devrait donc être :

#include <Wire.h>
#include <RTClib.h>


// Tableau de traduction des mois [1/2]
const char* month01 = "Janvier";
const char* month02 = "Fevrier";
const char* month03 = "Mars";
const char* month04 = "Avril";
const char* month05 = "Mai";
const char* month06 = "Juin";
const char* month07 = "Juillet";
const char* month08 = "Aout";
const char* month09 = "Septembre";
const char* month10 = "Octobre";
const char* month11 = "Novembre";
const char* month12 = "Decembre";
// Tableau de traduction des mois [2/2]
const char* monthTab[] = { 
		month01, month02, month03, month04, month05, month06, 
		month07, month08, month09, month10, month11, month12 };


// Gestionnaire du DS1307
RTC_DS1307 RTC;



// Setup: initialisation de l'arduino (Serial, Wire et RTC)
void setup()
{

	// Initialisation du Serial
	Serial.begin(9600);

	// Initialisation du bus I2C et du RTC
	Wire.begin();
	RTC.begin();

}


// Loop: affichage de l'heure toutes les secondes
void loop()
{

	// Réccupération de la date actuelle
	DateTime now = RTC.now();

	// Affichage de l'heure au faut hh:mm:ss
	Serial.print(now.hour());
	Serial.print(":");
	if (now.minute() < 10) {  Serial.print("0"); }
	Serial.print(now.minute());
	Serial.print(":");
	if (now.second() < 10) { Serial.print("0"); }
	Serial.print(now.second());

	// Affichage de l'heure au format j/m/a
	Serial.print(now.day());
	Serial.print("/");
		// L'astuce pour ne pas faire le switch/case : print de l'élément du taleau
	Serial.print(monthTab[now.month()-1]); 
	Serial.print("/");
	Serial.println(now.year());

	// Attente de 1s avant de recommencer
	delay(1000);

}




RTC_DS1307
  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 20:34:59

Alors si je ne me trompe pas ce code ci est la première étape ainsi que le deuxième que tu m'as conseillé (ps : vraiment merci de m'aider)

CODE SUPPRIME POUR EVITER LES COPIES CAR PROJET BAC

-
Edité par Frage 11 février 2015 à 23:25:57

  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 20:37:29

Je n'ai pas d'arduino sous la main pour tester mais ça m'a l'air pas mal ;)

Je te laisse donc tester et passer à l'étape 3 :)

  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 20:43:06

Pour l'étape 3 je prends en gros le code que j'avais trouvé et que tu as réécris ^^

CODE SUPPRIME POUR EVITER LES COPIES CAR PROJET BAC

Ensuite je présume qu'il faut faire pour l'étape quatre un gros while, avec white(key = #) {//lancement du code de réglage du adjusttime personnalisé avec le changement des bytes un par un}

sinon le loop normal

-
Edité par Frage 11 février 2015 à 23:28:01

  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 20:48:42

Non, pas besoin de while, tu peux faire ça dans le loop :

void loop() {

    // Réccupération de la touche enfoncée
    char key = keypad.getKey();

    // Si une touche est effectivement enfoncée
    if ( key != NO_KEY ) {

        // Si c'est un #
        if ( key == '#' ) {

            /* TODO: afficher toutes les touches déjà enfoncées */

        // Si ce n'est pas un #
        } else {

            /* TODO: mémoriser la touche pour l'afficher plus tard */

        }

    }

}



-
Edité par lorrio 2 février 2015 à 20:49:25

  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 20:56:39

On peut pas faire directement

CODE SUPPRIME POUR EVITER LES COPIES CAR PROJET BAC

(les lignes de code bug sur le forum)

-
Edité par Frage 11 février 2015 à 23:26:12

  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 21:05:58

Si tu veux griller les étapes, alors oui, tu peux faire un truc de ce genre.

Mais ce n'est pas pour rien que je te propose des objectifs intermédiaires.

D'autant plus que ce genre de if ne peut pas marcher car pour régler l'heure, il te faut appuyer sur plusieurs boutons.

D'où ma proposition de sauvegarder les touches appuyées et de les traiter toutes d'un coup quand tu appuis sur #

-
Edité par lorrio 2 février 2015 à 21:07:51

  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 23:15:19

J'ai essayé quelque chose je préfère que tu vérifies avant de continuer plus, juste demande de l'aide pour lire deux caractères (les mettres à la suite; remplacer les ? que j'ai mis dans le code).

CODE SUPPRIME POUR EVITER LES COPIES CAR PROJET BAC

-
Edité par Frage 11 février 2015 à 23:26:21

  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 23:49:39

Les == servent à faire une comparaison.

Écrire une ligne qui contient uniquement minute1 == key; n'a donc strictement aucun sens.


Fais aussi attention avec waitForKey :

This function will wait forever until someone presses a key. Warning: It blocks all other code until a key is pressed. That means no blinking LED's, no LCD screen updates, no nothing with the exception of interrupt routines.

Cela signifie que cette fonction bloques ton programme temps que tu n'appuie pas sur une touche.

Du coup, dès que tu appuis sur #, ton affichage de l'heure s'arrête temps que tu n'as pas entré l'heure.

Est-ce vraiment ce que tu veux ?

-
Edité par lorrio 2 février 2015 à 23:50:24

  • Partager sur Facebook
  • Partager sur Twitter
2 février 2015 à 23:54:54

Donc il faudrait que je retire un =.

Ensuite je pensais écrire heure : 00:00:00

et à chaque fois qu'une touché est pressée il y a un remplacement

00:00:00

02:00:00

02:50:00

02:55:00

Après si tu as une autre façon plus facile ou autre je suis toujours preneur.

-
Edité par Frage 2 février 2015 à 23:55:13

  • Partager sur Facebook
  • Partager sur Twitter
3 février 2015 à 0:47:41

Vu comme ça, c'est possible.

Du coup, pas besoin de "#".

A chaque appuis sur une touche, il te faudra alors reconfigurer l'un des éléments de la date.

Tu devras donc forcément faire un petit compteur qui retient l'élément à modifier : d'abord les dizaine d'heure, puis les unités d'heures, puis les dizaines de minutes, puis les unités de minutes ...

Pour que ton code soit réactif, il te faut à tout pris virer les delay et toute fonction bloquante.

Pour ne pas avoir à utiliser delay, tu peux faire un truc de ce genre :

loop {

    Récupération de la date

    Les secondes ont-elles changées depuis la dernière fois ?
    Si oui : rafraichir le Serial
    Si non : le rien faire

}

Vu que loop tourne en boucle, ton code va lire la date des milliers de fois par seconde (ce n'est pas forcément dérangeant) mais faire qu'un Serial.print toutes les secondes.

Au passage, tu peux donc rajouter la gestion du bouton dans cette boucle, toujours sans faire d'appel bloquant.

Le code devient alors un truc du genre :

loop {

    Récupération de la date

    Les secondes ont-elles changées depuis la dernière fois ?
    Si oui : rafraichir le Serial
    Si non : le rien faire

    Récupération pération du bouton

    Un bouton est-il appuyé ?
    Si oui : mettre à jour le RTC
    Si non : ne rien faire

}

Là encore, l'arduino va scanner les boutons des milliers de fois par seconde mais ce n'est pas dérangeant.


Pour faire ta mise à jour du RTC, il va te falloir faire un peu de math en jouant sur addition, multiplication, modulo, divison...

Histoire de te mettre sur la piste, voici un petit code qui permet de changer les unités de minutes à chaque appuis sur un bouton, tout en faisant défiler l'heure toutes les secondes

#include <Wire.h>
#include <RTClib.h>
#include <Keypad.h>

const byte rows = 4; // 4 colonnes pour le clavier
const byte cols = 3; // 3 colonnes pour le clavier

// Attribution des valeurs numériques pour le clavier
char keys[rows][cols] =
{
	{'1','2','3'},
	{'4','5','6'},
	{'7','8','9'},
	{'#','0','*'}
};

byte rowPins[rows] = {5, 4, 3, 2}; // Lignes connections
byte colPins[cols] = {8, 7, 6};    // Colonnes connections
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, rows, cols );

// Tableau de traduction des mois [1/2]
const char* month01 = "Janvier";
const char* month02 = "Fevrier";
const char* month03 = "Mars";
const char* month04 = "Avril";
const char* month05 = "Mai";
const char* month06 = "Juin";
const char* month07 = "Juillet";
const char* month08 = "Aout";
const char* month09 = "Septembre";
const char* month10 = "Octobre";
const char* month11 = "Novembre";
const char* month12 = "Decembre";
// Tableau de traduction des mois [2/2]
const char* monthTab[] = {
		month01, month02, month03, month04, month05, month06,
		month07, month08, month09, month10, month11, month12 };

// Gestionnaire du DS1307
RTC_DS1307 RTC;


// DisplayTime: affiche la date et l'heure
void displayTime(DateTime dt);


// Secondes du RTC lors du dernier affichage
int lastDisplaySec = -1;

 
// Setup: initialisation de l'arduino (Serial, Wire et RTC)
void setup()
{
    // Initialisation du Serial
    Serial.begin(9600);
    // Initialisation du bus I2C et du RTC
    Wire.begin();
    RTC.begin();
    // Réglage de l'horloge au 1 janvier 2010 00:00:00
    RTC.adjust(DateTime(2010,1,1,0,0,0));
}
  
  
// Loop: affichage de l'heure toutes les secondes
void loop()
{
	
	// Réccupération de la date actuelle
	DateTime now = RTC.now();
	
	// Si les secondes ont changées, on raffraichie l'affichage
	if ( now.second() != lastDisplaySec ) {
		displayTime(now);
		lastDisplaySec = now.second();
	}
	
	// Réccupération d'une touche appuyée 
	char key = keypad.getKey();
	
	// Si une touche 0 à 9 est appuyée, alors on mets à jour la date
	if ( ( key >= '0' ) && ( key >= '9' ) ) {
	
		// Convertion du code ascii en int
		int code = ( key - '0 );
		
		// Création de la variable mins dont les unités sont modifiées par la touche
		int mins = now.minute();
		mins = ( mins - ( mins % 10 ) + code );
		
		// Reparamétrage du RTC
		RTC.write(now.year(), now.month(), now.day(), now.hour(), mins, now.second());
		
	}
	
	// Et surtout pas de delay !
	
}


// DisplayTime: affiche la date et l'heure
void displayTime(DateTime dt) {

    // Affichage de l'heure au faut hh:mm:ss
    Serial.print(dt.hour());
    Serial.print(":");
    if (dt.minute() < 10) {  Serial.print("0"); }
    Serial.print(dt.minute());
    Serial.print(":");
    if (dt.second() < 10) { Serial.print("0"); }
    Serial.print(dt.second());
  
    // Affichage de l'heure au format j/m/a
    Serial.print(dt.day());
    Serial.print("/");
    //Print de l'élément du taleau
    Serial.print(monthTab[dt.month()-1]);
    Serial.print("/");
    Serial.println(dt.year());

}






  • Partager sur Facebook
  • Partager sur Twitter
3 février 2015 à 7:30:37

Ligne 81 : il n'y a pas une faute sur le >=9   c'est pas plutot <=9
  • Partager sur Facebook
  • Partager sur Twitter
3 février 2015 à 7:48:22

Et il faut prendre en compte le 0 ?

  • Partager sur Facebook
  • Partager sur Twitter