È possibile avere più di 14 pin di uscita su Arduino, sto lavorando a un progetto in cui ho bisogno di accendere diversi LED singolarmente. Ho solo un Arduino Uno e non voglio ottenere un Mega.
È possibile avere più di 14 pin di uscita su Arduino, sto lavorando a un progetto in cui ho bisogno di accendere diversi LED singolarmente. Ho solo un Arduino Uno e non voglio ottenere un Mega.
Risposte:
Un modo comune per espandere il set di pin di uscita disponibili su Arduino è utilizzare i registri a scorrimento come l'IC 74HC595 ( collegamento alla scheda tecnica ).
Sono necessari 3 pin per controllare questi chip:
In un programma, si passano i dati un bit alla volta al registro a scorrimento usando il comando shiftOut () , in questo modo:
shiftOut(dataPin, clockPin, data);
Con quel comando, imposti ciascuna delle 8 uscite sull'IC 595 con gli 8 bit nella data
variabile.
Con un 595, ottieni 5 pin (8 sull'IC, ma ne spendi 3 per parlare con esso). Per ottenere più output, è possibile collegare in serie una serie di 595 insieme, collegando il pin di uscita seriale al pin di dati di quello successivo. È inoltre necessario collegare insieme i pin di clock e di aggancio di tutti i 595 circuiti integrati.
Il circuito risultante (usando un 595) sarebbe simile al seguente:
La figura sopra è stata presa da questa pagina web codeproject.com :
Il perno di chiusura viene utilizzato per mantenere costanti le uscite del 595 mentre si spostano i dati al suo interno, in questo modo:
digitalWrite(latchPin, LOW);
shiftOut(dataPin, clockPin, data);
digitalWrite(latchPin, HIGH);
Esistono due modi per ottenere più pin da un arduino.
Il primo modo è usare i pin analogici come pin di uscita digitali, il che è davvero facile da fare. Tutto quello che devi fare è fare riferimento a A0-A5 come pin 14,15,16,17,18,19. Ad esempio per scrivere in alto sul pin A0 basta usare digitalWrite (14, HIGH).
L'altro modo per ottenere più pin da Arduino è utilizzare un registro a scorrimento. Per fare ciò ti consiglio di usare EZ-Expander Shield , che ti consente di usare digitalWrite ([20-35], HIGH) quando importi la libreria EZ-Expander. Questo schermo consente tuttavia solo ai pin di essere utilizzati solo come uscite e utilizza i pin 8,12 e 13 per controllare i registri di spostamento.
La cosa bella è che puoi usare entrambi i due metodi sopra, senza problemi.
A0
- A5
identificatori direttamente invece di usare i numeri 14-19. Ad esempio digitalWrite(A0, HIGH)
,.
digitalWrite(A0)
è più corretto rispetto a digitalWrite(14)
quando il primo mapperà sempre il pin fisico (analogico) corretto. Su una scheda diversa, pin 14
infatti , potrebbe non esserlo A0
, ad esempio pin 14
il MEGA è Serial3 TX
e non influenzerà il pin analogico che stai cercando . cioè, se si usa digitalWrite
su un pin analogico, usare il riferimento A0
- A5
.
Se si desidera pilotare i LED, è possibile utilizzare anche un MAX7219 in grado di pilotare 64 LED, senza circuiti aggiuntivi (non è necessario un transistor per amplificare il segnale).
La guida di un MAX7219 richiede solo 3 pin di uscita su Arduino. Inoltre, puoi trovare alcune librerie di Arduino per questo.
Puoi anche incatenarne alcuni se devi alimentare più di 64 LED.
L'ho usato con successo per più display a LED a 7 segmenti.
Unico inconveniente: è costoso (circa $ 10).
È possibile utilizzare Charlieplexing . Con questa tecnica puoi guidare direttamente i n*(n-1)
LED da n pin. Quindi con 3 pin puoi guidare 6 LED, 4 pin - 12 LED, 5 pin - 20 LED e così via.
Esempio:
Sei LED su 3 pin
PINS LEDS
0 1 2 1 2 3 4 5 6
0 0 0 0 0 0 0 0 0
0 1 Z 1 0 0 0 0 0
1 0 Z 0 1 0 0 0 0
Z 0 1 0 0 1 0 0 0
Z 1 0 0 0 0 1 0 0
0 Z 1 0 0 0 0 1 0
1 Z 0 0 0 0 0 0 1
0 0 1 0 0 1 0 1 0
0 1 0 1 0 0 1 0 0
0 1 1 1 0 0 0 1 0
1 0 0 0 1 0 0 0 1
1 0 1 0 1 1 0 0 0
1 1 0 0 0 0 1 0 1
1 1 1 0 0 0 0 0 0
Puoi vedere un tutorial migliore qui .
È possibile utilizzare il protocollo I 2 C (libreria Wire) per connettersi ad altri dispositivi come gli espansori di porte. Ad esempio, MCP23017.
Ho usato uno di quei chip per collegarmi a una scheda LCD. MCP23017 ha 16 porte, che possono essere configurate come ingressi o uscite. Se lo si desidera, come input possono generare interrupt.
Esempio di collegamento di 13 di questi 16 al display LCD:
Ora ci colleghiamo ad Arduino usando solo 2 fili (SDA / SCL) più alimentazione e terra:
Alcuni produttori di terze parti hanno realizzato schede con 4 x MCP23017, che offrono 64 ingressi / uscite:
È possibile utilizzare multiplexer analogici come il 74HC4051 (8 porte) o il 74HC4067 (16 porte) per collegare un pin a una delle porte 8/16 (ma solo una alla volta), in questo modo:
Questi sono bidirezionali, quindi possono essere utilizzati come espansori di input o output.
Utilizzando SPI è possibile inviare dati seriali veloci a un registro a scorrimento, come il 74HC595. Questi possono essere concatenati insieme. In questo esempio sto controllando 32 LED con solo 3 pin I / O (MOSI / MISO / SCK) più alimentazione e terra.
Ho scoperto all'interno di un cartello LED commerciale che i 72 LED erano pilotati da chip 74HC595.
Aveva 9 chip che guidavano le colonne (9 x 8 = 72 LED) e un chip che guidava le file, in una configurazione multiplata.
Se vuoi solo guidare i LED, di solito puoi multiplexarli. Il MAX7219 lo semplifica progettando per pilotare matrici LED, ad esempio display a 7 segmenti:
O matrici a 64 LED:
In entrambi i casi questi possono essere collegati in cascata insieme, ad esempio:
Tutti questi esempi usano solo 3 pin dell'Arduino (MOSI / MISO / SCK) più potenza e terra.
L'espansore di porte a 16 porte menzionato in precedenza (MCP23017) è disponibile anche in una variante SPI (MCP23S17), che fa praticamente cose identiche. Usa un altro filo, ma sarebbe più veloce.
Le strisce LED (come quelle NeoPixel) hanno i loro protocolli. C'è stato un post su Youtube di Josh Levine in cui l'autore ha guidato oltre 1000 pixel con un Duemilanove!
I registri a turni sono stati citati in altre risposte e sono sicuramente una scelta eccellente per molti progetti. Sono economici, semplici, moderatamente veloci e in genere possono essere concatenati per aggiungere più output. Tuttavia, hanno il rovescio della medaglia che di solito hanno bisogno dell'uso esclusivo di diversi pin (tra 2 e 4, a seconda di come li configuri).
Un'alternativa consiste nell'utilizzare espansori di porte più avanzati, come MCP23017 a 16 bit e MCP23S17 . Questi supportano rispettivamente I2C e SPI, il che significa che è possibile posizionarli su un bus con molti altri dispositivi (potenzialmente di diverso tipo). Ogni dispositivo sul bus può essere indirizzato individualmente, il che significa che sono necessari solo 2 o 3 pin per comunicare con tutti. Le velocità di aggiornamento sono in genere estremamente elevate, quindi è improbabile che si verifichi una latenza significativa (ad esempio ritardi di trasmissione) in un progetto Arduino.
A basso livello, l'utilizzo di I2C o SPI è sostanzialmente più complicato di un semplice registro a scorrimento. Tuttavia, esiste un codice di libreria per Arduino che se ne occupa. Vedi questa domanda, ad esempio: Come posso usare i dispositivi I2C con Arduino?
Oltre alla risposta di Ricardo , ciò che Wikipedia afferma sui registri a turni :
Uno degli usi più comuni di un registro a scorrimento è la conversione tra interfacce seriali e parallele. [...] I registri SIPO sono comunemente collegati all'uscita dei microprocessori quando sono necessari più pin di ingresso / uscita per scopi generici di quelli disponibili. Ciò consente a più dispositivi binari di essere controllati utilizzando solo due o tre pin, ma più lenti degli I / O paralleli.
Nel articolo Ricardo legato è possibile vedere lo schema del registro a scorrimento.
Quello che succede qui è che metti i dati degli 8 pin in una sequenza e per ogni tick di clock il registro a scorrimento si sposterà (sposta i dati binari da ciascun latch a quello successivo) fino a quando "crea un cerchio", ovvero il primo bit arriva all'ultimo perno. I registri a scorrimento hanno anche un input in cui è possibile attivare / disattivare lo spostamento in modo che lo stato possa essere mantenuto dopo che i dati sono stati spostati nella posizione. Per una semplice dimostrazione vedere la seguente animazione.
Qui la luce rossa è l'ingresso seriale e quelle verdi mostrano lo stato dei fermi in questo registro a scorrimento SIPO semplificato . Dopo che i dati sono stati spostati in posizione, è possibile disattivare lo spostamento e leggere i pin. In questo esempio mi sono spostato 10101011
.
Da questi esempi puoi capire che il trasferimento seriale sarà più lento del parallelo, perché devi aspettare che il registro a scorrimento sposta i bit al loro posto. Dovrai attendere la stessa quantità di tick di clock di quanti bit vuoi caricare. Questo è uno dei tanti motivi per cui non puoi incatenarli indefinitamente, perché il caricamento richiederebbe per sempre.
Come hai già scritto, puoi usare tutti i pin, inclusi TX e RX come output digitale. L'ho fatto qualche tempo fa per un dimostratore e ho registrato un video - 20 LED su 20 pin - di questo progetto piuttosto insensato.
Come descritto da Peter R. Bloomfield qui , devi disconnettere TX e RX per il caricamento. Inoltre, hai esaurito i pin per leggere i sensori per una possibile interattività e devi assicurarti che il limite di corrente totale non sia raggiunto. Non dimenticare che sei limitato a led 5V se li guidi direttamente con il tuo Arduino.
L'uso dei registri a scorrimento in generale e del 595, descritto da Ricardo, è quindi altamente raccomandato.
Li ho usati poco fa quando ho realizzato la parte di saldatura e programmazione di Kawaii me (il testo del link è in tedesco) dell'artista di upcycling Dominik Jais .
Qui, solo un gruppo di 595 sono stati usati per guidare un display di 8x11 led. Poiché i led erano tagliati da una striscia di led SMD 12V , erano necessari un alimentatore aggiuntivo e alcuni array Darlington UDN2803A , agganciati ai pin di uscita dei registri a scorrimento.
Altri metodi generali includono l'uso degli espansori di porte a 8 bit PCF8574 (A), che sono controllati tramite il bus I2C.
Ad ogni modo, proverei prima i 595 registri a turni.
Se devi controllare un paio di led RGB, tuttavia, potresti voler cercare soluzioni più specializzate. Alcuni LED RGB vengono forniti con il proprio WS2812 . Questi pezzi sottili possono essere collegati in cascata (bus a 1 filo) e indirizzati attraverso la loro posizione nella catena.
Se si tratta solo di LED, che dire delle strisce LED WS2812B o dei chip stessi del driver? Puoi controllare un numero praticamente illimitato di LED usando un solo pin!
Sebbene le persone siano abituate a queste in strisce, sono disponibili come LED autonomi (noti come neo pixel su Adafruit). O se stai guidando solo un singolo colore, ogni chip WS2811 potrebbe controllare 3 LED utilizzando ciascuna delle uscite RGB per un singolo LED ciascuna.
Di recente ho appena creato un progetto che utilizza 5 LED di questo tipo: Door1 aperto / chiuso, Door2 aperto / chiuso, motor1 attivo, motor2 attivo e potenza. I LED "attivi" hanno un duplice scopo poiché ho il rosso come input dal motore attivo e il verde è la bandiera attiva all'interno dell'Arduino.
Il punto è che, con 1 pin e la libreria installata, è possibile controllare qualsiasi numero di LED
Non rivendico questo metodo per me, ma ho trovato questo trucco sulla pagina MUX-DEMUX: CD4051 Parlor Tricks
Qualunque sia il metodo che scegli di utilizzare per pilotare le uscite o leggere gli ingressi (registri a scorrimento, multiplexor o l'uso diretto diretto dei pin Arduino stessi) puoi raddoppiare il numero di uscite o ingressi mediante un uso intelligente di coppie di circuiti paralleli (per formare un doppio input o output bank ), impiegando diodi in sensi opposti su ciascun ramo parallelo e commutando gli ingressi / uscite su alto e basso.
Per illustrare il metodo per le uscite (i LED in questo caso, notare che i diodi extra non sono richiesti):
Se si considera la coppia di LED in questo esempio un "banco" e si desidera accendere LED_0, è necessario impostare il PIN 17 su ALTO e il PIN 18 su BASSO. (I numeri dei pin sono confusi, ma corrispondono all'esempio successivo così nudo con me). Per accendere LED_1, basta invertire i PIN. La natura del diodo dei LED impedisce alla corrente di fluire nella direzione opposta mantenendo l'altro spento.
Per illustrare il metodo per gli input (CdS in questo caso, notare che sono richiesti i diodi extra):
Questo diventa un po 'più complicato se vuoi fare una lettura analogica su un sensore di luce CdS. Innanzitutto, è necessario aggiungere un diodo a ciascun sensore per controllare il flusso. In secondo luogo, poiché stai leggendo i valori, devi tirare gli input in alto o in basso per evitare che fluttuino. Essendo una persona pigra, ho intenzione di tirarli su usando le resistenze pull-up interne. Per leggere CdS_0, impostare la modalità PIN 17 su OUTPUT e impostarla su LOW. Questo lo rende il terreno. Quindi si imposta la modalità PIN 18 su INPUT e si imposta su HIGH per attivare la resistenza di pull-up. Ora sei pronto per leggere il PIN 18 (noto anche come pin analogico 4). Per accedere all'altro sensore, basta cambiare modalità e uscite.
Quindi, se si dispone di un multiplexor a 8 porte CD4051, utilizzando 5 pin su Arduino (anziché i soliti 3), è possibile ottenere 16 ingressi o uscite o un mix dei due.
Allo stesso modo, se si dispone di un multiplexor 4067 a 16 porte, è possibile ottenere 32 ingressi o uscite o un mix dei due.
Uno schizzo di esempio sarebbe:
/*
* Example of getting 16 i/o from 5 pins using a CD4051
*
* Based on tutorial and code by david c. and tomek n.* for k3 / malmö högskola
* http://www.arduino.cc/playground/Learning/4051?action=sourceblock&ref=1
*/
int selPin[] = { 14, 15, 16 }; // select pins on 4051 (analog A0, A1, A2)
int commonPin[] = { 17, 18}; // common in/out pins (analog A3, A4)
int led[] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW }; // stores eight LED states
int CdSVal[] = { 0, 0, 0, 0 }; // store last CdS readings
int cnt = 0; // main loop counter
int persistDelay = 100; // LED ontime in microseconds
void setup(){
Serial.begin(9600); // serial comms for troubleshooting (always)
for(int pin = 0; pin < 3; pin++){ // setup select pins
pinMode(selPin[pin], OUTPUT);
}
}
void loop(){
flashLEDs();
if (cnt == 0){
for(int x; x < 8; x++){
led[x] = random(2);
}
}
cnt++;
if (cnt > 100) { cnt = 0; }
}
void flashLEDs() {
for(int pin = 0; pin < 2; pin++) { // set common pins low
pinMode(commonPin[pin], OUTPUT);
digitalWrite(commonPin[pin], LOW);
}
for (int bank = 0; bank < 4; bank++) {
for(int pin = 0; pin < 3; pin++) { // parse out select pin bits
int signal = (bank >> pin) & 1; // shift & bitwise compare
digitalWrite(selPin[pin], signal);
}
if (led[bank * 2]){ // first LED
digitalWrite(commonPin[0], HIGH); // turn common on
delayMicroseconds(persistDelay); // leave led lit
digitalWrite(commonPin[0], LOW); // turn common off
}
if (led[bank * 2 + 1]){ // repeat for second LED
digitalWrite(commonPin[1], HIGH);
delayMicroseconds(persistDelay);
digitalWrite(commonPin[1], LOW);
}
}
}
Come ho detto nella prima riga, la spiegazione completa può essere trovata su MUX-DEMUX: CD4051 Parlor Tricks
Per un progetto di classe ho usato un CD4024 e due pin Arduino per guidare un display a 7 segmenti.
Ci sono alcuni avvertimenti su questo approccio. Ad esempio, per scrivere un high
valore sulla prima uscita di un contatore di ripple è necessario solo a reset
e attivare due volte il pin del clock. Ma se si desidera scrivere high
a tutti i pin n richiede portando l'orologio pin 2 n volte, e durante quel tempo tutti gli altri pin sono costantemente commutazione on e off.
Se la tua applicazione è in grado di gestire queste limitazioni e sei a corto di pin, è un'altra opzione.
Risposta bonus: ci sono molti esempi di input multiplexing qui , molti dei quali si applicano anche agli output multiplexing.
Con un po 'di lavoro (installazione di un bootloader diverso) sono disponibili altre sette linee I / O su Uno, sulle intestazioni ICSP1 e JP2. Il bootloader sostitutivo si chiama HoodLoader2 . Ti consente di installare schizzi sia su Atmega328 che su Atmega16U2 su Uno. Trattare con più processori sarebbe la principale complicazione dall'uso di questo metodo.
Su uno Uno, le intestazioni ICSP1 e JP2 si collegano ai pin PB1 ... PB7 dell'Atmega16U2. Inoltre, l'Atmega16U2 ha circa 9 pin I / O senza connessione al circuito. Una persona che lavora al microscopio potrebbe essere in grado di collegare i cavi a un totale di 18 pin I / O sulla 16U2, lasciando altri tre pin I / O collegati alle loro connessioni ordinarie.
HoodLoader2 funziona anche su schede Mega.