|
|
Ligne 27 : |
Ligne 27 : |
| | | |
| ==Esclave (target) i2c== | | ==Esclave (target) i2c== |
− | voici des exemples d'esclaves i2c, avec ou sans notion de registres
| |
− |
| |
− | ===sans registres===
| |
− | On donne les exemples suivant pour qu'un µcontroleur atmegaxxx se comporte comme un esclave i2c (pas de notion de registres)
| |
− | {|
| |
− | |-
| |
− | |
| |
− | <source lang=cpp>
| |
− | // Include the required Wire library for I2C
| |
− | #include <Wire.h>
| |
− |
| |
− | const int8_t i2cAddress = 0x1A;
| |
− | // !!! variable utilisée dans une interruption => volatile
| |
− | volatile uint16_t valPotar;
| |
− |
| |
− | void setup() {
| |
− | // Start the I2C Bus as Slave on address i2cAddress
| |
− | Wire.begin(i2cAddress);
| |
− | // fonction à exécuter lorsqu'on doit envoyer des données au master
| |
− | Wire.onRequest(requestEvent);
| |
− | }
| |
− |
| |
− | void requestEvent()
| |
− | {
| |
− | Wire.write(valPotar>>2);
| |
− | }
| |
− |
| |
− | void loop() {
| |
− | valPotar=analogRead(A0);
| |
− | }
| |
− | </source>
| |
− | ||
| |
− | <source lang=cpp>
| |
− | // Include the required Wire library for I2C
| |
− | #include <Wire.h>
| |
− |
| |
− | const int8_t i2cAddress = 9;
| |
− |
| |
− | void setup() {
| |
− | DDRD=0xFF;
| |
− | // Start the I2C Bus as Slave on address i2cAddress
| |
− | Wire.begin(i2cAddress);
| |
− | // fonction à exécuter lorsque le master nous envoie des données
| |
− | Wire.onReceive(receiveEvent);
| |
− | }
| |
− |
| |
− | void receiveEvent(int nbBytes)
| |
− | {
| |
− | PORTD=Wire.read();
| |
− | }
| |
− |
| |
− |
| |
− | void loop()
| |
− | {
| |
− | }
| |
− |
| |
− | </source>
| |
− | |}
| |
− |
| |
− | ===avec registres===
| |
− |
| |
− | {|
| |
− | |-
| |
− | |
| |
− | <source lang=cpp>
| |
− | // Include the required Wire library for I2C
| |
− | #include <Wire.h>
| |
− |
| |
− | const uint8_t i2cAddress = 9;
| |
− | const uint8_t nbRegistres=6;
| |
− | const uint8_t pinLeds[nbRegistres]={3,5,6,9,10,11};
| |
− | uint8_t registresValue[nbRegistres]={0,0,0,0,0,0};
| |
− |
| |
− | void setup()
| |
− | {
| |
− | for(uint8_t i=0;i<nbRegistres;i++)
| |
− | {
| |
− | pinMode(pinLeds[i],OUTPUT);
| |
− | analogWrite(pinLeds[i],registresValue[i]);
| |
− | }
| |
− | // Start the I2C Bus as Slave on address
| |
− | Wire.begin(i2cAddress);
| |
− | // fonction à exécuter lors de la réception des données envoyées par le master
| |
− | Wire.onReceive(receiveEvent);
| |
− | }
| |
− |
| |
− | void receiveEvent(int nbBytes)
| |
− | {
| |
− | // la 1ère valeur reçue correspond au numéro de registre
| |
− | uint8_t numRegistre=Wire.read();
| |
− | for (int i=0;i<nbBytes-1;i++)
| |
− | {
| |
− | // les valeurs suivantes correspondent aux valeurs des registres
| |
− | uint8_t value=Wire.read();
| |
− | if (numRegistre<nbRegistres)
| |
− | {
| |
− | registresValue[numRegistre]=value;
| |
− | analogWrite(pinLeds[numRegistre],value);
| |
− | }
| |
− | // on passe automatiquement au registre suivant
| |
− | numRegistre++;
| |
− | }
| |
− | }
| |
− |
| |
− | void loop() {
| |
− | }
| |
− | </source>
| |
− | ||
| |
− | <source lang=cpp>
| |
− | // Include the required Wire library for I2C
| |
− | #include <Wire.h>
| |
− |
| |
− | const uint8_t i2cAddress = 0x1A;
| |
− | // variables utilisées dans des interruptions
| |
− | volatile uint8_t numRegistre=0;
| |
− | volatile uint16_t valPotar[4];
| |
− |
| |
− | void setup() {
| |
− | // Start the I2C Bus as Slave on address
| |
− | Wire.begin(i2cAddress);
| |
− | // la transmission commence par un envoi du numéro de registre par le master
| |
− | // on indique la fonction à exécuter pour obtenir le numéro de registre
| |
− | Wire.onReceive(receiveEvent);
| |
− | // fonction à exécuter pour envoyer des données au master
| |
− | Wire.onRequest(requestEvent);
| |
− | }
| |
− |
| |
− | void receiveEvent(int nbBytes)
| |
− | {
| |
− | numRegistre=Wire.read();
| |
− | while(Wire.available()) // slave may send less than requested
| |
− | {
| |
− | Wire.read(); // receive a byte as character
| |
− | }
| |
− | }
| |
− |
| |
− | void requestEvent()
| |
− | {
| |
− | Wire.write(valPotar[numRegistre]>>2);
| |
− | if (numRegistre<4) numRegistre++; else numRegistre=0;
| |
− | }
| |
− |
| |
− | void loop() {
| |
− | for (uint8_t i=0;i<4;i++) valPotar[i]=analogRead(A0+i);
| |
− | _delay_ms(100);
| |
− | }
| |
− | </source>
| |
− | |}
| |
| | | |
| + | [[Cours:InfoS2_tdI2cSlave]] |
| | | |
| ==lecture i2c== | | ==lecture i2c== |
******************************************
*** Apporter la malette d'informatique ***
******************************************
Fiche résumé
Retour à la liste des Tds/Tps
Éléments de correction
simuler avec simulIDE
Pensez à mettre sur la 1ère ligne de votre code :
// Compiler: Avrgcc device: nomDuMicrocontroleur
Asservissement en position du moteur CC
On utilise la maquette avec le moteur à courant continu déjà utilisé : Cours:TPS_2103_tp_regulationVitesse
Le principe pour faire varier la vitesse du moteur est maintenant connu cf sujet
Ecrire un programme qui permet de faire tourner le moteur d'un certain nombre de tours
- on utilise la roue codeuse
- on compte de le nombre d'incréments et donc on obtient la position angulaire du rotor
- on pourra ralentir la vitesse du moteur lorsqu'on s'approche de la consigne (nombre de tours à réaliser)
bus i2c
nous allons raccorder la carte arduino qui pilote le moteur à une seconde carte arduino sur laquelle sera relié un écran lcd en i2c.
Ces cartes seront raccordées ensemble par le bus i2c :
- la "carte arduino écran" sera le master i2c
- la "carte arduino moteur" sera la slave i2c
Esclave (target) i2c
Cours:InfoS2_tdI2cSlave
lecture i2c
le µcontrôleur se comportant en esclave/target i2c ne comportera pas (dans un 1er temps) de registres.
Une lecture sur le bus i2c permettra d'obtenir le nombre de tours effectués par le moteur.
Ecrire les programmes permettant d'afficher sur l'écran lcd le nombre de tours parcouru par le moteur
Remarque :
- aide pour le master :
- on pourra éventuellement faire tourner le moteur à la main pour simplifier
- la valeur sur le bus i2c étant codée sur 8 bits, on sera limité à 255 tours
- vous pourrez modifier vos programmes pour palier ce problème :
- soit en ajoutant la notion de registres
- soit en demandant 2 lectures successives
écriture i2c
lorsqu'on envoie une donnée sur le bus i2c au µcontroleur esclave moteur, cela déclenche une rotation du moteur du nombre de tours correspondant à cette valeur.
Ajouter à votre programme cette possibilité
Remarque :
- vous avez 2 boutons sur votre shield arduino nano, par ex
- l'appui sur l'un des boutons fera tourner le moteur de 2 tours
- l'appui sur l'autre boutons fera tourner le moteur de 10 tours
- vous pourrez éventuellement utiliser les boutons sur l'écran pour ajouter des possibilités (et/ou le joystick)