Cascading Max7219

Posted on
  • Hi,

    i want to cascade multiple Max7219 8x8 LED like https://www.pjrc.com/teensy/td_libs_Matr­ix.html. Is this possible with the http://www.espruino.com/modules/MAX7219.­js module?

  • By the looks of it, you could put them on different spi pins, and write some glue to make it look like a single 16x8 display

  • It doesn't do it right now, but the changes required are trivial. To cope with multiple drivers it seems that you just send the two different bits of data to the same address while keeping CS asserted.

    Arduino's library here: https://github.com/lstoll/arduino-librar­ies/blob/master/Matrix/Matrix.cpp#L129

    So it's probably as simple as changing:

    raw : function(val) {
          spi.send ([0x9,0],cs); // output raw data
          for (var i=0;i<val.length;i++) {
            spi.send([i+1,val[i]],cs);
          }
          spi.send([0x0C,1],cs); // no shutdown
        },
    

    to:

    raw : function(val) {
          digitalWrite(cs,0);
          spi.send ([0x9,0]); // output raw data
          for (var i=0;i<val.length;i++) {
            spi.send([(i&7)+1,val[i]]);
          }
          spi.send([0x0C,1]); // no shutdown
          digitalWrite(cs,1);
        },
    

    One nice extra is that you can actually use Espruino's built-in graphics library with it, so you can do something like...

    var g = Graphics.createArrayBuffer(3*8,8,1,{vert­ical_byte:true});
    g.drawString("Hello",0,0);
    max.raw(g.buffer);
    
  • Having said that, you may need to send the same addresses to each chip. So:

    [0,chip1row0,0,chip2row0,1,chip1row1,1,c­hip2row1, ...]
    

    I don't have one here to play with and test but it should be pretty easy to get working.

  • Great. I will test it at the weekend.

  • Hi,

    I tested it with the following code and it does not work.

    var modules = {};
    
    SPI2.setup({mosi:B15, sck:B13});
    
    modules.connect = function(/*=SPI*/_spi,/*=PIN*/_cs) {
      var spi = _spi;
      var cs = _cs;
      spi.send ([0xA,0xF],cs);  // intensity  -full
      spi.send ([0xB,0x7],cs);  // scan limit - all 8 chars
      spi.send ([0xC,0],cs);    // shutdown
      return {
    
        raw : function(val) {
          digitalWrite(cs,0);
          spi.send ([0x9,0]); // output raw data
          for (var i=0;i<val.length;i++) {
            spi.send([(i&7)+1,val[i]]);
          }
          spi.send([0x0C,1]); // no shutdown
          digitalWrite(cs,1);
        },
    
        off : function() { spi.send([0xC,0],cs); },
    
        intensity : function(i) { spi.send([0xA,E.clip(i*15,0,15)],cs); }
      };
    };
    
    var count = 0;
    
    function doSomerhingStupid() {
      if (count > 0)
        run();
      count ++;
    }
    
    function run () {
      var max = modules.connect (SPI2,B14);
      digitalWrite (LED3, 1);
      max.off();
      clearInterval();
    
      setInterval(function() {
        digitalWrite (LED2, on);
        var c1r0 = Math.random () * 255;
        var c1r1 = Math.random () * 255;
        var c2r0 = Math.random () * 255;
        var c2r1 = Math.random () * 255;
        var c3r0 = Math.random () * 255;
        var c3r1 = Math.random () * 255;
        var c4r0 = Math.random () * 255;
        var c4r1 = Math.random () * 255;
        max.raw([0,c1r0,0,c2r0,0,c3r0,0,c4r0,1,c­1r1,1,c2r1,1,c2r1,1,c3r1]);
        max.intensity (Math.random ());
    
        on = !on;
      }, 200);
    }
    
    var on = 1;
    digitalWrite (LED1, 1);
    digitalWrite (LED2, 0);
    digitalWrite (LED3, 0);
    clearInterval();
    
    setWatch(doSomerhingStupid, BTN1, {repeat:true,edge:"rising", debounce:1});
    

    Here is a video.
    https://www.youtube.com/watch?v=WEmp9NjJ­uwM

    Do you have any idea what I did wrong?

    Regards
    Michael

  • I think there might have been some misunderstanding about my last post... You probably need to send all of the row 0s, followed by all row 1s, etc. So more like:

        raw : function(val) {
          digitalWrite(cs,0);
          spi.send ([0x9,0]); // output raw data
          digitalWrite(cs,1);
    
          for (var row=0;row<val.length&7;row++) {
            digitalWrite(cs,0); 
            for (var i=row;i<val.length;i+=8)
              spi.send([row,val[i]]);
            spi.send([0x0C,1]); // no shutdown
            digitalWrite(cs,1);
          }
        },
    

    I wonder if that'll be better?

    By the way, when posting code, if you highlight it and click the 'code' button, it'll appear properly in the forum (i just changed yours).

  • Hi,

    i took the new raw function and tested it again. It does not work at the moment.
    Here is the actual code:

    
    SPI2.setup({mosi:B15, sck:B13});
    
    var max7219 = function(/*=SPI*/_spi,/*=PIN*/_cs) {
      var spi = _spi;
      var cs = _cs;
      spi.send ([0xA,0xF],cs);  // intensity  -full
      spi.send ([0xB,0x7],cs);  // scan limit - all 8 chars
      spi.send ([0xC,0],cs);    // shutdown
      return {
    
        raw1 : function(val) {
          digitalWrite(cs,0);
          spi.send ([0x9,0]); // output raw data
          for (var i=0;i<val.length;i++) {
            spi.send([(i&7)+1,val[i]]);
          }
          spi.send([0x0C,1]); // no shutdown
          digitalWrite(cs,1);
        },
    
        raw2 : function(val) {
          digitalWrite(cs,0);
          spi.send ([0x9,0]); // output raw data
          digitalWrite(cs,1);
          for (var row=0;row<val.length&7;row++) {
            print ("row " + row + " " + val.length + " " + (row<val.length&7));
            digitalWrite(cs,0);
    
            for (var i=row;i<val.length;i+=8) {
              spi.send([row,val[i]]);
              print ("val " + row + " " + val[i]);
            }
            spi.send([0x0C,1]); // no shutdown
            digitalWrite(cs,1);
          }
        },
    
        off : function() { spi.send([0xC,0],cs); },
    
        intensity : function(i) { spi.send([0xA,E.clip(i*15,0,15)],cs); }
      };
    };
    
    function doSomerhingStupid() {
      setData();
      if (count > 0)
        run();
      count ++;
    }
    
    function setData()
    {
      for (var i = 0; i < 64; i ++)
      {
        data[i] = 0;
        if (i % 2 === 0)
        {
          if (i < 16) data[i] = 0;
          else if (i < 32) data[i] = 1;
          else if (i < 48)  data[i] = 2;
          else  data[i] = 3;
        } else {
          data[i] = (i * 4) - 1;
        }
        print ("data " + i + " " + data[i]);
      }
    }
    
    function run () {
      digitalWrite (LED3, 1);
      digitalWrite (LED2, on);
      max.raw2(data);
      on = !on;
    }
    
    var on = 1;
    digitalWrite (LED1, 1);
    digitalWrite (LED2, 0);
    digitalWrite (LED3, 0);
    clearInterval();
    
    var count = 0;
    var data = new Array (64);
    var max = max7219 (SPI2,B14);
    setWatch(doSomerhingStupid, BTN1, {repeat:true,edge:"rising", debounce:1});
    

    To see more details about the send-data, i added some print statements.
    The output looks like follows. I am not sure, but it doesn't look correct.

    Connected
    =undefined

    =undefined
    data 0 0
    data 1 3
    data 2 0
    data 3 11
    data 4 0
    data 5 19
    data 6 0
    data 7 27
    data 8 0
    data 9 35
    data 10 0
    data 11 43
    data 12 0
    data 13 51
    data 14 0
    data 15 59
    data 16 1
    data 17 67
    data 18 1
    data 19 75
    data 20 1
    data 21 83
    data 22 1
    data 23 91
    data 24 1
    data 25 99
    data 26 1
    data 27 107
    data 28 1
    data 29 115
    data 30 1
    data 31 123
    data 32 2
    data 33 131
    data 34 2
    data 35 139
    data 36 2
    data 37 147
    data 38 2
    data 39 155
    data 40 2
    data 41 163
    data 42 2
    data 43 171
    data 44 2
    data 45 179
    data 46 2
    data 47 187
    data 48 3
    data 49 195
    data 50 3
    data 51 203
    data 52 3
    data 53 211
    data 54 3
    data 55 219
    data 56 3
    data 57 227
    data 58 3
    data 59 235
    data 60 3
    data 61 243
    data 62 3
    data 63 251
    row 0 64 1
    val 0 0
    val 0 0
    val 0 1
    val 0 1
    val 0 2
    val 0 2
    val 0 3
    val 0 3
    row 1 64 1
    val 1 3
    val 1 35
    val 1 67
    val 1 99
    val 1 131
    val 1 163
    val 1 195
    val 1 227
    row 2 64 1
    val 2 0
    val 2 0
    val 2 1
    val 2 1
    val 2 2
    val 2 2
    val 2 3
    val 2 3
    row 3 64 1
    val 3 11
    val 3 43
    val 3 75
    val 3 107
    val 3 139
    val 3 171
    val 3 203
    val 3 235
    row 4 64 1
    val 4 0
    val 4 0
    val 4 1
    val 4 1
    val 4 2
    val 4 2
    val 4 3
    val 4 3
    row 5 64 1
    val 5 19
    val 5 51
    val 5 83
    val 5 115
    val 5 147
    val 5 179
    val 5 211
    val 5 243
    row 6 64 1
    val 6 0
    val 6 0
    val 6 1
    val 6 1
    val 6 2
    val 6 2
    val 6 3
    val 6 3
    row 7 64 1
    val 7 27
    val 7 59
    val 7 91
    val 7 123
    val 7 155
    val 7 187
    val 7 219
    val 7 251
    row 8 64 1
    val 8 0
    val 8 1
    val 8 1
    val 8 2
    val 8 2
    val 8 3
    val 8 3
    row 9 64 1
    val 9 35
    val 9 67
    val 9 99
    val 9 131
    val 9 163
    val 9 195
    val 9 227
    row 10 64 1
    val 10 0
    val 10 1
    val 10 1
    val 10 2
    val 10 2
    val 10 3
    val 10 3
    row 11 64 1
    val 11 43
    val 11 75
    val 11 107
    val 11 139
    val 11 171
    val 11 203
    val 11 235
    row 12 64 1
    val 12 0
    val 12 1
    val 12 1
    val 12 2
    val 12 2
    val 12 3
    val 12 3
    row 13 64 1
    val 13 51
    val 13 83
    val 13 115
    val 13 147
    val 13 179
    val 13 211
    val 13 243
    row 14 64 1
    val 14 0
    val 14 1
    val 14 1
    val 14 2
    val 14 2
    val 14 3
    val 14 3
    row 15 64 1
    val 15 59
    val 15 91
    val 15 123
    val 15 155
    val 15 187
    val 15 219
    val 15 251
    row 16 64 1
    val 16 1
    val 16 1
    val 16 2
    val 16 2
    val 16 3
    val 16 3
    row 17 64 1
    val 17 67
    val 17 99
    val 17 131
    val 17 163
    val 17 195
    val 17 227
    row 18 64 1
    val 18 1
    val 18 1
    val 18 2
    val 18 2
    val 18 3
    val 18 3
    row 19 64 1
    val 19 75
    val 19 107
    val 19 139
    val 19 171
    val 19 203
    val 19 235
    row 20 64 1
    val 20 1
    val 20 1
    val 20 2
    val 20 2
    val 20 3
    val 20 3
    row 21 64 1
    val 21 83
    val 21 115
    val 21 147
    val 21 179
    val 21 211
    val 21 243
    row 22 64 1
    val 22 1
    val 22 1
    val 22 2
    val 22 2
    val 22 3
    val 22 3
    row 23 64 1
    val 23 91
    val 23 123
    val 23 155
    val 23 187
    val 23 219
    val 23 251
    row 24 64 1
    val 24 1
    val 24 2
    val 24 2
    val 24 3
    val 24 3
    row 25 64 1
    val 25 99
    val 25 131
    val 25 163
    val 25 195
    val 25 227
    row 26 64 1
    val 26 1
    val 26 2
    val 26 2
    val 26 3
    val 26 3
    row 27 64 1
    val 27 107
    val 27 139
    val 27 171
    val 27 203
    val 27 235
    row 28 64 1
    val 28 1
    val 28 2
    val 28 2
    val 28 3
    val 28 3
    row 29 64 1
    val 29 115
    val 29 147
    val 29 179
    val 29 211
    val 29 243
    row 30 64 1
    val 30 1
    val 30 2
    val 30 2
    val 30 3
    val 30 3
    row 31 64 1
    val 31 123
    val 31 155
    val 31 187
    val 31 219
    val 31 251
    row 32 64 1
    val 32 2
    val 32 2
    val 32 3
    val 32 3
    row 33 64 1
    val 33 131
    val 33 163
    val 33 195
    val 33 227
    row 34 64 1
    val 34 2
    val 34 2
    val 34 3
    val 34 3
    row 35 64 1
    val 35 139
    val 35 171
    val 35 203
    val 35 235
    row 36 64 1
    val 36 2
    val 36 2
    val 36 3
    val 36 3
    row 37 64 1
    val 37 147
    val 37 179
    val 37 211
    val 37 243
    row 38 64 1
    val 38 2
    val 38 2
    val 38 3
    val 38 3
    row 39 64 1
    val 39 155
    val 39 187
    val 39 219
    val 39 251
    row 40 64 1
    val 40 2
    val 40 3
    val 40 3
    row 41 64 1
    val 41 163
    val 41 195
    val 41 227
    row 42 64 1
    val 42 2
    val 42 3
    val 42 3
    row 43 64 1
    val 43 171
    val 43 203
    val 43 235
    row 44 64 1
    val 44 2
    val 44 3
    val 44 3
    row 45 64 1
    val 45 179
    val 45 211
    val 45 243
    row 46 64 1
    val 46 2
    val 46 3
    val 46 3
    row 47 64 1
    val 47 187
    val 47 219
    val 47 251
    row 48 64 1
    val 48 3
    val 48 3
    row 49 64 1
    val 49 195
    val 49 227
    row 50 64 1
    val 50 3
    val 50 3
    row 51 64 1
    val 51 203
    val 51 235
    row 52 64 1
    val 52 3
    val 52 3
    row 53 64 1
    val 53 211
    val 53 243
    row 54 64 1
    val 54 3
    val 54 3
    row 55 64 1
    val 55 219
    val 55 251
    row 56 64 1
    val 56 3
    row 57 64 1
    val 57 227
    row 58 64 1
    val 58 3
    row 59 64 1
    val 59 235
    row 60 64 1
    val 60 3
    row 61 64 1
    val 61 243
    row 62 64 1
    val 62 3
    row 63 64 1
    val 63 251

  • Yes, it's not quite right. It should stop after row 7. I think what you want is:

    row 0 64 1
    val 0 0
    val 0 0
    val 0 1
    val 0 1
    val 0 2
    val 0 2
    val 0 3
    val 0 3
    row 1 64 1
    val 1 3
    val 1 35
    val 1 67
    val 1 99
    val 1 131
    val 1 163
    val 1 195
    val 1 227
    row 2 64 1
    val 2 0
    val 2 0
    val 2 1
    val 2 1
    val 2 2
    val 2 2
    val 2 3
    val 2 3
    row 3 64 1
    val 3 11
    val 3 43
    val 3 75
    val 3 107
    val 3 139
    val 3 171
    val 3 203
    val 3 235
    row 4 64 1
    val 4 0
    val 4 0
    val 4 1
    val 4 1
    val 4 2
    val 4 2
    val 4 3
    val 4 3
    row 5 64 1
    val 5 19
    val 5 51
    val 5 83
    val 5 115
    val 5 147
    val 5 179
    val 5 211
    val 5 243
    row 6 64 1
    val 6 0
    val 6 0
    val 6 1
    val 6 1
    val 6 2
    val 6 2
    val 6 3
    val 6 3
    row 7 64 1
    val 7 27
    val 7 59
    val 7 91
    val 7 123
    val 7 155
    val 7 187
    val 7 219
    val 7 251
    

    Try:

        raw2 : function(val) {
          digitalWrite(cs,0);
          spi.send ([0x9,0]); // output raw data
          digitalWrite(cs,1);
          for (var row=0;row<8;row++) {
            print ("row " + row + " " + val.length + " " + (row<val.length&7));
            digitalWrite(cs,0);
            for (var i=row;i<val.length;i+=8) {
              spi.send([row,val[i]]);
              print ("val " + row + " " + val[i]);
            }
            spi.send([0x0C,1]); // no shutdown
            digitalWrite(cs,1);
          }
        },
    
  • Just to add that I (finally) added support for multiple displays, now I have one to test with.

    All documented here: http://www.espruino.com/MAX7219

    Under 'Multiple chained MAX7219 (bigger than 8x8)'

  • I got a big Matrix LED : 32 x 16
    Can I draw it use module MAX7219 ?

    How to set the device count ?

    SPI2.setup({mosi:B15, sck:B13});
    var disp = require("MAX7219").connect(SPI2, B14, 8); //  8 seems not work
    
    var g = Graphics.createArrayBuffer(32, 16, 1);
    g.flip = function() { disp.raw(g.buffer); };
    
    g.drawString("Hello!", 0, 0, 1);
    g.flip();
    
  • Does this work:

    SPI2.setup({mosi:B15, sck:B13});
    var disp = require("MAX7219").connect(SPI2, B14, 8);
    var g = Graphics.createArrayBuffer(64, 8, 1);
    g.flip = function() { disp.raw(g.buffer); };
    g.drawString("Hello this is a very long string of text");
    g.flip();
    

    The issue may be that Espruino isn't aware that you want a 4x2 stack of matrices, and just assumes it is 8x1. I don't see anything in the module that would be limited to just 4 matrices.

    If the code above does work then it's not a big problem - it's relatively easy to add some code that will rearrange things into the format that you want.

  • Yeah,I have got it. Thx!
    The long string tells out the order LED Matrix rendering.
    Like this:

    treat as a 8 x 8 x 16 scrren:

  • Great! Did you figure out how to sort the ordering?

    Something like this should do it...

    SPI2.setup({mosi:B15, sck:B13});
    var disp = require("MAX7219").connect(SPI2, B14, 8);
    var gdisp = Graphics.createArrayBuffer(64, 8, 1);
    var g = Graphics.createArrayBuffer(32, 16, 1, {msb:true});
    g.flip = function() {
      var im = new Uint8Array(35);
      im.set([32,8,1]);
      im.set(new Uint8Array(g.buffer), 3);
      gdisp.clear();
      gdisp.drawImage(im,0,0);
      im.set(new Uint8Array(g.buffer,32), 3);
      gdisp.drawImage(im,32,0);
      disp.raw(gdisp.buffer);
    };
    g.drawLine(0,0,32,16);
    g.flip();
    
  • SPI2.setup({
      mosi: B15,
      sck: B13
    });
    var disp = require("MAX7219").connect(SPI2, B14, 16);
    
    /** 呼吸灯效 */
    function breath() {
      var light = 0.01;
      var increase = true;
    
      setInterval(function () {
        if (increase) {
          light += 0.01;
        } else {
          light -= 0.01;
        }
    
        if (light > 0.99) {
          increase = false;
        } else if (light < 0.01) {
          increase = true;
        }
        disp.intensity(light); // 亮度
      }, 30);
    }
    
    function onInit() {
      var data = [
      0, 0, 0, 0, 96, 2, 36, 0,
      0, 0, 0, 0, 72, 2, 200, 33,
      0, 14, 0, 0, 32, 2, 36, 8,
      128, 0, 0, 0, 160, 1, 72, 41, 224, 15, 0, 0, 32, 2, 70, 16, 0, 28, 0, 30, 144, 7, 72, 40, 96, 2, 0, 0, 16, 2, 128, 63, 248, 49, 248, 48, 96, 121, 40, 46, 64, 2, 192, 0, 8, 2, 0, 30, 12, 0, 8, 34, 16, 49, 8, 32, 64, 50, 128, 49, 4, 2, 0, 0, 228, 3, 200, 33, 132, 1, 248, 63, 192, 63, 0, 33, 0, 2, 0, 0, 192, 4, 8, 38, 192, 1, 0, 0, 126, 2, 4, 0, 0, 0, 0, 0, 96, 4, 232, 33, 128, 0, 0, 0 ];
      disp.raw(new Uint8Array(data).buffer);
    
      breath();
    }
    
    onInit();
    
  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Cascading Max7219

Posted by Avatar for user6772 @user6772

Actions