Librairie LCDi2cR

Bonsoir,

Il y a quelques mois, j'avais réalisé un programme avec la librairie LCDi2cR.
J'ai de nouveau besoins de cette libraire mais je ne la trouve plus sur le net.

Quelqu'un aurait-il la librairie ou quelqu'un connait-il le lien?

Merci

Il y a la LiquidCrystal_I2C qui est équivalent à la LiquidCrystal standard mais passe par un PCF8574 pour communiquer à un LCD type 2x16.

Je vais regarder avec cette librairie mais suis-je obligé de prendre un PCF8574? Car le programme est presque fini et fonctionne très bien avec la librairie LCDi2cR.

Mais comme j'ai eu moins le temps pour finaliser la partie électronique plus des problèmes avec les leds, je recommence seulement les essais et je me suis rendu compte que je n'avais pas sauvé la librairie lorsque je suis passé à la nouvelle version du logiciel d'Arduino.

C'est pour ca que j'aimerai retrouver cette librairie.
Ou alors avec une autre librairie tant que je ne dois pas ajouter d'autre composant (je vais voir avec LiquidCrystal_I2C).

Ps: mon écran est un LCD03 de 4*20

Ok, ton écran intègre déjà l'interface I2C ?
LiquidCrystal_I2C est fait pour travailler avec un LCD 2x16 traditionnel + un PCF8574, donc ca ne marcheras pas avec ton écran.

Par contre sur le lien donné, tout est indiqué a propos du protocole, donc c'est facile de recoder la lib tout seul si tu ne la retrouve pas.

Tu as cherché sur Google ?

Est ce que tu ne pourrais pas trouver ton bonheur là dedans :

http://arduino.cc/playground/Code/LCDi2c

Les liens n'aboutissent a rien. C'est çà le problème....

Oui,j'ai deja l'interface I2C.
J'ai également cherché sur google avant de poster mais je n'ai trouvé que des programme utilisant cette librairie mais pas la librairie.

Il ne me reste plus qu'à essayer de faire la librairie moi même á moins que quelqu'un l'aurait...

N'arrivant pas à créer une librairie, j'ai créé de petites fonctions mais j'ai un problème pour la fonction affichage:

Je dois choisir un type de variable mais la variable peut être un nombre, du texte, un nombre à virgule,...

Exemple:

#include <Wire.h>

#define addresse 0x63
int a=25;

void setup() {
  lcd03_print("test");
  lcd03_print(a);
}

void loop(){}


void lcd03_print(***** mot)
{
  Wire.beginTransmission(addresse);  //Aller sur l'adresse
  Wire.send((byte)0x00);              //Null
  Wire.send(mot);                       //Ecrire
  Wire.endTransmission();             //Fin de transmission
}

Que dois-je mettre à la place des ***** pour que ca fonctionne?

Tu ne peux pas.
Il faut faire chaque version de la fonction. En C++ cela s'appelle une surcharge.

void lcd03_print(int i);
void lcd03_print(float f);
void lcd03_print(char c);
void lcd03_print(char *s);

Mais le mieux c'est de faire une classe C++ dérivée de Stream.
Comme cela tu n'a besoin que d'implémenter la fonction membre write( char c );
Toutes les autres sont déjà dans Stream

Regarde comment LiquidCrystal est construite et utilise la même structure.
Cela permet d'avoir un module ayant la même syntaxe que l'API LCD Arduino, donc de rendre le code facilement portable.

J'avais déjà regardé dans LiquidCrystal pour refaire une librairie. J'ai de nouveau regardé et il y a beaucoup de choses que je ne comprend pas et je n'arrive pas à la modifier. je ne connais pas beaucoup le langage C
Par exemple dans LiquidCrystal.h :

