Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 11 of 11

Thread: Communicating between VL6180x & T4.1 using I2C2 instead of I2C

  1. #1

    Communicating between VL6180x & T4.1 using I2C2 instead of I2C

    Hello. I can't figure out how to change my code to use I2C2 with a LV6180. it worked fine using pins 19 & 18, but when I changed to pins 24 & 25 the program hangs. I was thinking the only thing I had to add was the following lines:
    Wire.setSCL(24); // SCL2 on third i2c bus on T4.1
    Wire.setSDA(25); // SDA2 on third i2c bus on T4.1
    Wire.begin();

    I'm relatively inexperienced at Arduino and and completely inexperienced at I2C. My project uses a Teensy 4.1, an ILI9341, & a VL6180x. sketch and photo attached (hopefully). I'll greatly appreciate any help you can offer.

    Code:
    // This sketch uses the following:  Radio Buttons,  Second Hand using sin() and cos(),
    // Bar Graph reading VL6180X
    //
    //
    //
    #include <SPI.h>
    #include <Wire.h>
    #include <ILI9341_t3.h>
    #include <XPT2046_Touchscreen.h>
    #include <TimeLib.h> //added
    #include "Adafruit_VL6180X.h"  //add ed from vl6180
    #include <movingAvg.h>         // https://github.com/JChristensen/movingAvg
    
    Adafruit_VL6180X vl = Adafruit_VL6180X();  //add ed from vl6180
    
    // This is calibration data for the raw touch data to the screen coordinates
    #define TS_MINX 400  //150
    #define TS_MINY 300  //130
    #define TS_MAXX 3900 //3800
    #define TS_MAXY 3900 //4000
    
    #define CS_PIN 8
    #define TIRQ_PIN  2
    
    XPT2046_Touchscreen ts(CS_PIN, TIRQ_PIN);
    #define TFT_CS 10
    #define TFT_DC  9
    ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
    uint8_t range = 0;
    int buttX = 255, buttWid = 60, buttHgt = 40, buttRnd = 10, buttSel = 3;
    int buttY[] = {195, 145, 95, 45};
    const char* buttText[] = {"GRN", "YEL", "RED", "AUT"};
    // unsigned int buttColor[] = {ILI9341_GREEN, ILI9341_YELLOW, ILI9341_RED, ILI9341_WHITE};
    unsigned int buttColor[] = {0x07E0, 0xFFE0, 0xF800, 0xFFFF};
    movingAvg rangeAvg(20);
    
    void setup(void)
    {
      Wire.setSCL(24); // SCL2 on third i2c bus on T4.1
      Wire.setSDA(25); // SDA2 on third i2c bus on T4.1
      Wire.begin();
    
      vl.begin();
      //Serial.begin(38400);
      //delay(1000);
      tft.begin();
      //if (!ts.begin()) { 
      //  Serial.println("Unable to start touchscreen.");
      //} 
      //else { 
      //  Serial.println("Touchscreen started."); 
      //}
      ts.begin();
      setSyncProvider(getTeensy3Time); //added
    
      tft.fillScreen(ILI9341_NAVY);
      // origin = left,top landscape (USB left upper)
      tft.setRotation(3); 
      ts.setRotation(1); 
      clockFace();
      for(int buttNum = 0; buttNum < 4; buttNum ++)
      {
        drawButton(buttNum);
      }
      rangeAvg.begin();
    }
    
    void loop()
    {
      checkTouchData();
      static int lastSec = 99;
      if (lastSec != second())
      {
        lastSec = second();
        digitalClockDisplay();  
      }
      static int lastSel = 99;
      if (lastSel != buttSel)
      {
        lastSel = buttSel;
        for(int buttNum = 0; buttNum < 4; buttNum ++)
        {
          drawButton(buttNum);
        }
      }
      unsigned long lastShortTime = 0;
      if ((millis() - lastShortTime) > 200)
      {
        getRange();
        lastShortTime = millis();
      }
    }
    
    void checkTouchData()
    {
      if (!ts.bufferEmpty())
      {   
        // Retrieve a point  
        TS_Point p = ts.getPoint(); 
        // Scale using the calibration #'s
        // and rotate coordinate system
        int x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width());
        int y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height());
        if((x > buttX) && (x < (buttX + buttWid)))
        {
          for(int buttNum = 0; buttNum < 4; buttNum ++)
          {
            if(buttSel != buttNum)
            {
              if((y > buttY[buttNum]) && (y < (buttY[buttNum] + buttHgt)))
              {
                buttSel = buttNum;
              }
            }
          }
        }
      }
    }
    
    void drawButton(int buttNum)
    {
      tft.setCursor((buttX + 12) , (buttY[buttNum] + 12));
      tft.setTextSize(2);
      if(buttNum != buttSel)
      {
        tft.fillRoundRect(buttX, buttY[buttNum], buttWid, buttHgt, buttRnd, ILI9341_BLACK); // Auto
        tft.setTextColor(buttColor[buttNum]);
      }
      else
      {
        tft.fillRoundRect(buttX, buttY[buttNum], buttWid, buttHgt, buttRnd, buttColor[buttNum]); // Auto
        tft.setTextColor(ILI9341_BLACK);
      }
      tft.println(buttText[buttNum]);
      tft.drawRoundRect(buttX, buttY[buttNum], buttWid, buttHgt, buttRnd, ILI9341_WHITE); // Auto
    }
    
    void clockFace()
    {
      int circCentX = 120;
      int circCentY = 120;
      int circRad1 = 90;
      int circRad2 = 100;
      tft.fillCircle(circCentX, circCentY, circRad2, ILI9341_BLACK);
      tft.drawCircle(circCentX, circCentY, circRad1, ILI9341_WHITE);
      tft.drawCircle(circCentX, circCentY, circRad2, ILI9341_WHITE);
      for(int i = 0; (i < 12); i ++)
      {
        int endX = circCentX + circRad2 * sin(i * 2 * PI / 12);
        int endY = circCentY - circRad2 * cos(i * 2 * PI / 12);
        tft.drawLine(circCentX, circCentY, endX, endY, ILI9341_WHITE);
      }
      tft.fillRect((circCentX - circRad2), (circCentY - 2), (circRad2 * 2), (5), ILI9341_YELLOW);
      tft.fillRect((circCentX - 2), (circCentY - circRad2), (5), (circRad2 * 2), ILI9341_YELLOW);
      tft.fillCircle(circCentX, circCentY, circRad1 - 1, ILI9341_BLACK);
    }
    
    void secondHand(int sec)
    {
      int circCentX = 120;
      int circCentY = 120;
      int circRad1 = 90;
    //  if(sec < 60) // ** single line
      if(sec == 0) // ** fills face **
      {
        tft.fillCircle(circCentX, circCentY, circRad1 - 1, ILI9341_BLACK);
      }
      int endX = circCentX + (circRad1 - 1) * sin(sec * 2 * PI / 60);
      int endY = circCentY - (circRad1 - 1) * cos(sec * 2 * PI / 60);
      if(buttSel == 3)
      {
        tft.drawLine(circCentX, circCentY, endX, endY, buttColor[autClr(range)]);
        tft.fillCircle(circCentX, circCentY, 25, ILI9341_BLACK);
        tft.fillCircle(circCentX, circCentY, 20, buttColor[autClr(range)]);
      }
      else
      {
        tft.drawLine(circCentX, circCentY, endX, endY, buttColor[buttSel]);
        tft.fillCircle(circCentX, circCentY, 25, ILI9341_BLACK);
        tft.fillCircle(circCentX, circCentY, 20, buttColor[buttSel]);
      }
      tft.setCursor((circCentX - 11), (circCentY - 7));
      tft.setTextColor(ILI9341_BLACK);
      tft.setTextSize(2);
      printCentSec(second());
      tft.println();
    }
    
    void digitalClockDisplay() {
      tft.setCursor(184, 6);
      tft.setTextColor(ILI9341_WHITE, ILI9341_NAVY);
      tft.setTextSize(2);
      int disHour = hour();
      if(hour() == 0) disHour = 12;
      else if(hour() >12) disHour = hour() - 12;
      if(disHour < 10) tft.print(" ");
      tft.print(disHour);
      printDigits(minute());
      printDigits(second());
      if (hour() > 12) tft.print(" PM");
      else tft.print(" AM");
      //tft.print(" ");
      tft.println(); 
      tft.setCursor(220, 22);
      tft.print(month());
      tft.print("/");
      tft.print(day());
      tft.print("/");
      tft.print(year() - 2000); 
      tft.println(); 
      secondHand(second());
    }
    
    time_t getTeensy3Time()
    {
      return Teensy3Clock.get();
    }
    
    void printDigits(int digits){
      // utility function for digital clock display: prints preceding colon and leading 0
      tft.print(":");
      if(digits < 10)
        tft.print('0');
      tft.print(digits);
    }
    
    void printCentSec(int digits)
    {
      // utility function for center second display: prints leading 0
      if(digits < 10)
        tft.print('0');
      tft.print(digits);
    }
    
    void getRange()
    {
      //added from vl6180x
      range = vl.readRange();
      range = rangeAvg.reading(range);
      uint8_t status = vl.readRangeStatus();
    // dispRangeTxt
      tft.setCursor(6, 3);
      tft.setTextColor(ILI9341_WHITE, ILI9341_NAVY);
      tft.print(range); 
      tft.println(" MM  ");
    // limit range
      if(range > 180) range = 180;
      barGrHrz(range);
    }
    void barGrHrz(int val)
    {
      int xPos = 30, yPos = 223, xLen = 180, yLen = 16;
      tft.fillRect((xPos + val),  yPos, (xLen - val), yLen, (CL(32, 32, 32))); // darker grey
      tft.fillRect(xPos,  yPos, val, yLen, buttColor[autClr(val)]);
      tft.drawRect((xPos - 1), (yPos - 1), (xLen + 1), (yLen + 1), 0xFFFF); // white
    }
    int autClr(int val)
    {
      int clr = 0;
      int sp[] = {50, 100, 150};
      if(val <= sp[0]) clr = 0;
      else if((sp[0] < val) &&(val <= sp[1])) clr = 1;
      else if((sp[1] < val) &&(val <= sp[2])) clr = 2;
      else  clr = 3;
      return clr;
    }
    Click image for larger version. 

Name:	IMG_0740 (1).jpg 
Views:	26 
Size:	196.5 KB 
ID:	26040
    Thanks
    Rocky

  2. #2
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    497
    Try
    Code:
    vl.begin(&Wire2);

  3. #3
    Thanks BriComp!

    I'll try that this afternoon.

    Can you help me understand what the argument (&Wire2) does exactly? Or can you point me to some resource that might explain it?

    Thanks again!

  4. #4
    Senior Member
    Join Date
    Feb 2017
    Posts
    428
    See 'Adafruit_VL6180X.h' for the prototype of the begin() function:
    Code:
    boolean begin(TwoWire *theWire = &Wire)
    So, it defaults to using Wire, but that can be overridden by supplying a pointer to a different TwoWire object.

  5. #5
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    497
    I think @gfvalvo said it before I got back.
    You also do not need the other Wire stuff in setup.
    Code:
    /*
      Wire.setSCL(24); // SCL2 on third i2c bus on T4.1
      Wire.setSDA(25); // SDA2 on third i2c bus on T4.1
      Wire.begin();
    */
      vl.begin(&Wire2);   //Pass over the pointer to the relevant Wire channel - vl (Adafruit_VL6180X.) will do the rest
    Wire addresses the first I2C bus (I2C),
    Wire1 the second (I2C1) and
    Wire2 the third (I2C2).

  6. #6
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    9,998
    Quote Originally Posted by BriComp View Post
    I think @gfvalvo said it before I got back.
    You also do not need the other Wire stuff in setup.
    Code:
    /*
      Wire.setSCL(24); // SCL2 on third i2c bus on T4.1
      Wire.setSDA(25); // SDA2 on third i2c bus on T4.1
      Wire.begin();
    */
      vl.begin(&Wire2);   //Pass over the pointer to the relevant Wire channel - vl (Adafruit_VL6180X.) will do the rest
    Wire addresses the first I2C bus (I2C),
    Wire1 the second (I2C1) and
    Wire2 the third (I2C2).
    Side notes here:
    I believe Wire2 only has one set of valid pins 24 and 25 which it defaults to, so you don't need to do a setSCL or setSDA.

    Also if it did have multiple valid pins like Wire1 on T4.1 has SCL with two possible pins (17, 44) and SDA (16, 45)
    Where the defaults as 16, 17... In these cases if I wanted to use pins 44 and 45 I do need to tell the system to use those pins.

    In this case you would do:
    Code:
    Wire1.setSCL(44);
    Wire1.setSDA(45);
    Note You use the Wire1 object in this case, not the Wire object.

    Also unclear if you will need to do a Wire1.begin()... The Adafruit class may do that internal.. But probably does not hurt to do so.

  7. #7
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    497
    Also unclear if you will need to do a Wire1.begin()... The Adafruit class may do that internal.. But probably does not hurt to do so.
    It does do the necessary begin(&wire). I downloaded the code too ensure that before giving my recommendation.

  8. #8
    Senior Member BriComp's Avatar
    Join Date
    Apr 2014
    Location
    Cheltenham, UK
    Posts
    497
    Here is a snippet of the Adafruit LV6180X code:
    Code:
    /**************************************************************************/
    /*!
        @brief  Initializes I2C interface, checks that VL6180X is found and resets
       chip.
        @param  theWire Optional pointer to I2C interface, &Wire is used by default
        @returns True if chip found and initialized, False otherwise
    */
    /**************************************************************************/ 
    boolean Adafruit_VL6180X::begin(TwoWire *theWire) {
      // only needed to support setAddress()
      _i2c = theWire;
    
      if (i2c_dev)
        delete i2c_dev;
      i2c_dev = new Adafruit_I2CDevice(_i2caddr, _i2c);
      if (!i2c_dev->begin())
        return false;
    
      // check for expected model id
      if (read8(VL6180X_REG_IDENTIFICATION_MODEL_ID) != 0xB4) {
        return false;
      }
    
      // fresh out of reset?
      if (read8(VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET) & 0x01) {
        loadSettings();
        write8(VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET, 0x00);
      }
    
      return true;
    }
    As it says in the comments it uses the I2C Wire address (Pointer) you supply (&Wire1 or &Wire2). If no address (Pointer) is supplied it defaults to Wire.

  9. #9
    Quote Originally Posted by gfvalvo View Post
    See 'Adafruit_VL6180X.h' for the prototype of the begin() function:
    Code:
    boolean begin(TwoWire *theWire = &Wire)
    So, it defaults to using Wire, but that can be overridden by supplying a pointer to a different TwoWire object.
    Thanks! I don't really understand all the syntax of that line, but I suppose that knowledge will eventually trickle into my brain. There is lot to learn about this hobby. So far, it's been great.

  10. #10
    Thanks KurtE! Side notes are good.

    Thanks BriComp! My brain is full for now. All this will make more sense to me in time. I think you've given me everything that I need to know about it.

  11. #11
    Thanks to everyone for the help!! It's back up and running. This is an amazing forum and the Teensy is an amazing product!

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •