[SOLVED] pointers and call functions with char[]

Hello everybody,

I’m writing a short function to enable only one of the lines of a basic 2x16 LCD to scroll, while the other line stay still.
My code is working well in the void() function, but as soon as I try to put it in another function to be called, it stops working.

First of all, the working code :

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 13, 8, 9, 5, 11);

int x;
int y;

void setup() {
  Serial.begin(9600);
  delay(500);
  lcd.begin(16, 2);
  lcd.print("Bienvenue");
  delay(2000);
}

void loop() {
 
    int pos = 1; // choice of the line
    char myMsg[] = "abcdefghijklmnopqrstuvwxyz1234567890";
    
    for (x = 0; x < sizeof(myMsg) - 1; x++){ 
    
      if (x+y > sizeof(myMsg)-1){break;}
      
      for (y = 0; y < 16; y++){
        
        if (x+y > sizeof(myMsg)-1){break;}
        lcd.setCursor(y,pos);
        lcd.print(myMsg[x+y]);
      }
      
      if (x == 0) {delay(1000);}
      delay(200); // speed of scrolling
    }
    delay(1000); 

}

The second line of the LCD screen print “abcdefghijklmnop”, wait 1 second, then scroll it for the rest of the chars to appear until “uvwxyz1234567890”, then wait another second, and do it again. Great.

Then the code with a second function :

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 13, 8, 9, 5, 11);

int x;
int y;

void setup() {
  Serial.begin(9600);
  delay(500);
  lcd.begin(16, 2);
  lcd.print("Bienvenue");
  delay(2000);
}

void loop() {
 
    int pos = 1; // choice of the line
    char myMsg[] = "abcdefghijklmnopqrstuvwxyz1234567890";

    scroll(myMsg,1);
 
}

void scroll(char msg[], int pos){
  
  for (x = 0; x < sizeof(msg) - 1; x++){
    
      Serial.println(sizeof(msg));
      if (x+y > sizeof(msg)-1){break;}
      
      for (y = 0; y < 16; y++){
        
        if (x+y > sizeof(msg)-1){break;}
        lcd.setCursor(y,pos);
        lcd.print(msg[x+y]);
      }
      if (x == 0) {delay(1000);}
      delay(200);
    }

    delay(1000); 
}

In that case, the LCD screen only show me the first two chars, “ab”.

Do you have any idea what is the problem ?
thanks for the help,

Simon

I forgot :
As I wrote it in the title, I tried with pointers, but I’m not familiar with these and I only get errors.
My code :

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 13, 8, 9, 5, 11);

int x;
int y;
char *myMsg;

void setup() {
  Serial.begin(9600);
  delay(500);
  lcd.begin(16, 2);
  lcd.print("Bienvenue");
  delay(2000);
}

void loop() {
 
    int pos = 1;
    myMsg[] = "abcdefghijklmnopqrstuvwxyz1234567890";

    scroll(&myMsg,1);
 
}

void scroll(char *msg, int pos){
  
  for (x = 0; x < sizeof(msg) - 1; x++){
    
      Serial.println(sizeof(msg));
      if (x+y > sizeof(msg)-1){break;}
      
      for (y = 0; y < 16; y++){
        
        if (x+y > sizeof(msg)-1){break;}
        lcd.setCursor(y,pos);
        lcd.print(msg[x+y]);
      }
      if (x == 0) {delay(1000);}
      delay(200);
    }

    delay(1000); 
}
      if (x+y > sizeof(myMsg)-1){break;}

sizeof() is the wrong method. strlen() is the correct method.

char msg[200] = "Joe";

sizeof(msg) --> 200 strlen(msg) -->3

In the function, the array is passed as a pointer, despite the way that you have it defined. The sizeof() a pointer is the same as the sizeof() an int - 2 bytes. The strlen() function will return the same value in loop() and in the function.

The problem is here:

      if (x+y > sizeof(msg)-1){break;}

In the first instance, myMsg is an array declared with a size, so sizeof() knows how big the array is. In the second instance, msg is an unsized array, so sizeof() returns the size of the pointer, not the length of the array.

Either make a #defined constant for the array size, and use that, or call strlen() to find the length of the string. You could also modify the function to detect the end of the string ('\0') and stop there. Something like:

if (msg[x+y] == '\0') break;

enjoy,

Thanks a lot for the quick answers. It’s working, here is my final code :

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 13, 8, 9, 5, 11);

int x;
int y;

void setup() {
  Serial.begin(9600);
  delay(500);
  lcd.begin(16, 2);
  lcd.print("Bienvenue");
  delay(2000);
}

void loop() {
 
    char myMsg[] = "abcdefghijklmnopqrstuvwxyz1234567890";
    scroll(myMsg,1);
 
}

void scroll(char msg[], int pos){
  
  for (x = 0; x < strlen(msg) - 1; x++){
 
      if (msg[x + y - 1] == '\0') break;
      
      for (y = 0; y < 16; y++){
        
        if (msg[x + y - 1] == '\0') break;
        lcd.setCursor(y,pos);
        lcd.print(msg[x+y]);
      }
      if (x == 0) {delay(1000);}
      delay(200);
    }

    delay(1000); 
}

There is just a thing, I wanted to declare the array of char before the setup()

char myMsg[128];

and then define it in the loop(),

myMsg[] = "abcdefghijklmnopqrstuvwxyz1234567890";

