Con questo progetto vorrei mostrarvi come usare arduino come presenter multimediale.
Usando un comunissimo telecomando tv e premendo tasti ben definiti (tipo next o back), arduino riceve i comandi e scrive sulla seriale le stringe NEXT e BACK.
Un programma in running sul proprio pc, si mette in ascolto sulla porta seriale dell’arduino e quando intercetta le stringe NEXT e BACK simula pressione dei tasti AVANTI o INDIETRO del proprio pc in modo tale da cambiare le slide durante la vostra presentazione.
Il codice relativo ad arduino è davvero minimale, ora sto scrivendo il programmino che mi permette di simulare la pressione dei tasti sul pc.
Attualmente sto a metà dell’opera, devo solo limare alcune cosette.
Ho usato la stessa pcb della scorsa volta (trasformandola in un modulto/breakout), un ricevitore IR e un led bicolore.
Un pò di foto:
Per il momento il codice relativo ad arduino è il seguente:
/*Arduino presenter receiver By Andrea Esposito Site: blackstufflabs.com For: The Fritzmas challenge - http://fritzing.org 17/12/2011 IRremote.h from: http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html IR Receiver pcb taked from an old divx player TV Remote control Button - INT Next - 16746615 Back - 16750695 NN - 4294967295*/
#include <IRremote.h>
#define next 16746615
#define back 16750695
#define NN 4294967295
#define red 9
#define green 10
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;
voidsetup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiverpinMode(green, OUTPUT); // Green ledpinMode(red, OUTPUT); // Red led
irrecv.enableIRIn();
Serial.println (" Arduino Presenter");
Serial.println ("Coding by: ");
Serial.println (" Andrea Esposito");
Serial.println ("blackstufflabs.com");
}
voidloop() {
digitalWrite(green, HIGH);
if (irrecv.decode(&results)) {
if (results.value != NN){
if (results.value == next)
Serial.println("NEXT");
if (results.value == back)
Serial.println("BACK");
digitalWrite(green, LOW);
digitalWrite(red, HIGH); // set the LED ondelay(100); // wait for a seconddigitalWrite(red, LOW); // set the LED offdelay(100);
digitalWrite(green, HIGH);
}
irrecv.resume();
}
delay(200);
}
Oggi si fa leggermente fuori tema e parlerò di pezzotti.
In particolare parlerò di come pezzottare la stampante multifunzione Samsung SCX-4300.
Le case produttrici mettono nel firmware delle proprie stampanti un contatore che impedisce di stampare gli ultimi grammi di toner e impedisce la ricarica dello stesso.
Insomma, se vi appare la voce “toner esaurito” non vi resta altro che acquistare un toner nuovo e originale.
Con un piccolo accorgimento andremo a flashare la memoria della vostra stampante invalidando la garanzia ma che ci permette, però, di risparmiare qualche soldino sul toner.
In particolare, vi illustro come installare il firmware 1.25 (sulla mia stampante c’era addirittura la versione 1.09).
Generalmente, un firmware aggiornato, permette di avere qualche funzione in più e una stabilità maggiore della stampante.
La versione che vi propongo, oltre ad aggiornare la stampante vi permetterà di resettare il contatore di cui sopra.
Ovviamente, non mi assumo nessuna responsabilità sull’eventuale brick della vostra stampante e su altre cazzate che potreste fare.
Prima di tutto, scaricate e scompattate questo archivio: fix-scx-4300.rar
Vi troverete una cartella contenente tre file:
1. Il firmware 1.25 FIX_SCX4300_V1.25_Fact_romdl.hd
2. Il caricatore usbprns2.exe
Giusto per scrupolo, stampate un report della vostra stampante che vi dirà un bel pò di informazioni sulla stessa, tra i quali:
1. la versione del firmware presente
2. quante stampe sono state effettuate
3. riepiloghi vari
Benissimo, ora premete velocemente e in sequenza i seguenti tasti sulla vostra stampante:
MENU COPIES <- -> MENU ->
<- freccia sx
-> freccia dx
Questa sequenza vi abiliterà il “tech mode” che permette di aggiornare il firmware.
Ora eseguite queste operazioni:
– DATA MENU’ -> Premere OK
– Spostarsi con le frecce direzionali fino a selezionare “Flash Upgrade” -> Premere OK
– [Local] -> Premere OK
– Sul display della stampante compare la voce “DATA RECEIVING”.
Dal vostro pc trascinare (lettaralmente) il firmware FIX_SCX4300_V1.25_Fact_romdl.hd sul file usbprns2.exe.
Si aprirà una finestra nera sul vostro monitor con un casino di puntini: è l’upload del firmware sulla stampante.
La stampante smetterà di funzionare e compariranno sul display la seguente serie di messaggi di stato:
DATA RECEIVING> FLASH ERASING> FLASHPROGRAMMING> CHECKSUMMING> DOWNLOAD OK
Durante questa operazione, non fate nulla, non staccate la corrente, mani in tasca e state fermi a fissare il display!
La stampante si riaccenderà, ora non vi resta che resettare il contatore:
– Premere il tasto MENU’
– Spostarsi sulla funzione -> 10.Manutenzione -> Premere OK;
– Spostarsi sulla voce “Cancella Impost.” E premere OK;
– Spostarsi sulla voce “Tutte le impostazioni” e premere OK.
Stampante un report della stampante e vi accorgerete che il firmware è cambiato in 1.25fix e i contatori ora sono tutti a 0.
Ottimo no?
Tutti i file sono stati raccolti da altri forum e siti web.
Il link con i files allegato non è opera mia.
Non ho MAI partecipato in vita mia ad un contest su internet… ho notato che vanno molto di moda.
Ma la maggior parte si tratta di contest “pro spamming”: vinci se pubblicizzi il loro sito o partecipi assiduamente alle loro iniziative.
Questi tipi di contest non mi piacciono per niente, anzi… preferisco quelli un pò più costruttivi: vinci se hai realizzato un buon progetto.
Fritzing mi ha allettato.
Così mi sono sforzato un pochino e ho realizzato questa cosetta molto semplice ma carina (credo).
In cosa consiste?
Brevemente: ho una cornice digitale con 10 immagini, ogni immagine “racconta” un numero… bisogna indovinare il numero per andare avanti nel gioco.
Ogni immagine è un livello…
Così ho caricato un pò di immagini che raccontassero di un numero: pigreco, sezione aurea, il numero del diavolo e cazzatelle varie.
La cornice digitale non l’ho modificata per niente, nel senso che non ho fatto saldature o aperta: è rimasta intatta.
Come faccio a cambiare immagine per poi andare avanti con i livelli?
Ho usato un pò di led IR. Una tecnologia un pò di cacca.
Ho usato il telecomando della mia TV per inserire il numero misterioso, ho dovuto codificare tutti i tasti per capire che codice corrisponde ad ogni tasto.
Ho usato un IR ricevitore su pcb preso da un vecchio lettore divx con già presaldati resistenze e condensatori, un led ir preso da un vecchio telecomando, 3 led rossi e un buzzer.
Ho collegato la pcb del ricevitore ad arduino e il led ir l’ho ficcato nel buchetto del ir receiver della cornice digitale (niente saldature giuro) per tenerlo fermo e per non fare brutte figure durante il video.
Il tre led rossi indicano se la sequenza dei numeri immessi è corretta, ogni led indica: primo, secondo e terzo numero della sequenza corretta immessa.
Se la sequenza o il numero immesso con il telecomando è errata non avviene nulla: hai sbagliato quindi non vai avanti di livello.
Il buzzer mi è servito per fare un pò “scena”, ho messo qualche canzoncina presa dal google e ho usato la libreria tone.h presa da (mi pare): http://code.google.com/p/rogue-code/
Probabilmente un video può aiutare meglio a capire che cavolo ho combinato.
Vi posto un pò di materiale:
/*Interactive digital frame game By Andrea Esposito Site: blackstufflabs.com For: The Fritzmas challenge - http://fritzing.org 13/12/2011 IRremote.h from: http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html Tone.h & RTTL function from: http://code.google.com/p/rogue-code/ IR Led wiring from: http://www.ladyada.net/make/tvbgone/design.html IR Receiver pcb taked from an old divx player NN = FFFFFFFF = 4294967295 TV Remote control: Button - HEX - INT 1 - FF32CD - 16724685 2 - FF708F - 16740495 3 - FFB24D - 16757325 4 - FFF20D - 16773645 5 - FF728D - 16741005 6 - FFD02F - 16764975 7 - FF52AD - 16732845 8 - FF12ED - 16716525 9 - FF50AF - 16732335 0 - FFB04F - 16756815 Digital Frame remote control: Button - HEX - INT next - 80579867 - 2153224295 power - 805728D7 - 2153195735 Answers: Level - sequence Level 0 - 111 Level 1 - 666 Level 2 - 011 Level 3 - 945 Level 4 - 314 Level 5 - 975 Level 6 - 328 Level 7 - 101 Level 8 - 161 Level 9 - 100 Level 10 - 210 */
#include <IRremote.h>
#include <Tone.h>
#define button_0 16756815
#define button_1 16724685
#define button_2 16740495
#define button_3 16757325
#define button_4 16773645
#define button_5 16741005
#define button_6 16764975
#define button_7 16732845
#define button_8 16716525
#define button_9 16732335
#define button_power 0x805728D7
#define button_next 0x80579867
#define NN 4294967295
Tone tone1;
#define OCTAVE_OFFSET 0
//char *song = "WeWishYou:d=4,o=5,b=200:d,g,8g,8a,8g,8f#,e,e,e,a,8a,8b,8a,8g,f#,d,d,b,8b,8c6,8b,8a,g,e,d,e,a,f#,2g,d,g,8g,8a,8g,8f#,e,e,e,a,8a,8b,8a,8g,f#,d,d,b,8b,8c6,8b,8a,g,e,d,e,a,f#,1g,d,g,g,g,2f#,f#,g,f#,e,2d,a,b,8a,8a,8g,8g,d6,d,d,e,a,f#,2g"; char *ending = "WeWishYou:d=4,o=5,b=200:d,g,8g,8a,8g,8f#,e,e,e,a,8a,8b,8a,8g,f#,d,d,b";
char *next = "TakeOnMe:d=4,o=4,b=160:8f#5,8f#5,8f#5,8d5,8p";
char *wrong = "StarWars:d=4,o=5,b=45:32p,32f#,32f#";
int notes[] = {
0,
NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4,
NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B5,
NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6,
NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7
};
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
IRsend irsend;
decode_results results;
short level=0;
short count=0;
#define isdigit(n) (n >= '0' && n <= '9')
voidsetup()
{
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiverpinMode(12, OUTPUT); // IR GREENpinMode(7, OUTPUT); // IR RED pinMode(4, OUTPUT); // 1 redpinMode(5, OUTPUT); // 2 red pinMode(6, OUTPUT); // 3 red
tone1.begin(8); //buzzer on pin 8
irrecv.enableIRIn();
Serial.println ("blackstufflabs.com");
}
voidloop() {
digitalWrite(12, HIGH);
if (irrecv.decode(&results)) {
if (results.value != NN){
Serial.print("Level: ");
Serial.println(level);
Serial.print("Code: ");
Serial.println(results.value);
digitalWrite(12, LOW);
digitalWrite(7, HIGH); // set the LED ondelay(100); // wait for a seconddigitalWrite(7, LOW); // set the LED offdelay(100);
digitalWrite(12, HIGH);
game(results.value);
}
if (level != 0 ) irrecv.enableIRIn();
irrecv.resume(); // Receive the next value
}
delay (200);
}
void game (unsignedlongint code)
{
switch (level)
{
case 0:
if ((code == button_1) && (count == 2)) {
digitalWrite(4, HIGH);
count++;
}
if ((code == button_1) && (count == 1)) {
digitalWrite(5, HIGH);
count++;
}
if ((code == button_1) && (count == 0)) {
digitalWrite(6, HIGH);
count++;
}
if (count == 3)
{
Serial.println("Level done!");
count=0;
level++;
blinky();
play_rtttl(next);
irsend.sendNEC(button_next, 32);
}
break;
case 1:
if ((code == button_6) && (count == 2)) {
digitalWrite(4, HIGH);
count++;
}
if ((code == button_6) && (count == 1)) {
digitalWrite(5, HIGH);
count++;
}
if ((code == button_6) && (count == 0)) {
digitalWrite(6, HIGH);
count++;
}
if (count == 3)
{
Serial.println("Level done!");
count=0;
level++;
blinky();
play_rtttl(next);
irsend.sendNEC(button_next, 32);
}
break;
case 2:
if ((code == button_1) && (count == 2)) {
digitalWrite(4, HIGH);
count++;
}
if ((code == button_1) && (count == 1)) {
digitalWrite(5, HIGH);
count++;
}
if ((code == button_0) && (count == 0)) {
digitalWrite(6, HIGH);
count++;
}
if (count == 3)
{
Serial.println("Level done!");
count=0;
level++;
blinky();
play_rtttl(next);
irsend.sendNEC(button_next, 32);
}
break;
case 3:
if ((code == button_5) && (count == 2)) {
digitalWrite(4, HIGH);
count++;
}
if ((code == button_4) && (count == 1)) {
digitalWrite(5, HIGH);
count++;
}
if ((code == button_9) && (count == 0)) {
digitalWrite(6, HIGH);
count++;
}
if (count == 3)
{
Serial.println("Level done!");
count=0;
level++;
blinky();
play_rtttl(next);
irsend.sendNEC(button_next, 32);
}
break;
case 4:
if ((code == button_4) && (count == 2)) {
digitalWrite(4, HIGH);
count++;
}
if ((code == button_1) && (count == 1)) {
digitalWrite(5, HIGH);
count++;
}
if ((code == button_3) && (count == 0)) {
digitalWrite(6, HIGH);
count++;
}
if (count == 3)
{
Serial.println("Level done!");
count=0;
level++;
blinky();
play_rtttl(next);
irsend.sendNEC(button_next, 32);
}
break;
case 5:
if ((code == button_5) && (count == 2)) {
digitalWrite(4, HIGH);
count++;
}
if ((code == button_7) && (count == 1)) {
digitalWrite(5, HIGH);
count++;
}
if ((code == button_9) && (count == 0)) {
digitalWrite(6, HIGH);
count++;
}
if (count == 3)
{
Serial.println("Level done!");
count=0;
level++;
blinky();
play_rtttl(next);
irsend.sendNEC(button_next, 32);
}
break;
case 6:
if ((code == button_8) && (count == 2)) {
digitalWrite(4, HIGH);
count++;
}
if ((code == button_2) && (count == 1)) {
digitalWrite(5, HIGH);
count++;
}
if ((code == button_3) && (count == 0)) {
digitalWrite(6, HIGH);
count++;
}
if (count == 3)
{
Serial.println("Level done!");
count=0;
level++;
blinky();
play_rtttl(next);
irsend.sendNEC(button_next, 32);
}
break;
case 7:
if ((code == button_1) && (count == 2)) {
digitalWrite(4, HIGH);
count++;
}
if ((code == button_0) && (count == 1)) {
digitalWrite(5, HIGH);
count++;
}
if ((code == button_1) && (count == 0)) {
digitalWrite(6, HIGH);
count++;
}
if (count == 3)
{
Serial.println("Level done!");
count=0;
level++;
blinky();
play_rtttl(next);
irsend.sendNEC(button_next, 32);
}
break;
case 8:
if ((code == button_1) && (count == 2)) {
digitalWrite(4, HIGH);
count++;
}
if ((code == button_6) && (count == 1)) {
digitalWrite(5, HIGH);
count++;
}
if ((code == button_1) && (count == 0)) {
digitalWrite(6, HIGH);
count++;
}
if (count == 3)
{
Serial.println("Level done!");
count=0;
level++;
blinky();
play_rtttl(next);
irsend.sendNEC(button_next, 32);
}
break;
case 9:
if ((code == button_0) && (count == 2)) {
digitalWrite(4, HIGH);
count++;
}
if ((code == button_0) && (count == 1)) {
digitalWrite(5, HIGH);
count++;
}
if ((code == button_1) && (count == 0)) {
digitalWrite(6, HIGH);
count++;
}
if (count == 3)
{
Serial.println("Level done!");
count=0;
level++;
blinky();
play_rtttl(next);
irsend.sendNEC(button_next, 32);
}
break;
case 10:
if ((code == button_0) && (count == 2)) {
digitalWrite(4, HIGH);
count++;
}
if ((code == button_1) && (count == 1)) {
digitalWrite(5, HIGH);
count++;
}
if ((code == button_2) && (count == 0)) {
digitalWrite(6, HIGH);
count++;
}
if (count == 3)
{
Serial.println("THE END");
count=0;
level=0;
irsend.sendNEC(button_next, 32);
blinky();
play_rtttl(ending);
Serial.println("Done.");
blinky();
//songSerial.println("Closing digital frame...");
irsend.sendNEC(button_power, 32);
Serial.println("Bye bye!!!");
Serial.println ("blackstufflabs.com");
}
break;
default:
break;
}
}
void blinky()
{
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
delay(300);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
delay(300);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
delay(300);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
delay(300);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
delay(300);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
delay(300);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
delay(300);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
delay(300);
}
void play_rtttl(char *p)
{
// Absolutely no error checking in herebyte default_dur = 4;
byte default_oct = 6;
int bpm = 63;
int num;
long wholenote;
long duration;
byte note;
byte scale;
// format: d=N,o=N,b=NNN:// find the start (skip name, etc)while(*p != ':') p++; // ignore name
p++; // skip ':'// get default durationif(*p == 'd')
{
p++;
p++; // skip "d="
num = 0;
while(isdigit(*p))
{
num = (num * 10) + (*p++ - '0');
}
if(num > 0) default_dur = num;
p++; // skip comma
}
//Serial.print("ddur: "); Serial.println(default_dur, 10);// get default octaveif(*p == 'o')
{
p++;
p++; // skip "o="
num = *p++ - '0';
if(num >= 3 && num <=7) default_oct = num;
p++; // skip comma
}
// Serial.print("doct: "); Serial.println(default_oct, 10);// get BPMif(*p == 'b')
{
p++;
p++; // skip "b="
num = 0;
while(isdigit(*p))
{
num = (num * 10) + (*p++ - '0');
}
bpm = num;
p++; // skip colon
}
// Serial.print("bpm: "); Serial.println(bpm, 10);// BPM usually expresses the number of quarter notes per minute
wholenote = (60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds)// Serial.print("wn: "); Serial.println(wholenote, 10);// now begin note loopwhile(*p)
{
// first, get note duration, if available
num = 0;
while(isdigit(*p))
{
num = (num * 10) + (*p++ - '0');
}
if(num) duration = wholenote / num;
else duration = wholenote / default_dur; // we will need to check if we are a dotted note after// now get the note
note = 0;
switch(*p)
{
case'c':
note = 1;
break;
case'd':
note = 3;
break;
case'e':
note = 5;
break;
case'f':
note = 6;
break;
case'g':
note = 8;
break;
case'a':
note = 10;
break;
case'b':
note = 12;
break;
case'p':
default:
note = 0;
}
p++;
// now, get optional '#' sharpif(*p == '#')
{
note++;
p++;
}
// now, get optional '.' dotted noteif(*p == '.')
{
duration += duration/2;
p++;
}
// now, get scaleif(isdigit(*p))
{
scale = *p - '0';
p++;
}
else
{
scale = default_oct;
}
scale += OCTAVE_OFFSET;
if(*p == ',')
p++; // skip comma for next note (or we may be at the end)// now play the noteif(note)
{
/* Serial.print("Playing: "); Serial.print(scale, 10); Serial.print(' '); Serial.print(note, 10); Serial.print(" ("); Serial.print(notes[(scale - 4) * 12 + note], 10); Serial.print(") "); Serial.println(duration, 10);*/
tone1.play(notes[(scale - 4) * 12 + note]);
delay(duration);
tone1.stop();
}
else
{
/* Serial.print("Pausing: "); Serial.println(duration, 10);*/delay(duration);
}
}
}
L’idea di oggi è quella di clonare la basetta di adafruit:
Avendo una lastra di plexiglass comprata da Leroy Merlin ho creato con due viti questo:
Le due viti messe in diagonale permettono di “flippare” l’arduino nel senso che più ci aggrada.
Questa basetta mi è servita molto in quanto faccio uso massiccio dei cavi telefonici per la prototipazione… essendo rigidi, tendono a spostare la breadboard o l’arduino.
In questo modo ho tutto sotto controllo.