Après avoir effectué un essai concluant, (voir article précédent), je me suis lancé dans la lecture d’une entrée numérique sur le NXT. Le principe reste le même que pour les entrées analogiques.
A la fin de l’article une petite surprise aboutit à ce que je voulais faire avec la carte Arduino: l’utiliser en capteur.
Je vous joins les programmes Arduino et RobotC pour la lecture de l’état d’une entrée numérique.
Code Arduino (version 1.0.3):
// A4 - SDA // A5 - SCL #include byte read_register = 0x00; String valeur; char buffer[32]; byte pin8,pin9,pin10,pin11,pin12; void setup(){ pinMode(8, INPUT); Wire.begin(0x0A); // Adresse carte Arduino Wire.onRequest(requestEvent); // Envoi data Wire.onReceive(receiveI2C); // Reception data } void loop(){ valeur = String(digitalRead(8),DEC); valeur.toCharArray(buffer, 10); Serial.println(pin8); delay(100); } // Demande du NXT la procédure est lancée void receiveI2C(int bytesIn) { read_register = bytesIn; while(1 < Wire.available()) { read_register = Wire.read(); } } // procédure envoie des valeurs ana A0 ou A1 au NXT pour affichage void requestEvent() { if(read_register == 0x01){ Wire.write(buffer); // envoi de la réponse au NXT pour affichage } }
Code RobotC:
#pragma config(Sensor, S1,TIR,sensorI2CCustom) #define ARDUINO_ADDRESS 0x14 // adresse carte Arduino #define ARDUINO_PORT S1 ubyte I2Cmessage[22]; char I2Creply[20]; string str1; string str2; string str3; string strtotal; int valeur = 0; void i2c_read_registers_text(ubyte register_2_read, int message_size, int return_size){ memset(I2Creply, 0, sizeof(I2Creply)); message_size = message_size+3; I2Cmessage[0] = message_size; I2Cmessage[1] = ARDUINO_ADDRESS; I2Cmessage[2] = register_2_read; sendI2CMsg(S1, &I2Cmessage[0], return_size); wait1Msec(20); readI2CReply(ARDUINO_PORT, &I2Creply[0], return_size); int i = 0; while(true){ writeDebugStream("%c", I2Creply[i]); str1 = I2Creply[0]; // Mise en memoire des valeurs pour affichage wait1Msec(50); i++; if(I2Creply[i] == 0){ valeur = atoi(str1); // conversion string vers int avec atoi() nxtDisplayString(2, "Input 8 etat:%2u", valeur); // affichage ecran NXT break; } } writeDebugStreamLine(" "); } task main() { while(true){ i2c_read_registers_text(0x01, 0,1); // Demande etat input 8 wait1Msec(2000); } }
La principale différence se situe, pour le programme Arduino, à lire l’état d’une entrée numérique (0 ou 1). Le code RobotC reste pratiquement identique, il ne traite qu’un seul octet à afficher.
Pour aller plus loin, l’utilisation de la carte Arduino offrant de nombreuses possibilités et l’exploration de l’I2C que j’ai effectuée me permettant d’utiliser celle ci comme capteur ou actionneur, j’ai connecté à l’Arduino un capteur de température DS18S20. Maintenant le NXT est capable de relever la température et dans cet exemple, l’Arduino est utilisé comme capteur.
Schéma:
Code Arduino (version 1.0.3):
// A4 - SDA // A5 - SCL #include <Wire.h> #include <OneWire.h> #include <DallasTemperature.h> #define ONE_WIRE_BUS 9 // 1-wire sur borne 9 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); // adresses des capteurs de temperatures DS18S20 DeviceAddress Temp3 = { 0x10, 0xD2, 0xAD, 0x71, 0x01, 0x08, 0x00, 0x74 }; byte read_register = 0x00; String valeur,valeur1; char buffer[32], buffer1[32]; float temp3; long milliref1; int tempmod; void setup() { Wire.begin(0x0A); // Adresse carte Arduino Wire.onRequest(requestEvent); // Envoi data Wire.onReceive(receiveI2C); // Reception data Serial.begin(9600); sensors.begin(); // activation capteur de température sensors.setResolution(Temp3, 10); delay(1000); } void loop() { sensors.requestTemperatures(); // demande de mesure température temp3 = sensors.getTempC(Temp3); // récupération de la température temp3 = temp3 * 100; tempmod = (int) temp3; // valeur modifiée pour transfert valeur = String(tempmod,DEC); // conversion int en string valeur.toCharArray(buffer, 10); // conversion string en char delay(5000); } // Demande du NXT la procédure est lancée void receiveI2C(int bytesIn) { read_register = bytesIn; while(1 < Wire.available()){ read_register = Wire.read(); } } // procédure envoie de la température pour affichage sur le NXT void requestEvent() { if(read_register == 0x01){ Wire.write(buffer); // envoi de la réponse au NXT pour affichage } }
Code RobotC:
#pragma config(Sensor, S1,TIR,sensorI2CCustom) #define ARDUINO_ADDRESS 0x14 // adresse carte Arduino #define ARDUINO_PORT S1 ubyte I2Cmessage[22]; char I2Creply[20]; string str1; string str2; string str3; string str4; string strtotal; int valeur = 0; float temp; void i2c_read_registers_text(ubyte register_2_read, int message_size, int return_size){ memset(I2Creply, 0, sizeof(I2Creply)); message_size = message_size+3; I2Cmessage[0] = message_size; I2Cmessage[1] = ARDUINO_ADDRESS; I2Cmessage[2] = register_2_read; sendI2CMsg(S1, &I2Cmessage[0], return_size); wait1Msec(20); readI2CReply(ARDUINO_PORT, &I2Creply[0], return_size); int i = 0; while(true){ writeDebugStream("%c", I2Creply[i]); str1 = I2Creply[0]; // Mise en memoire des valeurs pour affichage str2 = I2Creply[1]; // Mise en memoire des valeurs pour affichage str3 = I2Creply[2]; // Mise en memoire des valeurs pour affichage str4 = I2Creply[3]; // Mise en memoire des valeurs pour affichage wait1Msec(50); i++; if(I2Creply[i] == 0){ strtotal = str1 + str2; // Mise en forme pour affichage strtotal = strtotal + str3; // Mise en forme pour affichage strtotal = strtotal + str4; // Mise en forme pour affichage valeur = atoi(strtotal); // conversion string vers int avec atoi() // Convertion int en float fonctionne pour 99C > temperature > 10C temp = valeur; temp = temp / 100; // conversion pour faire apparaitre temperature avec 2 chiffres apres virgules nxtDisplayCenteredBigTextLine(3, "T:%2.2f", temp); // affichage ecran NXT break; } } writeDebugStreamLine(" "); } task main() { while(true){ i2c_read_registers_text(0x01, 0,4); // Demande valeur temperature 4 octets wait1Msec(30000); } }
Le code RobotC fonctionne pour une température comprise entre 10°C et 99°C. Au delà, il y a des problèmes de mise en forme de la température pour affichage sur le NXT. Je ne l’ai pas fait, car je voulais juste voir si ce que je voulais faire avec une carte Arduino et le NXT fonctionnait.
En conclusion, la carte Arduino peut apporter un plus au NXT de par sa facilité de mise en place (utilisation du bus I2C) et de par la multitudes de montages que l’on peut faire avec cette carte.
Héhé : cool ! Bien joué 🙂
Pour l’affichage… ne te prends pas trop la tête avec les décimales tout de même car ce capteur à une précision de +/- 0.5°C ! Quand tu affiche 27.56, il peut faire de 27°C à 28°C en réel !!! Alors, la décimale ne vaut pas grand chose et la seconde décimale encore moins 😉
C’est vraiment cool l’I²C !
Et donc : pourquoi un capteur de température en 1-wire et pas en I²C ? Une raison particulière ou c’est parce que c’est ce que tu avais sous la main ?