How much other code have you got ? But you have more or less answered that in post #40.
Directly addressing the Max7219 is not very friendly and there other libraries like LEDcontrol which are much easier to use. Maybe changing to one of those libraries would be better.
Yes. you have to work consistently using bytes for that method: MAX7219senddata(byte reg, byte data)
This is the FUNCTION I use to display the temperature on the display.
This is ONLY the bit of code which is called to display it.
So other things are set before/outside this code.
void new_display_temperature(float value, byte pos)
{
//
if (sub_debug == 1)
{
Serial.println("T1");
}
if (TimeShown == 1) // If set, wipe display
{
//
// Clear display of time shown.
//
wipe(15);
TimeShown = 0; // Turn off flag.
}
// byte pos = 8; // Position on display where first digit is shown. SHOULD BE EXTERNAL SET
byte digit_counter = pos; // Sneaky, because if used for second digit, can't use the 8 as before.
byte len;
byte count = 0;
char buffer[6];
dtostrf(value, 2,0, buffer); // Alas no decimal accuracy. :( But if ever I can work out how to get it.....
if (value_debug == 1)
{
Serial.print("1-> ");
Serial.println(buffer);
Serial.print("2-> ");
}
sprintf(message, "%s", buffer);
if (value_debug == 1)
{
Serial.println(message);
}
message_length = strlen(message);
//
len = format(message); // Change message format to required.
//
if (value_debug == 1)
{
//
Serial.print("Message is -> ");
Serial.println(message);
Serial.print("Message length is ");
Serial.println(len);
}
delay(2000);
while (count < message_length)
{
MAX7219senddata( (pos-count) , bmessage[count] );
count = count + 1;
digit_counter = digit_counter - 1;
// delay(400);
// delay(10);
}
//
byte j = 99; // This is the degree symbol
byte k = 13; // This is the c symbol Could be made to be capitol C rather than lower case.
// For Capitol C = 78.
// MAX7219senddata(9, 239); // Don't decode all digits bits set = decode. This has bit 5 set to 0.
MAX7219senddata(9, 207); // Don't decode all digits bits set = decode. This has bit 5 and 4 set to 0.
//
// pos - message_length = where the last thing was shown.
MAX7219senddata((pos+1-message_length-1),j);
MAX7219senddata((pos+1-message_length-2),k);
}
Ok, I am probably wrong.
And I haven't included the format() routine.
I get that this isn't going to be a walk in the park but with the code/s supplied by you both, I am seeing patterns that look close to what I want to do.
How did it take so long? I guess in retrospect things always look easy.
Now I just need to add a couple of lines to look one digit ahead and if it sees a decimal point, it adds 128 to the value and skips the decimal place as the next digit to be parsed.
Maybe do this where you first get the IP address. However, remember that chars cannot hold values over 127 so you have to consistently use the byte data type.
This is an extract from the code which I use and this gets the IP address.
Ok, first off this is THE line: Serial.println(WiFi.localIP());
And this is how it is in the bigger picture.
(bit more maybe of interest at the bottom though)
void setup_wifi()
{
delay(10);
byte l_count = 0;
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
if (l_count > 60)
{
Serial.println("");
l_count = 0;
//
// Need routine in here to show activity on display.
//
no_wap();
}
}
Serial.println("");
Serial.println("=================");
Serial.println("WiFi connected");
Serial.println("IP_Address: ");
Serial.println(WiFi.localIP());
Serial.println("=================");
This is a routine I call with the IP address:
It is a mess.
And I am not sure why byte is here.
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); ///// Why is byte here?
message_display();
Serial.println("Message displayed. Wiping display");
delay(600);
//post_message_wipe();
wipe(15);
}
//------------------------------------------------------------
/*
* This takes "message[] and formats it so it can be
* displayed on the 7 segment display with the decimal
* points (etc)
* returns "output_loop" in the correct format.
*/
byte format(char message[])
//void format(char message[])
//void format()
{
//
byte data; // Used to read IP address. Storage of value/s.
byte input_loop = 0;
byte output_loop = 0;
if (value_debug == 1)
{
//
Serial.println("Creating bmessage. Details below.");
Serial.println("Value received is ");
Serial.println(message);
}
while (message[input_loop] != '\0')
{
data = message[input_loop];
//
if (value_debug == 1)
{
Serial.print("Reading in from file ");
Serial.println(message[input_loop]);
}
//
if (data == '.')
{
//
// Decimal point detected.
//
if (value_debug == 1)
{
Serial.println("** Decimal place detected ** Editing this value");
Serial.println(message[input_loop-1]);
Serial.print(" at position --> ");
Serial.println(input_loop);
}
bmessage[output_loop-1] = (bmessage[output_loop-1] + 128);
input_loop = input_loop + 1;
} else
{
data = (data - '0' ); // Take "number" and make it a real value.
bmessage[output_loop] = data;
input_loop = input_loop + 1;
output_loop = output_loop + 1;
}
}
return output_loop;
}
This routine just return the size of the output message.
The message itself must be declared somewhere else - maybe as a global variable?
By only posting pieces of the code you make it very hard for anyone to understand what is going on... if you had of posted all the code from the beginning this thread would have been solved long ago...
But the code is so messy, I am kind of reluctant to share it as it isn't nice at all.
I guess that is a problem I need to address about being too reluctant to post code.
I wrote this (or started writing this) years ago when I had abs(no) idea/understanding of how to do things. It was more get things that did stuff I wanted and stick them together to get a working (bad choice) code.
As I got better things changed, and so on. I am sure you could appreciate this journey.
Ok so the size of the message is handy. I just add 8 to that and make sure I send 8 x blank digits - was my thinking.
Though now that doesn't seem to be needed.... Though I guess it could go in this line rather than the 24
for ( int i = 0 ; i < 24 ; i++ )
and maybe give it a better name. Like message_length
I'll go away and see what happens in the bigger picture.
I hope things meld together and it isn't that difficult.
/*******************************************************************************
Scroll example
NoiascaLedControl
Example based on a idea of
https://forum.arduino.cc/t/wanting-to-scroll-messages-on-a-display/924553/50
by noiasca
2021-11-14
*******************************************************************************/
#include "NoiascaLedControl.h" // download from: https://werner.rothschopf.net/201904_arduino_ledcontrol_max7219.htm
//#include <NoiascaLedControlSpi.h> // this is for Hardware SPI
const uint8_t maxCsPin = 8; // 8 LED CS or LOAD - 8 CS
const uint8_t maxClkPin = 52; // 13 CLK on UNO/NANO - 52 MEGA
const uint8_t maxDataPin = 51; // 11 MOSI on UNO/NANO - 51 MEGA
const uint8_t noOfModules = 1;
LedControl lc = LedControl (maxDataPin, maxClkPin, maxCsPin, noOfModules); // Software Bitbang - use this if you can't use Hardware SPI
//LedControlSpi lc = LedControlSpi (maxCsPin, noOfModules); // faster Hardware SPI
const unsigned long delaytime = 500; // speed of scrolling
const byte digits = 8; // used digits on MAX7219
byte myip[4]; // dummy IP
/*
convert the IP into text (char array) and scroll it on the display
*/
void scrollIP()
{
static byte actual = 0;
static uint32_t previousMillis = 0;
const char delimiter[] {"-"};
if (millis() - previousMillis > delaytime)
{
previousMillis = millis();
char scrolltext[42] {""}; // this variable will store the total scroll text
char buffer[4]; // temp buffer for byte convert to char (3 chars in DEC + null terminator)
itoa(myip[0], buffer, 10); // convert the byte into ASCII/text
strcpy(scrolltext, buffer);
strcat(scrolltext, delimiter);
itoa(myip[1], buffer, 10);
strcat(scrolltext, buffer);
strcat(scrolltext, delimiter);
itoa(myip[2], buffer, 10);
strcat(scrolltext, buffer);
strcat(scrolltext, delimiter);
itoa(myip[3], buffer, 10);
strcat(scrolltext, buffer);
const size_t lengthOfScrolltext = strlen(scrolltext);
lc.clearDisplay(0);
byte len = digits;
byte pos = 0;
char out[digits + 1]{""}; // we need one more than digits for the null terminator
if (actual < digits ) // start on right most side of display (position 7)
{
pos = digits - 1 - actual;
len = actual + 1;
lc.setCursor(pos);
strncpy(out, scrolltext, len); // cut text to length
}
else
{
strncpy(out, scrolltext + actual-digits+1, digits); // cut text to length
}
lc.print(out);
Serial.print(len);
Serial.print("\t");
Serial.print(pos);
Serial.print("\t");
Serial.println(out);
actual++;
if (actual >= lengthOfScrolltext+digits) actual = 0;// rollover
}
}
/*
simple print of IP address to display
*/
void dispIP()
{
static byte actual = 0;
static uint32_t previousMillis = 0;
const uint16_t delaytimeSlow = 1000;
if (millis() - previousMillis > delaytimeSlow)
{
previousMillis = millis();
lc.clearDisplay(0);
if (actual == 0)
{
lc.print("IP");
lc.print(myip[0]);
lc.print(".");
lc.print(myip[1]);
lc.print(".");
actual = 1;
}
else
{
lc.print(myip[2]);
lc.print(".");
lc.print(myip[3]);
actual = 0;
}
}
}
void setup() {
Serial.begin(115200);
lc.begin();
lc.shutdown(0, false);
lc.setIntensity(0, 8);
lc.clearDisplay(0);
// just some dummy values for the IP
myip[0] = 192;
myip[1] = 123;
myip[2] = 222;
myip[3] = 255;
}
void loop()
{
scrollIP();
//dispIP();
}
personally I think that scrolling on a 8 digit 7 segment display isn't readable very well.
Therefore there is also an example how to print the IP in two octets.
But I have to work with what I have. If the display is 8 digits there is little I can do about making it bigger.
Scrolling the IP over the display is not that bad. It doesn't fly past. This is only so if I need to know the device's IP address I run that code and it is seen.
It is nothing that is going to be there always.
Buy a second module and chain it with the first. It just connects on to the end of the first module as described in the supplied manual, and you code it accordingly. You do have to de-solder and bridge over the diode in the first module however - that "manual" omits to mention this.
In a perfect world, yes. (And I do have 2 displays.)
But they are going to be on top of one another. Not side by side.
Showing an IP on two displays that are vertical to one another isn't exactly a nice way to do it either - IMO.
While not typically done, you could display the IP address bytes in hex.
Much simpler to display and It would all fit on the display at once vs having to do any type of scrolling.