Ciao a tutti! Sto ancora lavorando un po' coi bit e in particolare con il bus i2c. Vorrei chiedervi delle conferme su ciò che sto facendo!
Il chip in questione è l'I/O extender MCP23017, e sto provando a farlo funzionare senza appoggiarmi alla libreria di Adafriut (che, come sempre, lavora egregiamente).
Ecco la prima domanda: da dove si comincia? Io ho pensato di cominciare da scrivergli i register 1-6, quelli con, credo, le info essenziali per farlo funzionare. Poi pensavo di andare direattamente sui pin di I/O prima dicendogli input/output, e poi acceso/spento per ciascun pin, non dovendo usare interrupt o altre funzioni.
Pensate possa andar bene come "Modus Operandi"?
Vi allego il primo sketch per il registro 0x05
#include <Wire.h>
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
}
void loop()
{
int x=0;
bitWrite(x, 0, 1);
bitWrite(x, 1, 0);
bitWrite(x, 2, 1);
bitWrite(x, 3, 0);
bitWrite(x, 4, 1); //Scrivo Bit per Bit, non sarà la mossa
bitWrite(x, 5, 0); //più veloce ma è solo per capire
bitWrite(x, 6, 1);
bitWrite(x, 7, 0);
Wire.beginTransmission(5); // transmit to device #4
Wire.write(x); // sends five bytes
Wire.endTransmission(); // stop transmitting
delay(500);
}
Solo una domanda: Per come l'ho inteso, lo sketch di cui sopra invia un byte al dispositivo con indirizzo 5 e Non esegue nessun settaggio delle porte. Corretto?
Cosa intendi per "Non esegue nessun settaggio delle port"??
Il MCP23017 ha diversi registri e si deve studiare il datasheet cosa significano i vari bit nei registri.
Ok, grazie Nid69Ita!! Sapevo che non poteva essere così macchinoso e un trucco ci dovesse essere
Io credo di sì, Inter, prima gli scrivo nel registro cosa si deve aspettare e poi gli setto gli input output e poi proseguo con I/O dei singoli pin.
Domani provo e vi faccio sapere! Per adesso il mio discorso "fila"?
Grazie e buonanotte!!
Si. Ho guardato sia il datasheet che il codice della libreria e ho capito il senso.
Quello che non mi è chiaro e perché nella libreria noto questo or con la costante MCP23017_ADDRESS. Fisicamente, il circuito non ha un range di id dal 0 al 7(i2caddr)?
Nello sketch di cui sopra cosa si esegue nel dettaglio?
#define MCP23017_ADDRESS 0x20
/**
* Writes a given register
*/
void Adafruit_MCP23017::writeRegister(uint8_t regAddr, uint8_t regValue){
// Write the register
Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
wiresend(regAddr);
wiresend(regValue);
Wire.endTransmission();
}
#include <Wire.h>
void setup() //metto tutto dentro al setup così lo fa andare solo una volta,
//ho provato anche col loop ma non cambia nulla
{
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600);
pinMode(13, OUTPUT);
delay(1000); //aspetto 1 secondo
int x=0;
bitWrite(x, 0, 0);
bitWrite(x, 1, 0);
bitWrite(x, 2, 1);
bitWrite(x, 3, 1);
bitWrite(x, 4, 1);
bitWrite(x, 5, 1);
bitWrite(x, 6, 1);
bitWrite(x, 7, 1);
Serial.println(x, BIN);
Wire.beginTransmission(0x05); // I/O Expander config reg. (credo sia unico
//per entrambi i banks
Wire.write(x);
Wire.endTransmission();
Serial.println("Done 1/4");
delay(500);
int y=0;
bitWrite(y, 0, 0);
bitWrite(y, 1, 0);
bitWrite(y, 2, 0);
bitWrite(y, 3, 0);
bitWrite(y, 4, 0);
bitWrite(y, 5, 0);
bitWrite(y, 6, 0);
bitWrite(y, 7, 0);
Serial.println(y, BIN);
Wire.beginTransmission(0x00); // Setto tutto come output prima sul Bank A
Wire.write(y);
Wire.endTransmission();
Serial.println("Done 2/5");
delay(500);
Wire.beginTransmission(0x10); // Poi sul bank B
Wire.write(y);
Wire.endTransmission();
Serial.println("Done 3/5");
delay(500);
byte z=B11111111; //provo col metodo di nic ;)
Serial.println(z, BIN);
Wire.beginTransmission(0x09); // transmit to device #4
Wire.write(z); // sends five bytes
Wire.endTransmission(); // stop transmitting
Serial.println("Done 4/5");
delay(500);
Wire.beginTransmission(0x19); // transmit to device #4
Wire.write(z); // sends five bytes
Wire.endTransmission(); // stop transmitting
Serial.println("Done 5/5");
delay(500);
digitalWrite(13, HIGH);
Serial.println("."); Serial.println("."); Serial.println(".");
}
void loop(){
}
Spero che si capisca dai commenti che ho fatto nel codice. Praticamente ho settato prima il config poi tutto come output e poi tutti i pin a livello alto. Quindi ho connesso un led (con resistenza ) in un pin qualunque ma non si accende... Ho sbagliato qualcosa nel codice?
Ciao Subsea,
io ieri sera ha fottao un Reverse Eng. della libreria Adafriut (che avevo già testato). Quello che posso consigliarti è di guardarla per capire.
Così scopriresti che (almeno per quanto ho capito io) che l'address sulla IC2 è dato dall'OR di 0x20 (B00100000) con l'address configurato sui pin (0-7) . Pertanto secondo me nel Wire.beginTransmission ci va un altro indirizzo.
Una volta avviata la comunicazione devi andare a scrivere neiregistri per settare i pin in gresso o uscita ...
Insomma, non ho provato ma penso che dovresti guardarci.
Ciao inter grazie della risosta, credo di aver capito! Ho confuso l adress dell integrato con gli indirizzi dei registri. Allora la domanda è: come faccio a inserire l'indirizzo di un registro nel wire.write? Domani guardo meglio la libreria e se ho altre domande, come sempre, chiedo!
Ecco come fa la libreria. In poche righe trovi tutte le domande:
/**
* Writes a given register
*/
void Adafruit_MCP23017::writeRegister(uint8_t regAddr, uint8_t regValue){
// Write the register
Wire.beginTransmission(MCP23017_ADDRESS | i2caddr);
wiresend(regAddr);
wiresend(regValue);
Wire.endTransmission();
}
Qui ti fa vedere come indirizzare il dispositivo e come scrivere in un registro. Se hai dubbi chiedi.
Secondo me la libreria e scritta bene e ti stai attrezzando a scoprire la ruota/acqua calda... Io dopo averla studiata ho capito che non vale la pena riscrivere altro codice e mi sono limitato ad aver capito il perché ...
Ok!! Penso di aver capito l'inghippo! Praticamente avevo frainteso l'immagine pag. 7 dello sheet, pensando che ogni registro avesse il suo i2c adress, mentre è l'integrato ad avere indirizzo e per scrivere nei registri devo prima trasmettere il codice del registro e poi il "Data_In". Vi faccio sapere questa sera quando modificherò il codice e farò le prime prove
Ok, mi sembra di avere seguito il codice di LadyAda, ma continua a non funzionare. Posto sotto il code:
#include <Wire.h>
void setup()
{
Wire.begin(); // Comincio il protocollo i2c
}
void loop()
{
Wire.beginTransmission(32); // Metto l'indirizzo 32 (0x20)
byte a=B01000000; // scrivo l'adress come scritto sul datasheet pag. 7 e 8 con l'ultimo bit a 0 per scrivere e non leggere
byte b=B11111100; // procedo con i registri di setting, sempre come riportato a pag. 7 e 17
byte c=B00000000; // poi fisso tutte le porte come output
byte d=B11111111; // e tutte le uscite come HIGH
Wire.write(a); // procedo a scrivere i dati prima citati
Wire.write(b);
Wire.write(0); // è il registro della PortA per in/out, pag. 9 e 12 data, valore in DEC provato anche con 0x00 HEX
Wire.write(c);
Wire.write(16); //come sopra per la PortB, valore in DEC provato anche con 0x10 HEX
Wire.write(c);
Wire.write(9); // è il registro della PortA per High/Low, pag. 9 e 22 data, valore in DEC provato anche con 0x09 HEX
Wire.write(d);
Wire.write(25); //come sopra per la PortB, valore in DEC provato anche con 0x19 HEX
Wire.write(d);
// sends value byte
Wire.endTransmission(); // stop transmitting
delay(500);
}
Credo di non aver commesso errori, ma il LED continua a non accendersi. L'unica differenza col code di LadyAda è che lei ha attuato l'operatore OR sul byte di adress per contemplare anche i casi in cui si usino i registri esterni, che non è il mio caso e ho appunto messo 0. L'unica cosa che non mi è totalmente chiara è l akn bit, che dovrebbe essere dato dal chip (e che forse dovrei leggere?)
Help, non so più dove mettere le mani
P.s. Il fatto è che anche io "credo" di aver capito, ma se poi le cose in pratica non funzionano allora vuol dire che non ho capito un bip :
Sì, il circuito funiona con la libreria. Mmm... ora che me lo fai notare potrebbe essere che chiuda e apra la connessone ogni volta, dalla pag. 7 del datasheet infatti fa vedere l'adress e poi il data in, ma non fa vedere un adress di un altro registro, a casa provo
I pin adress li ho collegati al GND e usato lla fig. 1-2 scrivndo il byte 0100 (che sono fixed bits) 000 (visto che li ho collegati al GND) e 0 visto che sto scrivendo l'indirizzo.
La libreria l'ho letta e capita (credo ), ma vorrei imparare a leggere un datasheet e scrivere il codice "da zero".
Ti faccio sapere tra qualche ora
Scusate per la lunga attesa! Ci sono quasi! O almeno, c'ero... A pranzo ho staccato l'arduino (che inviava i comandi i2c) e l'ho riattaccato dopo una mezzoretta... Morto. Tutto!! L'arduino mi sembra ancora funzionante ma forse lo spunto dei 16 led (uno per uscita) mi ha fritto l'MCP... Mah, quanto odio quando va tutto e poi quando attacchi e stacchi non va più nulla!!
EDIT: Ecco è tornato! Il metodo "lasciare riposare" allora non è valido solo in cucina...