Kokiuina beta - Una storia un po tormentata

Pubblicato il: 9 settembre 2010 @ 17:05
 
Chi segue questo mio progetto dall’inizio conosce le difficoltà incontrate da subito nel reperire il sensore adatto per iniziare le prove di fattibilità..
Ebbene i problemi non sono terminati li e quando finalmente ho ricevuto due esemplari dell’ADNS-2620 ho scoperto con grande disappunto che anche l’unico risonatore ceramico da 29Mhz montato sul mio mouse “matto” dava dei problemi (forse a causa della “dissaldata” per il riutilizzo), tanto che i nuovi sensori non ne volevano sapere di funzionare. Cerca e ricerca, anche su RS pareva proprio che questi componenti non dovessero essere disponibili..
Passati così altri giorni nella delusione e nello sconforto per non poter “tentare” il mio esperimento, riprovando un po per caso la ricerca su RS ho poi scoperto che invece di chiamarlo correttamente “risonatore ceramico”, quel componente lo avevano etichettato genericamente come “quarzo” … :-(
Pazienza! Ingoiato il rospo ho ordinato gli agognati “quarzi” e quando finalmente mi sono arrivati ho potuto iniziare l’esperimento (rimandato però per quasi tutto agosto per dare priorità ad un altro progetto a pagamento e quindi più urgente ;) ).

Pelle e ossa “riciclati”

 
Uno degli obiettivi di questo esperimento è stato l’utilizzare componenti a bassissimo costo e, dove possibile, di totale recupero.
Così, per darvi un’idea di cosa e come sia “fatta” Kokiuina, vi riporto un sommario elenco dei pezzi utilizzati:
  • 1 Arduino mod. “diecimila” equipaggiato con il piccolo ATMega168 (ovvero solo 1Kbyte di Ram e 16Kbytes di Flash Rom di cui 2Kbytes già usati dal bootloader);
  • 1 sensore ADNS-2620 (Optical Mouse Sensor);
  • 1 risonatore ceramico da 24Mhz;
  • 1 condensatore da 2,2µF;
  • 2 mini servomotori per modellismo dinamico reperiti su eBay un annetto fa e pagati pochi euro (ancora oggi si trovano a poco meno di 5 euro l’uno … ma valgono davvero poco…);
  • 24 led GIALLI originariamente montati su luci di Natale (e che ne avessi trovato uno uguale all’altro sia come colore che come luminosità… ma, come vedremo più avanti, non tutto il male viene per nuocere);
  • 1 led BLU sempre ricavato dalle stesse luci di natale;
  • 9 resistenze da 220Ω per la limitazione corrente ai led (8 per le colonne della matrice degli occhi e 1 per il led blu);
  • 2 pezzetti di circuito stampato “mille fori” per realizzare la matrice di led per gli occhi e il supporto del sensore ottico;
  • alcuni spezzoni di “piattina” grigia recuperata da vecchi PC (quei cavi a più fili che collegano Hard Disk, Floppy e drive per CD/DVD) + un pezzo di filo celeste per il led blu;
  • alcuni connettori passo 2,5mm per i collegamenti con Arduino (è sempre un problema collegare qualcosa ad Arduino, perchè non si trovano connettori adatti se non a prezzi esorbitanti!);
  • 2 supporti per uova di pasqua (quelle di cioccolata) utilizzati per “vestire” Kokiuina (il corpo ed il cappello);
  • 1 alloggiamento per cd come supporto cavo per il passaggio dei fili dalla base alla testa opportunamente lavorata (la colonnina centrale bianca);
  • 1 tappo di un pennarello come innesto/supporto tra il servo per il movimento orizzontale e la base;
  • 1 contenitore per uso alimentare per la base (non ricordo neppure più cosa c’era dentro..);
  • parte di una vecchia scatola di plastica trasparente per floppy disk come raccordo/supporto tra gli “occhi” (la matrice di led) e il servo per il movimento verticale;
  • una piccola lente recuperata da una vecchia macchina fotografica (e qui però, come vi racconterò più avanti, ancora non ho risolto del tutto…);
  • altro materiale vario (piccole viti autofilettanti, fascette, colla a caldo, pezzetti di densa spugna nera, ecc).
