Texte défilant sur Deulignes Snootlab

Bonjour à tous,

J'essaie de faire un texte défilant avec le shield LCD "Deulignes" de Snootlab mais le problème c'est qu'il se fait sur les 2 lignes alors que je n'en voudrais qu'une :

  • La ligne du haut pour le texte défilant sous forme de phrase
  • La ligne du bas pour d’éventuelles données supplémentaires à afficher

Pour le moment je n'ai fait que le test de la 1ère ligne.

Voici mon code :

#include "Wire.h"
#include <Deuligne.h>

char message[] = "TEST TEXTE DEFILANT ...............";
int i;

Deuligne lcd;

void setup() {
  Wire.begin(); // Départ Wire
  lcd.init(); // initialisation LCD
  lcd.setCursor(16,0); // Installation du curseur à 0,0
  //delay(5000); // 5 secondes de délai
  lcd.leftToRight();  //indique que le texte doit être déplacer vers la gauche
  lcd.autoscroll();
}

void loop() {
  for(i=0; i<sizeof(message)-1; i++){
    lcd.print(message[i]);
    delay(500);
  }
}

Si quelqu'un voit un problème, je le remercie d'avance :slight_smile:

Salut,

Et oui print() est bien foutu et va à la ligne quand il le faut :wink:

Par contre j'ai pas pigé leur logique sur le Deuligne.h, visiblement c'est pas du scrolling ... Y'a une manière simple de le faire. Il suffit de créer un tampon de 16 char puisqu'il y a 16 caractères sur une ligne et de recopier la partie qui t'interesse.

#include "Wire.h"
#include <Deuligne.h>

char message[] = "TEST TEXTE DEFILANT ...............";
int i;

Deuligne lcd;

void setup() {
  Wire.begin(); // Départ Wire
  lcd.init(); // initialisation LCD
}

void loop() {

for(y=0;y<strlen(message);y++) {

 lcd.clear();
lcd.setCursor(16,0); // Installation du curseur à 0,0

  for(i=0; i<16; i++){ 
if(i+y>strlen(message)) lcd.print(" ");
else lcd.print(message[i+y]);
 }
    delay(500);
  }
}

Normalement ça doit marcher, mais à moitié, c'est à dire que ça va défilé vers la gauche mais pas revenir par la droite. Je vais pas tout faire non plus :wink:

Bonjour,

Pour compléter la solution de B@tto : il est aussi possible d'utiliser un modulo pour faire un défilement fluide (qui ne s’arrête pas).

Bonjour,

Je vais tester cette solution, en revanche pour le modulo, puis-je en savoir plus ?

meteo59223:
Je vais tester cette solution, en revanche pour le modulo, puis-je en savoir plus ?

En gros tu as une boucle qui passe en revu chaque colonne de l'écran et une variable qui défini le point de départ de l'affichage du message. Et à chaque fois tu affiches un caractère du message, en repartant du début du message quand tu arrives à la fin.

message="test "
depart_msg = 0

  • En boucle :
    -- revient à la ligne N, colonne 0
    -- Pour i de 0 à 15:
    --- affiche_char(message[depart_msg])
    --- depart_msg = (depart_msg + 1) % strlen(message)
    -- attente 1s (par exemple)

(prévoir un espace en fin de message sinon le dernier et le premier mot du message seront collés ensembles)

Bonsoir,

Je vois ce que vous voulez dire, un peu comme un array en 2 dimensions (je me comprends :grin: ).

Je vais tester tout ça et je vous dis, merci pour votre aide à tous :wink:

Re-Bonsoir,

J'ai trouvé une alternative au script de B@tto en pensant à la fonction php substr() (pour ceux qui connaissent) ; par contre je n'ai pas suivi le modulo voulant que la fin du texte part à gauche totalement avant de revenir au début. Merci de m'avoir mis sur la voie en tout cas, ça a fait tilt :grin: .

Ca fonctionne impeccable malgré un peu de bidouillage. La 1ère boucle fait défiler le texte de gauche à droite sur les 16 colonnes de la 1ère ligne ;et une fois arrivée au bout la 2ème boucle prends le relais en tronquant par le début la phrase et ce jusqu'à ce que tous les caractères comptés y passent, et ainsi de suite.

#include "Wire.h"
#include <Deuligne.h>

char message[] = "Matinee fraiche et brumeuse sur beaucoup de regions avant une apres-midi ensoleillee du Nord au Sud et de l'Est a l'Ouest.";
int delai = 500;

Deuligne lcd;
String message2 = message;

void setup() {
  Wire.begin(); // Départ Wire
  lcd.init(); // initialisation LCD
}

