Go Down

Topic: Afficher variable sur LCD i2c (Read 2 times) previous topic - next topic

Mike74

Bonjour à tous, j'essaie de faire fonctionner ce petit programme basé sur un capteur de température LM34, mais impossible d'afficher les valeurs, encore ce fichu problème de conversion en chaine de caractères, voici le programme, merci pour votre aide :

Code: [Select]
nt sensorPin = A1;
float sensor_reading = 0.0;
float vref = 1.084;
int fahrenheit = 0;
char centigrade = 4;

void setup()
{
Serial.begin(19200);
  ELCD_initialize();
  delay(200);
  ELCD_Clear_LCD();
  ELCD_Cursor_Position(0, 0);
  ELCD_put_str("Temp:");
 
}

void loop()                                                      // run over and over again
{

sensor_reading = analogRead(sensorPin);
fahrenheit = (100.0 * sensor_reading * vref)/1023;
centigrade = (((5.0/9.0))*(fahrenheit-32.0));
ELCD_Cursor_Position(7, 0);                                                           
ELCD_put_chr(centigrade);
delay(1000);
}

/* Initialize l'afficheur lcd */
void ELCD_initialize(){
  Serial.print(0xA0, BYTE);
}

/* Cache le curseur */
void ELCD_Cursor_OFF(){
  Serial.print(0xA3, BYTE);
  Serial.print(0x0C, BYTE);
}

/* Affiche le curseur */
void ELCD_Cursor_ON(){
  Serial.print(0xA3, BYTE);
  Serial.print(0x0E, BYTE); 
}

/* Efface l'écran et place le curseur à (0, 0) */
void ELCD_Clear_LCD(){
  Serial.print(0xA3, BYTE);
  Serial.print(0x01, BYTE);
}

/* Place le curseur à la position (x, y) */
void ELCD_Cursor_Position(int x, int y){
  Serial.print(0xA1, BYTE);
  Serial.print(x, BYTE);
  Serial.print(y, BYTE); 
}

/* Affiche une chaine de caractéres (char[] terminé par \0) sur l'afficheur */
void ELCD_put_str(char *str){
  Serial.print(0xA2, BYTE);
  while(*str)
    Serial.print(*str++);
  Serial.print(0, BYTE); 
}

/* Affiche un caratéres ASCII sur l'afficheur (caractéres spéciaux aux LCD non pris en charge) */
void ELCD_put_chr(char ch){
  Serial.print(0xA2, BYTE);
  Serial.print(ch);
  Serial.print(0, BYTE); 
}

/* Définit un caractére personalisé à l'index défini (de 8 à 15) suivant le tableau newChar[],
   de structure identique à celui utilisé par la fonction createChar de la lib LiquidCrystal.
   Si showAfter = 1 le caractére sera afficher aprés la création, sinon il ne sera afficher qu'aprés un ELCD_put_chr(index) */
void ELCD_create_char(byte index, byte newChar[], byte showAfter) {
  if(showAfter)
    Serial.print(0xA4, BYTE);
  else
    Serial.print(0xA5, BYTE);
  Serial.print(index, BYTE);
  Serial.print(newChar[0] & 0x1F, BYTE);
  Serial.print(newChar[1] & 0x1F, BYTE);
  Serial.print(newChar[2] & 0x1F, BYTE);
  Serial.print(newChar[3] & 0x1F, BYTE);
  Serial.print(newChar[4] & 0x1F, BYTE);
  Serial.print(newChar[5] & 0x1F, BYTE);
  Serial.print(newChar[6] & 0x1F, BYTE);
  Serial.print(newChar[7] & 0x1F, BYTE);
}           