but it seems that it’s not working that way.

You can only initialize when you create the object. If you want to fill it after that you need to use strcpy():

strcpy(MyMsg, "This is the stuff to put in MyMsg);

The myMsg inside the loop is a different one from the global. What you want is to copy your string into the global one, not declare a new one.

void loop() {
    strcpy(myMsg, "abcdefghijklmnopqrstuvwxyz1234567890");
    scroll(myMsg,1);
}

This is not working anymore with strcpy():

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 13, 8, 9, 5, 11);

int x;
int y;
char myMsg[128];

void setup() {
  Serial.begin(9600);
  delay(500);
  lcd.begin(16, 2);
  lcd.print("Bienvenue");
  delay(2000);
}

void loop() {
 
  strcpy(myMsg, "message message message message message");
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("TEST: ");
  scroll(myMsg,1);
  delay(1000);
  
}

void scroll(char msg[], int pos){
  
  for (x = 0; x < strlen(msg) - 1; x++){
    
      if (msg[x + y - 1] == '\0') break;
      
      for (y = 0; y < 16; y++){
        
        if (msg[x + y - 1] == '\0') break;
        lcd.setCursor(y,pos);
        lcd.print(msg[x+y]);
      }
      if (x == 0) {delay(1000);}
      delay(200);
    }
    delay(1000); 
}

The LCD screen doesn’t write anything on the second line.

This is not working anymore with strcpy():

A few Serial.print() statements are in your future. I don’t see anything obviously wrong.

Except that everything you have in loop() could be done (for testing purposes) in setup(), except the delay().

Working, it was because of this statement:

if (msg[x + y - 1] == '\0') break; // wrong because on the first passage on the loop x+y-1 = -1
if (msg[x + y] == '\0') break; // better

Only thing, I put the minus 1 because the message stopped scrolling at the char before the last one. So now I just have to be sure that I put a space or some other char that won’t be displayed at the end of the char.

Final code:

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 13, 8, 9, 5, 11);

int x;
int y;
char myMsg[128];

void setup() {
  Serial.begin(9600);
  delay(500);
  lcd.begin(16, 2);
  lcd.print("Bienvenue");
  delay(2000);
 
}

void loop() {

  strcpy(myMsg, "message message message message message ");
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("TEST: ");
  scroll(myMsg,1);
  delay(1000);
  
}

void scroll(char msg[], int pos){
  
  for (x = 0; x < strlen(msg) - 1; x++){
    
      if (msg[x + y] == '\0') break;
      
      for (y = 0; y < 16; y++){
        
        if (msg[x + y] == '\0') break;
        lcd.setCursor(y,pos);
        lcd.print(msg[x+y]);
      }
      if (x == 0) {delay(1000);}
      delay(200);
    }
    delay(1000); 

}

Thank you again,

Simon

In your scroll routine, you're using y before you initialize it (at least after the first call to the routine). Clearly, you're getting away with it at the moment - still worth fixing though.

y is a global, so it is guaranteed to be initialized to zero.

Just in case you don't believe me: http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_varinit

Indeed. Not the second time scroll is called though.

Right, very final code, with some comments:

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 13, 8, 9, 5, 11);

int x;
int y;
char myMsg[128];

void setup() {

  Serial.begin(9600);
  delay(500);
  lcd.begin(16, 2);
  lcd.print("Bienvenue");
  delay(2000);

  strcpy(myMsg, "GO-scrolling message scrolling message scrolling message-STOP_"); // put an extra char at the end of the message, which won't be displayed
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("MESSAGE: "); // This message wont move
 
}

void loop() {

  scroll(myMsg,1); 
  
}

void scroll(char msg[], int pos){
  
  x = 0;
  y = 0;

  for (x = 0; x < strlen(msg) - 1; x++){

      if (msg[x + y] == '\0') break; // out of the loop at the end of message
      
      for (y = 0; y < 16; y++){ // for a 2x16 LCD screen
        
        if (msg[x + y] == '\0') break;
        lcd.setCursor(y,pos); // pos is the line where the message will appear: 0 is first line, 1 is second line.
        lcd.print(msg[x+y]);
      }
      if (x == 0) delay(1000); // wait 1 second at the beginning of the message
      delay(200); // speed of scrolling
    }
    delay(1000); // wait 1 second when message is at its end

}

Just a couple of things about your code.

If you pass in a string < 16 characters, it will fail. And if pos is > 1, I don’t know what will happen.
Also, use unsigned ints to prevent accidentally using a negative number. If you are going to use strlen() anyway, then you can avoid testing for the \0 character.

The code can be tightened up a bit. Here’s an example.

#define LINELEN 16
#define LINES   2

void scroll(char *msg, unsigned int pos) {
        unsigned int l = strlen(msg);
        unsigned int x, y;

        if (pos >= LINES) return;
        lcd.setCursor(0, pos);
        if (l <= LINELEN) {
                delay(1000);
                lcd.print(msg);
                delay(1000);
                return;
        }
        for (x = 0; x <= l - LINELEN; x++) {
                for (y = x; y < x + LINELEN; y++) {
                        lcd.print(msg[y]);
                }
                if (x == 0) delay(800);
                delay(200);
                lcd.setCursor(0, pos);
        }
        delay(800);
}

Sorry, wildbill…

grumble grumble…reading compreshension…grumble grumble