• Hello,
    i'm working with a pico and an Adafruit 8x8 matrix backpack (HT16k33).
    I setup the I2C and initialize the display

      I2C1.setup({scl: B6,sda: B7});
      I2C1.writeTo(0x70, 0x21); // turn on oscillator
      I2C1.writeTo(0x70, 0x81); // display on
    

    Some time (i'm unable to find a recurrent way, it come on a software upload or a switch on) the display does not start, with an I2C timeout (in the console)...
    I've tried with decay for writing command..
    same prob.

    I2C1.setup({scl: B6,sda: B7});
      setTimeout(function() {
        I2C1.writeTo(0x70, 0x21); // turn on oscillator
        I2C1.writeTo(0x70, 0x81); // display on
      }, 500);
    

    Any idea?
    It is not a wiring pb (cause most of the time it work)

    thanks for yopur help

  • On an arduino there is no pullup resistor to add to circuit.
    i tested with an other backpack, same result.
    some time it works, sometime not.

    i tried with a try catch and resend a I2C.setup() (read it in the forum) in the resend with no more result.

      try {
        I2C1.writeTo(0x70, 0x21); // turn on oscillator
      } catch(e) {
        I2C1.setup({scl: B6,sda: B7});
        setTimeout(function() {
          console.log("try again");
          try {
            I2C1.writeTo(0x70, 0x21); // turn on oscillator
          } catch(e) {
            console.log("does not init",e);
          }
        }, 100);
      }
    

    other idea?
    is there a way to loop on a init phase 'til it works? (a loop on the "try catch")?

  • Bonjour M. Mrbbp,

    1st thought - looking at the schematics w/ the HT16K33 - was VDD 5V...

    a) I assume you supply enough of the 5V to the board. I could imagine that there are power spikes / brownouts when starting to send things to the controller... Direct supply from the 5V source may help... Don't know if you need a cap. I'm surprised that it does also not work all the times with a Arduino, when reading your comment correctly. I see though applications working that use only S1 Lithium Battery - 3.7V, max 4.2V when freshly charged -https://learn.adafruit.com/trinket-slash­-gemma-space-invader-pendant/wirin

    b) Since pins of STN32 on PICO are 5V tolerant, you are fine except may be for the high signal of PICO. I see 10K pull-up resistors of 10K on the LED module: https://learn.adafruit.com/adafruit-led-­backpack/downloads - therefore in seams that in no environment a resistor has to be added (but with multiples connected they have to be removed on all but one - best is last in 'chain'). It may be that the high signal and it's flank are not good enough...

    d) I do not know about the pin mode PICO is in when just using it straight away without setting. I would expect it to be 'output open drain', but you setting it could help, because I experienced spikes in the past with Espruino's pinMode() - even when it is not changing - but here it IS changing from input to output for the clock and data lines. The issue was then though fixed... a while ago. But I still would give it a try to set pinMode upfront.

    e) My last straw would be to put a (Schottky) diodes with ring / cathode (-) towards PICO in the lines to give an extra 0.5..0.7V relieve to the resistors on high signal...

    Btw, about a year or two ago I bought this adafruit charlieplex 16x8 LED matrix https://learn.adafruit.com/adafruit-char­lieplex-bonnet, but I could not get it properly to display a matching Espruino Graphics display buffer... May be you have done something with that display? I got inspired by you installation with the deer(?) on a tin... and ot is still to come alive for the answer to your flip-dot-generosity!

  • Hello @allObjects M...

    a/ i power the board and the display with usb from my macbook. I've tried with a 700mA phone charger, it inconsistently... After some time unplugged, when i plug the circuit with 5v, it does not initialize at first time... have to switch off/on (plug/unplug) few time and the display start. (as an old car or a cold engine that need a starter)
    The backpack is supposed to work with a Feather (from adafruit) that work at 3.3v level.

    b/ not sure to understand what you mean (sorry)

    c/ no c/

    d/ i've tried

    pinMode(B6, 'opendrain');
    pinMode(B7, 'opendrain');
    

    not better.

    e/ I'll try tomorrow. I think i have a plastic bag full of these black diode... (i used it to stepdown current for led...is it the same?) (dont remember the ref... N4007 (in smd and old fashion black cylinder?)

    thanks for your advice...

  • Thr 2019.12.19

    'is there a way to loop on a init phase 'til it works? (a loop on the "try catch")?'

    Hello @Mrbbp, would you be so kind as to upload the output for the above snippet? Although L1,L2,L3 and L13 are not adding any value here, (as I2C is not setup by L2, an immediate error should be thrown - maybe the intention of the outer try/catch?) the output should fill multiple "try again" messages with two bytes placed on the I2C bus each 100msec, unless/until an error is detected, in which case "does not init < error msg detail here >" should display.

    Effectively, you have the looping mechanism you are after. 100msec may be too fast for the left hand console panel of the WebIDE to keep up though.

    Any additional detail in the WebIDE console output?
    WebIDE >> Settings >> Console

  • 1N4007 will do. But it looks that something else is at fault... you remember that there were some cold solder points in the flip dot boards... flippy behavior can come from that...

    ...yep c) somehow got skipped... - ignore

    regarding b): the module has on-board resistors to pull the data and clock lines up. the resistors are 10k resistors. My comment is: if you would have multiples of these modules on data and clock lines, only one should have resistors connected and all others not. And when multiples are connected, usually the driving device is at one end at the wires - where also ground is connected and power is fed - and the last module - on the other end of the wires - would be the module with the resistors. If more than one module keeps the resistors on, the pull-up force becomes with a certain number of modules too strong to be pulled down for any of the devices.

  • @Robin
    i give you more off my onInit()

    const onInit = function() {
      clearInterval();
      clearWatch();
      pinMode(B6, 'opendrain');
      pinMode(B7, 'opendrain');
      require("Font4x6").add(Graphics);
      /* rajouter les init de connexion pour le display */
      // initialisation I2C
      I2C1.setup({scl: B6,sda: B7});
      // rouge
      try {
        I2C1.writeTo(0x70, 0x21); // turn on oscillator
      } catch(e) {
        I2C1.setup({scl: B6,sda: B7});
        setTimeout(function() {
          console.log("try again");
          try {
            I2C1.writeTo(0x70, 0x21); // turn on oscillator
          } catch(e) {
            console.log("does not init",e);
          }
        }, 500);
      }
    
        console.log("init I2C");
        // init suite I2C
        I2C1.writeTo(0x70, 0x81); // display on
        I2C1.writeTo(0x70, 0xE0 | 0); // luminosité 0-15
        digitalPulse(LED2,1,20);
        setTimeout(envoieMatrice, 2000);
    };
    

    and the output.
    It does not loop
    it try once as in the code
    if i well understand, it fail on the first communication

    init I2C
    Uncaught InternalError: Timeout on I2C Write BUSY
     at line 1 col 541
    ... I2C'),I2C1.writeTo(112,129),I2C1.writeTo­(112,224),digitalPu...
                                  ^
    in function called from system
    try again
    does not init InternalError: InternalError: Timeout on I2C Write BUSY
    > 
    
  • @Robin

    i tried in a dirty way by adding some time in each command (a blank loop) and a try catch.
    i've got less error.
    sometime (1 in 5 switch on) there is no error but display does not start.
    When i unplug/plug i lost the connexion therefore i do not receive the error... but i blink the led in the main program and it blink....
    show you my ugly code

    const onInit = function() {
      clearInterval();
      clearWatch();
      pinMode(B6, 'opendrain');
      pinMode(B7, 'opendrain');
      require("Font4x6").add(Graphics);
      /* rajouter les init de connexion pour le display */
      console.log("init programme affichage matrice v2.2 - éric choisy ©2019");
      console.log("mém. utilisée: "+Math.round(process.memory().usage/proc­ess.memory().total*100)+"%");
      // initialisation I2C
    
        console.log("setup I2C");
      I2C1.setup({scl: B6,sda: B7});
      // rouge
      try {
        console.log("try OSC ON");
        I2C1.writeTo(0x70, 0x21); // turn on oscillator
      } catch(e) {
        I2C1.setup({scl: B6,sda: B7});
        setTimeout(function() {
          console.log("try again 0x21");
          try {
            I2C1.writeTo(0x70, 0x21); // turn on oscillator
          } catch(e) {
            console.log("does not init",e);
          }
        }, 250);
      }
    
      // init suite I2C
      for (var i=0; i<10000; i++) {
        //
      }
      try {
        console.log("try display ON");
        I2C1.writeTo(0x70, 0x81); // display on
      } catch(r) {
        digitalPulse(LED1,1,20); //rouge
        for (i=0; i<10000; i++) {
          //
        }
        console.log("try again display ON");
        I2C1.writeTo(0x70, 0x81); // display on
      }
      digitalPulse(LED2,1,20);//verte
      try {
        console.log("try brightness");
        I2C1.writeTo(0x70, 0xE0 | 0); // luminosité 0-15
      } catch(r) {
        digitalPulse(LED1,1,20); //rouge
        for (i=0; i<10000; i++) {
          //
        }
        console.log("try again brightness");
        I2C1.writeTo(0x70, 0xE0 | 0); // luminosité 0-15
      }
      digitalPulse(LED2,1,20);//verte
      setTimeout(envoieMatrice, 1000);
    };
    
  • ok understood! :)
    i've got only one module... i keep in mind to remove the resistors (not on last) if i need to chain modules.
    I do not work with flipdot matrix for this project (too deep, too expensive, no more flipdot module on sale :( ) just a big 60mm led matrix, with a ldr to adjust brightness and a pot for speed scroll text.

  • Surprised about duplicate setup in line 14 in post #7. I think that line should be removed...

    Same for the duplicate setup in post #8: line 19 should be removed.

    The time killer loops in lines 31..33, 39..41 and 51..53 cause problems because they hog the cpu and nothing else (js-wise) can happen during that time. Wait by burning cycles does not exist / does not work in Espruino... to the contrary, it will break the execution... 'Waiting' has to be done with 'deferred / timed-out resume (w/ setTimeout(...,...); ).

    Does the module have a reset command? If so, I would send that before sending the command for turning on the oscillator.

    Try something like that - my ugly chained steps with retries on timeouts...

    var ini = function() { // first
      require("Font4x6").add(Graphics);
      clearInterval(); // not sure you need that, only w/ arg
      clearWatch(); // not sure you need that, only w/ arg
      // initialisation I2C
      console.log("setup I2C");
      I2C1.setup({scl: B6,sda: B7});
      // pinMode(B6, 'opendrain'); // even though I suggested it, remove it
      /* rajouter les init de connexion pour le display */
      console.log("init programme affichage matrice v2.2 - éric choisy ©2019");
      console.log("mém. utilisée: "+Math.round(process.memory().usage/proc­ess.memory().total*100)+"%");
    }  
    , res = function(tries) { if (tries>0) { // second w/ retries
      try { console.log("reset");
        // I2C1.writeTo(0x70, 0x??); // reset
        setTimeout(osc,250,2);
      } catch(e) { console.log(e);
        setTimeout(res,250,--tries);
      } } else trow "Unable to reset";
    }
    , osc = function(tries) { if (tries>0) { // third w/ retries
      try { console.log("turn OSC ON");
        I2C1.writeTo(0x70, 0x21); // turn on oscillator
        setTimeout(don,250,2)
      } catch(e) { console.log(e);
        setTimeout(osc,250,--tries);
      } } else trow "Unable to turn osc on";
    }
    , don = function(tries) { if (tries>0) { // fourth w/ retries
      try { console.log("turn display ON");
        I2C1.writeTo(0x70, 0x81); // display on
        setTimeout(lum,250,2)
      } catch(e) { console.log(e);
        setTimeout(don,250,--tries);
      } } else trow "Unable to turn display ON";
    }
    , lum = function(tries) { if (tries>0) { // fifth w/ retries
      try { console.log("set brightness");
        I2C1.writeTo(0x70, 0xE0 | 0); // luminosité 0-15
        setTimeout(envoieMatrice, 1000);
      } catch(e) { console.log(e);
        setTimeout(lum,250,--tries);
      } } else throw "Unable to set brightness";
    }
    ;
    
    const onInit = function() {
      ini();
      res(2); // starts the chain \:
    };
    

    Another - better looking approach would be nested/chained promises w/ (global) retries that is set / reset at the right spots.

    PS: Code not tested (yet)

  • Gorgeous @allObjects!
    it works pretty well, have to try it more.
    Sometime pb persisting even with the tries...
    I definitively will try with the scotchy diode...

    My crappy solution seemed effective but it was an evidence there was a better, nicer code structure to write to do this.

    it seems if it catchs an error even with the tries it fail to initialize the display...
    never mind i use your "boot sequence"

    just a small misspelling throw rather than trow (i'm unfamiliar with this command).

    Thanks again.
    It's nice code

    I do not see a reset command in the doc
    therefore i remove the first function (res). ;)

    é.

    ps: clearInterval() was seen in a forum post about timeout

    var ini = function() { // first
      require("Font4x6").add(Graphics);
      // initialisation I2C
      console.log("setup I2C");
      I2C1.setup({scl: B6,sda: B7});
      /* rajouter les init de connexion pour le display */
      console.log("init programme affichage matrice v2.2 - éric choisy ©2019");
      console.log("mém. utilisée: "+Math.round(process.memory().usage/proc­ess.memory().total*100)+"%");
    }
    , osc = function(tries) { if (tries>0) { // third w/ retries
      try { console.log("turn OSC ON");
        digitalPulse(LED2,1,20);//verte
        I2C1.writeTo(0x70, 0x21); // turn on oscillator
        setTimeout(don,250,2);
      } catch(e) { console.log(e);
        setTimeout(osc,250,--tries);
        digitalPulse(LED1,1,20);//rouge
      } } else throw "Unable to turn osc on";
    }
    , don = function(tries) { if (tries>0) { // fourth w/ retries
      try { console.log("turn display ON");
      digitalPulse(LED2,1,20);//verte
        I2C1.writeTo(0x70, 0x81); // display on
        setTimeout(lum,250,2);
      } catch(e) { console.log(e);
        setTimeout(don,250,--tries);
        digitalPulse(LED1,1,20);// rouge
      } } else throw "Unable to turn display ON";
    }
    , lum = function(tries) { if (tries>0) { // fifth w/ retries
      try { console.log("set brightness");
        digitalPulse(LED2,1,20);//verte
        I2C1.writeTo(0x70, 0xE0 | 0); // luminosité 0-15
        setTimeout(envoieMatrice, 1000);
      } catch(e) { console.log(e);
        digitalPulse(LED1,1,20);//rouge
        setTimeout(lum,250,--tries);
      } } else throw "Unable to set brightness";
    };
    const onInit = function() {
      ini();
      osc(3); // starts the chain \:
    };
    

    i added led pulse to have visual feedback without a console...

  • ...and with a variable you can control the logging - even when connected - and enhanced with a watch dog for setup - sDog - which - if setup not successful - restarts. Timing may be adjusted because it is dependent on all the retries w/ the timeouts cumulated plus some reserve and pause that can and should happen under its watch. You may setup another watch dog for running / sending the texts / grpahics ( envoieMatrice() ).

    PS: é, I like the francophonisation of - not just - les noms... <;:{ooops}>>>

    var lon = false // logging is on / off
    ,   log = function() { console.log.apply(console,arguments); } 
    
    , sDog = null // setup watch dog
    
    , ini = function() { // first
      require("Font4x6").add(Graphics);
      // initialisation I2C
      if (lon) log("setup I2C");
      I2C1.setup({scl: B6,sda: B7});
      /* rajouter les init de connexion pour le display */
      if (lon) log("init programme affichage matrice v2.2 - éric choisy ©2019");
      if (lon) log("mém. utilisée: "+Math.round(process.memory().usage/proc­ess.memory().total*100)+"%");
     }
    , osc = function(tries) { if (tries>0) { // w/ retries
      try { if (lon) log("turn OSC ON");
        digitalPulse(LED2,1,20); // verte
        I2C1.writeTo(0x70, 0x21); // turn on oscillator
        setTimeout(don,250,2);
      } catch(e) { if (lon) log(e);
        setTimeout(osc,250,--tries);
        digitalPulse(LED1,1,20); // rouge
      } } else if (lon) log("Unable to turn osc on"); }
      
    , don = function(tries) { if (tries>0) { // w/ retries
      try { if (lon) log("turn display ON");
        digitalPulse(LED2,1,20); // verte
        I2C1.writeTo(0x70, 0x81); // display on
        setTimeout(lum,250,2);
      } catch(e) { if (lon) log(e);
        setTimeout(don,250,--tries);
        digitalPulse(LED1,1,20); // rouge
      } } else if (lon) log("Unable to turn display ON"); }
    
    , lum = function(tries) { if (tries>0) { // w/ retries
      try { if (lon) log("set brightness");
        digitalPulse(LED2,1,20); // verte
        I2C1.writeTo(0x70, 0xE0 | 0); // luminosité 0-15
        if (sDog) sDog = clearTimeout(sDog); // clear sDog
        setTimeout(envoieMatrice, 1000);
      } catch(e) { if (lon) log(e);
        digitalPulse(LED1,1,20); // rouge
        setTimeout(lum,250,--tries);
      } } else if (lon) log("Unable to set brightness"); }
    
    , sup = function() { // setup under setup watch dog
        sDog = setTimeout(sup,5000); // retry every 5 secs
        osc(3); } // starts the chain \:
    ;
    const onInit = function() {
      ini();
      sup(); // setup under sDog - setup watch dog monitor
    };
    
  • Had some after thoughts: does module have a busy status? If so it would have to be read and checked before sending new commands / data... that could have been the issue whit not working reliably... but working when retrying with timeouts...

  • some infos about the I2C from the IC doc
    I2C Serial Interface
    The HT16K33 includes an I2C serial interface. The I2C bus is used for bidirectional, two-line communication between different ICs or modules. The two lines are a serial data line (SDA) and a serial clock line (SCL). Both lines are connected to a positive supply via a pull-up resistor. When the bus is free, both lines are high. The output stages of devices connected to the bus must have an open-drain or open-collector to perform a wired and function. Data transfer is initiated only when the bus is not busy.
    [...]
    START and STOP Conditions
    • A high to low transition on the SDA line while SCL is high defines a START condition.
    • A low to high transition on the SDA line while SCL is high defines a STOP condition.
    • START and STOP conditions are always generated by the master. The bus is considered to be busy after the START condition.
    The bus is considered to be free again a certain time after the STOP condition.
    • The bus stays busy if a repeated START (Sr) is generated instead of a STOP condition. In this respect, the START(S) and repeated START (Sr) conditions are functionally identical.

    there is no busy pin on the driver board.
    i was thinking to read B6 and B7 to know if it's busy... (as read in the doc)
    If you digitalRead a pin, without a pinMode, you reset the pin in input :(
    I've tried.
    it freeze the display and add to upload a new firmware few time after (is it the cause.. i can't said)

  • I'd not have expected a busy pin but a register that can be read whether the controller is busy or it would respond on a command to not have accepted it because being busy. I have to read up on the HT16K33 controller. The lines cannot be read for it because the data line changes between input and output and the clock is always (open) output (because of stretching by client).

  • @allObjects,
    Hello Markus, i've tried to add a diode N4007 to sda and scl... (as you explain) it's worse, it does not init.
    The module have 2 10k resistor in pull-up on sda and scl.
    is it possible to remove the resistors or change value to a 4k7?
    i refer to an other post here

    regards

    é.


    1 Attachment

    • 2020-01-13 11.24.34.jpg
  • @Mrbbp
    Éric, the reason that w/ diodes it got worse is probably because of the capacities and the low current that is flowing... 0.5mA... You can for sure try w/ 4.7k and may be even w/ down to 1k - but it also depends how much the module can sink.

    If the higher control current does not straighten out eventual bad signal flanks, I have run out of ideas. Other than question the modules compliance... it though comes from a reputable source..

  • Ok, i stop to try to work with the ht16k33 and return to the « good old shit » alias the max7219.
    Spi nor i2c...
    With a delay of 100ms for the setup, it works fine (everytime) and is cheaper and easier to find!

    Thanks for your help @allObjects

    Ps: i tried to remove the 10k with just a bridge... and with a 4k7... no more results... grrrrrrr
    I was looking for a solution to have only 3v3, but it does not work as expected .fu...

  • Mon 2020.01.13

    Thread noob creative electronics enhancement observation.

    'N4007'

    In post #3 e "(Schottky) diodes"

    Isn't the 1N4007 just general purpose?

  • And so. Can you be more specific. Have you a ref on ebay?
    I’m living in farwest with no electronic furniture store in my area...

    I will try later... when i’ll have got some
    Regards

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

Timeout on I2C Write BUSY - not all the time [Adafruit 8x8 matrix backpack]

Posted by Avatar for Mrbbp @Mrbbp

Actions