Schema e Codici per Realizzare una Comunicazione tra Microcontrollori con Protocollo One Wire…
INTRO
Nel seguente articolo viene presentato lo schema e i codici necessari per programmare un microcontrollore che funge da trasmettitore e uno che funge da ricevitore per avviare una comunicazione One Wire. Questo tipo di comunicazione è molto efficace nel caso si vuole un numero ridotto di conduttori, infatti ne bastano solo due, uno per il segnale e uno per la massa se si trasmette in tensione oppure uno per l’andata e una per il ritorno della corrente nel caso di trasmissione in corrente 4-20mA.
Lo schema come esempio di trasmissione utilizza 4 interruttori e trasmette il loro indirizzo, il ricevitore riceve un codice per ogni interruttore e accende o spegne due LED. La trasmissione One wire può arrivare fino a 20 metri utilizzando solo gli ingressi e uscite dei microcontrollori, mentre con un trasmettitore e ricevitore in corrente con standard 4-20mA può arrivare fino a 20Km.
CODICE
clicca qui per la guida alla scrittura dell’articolo!!!
Il codice del trasmettitore è il seguente:
#define B1 PORTB.F0 //Definizione dei pulsanti
#define B2 PORTB.F1
#define B3 PORTB.F2
#define B4 PORTB.F3
#define TX PORTB.F7 //Definizione uscita di comunicazione
void send_preamble_and_sync(){ //Sottoprogramma Invia 16 bit sincr
unsigned char tx = 0;
for(tx = 0; tx < 15; tx++){ //Invia i primi 15 bit con periodo 600us
delay_us(300);
TX = 1;
delay_us(300);
TX = 0;
}
delay_us(170); //Ultimo bit di sincronizzazione
TX = 1; //Con periodo 230us (170us 0, 80us 1)
delay_us(80);
TX = 0;
delay_us(100);
}
void data_TX(unsigned char value){ //Sottoprogramma invio dati
unsigned char s = 0;
send_preamble_and_sync(); //Invia la sincronizzazione
for(s = 0; s < 8; s++){ //Ripeti 8 volte (invia un byte)
delay_us(20);
TX = 1; //Tx a livello alto
if((value & 0x80) != 0){ //Se il bit da inviare = 1 TX = 1 per 50us
delay_us(50);
}
delay_us(100); //Se invece bit = 0 100us
TX = 0;
value <<= 1; //Scorri il vettore di byte
}
}
void main(){ //Programma principale
TRISB = 0b00001111; //Configura pulsanti come input e Tx come uscita
while(1){ //Ciclo infinito
if(B1==1){ //Se premo B1
while(B1==1); //Aspetta che B1 venga rilasciato
data_TX(10); //Invia il codice 00001010
}
if(B2==1){ //Uguale a sopra con codice e tasto diversi
while(B2==1);
data_TX(20);
}
if(B3==1){ //Se premo B1
while(B1==1); //Aspetta che B1 venga rilasciato
data_TX(30); //Invia il codice 00001010
}
if(B4==1){ //Uguale a sopra con codice e tasto diversi
while(B2==1);
data_TX(40);
}
}
}
Prima di tutto si vanno a definire le connessioni dei pulsanti con il microcontrollore, e poi si va a scrivere il primo sottoprogramma, ovvero quello per inviare il preamble. Il reamble (preambolo) è un segnale che comunica l’inizio della comunicazione. Vengono inviati 15 periodi da 600uS ad onda quadra con duty cycle 50% e infine si invia un unico periodo con durata alta di 80uS e basso di 100uS.
Il secondo sottoprogramma è quello per inviare i dati; si invia il preamble richiamando il sottoprogramma visto prima, poi si invia il dato utilizzando un periodo di 50uS per un bit alto e 100uS per un bit basso, quindi si usa una modulazione di tempo, distinguendo i bit in base alla durata del periodo alto del segnale inviato mentre il segnale basso è sempre 20uS.
Nel programma principale si inizializzano ingressi e uscite e poi si vanno a controllare i pulsanti. Per ogni pulsante si invia un numero, primo pulsante 10, poi 20, poi 30 e alla fine per l’ultimo pulsante 40.
Il ricevitore riceve il numero associato al pulsante e in base a quale pulsante viene premuto accende o spegne un LED; primo pulsante accende LED1 e il secondo pulsante lo spegne, terzo pulsante accende LED2 e il quarto lo spegne. Il codice del ricevitore è:
#define Load1 PORTB.F0 //Connessione carico
#define Load2 PORTB.F1
#define RX PORTB.F7 //Connessione RX
unsigned char val;
unsigned char data_RX(){ //Sottoprogramma ricevitore
unsigned char dato, period, bits; //Inizializzazione variabili
dato=0;
if(RX){ //Se Rx=1
while(period > 50){ //Se il periodo è >50 rimani nel ciclo
while(!RX){ //Se RX=0 azzera la variabile
Period = 0;
}
while(RX){ //Altrimenti incrementala
period++; //Incrementa la variabile
}
}
bits = 8;
dato = 0;
while(bits){ //Finchè bits non è 0
while(!RX){ //Conta il periodo
Period = 0;
}
while(RX){
period++;
}
if(period >= 50) break; //Se il periodo è 50 esci dalla routine
if(period < 25) dato |= 0; //Se il periodo è minore di 25 allora ricevo 0
else dato |= 1; //Altrimenti ho ricevuto un 1
dato <<= 1; //shifto il vettore
bits--; //Decremento la variabile bits
}
dato = dato >> 1;
} //Ritorno il dato
return (dato);
}
void main(){
TRISB = 0b10000000; //Configura RX input e altri uscite
while(1){ //ciclo infinito
val = data_RX(); //Leggi valore ricevuto
if(val == 10){ //Se ricevo (10) accendi il carico 1
Load1 = 1; //Accendi carico 1
delay_ms(100);
}
if(val == 20){ //Se ricevo (20) Spegni carico 1
Load1 = 0; //Spegni carico 1
delay_ms(100);
}
if(val == 30){ //Se ricevo (10) accendi il carico 1
Load2 = 1; //Accendi carico 1
delay_ms(100);
}
if(val == 40){ //Se ricevo (20) Spegni carico 1
Load2 = 0; //Spegni carico 1
delay_ms(100);
}
}
}
Prima vengono inizializzati i LED e l’ingresso dell’RX, poi una variabile che verrà usata successivamente. Il primo sottoprogramma è necessario per la ricezione dei dati. Nel programma per la ricezione si va a misurare il tempo del segnale alto ricevuto e se il conteggio che avviene durante il periodo alto è maggiore di 50 vuol dire che il preample è finito. Se il preamble è finito allora, finché la variabile bit non è 0, allora viene misurato per 8 volte il periodo alto del segnale e se il conteggio è minore di 25 vuol dire che è un 1 logico, se invece maggiore di 50 è uno 0 logico. I valori di 0 e 1 vengono inseriti in un vettore.
Nel programma principale si inizializzano ingressi e uscite e poi nel ciclo infinito si va a leggere il dato ricevuto e si controllano i LED in base ad esso.
La frequenza è per entrambi a 4MHz e i fuses sono così configurati:
SCHEMA
Lo schema del trasmettitore è il seguente:
La tensione di ingresso è a 5V continui, e il microcontrollore viene alimentato con la tensione positiva al pin 20 e quella negativa ai pin 19 e 8. Il circuito di oscillazione è composto da un quarzo a 4MHz e due condensatori da 22pF.
I 4 pulsanti sono connessi alle PORTB e vi sono 4 resistori di pull-down. R3 serve per mantenere in funzione il microcontrollore e il segnale di uscita viene trasmesso dal pin RB7. Bisogna inviare al ricevitore due fili, il prima con il segnale e il secondo con la massa del circuito.
Lo schema del ricevitore è:
Alimentazione e circuito risonante sono uguali come nel caso precedente.
I LED sono connessi all’uscita PB0 e PB1 mentre il segnale ricevuto giunge all’ingresso PB7.
Lo schema montato su breadboard ha il seguente aspetto:
DOWNLOAD
Potete scaricare la simulazione del circuito con PROTEUS e il codice scritto con MIKROC al seguente LINK!!!