I've just recently finished building an esp8266 based Word Clock as a gift for my sister-in-law and have just given it to her after literally travelling to the other side of the world. I thought I had tested the code and checked it all to be working 100%, but alas I'm starting to notice a few weird behavioural issues now that I've given it to her and only have a week to fix it before we head back home.
For context, I built this clock myself but based the code on a project that someone else had created due to my very novice coding abilities being able to understand most of his code and rework it for my needs. My word clock was expanded from the original code driving 144 neopixels to now 196, and has minute accuracy. My programming skill however is very much beginner - I learnt a lot making this, and am at a stage where I thought I felt confident in being able to debug issues, however I can't seem to work out why these errors appear.
Whilst the code is functional, I am very confident in saying that you'll think that this has probably been done the hard way and there's better ways to code this. I hope to make another clock in the future but for the time being I'm pretty limited on time to fix the issue.
Clock was displaying "JO IT IS TWENTY SIX EEN MINUTES TO NINE". Correct time was 08:34PM. The EEN appears to be a remenent from perhaps 08:19, but I didn't see when it appeared precisely. I checked the code and can't see why this occurred - it looks like it should have been blacked out at 08:20.
Clock displayed " JO IT IS FOUR TWELVE MINUTES TO ONE". Correct time was 12:56PM. The clock had only been on for about half an hour or so, and this eventually disapeared after the minutes hit twelve again and I havent seen it since.
I would be very, very appreciative for any help and advice!
I've been considering building a Word Clock myself, so I had a very quick look over the code, but it is over 1000 lines long so I didn't go into too much detail.
You appear to think that the problem is to do with artifacts from the display of an earlier time.
If the problem is consistent, that is always at 08:34PM it will produce the same error, then it is likely to be a coding error. If it random, it can also be a coding error (array going out of bounds etc.) but it also be that, say, something is too big and you are running out of RAM memory. If the compiler shows that you are on the limits, there are some things you can do. For example, you should then changes such constructs: Serial.println("Half Break 719") ; to Serial.println( F("Half Break 719") ) ; to saves some RAM. (F macro)
On the preparation for the display of a new time, say a new minute rollover, do you completely wipe the entire display, then start building up the words for the new time, or do you attempt to blank only the unwanted words from the previous time display ?
I guess you have checked obvious things like the assignment of LEDs to the correct words on the display.
For trouble shooting, it might be good to add a feature to the sketch to systematically step through each possible time in N times the normal speed.
There's a lot of lines... I was hoping to use some code I found that utilised integers, however I wasnt able to work out how to convert the code to allow for the few vertical words I was using. This would have considerably cut down the lines I think, but WAY beyond my abilities.
I 'm not really sure how to determine memory usage on the Wemos D1 Mini board I use, I think that perhaps the code could be running too quickly for what it needs to do only once realistically every minute.
I will hopefully tonight be able to see if it consistently errors at this particular time. I don't really understand the out of bounds suggestion but I am keen to learn what the change you suggest actually does?
The minute rollover indeed does only blank unwanted words - which is an issue for some of the words that intersect which required some quick fixes by creating new partial words - eg. "Nine" became "Nin" when turning black so as not to affect the next word. I tried to blank the display with the minimal knowledge I had, but found that it created flickering on the currently displayed words as they refreshed. I imagine this is what I should be aiming to achieve but I'm not really sure how to do this effectively.
Also, I'm pretty certain that all the word to LED assignments are now correct and that isn't the issue in this case. Your idea of stepping through the time is partially implemented in the previous code if you enable the debug to on, however it still takes 5 seconds or so the change to the next minute - so it takes a lot of time to go through 24hrs, and I'm not really sure where to change this to speed it up, or if that might created its own issues if indeed there is memory problems?
Many thanks for your comments, and perhaps you can utilise some of my CAD files in the github repository for your own one day!
At compilation time, you see certain resource usage statistics:
Sketch uses 262732 bytes (52%) of program storage space. Maximum is 499696 bytes.
Global variables use 26676 bytes (32%) of dynamic memory, leaving 55244 bytes for local variables. Maximum is 81920 bytes.
The dynamic memory can cause problems if the % is too high.
If you are not using any special effects which would require the loop to be run more often, it would (probably) be possible to run the loop at once per second and, at the beginning, wipe the entire display. It is not clear, though, if that would introduce more flickering.
Here is how you could run it once per second:
void loop() {
static uint32_t lastLoopAtMs = 0 ;
if ( millis() - lastLoopAtMs > 1000 ) {
// your normal code here to be run once per 1000mS
lastLoopAtMs = millis() ;
}
}
Thanks for the advice - the 08:34 time came and went without any problems last night so indeed I think it is not a programming error per se.
I checked the memory usage - this is what it reports:
IROM : 283888 - code in flash (default or ICACHE_FLASH_ATTR)
IRAM : 27448 / 32768 - code in IRAM (ICACHE_RAM_ATTR, ISRs...)
DATA : 2620 ) - initialized variables (global, static) in RAM/HEAP
RODATA : 1700 ) / 81920 - constants (global, static) in RAM/HEAP
BSS : 29608 ) - zeroed variables (global, static) in RAM/HEAP
Sketch uses 315656 bytes (30%) of program storage space. Maximum is 1044464 bytes.
Global variables use 33928 bytes (41%) of dynamic memory, leaving 47992 bytes for local variables. Maximum is 81920 bytes.
My other thought - could it have been a incorrect time that was provided on an occassion by the ntp server/ntp library?
With this information at hand, what do you suggest I should try first? eg. F macro, slow down the loop?
The problem with a non-repeatable error of that nature is that you often can't be sure immediately you have solved the root cause.
I can't believe that an incorrect time could cause that, though. I'd imagine that it would always return a time in the correct format, and would correctly display, even if it did not display an accurate time (say because the timezone was incorrect etc.).
It does not appear to be a RAM problem. The usage is small and the variables are mainly globals so the stack should not get too big.
I would probably try the one minute loop, but with the first activity at the beginning of the minute being to wipe the entire display. That you can test easily and also see if it introduces unacceptable flicker. (the code I supplied was an example of a 1 second (not 1 minute) loop)