Connections I2C Afficheur + clavier

J'ai vu un autre souci :

Wire.beginTransmission(0x38); //Adresse de l'afficheur
Wire.send(0x20); //Registre pour le rétroéclairage
Wire.send(1); //Allumage du rétroéclairage
Wire.endTransmission();

Dans un message précédent tu dis que :

"L'adresse du contrôleur I2C de la carte afficheur est 0x23".

Sinon pour envoyé le fameux 1 (à la place de Wire.send(1):wink: essaye plutôt : Wire.send(0b00000001) ou Wire.send(0b10000000) ou bien encore Wire.send(0b11111111)

Bonjour effectivement je m'était trompé dans le 1er post sur l'adressage de la carte sur l'I2C, c'est bien 0x38.

Ensuite je bien d'essayé avec 0b00000001 ... mais c'est pas mieux l'afficheur continu sont cycle, il doit surement y avoir un truc à envoyer pour qu'il arrête son boot

Bon en faite j'était a coter de la plaque, car effectivement il y a tout un protocole qui a été mis en place dans le contrôleur de l'afficheur.

Il faut lui dire l'adresse bien sur 0x38 si l'on est en écriture 0x39 si l'on est en lecture car on ajoute un bit d'ecriture et lecture

Ensuite L'adresse du registre puis le type des data ajouter au nombre de Byte à envoyer et enfin le checksum

S'il ne reçoit pas un message complet il ne démarre pas et fait que booter

Donc c'est bon maintenant ça fonctionne ?

Je suis au boulot donc j'ai pas avec moi l'arduino et les interfaces :), mais j'essaie sa se soir ou se week au pire. En tout cas avant cela ne pouvait pas marcher avec ce que je faisais car le microcontroleur ne répondra quelque chose, à la 1ère connexion, uniquement dans le cas d'une trame conforme. Ce qui arrêtera les Boot répété.

Dans un 1er temps je vais essayer d'activer le rétro éclairage.

Apparemment j'ai pas besoin de rajouter des résistance de pull up puisqu'il y a ceux de la DS1307 qui sont sur le 5V.

Il y en a également intégrées à l'arduino :wink:

Bonsoir, j'ai récupéré la documentation des trames à envoyer en I2C.

Voici l'exemple pour l'écriture:

Start

Slave adresse sur 7 bits, le bit faible étant le Read/Write (0 étant apparemment le Write et 1 Read)

Adresse sur 8 bites

Data Type sur 8 bites étant 0x80 + le nombre de data

Data Byte 1

Data Byte n

Cheksum

Stop

Voila bon j'ai essayer des truc mais j'arrive à rien encore. Je me foutrais des claques parfois :slight_smile:

L'adresse de la carte étant 0x38

Si par exemple on essaye d'allumer le rétroéclairage l'adresse est 0x20 et il comporte 1 bit, 1 pour allumer et 0 pour éteindre

pour le checksum, voici le code que j'ai récupéré:

  checksum = slaveAddr | I2C_WRITE;
  for (idx = 0; idx < dataSize + 2; idx++){
    checksum += I2CXD_Message[idx];
  }
 checksum = ~checksum;

Avec :
#define I2C_WRITE 0

unsigned char slaveAddr
unsigned char dataSize

unsigned char checksum;
unsigned char idx;

Si vous pouvez m'aider un peut, je pensais avoir compris ce qu' il m'avait dit mais cela marche pas, je pense que je me plante avec l'histoire des adresse en 7bites sans le poids faible

Pour l'envoie j'ai crée un méthode:

void I2C_Write(unsigned char Addr, unsigned char * Buff, unsigned char Size)
{
  Wire.beginTransmission(Addr);
  Wire.send(Buff, Size);
  Wire.endTransmission();
  
}

Bonjour,

Voila en fonction de ce que j'ai recuperé, le code que j'ai effectué:

/*
 *------------------------------------------
 *        Include declaration
 *------------------------------------------
  */