class LiquidCrystal : public Print {
public:
  LiquidCrystal(uint8_t rs, uint8_t enable,
		uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
		uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
  LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
		uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
		uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
  LiquidCrystal(uint8_t rs, uint8_t rw, uint8_t enable,
		uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);
  LiquidCrystal(uint8_t rs, uint8_t enable,
		uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);

  void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
	    uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
	    uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);

barbudor:
Il faut faire chaque version de la fonction. En C++ cela s'appelle une surcharge.

void lcd03_print(int i);

void lcd03_print(float f);
void lcd03_print(char c);
void lcd03_print(char *s);

Pour les fonctions, je dois plusieurs fonctions dans ce style?

void lcd03_print(char* mot)
{
  Wire.beginTransmission(addresse);  //Aller sur l'adresse
  Wire.send((byte)0x00);            //Null
  Wire.send(mot);               //Ecrire Hello
  Wire.endTransmission();            //Fin de transmission
}
void lcd03_print(int mot)
{
  Wire.beginTransmission(addresse);  //Aller sur l'adresse
  Wire.send((byte)0x00);            //Null
  Wire.send(mot);               //Ecrire Hello
  Wire.endTransmission();             //Fin de transmission
}

Et les appeler comme ceci?

lcd03_print("hello");
lcd03_print(a);  Avec par exemple a=25

Oublions la référence à LiquidCrystal pour l'instant.

Oui tu dois faire une fonction pour chaque type mais c'est plus compliqué que cela.

void lcd03_print(char* mot)
{
  Wire.beginTransmission(addresse);  //Aller sur l'adresse
  Wire.send(mot);               //Ecrire le caractère mot
  Wire.endTransmission();            //Fin de transmission
}

Ca c'est OK, tu envoie le caractère mot sur l'écran
J'ai viré le write(0x00) qui ne sert à rien.

void lcd03_print(int mot)
{
  Wire.beginTransmission(addresse);  //Aller sur l'adresse
  Wire.send(mot);               //Ecrire la valeur de mot
  Wire.endTransmission();             //Fin de transmission
}

Ça c'est pas bon parce qu'il n'existe pas de fonction Wire::send( int mot );

En fait pour écrire un entier il faut faire une conversion de l'entier en une chaîne de caractères vers ASCII et ensuite envoyer cette chaîne de caractères vers l'écran.

Intéressons nous d'abord à la fonction pour envoyer une chaîne de caractères :

void lcd03_print(char *str)
{
  Wire.beginTransmission(addresse);  //Aller sur l'adresse
  while ( *str  )                                  // tant que l'on n'arrive pas au caractère de fin de châine (caractère nul '\0')
    Wire.send(*str++);                        // on envoie chaque caractère et on passe au suivant
  Wire.endTransmission();             //Fin de transmission
}

Maintenant, on sais faire lcd03_print( "Hello world!" );
On progresse.

Maintenant comment afficher la valeur d'un entier ?
On va recopier le code de Print::printNumber( unsigned long n, uint8_t base ) qui est dans \arduino\hardware\arduino\cores\arduino\Print.cpp

void lcd03_print(unsigned long n, uint8_t base = 10)
{
  char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
  char *str = &buf[sizeof(buf) - 1];

  *str = '\0';

  // prevent crash if called with base == 1
  if (base < 2) base = 10;

  do {
    unsigned long m = n;
    n /= base;
    char c = m - base * n;
    *--str = c < 10 ? c + '0' : c + 'A' - 10;
  } while(n);

  return lcd03_print(str);
}

Tu peux maintenant faire aussi :
lcd03_print( 10 ) pour afficher en décimal
lcd03_print( 10, HEX ) pour afficher en hexa
lcd03_print( 10, BIN ) pour le binaire

Je te laisse tester.

Merci pour ta réponse. Je n'aurais pas su trouver ca tout seul.

Mais je n'arrive toujours pas à le faire fonctionner.

Faut-il mettre le dernier ou les 2 derniers code que tu m'as donné?
Car si je met que le dernier, il m'indique que lcd03_print n'est pas déclarée. Pourtant, le nom est exactement le même, puis, j'ai fait un copier-coller, changer de nom et le résultat est le même.
Et lorsque je met les 2, je sais afficher "Hello" (sauf qu'il manque le H) mais je n'arrive pas à afficher les nombres que ce soit avec lcd03_print( 10 ) ou lcd03_print( 10, HEX ) ou lcd03_print( 10, BIN ). Il indique conversion invalide int to char.

Edit: Est-ce normal d'avoir "return lcd03_print(str);" dans un void? Il me semblai que dans une fonction void, on ne pouvait rien retourner

Faut-il mettre le dernier ou les 2 derniers code que tu m'as donné?

Il faut le 1er et les 2 derniers. Chacun traitent un cas particulier.

Par contre j'ai oublié de corriger la première fonction : void lcd03_print(char mot) : on prend un charactère comme paramètre, pas un pointeur.

Si tu ne vois que "ello World!" c'est donc que j'ai peut être abusivement supprimé le write( 0x00 );
En relisant la doc, ca semble en effet nécessaire de commencer chaque transaction par un write( 0x00 ) pour spécifier le registre de commande dans lequel on va écrire.

Voici ce que çà donnerait :

#include "Wire.h"

int addresse = 0x20;

void lcd03_print(char mot)
{
  Wire.beginTransmission(addresse);  //Aller sur l'adresse
  Wire.write( 0x00 );             // spécifie le Registre de commande
  Wire.write(mot);               //Ecrire le caractère mot
  Wire.endTransmission();            //Fin de transmission
}

void lcd03_print(char *str)
{
  Wire.beginTransmission(addresse);  //Aller sur l'adresse
  Wire.write( 0x00 );             // spécifie le Registre de commande
  while ( *str  )                                  // tant que l'on n'arrive pas au caractère de fin de châine (caractère nul '\0')
    Wire.write(*str++);                        // on envoie chaque caractère et on passe au suivant
  Wire.endTransmission();             //Fin de transmission
}

void lcd03_print(unsigned long n, uint8_t base = 10)
{
  char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
  char *str = &buf[sizeof(buf) - 1];

  *str = '\0';

  // prevent crash if called with base == 1
  if (base < 2) base = 10;

  do {
    unsigned long m = n;
    n /= base;
    char c = m - base * n;
    *--str = c < 10 ? c + '0' : c + 'A' - 10;
  } while(n);

  lcd03_print(str);
}


void setup()
{
  Serial.begin( 9600 );
  pinMode( 9, OUTPUT );
  digitalWrite( 9, LOW );
 
  Wire.begin();
  
  Serial.println( "go" );
  digitalWrite( 9, HIGH );
  lcd03_print( '!' );
  lcd03_print( "Hello World!" );
  lcd03_print( 10, DEC );
  lcd03_print( 10, HEX );
  lcd03_print( 10, BIN );
  
  Serial.println( "done" );
}

void loop()
{
}

çà compile et çà tourne sur ma Nono mais je n'ais pas l'écran pour vérifier.

Ah Ca fonctionne!

Merci beaucoup sans toi, je n'y serais pas arrivé.

Ps: pour ceux qui veulent tester le code avec un écran LCD03, il faut changé l'adresse 0x20 => 0x63

Oui, j'ai laissé trainé l'adresse de mon PCF8574...

Je viens de remarquer qu'il y a 2 petits problèmes:

Il n'affiche pas les nombres décimales: (ex: 17.57 devient 17) et les nombres négatifs ne sont pas bon (-1920.06 devient 4294965376)

Bien sur pour le 1er point; il faut maintenant créer lcd03_print( float f );
Pour afficher un entier je me suis inspiré (oui, enfin j'ai franchement copié ;)) de la fonction Print::printNumber()
Je te laisse un peu réfléchir sur comment faire pour un flottant (en étant aussi fainéant que moi, je te demande pas l'impossible)

Pour ce qui est des nombres négatifs effectivement la fonction que l'on a codé est void lcd03_print(unsigned long n, uint8_t base = 10) qui demande un entier non signé.

je propose de l amodifier pour traiter les entier signés.
Essaye ca (attention : j'ai pas eu le temps de tester)

void lcd03_print(long n, uint8_t base = 10)
{
  char buf[8 * sizeof(long) + 1 + 1]; // Assumes 8-bit chars plus zero byte plus sign.
  char *str = &buf[sizeof(buf) - 1];
  bool isNeg = ( n < 0 );

  if ( isNeg )
    n = -n;

  // prevent crash if called with base == 1
  if (base < 2) base = 10;

  do {
    unsigned long m = n;
    n /= base;
    char c = m - base * n;
    *--str = c < 10 ? c + '0' : c + 'A' - 10;
  } while(n);
  
  if ( isNeg )
    *--str = '-';

  lcd03_print(str);
}

Les 2 versions (signé et non-signé) ne peuvent pas cohabiter. Il faut que tu n'en garde qu'une.