[Partage] Clavier 4x3

la gestion d'un clavier 4x3 sans utiliser de bibliothèque et en utilisant le moins d'entrée sortie sur la carte arduino.

le clavier utilisé :

  • Pour commencer j'ai branché les 7 fils du clavier à l'arduino uno 3 entrées et 4 sorties

  • ensuite j'ai utilisé juste 3 entrées analogique et quelques résistances.

  • à suivre ...

Fichier pdf

le fichier zip avec les cablages et les programmes d'exemple

mise à jour des fichiers le 7/10/2015

  • simplification du montage utilise 6 résistances de 10kohms et 3 entrées analogique

exemple de gestion du clavier avec menu et lcd 16x2, j'ai essayer de commenter le plus possible

/* Arduino Uno, clavier 4x3 et écran lcd 16x2 i2c 
   gestion de menus avec le clavier, touche 8 et 2 navigue dans les menus et # entre dans le menu, la touche * remet à zéro les valeurs
 ===> les données du tableau eclac[] sont donnée à titre d'exemple car le montage du clavier branché sur une seule entrée analogique n'est pas définitif
 => le mot de passe est '2015'
   fifi82 2015
*/

#include <Wire.h> // pour la gestion du lcd
#include <LiquidCrystal_I2C.h>   // (i2c liaison série le lcd est branché avec 2 fils)
LiquidCrystal_I2C lcd(63,2,1,0,4,5,6,7,3,POSITIVE); //63 c'est l'adresse de mon afficheur

// pour la gestion du clavier
const int eclav[12]={229,389,495,306,486,594,459,647,742,927,976,992}; // valeurs à récupérée sur l'entrée A0
const int tclav[12]={1,2,3,4,5,6,7,8,9,-3,0,-2}; // correspondance des touches suivant les valeurs ci dessus
int mct1, mct2, ct;  // état et anti-rebond du clavier, ct est le code touche appuyé sur un seul scan (front montant)

// pour gerer le mot de passe
boolean pass=0;        // est à 1 si le mot de passe est bon

// pour la gestion des menus
const byte nbmenu=4;  // nombre de menu
char* menu[nbmenu]={"Mot de passe", " Sortie 13 1/0", " Temps 0 en ms", " Temps 1 en ms"};  // nom des menus pour l'affichage
unsigned int   data[nbmenu]={0,0,500,500};  // valeurs des données de chaque menu 
byte  nmenu=0; // choix du menu dans lequel on se trouve, au début 0 c'est le mot de passe qui débloque l'acces à tous les menus
boolean emenu=1; //état du menu si on est dans le menu ou pas, au début on entre dans le menu du mot de passe

// pour la gestion des timer
unsigned int  ptimer[2]={(data[2]),(data[3])};  // le preset du timer deux preset, le premier pour led éteinte le deuxieme pour led allumée
unsigned long timer=0; // temporisation pour le clignotement de la led
unsigned long time; // pour stocker le temps qui passe
 
void setup()
{

  lcd.begin (16,2);         //  configure le l'afficheur en 16x2
  lcd.setBacklight(HIGH);   //  allume l'afficheur
  lcd.home ();              //  init l’afficheur
  pinMode(13, OUTPUT);      // la led verte
  lcd.blink();              // affiche le pointeur carré clignotant
  aff();                    // rafraîchit l'écran 
  
}

