Posts tagged Arduino

Controllo matrice di LED 4×4 con Arduino e Nunchuck

0

Dopo il post precedente (Arduino & Registro SIPO) ho deciso di realizzare una piccola matrice di LED dalle dimensioni 4 x 4 controllate da due registri a scorrimenti 74164 (datasheet).

Inizialmente avevo sviluppato il programma solo per fare dei semplici giochi di luce ma successivamente ho deciso di aggiungere al progetto il Nunchuck in modo da poter muovermi punto per punto sulla matrice e selezionare un punto ed accenderlo!

Mi spiego meglio: alimentando il circuito inizierà a lampeggiare un punto sulla matrice, questo punto può essere spostato tramite il joystick del nunchuck e tramite il pulsante C posso “selezionare” quel punto e lasciarlo sempre acceso.

Premendo il pulsante Z invece i led si accendono tutti.

Video:

 

Ecco lo schema di collegamento:

I pin non collegati dei 74164 sono le uscite A-B-C-….H e vanno collegati tramite resistenza ai led.

I due integrati sono, come detto prima, registri a scorrimento (da 8bit) e sono collegati in cascata per cui l’uscita H del primo integrato va all’ingresso dati del secondo integrato.

I collegamenti ai led devono essere così impostati:

A B C D <- Primo 74164

E F G H <- Primo 74164

A B C D <- Secondo 74164

E F G H <- Secondo 74164

Consultare il datasheet per il pinout dell’integrato.

Ed ecco il codice sorgente:

/*Controllo di una matrice di led 4x4 tramite
 registri SIPO 74164. 

 Versione 2 - Aggiunto il nunchuck
 Xfox
 */

//Includo librerie
#include <Wire.h>
#include <string.h>
#undef int
#include <stdio.h>

const int datapin = 2; //Pin di serial
const int clockpin = 3; //Pin di clock
const int catodo = 5; //Catodo

byte primobyte = B00000000;
byte secondobyte = B00000000;

byte primo_point, secondo_point, terzo_point, quarto_point = B0000;
byte xpos = B1000;

long delaytime = 100;

//Variabili per i dati Nunchuck
int joy_x_axis = 0;
int joy_y_axis = 0;
int accel_x_axis = 0;
int accel_y_axis = 0;
int accel_z_axis = 0;
int z_button = 1;
int c_button = 1;
//Variabili Nunchuck
uint8_t outbuf[6];
int cnt = 0;

int posizione_x = 2;
int posizione_y = 2;

int griglia[5][5] = {
  {
    B0,B0,B0,B0,B0                } //Rga inutile ma necessaria per far si che gli arry partano da griglia [1][1]
  ,{
    B0,B0,B0,B0,B0            }
  ,{
    B0,B0,B0,B0,B0               }
  ,{
    B0,B0,B0,B0,B0              }
  ,
  {
    B0,B0,B0,B0,B0             }
};

void setup(){
Serial.begin(9600);

  pinMode(datapin, OUTPUT);
  pinMode(clockpin, OUTPUT);
  pinMode(catodo, OUTPUT);

  Wire.begin ();		// join i2c bus with address 0x52
  nunchuck_init (); // send the initilization handshake
}

