Archivi categoria: Arduino

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.

eXtreme Burner & Atmega328P

eXtreme Burner è un software alternativo ad avrdude per la riprogrammazione di chip AVR con programmatore USBasp.
E’ abbastanza funzionale ma mancano un pò di chip tra i target, tra i quali proprio l’Atmega328P.

Vediamo come aggiungere il 328p all’interno di questo software.
Andiamo in C:Program Files (x86)eXtreme Burner – AVRData e diamo diritti di lettura/scrittura al file chips.xml in questo modo:

Tasto destro sul file > Proprietà > Sicurezza > Modifica > Users > Controllo Completo e applichiamo le modifiche.

capture

Ora possiamo modificare il file chips.xml in questo modo….
Nella seione chiplist aggiungiamo questo:

    <CHIP>
        <NAME>ATmega328P</NAME>
        <FLASH>32768</FLASH>
        <EEPROM>1024</EEPROM>
        <SIG>0x000F951E</SIG>
        <PAGE>256</PAGE>
        <LFUSE>YES</LFUSE>
        <HFUSE>YES</HFUSE>
        <EFUSE>YES</EFUSE>
        <LOCK>YES</LOCK>
        <CALIB>YES</CALIB>
        <PLACEMENT>.ImagesPlacementsZIF_DIP_40.bmp</PLACEMENT>
    </CHIP>

capture

Salviamo il file e in eXtreme Burner ora avremo il target Atmega328P:

capture

Ora possiamo fare quel che ci pare….
….resta il fatto, però, che consiglio avrdude…

USBasp & Win7 x64

Riprogrammare un atmega può essere un pò complicato, ma tool hardware come l’USBasp o USBtinyISP possono dare un certo grado di affidabilità per una corretta programmazione dell’IC.
Mio zio diceva sempre: “Song’ ‘e fierr ca’ fann ‘o mast” (sono i giusti utensili che ti fanno capomastro)… ed è proprio vero!

usbasp

USBasp è un programmatore AVR multipiattaforma davvero molto economico, su ebay ne trovate di già pronti a pochissimi euri.
Il sito ufficiale è questo: http://www.fischl.de/usbasp/
Qui troviamo della documentazione e i driver per Windows.

Il vero problema con i driver Windows è che non sono “signati”, nel readme si legge questo “With WinAVR version 20100110 or older, please use libusb_0.1.12.1.

Se con la versione libusb_1.2.4.0 non ho particolari problemi a farlo riconoscere (esce solo il popup di warning a fine installazione: ignoratelo) con questa versione (libusb_0.1.12.1) si ha qualche problema in più su sistemi operativi Windows 7 x64 in quanto il sistema proprio non ne vuole sapere di riconoscere la periferica in quanto non signata.

La mia soluzione tampone, per ora, è quella di usare un software particolare chiamato DSEO.
Questo software permette di abilitare sul proprio sistema operativo la modalità “test” che ci permette provare driver non signati.
In pratica è un workaround…

Una volta scaricata l’ultima versione, basterà mettere il pallino su “Enable Test Mode” e riavviare il pc:

Driver Signature Enforcement Overrider

Come dicevo è una soluzione tampone, ma meglio di niente….

Tutto questo casino è per far funzionare USBasp con AVRdude che è uno dei migliori software per la riprogrammazione degli AVR…. anche se un pò ostico in quanto gira tutto sotto riga di comando (ma esistono un casino di GUI per facilitare tale operazione).

Io ho provato libusb_1.2.4.0 con altri tool quali eXtreme Burner – AVR.

Arduino Software Reset

Aggiornamento: nelle ultime versione dell’ide/bootloader questa macro fa andare in loop il nostro arduino, non lo fate! Per sbloccarlo: https://blackstufflabs.com/2013/10/24/aggiornare-firmware-usbasp-con-arduino/

 

Raramente vi capiterà di intervenire via software per resettare l’arduino.
Il miglior modo per fare un buon reset software e quello indicato dal sito ufficiale dell’atmel: reset

Usare il reset software significa, per la maggior parte delle volte, aver scritto uno sketch fatto un pò una merda.

Può capitare che qualcosa si può freezare: ad esempio il wiznet w5100 sull’ethernet shield.
A quel punto, l’unica soluzione è resettare.

Il codice da inserire in testa allo sketch è questo:

#include
#include

#define Reset_AVR() wdt_enable(WDTO_30MS); while(1) {}

E invocare, poi, la macro nel punto in cui avete bisogno di resettare l’arduino in questo modo:
Reset_AVR();

