Archivio mensile:dicembre 2011

Terza mano autocostruita

Girando per la rete ho visto questo progettino davveri carino e interessante: http://www.instructables.com/id/Yet-another-third-hand-soldering-aid-with-some-n/

Si tratta di una supporto per saldare… spesso si trova dai cinesi con tanto di lente di ingrandimento, tipo questa:

third_hand_parts_holder

Così mi sono ingegnato e con un vecchio dissipatore ed un vecchio caricabatterie ho fatto la mia terza mano assai comoda:

img20111219211102
img20111219211111
img20111219211121
img20111219211130

Arduino come presenter multimediale

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:

header

capture3

IMG_20111216_155059

IMG_20111217_173201

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;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
  pinMode(green, OUTPUT); // Green led
  pinMode(red, OUTPUT); // Red led
  irrecv.enableIRIn();
  Serial.println (" Arduino Presenter");
  Serial.println ("Coding by: ");
  Serial.println (" Andrea Esposito");
  Serial.println ("blackstufflabs.com");
}

void loop() {
  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 on
      delay(100);              // wait for a second
      digitalWrite(red, LOW);    // set the LED off
      delay(100);
      digitalWrite(green, HIGH);
    }
    irrecv.resume();
  }
  delay(200);
}

Interactive digital frame

In questi giorni è in corso un contest sul sito del famoso programma “Fritzing”: http://fritzing.org/news/the-fritzmas-challenge-send-in-your-projects/

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.

Tutto questo grazie alla splendida libreria IRremote.h fornita da: http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html

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:

capture

 

/*
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')

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
  pinMode(12, OUTPUT); // IR GREEN
  pinMode(7, OUTPUT); // IR RED 
  pinMode(4, OUTPUT);  // 1 red
  pinMode(5, OUTPUT);  // 2 red 
  pinMode(6, OUTPUT);  // 3 red
  tone1.begin(8);  //buzzer on pin 8
  irrecv.enableIRIn();
  Serial.println ("blackstufflabs.com");
}

void loop() {
  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 on
      delay(100);              // wait for a second
      digitalWrite(7, LOW);    // set the LED off
      delay(100);
      digitalWrite(12, HIGH);
      game(results.value);

    }
    if (level != 0 ) irrecv.enableIRIn();
    irrecv.resume(); // Receive the next value
  }
  delay (200);
}

void game (unsigned long int 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();      
      //song
      Serial.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 here

  byte 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 duration
  if(*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 octave
  if(*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 BPM
  if(*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 loop
  while(*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 '#' sharp
    if(*p == '#')
    {
      note++;
      p++;
    }

    // now, get optional '.' dotted note
    if(*p == '.')
    {
      duration += duration/2;
      p++;
    }

    // now, get scale
    if(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 note

    if(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);
    }
  }
}

Basetta supporto per Arduino e breadboard

L’idea di oggi è quella di clonare la basetta di adafruit:

mountingplateinuse_LRG
mountingplate_LRG

Avendo una lastra di plexiglass comprata da Leroy Merlin ho creato con due viti questo:

02122011014
02122011015
02122011016
02122011017

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.