=(

B@tto

Oué mais ça affiche quelque chose ? Une valeur eronnée ?
Blog électronique : http://battomicro.wordpress.com/
Photographie : www.interactive-celebration.fr

skizoh

bonjour, ton problème c'est que sur un LCD tu peut afficher que du ascii donc tu doit faire ça:


Code: [Select]

int unite,dizaine,centaine,virgule;  //pour décomposé
char temp[4];
sensor_reading = analogRead(sensorPin);
fahrenheit = (100.0 * sensor_reading * vref)/1023;
centigrade = (((5.0/9.0))*(fahrenheit-32.0));
ELCD_Cursor_Position(7, 0);
centaine= centigrade/100;
dizaine=(centigrade/10)-(centaine*10);
unite =centigrade-(centaine*100)-(dizaine*10);
virgule=(centigrade*10)-(centaine*1000)-(dizaine*100)-(unite*10); // préscision a 1 chiffre apres la virgule mais tu peut continuer pour faire mieux

temp[0]=centaine+0x48;
temp[1]=dizaine+0x48; //0x48 = 0 en ASCII (int<10) + 0 en ASCII = int<10 en ASCII
temp[2]=unite+0x48;
temp[3]=virgule+0x48;

// et en string
//temp=(centaine+0x48)+(dizaine+0x48)+(unite+0x48)+(virgule+0x48);

                                                           
ELCD_put_chr(temp);
delay(1000);



voila, je sais pas si sa te convient..

Skizo !
Un tien vaux mieux que deux tu l'auras !

barbudor

et itoa() te le fait tout seul


Sinon, il aurait été plus malin de faire ta lib ELCD comme LiquidCrystal, en dérivant de la classe Print ce qui te permet d'hériter de la classe print toutes les fonctions .print() et .println() existante.

L'avantage est de disposer d'une lib interchangeable avec LiquidCrystal, LiquidCrystalI2C, serLCD, etc ... qui ont la même API (les mêmes fonctions). Le sketch devient ainsi portable sans changement d'un type d'écran à l'autre.
Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

skizoh

lol je suis trop habitué au C moi ça ce vois je le fait a l'ancienne xDD

Skizo !
Un tien vaux mieux que deux tu l'auras !

barbudor

Et en utilisant une classe basée sur Print, tu peux utiliser mon complément EZPrint (voir dans section Projets Finis) :
Code: [Select]
lcd << "la variable vaut " << variable << endl;
Et hop :)
Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

Mike74

Salut, merci Skizoh j'ai essayé ton bout de code et ca m'affiche que des lettres  :smiley-eek:

Barbudor j'ai suivi ton conseil et j'ai utilisé la fonction itoa mais j'ai une valeur absurde qui s'affiche, en l'occurence -3  :smiley-eek-blue:

voici le code :

Code: [Select]
int sensorPin = A1;
float sensor_reading = 0.0;
float vref = 1.084;
int fahrenheit = 0;
int centigrade = 0;

void setup()
{
Serial.begin(19200);
  ELCD_initialize();
  delay(200);
  ELCD_Clear_LCD();
  ELCD_Cursor_Position(0, 0);
  ELCD_put_str("Temp:");
 
}

void loop()                                                     
{

sensor_reading = analogRead(sensorPin);
fahrenheit = (100.0 * sensor_reading * vref)/1023;
centigrade = (((5.0/9.0))*(fahrenheit-32.0));
char centigrade_str[4];  //reserve the string space first
itoa(centigrade, centigrade_str, 10);
ELCD_Cursor_Position(7, 0);                                                           
ELCD_put_str(centigrade_str);
delay(1000);
}

barbudor

#7
May 23, 2012, 09:33 pm Last Edit: May 23, 2012, 09:41 pm by barbudor Reason: 1
Et tu as regardé sur le terminal ce qu'il y a dans centigrade_str ?

Serial.println( centigrade_str );

Il ne faut pas tourner en aveugle. Il n'y a pas beaucoup de moyen de debug sur Arduino, juste la liaison série vers le PC, mais il faut pas hésiter à s'en servir pour essayer de comprendre ce qu'il se passe avant de poser des questions.


EDIT : Flute, j'avais pas compris ta liaison série est dédiée au LCD.
Tu ne pouvait pas utiliser une SoftwareSerial pour le LCD et garder ta liaison série pour le debug.

Une partie de ma remarque reste valide : quand tu ne sais pas ce que fait une partie de code, extrait le et teste le sans le LCD vers le serial monitor.

EDIT2 :
Je confirme que ce code ci marche très bien :
Code: [Select]
int centigrade = 0;

void setup()
{
Serial.begin(9600);

centigrade = 123;
char centigrade_str[4];  //reserve the string space first
itoa(centigrade, centigrade_str, 10);
  Serial.println( centigrade_str);
}

void loop()                                                     
{
}


Donc la vérité est ailleurs.
ELCD_put_str() ?


EDIT3 : quelle valeur de centigrade attends tu ?
Essaye d'agrandir la taille du tableau centigrade_str à 7 pour pouvoir supporter aussi les nombre négatifs.
Un int va entre "-32768" et "32767" + le caractère de fin \0
Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

Mike74

Oui c'était un problème de formule de conversion mais voilà avec ce code j'ai la bonne température par contre pas de virgule, pour 26.0, ca m'affiche 260, pourtant j'ai déclaré mes variables en 0.0

Code: [Select]
int sensorPin = A1;
float sensor_reading = 0.0;
float vref = 1.084;
int fahrenheit=0;
int centigrade = 0.0;

void setup()
{
Serial.begin(19200);
  ELCD_initialize();
  delay(200);
  ELCD_Clear_LCD();
  ELCD_Cursor_Position(0, 0);
  ELCD_put_str("Temp:");
 
}