void loop(){

  Nunchuck(); //Richiama funzione per acquisire dati nunchuck
  controlloxy();

  if (z_button == 0){
    scrivi(B1111, B1111, B1111, B1111, 0);
  }

  if(c_button == 0){
    set(posizione_x, posizione_y);
    delay(300);
  }

/*
  //Primo gioco
   point(1, 1);
   delay(delaytime);

   point(2, 1);
   delay(delaytime);

   point(3, 1);
   delay(delaytime);

   point(4, 1);
   delay(delaytime);

   point(4, 2);
   delay(delaytime);

   point(4, 3);
   delay(delaytime);

   point(4, 4);
   delay(delaytime);

   point(3, 4);
   delay(delaytime);

   point(2, 4);
   delay(delaytime);

   point(1, 4);
   delay(delaytime);

   point(1, 3);
   delay(delaytime);

   point(1, 2);
   delay(delaytime);

   //Secondo gioco
   point(1, 1);
   delay(delaytime);

   point(2, 1);
   delay(delaytime);

   point(3, 1);
   delay(delaytime);

   point(4, 1);
   delay(delaytime);

   point(4, 2);
   delay(delaytime);

   point(3, 2);
   delay(delaytime);

   point(2, 2);
   delay(delaytime);

   point(1, 2);
   delay(delaytime);

   point(1, 3);
   delay(delaytime);

   point(2, 3);
   delay(delaytime);

   point(3, 3);
   delay(delaytime);

   point(4, 3);
   delay(delaytime);

   point(4, 4);
   delay(delaytime);

   point(3, 4);
   delay(delaytime);

   point(2, 4);
   delay(delaytime);

   point(1, 4);
   delay(delaytime);
  */
}

long wait = 0;
void Nunchuck(){
  if (wait < millis()){
    wait = millis() + 100;
    Wire.requestFrom (0x52, 6);	// request data from nunchuck
    while (Wire.available ())
    {
      outbuf[cnt] = nunchuk_decode_byte (Wire.receive ());	// receive byte as an integer
      cnt++;
    }

    // If we recieved the 6 bytes, then go print them
    if (cnt >= 5)
    {
      print ();
    }

    cnt = 0;
    send_zero (); // send the request for next bytes
  }
}

void nunchuck_init ()
{
  Wire.beginTransmission (0x52);	// transmit to device 0x52
  Wire.send (0x40);		// sends memory address
  Wire.send (0x00);		// sends sent a zero.
  Wire.endTransmission ();	// stop transmitting
}

void send_zero ()
{
  Wire.beginTransmission (0x52);	// transmit to device 0x52
  Wire.send (0x00);		// sends one byte
  Wire.endTransmission ();	// stop transmitting
}

void print ()
{

  joy_x_axis = outbuf[0];
  joy_y_axis = outbuf[1];
  accel_x_axis = outbuf[2] * 2 * 2;
  accel_y_axis = outbuf[3] * 2 * 2;
  accel_z_axis = outbuf[4] * 2 * 2;

  z_button = 0;
  c_button = 0;

  if ((outbuf[5] >> 0) & 1)
  {
    z_button = 1;
  }
  if ((outbuf[5] >> 1) & 1)
  {
    c_button = 1;
  }

  if ((outbuf[5] >> 2) & 1)
  {
    accel_x_axis += 2;
  }
  if ((outbuf[5] >> 3) & 1)
  {
    accel_x_axis += 1;
  }

  if ((outbuf[5] >> 4) & 1)
  {
    accel_y_axis += 2;
  }
  if ((outbuf[5] >> 5) & 1)
  {
    accel_y_axis += 1;
  }

  if ((outbuf[5] >> 6) & 1)
  {
    accel_z_axis += 2;
  }
  if ((outbuf[5] >> 7) & 1)
  {
    accel_z_axis += 1;
  }
}

char nunchuk_decode_byte (char x)
{
  x = (x ^ 0x17) + 0x17;
  return x;
}

void scrivi(byte primo, byte secondo, byte terzo, byte quarto, int n){

  //Imposto primobyte
  bitWrite(primobyte, 0, bitRead(secondo, 0));
  bitWrite(primobyte, 1, bitRead(secondo, 1));
  bitWrite(primobyte, 2, bitRead(secondo, 2));
  bitWrite(primobyte, 3, bitRead(secondo, 3));
  bitWrite(primobyte, 4, bitRead(primo, 0));
  bitWrite(primobyte, 5, bitRead(primo, 1));
  bitWrite(primobyte, 6, bitRead(primo, 2));
  bitWrite(primobyte, 7, bitRead(primo, 3));

  //Imposto secondobyte
  bitWrite(secondobyte, 0, bitRead(quarto, 0));
  bitWrite(secondobyte, 1, bitRead(quarto, 1));
  bitWrite(secondobyte, 2, bitRead(quarto, 2));
  bitWrite(secondobyte, 3, bitRead(quarto, 3));
  bitWrite(secondobyte, 4, bitRead(terzo, 0));
  bitWrite(secondobyte, 5, bitRead(terzo, 1));
  bitWrite(secondobyte, 6, bitRead(terzo, 2));
  bitWrite(secondobyte, 7, bitRead(terzo, 3));

  if(n == 1){
    sommagriglia();
  }

  inviadati();
}

void sommagriglia(){
  //Unisco 4° Pezzo
  for(int i = 0; i <= 3; i++){
    bitWrite(secondobyte, i, (griglia[1][converti(i)] || bitRead(secondobyte, i)));
  };    

  //Unisco 3° Pezzo
  for(int i = 0; i <= 3; i++){
    bitWrite(secondobyte, i+4, (griglia[2][converti(i)] || bitRead(secondobyte, i+4)));
  };

  //Unisco 2° Pezzo
  for(int i = 0; i <= 3; i++){
    bitWrite(primobyte, i, (griglia[3][converti(i)] || bitRead(primobyte, i)));
  };    

  //Unisco 1° Pezzo
  for(int i = 0; i <= 3; i++){
    bitWrite(primobyte, i+4, (griglia[4][converti(i)] || bitRead(primobyte, i+4)));
  };
}

//Funzione che permette di convertire un valore per
//la somma fra griglia e byte
int converti(int n){
  switch(n){
  case 0:
    return 4;
    break;

  case 1:
    return 3;
    break;

  case 2:
    return 2;
    break;

  case 3:
    return 1;
    break;

  }
}

//Funzione che invia dati tramite seriale
void inviadati(){

  digitalWrite(catodo, HIGH);

  //Scrivo sul secondo 74164
  for (int i = 0; i <= 7; i++){
    digitalWrite(datapin, bitRead(secondobyte, i));

    //Impulso per il clock
    digitalWrite(clockpin, HIGH);
    digitalWrite(clockpin, LOW);
  }

  //scrivo sul primo 74164
  for (int i = 0; i <= 7; i++){
    digitalWrite(datapin, bitRead(primobyte, i));

    //Impulso per il clock
    digitalWrite(clockpin, HIGH);
    digitalWrite(clockpin, LOW);
  }

  digitalWrite(catodo, LOW);
}

//Funzione per dare coordinate XY di un punto

void point(byte x, byte y){

  primo_point = B0000;
  secondo_point = B0000;
  terzo_point = B0000;
  quarto_point = B0000;

 findxpos(x);

  switch (y){
  case 1:
    quarto_point += xpos;
    break;

  case 2:
    terzo_point += xpos;
    break;

  case 3:
    secondo_point += xpos;
    break;

  case 4:
    primo_point += xpos;
    break;

  default:
    scrivi(B1001, B0110, B0110, B1001, 1);
    break;
  }

    scrivi(primo_point, secondo_point, terzo_point, quarto_point, 1);
  }

void findxpos(byte x){
  xpos = B0000;

  switch(x){
  case 1:
    xpos = B1000;
    break;

  case 2:
    xpos = B0100;
    break;

  case 3:
    xpos = B0010;
    break;

  case 4:
    xpos = B0001;
    break;
  }
}

void lampeggia(int n){
  if (n == 0){
    digitalWrite(catodo, HIGH); //Spegne
    delay(250);
    digitalWrite(catodo, LOW); //Accende
    delay(250);
  }
  else{
    for(int i = 0; i < n; i++){
      digitalWrite(catodo, HIGH); //Spegne
      delay(250);
      digitalWrite(catodo, LOW); //Accende
      delay(250);
    }
  }
}

void set(int x, int y){
  griglia[y][x] = !bitRead(griglia[y][x], 0);
  sommagriglia();
  inviadati();
}

long wait_controllo = 0;
long wait_lampeggio = 0;
byte state = B0;
void controlloxy(){
  if (wait_controllo < millis()){
    wait_controllo = millis() + 300;

    if (posizione_x < 4){
      if(joy_x_axis > 178){
        posizione_x++;
      }
    }

    if(posizione_x > 1){
      if(joy_x_axis < 78){
        posizione_x--;
      }
    }

    if (posizione_y < 4){
      if(joy_y_axis > 178){
        posizione_y++;
      }
    }
    if(posizione_y > 1){
      if(joy_y_axis < 78){
        posizione_y--;
      }
    }
  }

if (state == 1)
  point(posizione_x, posizione_y);
 else
scrivi(B0,B0,B0,B0,1); 

if(wait_lampeggio < millis()){
  wait_lampeggio = millis() + 250;
  state = !state;
  }
}

Il pezzo di codice commentato nel loop è semplicemente un piccolo giochetto di luci.

Il codice può sembrare molto confuso poichè ho unito lo sketch per il nunchuck con lo sketch per la matrice.

E’ comunque un codice che andrebbe rivisto ma non credo che lo farò dato che ho già smontato tutto dalla breadboard per dare spazio al mio prossimo progetto! :)

Arduino & Registro SIPO (74164)

2

Oggi, passando dalla mia stanzetta mi son caduti gli occhi sulle mensole dove ho dei piccoli contenitori con componenti elettronici e così ho deciso di dare un’occhiata. Ho trovato moltissimi integrati fra cui un paio di registri SIPO (serial input parallel ouput) 74164 (datasheet).

Ho deciso quindi di realizzare qualcosa con questi registri ed il mio Arduino UNO.

Ho fatto un piccolo sketch che pilota 8 led con soli due pin, sfruttando appunto la particolarità del registro che consente di inserire un dato (di 8 bit) in seriale e prelevarlo in parallelo.

Ed ecco lo sketch:

const int datapin = 2; //Pin di serial out
const int clockpin = 3; //Pin di clock

void setup(){
  pinMode(datapin, OUTPUT);
  pinMode(clockpin, OUTPUT);
}

int numero = 0;
void loop(){

  if (numero <= 255){
    numero++;
  }
  else{
    numero = 0;
  }

  scrivi(numero);
  delay(500);
}

void scrivi(byte dato){

  for (int i = 0; i <= 7; i++){
    digitalWrite(datapin, bitRead(dato, i));

    //Impulso per il clock
    digitalWrite(clockpin, HIGH);
    digitalWrite(clockpin, LOW);
  }
}

E’ molto semplice, una variabile chiamata “numero” conta fino a 255 (il massimo valore che si può rappresentare con 8 bit) e mostra su questi led il valore in codice binario.

 

In realtà la mia idea era di controllare un piccolo quadretto di led 4×4 tramite due di questi registri, ma dovrei realizzare una PCB per far questo, non mi va di impazzire con le basette millefori. :D Chissà, magari un giorno mi viene la voglia di completare questo lavoro.

 

A presto!

Arduino Personal Trainer

0

Ultimamente, vedendo dei pesi sulla mia scrivania ho deciso di cominciare ad utilizzarli, così ho creato un programmino per l’Arduino che mi permetta di contare le serie di pesi che faccio e il tempo fra una serie e l’altra.

Per essere più precisi, stabilisco io quante serie voglio fare (da una serie a cinque) e il tempo (da uno a cinque minuti) fra una serie e l’altra. Il programma segue uno schema piramidale al contrario, ovvero, parto da un numero maggiore di pesi (numero della serie * 20; es. 4a serie * 20 = 80 pesi) per poi finire con un ultima serie da 20.

 

Codice sorgente:

//Personal Trainer (pesi) By Xfox

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

