Posts tagged Infrarossi

Trasmissioni a infrarossi – Parte due

0

Sono finalmente riuscito ad inviare un byte da un’Arduino ad un altro (in realtà una board UNO e un ATMega 328 su breadboard, come nell’articolo precedente).
Ho apportato qualche modifica per migliorare l’efficienza del programma ed evitare errori di comunicazione.

Essendo un semplice esempio per l’invio di 8 bit ho fatto in modo che tramite un dip switch posso andare a modificarli singolarmente.

Nel trasmettitore ho creato un byte che conterrà i bit da inviare e un secondo byte, dove sfrutterò solamente il bit 0, per utilizzarlo come bit di parità; ho aggiunto anche un pulsante che mi permetta di decidere quando inviare il byte.
In realtà vengono inviati 10 bit, 1 di attenzione, 8 per il “dato” e l’ultimo per la parità.

Anche nel ricevitore ho creato un byte che conterrà i bit ricevuto, un secondo byte per ricevere il bit di parità e un terzo byte per contenere il bit di parità calcolato sul ricevitore (avrei potuto utilizzare diversi bit di un solo byte per immagazzinare sia il bit di parità ricevuto che quello calcolato in locale, ma ho preferito creare due byte per non creare confusione).

Il bit di start, in realtà, non viene proprio ricevuto, piuttosto viene calcolato il tempo in cui il trasmettitore invia un valore logico alto per più di 95 ms (il bit di start si distingue dagli altri per la sua durata, poichè tutti gli altri bit vengono trasmessi per un tempo pari a 50 ms), sta qui una delle principali differenze fra questo nuovo progetto e quello vecchio: l’individuazione del bit di start.

 

Prima:

  temp1 = 0;
  temp2 = millis();
  while (digitalRead(in) == 0){
    temp1 = millis() - temp2;
  }

Dove “temp1″ era il tempo del bit di start.

Dopo:

  tempo = pulseIn(2, LOW)/1000;

Dove “tempo” è il tempo calcolato grazie a pulseIn():

  • 2: è il pin di riferimento
  • LOW: è il “valore”, questo significa che quando il pin 2 va “LOW” (valore logico basso) parte il timer che si fermerà non appena il pin 2 tornerà ad un livello logico alto.
  • /1000: Il risultato viene diviso per mille per convertire da microsecondi a millisecondi.

 

Sorgente trasmettitore:

/* Tramissione tramite infrarossi - www.xfox.it
 -----------------
 Trasmettitore  |
 ----------------- */
byte valore = B00000000; //Byte per l'invio
byte parity = B00000000; //Byte contenente il bit di parità

int out = 5; // Pin di uscita infrarossi
int freq[] = { //Arry contentenente le frequenze
  0, 38000};

//Pin per la selezione dei bit (dip switch)
int bit0 = 2;
int bit1 = 3;
int bit2 = 4;
int bit3 = 6;
int bit4 = 7;
int bit5 = 8;
int bit6 = 9;
int bit7 = 10;

//Pulsante di comando per l'invio
int button = 11;

void setup(){

  //Dichiaro i pin di ingresso e inserisco la resistenza di pullup (20Kohm)
  pinMode(bit0, INPUT);
  digitalWrite(bit0, HIGH);
  pinMode(bit1, INPUT);
  digitalWrite(bit1, HIGH);
  pinMode(bit2, INPUT);
  digitalWrite(bit2, HIGH);
  pinMode(bit3, INPUT);
  digitalWrite(bit3, HIGH);
  pinMode(bit4, INPUT);
  digitalWrite(bit4, HIGH);
  pinMode(bit5, INPUT);
  digitalWrite(bit5, HIGH);
  pinMode(bit6, INPUT);
  digitalWrite(bit6, HIGH);
  pinMode(bit7, INPUT);
  digitalWrite(bit7, HIGH);

  pinMode(out, OUTPUT);

  pinMode(button, INPUT);
  digitalWrite(button, HIGH);

  Serial.begin(9600);
}

void loop(){
  assegnabit();

  if (digitalRead(button) == 0){
    //Richiesta di attenzione
    tone(out, freq[1]);
    delay(100);
    noTone(out);
    delay(100);

    //Invio byte
    tone(out,freq[bitRead(valore,7)]);
    delay(50);
    noTone(out);

    tone(out,freq[bitRead(valore,6)]);
    delay(50);
    noTone(out);

    tone(out,freq[bitRead(valore,5)]);
    delay(50);
    noTone(out);

    tone(out,freq[bitRead(valore,4)]);
    delay(50);
    noTone(out);

    tone(out,freq[bitRead(valore,3)]);
    delay(50);
    noTone(out);

    tone(out,freq[bitRead(valore,2)]);
    delay(50);
    noTone(out);

    tone(out,freq[bitRead(valore,1)]);
    delay(50);
    noTone(out);

    tone(out,freq[bitRead(valore,0)]);
    delay(50);
    noTone(out);

    tone(out,freq[bitRead(parity, 0)]);
    delay(50);
    noTone(out);

    delay(100);
  }
}

void assegnabit(){
  //Controllo su bit0
  if(digitalRead(bit0) == 1){
    bitWrite(valore, 0, 1);
  }
  else if(digitalRead(bit0) == 0){
    bitWrite(valore, 0, 0);
  }

  //Controllo su bit1
  if(digitalRead(bit1) == 1){
    bitWrite(valore, 1, 1);
  }
  else if(digitalRead(bit1) == 0){
    bitWrite(valore, 1, 0);
  }

  //Controllo su bit2
  if(digitalRead(bit2) == 1){
    bitWrite(valore, 2, 1);
  }
  else if(digitalRead(bit2) == 0){
    bitWrite(valore, 2, 0);
  }

  //Controllo su bit3
  if(digitalRead(bit3) == 1){
    bitWrite(valore, 3, 1);
  }
  else if(digitalRead(bit3) == 0){
    bitWrite(valore, 3, 0);
  }

  //Controllo su bit4
  if(digitalRead(bit4) == 1){
    bitWrite(valore, 4, 1);
  }
  else if(digitalRead(bit4) == 0){
    bitWrite(valore, 4, 0);
  }

  //Controllo su bit5
  if(digitalRead(bit5) == 1){
    bitWrite(valore, 5, 1);
  }
  else if(digitalRead(bit5) == 0){
    bitWrite(valore, 5, 0);
  }

  //Controllo su bit6
  if(digitalRead(bit6) == 1){
    bitWrite(valore, 6, 1);
  }
  else if(digitalRead(bit6) == 0){
    bitWrite(valore, 6, 0);
  }

  //Controllo su bit7
  if(digitalRead(bit7) == 1){
    bitWrite(valore, 7, 1);
  }
  else if(digitalRead(bit7) == 0){
    bitWrite(valore, 7, 0);
  }

 //Assegnazione bit di parità
  bitWrite(parity, 0, (digitalRead(bit0) ^ digitalRead(bit1) ^ digitalRead(bit2) ^ digitalRead(bit3) ^ digitalRead(bit4) ^ digitalRead(bit5) ^ digitalRead(bit6) ^ digitalRead(bit7)));
}

 

Sorgente ricevitore:

/* Tramissione tramite infrarossi - www.xfox.it
 -----------------
 Ricevitore  |
 ----------------- */

byte valore = B00000000; //Byte ricevuto
byte parity = B00000000; //Byte contenente il bit di parità ricevuto
byte paritylocal = B00000000; //Byte contenente il bit di parità calcolato in locale

unsigned long tempo;

void setup(){
  Serial.begin(9600);
  pinMode(2, INPUT);

  Serial.println("Program Start!");
}

void loop(){
  parity = paritylocal = B00000000;

  tempo = pulseIn(2, LOW)/1000;
  if(tempo > 95){
    Serial.println("Valore > 95");
    delay(120);
    bitWrite(valore, 7, !digitalRead(2));
    delay(50);
    bitWrite(valore, 6, !digitalRead(2));
    delay(50);
    bitWrite(valore, 5, !digitalRead(2));
    delay(50);
    bitWrite(valore, 4, !digitalRead(2));
    delay(50);
    bitWrite(valore, 3, !digitalRead(2));
    delay(50);
    bitWrite(valore, 2, !digitalRead(2));
    delay(50);
    bitWrite(valore, 1, !digitalRead(2));
    delay(50);
    bitWrite(valore, 0, !digitalRead(2));
    delay(50);
    bitWrite(parity, 0, !digitalRead(2));

    scrivi();
  }
}