#include <Wire.h>
#include <stdio.h>
/*
 *------------------------------------------
 *        Constant declaration
 *------------------------------------------
  */
#define I2CXD_MSG_LGTH  21

/*-- Write command I2C 0x20 to 0x2--*/
#define I2C_CMD_BACKLIGHT_ONOFF        (0x20)
#define I2C_CMD_CONSTRAST              (0x21)
#define I2C_CMD_LEDSCONTROL            (0x22)
#define I2C_CMD_WRITE_LINE1            (0x23)
#define I2C_CMD_WRITE_LINE2            (0x24)
#define I2C_CMD_DISPLAY_CONTROL        (0x25)
#define I2C_CMD_SET_CURSOR_PO          (0x26)
#define I2C_CMD_WRITE_SPECIAL_CHAR     (0x27)
#define I2C_CMD_BUTTON_STATUS_REGISTER (0x10)

/*-- Constante --*/
#define I2C_WRITE  0
#define ERROR      (0x01)
#define OK         (0x00)

/*ADDRESS CARTE I2C */
#define LCD_SLAVE_ADRR    (0x38) //display & Keyboard/Led slave address

/*--Variable déclaration--*/
unsigned char * I2CXD_Message;
boolean L;

void setup()
{
  Serial.begin(9600);
  Wire.begin(); // join i2c bus (address optional for master)
  L = false;
}

byte val = 0;

void loop()
{
  unsigned char dt[1];
  dt[0] = (0x80);
  
  if ( L = true){
    dt[0] = (1);
    I2C_WriteCommand(LCD_SLAVE_ADRR, I2C_CMD_BACKLIGHT_ONOFF, 1, dt);
    L = false;
  }else{
    dt[0] = (0);
    I2C_WriteCommand(LCD_SLAVE_ADRR, I2C_CMD_BACKLIGHT_ONOFF, 1, dt);
    L = true;
  }
  
  delay(1500);
}

unsigned char I2C_WriteCommand (unsigned char slaveAddr, unsigned char command, unsigned char dataSize, unsigned char *ptData)
{
  unsigned char idx;
  unsigned char checksum;
  if (dataSize > (I2CXD_MSG_LGTH-3)){
    dataSize = I2CXD_MSG_LGTH-3;
  }
  I2CXD_Message[0] = command >> 1;           /* Commands. */
  I2CXD_Message[1] = 0x80 + dataSize;        /* Byte block 0x80 + data lenght */
  for (idx = 0; idx < dataSize; idx++){
    I2CXD_Message[idx + 2] = *ptData++;
  }
  checksum = slaveAddr | I2C_WRITE;
  for (idx = 0; idx < dataSize + 2; idx++){
    checksum += I2CXD_Message[idx];
  }
  checksum = ~checksum;
  I2CXD_Message[dataSize + 2] = checksum;
  if (I2C_Write(slaveAddr, I2CXD_Message, dataSize +3) != true){
     return ERROR;
  }else{
    return OK;
  }  
}

boolean I2C_Write(unsigned char Addr, unsigned char * Buff, unsigned char Size)
{
  Wire.beginTransmission(Addr >> 1);
  Wire.send(Buff, Size);
  Wire.endTransmission();
  
}

Mais cela marche toujours pas
La méthode I2C_WriteCommand est la même chose que ce que l'on utilise au boulot

Bonsoir,

J'avance un peut,
J'arrive maintenant a allumer le retroéclairage et a envoyer du texte sur la ligne 1 ou la ligne 2.

Pour le moment j'arrive a rien de plus, je n'arrive pas par exemple a modifier le constrast

Command code: 0x21
Length: 1Byte
Byte 0:
0 (minimum) to 255(maximum)
Contrast values are permanently stored is EEPROM

Ou faire changer les voyants:

Command code: 0x22
Length: 1Byte
Byte 0:
b0: 0 = Led1 (red) OFF
1 = Led1 ON
b1-3: flashing period index for Led1
b4: 0 = Led2 (green) OFF
1 = Led2 ON
b5-7:flashing period index for Led2

