Sommario:

Monitor di temperatura e livello di luce con visualizzazione su LCD NOKIA 5110: 4 passaggi
Monitor di temperatura e livello di luce con visualizzazione su LCD NOKIA 5110: 4 passaggi

Video: Monitor di temperatura e livello di luce con visualizzazione su LCD NOKIA 5110: 4 passaggi

Video: Monitor di temperatura e livello di luce con visualizzazione su LCD NOKIA 5110: 4 passaggi
Video: Arduino - Display LCD 2024, Novembre
Anonim
Image
Image

Ciao a tutti!

In questa sezione realizziamo un semplice dispositivo elettronico per monitorare la temperatura e il livello di luce. Le misurazioni di questi parametri vengono visualizzate sul display LCD NOKIA 5110. Il dispositivo è basato sul microcontrollore AVR ATMEGA328P. Il dispositivo di monitoraggio è dotato di termometro digitale DS18B20 e fotoresistenza per misurare il livello di luce.

Fase 1: Descrizione Componenti

Descrizione Componenti
Descrizione Componenti
Descrizione Componenti
Descrizione Componenti

Componenti di base del dispositivo di monitoraggio:

  • Microcontrollore AVR «ATMEGA328P»
  • LCD grafico monocromatico «NOKIA 5110»
  • Termometro digitale a 1 filo con risoluzione programmabile «DS18B20»
  • Resistenza dipendente dalla luce
  • fili

Microcontrollore AVR «ATMEGA328P»

Il dispositivo di monitoraggio utilizza le seguenti funzionalità periferiche del microcontrollore:

  1. Interruzione timer/contatore a 16 bit
  2. ADC a 8 canali a 10 bit
  3. Interfaccia seriale SPI master/slave

LCD grafico monocromatico «NOKIA 5110»

Specifiche:

  1. Display LCD a 48 x 84 punti
  2. Interfaccia bus seriale con massima velocità 4 Mbit/S
  3. Controller/Driver interno «PCD8544»
  4. Retroilluminazione a LED
  5. Funziona a tensione 2,7-5 Volt
  6. Basso consumo energetico; è adatto per applicazioni a batteria
  7. Intervallo di temperatura da -25˚C a +70˚C
  8. Supporta l'ingresso CMOS del segnale

Gestione dell'indirizzo LCD (indirizzamento):

La disposizione degli indirizzi della memoria mostrata sul display LCD (DDRAM) è Matrix che consiste di 6 righe (indirizzo Y) da indirizzo Y 0 a indirizzo Y 5 e 84 colonne (indirizzo X) da indirizzo X 0 a X- Indirizzo 83. Se l'utente vuole accedere alla posizione di visualizzazione del risultato sul Display LCD, deve fare riferimento alla relazione tra X-Address e Y-Address.

I dati che verranno inviati al display sono di 8 bit (1 Byte) e saranno disposti come una linea verticale; in questo caso Bit MSB sarà inferiore e Bit LSB sarà superiore come mostrato in figura.

Termometro Digitale 1 Filo Risoluzione Programmabile DALLAS «DS18B20»

Caratteristiche:

  1. L'esclusiva interfaccia 1-Wire® richiede solo un pin della porta per la comunicazione
  2. Riduci il numero di componenti con il sensore di temperatura integrato e l'EEPROM
  3. Misura temperature da -55°C a +125°C (-67°F a +257°F)
  4. ±0,5°C Precisione da -10°C a +85°C
  5. Risoluzione programmabile da 9 bit a 12 bit
  6. Nessun componente esterno richiesto
  7. La modalità di alimentazione parassita richiede solo 2 pin per il funzionamento (DQ e GND)
  8. Semplifica le applicazioni di rilevamento della temperatura distribuite con capacità multidrop
  9. Ogni dispositivo ha un codice seriale univoco a 64 bit memorizzato nella ROM integrata
  10. Impostazioni di allarme non volatile (NV) flessibili definibili dall'utente con comando di ricerca allarme Identifica i dispositivi con temperature al di fuori dei limiti programmati