void loop()
{
  mct1=clav(); if (mct1!=mct2) ct=mct2=mct1; // lecture du clavier et mémorisation pour l"anti-rebond front montant
  time=millis();   // mémorise le temps qui passe ...

if(emenu){  // si on est dans un menu "état menu"

  switch (nmenu) { // choix des menus "numéro menu"
  
  case 0: //menu 0 gestion du mot de passe, bloque l’accès aux autres menus  
    
      if(ct>-1) {data[nmenu]=data[nmenu]*10+ct; if (data[nmenu]>9999) data[nmenu]=0;  } // création du mot de passe ici je bloque les mots de passe de plus de 4 chiffres
      if (data[nmenu]==2015 && ct==-2) pass=1; else pass=0;    // mot de passe pour déverrouiller les menus "2015" et # ( de 0 à 65535 )
                           
  break;   
      
  case 1: // menu 1 etat de la sortie 13
   
     if(ct==1) data[nmenu]=1; // touche 1 active le clignotement de la led verte
     if(ct==0) data[nmenu]=0; // touche 0 désactive le clignotement de la led verte
 
  break;
      
  case 2: // temps 0 led éteinte
   
      if(ct>- 1) data[nmenu]=data[nmenu]*10+ct; // entre la valeur du clavier
      if(ct==-2) {ptimer[0]=(data[2]); timer=time+ptimer[0]; }  // enregistre la valeur et init le timer avec '#'

  break;   
      
  case 3:  // temps 1 led allumée
 
      if(ct>- 1) data[nmenu]=data[nmenu]*10+ct; // entre la valeur du clavier
      if(ct==-2) {ptimer[1]=(data[3]);  timer=time+ptimer[1];} // enregistre la valeur et init le timer avec '#'
      
  break;

    }
    if(ct==-2) emenu=0; // si la touche # est appuyée on sort du menu
    if(ct==-3) data[nmenu]=0; // reset la valeur avec '*'

  } else { // si on n'est pas dans un menu, "2" et "8" servent à naviguer et "#" pour entrer dans un menu
  
    if(ct==2 && pass && nmenu < nbmenu-1) nmenu++;  // monte d'un niveau de menu si le mot de passe est bon
    if(ct==8 && pass && nmenu > 0) nmenu--;        // descend d'un niveau de menu si le mot de passe est bon
    if(ct==-2) emenu=1; // rentre dans le menu
  }
  
  if (ct!=-1) aff(); // raffaichit l'écran si une touche est appuyée 
  
  // gestion des données
  if(data[1]) {  // si dans le menu 1 la valeur est 1 "Sortie 13 1/0"
               if (time>timer) if (digitalRead(13)) {digitalWrite(13, 0); timer=time+ptimer[0];}
                               else                 {digitalWrite(13, 1); timer=time+ptimer[1];}
                     
  }else digitalWrite(13, 0); // éteint la led verte si dans le menu 1 la valeur est 0
  
  ct=-1; // évite le rebond du clavier doit être à la fin de loop() 
}

 // ****************** gestion du clavier ******************************
int clav() { 
   int ret=-1, a=analogRead(A0);  // lecture de l’entrée analogique
   if (a>50) for (int i=0; i <= 11; i++) if (a < eclav[i]+5 && a> eclav[i]-5) ret=tclav[i];  // fourchette de +/-5
   return ret;   // retourne -1 => pas de touche, -2 => #, -3 => * et de 0 à 9 => 0 à 9
}

// ******************* gestion de l'affichage ***************************
void aff(){ 
 lcd.clear();  // efface l'écran

 if (emenu){ // si dans un menu
     if (pass) lcd.print(menu[nmenu]); else lcd.print("Code: 0-9 * #"); // pour le 1er menu on affiche "code: o-9 * # sur la premère ligne
     lcd.setCursor (0,1); if (!nmenu) lcd.print(data[0]);  else  lcd.print(data[nmenu]); // deuxième ligne
 } else {  // si sélection d'un menu
     lcd.print(menu[nmenu]);  if(!nmenu) if (pass) lcd.print(" on"); else lcd.print(" off"); // 1er ligne affiche le nom du menu ou l'état du mot de passe
     lcd.setCursor (0,1);
     lcd.print("Choix 2, 8, #");  // 2eme ligne
     lcd.setCursor (0,0);  // place le curseur en haut de l'écran
   }
}

Sur AVR tutorial, il y a même une méthode où on n'utilise qu'un seul fil!

Clavier 1 fil

Ca marche bien, mais il faut des résistances à 1%.

Bons tests.

Gérard.

oui c'est justement ce montage que je comptais faire, je vais tester ça

Merci bien

Bonjour je n'ai pas encore des résistances de 1% donc j'utilise des 5% et en plus je n'ais que des 10kohms !
ça fonctionne mais de temps en temps j'ai des bug mais pas souvent donc pas trop gênant pour le moment (phase test)
je pense que 5% c'est suffisant pour gérer le clavier je verrai bien ...

merci pepe

Un montage R/2R ne convient-il pas ?

Car dans ce cas en n'utilisant que des résistances R ( on en met 2 en série pour faire 2 R :slight_smile: ) on s'affranchi de la tolérance car c'est toujours pareil les 5% c'est tous les lots de fab confondu, mais si on prend des résistances d'un même lot de fab, pratiquement cela se traduit par du même ruban, elles seront à moins de 1 % entre elles.

j'ai 6 résistances de 7.5k une de 160ohms au + c'est se que j'ai sous la main pour faire mes premier test ça fonctionne mais il y à par moment des erreurs mais sans plus, j'ai un afficheur 16x2 le clavier fonctionne assez bien pour me balader dans les menu et entrer des valeurs sans trop d'erreurs.
je vais commander les bonnes résistances mais à 5% je verrai bien

resistances serie e12 : 182 = 180 , 681=680, 3320=3300, 825=820

15k idem, 1 k idem
on les trouve sans probleme à 1%, ce qui était bien plus rare et plus couteux jusque fin des années 90

en fait j'ai réussi à le faire avec les résistances 5% il me reste plus qu'à poster le résultat