Flashing period index Cycle delay (s)
0 (infinite)
1 0.32
2 0.64
3 0.96
4 1.28
5 1.60
6 1.92
7 2.24

Notes:
? If both LED flash at the same period, b0=b1 make them flash in phase and b0 different from b0 make them flash in phase opposition.
? Led's flash at startup, so the user should issue a Led control short after to stop it.

Je continu à chercher

J'ai réussi a faire fonctionner mes voyant mais je n'y arrive pas encore de façon conventionnel.

Pour allumer les 2 LED en fixe, il faut que j'envoie 0x11

dt[0] = (0x11);
I2C_WriteCommand(LCD_SLAVE_ADRR, I2C_CMD_LEDSCONTROL, 1, dt);

Mais pour que cela marche je suis obligé d'envoyer avant un serial.println(dt[0], HEX)

Comme cela:
dt[0] = (0x11);
Serial.println(dt[0], HEX),
I2C_WriteCommand(LCD_SLAVE_ADRR, I2C_CMD_LEDSCONTROL, 1, dt);

Et la cela marche.

J'ai essayé pour la même commande 0x11:
dt[0] = 17;
dt[0] = 0b00010001;
dt[0] = 0x11, HEX,

mais rien

Pour la récupération des boutons, les trames à envoyer sont plus complexe car il faut le faire en 2 étapes:

Partie - SetDataAdress:

Start
Byte 1 : Adress
Byte 2 : Command
Byte 3 : Data Type + taille
Byte 4 : checksum

Partie - GetData
Start
Byte 1 : Adress
Byte 2 : Error Code
Byte 3 : Byte donnee 1
Byte n : Byte donnee n
Byte n+1: checksum

Voici le code tel qu'il est dans notre programme standard au boulot:

unsigned char I2CXD_ReadCommand(unsigned char slaveAddr, unsigned char command, unsigned char dataSize)
{
  unsigned char checksum;
 
  I2CXD_Message[0] = command;
  I2CXD_Message[1] = 0x80 + dataSize;
  checksum = slaveAddr | I2C_WRITE;
  I2CXD_Message[2] = checksum + I2CXD_Message[0] + I2CXD_Message[1];
  I2CXD_Message[2] = ~I2CXD_Message[2];
  I2C_Write(slaveAddr, I2CXD_Message, 3);
  delay(5);
  I2C_Read(slaveAddr, I2CXD_Message, dataSize + 2);
  
}

Et voici ce que j'ai fait sachant que I2C_Write fonctionne avec l'envoie de commande:

boolean I2C_Write(unsigned char Addr, unsigned char * Buff, unsigned char Size)
{
  Wire.beginTransmission(Addr >> 1);
  Wire.send(Buff, Size);
  Wire.endTransmission();
}
boolean I2C_Read(unsigned char Addr, unsigned char * Buff, unsigned char Size)
{
//j'ai mis les tailles en fixe pour les essais
  byte Recep[3];
  Wire.requestFrom(Addr >> 1, 1+2);
  Recep[0] = Wire.receive(); //Code d'erreur
  Recep[1] = Wire.receive(); // Byte de donnée du clavier
  Recep[2] = Wire.receive(); // Checksum
  Serial.print ("Code Erreur = ");
    Serial.println(Recep[0], HEX);
    Serial.print ("Reception = ");
    Serial.print(Recep[1], HEX);
    Serial.print ("Checksum= ");
    Serial.print(Recep[2], HEX);
  Wire.endTransmission();
}

Je fait des essaie avec I2C_Read mais actuellement cela marche pas.
car en code d'erreur il me renvoie 0xAA ce qui correspond a "commande comprise" donc pas d'erreur
en donnée je reçois toujours 0 que je tape ou pas sur le clavier.
en checksum j'ai toujours 0x55

Bonjour,
Vous pourriez me dire pourquoi je suis obliger de faire un Serial.print(xxx), avant d'envoyer m'a commande I2C. Cela marche pas si je le fait pas (voir les post précédent).