Cosa fa di preciso il reset software?
Con reset software si intende invocare il “watchdog” (cane da guardia) interno per almeno 25mili secondi che si occuperà di resettare il program counter (instruction pointer) a 0, pulisce i registri del’IC ed effettua altre operazioni. Questa operazione è teoricamente uguale a quella di premere il tasto reset sulla scheda.

OptiBoot 4.4

Nel precedente articolo vi avevo parlato di come aggiornare le vostre Arduino Duemilanove/Uno al nuovo bootloader OptiBoot 4.4.

Personalmente l’ho fatto sulla mia Luigino328 (clone italiano della Duemilanove) e devo ammettere che mi trovo davvero bene.
Ho più spazio per il codice e la velocità di trasferimento degli sketch sulla scheda è stata aumentata di un bel pò.

Volevo, però, precisare un pò di cose.

In primis la questione dei “fuses”.
Ma cosa sono?
All’intero di questo tipo di chip ci sono oltre alla ram, flash ed eproom anche 3 byte di memoria permanente chiamato “fuses” (in italiano: “fusibili”).
I fuses hanno il compito di descrivere alcune caratteristiche dell’integrato, come: determinare in che modo il chip agisce, se ha un bootloader, velocità del clock e la tensione di lavoro, ecc…
In particolare, quelli che ci interessano in questo momento sono quelli descritti nell’articolo precedente: High Fuse, Low Fuse, Extended Fuse e Lock Bit.
Grosso modo, questi descrivono in che zona della memoria è presente il bootloader.
Questo è estremamente importante in quanto, ad esempio, se settassimo i fuses in modo errato, probabilmente parte del codice verrebbe scritto nell’area di memoria dove risiede il bootloader.

Sono come dei paletti: codice da una parte e bootloader da un’altra.

Il bootloader caricato nella duemilanove era grosso circa 2k, il bootloader OptiBoot 4.4 circa 0.5k: un quarto più piccolo.

Quindi bisogna risettare l’High Fuse in modo tale da descrivere che l’area di memoria dove risiede il nuovo bootloader è più piccola (o più grande) di com’era prima.

Ecco perchè avevo inserito due valori per l’high fuse: uno per il bootloader della duemilanove e l’altro per l’OptiBoot.

Il modo più semplice, come già avevo segnalato, è quello di prendere questi valori direttamente da un file descrittivo all’interno dell’IDE ufficiale.
Mi riferisco in particolare al file: arduino-0023hardwarearduinoboards.txt

Leggendo bene questo file ci accorgiamo, ad esempio, che per la UNO abbiamo questa sezione:

uno.name=Arduino Uno
uno.upload.protocol=stk500
uno.upload.maximum_size=32256
uno.upload.speed=115200
uno.bootloader.low_fuses=0xff
uno.bootloader.high_fuses=0xde
uno.bootloader.extended_fuses=0x05
uno.bootloader.path=optiboot
uno.bootloader.file=optiboot_atmega328.hex
uno.bootloader.unlock_bits=0x3F
uno.bootloader.lock_bits=0x0F
uno.build.mcu=atmega328p
uno.build.f_cpu=16000000L
uno.build.core=arduino

L’ide di arduino viene utilizzata anche per aggiornare i bootloader quindi, AvrDude che si occupa di flashare le schede con i nuovi bootloader, ha bisogno di alcuni parametri come, ad esempio, i fuses!

Quindi, se abbiamo l’esegineza di flashare l’ultimo optiboot, ma non conosciamo i valori dei fuses, li possiamo prendere proprio da questa sezione, ed in particolare: uno.bootloader.high_fuses=0xde

Semplice no?

Ovviamente lo stessissimo discorso vale nel caso in cui volessimo flashare le schede con il vecchio bootloader duemilanove: leggiamo la sezione relativa alle schede duemilanove e cambiamo i fuses proprio così come leggiamo nel file boards.txt

Ultima cosa, come potete vedere leggiamo anche il valore dello uno.upload.speed=115200 di caricamento degli sketch (che con l’optiboot è stato maggiorato), il size massimo degli sketch che in questo caso è uno.upload.maximum_size=32256 e altre cose interessanti…

Il bootloader, di norma, lo trovate sempre all’interno delle cartelle dell’IDE… accertatevi, però, che i paramentri dei fuses e il file HEX (in cui risiede il bootloader) corrispondano a quelli del file boards.txt

La mia luigino328 dopo il flashing del’OptiBoot 4.4:

19112011005