Wanting to scroll messages on a "display"

I bought an 8 digit 7 segment display. SPI.

This one

It works and I get most of how to use it.

But I am stuck when I want to display an IP number which is longer than the display.

This is the first bit of the code:

void Show_IP_on_Display()
{
  header(3);

  char message[16];
  uint8_t *IpPtr = &(WiFi.localIP()[0]);
  sprintf(message, "%u.%u.%u.%u", WiFi.localIP()[0], WiFi.localIP()[1], WiFi.localIP()[2], WiFi.localIP()[3]);

  //Serial.println(message);
 
  byte x = format(message);
  message_display();
  Serial.println("Message displayed.  Wiping display");
  delay(600);
  //post_message_wipe();
  wipe(15);
}
void message_display()
{
  //
  Serial.println("Displaying message on display now");
  byte foo = 0;
  byte data = 0;    //  What is read.
  while (foo < bmessage_length)
  {
    //
    data = bmessage[foo];
//    Serial.print("Digit being sent to display ---->  ");
//    Serial.println(data);
//    delay(100);
    start(data);
    foo = foo + 1;
    delay(delay_time);
  }
}

Which splits up the IP number to littler numbers then prints them on the display.

Before you complain:
I probably haven't shown enough of the code. Sorry.

The entire code is probably too big to want someone to sit down and go through it.

I am also going to re-write a lot of it as the needs have changed and HOW it does things is also re-designed.
I shall have two of these displays (16 digits in total) as two rows of eight.
They will be then divided into 4 x 4 areas.
I will control what is displayed in these 4 sections upstream.
If I want to display an 8 digit message (time/date eg) then it will be sent to the left most of the two places and the right one won't be sent anything.

But that's in the future and at some stage I will need to get this part working.

It is pretty well documented, but as I am kind of new here, I don't want to annoy anyone.

The idea to display the entire IP number is something like this:

1 - Brake the IP number into smaller parts.
2 - Wipe the display.
3 - Print the indexed digit on the display at position 0. (Right most actually)
4 - Loop:
5 - Move all digits right one position. Any at extreme left are lost.
6 - Increase index ++1 and display digit at position 0.
7 - repeat.

So if my IP is (say) 192.168.2.200
The display would be:
(x means blank)
xxxxxxx1
xxxxxx19
xxxxx192
xxxx192.1
xxx192.16
xx192.168.
x192.168.2.
192.168.2.2
92.168.2.20
2.168.2.200
168.2.200x
68.2.200xx
8.2.200xxx
2.200xxxx
200xxxxx

and so on until the display is wiped.

Then it goes back to what it was doing.

I nearly have it but it doesn't shunt the last 2 digits onto the display.
All I get to see is 192.168.2.2

I can post the entire code - but it has a lot of old code in it as it evolved, some of which is no longer used. Yeah, I should get it deleted.

But to the best of my knowledge, I split up the IP number into an array/thing and it is read from left to right and it prints the current digit at the right most position and shoves all others left one position before that.
Decimal points are handled ok. Or they seem to be.

Thanks in advance.

Then shunt them. What else can anyone realistically say about it? Imagine that you were asked to solve this, knowing only what you've said...

Well, I get the IP address, stick 8 spaces on the end, but it doesn't get past showing only the first 8 digits.

