Table des matières
TP Projet Objets connectés: Bus I2C sur Arduino
cours bus de com cours_bus_terrain_livret_portrait.pdf
Objectifs
- Comprendre les chronogrammes des transactions I2C
- Comprendre l'énumération des composants sur un bus I2C
- Comprendre les notions d'adressage, (sur le bus et dans le composant)
Carte d'extension pour le TP
Schéma de la carte principale:
Schéma de la carte amovible:
fichiers eagle: https://bvdp.inetdoc.net/files/iut/td2_capt/carte-arduino-8574-12.sch et https://bvdp.inetdoc.net/files/iut/td2_capt/carte-arduino-8574-12.brd
La carte d'extension utilisée pour ce TD/TP permet de connecter plusieurs périphériques à l'Arduino. Elle dispose:
- de deux port E/S sur bus I2C dont un est piloté par des interrupteurs et l'autre pilote des leds. Le composant utilisé est un circuit PCF 8574A, dont la documentation est à l'adresse: https://bvdp.inetdoc.net/files/iut/td2_capt/pcf8574.pdf . L'adresse de chacun de ces composants est en partie configurable via 3 cavaliers dont la fermeture revient à imposer un 0 logique sur le bit correspondant.
- d'une EEPROM SPI AT25040 (documentation: http://www.atmel.com/images/doc3348.pdf ) qui sera utilisée dans un prochain TP concernant le bus SPI: https://bvdp.inetdoc.net/wiki/doku.php?id=tdethindus1
- d'une led infrarouge pour assurer la fonction de télécommande
- d'un module amovible assurant la fonction de RTC via le composant DS1307 (documentation: http://datasheets.maximintegrated.com/en/ds/DS1307.pdf ) et EEPROM I2C AT24C32N (documentation: http://www.atmel.com/images/doc0336.pdf ). Une sonde de températeur DS18B20 sur bus OneWire est également présente (documentation: http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf ) et sera utilisée dans un prochain TP concernant le bus OneWire: https://bvdp.inetdoc.net/wiki/doku.php?id=tp_one_wire
Exercice 1 : Détermination des adresses des esclaves I2C
Lancer l'IDE Arduino, brancher la carte au port USB du PC et cliquer sur Outils→Port. Sélectionner le dernier de la liste et noter son numéro.
1.1: Programmer l'Arduino avec le sketch suivant et ouvrir la console arduino en 9600 8N1. (sketch récupéré sur http://playground.arduino.cc/Main/I2cScanner )
- i2c_scanner.ino
// -------------------------------------- // i2c_scanner // // Version 1 // This program (or code that looks like it) // can be found in many places. // For example on the Arduino.cc forum. // The original author is not know. // Version 2, Juni 2012, Using Arduino 1.0.1 // Adapted to be as simple as possible by Arduino.cc user Krodal // Version 3, Feb 26 2013 // V3 by louarnold // Version 4, March 3, 2013, Using Arduino 1.0.3 // by Arduino.cc user Krodal. // Changes by louarnold removed. // Scanning addresses changed from 0...127 to 1...119, // according to the i2c scanner by Nick Gammon // http://www.gammon.com.au/forum/?id=10896 // Version 5, March 28, 2013 // As version 4, but address scans now to 127. // A sensor seems to use address 120. // // // This sketch tests the standard 7-bit addresses // Devices with higher bit address might not be seen properly. // #include <Wire.h> void setup() { Wire.begin(); Serial.begin(9600); Serial.println("\nI2C Scanner"); } void loop() { byte error, address; int nDevices; Serial.println("Scanning..."); nDevices = 0; for(address = 1; address < 127; address++ ) { // The i2c_scanner uses the return value of // the Write.endTransmisstion to see if // a device did acknowledge to the address. Wire.beginTransmission(address); error = Wire.endTransmission(); if (error == 0) { Serial.print("I2C device found at address 0x"); if (address<16) Serial.print("0"); Serial.print(address,HEX); Serial.println(" !"); nDevices++; } else if (error==4) { Serial.print("Unknow error at address 0x"); if (address<16) Serial.print("0"); Serial.println(address,HEX); } } if (nDevices == 0) Serial.println("No I2C devices found\n"); else Serial.println("done\n"); delay(5000); // wait 5 seconds for next scan }
Vous devriez obtenir un affichage ressemblant à:
1.2: Débrancher et rebrancher le module amovible RTC et interpréter le résultat. Jouez sur les cavaliers permettant de configurer l'adresse matérielle des 8574. En déduire l'adresse de tous les composants que vous allez utiliser.
Exercice 2 : Utilisation du PCF8574
2.1: Positionner les cavaliers pour attribuer l'adresse 0x3e au composant 8574_A et 0x3f au composant 8574_B. Pour cela vous devez déterminer la valeur des 3 bits de poids faible des adresses et les régler, un cavalier ouvert permet de régler un bit à 1 et un cavalier fermé à 0. Vérifier les adresses à l'aide du programme de l'exercice 1 puis programmer l'Arduino avec le sketch suivant:
- i2c_8574_0x12.ino
#include <Wire.h> //adresses codées sur 7bits #define SLAVE_ADDR_8574_A 0x3e #define SLAVE_ADDR_8574_B 0x3f ////////////////////////////////////////// char readPort8574(char addr, char * ptr_value) /*addr, l'adresse du PCF8574 ptr_value, pointeur pour renvoyer la valeur lue sur le port retourne -1 si échec 0 sinon*/ { Wire.requestFrom((byte)addr, (byte)1);// demande la lecture d'1 octet depuis l'adresse du pérpiphérique if (Wire.available()==1) //si l'octet est disponible { (* ptr_value) = Wire.read(); // lire l'octet return 0; } else { (* ptr_value) =0; //valeur par défaut si le composant n'a pas acquité return -1; } } ////////////////////////////////////////// char writePort8574(char addr, char value) /*addr, l'adresse du PCF8574 value, la valeur à écrire sur le port retourne -1 si échec 0 sinon */ { Wire.beginTransmission((byte)addr);//démarre la transmission avec l'adresse du pérpiphérique Wire.write((byte)value); //envoie la donnée if (Wire.endTransmission()==0) //stoppe la transmission return 0; else return -1; } ////////////////////////////////////////// void setup() { Serial.begin(9600); // start serial port at 9600 bps: Serial.print("Bonjour"); Wire.begin(); // joindre le bus i2c en tant que maître writePort8574( SLAVE_ADDR_8574_B , 0xff); //configure le composant B en entrée } ////////////////////////////////////////// ////////////////////////////////////////// void loop() { writePort8574(SLAVE_ADDR_8574_A, 0x12); delay(1000); writePort8574(SLAVE_ADDR_8574_A, ~0x12); delay(1000); }
2.2: Relever les chronogrammes des signaux SDA et SCL. Faites une capture d'écran et insérez-la dans le bloc note. Faire apparaître sur les chronogrammes relevés les conditions de start et stop et les différentes phases (adressage et échange de données) ainsi que les bits transmis en indiquant quel composant pilote le bus à chaque instant. Déterminer la fréquence du signal d'horloge du bus I2C.
2.3: Retirer le cavalier A0 du PCF8574_A et relever à nouveau les chronogrammes des signaux SDA et SCL. Faites une capture d'écran et insérez-la dans le bloc note. Quelles sont les différences avec 2.2. Pourquoi ?
2.4: Remettre le cavalier A0 du PCF8574_A et modifier le programme pour réaliser la recopie du port d'entrée PCF8574_B vers le port de sortie PCF8574_A toutes les 100ms. Dans le cas où la lecture n'est pas possible (la fonction readPort8574() retourne -1), il ne faudra pas appeler l'écriture sur le port de sortie. Programmer l'Arduino et vérifier que les interrupteurs permettent de piloter les LEDs.
Dans le cas où vous n'arriveriez pas à modifier le programme par vous même vous pourrez programmer l'Arduino directement en faisant:
Si vous travaillez sous Windows (c'est dommage pour vous):
- Dans Arduino, relever le nom du port série utilisé par la carte (Menu Outils→Port Série)
- Taper sur “touche Windows”+R puis taper “cmd” et entrée.
- Copier coller dans la console Windows en remplaçant COM6 par le nom du port série relevé précédemment:
set PORT="COM6"
- Copier coller la ligne suivante dans la console Windows:
C:\applis\arduino-1.8.7\hardware\tools\avr/bin/avrdude -CC:\applis\arduino-1.8.7\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -P%PORT% -b115200 -D -Uflash:w:S:\commun\2EN\Projet_IOT\demo_8574_IUT.ino.hex:i
Si vous travaillez sous Linux (vous avez bien raison):
* Copier coller la ligne suivante dans la console Linux:
cd ~/ && wget https://bvdp.inetdoc.net/files/iut/tpi2cobjetsconnectes/demo_8574_IUT.ino.hex && /usr/local/share/arduino-1.8.9/hardware/tools/avr/bin/avrdude -C/usr/local/share/arduino-1.8.9/hardware/tools/avr/etc/avrdude.conf -v -patmega328p -carduino -P/dev/ttyACM0 -b115200 -D -Uflash:w:demo_8574_IUT.ino.hex:i
ou
cd ~/ && wget https://bvdp.inetdoc.net/files/iut/tpi2cobjetsconnectes/demo_8574_IUT.ino.hex && /usr/local/share/arduino-1.8.9/hardware/tools/avr/bin/avrdude -C/usr/local/share/arduino-1.8.9/hardware/tools/avr/etc/avrdude.conf -v -patmega328p -carduino -P/dev/ttyUSB0 -b115200 -D -Uflash:w:demo_8574_IUT.ino.hex:i
2.5: Positionner les interrupteurs du ports d'entrée dans une configuration de votre choix (mais tous les bits ne doivent pas être au même état) et relever les chronogrammes des signaux SDA et SCL. Faites une capture d'écran et insérez-la dans le bloc note. Identifier sur le chronogramme les différentes transactions I2C en indiquant leurs directions. Vérifier que les chronogrammes changent en fonction de la position des interrupteurs.
Exercice 3 : Utilisation du DS1307
3.1: Programmez l'Arduino avec le programme fourni en copiant collant la ligne suivante:
Si vous travaillez sous Windows (c'est dommage pour vous):
C:\applis\arduino-1.8.7\hardware\tools\avr/bin/avrdude -CC:\applis\arduino-1.8.7\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -carduino -P%PORT% -b115200 -D -Uflash:w:S:\commun\2EN\Projet_IOT\demo_DS1307_IUT.ino.hex:i
Si vous travaillez sous Linux (vous avez bien raison):
* Copier coller la ligne suivante dans la console Linux:
cd ~/ && wget https://bvdp.inetdoc.net/files/iut/tpi2cobjetsconnectes/demo_DS1307_IUT.ino.hex && /usr/local/share/arduino-1.8.9/hardware/tools/avr/bin/avrdude -C/usr/local/share/arduino-1.8.9/hardware/tools/avr/etc/avrdude.conf -v -patmega328p -carduino -P/dev/ttyUSB0 -b115200 -D -Uflash:w:demo_DS1307_IUT.ino.hex:i
ou
cd ~/ && wget https://bvdp.inetdoc.net/files/iut/tpi2cobjetsconnectes/demo_DS1307_IUT.ino.hex && /usr/local/share/arduino-1.8.9/hardware/tools/avr/bin/avrdude -C/usr/local/share/arduino-1.8.9/hardware/tools/avr/etc/avrdude.conf -v -patmega328p -carduino -P/dev/ttyACM0 -b115200 -D -Uflash:w:demo_DS1307_IUT.ino.hex:i
3.2: Le module RTC étant connecté à la carte, relever les chronogrammes des signaux SDA et SCL. Faites une capture d'écran et insérez-la dans le bloc note. Interpréter les chronogrammes. Identifier sur le chronogramme les différentes transactions I2C en indiquant leurs directions et interpréter les chronogrammes.
3.3: Déconnecter le module RTC et relever les chronogrammes des signaux SDA et SCL. Faites une capture d'écran et insérez-la dans le bloc note. Interpréter les chronogrammes.