Au boulot, ils ne voient pas pourquoi non plus.

Merci

Pas de Wire.endTransmission(); après un request, c'est surement ça qui fait buguer. Très souvent quand un print "débug" un programme, c'est souvent un problème de timing. En fait le endTransmission doit tout faire foirer, du coup avec les print ça le retardait un peu et la réception avait le temps de se faire correctement.

Sinon pourquoi :

Wire.requestFrom(Addr >> 1, 1+2);

Fâché avec les additions ?? ;D

Et tu peux simplifier un peu ton code :

boolean I2C_Read(unsigned char Addr, int BytesDemandes)
{
byte Recep[BytesDemandes];
Wire.requestFrom(Addr >> 1, BytesDemandes);
for (int i=0;i<BytesDemandes;i++){
 Recep[i] = Wire.receive(); 
Serial.print("Byte ");
Serial.print(i);
Serial.print(" = ");
Serial.println(Recep(i));
}
  
}

Ca aura l'avantage en plus de pouvoir facilement se faire pour n'importe quel nombre de bytes nécessaires.

Merci pour l'info, dans la partie I2C_Read

En ce qui concerne la simplification, merci mais il n'y a pas de souci je suis vraiment en plein débogage donc c'est brut de décoffrage.

Par contre en ce qui concerne l'addition :slight_smile: j'ai rien invente à ce niveau j'ai repris le code utilisé au boulot. C'est clair que c'est bizarre.

Donc pour la lecture je vais tester sa.

Par contre dans la partie écriture I2C_Write je n'est pas de requestfrom et cela plantait tout pareil si j'avais pas de serial.print. Je vais tester avec des (delay). Mais vu que je vais gérer 2 servomoteurs la vitesse va être gérer avec Millis (de mémoire), il va falloir que j'intègre aussi cette fonction pour géré l'intervalle de temps entre 2 envois.

En tout cas un gros merci d'avoir répondu car je commençais à me sentir un peut seul ;D

Si le write bug aussi, il faut peut-être cherché ailleurs : certains disposif ou CI sont en i2c "lent", la librairie wire par défaut fonctionne sur ce mode. Peut-être qu'en la passant en rapide ... Plus d'infos : http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1241668644

Merci, il faut pas que cela me bloque aussi mon DS1307. Mais je vais regarder le lien, merci

Bon ba un grand merci car tout marche impeccable, j'ai ajouté avant chaque envoie sur l'I2C un "delay(100)" pour le moment, il faudra que je le modifie par la fonction "millis" dans le "loop" mais cela marche nickel, je vais essayer de réduire le "delay" aussi mais bon c'est pas non plus bloquant les 100ms une fois que cela sera gérer avec "millis", ainsi que le "I2C_Read", j'ai enlevé le "endTransmission()" et c'est bon + le "delay" ajouté aussi.

Je vais quand même demander pour la fréquence du bus, mais vu que la DS1307 marche bien j'ai peur qu'elle se mette a déconner, vous en pensé quoi?

Le truc c'est que la librairie wire d'origine est en mode lent (100 khz) et donc devrait marcher avec tous les composants i2c.
Ne t'inquiete pas pour le DS1307, à moins qu'il ait un timeout intégré, il pourrait même fonctionner à 1hz ^^ par contre en i2c rapide il faut voir ...
Mais c'est quand même étrange cette histoire ...

Bonjour,

Apparemment le micro-contrôleur est bien aussi prévu de fonctionner à 100Khz. Par contre la personne qui s'est occupée de cet afficheur me confirme qu'il faut bien un temps de pose entre chaque envoie car la gestion de l'I2C sur le micro est entièrement logiciel. Il y a donc un temps de traitement plus long que la DS1307 qui elle a une gestion hardware. Donc tout est normale à ce niveau. Donc j'ai plus qu'a bien gérer mes envoies I2C.

Merci de votre aide