Comunicazione Attiny85 con Arduino

Ciao a tutti, mi sono letto la guida sulla programmazione dell'Attiny85 e ho visto che si può implementare il protocollo USI (che simula l'I2C), avrei bisogno di interfacciare, come slave, l'Attiny all'Arduino. E' possibile (penso di si), qualcuno ha qualche guida o pagina internet da 'sfogliare'?

Grazie mille e BUON NATALE

Non so che guida hai letto, nella mia c'è un capitoletto che spiega con esempio di codice e schema come far comunicare Arduino e Tiny via I2C emulata con USI.

mastraa: Ciao a tutti, mi sono letto la guida sulla programmazione dell'Attiny85 e ho visto che si può implementare il protocollo USI (che simula l'I2C), avrei bisogno di interfacciare, come slave, l'Attiny all'Arduino. E' possibile (penso di si), qualcuno ha qualche guida o pagina internet da 'sfogliare'?

Grazie mille e BUON NATALE

Che guida hai letto? mi puoi dare il link?

Io credo di aver letto proprio la tua guida, sei Leo Miliani giusto? A questo punto ritengo mi manchi qualche pagina nel pdf...o meglio, io non vorrei comunicare via seriale, ma via I2C (USI), sulla guida trovo solo il tutorial per impostarlo come master per una eeprom. Credo non cambi molto, ma prima di mettere le mani preferisco capire bene che devo fare!

Grazie mille

Ho scritto 2 guide, una per le vecchie versioni 002x dell'IDE che però funziona anche per la 1.0: http://www.leonardomiliani.com/2012/guida-agli-attiny-aggiornata/

L'altra per la nuova IDE 1.5, messa online da poche settimane: http://www.leonardomiliani.com/2013/guida-allutilizzo-dei-micro-attiny-con-lide-arduino-1-5-x/

In entrambe le guide c'è il capitolo sull'uso dell'I2C.

Scusa forse sono un po’ duro io a capire :slight_smile: Io nella guida ho trovato l’uso della I2C come master su una eeprom giusto? Io avrei bisogno di usarlo come slave (oltre ovviamente a caricare l’altra library)?

Se l’Attiny deve lavorare come slave usi la TinyWireS. Sull’Arduino non hai di questi problemi, usi la Wire classica.

Per impostare i device come master e slave fai riferimento alla lib Wire:
http://arduino.cc/en/Reference/Wire

Ah ok, mi mancava il passaggio nel quale le due fossero in tutto e per tutto uguali.

Ricapitolando quindi:

Includo le due librerie (Wire e TinyWire)

Quindi nel master Wire.begin() senza indirizzo, nello slave inserico l'indirizzo a 7 bit (quello che voglio io giusto? posso scriverlo in qualsivoglia formato o solo hex?)

Quindi Wire.beginTrasmission(address) nel master per 'chiamare' lo slave e Wire.requestFrom(address, bytes) per chiedere risposta corretto? Quindi Wire.read()...e manipolo il dato... Infine wire.endTrasmission() e chiudo.

Nello slave cosa devo mettere? ...programma... if Wire.available() { Wire.write('qualcosa') } ...programma...

E' corretto? spero di essermi spiegato, il mio problema è come inviare, nel senso che uno slave non l'ho mai programmato

Non devi includere entrambe le lib su entrambi i chip.
Sull’Arduino includi solo la Wire, essa gestisce sia la modalità master che slave. Per inizializzare l’Arduino come Master metti un begin() senza indirizzo.
Nell’Attiny carichi invece la TinyWireS, e la inizializzi con un begin(indirizzo), in modo che si agganci come slave.
A questo punto dall’Arduino per comunicare con lo slave usi beginTransmission(indirizzo), lo stesso indirizzo che hai messo nello slave (è arbitrario, lo scegli te).
Insomma, come hai scritto tu.

Sisi certo, ogni libreria al suo posto! Bene dai, domani se non mi ingolfo al pranzo ci provo. e riguardo bene anche la tua guida perchè oggi mi dava un errore caricando il bootloader a 8Mhz. Funziona anche con la 1.5.5 BETA o solo con la 1.5.4?

Funziona anche con la 1.5.5. :grin:
Anzi ora che ci penso cambio il titolo.

Ok allora avrò sbagliato qualcosa io, dopo riprovo. Nel caso ti romperò ancora ]:)

Con la tua guida non sono riuscito a ottenere nulla con la versione 1.5.x, avevo però la cara vecchia 0022 con la quale riesco a lavorare e sono riuscito a far parlare l’Arduino UNo R3 e il mio AtTiny85.

Di fatto ho selezionato l’indirizzo, inviato la richiesta e attivato una funzione in seguito alla richiesta.
Ora però vorrei fare in modo che lo slave (Tiny) mi inviasse un dato, devo usare TinyWireS.send(x) giusto?

Mentre sul master qualcosa del genere y=Wire.read();

Che tipo di dato deve essere la x? perchè ho problemi nel senso che la y risulta essere sempre -1…
Ho ovviamente inserito dei delay abbastanza ampi per fare in modo che tutte le richieste abbiano successo…

Preciso meglio:
Inizializzazione, invio dati dal master e ricezione da parte dello slave funzionano, infatti il led che accesso a seguito della funzione available() nello slave funziona. (La funzione read l’ho messa esclusivamente per cancellare dal buffer).

Quando però nella funziona vado a chiamare la funzione send(), sempre nel lato slave, credo che qualcosa non funzioni.
Non so se sia un problema di tipo di variabile (è un po’ un mio tallone d’achille perchè con c ho avuto a che fare solo con arduino) oppure qualcosa che non capisco di come vada usata la libreria.
Posto il codice, qualcuno sa darmi una mano?
Sono abbastanza sicuro che il problema sia nel send perchè la funzione wire.available() ritorna un false nel master e infatti sulla seriale non vedo nemmeno ‘leggo…’

MASTER - ArduinoUNO R3

#include <Wire.h>
#define I2C_SLAVE_ADDR 0x04
#define LED 13
int x;

void setup() {
  // put your setup code here, to run once:
Wire.begin();
Serial.begin(9600);
pinMode (LED, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly: 
  Wire.beginTransmission(I2C_SLAVE_ADDR);
  Wire.write(1);
  delay(500);
  if (Wire.available()){
    Serial.print("Leggo: ");
    x=Wire.read();
    Serial.println(x);
  }
  Wire.endTransmission();
  digitalWrite(LED, HIGH);
  
  delay(2000);
  digitalWrite (LED, LOW);
  
  delay(5000);
      
}

SLAVE - AtTiny85

#include <TinyWireS.h>
#define I2C_SLAVE_ADDR 0x04
#define LED 3
int x = 0;
byte y;

void setup() {
  // put your setup code here, to run once:
TinyWireS.begin(I2C_SLAVE_ADDR);
pinMode (LED, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly: 
  if (TinyWireS.available()){
    int a = TinyWireS.receive();
    y = byte(x);
    TinyWireS.send(x);
    digitalWrite (LED, HIGH);
    delay(2000);
    x++;
    digitalWrite (LED, LOW);
      
  }
  delay(1000);
}

A parte che stai mescolando le lib.... sullo slave devi usare la TinyWire*S*, te lo avevo già scritto. ;)

Poi send() vuole un byte, non un int. Quindi devi spezzare il dato in 2 byte. Puoi usare le operazioni sui bit oppure le funzioni di arduino lowByte e highByte (guarda nel Reference per maggiori info).

leo72: A parte che stai mescolando le lib.... sullo slave devi usare la TinyWire*S*, te lo avevo già scritto. ;)

Poi send() vuole un byte, non un int. Quindi devi spezzare il dato in 2 byte. Puoi usare le operazioni sui bit oppure le funzioni di arduino lowByte e highByte (guarda nel Reference per maggiori info).

Adesso riguardo bene, non ho capito però dove sto facendo confusione con le librerie, nello slave c'è la TinyWireS, mentre nel master la Wire... Sui byte credevo che trasformando la x (intero) in byte con la funzione byte() potesse andare, adesso guardo meglio la reference!

mastraa: Sui byte credevo che trasformando la x (intero) in byte con la funzione byte() potesse andare, adesso guardo meglio la reference!

Scusa, se un intero (tipo int) è di DUE bytes ... come pretendi di poterlo trasformare in UN byte ??? Pretendi di versare una bottiglia da due litri d'acqua dentro un contenitore da massimo un litro ... XD

Al limite puoi versare i due litri in DUE contenitori da un litro ... ovvero, con le apposite funzioni, puoi prendere o il byte più significativo o quello meno significativo dell'int e mettere ciascuno in una differente variabile byte ;)

Guglielmo

mastraa:
Adesso riguardo bene, non ho capito però dove sto facendo confusione con le librerie, nello slave c’è la TinyWireS,

Hai ragione, ho sbagliato io. Ho letto male. Scusa :sweat_smile:

Sisi scusate avevo fatto un ragionamento idiota io. Non avevo contato che anche se riempie gli slot di zeri un int è sempre da 16 bit, ma avevo pensato che essendo sicuramente inferiore al 256 si potesse scrivere con un solo byte :grin:

Pardon, grazie mille!!!

mastraa: ... ma avevo pensato che essendo sicuramente inferiore al 256 si potesse scrivere con un solo byte

Ma difatti questo è vero !!! :D

Se il valore del tuo int è compreso tra 0 e 255 allora puoi assegnarlo ad una variabile byte (... utilizzando un cast) poiché, anche se perderai il byte più significativo, esso sarà comunque solo a 0 e quindi non rilevante. ;)

Guglielmo

mastraa: Sisi scusate avevo fatto un ragionamento idiota io. Non avevo contato che anche se riempie gli slot di zeri un int è sempre da 16 bit, ma avevo pensato che essendo sicuramente inferiore al 256 si potesse scrivere con un solo byte :grin:

Pardon, grazie mille!!!

Anche se è meglio evitare questo modo di gestire i dati perché se per caso superassi 255, l'autocasting fatto dal compilatore potrebbe portare risultati inattesi.