Communication capteur de température Arduino protocole RS 232 C

Bonjour tout le monde,

Je fais ce post suite à un projet ayant pour but de faire communiquer une sonde de température avec une carte Arduino Uno grâce à un protocole RS 232.

Ma communication parait établie sauf que la réponse de la sonde de température n’est pas celle prévue par la documentation mais une réponse complètement loufoque.
De plus lorsque j’émule la liaison série grâce à Hyperterminal relié à l’arduino je peux voir que les bonnes instructions sont passées en écriture et les bonnes données en lecture.
J’ai aussi transmis l’instruction à la sonde via Hyperterminal et j’ai la aussi la bonne réponse…

Je vous transmets également mon code dans l’espoir que quelqu’un puisse m’aider

Un grand merci pour toutes tentatives de réponses

PS : Dans le code se trouve aussi des instructions afin d’afficher le résultat de la comm sur un écran ne soyez pas surpris :slight_smile:

//Created August 2020
//author JNU
//http://www.arduino.cc

#include <ctype.h>
#include <LiquidCrystal.h>

#define bit9600Delay 100  
#define halfBit9600Delay 50
#define bit4800Delay 188
#define halfBit4800Delay 94
#define RS 11
#define enable 10
#define d4  5  
#define d5  4
#define d6  3
#define d7  2  


LiquidCrystal lcd(RS,enable,d4,d5,d6,d7);

byte rx = 6;
byte tx = 7;
byte SWval;
char message[6]="#01VC"; // 01 est l'adresse VC la commande de lecture de température

void setup() {
  lcd.begin(16,2);
  lcd.clear();
 lcd.print("couc");
  Serial.begin(9600);
  pinMode(rx,INPUT);
  pinMode(tx,OUTPUT);
  digitalWrite(tx,HIGH);
  delay(2);
  digitalWrite(13,HIGH); //turn on debugging LED
  for (int i=0; i<6;i++ ) {
    SWprint(message[i]);
  }
 // SWprint('h');  //debugging hello
 // SWprint('i');
 // SWprint('n'); 
  SWprint(13);//carriage return
  SWprint(10);// Line feed 
 }

void SWprint(int data)
{
  byte mask;
  //startbit
  digitalWrite(tx,LOW);
  delayMicroseconds(bit9600Delay);
  for (mask = 0x01; mask>0; mask <<= 1) {
   // int a=data & mask;
   // Serial.println(a);
    if (data & mask){ // choose bit
     digitalWrite(tx,HIGH); // send 1
    }
    else{
     digitalWrite(tx,LOW); // send 0
    }
    delayMicroseconds(bit9600Delay);
  }
  //stop bit
  digitalWrite(tx, HIGH);
  delayMicroseconds(bit9600Delay);
}

int SWread()
{
  byte val = 0;
  while (digitalRead(rx)); // tant que c 'est rx=high
  //wait for start bit
  if (digitalRead(rx) == LOW) {
    delayMicroseconds(halfBit9600Delay);
    for (int offset = 0; offset < 8; offset++) { // sert a lire les bits de droite a gauche
     delayMicroseconds(bit9600Delay);
     val |= digitalRead(rx) << offset; // val = val ou digitalread(rx) val prend la valeur tapée au clavier
    }
    //wait for stop bit + extra
    delayMicroseconds(bit9600Delay);
    delayMicroseconds(bit9600Delay);
    return val;
  }
}

int rep[13];
int j=0;
int k=0;
String mess;

void loop() {
    if (j<13) {
      SWval=SWread();
      for (int k=0;k<12;k++) {
        rep[k]=SWread();
        mess=mess +String(rep[k]);
      }//for   
      Serial.print("Température : ");
      Serial.println((SWval)); 
      j++;
    lcd.print(mess);  
    }//if  
  //SWprint(toupper(SWval)); // change en majuscule
    
}

essai_projet_irtd.ino (2.33 KB)

Bonjour,

Pourquoi tu n'utilises pas SoftwareSerial au lieu d'essayer de lire bit par bit?

Mets ton code entre balises de code

Il n'y a pas de raison particulière j'ai trouvé ce code qui avait l'air de marcher donc je l'ai utilisé.
Je l'ai rajouté :slight_smile:

En survolant le code, je pense qu'il devrait fonctionner sauf qu'à la fin de la lecture de l'octet le temps d'attente parait trop long (mais je ne sais pas si c'est le problème).

    //wait for stop bit + extra
    delayMicroseconds(bit9600Delay);
    delayMicroseconds(bit9600Delay);

Pour un stop bit ce devrait être

    //wait for stop bit + extra
    delayMicroseconds(halfBit9600Delay);
    delayMicroseconds(bit9600Delay);

Mais je te conseille plutôt d'utiliser SerialSoftware qui doit être plus fiable.

ça marche merci j'essaye ça

Mais justement comment savoir quel délai faut-il ?

Autre chose

ici

      mess = mess + String(rep[k]);

Tu ajoutes la chaine de caractère représentant l'entier rep[k]. Est ce vraiment ce que tu veux faire?

Ce ne serait pas plutôt l'ajout du caractère rep[k]?
Dans ce cas ce serait:

      mess=mess+(char)rep[k];

La String mess ne sert à rien. Il suffirait de définir rep comme tableau de caractères et tu as directement ton message.

Bonjour
Un lien vers la, sonde de température ?

Si cette dernière communique en 'RS232 vrai' quelque chose a-t-il été fait pour adapter les niveaux de tensions ? circuit intégré MAX232 ou équivalent ?

al1fch:
Bonjour
Un lien vers la, sonde de température ?
Si cette dernière communique en RS232 'vrai' quelque chose a été fait pour tenir compte des niveaux de tensions ?

Oui j'utilise un shield RS 232 pour tenir compte des tensions voir le lien : https://asset.conrad.com/media10/isa/160267/c1/-/fr/1310314_BB_00_FB/image.jpg?x=400&y=400

C'est une sonde de température IRTD-400 le constructeur est Kaye.
je vous mets les parties utiles de la doc :

Example 1: Read value in °C.
To read the temperature in °C (VC for Value Celsius) from Probe
01, enter:
#01VC
The Intelligent RTD Probe responds with a value, such as:
VC = +22.388
This indicates that the sensor temperature is 22.388°C.
Note: The response to all Data Read commands is a 12-
character string. The first 3 characters are the two upper
case letters of the command plus an equal sign (=). The
remaining 9 characters indicate the value. A blank is a
character

AD: Read Probe Address
Format: #A1A2AD
Where:

= command lead-in

A1A2 = probe address 01-99
AD = command for reading the probe address
For example, to read (verify) the address at Probe 04, enter:
#04AD
The RTD Intelligent Probe responds with a value, such as:
AD = 04

VC: Read Sensor Value °C
Format: #A1A2VC
Where:

= command lead-in

A1A2 = probe address 01-99
VC = command for reading the sensor Value in °C
For example, to read the sensor Value in °C at Probe 35, enter:
#35VC
The RTD Intelligent Probe responds with a value, such as:
VC = +320.138

Setting the RS-232C Interface
If you are using a CRT or VDU, follow the manufacturer's
instructions to set the baud rate to 9600, the parity to N (none)
and the word length to 8 bits. Make sure that a carriage return
(CR) character is sent out from your terminal every time you
press RETURN or ENTER.
To test the communications link, enter the command:
#01VC
The temperature of the probe will be displayed on your screen in
degrees Celsius. (Commands are explained in detail in Chapter
4.)

kamill:
Autre chose

ici

      mess = mess + String(rep[k]);

Tu ajoutes la chaine de caractère représentant l'entier rep[k]. Est ce vraiment ce que tu veux faire?

Ce ne serait pas plutôt l'ajout du caractère rep[k]?
Dans ce cas ce serait:

      mess=mess+(char)rep[k];

La String mess ne sert à rien. Il suffirait de définir rep comme tableau de caractères et tu as directement ton message.

Je pensais le passage en string nécessaire afin de pouvoir les concaténer

Dans les deux cas la conversion peut être implicite (la conversion en String est automatique) ou explicite.
La différence est que si tu reçois le caractère '1' par exemple, dans le premier cas ça va te donner la chaine "49", dans le deuxième cas ça te donne la chaine "1".

D'après la doc de ton capteur c'est bien mess=mess+(char)rep[k]; qu'il faut faire (tu pourrais aussi faire mess=mess+String((char)rep[k]);

De toutes façons utiliser String sur un ARDUINO, c'est jouer avec le feu.

bien compris merci