const int A = A0;
const int B = A1;
const int Sound = 10;

int no_serie = 1;
int intervallo_serie = 1;

//Variabili per l'attesa
long start_time = 0;
long end_time = 0;
long tempo = 0;

void setup() {
  lcd.begin(16, 2);
  lcd.print("www.xfox.it");
  lcd.setCursor(0,1);
  lcd.print("PT By Xfox");

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

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

  pinMode(Sound, OUTPUT);

  delay(2000);

  settaggio(); //Richiamo alla funzione di avvio programma
}

void loop(){
  if(no_serie >= 1){
    delay(500); //Delay sul pulsante
    while (digitalRead(A) == 1){
      scrivi(4);
    } //Ciclo di attesa completamento
    no_serie--;

    attesa();
  }
  else  {
    scrivi(6);
  }
}

void settaggio(){
  //Passo 1: Settaggio numero serie
  while(digitalRead(B) == 1){
    scrivi(1);
    if(digitalRead(A) == 0){
      if(no_serie < 5){
        no_serie++;
      }
      else{
        no_serie = 1;
      }
      delay(300);
    }
  }
  delay(300); //Delay per il pulsante B

  //Passo 2: Settaggio tempo serie
  while(digitalRead(B) == 1){
    scrivi(2);
    if(digitalRead(A) == 0){
      if(intervallo_serie < 5){
        intervallo_serie++;
      }
      else{
        intervallo_serie = 1;
      }
      delay(300);
    }
  }
  delay(300); //Delay per il pulsante B

  //Passo 3: Wait per lo start
  while(digitalRead(A) == 1){
    scrivi(3);
  }
  delay(300); //Delay per il pulsante B
}

long wait_scrivi = 0;
void scrivi(int mode){
  if (wait_scrivi < millis()){
    wait_scrivi = millis() + 100;

    //Mode 1 = Settaggio no_serie
    if (mode == 1){
      lcd.clear();
      lcd.print("Quante serie?");
      lcd.setCursor(0,1);
      lcd.print(no_serie);
    }

    //Mode 2 = Settaggio tempo serie
    if (mode == 2){
      lcd.clear();
      lcd.print("Intervallo?");
      lcd.setCursor(0,1);
      lcd.print(intervallo_serie);
    }

    //Mode 3 = Wait per lo start
    if (mode == 3){
      lcd.clear();
      lcd.print("Premi A per");
      lcd.setCursor(0,1);
      lcd.print("andare avanti!");
    }

    //Mode 4 = Prima serie
    if (mode == 4){
      lcd.clear();
      lcd.print("Serie da:");
      lcd.print(no_serie * 20);
      lcd.setCursor(0,1);
      lcd.print("Premi A");
    }

    //Mode 5 = Tempo
    if (mode == 5){
      lcd.clear();
      lcd.print("Attesa:");
      lcd.setCursor(0,1);
      lcd.print( tempo / 1000 );
      lcd.print(" Secondi");
    }

    //Mode 6 = Fine allenamento
    if (mode == 6){
      lcd.clear();
      lcd.print("Allenamento");
      lcd.setCursor(0,1);
      lcd.print("completato!!!");
    }

    //Mode 7 = Prossima serie
    if (mode == 7){
      lcd.clear();
      lcd.print("Premi A per la");
      lcd.setCursor(0,1);
      lcd.print("prossima serie");
    }
  }
}

long wait_suona = 0;
void suona(){
  if (wait_suona < millis()){
    wait_suona = millis() + 1000;
    tone(Sound, 262, 500);
  }
}

void attesa(){
  start_time = millis();
  end_time = start_time + (intervallo_serie * 60000);

  while(end_time > millis()){
    tempo = (end_time - start_time) - (millis() - start_time);
    scrivi(5);
  }
  while(digitalRead(A) == 1){
    suona();
    scrivi(7);
  }
}

