Note

Bonjour et bienvenue dans la communauté SunFounder Raspberry Pi & Arduino & ESP32 Enthusiasts sur Facebook ! Explorez en profondeur les Raspberry Pi, Arduino et ESP32 avec d’autres passionnés.

Pourquoi nous rejoindre ?

  • Support d’experts : Résolvez vos problèmes après-vente et défis techniques avec l’aide de notre communauté et de notre équipe.

  • Apprenez et partagez : Échangez des astuces et des tutoriels pour améliorer vos compétences.

  • Avant-premières exclusives : Accédez en avant-première aux annonces de nouveaux produits.

  • Réductions spéciales : Bénéficiez de réductions exclusives sur nos nouveaux produits.

  • Promotions festives et concours : Participez à des promotions spéciales et des tirages au sort.

👉 Prêt à explorer et créer avec nous ? Cliquez sur [Ici] et rejoignez-nous dès aujourd’hui !

2.1.5 Keypad

Introduction

Un clavier numérique est une matrice rectangulaire de boutons. Dans ce projet, nous l’utiliserons pour saisir des caractères.

Composants

_images/list_2.1.5_keypad.png

Principe

Clavier numérique

Un clavier numérique est une matrice rectangulaire de 12 ou 16 boutons OFF-(ON). Leurs contacts sont accessibles via un connecteur adapté à une connexion avec un câble ruban ou une insertion dans un circuit imprimé. Dans certains claviers, chaque bouton se connecte à un contact séparé dans le connecteur, tandis que tous les boutons partagent une masse commune.

_images/image314.png

Souvent, les boutons sont encodés en matrice, ce qui signifie que chacun d’eux relie une paire unique de conducteurs dans une matrice. Cette configuration est adaptée pour un microcontrôleur, qui peut être programmé pour envoyer une impulsion de sortie à chacun des quatre fils horizontaux à tour de rôle. Pendant chaque impulsion, il vérifie les quatre fils verticaux restants pour déterminer lequel, le cas échéant, transporte un signal. Des résistances pullup ou pulldown doivent être ajoutées aux fils d’entrée pour empêcher les entrées du microcontrôleur de se comporter de manière imprévisible lorsqu’aucun signal n’est présent.

Schéma de câblage

_images/image315.png _images/image316.png

Procédures expérimentales

Étape 1 : Construisez le circuit.

_images/image186.png

Pour les utilisateurs de C

Étape 2 : Ouvrez le fichier de code.

cd ~/davinci-kit-for-raspberry-pi/c/2.1.5/

Étape 3 : Compilez le code.

gcc 2.1.5_Keypad.cpp -lwiringPi

Étape 4 : Exécutez le programme.

sudo ./a.out

Après l’exécution du code, les valeurs des boutons pressés sur le clavier (Valeur du bouton) seront affichées à l’écran.

Note

Si cela ne fonctionne pas après l’exécution ou si un message d’erreur s’affiche : "wiringPi.h : Aucun fichier ou répertoire de ce type", veuillez consulter C code is not working?.

Code

#include <wiringPi.h>
#include <stdio.h>

#define ROWS  4
#define COLS  4
#define BUTTON_NUM (ROWS * COLS)

unsigned char KEYS[BUTTON_NUM] {
'1','2','3','A',
'4','5','6','B',
'7','8','9','C',
'*','0','#','D'};

unsigned char rowPins[ROWS] = {1, 4, 5, 6};
unsigned char colPins[COLS] = {12, 3, 2, 0};

void keyRead(unsigned char* result);
bool keyCompare(unsigned char* a, unsigned char* b);
void keyCopy(unsigned char* a, unsigned char* b);
void keyPrint(unsigned char* a);
void keyClear(unsigned char* a);
int keyIndexOf(const char value);

void init(void) {
    for(int i=0 ; i<4 ; i++) {
        pinMode(rowPins[i], OUTPUT);
        pinMode(colPins[i], INPUT);
    }
}

int main(void){
    unsigned char pressed_keys[BUTTON_NUM];
    unsigned char last_key_pressed[BUTTON_NUM];

    if(wiringPiSetup() == -1){ //when initialize wiring failed,print message to screen
        printf("setup wiringPi failed !");
        return 1;
    }
    init();
    while(1){
        keyRead(pressed_keys);
        bool comp = keyCompare(pressed_keys, last_key_pressed);
        if (!comp){
            keyPrint(pressed_keys);
            keyCopy(last_key_pressed, pressed_keys);
        }
        delay(100);
    }
    return 0;
}

void keyRead(unsigned char* result){
    int index;
    int count = 0;
    keyClear(result);
    for(int i=0 ; i<ROWS ; i++ ){
        digitalWrite(rowPins[i], HIGH);
        for(int j =0 ; j < COLS ; j++){
            index = i * ROWS + j;
            if(digitalRead(colPins[j]) == 1){
                result[count]=KEYS[index];
                count += 1;
            }
        }
        delay(1);
        digitalWrite(rowPins[i], LOW);
    }
}

