Why does my 8x8 matrix stop displaying?

Posted on
  • Hey guys,

    I have an Espruino WiFi (love this thing) with an 8x8 matrix led display as recommended here. I have node-red running on my Raspberry PI 4. My Espruino makes calls every 3 seconds to my PI to get the current time and displays it scrolling across the matrix.

    The problem is it just stops after about 10 minutes, I checked the Rasperry Pi and it is still being called by the Espruino every 3 seconds in the log. So the reason it's not displaying could be in this script somewhere, just not sure how to even debug it...

    var WIFI_NAME = "BTHub-XXX";
    var WIFI_OPTIONS = { password : "XxXxX" };
    var http = require("http");
    
    var output = 'default text';
    var interval = false;
    
    const ANODES = [B6,A7,A6,B9,A4,B8,B4,B3];
    const CATHODES = [B0,B5,A0,B7,B10,A1,B1,A5];
    var g = Graphics.createArrayBuffer(8,8,1);
    
    var wifi = require("Wifi");
    
    function onInit() {
      wifi.connect(WIFI_NAME, WIFI_OPTIONS, function(err) {
        if (err) {
          console.log("Connection error: "+err);
          return;
        }
        console.log("Connected!");
        getData();
        start();
        scroll();
      }.bind(this));
    }
    
    
    // Start scanning out the LED display
    function start() {
      console.log('start');
      var b = new Uint8Array(g.buffer);
      // Pre-bind digitalWrites to make things faster
      var a = digitalWrite.bind(undefined,ANODES);
      var c = digitalWrite.bind(undefined,CATHODES.con­cat(ANODES));
      return setInterval(function() {
        b.map((d,i)=>{c(65280^(256<<i));a(d);});­c(65280);
      },10); // 100 Hz
    }
    
    function scroll() {
      var i = 8;
      if (interval)
        clearInterval(interval);
      
      interval = setInterval(function(){
        if(i == -(output.length * 4)) i = 8;
        g.clear();
        g.drawString(output, i, 2);
        i--;
      }, 100);
    }
    
    function getData() {
      setInterval(function(){
        http.get("http://192.168.1.146:1880/hell­o-data", function(res) {
          res.on('data', function(data) {
            output = data;
            console.log(output);
          }.bind(this));
        });
      }.bind(this), 3000);
    }
    
  • Glad you like Espruino as SW and also committed to the HW... otherwise the SW part would cease to exist... or just sink into the big bit bucket as many open source do... (and so do many proprietary SWs: they become open source so the dying away users can still maintain the code until they die themselves... and the sw can finally die together with them as well - hope I got the d-i/y right as a non-English language native).

    ...wild goose - more seasonal: turkey - chase: most likely the log buffer has filled up and log output does not know where to go else (if disconnected...?). Therefore comment console.log(...); (or use the other method(s) of 'routing the console into the void').

    If you hit disconnects for what ever reason, add ....on("...",function() { ... } to reconnect, but I assume the callback processing the data just dies 'silently'.

    Btw 1, do not understand the .bind(this) in line 24.

    Btw 2, you can put your WLAN credentials into a module and keep it locally in your Espruino Web IDE sandbox ./modules folder. You pull it with ... `require("creds"); use it as object w/ properties im your ./project/....js code(s), then you less likely publish it mistakingly. ;-) forgetting to edit the forum pasted source. See: http://forum.espruino.com/comments/13668­571/ - even though they do - logically - not belong there, as @opichals points out in http://forum.espruino.com/comments/14102­812/

  • Wed 2019.11.27

    Hi @Coder2012, don't have these devices to be able to test,

    'just not sure how to even debug it'

    but I did notice a few things. It's likely bad data is being passed to the graphics object, or an array is going out of range or running out of memory perhaps.

    Function scroll() is called one time. L42 and L43 will only be called one time, incidentally
    setInterval() returns a number, the timer ID, not a boolean, so var interval is never cleared.

    http://www.espruino.com/Reference#l__glo­bal_setInterval



    As L45 is being called ten times a second, to check if running out of memory, place a
    process.memory() inside that interval. I'd also only check, say every tenth time using a conditional such as if( (skipcounts % 10) == 0 ) so that output to the console (Left-Hand side) may keep up. Could also check the arguments at that point to see if out of bounds errors may be occurring.

    http://www.espruino.com/Reference#proces­s



    Try placing a try/catch block around the functions called inside onInit() to see if any errors are occurring, bubbling up and not being caught.


    Suspect L34. Using concat repetitively may be appending beyond the available buffer size.

  • Hey guys,

    Thank you so much for taking the time to have a look at my code:

    @allObjects

    Good tips for debugging. I'll add an on handler.

    L24 .bind(this) , I add these to every nested function to maintain function scope to avoid things like var temp = this etc.

    I've read about places to put the WiFi creds and yes I'll do that when i'm happy its working well.

    @Robin

    If it's bad data or an out of range error, wouldn't that crash the whole thing? I mentioned that the Espruino is still calling the Pi4 every 3 seconds even after display stops, so surely there's no error here? Or could it be repeatedly throwing an error but still making calls?

    Yes setInterval does return an integer, but JS will coerce this to false if 0 and true if its any value greater than 0, so I believe this is correct.

    Good tip about the process.memory() call and the try catch.

    Really appreciate the advice, will see what I can find out and report back.

  • OK sorry @Robin, I see what you mean't with the interval I had set that to false initially, this was something I needed previously, but isn't required now.

    So thanks to you two, i've been able to debug this, and it turned out to be a problem with L46.

    That test there sometimes didn't reset i = 8 so the text was getting updated fine, but was so far scrolled away I could never see it.

    Thanks a lot.

  • @Coder2012,

    I don't know how your scroll behaves. Since it is not much data, it may do well.

    There are though alternatives:

    Reading out and pushing to display can handle the scroll by moving the readout start pointer... No need for redrawing all the time... this is especially useful when drawing more complex things... The readout can then be compiled js or even written in c... see for example conversation about Efficiently moving things around in zig-zag Graphics buffer visualized w/ 24/32 bpp displays / neopixel strings

  • Glad you got it all sorted out, and in a short period of time to boot!

    'Yes setInterval does return an integer, but JS will coerce this to false if 0 and true if its any value greater than 0, so I believe this is correct.'

    Just to clarify for others reading along, that statement would hold true for the test condition using if(). However, it was the use of the argument value for var interval that would cause an error with the clearInterval() function, which requires the timer ID which you have identified is numeric. Was it also realized that the interval argument is never used/reset?

    http://www.espruino.com/Reference#l__glo­bal_clearInterval


    'That test there sometimes didn't reset i = 8'

    re: L46   So was it just a simple <=?

  • Hello again,

    Yes exactly <= fixed it.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Why does my 8x8 matrix stop displaying?

Posted by Avatar for Coder2012 @Coder2012

Actions