Applicazioni:

  1. Controlli termostatici
  2. Sistemi industriali
  3. Prodotti di consumo
  4. Termometri
  5. Sistemi termicamente sensibili

Resistenza dipendente dalla luce

Il resistore dipendente dalla luce (LDR) è un trasduttore che cambia la sua resistenza quando la luce cade sulla sua superficie cambia.

Tipicamente un LDR avrà da un megaOhm a due megaOhm al buio totale, da dieci a venti kiloOhm a dieci LUX, da due a cinque kiloohm a 100 LUX. La resistenza tra i due contatti del sensore diminuisce con l'intensità della luce o la conduttanza tra due contatti del sensore aumenta.

Utilizzare il circuito divisore di tensione per convertire la variazione di resistenza in variazione di tensione.

Passaggio 2: codice firmware del microcontrollore

#ifndef F_CPU#define F_CPU 16000000UL // indica la frequenza del cristallo del controller (16 MHz AVR ATMega328P) #endif

// DEFINISCI L'INTERFACCIA SPI #define MOSI 3 // MOSI è PORT B, PIN 3 #define MISO 4 // MISO è PORT B, PIN 4 #define SCK 5 // SCK è PORT B, PIN 5 #define SS 2 // SS è PORTA B, PIN 2

// RESET IL DISPLAY #define RST 0 // RESET è PORT B, PIN 0

//SELEZIONE MODALITÀ DISPLAY - Ingresso per selezionare comando/indirizzo o input di dati. #define DC 1 // DC è PORT B, PIN 1

// array di codici di segno negativostatic const unsigned char neg[4] = {0x30, 0x30, 0x30, 0x30};

// code array di cifre [0..9] static const unsigned char font6x8[10][16] = { { 0xFC, 0xFE, 0xFE, 0x06, 0x06, 0xFE, 0xFE, 0xFC, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 0 { 0x00, 0x00, 0x18, 0x1C, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00}, // 1 { 0x0C, 0x8E, 0xCE, 0xE6, 0xE6, 0xBE, 0x9E, 0x0C, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 2 { 0x00, 0x04, 0x06, 0x26, 0x76, 0xFE, 0x8C, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 3 { 0x3C, 0x3E, 0x7C, 0x60, 0x60, 0xFC, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00 0x01, 0x03, 0x01}, // 4 { 0x1C, 0x3E, 0x3E, 0x36, 0x36, 0xF6, 0xF6, 0xE4, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 5 { 0xFC, 0xFE, 0xFE, 0x36, 0x36, 0xF6, 0xF6, 0xE4, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01}, // 6 { 0x04, 0x06, 0x06, 0x86, 0xE6, 0xFE, 0x1C, 0x7E, 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00}, // 7 { 0xCC, 0xFE, 0xFE, 0x36, 0x36, 0xFE, 0xFE, 0xCC, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x0 3, 0x01}, // 8 { 0x3C, 0x7E, 0x7E, 0x66, 0x66, 0xFE, 0xFE, 0xFC, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01} // 9 };

// array di codici della parola "TEMP:" static const unsigned char TEMP_1[165] = { 0x02, 0x06, 0x06, 0xFE, 0xFE, 0xFE, 0x06, 0x06, 0x02, 0x00, 0xFC, 0xFE, 0xFE, 0x26, 0x26, 0x24, 0x00, 0xFC, 0xFE, 0xFE, 0x1C, 0x38, 0x70, 0x38, 0x1C, 0xFE, 0xFE, 0xFC, 0x00, 0xFC, 0xFE, 0xFE, 0x66, 0x66, 0x7E, 0x7E, 0x3C, 0x8C, 0x8C 0x00, 0x00, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0 0x01, 0x03, 0x01, 0x00, 0x01, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x0C, 0x1E, 0x33, 0x33, 0x1E, 0x0C, 0x00, 0xF8, 0x9C, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x01, };