void scrivi(){
  Serial.print("\tRicevuto valore: ");
  Serial.print(bitRead(valore,7));
  Serial.print(bitRead(valore,6));
  Serial.print(bitRead(valore,5));
  Serial.print(bitRead(valore,4));
  Serial.print(bitRead(valore,3));
  Serial.print(bitRead(valore,2));
  Serial.print(bitRead(valore,1));
  Serial.print(bitRead(valore,0));

  //Calcolo la parità
  bitWrite(paritylocal, 0, (bitRead(valore, 0) ^ bitRead(valore, 1) ^ bitRead(valore, 2) ^ bitRead(valore, 3) ^ bitRead(valore, 4) ^ bitRead(valore, 5) ^ bitRead(valore, 6) ^ bitRead(valore, 7) ^ bitRead(parity, 0)));

  Serial.print("\t Parita': ");
  Serial.print(bitRead(parity,0), BIN);
  Serial.print("\t Parita' locale: ");
  Serial.println(bitRead(paritylocal, 0), BIN);

  if(bitRead(paritylocal, 0) == 0){
    Serial.println("Nessun errore!");
  }
  else if (bitRead(paritylocal, 0) == 1){
    Serial.println("Errore durante la comunicazione!");
  }
}

Una cosa da notare durante il calcolo della parità che potrebbe sfuggire è che nel trasmettitore la parità viene calcolata con gli 8 bit mentre nel ricevitore viene calcolata con gli 8 bit più il bit di parità ricevuto, se la parità locale sarà pari non vi è alcun errore nella comunicazione, al contrario, se la parità locale è dispari vuol dire che è avvenuto un errore durante la comunicazione.

 

Qualche approfondimento sul bit parità:

Il bit di parità è un codice di controllo utilizzato nei calcolatori per prevenire errori nella trasmissione o nella memorizzazione dei dati. Tale sistema prevede l’aggiunta di un bit ridondante ai dati, calcolato in modo tale che il numero di bit che valgono 1 sia sempre pari o dispari. I bit di parità sono uno dei codici di rilevazione e correzione d’errore più semplici.

Nel mio caso viene utilizzato il bit di parità pari, ovvero, i bit di valore 1 devono essere di numero pari.

 

Bit di parità secondo wikipedia: http://it.wikipedia.org/wiki/Bit_di_parit%C3%A0

 

Trasmissione di 2 bit tramite infrarossi

2

Come annunciato nell’articolo precedente, ho cominciato a lavorare con le comunicazioni a infrarossi. Ho realizzato un piccolo progettino che consente l’invio di due bit da un Arduino (stand alone su breadboard) ad un’altro Arduino (sulla board UNO) che riceve i dati e li visualizza al pc tramite il serial monitor.

Tramite due deviatori posso stabilire il valore dei due bit (0 – GND o 1 – VCC).

Il protocollo, se così si può definire, è rappresentato nella seguente figura:

Inizialmente il trasmettitore invia una richiesta di attenzione che dura 100 ms (invia una frequenza di 38KHz che viene rilevata dal ricevitore), il ricevitore controlla se effettivamente si tratta della richiesta di invio dati (se riceve un valore alto per più di 85ms si tratta della richiesta), successivamente il trasmettitore invia il primo bit per 50 ms, il ricevitore dopo aver atteso per 125 ms (si troverà esattamente a 25ms dall’inizio della trasmissione del primo bit) ne leggerà il valore immagazinandolo nella variabile “val1″, successivamente lo stesso avviene per il secondo bit.

Se entrambi i bit sono a “1″ il led nella scheda Arduino (al pin 13) si accenderà.

N.B.

