Controle saisie nouveau message par Moniteur Série


```cpp
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <EEPROM.h>

#define PIN 6
#define mw 128
#define mh 8
#define EEPROM_SIZE 1050

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(mw, mh, PIN,
  NEO_MATRIX_BOTTOM + NEO_MATRIX_RIGHT +
  NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
  NEO_GRB + NEO_KHZ800);

const uint16_t colors[] = {
  matrix.Color(255, 0, 0),
  matrix.Color(0, 255, 0),
  matrix.Color(0, 0, 255)
};

char message[EEPROM_SIZE + 1];  // message affiché
char buffer[EEPROM_SIZE + 1];   // pour la réception
int x = mw;
int pass = 0;
bool messageRecu = false;

unsigned long dernierDefilement = 0;
const unsigned long intervalleDefilement = 30;

void setup() 
{
  Serial.begin(9600);
  matrix.begin();
  matrix.setTextWrap(false);
  matrix.setBrightness(15);
  matrix.setTextColor(colors[pass]);

  chargerMessageEEPROM();
  Serial.println("Message actuel :");
  Serial.println(message);
  Serial.println("Entrez un message terminé par ';'");
}

void loop() 
{
  gestionSaisieSerie();

  if (messageRecu) 
  {
    messageRecu = false;
    Serial.print("Nouveau message enregistré : ");
    Serial.println(message);
    Serial.print("Longueur : ");
    Serial.println(strlen(message));
  }

  if (millis() - dernierDefilement >= intervalleDefilement) 
  {
    dernierDefilement = millis();
    afficherMessage();
  }
}

void afficherMessage() 
{
  matrix.fillScreen(0);
  matrix.setCursor(x, 0);
  matrix.print(message);
  if (--x < -((int)strlen(message) * 6)) 
  {
    x = mw;
    pass = (pass + 1) % 3;
    matrix.setTextColor(colors[pass]);
  }
  matrix.show();
}

void gestionSaisieSerie() 
{
  static uint16_t index = 0;
  while (Serial.available()) 
  {
    char c = Serial.read();
    if (c == ';') 
    {
      buffer[index] = '\0';

      // Remise à zéro EEPROM
      for (int i = 0; i < EEPROM_SIZE; i++) 
      {
        EEPROM.write(i, 0xFF);
      }

      // Sauvegarde en HEX
      for (uint16_t i = 0; i < index && i < EEPROM_SIZE; i++) 
      {
        EEPROM.write(i, (byte)buffer[i]);
      }

      // Lecture et affichage
      chargerMessageEEPROM();
      messageRecu = true;
      index = 0;
    } else if (index < EEPROM_SIZE) 
    {
      buffer[index++] = c;
    }
  }
}

void chargerMessageEEPROM() 
{
  for (int i = 0; i < EEPROM_SIZE; i++) 
  {
    byte val = EEPROM.read(i);
    if (val == 0xFF || val == 0x00) 
    {
      message[i] = '\0';
      break;
    }
    message[i] = (char)val;
  }
  message[EEPROM_SIZE] = '\0'; // sécurité
}


Bonjour à tous, je vous expose mon problème : je cherche a changer le message, via un cable USB (ou plus tard en Bluetooth (HM-10) avec un IPhone 11 (UTF-8)) avec le Monitor Série tout en filtrant les caractères ASCII entre 32 & 126 (sans accent). Pour l'instant, il me manque, de façon aléatoire, quelques caractères. Je n'arrive pas à vider/effacer l'EEPROM quand il y a un nouveau message à enregistrer. Pourriez-vous me donner un coup de main. L'affichage se fait sur 3 panneaux WS2812 32x8 (soit 128 colonnes x 8 lignes). Merci par avance Philou

Je ne vois aucun filtrage dans ton code. Est-ce que la saisie prédictive ne t’insérerait pas des caractères accentués par hasard?

Quel CPU utilises-tu? Sur les AVR de base l'EEPROM a une taille de 1024 éléments.

La carte est une MEGA 2560 de chez AZ-Delivery (8k)

#include <Adafruit_NeoMatrix.h>
#include <Adafruit_GFX.h>
#include <EEPROM.h>

#define PIN 6
#define mw 128
#define mh 8
#define EEPROM_SIZE 1050

Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(mw, mh, PIN,
  NEO_MATRIX_BOTTOM + NEO_MATRIX_RIGHT +
  NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
  NEO_GRB + NEO_KHZ800);

const uint16_t couleurs[] = {
  matrix.Color(255, 0, 0),
  matrix.Color(0, 255, 0),
  matrix.Color(0, 0, 255),
  matrix.Color(255, 255, 0),
  matrix.Color(255, 0, 255),
  matrix.Color(0, 255, 255),
  matrix.Color(255, 255, 255)
};

char message[EEPROM_SIZE + 1];          // Message affiché
char inputBuffer[EEPROM_SIZE + 1];      // Buffer de saisie
int inputIndex = 0;
int pos = mw;
int couleurIndex = 0;
bool defilementActif = false;
unsigned long dernierDéfilement = 0;
const unsigned long intervalleDéfilement = 30;

void setup() {
  Serial.begin(9600);
  matrix.begin();
  matrix.setTextWrap(false);
  matrix.setBrightness(15);
  matrix.setTextColor(couleurs[couleurIndex]);

  chargerMessageEEPROM();
  if (strlen(message) > 0) {
    defilementActif = true;
  }

  Serial.println("Entrez un message terminé par ';' (sans accents).");
  Serial.print("Message actuel : ");
  Serial.println(message);
}

void loop() {
  traiterSaisieSerie();

  if (defilementActif && millis() - dernierDéfilement > intervalleDéfilement) {
    dernierDéfilement = millis();
    afficherMessage();
  }
}

void afficherMessage() {
  matrix.fillScreen(0);
  matrix.setCursor(pos, 0);
  matrix.print(message);
  matrix.show();
  pos--;
  int messageWidth = strlen(message) * 6;
  if (pos < -messageWidth) {
    pos = mw;
    couleurIndex = (couleurIndex + 1) % (sizeof(couleurs) / sizeof(couleurs[0]));
    matrix.setTextColor(couleurs[couleurIndex]);
  }
}

void traiterSaisieSerie() {
  while (Serial.available()) {
    char c = Serial.read();

    if (c == ';') {
      inputBuffer[inputIndex] = '\0';

      Serial.print("Message reçu (");
      Serial.print(inputIndex);
      Serial.print(" caractères) : ");
      Serial.println(inputBuffer);

      if (strcmp(inputBuffer, "!RESET") == 0) {
        Serial.println("Commande RESET reçue.");
        memset(message, 0, sizeof(message));
        memset(inputBuffer, 0, sizeof(inputBuffer));
        inputIndex = 0;
        defilementActif = false;
        for (int i = 0; i < EEPROM_SIZE; i++) EEPROM.write(i, 0);
        Serial.println("EEPROM réinitialisée. Entrez un nouveau message.");
        return;
      }

      sauvegarderMessageEEPROM(inputBuffer, inputIndex);
      inputIndex = 0;
      memset(inputBuffer, 0, sizeof(inputBuffer));
    }
    else if (inputIndex < EEPROM_SIZE - 1 && c >= 32 && c <= 126) {
      inputBuffer[inputIndex++] = c;
    }
  }
}

void sauvegarderMessageEEPROM(const char *msg, int longueur) {
  if (longueur >= EEPROM_SIZE) longueur = EEPROM_SIZE - 1;
  strncpy(message, msg, EEPROM_SIZE);
  message[longueur] = '\0';

  for (int i = 0; i < longueur; i++) {
    EEPROM.write(i, message[i]);
  }
  EEPROM.write(longueur, '\0');

  Serial.print("Nouveau message enregistré : ");
  Serial.println(message);
  Serial.print("Longueur : ");
  Serial.println(longueur);

  defilementActif = true;
  pos = mw;
}

void chargerMessageEEPROM() {
  for (int i = 0; i < EEPROM_SIZE; i++) {
    char c = EEPROM.read(i);
    if (c == '\0' || c == 255) {
      message[i] = '\0';
      break;
    }
    message[i] = c;
  }
}

ce n'etait pas le bon croquis !!!

OK donc l'EEPROM est assez grande.

  • Tu rafraîchis l'affichage toutes les 30ms.
  • A 9600 bauds il arrive un caractère toutes les 1ms environ

Il faudrait peut-être envisager de bloquer le rafraîchissement de l'affichage s'il y a un transfert en cours avec le téléphone. En effet la librairie NeoPixel bloque les interruptions et donc des caractères peuvent être perdus à ce moment là. Ce blocage ne serait pas très long (environ 1s pour 1000 caractères) et je suppose que cela ne doit pas se produire trop souvent.

Il se pourrait ne pas avoir d'affichage pendant la saisie jusqu'a la validation du nouveau message par ";" et l'affichage reprendre a ce moment-là .

ce n'est pas genant de ne pas avoir l'affichage le temps de la saisie, validation du nouveau message

Alors il suffit de positionner un boolean lorsque tu reçois un caractère dans traiterSaisieSerie() et tu effaces ledit boolean à la fin du traitement du ;
Il faut ajouter une condition supplémentaire dans:
if (defilementActif && millis() - dernierDéfilement > intervalleDéfilement) {
pour tester l'état du boolean.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.