// array di codici della parola "LUX:" const unsigned char TEMP_2[60] = { 0xFC, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFE, 0xFC, 0x00, 0x00, 0xFC, 0xFE, 0xFC, 0x00, 0x04, 0x8E, 0xDE, 0xFC, 0xF8, 0xFC, 0xDE, 0x8E, 0x04, 0x00, 0x8C, 0x8C, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x03, 0x03, 0x01, 0x00, 0x01, 0x01 };

#includere

#include #include

// Port Initializationvoid Port_Init() { DDRB = (1<<MOSI)|(1<<SCK)|(1<<SS)|(1<<RST)|(1<<DC);// Imposta MOSI, SCK, SS, RST, DC come output, tutti gli altri input PORTB |= (1<<RST);// Imposta il pin RST come alto PORTB |= (1<<SS);// Imposta il pin SS come alto - Il display è Disabilita DDRC=0xFFu; // Imposta tutti i pin del PORTC come output. DDRC &= ~(1<<0);//Crea il primo pin di PORTC come Input PORTC=0x00u; // Imposta tutti i pin di PORTC bassi che lo disattivano. }

// Inizializzazione ADC void ADC_init() { // Abilita ADC, frequenza di campionamento=osc_freq/128 imposta il prescaler al valore massimo, 128 ADCSRA |= (1<<ADEN) | (1<<ADPS2)| (1<<ADPS1)| (1<<ADPS0); ADMUX = (1<<REFS0); // Seleziona il riferimento di tensione per l'ADC // Seleziona il canale zero per impostazione predefinita utilizzando il registro ADC Multiplexer Select (ADC0). }

// Funzione per leggere il risultato della conversione da analogico a digitale uint16_t get_LightLevel() { _delay_ms(10); // Attendi un po' che il canale venga selezionato ADCSRA |= (1<<ADSC); // Avvia la conversione ADC impostando il bit ADSC. scrivi 1 in ADSC while(ADCSRA & (1<<ADSC)); // attendi il completamento della conversione // ADSC diventa di nuovo 0 fino ad allora, esegui il ciclo continuamente _delay_ms(10); ritorno(ADC); // Restituisce il risultato a 10 bit }

// Inizializzazione SPI void SPI_Init() { SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);//Abilita SPI, Imposta come Master, Imposta Prescaler come Fosc/16 nel controllo SPI Registrati }

// inizializza Timer1 a 16 bit, interrupt e variabile void TIMER1_init() { // imposta timer con prescaler = 256 e modalità CTC TCCR1B |= (1 << WGM12)|(1 << CS12); // inizializza il contatore TCNT1 = 0; // inizializza il valore di confronto - 1 sec OCR1A = 62500; // abilita l'interruzione di confronto TIMSK1 |= (1 << OCIE1A); // abilita gli interrupt globali sei(); }

//Display Enable void SPI_SS_Enable() { PORTB &= ~(1<<SS); // Abilita il pin SS alla logica 0 }

//Disabilita visualizzazione void SPI_SS_Disable() { PORTB |= (1<<SS); // Disabilita il pin SS su logic 1 }

//Funzione per inviare dati nel buffer di visualizzazione void SPI_Tranceiver (dati char non firmati) { SPDR = data; //Carica i dati nel buffer while(!(SPSR & (1<<SPIF))); // Attendi fino al completamento della trasmissione }

// Reimposta il display all'inizio dell'inizializzazione void Display_Reset() { PORTB &= ~(1<<RST); _delay_ms(100); PORTAB |= (1<<RST); }

//Funzione di scrittura del comando void Display_Cmnd(unsigned char data) { PORTB &= ~(1<<DC); // imposta il pin DC sulla logica 0 per l'operazione di comando SPI_Tranceiver(data); // invia i dati sul registro dati PORTB |= (1<<DC); // imposta il pin DC in alto logico per il funzionamento dei dati }