Il ricevitore funziona con una logica negata, ovvero, quando legge una frequenza di 38KHz da in uscita un valore logico basso (0), viceversa quando non legge nulla da in uscita un valore logico alto (1).

Ecco il video della realizzazione:

 

Sorgente trasmettitore:

/* Test di trasmissioni a infrarossi tramite XP (Xfox's Protocol)
 Invio di 2 bit
 -----------------
 Trasmettitore |
 -----------------   */
int bit1 = 2;
int bit2 = 3;
int out = 5;

int val1 = 0;
int val2 = 0;

int freq[] = {
  0, 38000};

void setup(){
  pinMode(bit1, INPUT);
  pinMode(bit2, INPUT);
  pinMode(out, OUTPUT);
}

void loop(){
  val1 = digitalRead(bit1);
  val2 = digitalRead(bit2);
  //Inizio comunicazione, richiesta di attenzione da parte del ricevitore
  tone(out, freq[1]);
  delay(100);
  noTone(out);
  delay(100);

  tone(out,freq[val1]);
    delay(50);
  noTone(out);

  tone(out, freq[val2]);
    delay(50);
  noTone(out);
}

Sorgente ricevitore:

/* Test di trasmissioni a infrarossi tramite XP (Xfox's Protocol)
 Invio di 2 bit
 -----------------
 Ricevitore |
 -----------------   */

int in = 2;

int val1 = 0;
int val2 = 0;

long temp1 = 0;
long temp2 = 0;
long wait = 0;

void setup(){
  pinMode(in, INPUT);
  pinMode(13, OUTPUT);
  Serial.begin(9600);
}

void loop(){
  temp1 = 0;
  temp2 = millis();
  while (digitalRead(in) == 0){
    temp1 = millis() - temp2;
  }

  if (temp1 > 85){
    delay(125);
    val1 = !digitalRead(in);
    delay(50);
    val2 = !digitalRead(in);
  }

  if((val1 == 1) && (val2 == 1))
    digitalWrite(13, HIGH);
  else
    digitalWrite(13, LOW);

  scrivi();

}

void scrivi(){
  if(wait < millis()){
    wait = millis() + 100;
    Serial.print("Temp1: ");
    Serial.print(temp1);
    Serial.print("\tVal1 :");
    Serial.print(val1);
    Serial.print("\tVal2: ");
    Serial.println(val2);
  }
}

Il tutto è realizzato con due ricetrasmettitori ad infrarossi di un vecchio robot della DeAgostini (come detto nell’articolo precedente).

La cosa potrebbe farsi più interessante sfruttando questi componenti sia come trasmettitori che ricevitori, mentre nel mio progetto ho utilizzato ogni componente o come trasmettitore o come ricevitore. Adesso cercherò di creare un protocollo vero e proprio che mi permetta di inviare un byte alla volta in tempi più brevi.

Prossimo passo: sensore di distanza

0

Ultimamente mi sono dedicato all’Xfox’s Robot, ancora in versione di sperimentazione poichè non è in grado di eseguire operazioni autonomamente. Avevo pensato di aggiungere due foto-resistenze (le stesse del progetto “Arduino UNO – Inseguitore di luce“) per far si che il robot seguisse la luce, devo dire che sono riuscito con risultati abbastanza soddisfacenti anche se non molto accurati.

Il prossimo passo sarà utilizzare dei sensori di distanza (ad infrarossi o ad ultrasuoni) per rendere il robot autonomo.

 

Cambiando un’attimo argomento, mi sono ritrovato a casa dei ricetrasmettitori ad infrarossi di un vecchio robot della Deagostini, li utilizzerò per cominciare a fare qualche lavoretto con le trasmissioni senza fili (oltre ovviamente il modulo xBee).

Scheda UC3 – IR TX-RX Robot

Scheda UC1-IR TX-RX – Telecomando

Contapersone by Xfox

0

Come avevo promesso negli articoli precedenti, ho finalmente realizzato il video del programma “contapersone”.

Il codice è cambiato un pochino e ho aggiunto un display LCD che visualizza il totale delle persone presenti.

Ecco il video:

http://www.youtube.com/watch?v=gsTIoOBkCgI

Go to Top