void loop()                                                     
{

sensor_reading = analogRead(sensorPin);
fahrenheit = (100.0 * sensor_reading * vref)/1023;
centigrade = (sensor_reading * 900 / 1024)+32;
char centigrade_str[7]; 
itoa(centigrade, centigrade_str, 10);
ELCD_Cursor_Position(6,0);                                                           
ELCD_put_str(centigrade_str);
delay(1000);
}

barbudor

Code: [Select]
int centigrade = 0.0;

Tu as surtout déclarée ta variable en entier et pas en flottant ;)

Une fois passé en flottant, ce n'est plus itoa() qu'il faut utiliser mais dtostrf() donc la doc se trouve ici

Note que toute la doc de l'avr-libc (bibliothèque standard C pour l'AVR) se trouve aussi sur ton PC dans le répertoire  arduino\hardware\tools\avr\doc\avr-libc\\avr-libc-user-manual

Barbuduino: Arduino sur Breadboard & VinciDuino: Clone Leonardo // WR703: Mini-routeur hacké // LauchPad MSP430 et Stellaris // Panda II Arduino-like .NetMF sous VisualC#
RTFC: Read That F.....g Code / RTFD: Read That F.....g Doc / RTFDS: Read That F.....g DataSheet / RTFS: Read That F.....g Schematic / Wot da ya wanna D.I.Y. today ?

Mike74

bien j'ai essaye ca mais message d'erreur me disant que dtostrf n'est pas déclaré  :smiley-eek:

Code: [Select]
int sensorPin = A1;
float sensor_reading = 0.00;
float vref = 1.084;
int fahrenheit = 0;
float centigrade = 0;
char centigrade_str[4];

void setup()
{
Serial.begin(19200);
  ELCD_initialize();
  delay(200);
  ELCD_Clear_LCD();
  ELCD_Cursor_Position(0, 0);
  ELCD_put_str("Temp:");
}

void loop()                                                     
{
sensor_reading = analogRead(sensorPin);
fahrenheit = (100.0 * sensor_reading * vref)/1023;
centigrade = (sensor_reading * 900 / 1024)+32;
dtostrf(centigrade, 3, 0, centigrade_str);
ELCD_Cursor_Position(6,0);                                                           
ELCD_put_str(centigrade_str);
delay(1000);
}

skizoh

a tu pensée à mettre cette lib?:

#include <stdlib.h>

Skizo !
Un tien vaux mieux que deux tu l'auras !

Mike74

oui mais message d'erreur

Code: [Select]
#include <stdlib.h>

int sensorPin = A1;
float sensor_reading = 0.00;
float vref = 1.084;
int fahrenheit = 0;
float centigrade = 0;
char centigrade_str[4];

void setup()
{
Serial.begin(19200);
  ELCD_initialize();
  delay(200);
  ELCD_Clear_LCD();
  ELCD_Cursor_Position(0, 0);
  ELCD_put_str("Temp:");
}

void loop()                                                     
{
sensor_reading = analogRead(sensorPin);
fahrenheit = (100.0 * sensor_reading * vref)/1023;
centigrade = (sensor_reading * 900 / 1024)+32;
dtostrf(centigrade, 3, 0, centigrade_str);
ELCD_Cursor_Position(6,0);                                                           
ELCD_put_str(centigrade_str);
delay(1000);
}



message d'erreur : emp_LM34.cpp:36: undefined reference to `dtostrf'
collect2: ld returned 1 exit status

skywodd

Bonjour,


Sinon, il aurait été plus malin de faire ta lib ELCD comme LiquidCrystal, en dérivant de la classe Print ce qui te permet d'hériter de la classe print toutes les fonctions .print() et .println() existante.

L'avantage est de disposer d'une lib interchangeable avec LiquidCrystal, LiquidCrystalI2C, serLCD, etc ... qui ont la même API (les mêmes fonctions). Le sketch devient ainsi portable sans changement d'un type d'écran à l'autre.

Je crois pouvoir dire sans trop m'avancer que la partie ELCD vient de mon blog ;)
https://skyduino.wordpress.com/2011/08/05/arduino-drivers-arduino-pour-elcd-lextronic/


lol je suis trop habitué au C moi ça ce vois je le fait a l'ancienne xDD

itoa est beaucoup plus performant que du bricolage fait main ;)
Ps: parcourir les fonctions de la libc ne demande pas beaucoup de temps et c'est un plus non négligeable.


Et en utilisant une classe basée sur Print, tu peux utiliser mon complément EZPrint (voir dans section Projets Finis) :
Code: [Select]
lcd << "la variable vaut " << variable << endl;

Dans le même genre tu as la librairie Streaming pour arduino >=0018 et >=1.0
http://arduiniana.org/libraries/streaming/
Des news, des tutos et plein de bonnes choses sur http://skyduino.wordpress.com !

Mike74

je te remercie pour l'info mais là j'arrive au bout de mes connaissances actuelles, un petit coup de pouce  =(

Go Up