//Inizializzazione di Display void Display_init() { Display_Reset(); // resetta il display Display_Cmnd(0x21); // set di comandi in modalità aggiunta Display_Cmnd(0xC0); // imposta la tensione inviando C0 significa VOP = 5V Display_Cmnd(0x07); // imposta la temperatura coefficiente a 3 Display_Cmnd(0x13); // imposta il valore di Voltage Bias System Display_Cmnd(0x20); // set di comandi in modalità base Display_Cmnd(0x0C); // visualizza il risultato in modalità normale }

// Cancella il Display void Display_Clear() { PORTB |= (1<<DC); // imposta il pin DC in alto logico per il funzionamento dei dati per (int k=0; k<=503; k++){SPI_Tranceiver(0x00);} PORTB &= ~(1<<DC); // imposta il pin DC in logica zero per operazione di comando }

// imposta la colonna e la riga nella posizione di visualizzazione del risultato sul display LCD void Display_SetXY(unsigned char x, unsigned char y) { Display_Cmnd(0x80|x); // colonna (0-83) Display_Cmnd(0x40|y); // riga (0-5) }

// Funzione per visualizzare il segno negativo void Display_Neg(unsigned char neg) { Display_SetXY(41, 0); // Imposta l'indirizzo della posizione sul display per (int index=0; index0) {SPDR = 0x30;} //Carica i dati nel buffer del display (visualizza segno negativo) else {SPDR = 0x00;} //Carica i dati in il buffer di visualizzazione (segno negativo chiaro) while(!(SPSR & (1<<SPIF))); //Attendi fino al completamento della trasmissione _delay_ms(100); } }

// Funzione per cancellare il segno digitale void Off_Dig(unsigned char x, unsigned char y) { Display_SetXY(x, y); // Imposta l'indirizzo della posizione sul display (riga superiore) for (int index=0; index<8; index++) {SPI_Tranceiver(0);} //Carica i dati nel buffer del display (cancella la parte superiore del segno digitale) y++; Display_SetXY(x, y);// Imposta l'indirizzo della posizione sul display (riga inferiore) for (int index=0; index<8; index++) {SPI_Tranceiver(0);}// Carica i dati nel buffer del display (parte inferiore chiara del segno digitale) }

// Funzione per visualizzare il segno digitale void Display_Dig(int dig, unsigned char x, unsigned char y) { Display_SetXY(x, y); // Imposta l'indirizzo della posizione sul display (riga superiore) for (int index=0; index <16; index++) { if (index==8){y++;Display_SetXY(x, y);} // Imposta l'indirizzo della posizione sul display (riga in basso) SPI_Tranceiver(font6x8[dig][index]); // Carica l'array di codici di dati di cifre nel buffer del display _delay_ms(10); } }

// Inizializzazione di DS18B20 unsigned char DS18B20_init() { DDRD |= (1 << 2); // Imposta il pin PD2 del PORTD come output PORTD &= ~(1 << 2); // Imposta il pin PD2 come basso _delay_us(490); // Tempo di inizializzazione DDRD &= ~(1 << 2); // Imposta il pin PD2 del PORTD come input _delay_us(68); // Temporizzazione OK_Flag = (PIND & (1 << 2)); // ottiene l'impulso del sensore _delay_us(422); ritorna OK_Flag; // ritorno 0-ok il sensore è collegato, 1-errore il sensore è scollegato }

// Funzione per leggere byte da DS18B20 unsigned char read_18b20() { unsigned char i, data = 0; for(i = 0; i < 8; i++) { DDRD |= (1 << 2); // Imposta il pin PD2 del PORTD come output _delay_us(2); // Timing DDRD &= ~(1 1; // Bit successivo if(PIND & (1 << 2)) data |= 0x80; // inserisce il bit nel byte _delay_us(62); } restituisce i dati; }

// Funzione per scrivere byte su DS18B20 void write_18b20(unsigned char data) { unsigned char i; for(i = 0; i < 8; i++) { DDRD |= (1 << 2); // Imposta il pin PD2 del PORTD come output _delay_us(2); // Temporizzazione if(data & 0x01) DDRD &= ~(1 << 2); //se vogliamo scrivere 1, rilasciamo la riga else DDRD |= (1 1; // Next bit _delay_us(62); // Timing DDRD &= ~(1 << 2); // Imposta il pin PD2 del PORTD come input _delay_us(2); } }