In sostanza all’avvio del programma si sceglie il numero di serie ed il tempo fra una serie e l’altra, successivamente ci viene chiesto di premere il pulsante A per cominciare “l’allenamento” una volta completata la serie premeremo ancora A per far comparire il countdown alla prossima serie, scaduto il countdown un buzzer ci avvertirà, premeremo ancora A per far comparire il numero di pesi da svolgere, una volta completati premeremo A e ci troveremo al punto di prima.

Una cosa da aggiungere, sicuramente molto utile, sarebbe un accelerometro per implementare la funzione di contare i pesi che si fanno.

Piccola realizzazione con LED RGB Slow Flashing

2

Sono finalmente arrivati i 100 LED RGB Slow Flashing che avevo ordinato su eBay (da Hong Kong) per poco più di 6€, così ho deciso di realizzare un piccolo progettino tanto per passarmi il tempo, niente di particolare!

Un semplice servomotore con attaccati due di questi led. E’ abbastanza semplice il progetto perchè i LED non hanno bisogno di microcontrollore per cambiare colore, fanno tutto da sè!

Ecco un video della realizzazione:

 

 

Questi LED operano con una tensione di 3,2V-3,4V e una corrente di 20 mA e proprio per queste caratteristiche li ho alimentati con Arduino (che controlla anche il servomotore) prelevando la tensione 3,3V presente sulla board. Il motivo per cui ho scelto di mettere due soli LED è semplice, l’uscita di 3,3V dalla board Arduino può erogare un massimo di 50 mA quindi è impossibile inserirne più di due.

 

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

 

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

Google si affida ad Arduino per allargare i confini di Android

0

Google vuole allargare i confini del suo sistema operativo Android dedicato a cellulari e tablet. E ha lanciato da poco un kit per progettare e costruire accessori hardware da collegare con gli smartphone. Ma il cuore tecnologico del kit risiede in un microcontroller inventato a Ivrea: Arduino.

Continua a leggere articolo su “Il sole 24 Ore”: http://www.ilsole24ore.com/art/tecnologie/2011-05-13/arduino-202014.shtml?uuid=Aa0dHuWD

Xfox’S Robot – Anteprima

0

Ecco una piccola anteprima del robottino wifi-controllato da me realizzato mediante la piattaforma Arduino.

Non appena realizzerò una versione completa del progetto farò un nuovo post. :D

Controllo display con xBee

0

Ed ecco la prima realizzazione con il modulo xBee che mi è arrivato qualche giorno fa!

Il progetto consiste nel controllare “senza fili” un display LCD 16×2. Il codice base è semplice, come se si dovesse controllare via seriale con il cavetto USB, solamente che al posto del cavo c’è il modulo xBee.

Ecco lo schema:

 

Clicca per ingrandire

Perdonatemi se è un poco confusionario ma è stato realizzato con Fritzing e non sono molto pratico.

 

Ecco il video:

(So che la qualità è pessima, prima o poi mi deciderò ad acquistare una videocamera decente!)

Codice sorgente:

Ordine moduli xBee e varie

1

Qualche oretta fa ho finalmente ordinato dal sito della SparkFun i moduli wiriless xBee e tutto ciò che mi serve per “rimuovere” il cavo USB per la comunicazione seriale fra pc ed Arduino (come detto nell’articolo precedente).

Ho ordinato anche 3 ponti H per il controllo di motori in corrente continua, nell’ultimo progetto si può notare che i motorini girano solo in un verso, ecco, con questi integrati (L293D) potrò invertire anche il senso di rotazione (piano piano sto comprando i componenti per un piccolo robot), 3 ATMega 328 (e 3 quarzi da 16MHz per questi ultimi) semplicemente per averli in casa e poterli usare in un secondo momento (un pezzo, come si vede in figura, costa 3,87€ mentre su siti italiani il prezzo si aggira intorno a 7€) e la ProtoShield per l’Arduino.

In totale ho speso 87,28€ più 21,12€ di spedizione = 108.40€.

Go to Top