void loop() {

    for(int i=16;i>0;i--){
     lcd.clear();
     lcd.setCursor(i,0);
     lcd.print(message2.substring(0,16));
     delay(delai);
    }
    
    for(int i=0;i<=sizeof(message)-1;i++){
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(message2.substring(i,i+16));
      delay(delai);
     }
}

En revanche, lors de la mise en fonction pour faire plus propre et réutiliser à plusieurs reprises dans un futur script, j'ai un problème avec le sizeof() de la 2ème boucle qui ne me compte que 2 caractères au lieu de la totalité ?!? Alors que dans le script précédent ça marche impeccablement.

#include "Wire.h"
#include <Deuligne.h>

Deuligne lcd;

void setup() {
  Wire.begin(); // Départ Wire
  lcd.init(); // initialisation LCD
}

void loop() {

textDefilantLCD("Test du texte defilant.", 400);

  }

void textDefilantLCD(char message[], int delai){
  String message2 = message;
    for(int i=16;i>0;i--){
     lcd.clear();
     lcd.setCursor(i,0);
     lcd.print(message2.substring(0,16));
     delay(delai);
    }
    
    for(int i=0;i<=sizeof(message)-1;i++){
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(message2.substring(i,i+16));
      delay(delai);
     }
}

Me suis-je trompé quelque part ? J'espère que oui :frowning:

for(int i=0;i<=strlen(message);i++){

au lieu de

for(int i=0;i<=sizeof(message)-1;i++){

sizeof() => taille totale, même les caractères null
strlen() => nombre de caractère jusqu'à la fin de chaine (soit le premier caractère null rencontré)

oui, mais, l'un fonctionne et pas l'autre.
ca viens du passage a la fonction, sizeof retourne toujours 2, histoire de pointeurs, certainement.
j'ai pas approfondi, juste posté une solution simple.

Oui exact, il faut soit utilisé strlen() ou bien faire le sizeOf() à l'appel :

#include "Wire.h"
#include <Deuligne.h>

Deuligne lcd;

void setup() {
  Wire.begin(); // Départ Wire
  lcd.init(); // initialisation LCD
}

void loop() {

char texte[]="Test du texte defilant.";
textDefilantLCD(Texte,sizeOf(Texte), 400);

  }

void textDefilantLCD(char message[], int size, int delai){
  
String message2 = message;

    for(int i=16;i>0;i--){
     lcd.clear();
     lcd.setCursor(i,0);
     lcd.print(message2.substring(0,16));
     delay(delai);
    }
    
    for(int i=0;i<=size-1;i++){
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print(message2.substring(i,i+16));
      delay(delai);
     }
}

Et de mémoire 1 byte pour le pointeur et un pour son type char = 2 bytes

Si c'est un type int ça donnerait 3 donc si j'ai raison

Les pointeurs sont des int, donc 2 bytes sur un système 16 bits, et ne contiennent pas leur type.

donc sizeof(void*) = sizeof(char*) = sizeof(long long long*) = sizeof(ptr_t)

La seule différence est sizeof(array statique) = taille * sizeof(élément d'une cellule).

sizeof() => taille totale, même les caractères null
strlen() => nombre de caractère jusqu'à la fin de chaine (soit le premier caractère null rencontré)

Je n'avais pas pensé à strlen() en effet ! Mais je ne savais pas que ça ne comptait pas les caractères NULL ; ayant l'habitude du PHP je n'ai jamais eu ce souci, à moins que ça ne soit différent en C++ ?

Oui exact, il faut soit utilisé strlen() ou bien faire le sizeOf() à l'appel :

char texte[]="Test du texte defilant.";

textDefilantLCD(Texte,sizeOf(Texte), 400);

Je vais tester ces 2 moyens de ce fait et je vous dis quoi, merci pour votre aide :wink:

Bonjour,

Pour en finir j'ai utilisé string.length() pour faire mes texte défilants et ça marche impeccable.

Maintenant le problème que j'ai, c'est qu'apparemment ma RAM arrive à saturation avec les longues chaines de caractères que je souhaite faire défiler, car certaines ne s'affichent pas entièrement, selon leur longueur ...

Mon code :

#include <SPI.h>

#include "Wire.h"
#include <Deuligne.h>

#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EthernetUdp.h>
#include <util.h>

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // Attribution d'une MAC

IPAddress server(xx, xx, xx, xx); // Connexion au serveur distant

Deuligne lcd; // Préparation LCD
EthernetClient client; // Préparation Ethernet mode Client

void setup()
	{
	Wire.begin(); // Départ Wire
	lcd.init(); // initialisation LCD
	// Obtention d'une adresse IP par DHCP
	if (!Ethernet.begin(mac)){textDefilantLCD("Probleme de connexion au serveur distant.", 200, 0); for(;;);}  // Si erreur
	}

void loop()
	{
	// Préparation des variables
	String str;
	String var1 = "500";
	String var2 = "2";
	String var3 = "Actuellement indisponible.";
	String var4 = "Actuellement indisponible.";
	String var5 = "Actuellement indisponible.";
	String init = "0";
	char c;
	
	// Si connexion réussie, on bosse
	if (client.connect(server, 80))
		{
		client.println("GET http://urlsitedistant.com/fichieralire.xml HTTP/1.1"); // Requête GET vers le serveur distant
		client.println("Host: localhost");
		client.println("Accept: */*"); // */
		client.println();
		client.println();
		}
		
	// Sinon on stoppe et erreur
	else
		{
		textDefilantLCD("Probleme de recuperation des donnees distantes.", 500, 0); // Si erreur lors de la connexion
		return; // Quitte loop()
		}
	
	// Boucle infinie
	for(;;)
		{
		
		// Si des données sont disponible sur l'objet EthernetClient
		if(client.available())
			{
			c = client.read(); // Lecture d'un octet
			
			// Si fin de ligne atteinte
			if(c == '\n') 
				{
				// Variable de l'init
				if(str.startsWith("<init>"))
					{
					str.replace("<init>", "");
					str.replace("</init>", "");
					init = str;
					}
					
				// Variable 1
				if(str.startsWith("<var1>"))
					{
					str.replace("<var1>", "");
					str.replace("</var1>", "");
					var1 = str;
					}
					
				// Variable 2
				if(str.startsWith("<var2>"))
					{
					str.replace("<var2>", "");
					str.replace("</var2>", "");
					var2 = str;
					} 
					
				// Variable 3
				if(str.startsWith("<var3>"))
					{
					str.replace("<var3>", "");
					str.replace("</var3>", "");
					var3, str;
					} 
       
				// Variable 4
				if(str.startsWith("<var4>"))
					{
					str.replace("<var4>", "");
					str.replace("</var4>", "");
					var4, str;
					}
					
				// Variable 5
				if(str.startsWith("<var5>"))
					{
					str.replace("<var5>", "");
					str.replace("</var5>", "");
					var5, str;
					} 
					
				if(str.startsWith("end")){break;}  // Sort de la boucle infini
				str = ""; // Vidage de la ligne
				} 
				
			else str += c; // Concaténation de l'octet reçu dans la chaîne de char
			}
			
		if(!client.connected()){break;}
		}
	client.stop();
		
	lcd.clear();
	
	MessageDefilant("Message 0", init, var1.toInt(), var2.toInt());
	MessageDefilant("Message 1", var3, var1.toInt(), var2.toInt());
	MessageDefilant("Message 2", var4, var1.toInt(), var2.toInt());
	MessageDefilant("Message 3", var5, var1.toInt(), var2.toInt());
	}

// Fonction de conversion StringToChar
char* StringToChar(String s) 
	{
	unsigned int bufSize = s.length() + 1; //String length + null terminator
	char* ret = new char[bufSize];
	s.toCharArray(ret, bufSize);
	return ret;
	}

// Fonction de texte défilant
void textDefilantLCD(String message, int delai, int ligne)
	{
	// Ajouter une boucle infinie avec delay() dans le but de faire une continuité du texte défilant
	for (int i=16; i>0; i--)
		{
		lcd.clear();
		lcd.setCursor(i,ligne);
		lcd.print(message.substring(0, 16));
		delay(delai);
		}
    
	for (int i=0; i <= message.length(); i++)
		{
		lcd.clear();
		lcd.setCursor(0,ligne);
		lcd.print(message.substring(i, i+16));
		delay(delai);
		}
	}

// Fonction de messages defilants
void MessageDefilant(String titre, String message, int delai, int passages)
	{
	String message2 = "                ";
	message2 += message;
	message2 += " ";
	
	lcd.clear();
	lcd.setCursor(0,0);
	lcd.print(titre);
	for(int j = 1; j <= passages; j++)
		{
		for (int i=0; i <= message2.length(); i++)
			{
			lcd.setCursor(0,1);
			lcd.print(message2.substring(i, i+16));
			delay(delai);
			}
		}
	}

Mon fichier distant :

<init>1</init>\n
<var1>200</var1>\n
<var2>1</var2>\n
<var3>Message 1</var3>\n
<var4>Message 2</var4>
<var5>Message 3</var5>\n
end

A ce moment, 2 solutions que j'envisage :

- Utiliser la librairie FLASH qui stockera ces longues phrases dans la flash memory. Mais cette librairie fait des erreurs à la compilation sous IDE 1.0.6, malgré les manipulations expliquées ici : http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.LibrairieFlashProgramme . Si j'utilise l'IDE 0023, c'est le reste de mon code qui créé des erreurs ...

(Ne pouvant pas copier mon code car je dépasse le nombre de caractère autorisé du post-forum, je vous montre uniquement les variables changées)

...
#include <Flash.h>
...
FLASH_STRING(var3, str);
...
FLASH_STRING(var4, str);
...
FLASH_STRING(var5, str);

Et les erreurs :

sketch_oct04a.ino: In function 'void loop()':
sketch_oct04a:102: error: initializer fails to determine size of 'var3_flash'
sketch_oct04a:110: error: initializer fails to determine size of 'var4_flash'
sketch_oct04a:118: error: initializer fails to determine size of 'var5_flash'

- Avec une carte SD : Faire un code qui mettra mes longues chaines de caractères dans un fichier propre à chacune, que je relis un par un pour faire les défilements de cette façon :

  1. Récupération, traitement des données et créations des 3 fichiers sur la carte SD (toutes les heures).
  2. Création variable, récupération chaine de caractère 1 dans fichier 1, Affichage sur LCD, destruction variable.
  3. Création variable, récupération chaine de caractère 2 dans fichier 2, Affichage sur LCD, destruction variable.
    etc ... etc ...

Mais j'aimerais avoir l'avis des connaisseurs avant de me casser la tête à essayer cette dernière solution (et éviter d'acheter une carte SD aussi :slight_smile: ) si je ne trompe pas complètement ...

Merci à vous ! Bonne soirée :wink: .

au lieu de copier de code, tu peut joindre un/des fichier(s).

tu as essayé avec l'ise 1.0.5?

Bonjour,

Ah je n'avais pas pensé à joindre les fichiers :grin: .

Donc :

  • Fichier 1 => Script sans flash.h .
  • Fichier 2 => Script avec flash.h

J'ai testé avec l'IDE 1.0.5 et plus d'erreurs apparaissent, notamment au niveau du Deuligne :

In file included from sketch_oct05a.ino:4:
C:\Program Files\Arduino\libraries\Deuligne/Deuligne.h:68: error: conflicting return type specified for 'virtual void Deuligne::write(uint8_t)'
C:\Program Files\Arduino\hardware\arduino\cores\arduino/Print.h:48: error: overriding 'virtual size_t Print::write(uint8_t)'
sketch_oct05a.ino: In function 'void loop()':
sketch_oct05a:108: error: initializer fails to determine size of 'alerte_flash'
sketch_oct05a:116: error: initializer fails to determine size of 'previsions_flash'
sketch_oct05a:124: error: initializer fails to determine size of 'observations_flash'

Donc je suis un peu perdu ... :frowning:

fichier1.txt (4.39 KB)

fichier2.txt (4.45 KB)

problem sur la version de la biblioteque deulignes.
celle de github pose probleme pour ide 1.0.x

prendre celle ci:
http://forum.snootlab.com/viewtopic.php?f=34&t=148#p497

j'ai pas trop compris, ou c'est toi qui n'a pas compris, ce que t'as essayer de faire avec Flash.

ton code avec Flash ne peut pas fonctionner.
Les données en Flash ne sont pas modifiable la l'execution, elles ne sont pas en Ram.
ils doivent donc etre declaré avant setup et loop et seront créées en Flash au moment de la compilation.

le lien de la lib Flash (v3) que tu donne n'est pas fais pour l'ide 1.0.5.
pour que la librairie Falsh fonctionne, il faut modifier le print. malgré la modif, ca ne marche pas.

essaye celle ci(v5):

Bonsoir,

J'ai testé avec la version 5 mais toujours les mêmes erreurs à la compilation.

Par contre si il faut déclarer en dehors du loop() ou dans le setup(), c'est normal que ce que j'ai fait ne marche pas ... Peut-être qu'en effet je n'ai pas bien compris l'utilisation de cette librairie et de la mémoire flash :expressionless:

Comme je dois impérativement récupérer ces longues chaines de caractères dans un fichier distant régulièrement (minimum chaque 30 min), je n'ai pas le choix que de travailler dans loop().

Comment je peux faire à ce moment ? Avec la solution carte SD ?

quelle est la quantitée de donné que tu recoi toutes les 20 min?
combien de temps est tu censé conserver ces données?
quelle µC utilise tu?
combien de trame est tu censé avoir simultanément en Ram?

en fonction des reponses, les solutions possible seront:

  • EEprom,
  • Eprom serie externe,
  • carte SD.
  • changer de carte,