Per migliorare l’illuminazione dei LED gialli ho dovuto “opacizzarli” in quanto la lente dei LED degli alberi di natale è rovesciata per diffondere al meglio la luce, così facendo ho involontariamente ottenuto un effetto “valvola” accesa, maggiormente marcato dalla differente luminosità e colore dei LED impiegati. Insomma: un effetto non cercato ma piacevole.
Ho anche aggiunto un LED blu (non previsto inizialmente) che si accende ogni volta che Kokiuina si accorge di un oggetto, sino a spegnersi gradualmente a “interesse” terminato.
Come si vede il risultato è di una robottina simpatica con un aspetto un poco “retrò” , che reagisce con tutte le espressioni previste e in piena autonomia (è sufficiente la sola alimentazione senza collegamento via usb).
I problemi che non sono riuscito ancora a risolvere sono due:
  1. la memoria ram a disposizione è praticamente finita (1024 byte sono veramente troppo pochi per un programma come questo se scritto in C), così non ho potuto implementare al meglio reazioni e comportamenti dipendenti dal tempo (per non lasciare Kokiuina sempre ferma in una posizione voglio implementare comportamenti di “distrazione” e una situazione di “riposo” quando non avviene nulla per periodi lunghi (per limitare anche i consumi quando sarà alimentata a pila);
  2. la lente che alla fine ho utilizzato (ne ho provate più di 6 prima di sceglierla) l’ho recuperata da un vecchio masterizzatore di CD (una delle lenti che focalizzano il raggio laser) ma nonostante questo il campo di visione che si ottiene è comunque troppo ristretto.
 
vista-kokiuina.jpeg
Così, al momento, Kokiuia è ridotta a guardare da una specie di “buco della serratura”, tanto che alla distanza di 1,6mt  (da a a b nel disegno) “vede” solo una zona di 50cm x 50cm.
Per il primo problema provvederò quanto prima ad aggiornare il mio Arduino con un ATmega328, così da raddoppiare la memoria disponibile.
Per il secondo problema (la lente) a meno che non trovi un’anima pia (o qualcuno interessato ad un’eventuale commercializzazione del progetto) che mi possa fornire una lente creata apposta (con la focale giusta), temo che mi dovrò accontentare del risultato ottenuto.
Problemi riscontrati (e irrisolvibili con il sensore del mouse):
Il sensore ADNS-2620 (e simili) non è fatto per inviare immagini, e quando si legge un frame, nonostante il framerate (la velocità di scansione del sensore) possa essere veramente molto elevata (da un minimo di  369 frame per secondo ad un massimo di 3000 frame/sec), questo arriva con una velocità molto limitata in quanto il sensore spedisce un pixel ogni frame acquisito.
Così la velocità di acquisizione potrà essere al massimo di 9.25 frame al secondo… Velocità comunque inutilizzabile in quanto maggiore è la velocità di scansione e minore è la luminosità che si ottiene. Così, per ottenere una discreta luminosità dell’immagine, in un ambiente molto illuminato si è costretti ad acquisire alla metà della velocità (4.5 frame al secondo).
 

Al momento la scansione (come si vede anche dal video sopra riportato) è veramente molto lenta (poco più di 1 frame al secondo), così la nostra “povera” Kokiuina ha la reattività di un bradipo… ma nonostante questo, funziona!!
Per chi volesse fare qualche prova con il sensore (reperibile anche su RS con il suo risonatore ceramico) ecco qui come collegarlo:
 
schema-sensore-mouse.jpeg
E qui un paio di listati di codice:
Per Arduino – al solito è inutile riscrivere cose che qualcuno ha già scritto, e come si vede per il “dialogo” tra Arduino e il sensore ho utilizzato la libreria presente a questo indirizzo, mentre il codice l’ho scritto appositamente per ottimizzare la comunicazione con Processing.
/* Sensore ottico per mouse ADNS-2620
 * invio della sola immagine tramite codici ascii dove 32 = 0 e ciascun pixel è nel range tra 0 e 63
 * il record inizia con il valore '>' e termina con '<'
 *
 * (c) Kokiua alias L.M. Sorbolo Parma Italia
 */

#include "Adns.h"

#define cam_sclk 2  //definisce il pin 2 di Arduino come SCLK
#define cam_sdio 3  //definisce il pin 3 di Arduino come SDIO

Mousecam cam( cam_sclk, cam_sdio ); // attiva il sensore

void setup(){
  Serial.begin(115200);
  if(cam.adns_init() == 0){
    Serial.println("sensore non presente...");
    for(;;);  //si ferma con un loop infinito
  }
  cam.adns_write(ADNS_CONFIG, 0x01); // forza lo stato del sensore ottico a "sempre sveglio" (Forced Awake Mode)
  cam.adns_write(ADNS_FRAME_PERIOD, 0x04); // imposta il FrameRate per ottenere la massima luminosità (norm C2 - min 20 - max F0)
  Serial.println(byte('>')); //invia inizio record
}

void loop(){
  byte val = 255;
  register int z = 324;
  cam.adns_write(ADNS_PIXEL_GRAB, 0x00); // scrive per iniziare il frame
  do { val = cam.adns_read(ADNS_PIXEL_GRAB); } while (!(val & 0x40));  //legge il sensore sino a quando non è settato il flag DATA_VALID (bit 6)
  while( z ){ //prosegue sino a quando non ha letto tutti i pixel
    val = 32 + (val & B00111111);//maschera per valore < 64
    Serial.print(byte(val)); //invia il dato in seriale
    if( ((z-1) % 18) == 0 ) Serial.println(); //a capo se multiplo di 18 (per lettura su monitor di Arduino)
    z--; //decrementa conteggio pixel
    do { val = cam.adns_read(ADNS_PIXEL_GRAB); } while (!(val & 0x40));  //legge il sensore sino a quando non è settato il flag DATA_VALID (bit 6)
  }
  Serial.println("<>"); //invia fine/inizio record
}
e al fine di poter visualizzare le immagini ottenute, per Processing:
/* Sensore ottico per mouse ADNS-2620
 * ricezione immagine da Arduino
 *
 * (c) Kokiua alias L.M. Sorbolo Parma Italia
 */

import processing.serial.*;
int DimCella = 20, i = 0, val = 0;
byte fotogramma = 0;
Serial PortaSeriale;

void setup () {
  size(360, 360);
  String NomePorta = Serial.list()[1];
  PortaSeriale = new Serial(this, NomePorta, 115200);
  background(0);
}

void draw() { //non usato
}

void serialEvent(Serial PortaSeriale) {
    val = PortaSeriale.read();
    switch( val ){
      case '>': i = 0; fotogramma = 1; // nuovo inizio fotogramma
        break;
      case '<': fotogramma = 0; //fine fotogramma
        break;
      default:
        if( fotogramma == 1 && val > 63 ){
          int x = i / 18;
          int y = 17 - ((i - (x * 18)) + 1);
          x = 17 - x; //immagine raddrizzata
          int temp = (val - 64) * 4;//moltiplica il valore letto per aumentare la luminosità e il contrasto
          fill( temp );
          stroke(153);
          rect(x * DimCella, (y+1) * DimCella, DimCella, DimCella);
          i++;
        } else {
          if( fotogramma == 0) print(char(val)); //qualsiasi altro carattere ricevuto viene visualizzato nell'area di stampa di Processing
        }
    }
}

Probabilmente in un prossimo futuro proverò ad acquisire direttamente l'immagine da una telecamera a basso costo (se ne trovano su internet a poco più di 5 euro) così da ottenere una migliore velocità e risolvere del tutto il problema della lente.

 

Prometto che prima o poi troverò il tempo per pubblicare anche altre porzioni del codice che fa funzionare autonomamente Kokiuina, ma per farlo come si deve è importante documentare il tutto, e questo richiede molto tempo ;-)

Tag: