Giocando con l'Attiny85

Ok,grazie, sempre gentile.

Faccio riemergere questo topic cercando come al solito aiuto. Vorrei fare delle prove di trasmissione RF con gli ATtiny85 e in questa discussione http://arduino.cc/forum/index.php?topic=80942.0 ho visto che modificando opportunamente la libreria VirtualWire è possibile farlo. Questo comporta il fatto di impostare i fuses per usare il micro con quarzo esterno 16MHz. Ho provato a ricavarmeli con fuse calc http://www.engbedded.com/fusecalc/ ma i valori che trovo sono diversi da quelli contenuti nella board.txt creata dal tipo del link. E' sufficiente che li setto come nella boards.txt e cioè low_fuses=0xFF, high_fuses=0xD7, extended_fuses=0xFF? Mi appello alla vostra saggezza.. Grazie.

E' sufficiente che li setto come nella boards.txt e cioè low_fuses=0xFF, high_fuses=0xD7, extended_fuses=0xFF

Sì, questi vanno bene. Puoi usare per il fuse Alto anche il valore $DF, che a differenza di $D7 non preserva il contenuto della EEPROM durante la flashatura del micro.

Per il fuse Esteso, prova con $FF oppure con il suo complementare $01. Il fuse esteso è un po' particolare, alcuni micro accettano il valore diretto (ossia 0 per 0 e 1 per 1) dei bit oppure il valore inverso (ossia 0 per impostare 1 e viceversa), dipende dal micro. Se programmando i fuse vedi che ti restituisce l'errore, prova l'altro valore.

Grazie Leo!

DevonMiles: Grazie Leo!

Prego ma... funzionano? :sweat_smile:

Intanto sto raccogliendo nozioni, quando metterò in piedi una mezza basettina ti saprò dire. Se ce la faccio in settimana faccio due prove con la breadboard. Tutto nasce dalla richiesta di un mio amico che mi stressa perchè gli costruisca un radiocomando per pilotare la sua macchina del fumo. Ho pensato quindi agli attiny+moduli radio Aurel visto che ne ho una decina. Userei 2 pin in ingresso per 2 canali, 1 in output per il modulo radio tx e un altro output per led di segnalazione trasmissione. Piú o meno stessa cosa per rx con aggiunta di transistor + relè per chiudere il pulsante attivazione fumo.

Alcune cose: 1) tra i pin che userai ti troverai il pin di reset, che è un pin un po' più "debole" degli altri in quanto a segnale elettrico, secondo datasheet. 2) come ricevi i dati? Via seriale? Ricordati che l'Attiny non gestisce la seriale in HW e devi usare la SoftwareSeriale, che però blocca il codice in ricezione. La NewSoftSerial in ricezione NON funziona perché non è compatibile con l'Attiny85.

1) Adesso che mi ci fai pensare, su delle prove che avevo fatto mi ricordo che c' era un pin che sembrava più debole. Grazie di avermelo ricordato. Bhè potrei evitare di usare il pin di RESET tanto nel conto dei pin 2(input)+2(output)+2(alimentazione)=6 pin usati, ne avanzerei ancora 2. Oppure lo potrei usare come input. *** 2) Per ricevere i dati utilizzo un modulino rx radio 433MHz. Vorrei appunto provare la libreria VirtualWire modificata come ha fatto l' utente sul post http://arduino.cc/forum/index.php?topic=80942.0 per vedere se riesco effettivamente a trasmettere e ricevere lo stesso dato. Alla fine del post ha scritto che con 2 Attiny85 la libreria funziona.

*** che scemo nella mia equazione ho dimenticato i due pin del quarzo :grin:

Tieni a mente un altro problema. Per usare il pin di reset devi disattivare questa funzione con i fuse. Ma ciò comporta che dopo la sua disattivazione NON puoi più flashare il micro né ripristinare il reset senza usare un programmatore ad alta tensione (12V). L’operazione non è impossibile (in rete c’è uno schema di un programmatore H/V per ripristini di emergenza di chip briccati) però devi tenerne conto.

Domanda: ma usare un Tiny84 (14 pin)? Avresti 9 linee I/O, tolti i pin dell’alimentazione (2), quelli del quarzo esterno (2) e quello di reset (1). L’ingombro rispetto al Tiny85 sarebbe di poco superiore.

