Nota

Ciao, benvenuto nella Community di SunFounder per appassionati di Raspberry Pi, Arduino e ESP32 su Facebook! Approfondisci le tue conoscenze su Raspberry Pi, Arduino ed ESP32 insieme ad altri appassionati.

Perché unirti?

  • Supporto Esperto: Risolvi i problemi post-vendita e le sfide tecniche con l’aiuto della nostra community e del nostro team.

  • Impara e Condividi: Scambia suggerimenti e tutorial per migliorare le tue competenze.

  • Anteprime Esclusive: Ottieni accesso anticipato agli annunci di nuovi prodotti e anteprime.

  • Sconti Speciali: Approfitta di sconti esclusivi sui nostri prodotti più recenti.

  • Promozioni Festive e Giveaway: Partecipa ai concorsi e alle promozioni festive.

👉 Pronto a esplorare e creare insieme a noi? Clicca [Qui] e unisciti oggi stesso!

2.1.5 Tastierino

Introduzione

Un tastierino è un array rettangolare di pulsanti. In questo progetto, lo useremo per inserire caratteri.

Componenti

_images/list_2.1.5_keypad.png

Principio

Tastierino

Un tastierino è un array rettangolare di 12 o 16 pulsanti OFF-(ON). I contatti sono accessibili tramite un connettore adatto per un cavo a nastro o per l’inserimento in un circuito stampato. In alcuni tastierini, ogni pulsante è collegato a un contatto separato nel connettore, mentre tutti i pulsanti condividono una massa comune.

_images/image314.png

Più spesso, i pulsanti sono codificati a matrice, il che significa che ognuno di essi collega una coppia unica di conduttori in una matrice. Questa configurazione è adatta per un polling da parte di un microcontrollore, programmato per inviare un impulso di uscita su ciascuno dei quattro fili orizzontali a turno. Durante ogni impulso, controlla in sequenza i restanti quattro fili verticali per determinare quale di essi, se presente, sta trasmettendo un segnale. Per evitare comportamenti imprevedibili degli ingressi del microcontrollore quando non è presente alcun segnale, dovrebbero essere aggiunti resistori di pullup o pulldown ai fili di ingresso.

Schema Elettrico

_images/image315.png _images/image316.png

Procedure Sperimentali

Passo 1: Assembla il circuito.

_images/image186.png

Per gli Utenti di Linguaggio C

Passo 2: Apri il file del codice.

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

Passo 3: Compila il codice.

gcc 2.1.5_Keypad.cpp -lwiringPi

Passo 4: Esegui.

sudo ./a.out

Dopo l’esecuzione del codice, i valori dei pulsanti premuti sul tastierino (Valore del pulsante) verranno visualizzati sullo schermo.

Nota

Se non funziona dopo l’esecuzione o viene visualizzato un messaggio di errore: "wiringPi.h: No such file or directory", fai riferimento a Il codice C non funziona?.

Codice

#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){ //in caso di errore nella configurazione iniziale, stampa un messaggio a schermo
        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;
}

Spiegazione del Codice

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};

Dichiara ciascun tasto della tastiera a matrice nell’array keys[] e definisce i pin di ogni riga e colonna.

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);
    }

Questa parte della funzione principale legge e stampa il valore del pulsante premuto.

La funzione keyRead() legge lo stato di ogni pulsante.

KeyCompare() e keyCopy() vengono utilizzate per verificare se lo stato di un pulsante è cambiato (cioè se è stato premuto o rilasciato).

keyPrint() stampa il valore del pulsante che si trova attualmente ad un livello alto (cioè il pulsante è premuto).

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);
    }
}

Questa funzione assegna un livello alto a ciascuna riga a turno, e quando viene premuto un pulsante in una colonna, la colonna in cui si trova il pulsante ottiene un livello alto. Dopo il giudizio del ciclo a due livelli, la compilazione dello stato del pulsante genererà un array (result[]).

Quando si preme il pulsante 3:

_images/image187.png

RowPin[0] scrive il livello alto e colPin[2] ottiene il livello alto. ColPin[0], colPin[1], colPin[3] ottengono il livello basso.

Questo produce 0,0,1,0. Quando rowPin[1], rowPin[2] e rowPin[3] sono scritti ad un livello alto, colPin[0]~colPin[4] ottengono un livello basso.

Dopo il completamento del giudizio del ciclo, si genera un array:

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];
    }
}

Queste due funzioni vengono utilizzate per determinare se lo stato del tasto è cambiato, ad esempio quando si rilascia il pulsante premuto '3' o si preme '2', keyCompare() restituisce false.

KeyCopy() viene utilizzata per riscrivere il valore corrente del pulsante per l’array a (last_key_pressed[BUTTON_NUM]) dopo ogni confronto. Così possiamo confrontarli la volta successiva.

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");
}

Questa funzione stampa il valore del pulsante attualmente premuto. Se viene premuto il pulsante “1”, verrà stampato “1”. Se vengono premuti i pulsanti “1” e “3”, verrà stampato “1, 3”.

Per Utenti Python

Passo 2: Apri il file del codice.

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

Passo 3: Esegui.

sudo python3 2.1.5_Keypad.py

Dopo aver eseguito il codice, i valori dei pulsanti premuti sulla tastiera (valore del pulsante) verranno visualizzati sullo schermo.

Codice

Nota

Puoi Modificare/Reimpostare/Copiare/Eseguire/Interrompere il codice qui sotto. Prima di procedere, devi accedere al percorso del codice sorgente come 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)

# Definisci una funzione di distruzione per pulire tutto al termine dello script
def destroy():
    # Rilascia risorse
    GPIO.cleanup()

if __name__ == '__main__':     # Il programma inizia da qui
    try:
        setup()
        while True:
            loop()
    except KeyboardInterrupt:   # Quando viene premuto 'Ctrl+C', la funzione destroy() viene eseguita.
        destroy()

Spiegazione del Codice

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 = []

Dichiara ogni tasto della tastiera a matrice nell’array keys[] e definisce i pin di ogni riga e colonna.

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)

Questa è la parte della funzione principale che legge e stampa il valore del tasto premuto.

La funzione keyRead() legge lo stato di ogni tasto.

L’istruzione if len(pressed_keys) != 0 and last_key_pressed != pressed_keys viene utilizzata per determinare se è stato premuto un tasto e lo stato del tasto stesso. (Se premi “3” mentre premi “1”, la condizione è vera.)

Stampa il valore del tasto premuto attualmente quando la condizione è verificata.

L’istruzione last_key_pressed = pressed_keys assegna lo stato di ogni verifica a un array last_key_pressed per facilitare il prossimo ciclo di verifica.

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

Questa funzione assegna un livello alto a ciascuna riga a turno e, quando viene premuto il tasto in una colonna, la colonna in cui si trova il tasto ottiene un livello alto. Dopo aver eseguito il loop a due livelli, il valore del tasto il cui stato è 1 viene memorizzato nell’array pressed_keys.

Se premi il tasto “3”:

_images/image187.png

rowPins[0] viene impostato su alto, e colPins[2] ottiene il livello alto.

colPins[0], colPins[1], colPins[3] ottengono livello basso.

Gli stati sono quattro: 0, 0, 1, 0; e scriviamo “3” in pressed_keys.

Quando rowPins[1], rowPins[2], rowPins[3] sono impostati su alto, colPins[0] ~ colPins[4] ottengono livello basso.

Il ciclo si interrompe e viene restituito pressed_keys = “3”.

Se premi i tasti “1” e “3”, verrà restituito pressed_keys = [“1”,”3”].

Immagine del Fenomeno

_images/image188.jpeg