I2C2 now working on pico?

Posted on
Page
of 2
/ 2
Next
  • Hi All!
    Impressed with the pico so far, but im stuggling to get the I2C2 bit working. Testing with the following code for an OLED, but iv tried other I2C devices to no avail on the second bus.

    function onInit() {
      I2C2.setup({scl:B10,sda:B3});
      var g = require("SSD1306").connect(I2C2);
      if(!g)
        console.log("error initing oled");
      else
        console.log("init SUCCESS");
    }
    

    any help appreciated

  • Just a quick check:

    • Have you got pullups on SDA and SCL?
    • Did it work on I2C1?
  • No pullups no, although can try tonight.
    It did work fine, hence not trying any pullups, unless I2C2 doesnt have any?

    PS. You may get a few pull requests from me on github for a couple of modules, not having I2C working properly has forced me to make a few changes so they dont hang and break the rest of the execution.

  • I'd definitely try some pullups - it might have just been on the edge of working with I2C1.

    However it might be that your SSD1306 LCD has them built in anyway - worth a try though.

    That's great about the PRs - thanks!

  • Just looking into this - it's a bug, and I should be able to fix it for the next release.

  • Ok, fixed!

    In an hour or so there'll be a build for the Pico in: http://www.espruino.com/binaries/git/com­mits/34e8f0101f73604d3ffc3db0a36816302e5­c8a23

    Instructions on using it at the top of http://www.espruino.com/Download

  • Okay not a problem, it started because I couldn't talk to two I2C devices at once on the same I2C1 bus. And when i say cant, i mean it really messes things up. If i try to communicate with another devices it locks up the stream and i get "Timeout on I2C Write BUSY". Im wondering if its because the whole I2C way of communicating is a singleton. Looking into now.

  • Sweet, many thank!

  • I2C should work with many devices on a bus, but there are sometimes some issues:

    • Each device has to have a different address (so 2 of the same device isn't usually possible)
    • A lot of the boards you get with I2C devices on have pullup resistors pre-installed. If you put too many of them together you're going to end up with too much pullup resistance.

    Hope that helps!

  • Okay thats good, could you give an example of doing this? I keep getting Timeout on I2C Write BUSY

  • Just did this with a SSD1306 OLED and an HD44780 16x2 LCD:

    I2C1.setup({scl:B6,sda:B7});
    
    var g = require("SSD1306").connect(I2C1, function(){
       // write some text
       g.drawString("Hello World!",2,2);
       // write to the screen
       g.flip(); 
     }
    );
    var lcd = require("HD44780").connectI2C(I2C1);
    lcd.print("Hello World!");
    

    It's as easy as just setting I2C up once, and then using it multiple times.

  • Ahhh i see, so for others reading this here is where i went wrong.

    I2C1 needs to be called within scope of what your communicating with, im guessing its a state machine, so when you call ".connect(I2C1)" you taking control away from other modules that are using. When i see "require" i automatically think they need to be grouped at the top all pretty, but they dont.

    I was trying to do:

    var g = require("SSD1306").connect(I2C1);
    var bmp = require("BMP085").connect(I2C1);
    //... more code here
    
    bmp.getPressure(function(d) {
        //console.log("Pressure: " + d.pressure + " Pa");
        console.log("Temperature: " + d.temperature + " C");
    	g.clear();
       g.drawString("Temperature: " + d.temperature + " C",2,2);
       // write to the screen
       g.flip(); 
    
      });
    
    

    this doesnt work!

    what i needed was

    I2C1.setup({scl:B6,sda:B7});
    
    var text ="";
    
    function getTemp()
    {
      var bmp = require("BMP085").connect(I2C1);
      if (!bmp)
      {
        console.log("bmp failed to init");
        return null;
      }
      bmp.getPressure(function(d) {
        text = "Temperature: " + d.temperature + " C";
      });
      
    }
    
    function showTemp()
    {
      var g = require("SSD1306").connect(I2C1);
        if (!g)
      {
        console.log("g failed to init");
        return null;
      }
      g.clear();
      g.drawString(text,2,2);
      g.flip(); 
    
    }
    
    setInterval(function(){
        getTemp();
        showTemp();
     },1000);
    
    

    Many thanks for your help Gordon!

  • I think in this case it might have been because you were using I2c1 in the modules before it had been set up?

    Possibly even:

    I2C1.setup({scl:B6,sda:B7});
    var g = require("SSD1306").connect(I2C1);
    var bmp = require("BMP085").connect(I2C1);
    //... more code here
    

    Would have been fine...

    The other issue is that usually you do:

    var g = require("SSD1306").connect(I2C1, function(){
    ...
    });
    

    The function gets called when the display is initialised, which is actually after a slight delay.

    What you were doing with getting the pressure and then immediately writing to the display might have been trying to send stuff to the display before it had actually initialised.

  • @Gordon Thanks alot, was struggling with this, too.

  • The top one doesnt work, i was doing the setup, just ommited it in my example.

  • iv also ran into more problems with the SSD1306 display. if you increase the font size to more than about 4 (so its actually readable) it crashes.
    using :

    g.setFontVector(fontsize);
    

    very strange.

  • Huh! g.setFontVector() used to work - I remember someone using it to get 2 digits to fill a PCD8544 with the temperature...

  • unless im doing somthing wrong it no workie. Heres the code:

    I2C1.setup({scl:B6,sda:B7});
    
    
    var text ="temp";
    var fontsize =2;
    
    function getTemp()
    {
      var bmp = require("BMP085").connect(I2C1);
      if (!bmp)
      {
        console.log("bmp failed to init");
        return null;
      }
      bmp.getPressure(function(d) {
      text = "" + d.temperature + " C";
      });
      
    }
    
    function showTemp()
    {
      //require("Font8x12").add(Graphics);
      var g = require("SSD1306").connect(I2C1);
        if (!g)
      {
        console.log("g failed to init");
        return null;
      }
      g.clear();
      g.setColor(255,255,255);
      g.setFontVector(fontsize);
      //g.setFont8x12();
      g.drawString("Temperature: ",0,0);
      g.drawString(text,0,20);
      g.flip(); 
    
    }
    
    function onInit(){
    setInterval(function(){
        getTemp();
        showTemp();
     },1000);
    }
    

    if i increase the fontsize variable beyond 4 it freezes up (sometimes loops a couple of times) seems like a leak or overflow somewhere.

  • I think your problem is partially that you're re-initialising the display each time. setFontVector definitely works - I was using it just today, and just tested again.

    Try:

      var g = require("SSD1306").connect(I2C1);
        if (!g) {
        console.log("g failed to init");
        return null;
      }
    
    
    function showTemp()
    {
      g.clear();
      g.setColor(255,255,255);
      g.setFontVector(20);
      g.drawString("Temperature: ",0,0);
      g.drawString(text,0,20);
      g.flip(); 
    }
    

    There is however some regression issue when re-initialising the graphics multiple times, that I did notice recently and try to fix this morning (I fixed one problem, but haven't quite solved it yet).

  • Okay, it does work thanks for your help Gordon, it was indeed because i was initialising each time. The code that eventually worked properly was

    I2C1.setup({scl:B6,sda:B7});
    var g = require("SSD1306").connect(I2C1);
    var bmp = require("BMP085").connect(I2C1);
    //... more code here
    setInterval(function(){
    bmp.getPressure(function(d) {
        //console.log("Pressure: " + d.pressure + " Pa");
        console.log("Temperature: " + d.temperature + " C");
        g.clear();
      g.setFontVector(20);
       g.drawString("Temp: ",0,0);
      g.drawString(" "+ d.temperature + " C",0,25);
       // write to the screen
       g.flip(); 
      });
    },1000);
    
  • Ok, try:

    I2C1.setup({scl:B6,sda:B7});
    var bmp;
    var g = require("SSD1306").connect(I2C1, function() {
      bmp = require("BMP085").connect(I2C1);   
      setInterval(function(){
         bmp.getPressure(function(d) {
         //console.log("Pressure: " + d.pressure + " Pa");
         console.log("Temperature: " + d.temperature + " C");
         g.clear();
         g.drawString("Temperature: " + d.temperature + " C",2,2);
         // write to the screen
         g.flip(); 
       });
      },1000);
    });
    

    So initialising the display, and then initialising everything else in its callback. If that doesn't work it could be the BMP085 is messing things up somehow when it's not initialised, so you could try doing it first:

    I2C1.setup({scl:B6,sda:B7});
    var g;
    var bmp = require("BMP085").connect(I2C1);   
    setTimeout(function() {
      g = require("SSD1306").connect(I2C1, function() {  
        setInterval(function(){
          bmp.getPressure(function(d) {
            //console.log("Pressure: " + d.pressure + " Pa");
            console.log("Temperature: " + d.temperature + " C");
            g.clear();
            g.drawString("Temperature: " + d.temperature + " C",2,2);
            // write to the screen
            g.flip(); 
          });
        },1000);
      });
    }, 1000 /* 1 sec after BMP085 init */);
    

    Re-initialising the display each time really isn't a solution (it'll flicker massively every time you update it).

  • its all working now, although i have to reset the pico alot as the i2c bus locks up. is there any way to safely stop the i2c stuff? and or is there a better way of reseting other than re-plugging it.

  • Did you add the pullup resistors @user54499? They are necessary to keep a reliable state on the bus. Devices that are inherently slaves should not have pullups (though some will have them in 20k-100k range and will provide a weak current).
    I would add 4k7 (seems to be a popular compromise) near the master and see if it helps.

    R = 4k7 (4700) ohm
    
    VCC--+--+
         |  |
         R  R
         |  |
    SDA--+--|--->
    SCL-----+--->
    
  • I actually have had problems doing this in the past with the BMP180 specifically; almost identical configuration actually, doublebuffered display and BMP180 on same I2C bus; sometimes the BMP180 just seemed to get pissed off and start holding the bus low. I kept thinking it was wiring - and sometimes it reacted as if it was - but there was also behavior I couldn't reconcile with a hardware explanation. Plus I didn't get accurate data from it when it was inside my device, while it worked fine on the bench. I eventually gave up and have it disconnected. Never did figure out why it would go off the rails like that, but it failed with 3 different BMP180's, but they'd all work fine when I tried to test on the bench, and it failed with three different wiring setups as well (2 home-made PCB's and before that with wires)

  • Its a bit finicky at best for the BMP085.I submitted some code changes on Github which should help out a lot, instead of just locking the I2C bus permanently, it should just return null and let you try again. Previously if your BMP fails to init for some reason, you have to do a FULL reset and re-upload! Looks like the changes are now live.

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

I2C2 now working on pico?

Posted by Avatar for user54499 @user54499

Actions