// Funzione per visualizzare il livello di luce void Read_Lux() { uint16_t buffer; unsigned int temp_int_1, temp_int_2, temp_int_3, temp_int_0; // cifre singole, doppie cifre, triple cifre, un quarto di cifre buffer = get_LightLevel(); // legge il risultato della conversione da analogico a digitale del livello di luce temp_int_0 = buffer % 10000 / 1000; // quarto di cifra temp_int_1 = buffer % 1000 / 100; // temp_int_2 a tre cifre = buffer % 100 / 10; // temp_int_3 a due cifre = buffer % 10; // una cifra if(temp_int_0 > 0) // se il risultato è un quarto di cifra { Display_Dig(temp_int_0, 32, 2); // visualizza 1 cifra del livello di luce Display_Dig(temp_int_1, 41, 2); // visualizza 2 cifre del livello di luce Display_Dig(temp_int_2, 50, 2); // visualizza 3 cifre del livello di luce Display_Dig(temp_int_3, 59, 2); // visualizza 4 cifre del livello di luce } else { if(temp_int_1 > 0) // se il risultato è un numero a tre cifre { Off_Dig(32, 2); // cancella 1 segno del numero Display_Dig(temp_int_1, 41, 2); // visualizza 1 cifra del livello di luce Display_Dig(temp_int_2, 50, 2); // visualizza 2 cifre del livello di luce Display_Dig(temp_int_3, 59, 2); // visualizza 3 cifre del livello di luce } else { if(temp_int_2 > 0) // se il risultato è un numero a due cifre { Off_Dig(32, 2); // cancella 1 segno del numero Off_Dig(41, 2); // cancella 2 segni del numero Display_Dig(temp_int_2, 50, 2); // visualizza 1 cifra del livello di luce Display_Dig(temp_int_3, 59, 2); // visualizza 2 cifre del livello di luce } else // se il risultato è un numero a una cifra { Off_Dig(32, 2); // cancella 1 segno del numero Off_Dig(41, 2); // cancella 2 segni del numero Off_Dig(50, 2); // cancella il 3 segno del numero Display_Dig(temp_int_3, 59, 2); // visualizza 1 cifra del livello di luce } } } }

// Funzione per visualizzare la temperatura void Read_Temp() { unsigned int buffer; unsigned int temp_int_1, temp_int_2, temp_int_3; // cifre singole, doppie cifre, triple cifre, quarti di cifra senza segno char Temp_H, Temp_L, OK_Flag, temp_flag; DS18B20_init(); // Inizializzazione di DS18B20 write_18b20(0xCC); // Controllo del codice del sensore write_18b20(0x44); // Avvia la conversione della temperatura _delay_ms(1000); // Ritardo interrogazione sensore DS18B20_init(); // Inizializzazione di DS18B20 write_18b20(0xCC); // Controllo del codice del sensore write_18b20(0xBE); // Comando per leggere il contenuto della RAM del sensore Temp_L = read_18b20(); // Legge i primi due byte Temp_H = read_18b20(); temp_flag = 1; // 1 temperatura positiva, temperatura 0 negativa // Ottieni temperatura negativa if(Temp_H &(1 << 3)) // Verifica bit con segno (se il bit è impostato - temperatura negativa) { sign int temp; temp_flag = 0; // flag è impostato 0 - temperatura negativa temp = (Temp_H <<8)|Temp_L; temperatura = -temp; // Converti il codice aggiuntivo in direct Temp_L = temp; Temp_H = temperatura>> 8; } buffer = ((Temp_H 4); temp_int_1 = buffer % 1000 / 100; // temp_int_2 a tre cifre = buffer % 100 / 10; // temp_int_3 a due cifre = buffer % 10; // a una cifra

