je rencontre des problèmes avec le bus I2C connecté à deux esclaves PCF8583p en utilisant la bibliothèque PCF8583-h de M PEREZ. Avant d'exposer mon problème, je souhaite préciser
1 avant chaque série de tests, j'exécute un scan I2C pour vérifier la connexion des l'esclaves et leur adresse.
2 j'ai commencé par faire des tests de la bibliothèque avec un seul esclave et un signal PWM. Le fonctionnement était satisfaisant.
Depuis que je fais des tests avec les deux esclaves, le bus I2C ne fonctionne plus ?
le code du test
#include "PCF8583.h"
// déclaration d'une instance de la bibliothèque PCF8583.h pour l'esclave à l'adresse 0x50
// (pin A0 connecté au ground)
PCF8583 anemometre(0x50); // Adresse en 7 bits
// déclaration d'une instance de la bibliothèque PCF8583.h pour l'esclave à l'adresse 0x51
// ((pin A0 connecté au 3,3 V)
PCF8583 pluviometre(0x51); // Adresse en 7 bits
void setup() {
// configure la liaison série pour le terminal de debogue
Serial.begin(115200);
Wire.begin(); // Obligatoire pour initialiser le bus I2C
Wire.setClock(100000); // fixe la fréquence du bus à 100 kHz
// PCF8583 paramètré en compteur d'évènements pour l'anémomètre avec remise à zéro
anemometre.setMode(MODE_EVENT_COUNTER);
anemometre.setCount(0);
// PCF8583 paramètré en compteur d'évènements pour le pluviomètre avec remise à zéro
pluviometre.setMode(MODE_EVENT_COUNTER);
pluviometre.setCount(0);
}
void loop() {
// édition de la valeur du compteur de l'anémomètre à chaque période puis remise à zéro
Serial.print("anemometre : ");
Serial.println(anemometre.getCount());
anemometre.setCount(0);
// délai entre les deux lectures I2C
delay(50);
// édition de la valeur du compteur du pluviomètre à chaque période puis remise à zéro
Serial.print("pluviometre : ");
Serial.println(pluviometre.getCount());
pluviometre.setCount(0);
//une lecture des compeurs toutes les x secondes
delay(1000);
}
trace du moniteur lors de l'exécution
anemometre : E (6300) i2c.master: I2C hardware NACK detected
E (6300) i2c.master: I2C transaction unexpected nack detected
E (6300) i2c.master: s_i2c_synchronous_transaction(924): I2C transaction failed
E (6307) i2c.master: i2c_master_multi_buffer_transmit(1186): I2C transaction failed
E (6314) i2c.master: I2C hardware NACK detected
E (6318) i2c.master: I2C transaction unexpected nack detected
E (6323) i2c.master: s_i2c_synchronous_transaction(924): I2C transaction failed
E (6330) i2c.master: i2c_master_receive(1240) : I2C transaction failed
1666665
puis se répète à l'infini
J'ai essayé de baisser la fréquence du bus à 100 Hz, le résultat est identique.
J'ai ajouté un délai entre les deux lectures de compteur, le résultat est identique
Pour tenter un diagnostic, j'ai écrit un code de dé bogue avec un seul esclave et tout le code dans la fonction SET UP afin de l'exécuter qu'une seule fois.
le code
#include "PCF8583.h"
// déclaration d'une instance de la bibliothèque PCF8583.h pour l'esclave à l'adresse 0x50
// (pin A0 connecté au ground)
PCF8583 anemometre(0x50); // Adresse en 7 bits
void setup() {
// configure la liaison série pour le terminal de debogue
Serial.begin(115200);
Wire.begin(); // Obligatoire pour initialiser le bus I2C
Wire.setClock(100000); // fixe la fréquence du bus à 100 kHz
// PCF8583 paramètré en compteur d'évènements pour l'anémomètre avec remise à zéro
anemometre.setMode(MODE_EVENT_COUNTER);
anemometre.setCount(0);
// édition de la valeur du compteur de l'anémomètre à chaque période puis remise à zéro
Serial.print("anemometre : ");
Serial.println(anemometre.getCount());
anemometre.setCount(0);
}
void loop() {
}
trace du moniteur pour ce code
E (327) i2c.master: i2c_master_receive(1240): I2C transaction failed
E (333) i2c.master: I2C hardware NACK detected
E (337) i2c.master: I2C transaction unexpected nack detected
E (342) i2c.master: s_i2c_synchronous_transaction(924): I2C transaction failed
E (349) i2c.master: i2c_master_multi_buffer_transmit(1186): I2C transaction failed
E (357) i2c.master: I2C hardware NACK detected
E (361) i2c.master: I2C transaction unexpected nack detected
E (366) i2c.master: s_i2c_synchronous_transaction(924): I2C transaction failed
E (373) i2c.master: i2c_master_multi_buffer_transmit(1186): I2C transaction failed
E (380) i2c.master: I2C hardware NACK detected
E (384) i2c.master: I2C transaction unexpected nack detected
E (390) i2c.master: s_i2c_synchronous_transaction(924): I2C transaction failed
E (397) i2c.master: i2c_master_multi_buffer_transmit(1186): I2C transaction failed
E (404) i2c.master: I2C hardware NACK detected
E (408) i2c.master: I2C transaction unexpected nack detected
E (413) i2c.master: s_i2c_synchronous_transaction(924): I2C transaction failed
E (420) i2c.master: i2c_master_receive(1240): I2C transaction failed
E (426) i2c.master: I2C hardware NACK detected
E (430) i2c.master: I2C transaction unexpected nack detected
E (436) i2c.master: s_i2c_synchronous_transaction(924): I2C transaction failed
E (443) i2c.master: i2c_master_multi_buffer_transmit(1186): I2C transaction failed.
J'avais vu la pin A0 et le CI ne fait pas que calendrier.
Mais est-ce qu'il n'y a pas "des choses à faire" ?
Comme désactiver un calendrier par exemple.
merci, voici un résumé qui pourrait être utile à d'autres
codage de l’adresse de l’esclave
Même si l’adresse de l’esclave PCF8583 est codé sur 7 bits ( voir ci aprés), la bibliothèque «PCF8583.h»attend une adresse sur 8 bits0xA0ou 0xA2, parce qu’elle décaledans son codecette adresseà droite de 1 bit pour en extraire l'adresse 7 bits.
Extrait de la datasheet
Bit A0 corresponds to hardware address pin A0. Connecting this pin to VDD or VSS allows the device to have one of two different addresses
// provide device address as a full 8 bit address (like the datasheet)
PCF8583::PCF8583(uint8_t address) {
_address = address >> 1; // convert to 7 bit so Wire doesn't choke
Wire.begin();
}
pour conclure l’utilisation de la bibliothèque n’écessite une adresse d’esclave codé sur 8 bits bien que celle ci dans le PCF8583 soit codé sur 7 bits
Non, et dire cela peut induire des débutants en erreur. Une adresse i2c est sur 8 bits que ce soit 0x50 (0101 0000) ou 0xA0 (1010 0000) c'est 8 bits et la bibliothèque PCF8583 ne déroge pas à cette règle.
Simplement 0xA0 (1010 0000) est l'adresse pour écrire dans le composant (c'est l'adresse par défaut) et 0xA1(1010 0001) l'adresse pour lire dans le composant. Le fabricant du composant donne la possibilité de modifier physiquement le bit 1 pour obtenir 0xA2 (1010 0010) en écriture et 0xA3 (1010 0011) en lecture.
Expliquer pourquoi il y a ce passage à 7 bits (interne à la bibliothèque) serait un peu long ici et sort du cadre d'Arduino qui se réclame d'une utilisation facile pour les débutants. Celui que ça intéresse peut toujours regarder la bibliothèque Arduino wire/utility/twi et sa relation avec les bibliothèques AVR avr/io.h et util/twi.h. Ceci nécessite de connaître l'usage des registres des micros ainsi que la manipulation des bits en C
Cette façon de définir les adresses est celle des Data Sheet des composants que les débutants auront un jour ou l'autre besoin de consulter. Un évitement de cette 'subtilité' d'adressage me parait donc contre productif.
Note: There are both 7 and 8-bit versions of I2C addresses. 7 bits identify the device, and the eighth bit determines if it’s being written to or read from. The Wire library uses 7 bit addresses throughout. If you have a datasheet or sample code that uses 8-bit address, you’ll want to drop the low bit (i.e. shift the value one bit to the right), yielding an address between 0 and 127. :
D'autant que NXP (anciennement Philips) est l'inventeur et le "patron" de l'I2C.
Une seule chose est sûre c'est qu'on envoie 1 octet.
Sûr ? En fait, absolument pas → la norme a été étendue pour augmenter le nombre d'adresses possibles.
Actuellement, vu le peu d'adresses possibles avec 7 bits, les adresses sont plus par fonctions génériques que par références produit ou fabricants.
Si on considère les composants avec le réglage A0, A1, A2, ce n'est plus 7 bits qui sont disponibles pour identifier la famille des composants, mais 4.
Sujet bien complexe, je délègue le travail à la bibliothèque qui gère l'I2C.