bool keyCompare(unsigned char* a, unsigned char* b){
    for (int i=0; i<BUTTON_NUM; i++){
        if (a[i] != b[i]){
            return false;
        }
    }
    return true;
}

void keyCopy(unsigned char* a, unsigned char* b){
    for (int i=0; i<BUTTON_NUM; i++){
        a[i] = b[i];
    }
}

void keyPrint(unsigned char* a){
    if (a[0] != 0){
        printf("%c",a[0]);
    }
    for (int i=1; i<BUTTON_NUM; i++){
        if (a[i] != 0){
            printf(", %c",a[i]);
        }
    }
    printf("\n");
}

void keyClear(unsigned char* a){
    for (int i=0; i<BUTTON_NUM; i++){
        a[i] = 0;
    }
}

int keyIndexOf(const char value){
    for (int i=0; i<BUTTON_NUM; i++){
        if ((const char)KEYS[i] == value){
            return i;
        }
    }
    return -1;
}

Explication du Code

unsigned char KEYS[BUTTON_NUM] {
'1','2','3','A',
'4','5','6','B',
'7','8','9','C',
'*','0','#','D'};

unsigned char rowPins[ROWS] = {1, 4, 5, 6};
unsigned char colPins[COLS] = {12, 3, 2, 0};

Déclarez chaque touche du clavier matriciel dans le tableau keys[] et définissez les broches de chaque ligne et colonne.

while(1){
        keyRead(pressed_keys);
        bool comp = keyCompare(pressed_keys, last_key_pressed);
        if (!comp){
            keyPrint(pressed_keys);
            keyCopy(last_key_pressed, pressed_keys);
        }
        delay(100);
    }

Ceci est la partie de la fonction principale qui lit et affiche la valeur des touches.

La fonction keyRead() lira l’état de chaque touche.

keyCompare() et keyCopy() sont utilisées pour déterminer si l’état d’une touche a changé (c’est-à-dire si une touche a été appuyée ou relâchée).

keyPrint() affichera la valeur de la touche dont le niveau actuel est élevé (la touche est enfoncée).

void keyRead(unsigned char* result){
    int index;
    int count = 0;
    keyClear(result);
    for(int i=0 ; i<ROWS ; i++ ){
        digitalWrite(rowPins[i], HIGH);
        for(int j =0 ; j < COLS ; j++){
            index = i * ROWS + j;
            if(digitalRead(colPins[j]) == 1){
                result[count]=KEYS[index];
                count += 1;
            }
        }
        delay(1);
        digitalWrite(rowPins[i], LOW);
    }
}

Cette fonction attribue un niveau élevé à chaque ligne à tour de rôle, et lorsque la touche dans la colonne est enfoncée, la colonne obtient un niveau élevé. Après la double boucle de vérification, l’état des touches compilé générera un tableau (result[]).

Lorsque vous appuyez sur la touche 3 :

_images/image187.png

RowPin [0] écrit un niveau élevé, et colPin[2] reçoit le niveau élevé. Les autres colPin obtiennent un niveau bas.

Cela donne 0,0,1,0. Lorsque rowPin[1], rowPin[2] et rowPin[3] sont écrits en niveau élevé, les colPin recevront tous un niveau bas.

Après la boucle, un tableau est généré :

result[BUTTON_NUM] {
0, 0, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0};
bool keyCompare(unsigned char* a, unsigned char* b){
    for (int i=0; i<BUTTON_NUM; i++){
        if (a[i] != b[i]){
            return false;
        }
    }
    return true;
}

void keyCopy(unsigned char* a, unsigned char* b){
    for (int i=0; i<BUTTON_NUM; i++){
        a[i] = b[i];
    }
}

Ces deux fonctions sont utilisées pour vérifier si l’état des touches a changé, par exemple lorsque vous relâchez la touche “3” ou appuyez sur “2”, keyCompare() renverra false.

KeyCopy() réécrit la valeur actuelle de la touche dans le tableau a (last_key_pressed[BUTTON_NUM]) après chaque comparaison pour permettre une comparaison la prochaine fois.

void keyPrint(unsigned char* a){
//printf("{");
    if (a[0] != 0){
        printf("%c",a[0]);
    }
    for (int i=1; i<BUTTON_NUM; i++){
        if (a[i] != 0){
            printf(", %c",a[i]);
        }
    }
    printf("\n");
}

Cette fonction est utilisée pour afficher la valeur de la touche actuellement enfoncée. Si la touche “1” est enfoncée, “1” sera affiché. Si vous appuyez sur “1” et ensuite sur “3”, “1, 3” sera affiché.

Pour les utilisateurs de Python

Étape 2 : Ouvrez le fichier de code.

cd ~/davinci-kit-for-raspberry-pi/python/

Étape 3 : Exécutez.

sudo python3 2.1.5_Keypad.py

Après l’exécution du code, les valeurs des touches pressées sur le clavier (valeur des boutons) seront affichées à l’écran.

Code

Note

Vous pouvez Modifier/Réinitialiser/Copier/Exécuter/Arrêter le code ci-dessous. Mais avant cela, vous devez accéder au chemin source du code, tel que davinci-kit-for-raspberry-pi/python.

import RPi.GPIO as GPIO
import time

class Keypad():

    def __init__(self, rowsPins, colsPins, keys):
        self.rowsPins = rowsPins
        self.colsPins = colsPins
        self.keys = keys
        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BCM)
        GPIO.setup(self.rowsPins, GPIO.OUT, initial=GPIO.LOW)
        GPIO.setup(self.colsPins, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

    def read(self):
        pressed_keys = []
        for i, row in enumerate(self.rowsPins):
            GPIO.output(row, GPIO.HIGH)
            for j, col in enumerate(self.colsPins):
                index = i * len(self.colsPins) + j
                if (GPIO.input(col) == 1):
                    pressed_keys.append(self.keys[index])
            GPIO.output(row, GPIO.LOW)
        return pressed_keys

def setup():
    global keypad, last_key_pressed
    rowsPins = [18,23,24,25]
    colsPins = [10,22,27,17]
    keys = ["1","2","3","A",
            "4","5","6","B",
            "7","8","9","C",
            "*","0","#","D"]
    keypad = Keypad(rowsPins, colsPins, keys)
    last_key_pressed = []

def loop():
    global keypad, last_key_pressed
    pressed_keys = keypad.read()
    if len(pressed_keys) != 0 and last_key_pressed != pressed_keys:
        print(pressed_keys)
    last_key_pressed = pressed_keys
    time.sleep(0.1)

# Définir une fonction destroy pour nettoyer tout après la fin du script
def destroy():
    # Libérer les ressources
    GPIO.cleanup()

if __name__ == '__main__':     # Le programme commence ici
    try:
        setup()
        while True:
            loop()
    except KeyboardInterrupt:   # Lorsque 'Ctrl+C' est pressé, la fonction destroy() sera exécutée.
        destroy()

Explication du Code

def setup():
    global keypad, last_key_pressed
    rowsPins = [18,23,24,25]
    colsPins = [10,22,27,17]
    keys = ["1","2","3","A",
            "4","5","6","B",
            "7","8","9","C",
            "*","0","#","D"]
    keypad = Keypad(rowsPins, colsPins, keys)
    last_key_pressed = []

Déclarez chaque touche du clavier matriciel dans le tableau keys[] et définissez les broches pour chaque ligne et colonne.

def loop():
    global keypad, last_key_pressed
    pressed_keys = keypad.read()
    if len(pressed_keys) != 0 and last_key_pressed != pressed_keys:
        print(pressed_keys)
    last_key_pressed = pressed_keys
    time.sleep(0.1)

Voici la partie de la fonction principale qui lit et affiche la valeur des boutons pressés.

La fonction keyRead() lira l’état de chaque bouton.

La condition if len(pressed_keys) != 0 and last_key_pressed != pressed_keys est utilisée pour vérifier

si une touche est enfoncée et si l’état de la touche pressée a changé. (Si vous appuyez sur « 3 » après avoir appuyé sur « 1 », cette condition est vraie.)

Affiche la valeur de la touche actuellement pressée lorsque la condition est remplie.

L’instruction last_key_pressed = pressed_keys attribue l’état de chaque jugement à un tableau last_key_pressed pour faciliter le prochain tour de jugement conditionnel.

def read(self):
        pressed_keys = []
        for i, row in enumerate(self.rowsPins):
            GPIO.output(row, GPIO.HIGH)
            for j, col in enumerate(self.colsPins):
                index = i * len(self.colsPins) + j
                if (GPIO.input(col) == 1):
                    pressed_keys.append(self.keys[index])
            GPIO.output(row, GPIO.LOW)
        return pressed_keys

Cette fonction affecte un niveau haut à chaque ligne à tour de rôle, et lorsque le bouton d’une colonne est enfoncé, la colonne dans laquelle la touche se trouve reçoit un niveau haut. Après la vérification en boucle, la valeur du bouton dont l’état est 1 est stockée dans le tableau pressed_keys.

Si vous appuyez sur la touche « 3 » :

_images/image187.png

rowPins[0] est écrit en niveau haut, et colPins[2] obtient un niveau haut.

colPins[0], colPins[1], colPins[3] obtiennent un niveau bas.

Il y a quatre états : 0, 0, 1, 0 ; et nous écrivons « 3 » dans pressed_keys.

Lorsque rowPins[1], rowPins[2] et rowPins[3] sont écrits en niveau haut, colPins[0] ~ colPins[4] obtiennent un niveau bas.

La boucle s’arrête et retourne pressed_keys = “3”.

Si vous appuyez sur les touches “1” et “3”, pressed_keys retournera = [“1”, “3”].

Image du Phénomène

_images/image188.jpeg