Bus I2C, liaison NXT carte Arduino, partie 2.

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.

Image de prévisualisation YouTube

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.

Une réflexion sur « Bus I2C, liaison NXT carte Arduino, partie 2. »

  1. 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 ?

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *