Elettronica
Controllo di un servomotore tramite tastiera PS2 con Arduino
0
Tramite la libreria “PS2KeyBoard” per arduino è possibile ricevere i dati da una comune tastiera per computer PS2, così tramite questa libreria ho fatto in modo di controllare un servomotore con i tasti direzionali.
Il link che porta al playground di arduino è il seguente: http://www.arduino.cc/playground/Main/PS2Keyboard, tuttavia per scaricare l’ultima versione della libreria è necessario seguire questo link: http://www.pjrc.com/teensy/td_libs_PS2Keyboard.html.
I collegamenti da effettuare sono molto semplici e sono mostrati in un immagine nel precedente link, ma che riporto di seguito:

Se non disponete di un connettore, come nel mio caso, basta semplicemente comprare una prolunga PS2 (potrà costare al massimo 3€), tagliare la parte maschio del connettore, spellare i fili e verificarli tramite una resistenza e un multimetro.
Video:
Ecco il codice sorgente:
#include <PS2Keyboard.h>
#include <Servo.h>
const int DataPin = 4;
const int IRQpin = 3;
PS2Keyboard keyboard;
Servo servo;
int pos = 90;
int passo = 10;
long wait = 0;
void setup() {
delay(1000);
keyboard.begin(DataPin, IRQpin);
Serial.begin(9600);
Serial.println("Controllo Servo tramite tastiera PS2:");
servo.attach(5);
servo.write(pos);
}
void loop() {
if (keyboard.available()) {
// Leggo il valore ricevuto dalla tastiera
char c = keyboard.read();
// Controllo fra i tasti speciali (Es. BKSP, DEL, ESC)
if (c == PS2_LEFTARROW) {
Serial.print("[Left]");
pos -= passo;
}
else if (c == PS2_RIGHTARROW) {
Serial.print("[Right]");
pos += passo;
}
else if (c == PS2_UPARROW) {
Serial.print("[Up]");
passo += 10;
}
else if (c == PS2_DOWNARROW) {
Serial.print("[Down]");
passo -= 10;
}
else {
// Altrimenti mostro il carattere
Serial.print(c);
}
if (pos > 180)
pos = 180;
if(pos < 0)
pos = 0;
Serial.println();
Serial.println("--------------------------");
Serial.print("Posizione servo: ");
Serial.print(pos);
Serial.print("\tPasso: ");
Serial.println(passo);
Serial.println("--------------------------");
}
if (wait < millis()){
wait = millis() + 50;
servo.write(pos);
}
}
Come si può notare dal codice, tramite le frecce direzionali SU e GIU’ è possibile aumentare o decrementare (+10/-10) la variabile passo ovvero l’incremento/decremento che daremo alla variabile pos (posizione del servomotore) una volta premute le frecce direzionali DESTRA/SINISTRA.
Controllo matrice di LED 4×4 con Arduino e Nunchuck
0Dopo 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
0Sono 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
2Come 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
0Ultimamente 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).

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
0Ecco 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