Cavolo sto pin di RESET ora diventa il mio problema ]:) . Per fortuna che me lo hai fatto presente se no chissà quanto tempo ci perdevo! L' idea di usare un 85 era perché li avevo già a disposizione, senza stare a riordinare materiale. Per quello che devo fare mi basta comunque un canale, per cui potrei eliminare proprio il pin di RESET e far fare tutto alla logica RX (vedi schema sotto). Eventualmente se mi dovesse servire un altro canale con qualche trick (tipo doppio click o pressione più lunga del pulsante) potrei spedire un' altra informazione.

START <----------------------------------------------- | | | no | Dato RX ------------------------------------------->| sì | | | no | Sto già sparando il fumo? ------> Spara fumo ----->| | | |sì | Blocca fumo -------------------------------------------->|

Se non hai problemi di implementazione e ti trovi un banale SN7400, 01, 06, 14, usa due porte in serie al segnale e lo amplifichi in tensione e corrente; o al limite usa un TR, tenendo conto che devi invertire poi tu la logica del pin. Se è solo "debole" risolvi senza problemi.

Sì sarebbe sperimentabile anche questa via, ma mi sa che il pin di RESET non lo disabilterò..non vorrei trovarmi incasinato dopo per la riprogrammazione.

Scusami, devo essermi espresso malissimo, sempre che tu abbia risposto a me :) Io NON parlo di disabilitare ma semplicemente di potenziare il pin, e quindi usarlo come tutti gli altri, solo integrando un componente che permetta di superare le limitazioni di questa "debolezza" che ancora non ho capito in cosa consiste, ecco perché non sono sicuro che il mio suggerimento sia idoneo.

menniti: Scusami, devo essermi espresso malissimo, sempre che tu abbia risposto a me :)

No no sei stato chiarissimo, è un metodo da tenere in considerazione solo che Leo ha scritto:

leo72: Tieni a mente un altro problema. Per usare il pin di reset devi disattivare questa funzione con i fuse.

Quindi il dubbio è questo, devo comunque disabilitare il RESET per poter usare questo pin come IN/OUT o posso comunque utilizzarlo con la coscienza di non avere il massimo della potenza?

Vedo di far chiarezza, perché penso di aver capito di cosa stiate parlando entrambi.

1) di default il pin di reset è configurato come RESET per cui NON può essere usato come pin di I/O 2) per poterlo usare come normale pin di I/O bisogna (leggi "SI DEVE") programmare i fuse per disattivare il circuito di reset ed attivare quello di I/O - vedi però punto 4) 3) siccome il pin di reset deve tollerare voltaggi di 12V quando il micro viene programmato ad alto voltaggio, il circuito elettrico interno è più debole di quello presenti sugli altri pin. Il datasheet da pag. 189 mostra infatti che la corrente che può generare o assorbire è inferiore rispetto a quella degli altri pin. 4) una volta programma come I/O, non puoi più inviare nessun tipo di sketch tramite la procedura ISP usando un comune Arduino ma ti serve un programmatore ad alta tensione per azzerare i fuse né puoi più resettare il micro ma devi per forza ogni volta staccare/riattaccare l'alimentazione.

Bene, ora è proprio chiaro. Quindi mi sa che lascio il RESET a fare quello per cui è stato preposto di dafault.

DevonMiles: Bene, ora è proprio chiaro. Quindi mi sa che lascio il RESET a fare quello per cui è stato preposto di dafault.

+1, mi ero incasinato anch'io, sorry.

Riesumo questo post perché forse adesso abbiamo una NewSoftSerial compatibile in ricezione sia sui Tiny85 che sui Tiny84. Allo stato attuale resta per la NewSoftSerial la limitazione della frequenza minima di 8 MHz.

Dunque, è farina del mio sacco al 50% dato che la modifica per il Tiny85 l'avevo già fatta quasi del tutto, mi era mancato il tempo di vedere come fare per i Tiny84, poi ho trovato questo in cui era stata fatta per i Tiny84. Stamani avevo una mezz'oretta per riguardare il codice, e ciò che avevo fatto per il Tiny85 era quasi esatto, poi osservando l'altro codice ho capito come sistemare un paio di cose che mi erano rimaste volanti... et voilà! Ecco cosa fare.

1) aprite il file NewSoftSerial.cpp della NewSoftSerial con un editor di testo 2) cercato intorno alla riga 40 il blocco di codice che inizia con // Abstractions for maximum portability between processors 3) sostituitelo con il seguente:

// Abstractions for maximum portability between processors
// These are macros to associate pins to pin change interrupts
#if !defined(digitalPinToPCICR) // Courtesy Paul Stoffregen
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
#define digitalPinToPCICR(p)    (((p) >= 0 && (p) <= 21) ? (&PCICR) : ((uint8_t *)NULL))
#define digitalPinToPCICRbit(p) (((p) <= 7) ? 2 : (((p) <= 13) ? 0 : 1))
#define digitalPinToPCMSK(p)    (((p) <= 7) ? (&PCMSK2) : (((p) <= 13) ? (&PCMSK0) : (((p) <= 21) ? (&PCMSK1) : ((uint8_t *)NULL))))
#define digitalPinToPCMSKbit(p) (((p) <= 7) ? (p) : (((p) <= 13) ? ((p) - 8) : ((p) - 14)))
#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || (__AVR_ATtiny84__)
#define digitalPinToPCICR(p)    (((p) >= 0 && (p) <= 10) ? (&GIMSK) : ((uint8_t *)NULL))
#define digitalPinToPCICRbit(p) (((p) <= 2) ? 5 : 4)
#define digitalPinToPCMSK(p)    (((p) <= 2) ? (&PCMSK1) : (((p) <= 10) ? (&PCMSK0) : ((uint8_t *)NULL)))
#define digitalPinToPCMSKbit(p) (((p) <= 2) ? (p) : (((p) - 10) * -1))
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || (__AVR_ATtiny85__)
#define digitalPinToPCICR(p)    (((p) >= 0 && (p) <= 5) ? (&GIMSK) : ((uint8_t *)NULL))
#define digitalPinToPCICRbit(p) 5
#define digitalPinToPCMSK(p)    (((p) >= 0 && (p) <= 5) ? (&PCMSK) : ((uint8_t *)NULL))
#define digitalPinToPCMSKbit(p) (p)
#else
#define digitalPinToPCICR(p)    ((uint8_t *)NULL)
#define digitalPinToPCICRbit(p) 0
#define digitalPinToPCMSK(p)    ((uint8_t *)NULL)
#define digitalPinToPCMSKbit(p) 0
#endif
#endif

Adesso compilate e provate perché.... non ho avuto tempo di verificare che quello per il Tiny85 funzioni al 100%. Io ho usato una versione modificata del BlinkWithoutDelay mettendo un serial.available() per controllare se ci sono dei byte in arrivo e non mi ha bloccato l'esecuzione, con il led che continua a blinkare. Stasera faccio delle prove di trasmissione reale, se qualcun altro vuol farle al mio post ben venga.

Ecco il codice di test che ho provato ad uploader:

#include 
NewSoftSerial mySerial(0, 1);
const int ledPin =  3;      // the number of the LED pin
int ledState = LOW;           
long previousMillis = 0;      
long interval = 1000;      

void setup() {
  pinMode(ledPin, OUTPUT);      
  mySerial.begin(9600);
}

void loop()
{
  unsigned long currentMillis = millis();
  if (mySerial.available()) {
      for (byte i=0; i<3; i++) {
          digitalWrite(ledPin, HIGH);
          delay(250);
          digitalWrite(ledPin, LOW);
          delay(250);
      }
  }
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;   
    ledState^=1;
    digitalWrite(ledPin, ledState);
  }
}

Leo, ma queste librerie non hanno una collocazione, non potresti fare opera pia e metterla a disposizione su quel sito (p.es.) da dove scarichiamo il core dei tiny? Così la scarichiamo e basta.
Mi confermi che (salvo ulteriore test) questa libreria ora funziona, nel senso che non si blocca più in rx (mi pare fosse lì l’inghippo) ma continua ad avere il limite che a 1MHz (o comunque <8MHz) non funziona?

menniti:
Leo, ma queste librerie non hanno una collocazione

In che senso? Non capisco…

, non potresti fare opera pia e metterla a disposizione su quel sito (p.es.) da dove scarichiamo il core dei tiny? Così la scarichiamo e basta.

Ma al sito del core Tiny non ho accesso.

Mi confermi che (salvo ulteriore test) questa libreria ora funziona, nel senso che non si blocca più in rx (mi pare fosse lì l’inghippo) ma continua ad avere il limite che a 1MHz (o comunque <8MHz) non funziona?

A me non si bloccava, però devo sperimentarla per bene con una trasmissione reale. Resta il limite degli 8 MHz ma questo è un limite dato dal fatto che la seriale ha dei tempi da rispettare e l’implementazione, essendo SW, non può essere mai veloce come una seriale HW per cui hai una frequenza minima. Modificarla per farla andare con chip ad 1 MHz non è un problema, ma poi i tempi ricadono in un intervallo dove i valori errati sono molto alti, ergo diventa inusabile.