• Finally 'almost final' working example with picture and clip of 7 seconds: testing the scan algorithm that puts out an Espruino Graphics buffer onto a LED matrix.

    The test uses the drawing of a sequence of rectangles (rs[]) to show the workings. Two independently and 'continuously' running loops do the job:

    1. Drawing rectangles one ofter the other - about every half second one (500 [ms]).
    2. Scanning the buffer and driving the leds - about a column every 3 [ms].

    'Continuously' is achieved by delayed self re-invocation at the end of each function after first invocation in onInit() using setTimeot() because that allows the pseudo-multi-threaded-ness of the application on a single threaded platform, such as JavaScript, and on top of that, Espruino, which has also to 'squeeze' in handling of hardware interrupts... (the display would anyway be only a part of the overall function of the whole system). There is the Espruino provide module that does charlie-plexing (http://www.espruino.com/CharlieplexI), ready-made for use, with one difference: it requires invocation of the Graphics.flip() method to transfer - in an Export-Transform-Load (ETL) manner - the Graphics buffer into a useful working buffer for the actual charlieplexing. Using the .flip() method has the advantage of separating the concerns of having a buffer to draw to for the Graphics object, and the scanning and driving w/ charlie-plexing the display ILED matrix. The disadvantage though is that the application has to initiate the transfer. Even though the latter is named as a disadvantage, it can be an advantage: only completely drawn frames are passed for display, because the application 'usually' knows - in a less interrupt / unpredictable situation - when it is done with drawing and has completed a frame.

    INTERESTING due to low-light condition: The second pic catches a transition between two drawings - shorter time scanning the 'outgoing' 4x3 rectangle and longer time of scanning begin of 'incoming' indented 3x3 rectangle - and the clearing of the display and drawing of the new rectangle in between. The transition is caught by the shutter time straddling the two drawings. That the display time of the outgoing drawing is shorter is noticeable by the first column being less bright (more dim) than the incoming drawing... :) . One should even be able to notice that the LED second from left and top is less bright than the other ones of the incoming rectangle, because the other ones are lit in both of the rectangles / frames... :O. It would be noticeable if LEDs would be properly aligned to project light in exact same direction (to the focal point), which they clearly do not... :/ sorry for that...

    With the low duty cycle and the diodes in the cathode lines I was not worried about the average forward voltage and current... about 2.6V from Espruino PIC on 2..2.2V red LEDs... - 'old' LEDs, not able to handle the today's regular 20mA (I have anyway not to worry about their life time hours). The diodes are there to protect these LEDS with their weak / low reverse voltage breakdown... Was thought just reading up on it and became aware that older manufacturing techniques yield actually better / higher reverse voltage breakdowns than newer ones... but when I bought them decades ago w/ student money, it was too expensive to take the risk... hahah). Also, I'm not worried about the LEDs taking down Espruino or 'over sinking' the STM32F4 chip: only max three (3) LEDs can be up at one time, way below the max of the chip's supply capability. For more about this particular DIY and other LED matrix' with close pictures, see conversation about Driving LED matrix with shift registers such as 74HC595.

    // M5x7mm0.js
    // shows continuous scaning and Charlie-Plexing LED Matrix
    // from Espruino Graphics buffer. Displays buffer content.
    
    // 5x7 (5x3) RED LED MATRIX w/ row anodes and columns cathods
    // Algorithm works a complete 7 pixels / rows tall display,
    // even though actual matrix hardware 'implmeents' / uses only
    // 3 2rows (Ignore the (5) diodes in the column / cathodes lines,
    // they would be resistors depending limiting the forward current).
    var rps = [ A5,  A8,  B7,  B6,  B5,  B4,  B3]; // row pins anodes
    var cps = [ A6,  A7,  B1, B10, B13]; // col pins csthodes
    
    var g = Graphics.createArrayBuffer(5,8,1,{verticĀ­al_byte:true});
    var b = new Uint8Array(g.buffer);
    
    // "  HELLO!  " - 2+6+2=10 chars is 50 cols pixels with 
    // 6x4 font + 1 pixel char space displayed in 2x 7x5 matrix
    var d =  3; // delay in ms
    var n = 10; // times to 'scan' every frame that is pushed
    var m = 40; // m buffer col begins to shift thru (0..39)
    var w = 10; // w cols displayed at once (8x10 display)
    
    // Overriding for test with rectangles
    // - static, no shifting, because m=0 -
    // and display port is only 5 cols wide.
    m = 0; w = 5;
    
    // setup scan start
    var p = -1, i, j, k, s = n - 1, c;
    // continually scan out the Graphics buffer 
    // in 'Charlie-Plexing LED matrix'-manner.
    function scan() { 
      if (++s>=n) { 
        s = 0;
        if (++p>=m) {
          p = 0; // start over
        }
      }
      i = p;  // i byte to put out
      k = -1; // k col in view port
      c = 30; // (2 ^ 5) -1; // ...11110
      while (++k<w) {
        digitalWrite(rps,b[i]);
        digitalWrite(cps,c);       
         i++; c = (c<<1) | 1;
        digitalWrite(cps,31);
      }
      if (d) { // keeps calling itself after d [ms]
        setTimeout(scan,d);
      }
    }
    
    var rs =    // defines sequence of rectangles
    [ [0,0,0,0] // top row 1 dot
    , [1,0,1,0] // top row 2nd dot
    , [2,0,2,0] // top row 3rd dot
    , [3,0,3,0] // top row 4th dot
    , [4,0,4,0] // top row 5th dot
    , [0,0,1,0] // top row 2 dots
    , [0,0,2,0] // top row 3 dots
    , [0,0,4,0] // top row 5 dots
    , [3,0,4,0] // top row last 2 dots
    , [0,1,0,1] // 2nd row 1 dot
    , [0,1,1,1] // 2nd row 2 dots 
    , [0,1,2,1] // 2nd row 3 dots
    , [0,1,4,1] // 2nd row 5 dots
    , [3,1,4,1] // 2nd row last 2 dots
    , [0,0,3,2] // real rectangle
    , [0,0,3,2] // real rectangle
    , [1,0,3,2] // real rectangle
    , [1,0,3,2] // real rectangle
    , [1,0,2,2] // real rectangle
    , [1,0,2,2] // real rectangle
    , [1,1,2,2] // real rectangle
    ];
    
    var rsc = rs.length; // rectangle cound (# of rects9
    var rx = -1;  // rect index to iterate thru rects []
    var rd = 500; // a new rectangle about every rd [ms]
    function drawRects() {
      if (++rx>=rsc) {
        rx = 0;
      }
      g.clear();
      g.drawRect.apply(g,rs[rx]);
      if (rd) { // keeps calling itself after rd [ms]
        setTimeout(drawRects,rd);
      }
    }
    
    function onInit() {
      scan();      // keeps calling itself after d [ms]
      drawRects(); // keeps calling itself after rd [ms]
    }
    
    setTimeout(onInit,500);
    

    3 Attachments

About

Avatar for allObjects @allObjects started