So the entire message being parsed is >192.126.2.200 < (Argh! can't show multiple spaces here.)
All I get to see on the display is 192.168.2.2

I'll have another look at it soon - now I have the library problem sort of resolved.

Write an MRE, minimum reproducible example. I'll bet, when you do, you won't even need to post it because you might make it work. If not, you could post the MRE and get help.

Why don't you just post the full code? Posting bits of the code is useless to anyone that might be inclined to try and help.

Thanks.

The entire code is an abortion and really it isn't addressing the problem.

I checked what I thought was right: and it isn't. It doesn't do what I want.
It just prints the IP address along the screen, rather than scrolling it.

It has been so long since I have done this and I am not a good programmer.

This is what I have so far:

(but it doesn't work for reasons I'll explain after the code)

#define MAX7219DIN D1
#define MAX7219CS D2
#define MAX7219CLK D3

unsigned long n=13000;

char bmessage[] = {1,9,130,1,6,136,128,2,3,4};    //  IP address encoded with deciaml points.
char msg_buffer[] = {15,15,15,15,15,15,15};   //  not sure if I need this.
//  IDEA: This is 8 x blanks on the display.
//        The new value is injected at the right most position.
//        Then in the loop, the values are moved 1 position left every time
//        and the new value is added in the right most position.
//        Then the new message is displayed.

void setup() 
{
  MAX7219init();
  MAX7219brightness(15);
}

void loop() 
{
  //
  //
  //
  wipe(15);
  delay(200);
  test();
  delay(800);
  
}

void test()
{
  //
  byte loop_counter = 1;
  byte display_pointer = 0;
  byte display_size = 8;
  byte other_pointer = 0;
  byte msg_length = 10;   //  This needs to be able to get the real value.
  char position_zero = " ";
  //
  //
  //msg_buffer[0] = bmessage[0];
  position_zero = msg_buffer[(msg_length - other_pointer)];
  while (loop_counter < msg_length)
  {
    //
    MAX7219senddata(0,msg_buffer[(msg_length - other_pointer)]);
    //
    while (other_pointer < display_size)
    {
      //  This moves the displayed number on the display.
      //
      MAX7219senddata(display_size-other_pointer,
    }

    other_pointer = other_pointer + 1;
    //  position / data
    MAX7219senddata((display_size - other_pointer),
    //  Adjust index as needed
    
    //
    //
    delay(1000);
  }
}
//------------------------------------------------------------
void wipe(byte w)
{
  Serial.println("Wipe");
  for (byte i = 0; i < 8;)
  {
    MAX7219senddata(i + 1, w);
    i = i + 1;
  }
}
//------------------------------------------------------------
void MAX7219senddata(byte reg, byte data){
  digitalWrite(MAX7219CS,LOW);   //CS on
  for(int i=128;i>0;i=i>>1){
    if(i&reg){
      digitalWrite(MAX7219DIN,HIGH);
    }else{
      digitalWrite(MAX7219DIN,LOW);      
    }
  digitalWrite(MAX7219CLK,HIGH);   
  digitalWrite(MAX7219CLK,LOW);   //CLK toggle    
  }
  for(int i=128;i>0;i=i>>1){
    if(i&data){
      digitalWrite(MAX7219DIN,HIGH);
    }else{
      digitalWrite(MAX7219DIN,LOW);      
    }
  digitalWrite(MAX7219CLK,HIGH);   
  digitalWrite(MAX7219CLK,LOW);   //CLK toggle    
  }
  digitalWrite(MAX7219CS,HIGH);   //CS off
}

void MAX7219brightness(byte b){  //0-15 is range high nybble is ignored
  MAX7219senddata(10,b);        //intensity  
}

void MAX7219init(){
  pinMode(MAX7219DIN,OUTPUT);
  pinMode(MAX7219CS,OUTPUT);
  pinMode(MAX7219CLK,OUTPUT);
  digitalWrite(MAX7219CS,HIGH);   //CS off
  digitalWrite(MAX7219CLK,LOW);   //CLK low
  MAX7219senddata(15,0);        //test mode off
  MAX7219senddata(12,1);        //display on
  MAX7219senddata(9,255);       //decode all digits
  MAX7219senddata(11,7);        //scan all
  for(int i=1;i<9;i++){
    MAX7219senddata(i,0);       //blank all
  }
}

The idea is/was that the display has 8 digits.
They are (left to right) 7,6,5,4,3,2,1,0

So, I would write the first value to position 0.
Then I would loop and move what is in 6 to 7. 5 to 6. 4 to 5, etc.
When 0 gets moved to 1, the next value would be put in to 0.
This would repeat until all 10 digits of the IP address were shown.
(The extra 8 spaces to then wipe the display aren't really needed.... I thought it would look nice/r than just stopping after showing the IP address)

But as I said: It has been WAY TOO LONG since I have done anything like this.

I can't get my head around how to do it.

I was trying 2 loops, but I now see that is wrong. It is only 1 loop that is invoked 10 times (the length of the IP address).

If I can get this working the rest of the code is nothing to worry about - just now.

I'll see if I can work out the other things then.
Here/now I just want to get my head around how to scroll the IP address.

Maybe try something like this...


const uint8_t DISPLAY_SIZE = 8;
const uint8_t MESSAGE_MAX  = 20;

char myDisplay[DISPLAY_SIZE];
char myMessage[MESSAGE_MAX]  = "192.168.1.117        ";


void setup()
{
  Serial.begin(9600);
  delay(500);

  //Clear the display
  for (uint8_t y = 0; y < DISPLAY_SIZE; y++)
  {
    myDisplay[y] = ' ';
  }
}

void loop()
{

  // Loop through the characters of the message we want to display.
  for (uint8_t x = 0; x < MESSAGE_MAX; x++)
  {
    // Shuffle the characters left along the display.
    for (uint8_t y = 0; y < (DISPLAY_SIZE - 1); y++)
    {
      myDisplay[y] = myDisplay[y + 1];
    }
    
    // Move a character from the message into the last character of the display.
    myDisplay[DISPLAY_SIZE - 1] = myMessage[x];

    // Display the output.
    for (uint8_t y = 0; y < DISPLAY_SIZE; y++)
    {
      Serial.print(myDisplay[y]);      
    }
    Serial.println();
    delay(300);
  }
}

1 Like

Thanks.

I shall have to look at that code and study it.

In the mean time I worked out this code:

(Only the main bit)

  while (display_pointer < msg_length)
  {
    //
    MAX7219senddata(0,msg_buffer[(display_pointer)]);
    //
    while (loop_counter < msg_length)
    {
      //  This moves the displayed number on the display.
      //
      MAX7219senddata(display_size-loop_counter,msg_buffer[display_size - loop_counter -1]);
      loop_counter = loop_counter + 1;
    }
    loop_counter = 0;

    other_pointer = other_pointer + 1;
    //
    delay(1000);
  }

Would this also work?

Again: Thanks.

Alas because of things I can't understand the lines like:

for (uint8_t y = 0; y < DISPLAY_SIZE; y++)

are traps for me.
Partly because I see uint as unit and that really hurts me reading it.

I'm not seeing how y is reset to 0 after that loop.
In my code there is a line that resets that counter back to 0.

I got to the code I have by trying it in JavaScript. I know that is a whole different beast but I use it a lot more than C++, which is a lot more like what is used here.

If I get excited/motivated I'll try to give it a go later on today.

uint8_t is just a variable type. unsigned integer, 1 byte long. You could use:

for (int y = 0; y < DISPLAY_SIZE; y++)

If you don't understand for loops then just check for - Arduino Reference

Again: Thanks.

I think I need exposure to the language more than I am getting.

Alas I am exposed to JavaScript more with what I am doing. But......

Could you look at what I posted and do a sanity check?

I am pretty sure it should work as it showed a good result when I tested it in JavaScript.
Ok, the order may not be exact - reversed? But that is just a maths function to reverse how one pointer steps.

Your code doesn't even compile.

I have no idea what the MAX7219 routines are that you are calling? You don't appear to have included any external libraries where these might be defined?

Sorry. The display I am using is at the top of the thread/post. "this one".

This one.

Manuals

Software

I was more meaning just how I did/wrote it.

Alas I tried it and it is not playing fair.
Despite it worked ok for structure and what I was seeing being spat out.

:frowning:

Post a minimal sketch which can write "HELLO WO" to your MAX7219 based display.
It will then be trivial to have it adapted it for you to scroll a sample IP address on the basis of the code that @red_car has already provided.

char myMessage[MESSAGE_MAX] = "192.168.1.117 ";

(With all the extra spaces at the end)
Gets error:

exit status 1
initializer-string for array of chars is too long [-fpermissive]

Don't worry. I think it is the line above:
const uint8_t MESSAGE_MAX = 20;

Changed it to 30 and all is happy.

It isn't that easy, sorry.

I have the code that @red_car posted working.

It works, but there are problems with it. Not blaming.
It fills the screen with 0s. Blank (empty) points are 15. (Not spaces as it may not be shown.)
If there is a decimal point the number before it needs its value to be increased by 128.
(the 7'th bit indicates to the board to add the decimal point)

After the IP address scrolls off, it is appended with 0's rather than 15 (digit off)

How I got around the decimal point problem is I got the original IP address and parsed it for .
If that was found, it winds back the pointer and added 128 to the previous digit. Then stepped the counter +2 to skip the .

Then that is used by the code to scroll the message across the display.

So I am stuck with using the code posted and using it to save it to another message and then scrolling it along the display/screen.

So I guess the conversion will happen at the start and parse the message and do the trick with the . and adjusting the value.

Then send that new message to the code supplied.
Then I'll just have to find a way to see the and replace that with 15.

It isn't so much getting the message on the screen. It is parsing the message and modifying the digits that precede a . and add 128 to their value.
Then once I have that made: given the code given all should work.

Sorry if I seem bad at sharing information. I'm not in the best of mental health and it is making it even worse for me to share.

You can't copy my original code exactly... it was just an example.

The display you are using uses low level commands to communicate with the Arduino.

I have tried to combine your code in the example below.. no guarantee it will work - I don't have a display to test with. Try it... if it doesn't hopefully you can tweak to get working.

One thing - are you using Pin 1 on the Arduino? Usually this is not a good idea as pins 0 & 1 are used for Serial communication, which is very useful for debugging.

#define MAX7219DIN 1
#define MAX7219CS  2
#define MAX7219CLK 3  


const byte    DISPLAY_SIZE = 8;
const uint8_t MESSAGE_SIZE = 20;

byte message[MESSAGE_SIZE] = {1,9,130,1,6,136,128,2,3,4,15,15,15,15,15,15,15,15,15,15};  // 192.168.0.234   
byte display[DISPLAY_SIZE];

void setup() 
{
  
//  Serial.begin(9600);
//  delay(500);
  
  MAX7219init();
  MAX7219brightness(15);
}

void loop() 
{
  // Clear the display
  fill (15);
  delay(1000);

  // Display the message
  test();
  delay(800);
}

void test()
{

 // Loop through the characters of the message we want to display.
  for (uint8_t x = 0; x < MESSAGE_SIZE; x++)
  {
    // Shuffle the characters left along the display.
    for (uint8_t y = 0; y < (DISPLAY_SIZE - 1); y++)
    {
      display[y] = display[y + 1];
    }
    
    // Move a character from the message into the last character of the display.
    display[DISPLAY_SIZE - 1] = message[x];

    // Display the output.
    for (byte y = 0; y < DISPLAY_SIZE; y++)
    {
//      Serial.print(display[y], HEX); 
//      Serial.print(" "); 
           
      MAX7219senddata(y + 1, display[y]);
    }
    
//    Serial.println();
    delay(300);
  }
}


//------------------------------------------------------------


void fill (byte w)
{
//  Serial.println("fill");
  for (byte i = 1; i <= DISPLAY_SIZE; i++)
  {
    MAX7219senddata(i, w);
  }
}


//------------------------------------------------------------
void MAX7219senddata(byte reg, byte data){
  digitalWrite(MAX7219CS,LOW);   //CS on
  for(int i=128;i>0;i=i>>1){
    if(i&reg){
      digitalWrite(MAX7219DIN,HIGH);
    }else{
      digitalWrite(MAX7219DIN,LOW);      
    }
  digitalWrite(MAX7219CLK,HIGH);   
  digitalWrite(MAX7219CLK,LOW);   //CLK toggle    
  }
  for(int i=128;i>0;i=i>>1){
    if(i&data){
      digitalWrite(MAX7219DIN,HIGH);
    }else{
      digitalWrite(MAX7219DIN,LOW);      
    }
  digitalWrite(MAX7219CLK,HIGH);   
  digitalWrite(MAX7219CLK,LOW);   //CLK toggle    
  }
  digitalWrite(MAX7219CS,HIGH);   //CS off
}

void MAX7219brightness(byte b){  //0-15 is range high nybble is ignored
  MAX7219senddata(10,b);        //intensity  
}

void MAX7219init(){
  pinMode(MAX7219DIN,OUTPUT);
  pinMode(MAX7219CS,OUTPUT);
  pinMode(MAX7219CLK,OUTPUT);
  digitalWrite(MAX7219CS,HIGH);   //CS off
  digitalWrite(MAX7219CLK,LOW);   //CLK low
  MAX7219senddata(15,0);        //test mode off
  MAX7219senddata(12,1);        //display on
  MAX7219senddata(9,255);       //decode all digits
  MAX7219senddata(11,7);        //scan all
  for(int i=1;i<9;i++){
    MAX7219senddata(i,0);       //blank all
  }
}

My suggestion for at least one of your problems is not to attempt to display a '.' (dot) in the IP address. Display a '-' (minus sign) made from the middle segment of the seven segment display. The dot is more complicated to handle because a digit plus a dot takes up only one and not two display positions.

The original code I have shows the IP address quite happily.

But for the fact the display isn't long enough to show all the digits and it isn't scrolled onto the display.

Using a - takes up another digit on the display.

I'm trying @red_car latest post.

@red_car
I would nearly give you a hug, but I'm not sure that is allowed these days.

Alas, I have sat here for the past long time trying to get my head around the only problem I can see at this point in time.

The IP address scrolls RIGHT TO LEFT. Not LEFT TO RIGHT.

That shouldn't be a big deal.

I simply reverse how the message is displayed on the screen.
I'm sure it is something to do with this line:
display[DISPLAY_SIZE - 1] = message[x];

Because DISPLAY_SIZE is 8.
Though I am not sure how this differs from display[DISPLAY_SIZE]

It really as me perplexed.
From what I can see all the loops are the right way around.

Could you (please) expand out those loops so they are written for idiots (me) to read better.

That is kind of not helping me either. But I can see it works (all be it backwards across the screen) I can't see it.

Also.... Thinking about it.
When it moves (shuffles) the displayed value left on the display:
It only needs to move the number of digits of the IP address (up to the DISPLAY_SIZE) left by the number of digits shown.
Looping 8 times each time seems extraneous.

So the move left pointer would be incremented to mirror the number of digits of the IP address shown.

And, ideally: Outside the loops - or maybe just inside them - the value should be written to position 0 of the display.
But that is only after the others have been moved left.

I can't find where that is happening. Though I suspect it is that line above I mentioned.
Given the scroll is left to right.

Again: I am sorry. I prefer to work things out for myself. But the structure of the arduino code has me at a big disadvantage.

I feel I have the structure as I posted (I hope) before.
(Ah, here it is. Though the order it is stored maybe back to front also)

let a = ["a","b","c","d","e","f","g","h","i"];
let b = ["","","","",""];
let display_pointer = 0;
let msg_pointer = 0;

let start = 1;
let size = 5;       //  size of display
let length = 9;     //  size of message (a)

node.warn("A is " + a);
node.warn("Adisplay_pointer " + a[display_pointer]);

while (msg_pointer < length)
{
    b[0] = a[msg_pointer];

    node.warn("B is " + b);
    node.warn("Result " + b);  //  This shows me what I expect to see.
                               //  A progressive increment of the IP number along the
                               //  variable

    while (pointer < length)
    {
        b[ size - display_pointer ] = b[ size - display_pointer - 1 ];
       display_pointer = display_pointer + 1;
    }
   display_pointer = 0;

   msg_pointer = msg_pointer + 1;
}

Oh, this is only example code to get the idea working.
The size is only 5 to see things happening correctly/as expected.
And it also doesn't have the correct code to only move the required digits.
(or I don't think it does. Sorry way past my bed time.)
But the output goes look good.