// Se la temperatura è negativa, mostra il segno della temperatura, altrimenti cancella

if(temp_flag == 0) {Display_Neg(1);} else {Display_Neg(0);} if(temp_int_1 > 0) // if risultato è un numero a tre cifre { Display_Dig(temp_int_1, 45, 0); // visualizza 1 cifra della temperatura Display_Dig(temp_int_2, 54, 0); // visualizza 2 cifre della temperatura Display_Dig(temp_int_3, 63, 0); // visualizza 3 cifre della temperatura } else { if(temp_int_2 > 0) // se il risultato è un numero a due cifre { Off_Dig(45, 0); // cancella 1 segno del numero Display_Dig(temp_int_2, 54, 0); // visualizza 1 cifra della temperatura Display_Dig(temp_int_3, 63, 0); // visualizza 2 cifre della temperatura } else // se il risultato è un numero a una cifra { Off_Dig(45, 0); // cancella 1 segno del numero Off_Dig(54, 0); // cancella 2 segni del numero Display_Dig(temp_int_3, 63, 0); // visualizza 1 cifra di temperatura } } }

// Questo ISR viene attivato ogni volta che si verifica una corrispondenza del conteggio del timer con il valore di confronto (ogni secondo) ISR (TIMER1_COMPA_vect) { // Lettura, visualizzazione della temperatura e del livello di luce Read_Temp(); Read_Lux(); }

// Funzione per visualizzare le parole "TEMP" e "LUX" void Display_label() { // Parola "TEMP" Display_SetXY(0, 0); // Imposta l'indirizzo della posizione sul display (riga su) for (int index=0; index<105; index++) { if (index==40){Display_SetXY(0, 1);} // Imposta l'indirizzo della posizione on display (riga in basso) if (index==80){Display_SetXY(72, 0);} // Imposta l'indirizzo della posizione sul display (riga in alto) if (index==92){Display_SetXY(72, 1); } // Imposta l'indirizzo di posizione sul display (riga in basso) SPDR = TEMP_1[index]; // Carica i dati dell'array di codici nel buffer del display while(!(SPSR & (1<<SPIF))); // Attendi il completamento della trasmissione _delay_ms(10); } // Parola "LUX" Display_SetXY(0, 2); // Imposta l'indirizzo della posizione sul display (riga su) for (int index=0; index<60; index++) { if (index==30){Display_SetXY(0, 3);} // Imposta l'indirizzo della posizione sul display (riga in basso) SPDR = TEMP_2[indice]; // Carica i dati dell'array di codici nel buffer del display while(!(SPSR & (1<<SPIF))); // Attendi il completamento della trasmissione _delay_ms(10); } }

int main (vuoto)

{ Port_Init(); // Inizializzazione della porta ADC_init(); // Inizializzazione ADC SPI_Init(); // Inizializzazione SPI SPI_SS_Enable(); // Abilita visualizzazione DS18B20_init(); // Inizializzazione di DS18B20 Display_init(); // Inizializzazione display Display_Clear(); // Visualizza clear Display_label(); // Visualizza le parole "TEMP" e "LUX" TIMER1_init(); // Inizializzazione Timer1. Avvia il monitoraggio. Ottenere parametri ogni secondo. // Ciclo infinito mentre (1) { } }

Passaggio 3: aggiornamento del firmware sul microcontrollore

Caricamento del file HEX nella memoria flash del microcontrollore. Guarda il video con una descrizione dettagliata della masterizzazione della memoria flash del microcontrollore: Masterizzazione della memoria flash del microcontrollore…

Passaggio 4: assemblaggio del circuito del dispositivo di monitoraggio

Montaggio del circuito del dispositivo di monitoraggio
Montaggio del circuito del dispositivo di monitoraggio
Montaggio del circuito del dispositivo di monitoraggio
Montaggio del circuito del dispositivo di monitoraggio

Collegare i componenti secondo il diagramma schematico.

Collega l'alimentazione e funziona!

Consigliato: