Changing I2C pins with library "BitBang_I2C"

Hi to all,
I am not sure, if this is the correct forum for my question, so please move it if necessary.

I need to change the I2C pins. I use a color TFT display (https://www.az-delivery.de/products/2-4-tft-lcd-touch-display), which uses the standard SDA pin (A4) for LCD_RST. I could swap to Arduino Mega, but this board is too large (and uses too much current), I want to realize my project on an Arduino Mini Pro.

I found that there are some "bit banging" libraries which replace the Wire library, so BitBang_I2C (https://raw.githubusercontent.com/bitbank2/BitBang_I2C/master/examples/I2C_Detector/I2C_Detector.ino)

I used the following code to test the library and the device. (Hardware: AS7262 Breakout Board, SDA connected with D10, SCL connected with D11 of an Mini Pro 328, 5V)

When running the program I got an "0 device(s) found", when disconnecting the Breakout Board I got "I2C pins are not correct or the bus is being pulled low by a bad device; unable to run scan"

Can you help me to find out what was wrong?

//
// I2C Detector - scan and identify devices on an I2C bus using the BitBang_I2C library
// 
// The purpose of this code is to provide a sample sketch which can serve
// to detect not only the addresses of I2C devices, but what type of device each one is.
// So far, I've added the 25 devices I've personally used or found to be reliably detected
// based on their register contents. I encourage people to do pull requests to add support
// for more devices to make this code have wider appeal.

// There are plenty of I2C devices which appear at fixed addresses, yet don't have unique
// "Who_Am_I" registers or other data to reliably identify them. It's certainly possible to
// write code which initializes these devices and tries to verify their identity. This can
// potentially damage them and would necessarily increase the code size. I would like to keep
// the size of this code small enough so that it can be included in many microcontroller 
// projects where code space is scarce.

// Copyright (c) 2019 BitBank Software, Inc.
// Written by Larry Bank
// email: bitbank@pobox.com
// Project started 25/02/2019
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// Uses my Bit Bang I2C library. You can find it here:
// https://github.com/bitbank2/BitBang_I2C
#include <BitBang_I2C.h>


#define SDA_PIN 10
#define SCL_PIN 11
//
// If you don't need the explicit device names displayed, disable this code by
// commenting out the next line
//
//#define SHOW_NAME
#ifdef SHOW_NAME
const char *szNames[]  = {"Unknown","SSD1306","SH1106","VL53L0X","BMP180", "BMP280","BME280",
                "MPU-60x0", "MPU-9250", "MCP9808","LSM6DS3", "ADXL345", "ADS1115","MAX44009",
                "MAG3110", "CCS811", "HTS221", "LPS25H", "LSM9DS1","LM8330", "DS3231", "LIS3DH",
                "LIS3DSH","INA219","SHT3X","HDC1080","MPU6886","BME680", "AXP202", "AXP192", "24AA02XEXX", 
                "DS1307", "MPU688X", "FT6236G", "FT6336G", "FT6336U", "FT6436", "BM8563","BNO055"};
#endif

BBI2C bbi2c;

void setup() {
  Serial.begin(115200);
  memset(&bbi2c, 0, sizeof(bbi2c));
  bbi2c.bWire = 0; // use bit bang, not wire library
  bbi2c.iSDA = SDA_PIN;
  bbi2c.iSCL = SCL_PIN;
  I2CInit(&bbi2c, 100000L);
  delay(100); // allow devices to power up
}

void loop() {
uint8_t map[16];
uint8_t i;
int iDevice, iCount;

  Serial.println("Starting I2C Scan");
  I2CScan(&bbi2c, map); // get bitmap of connected I2C devices
  if (map[0] == 0xfe) // something is wrong with the I2C bus
  {
    Serial.println("I2C pins are not correct or the bus is being pulled low by a bad device; unable to run scan");
  }
  else
  {
    iCount = 0;
    for (i=1; i<128; i++) // skip address 0 (general call address) since more than 1 device can respond
    {
      if (map[i>>3] & (1 << (i & 7))) // device found
      {
        iCount++;
        Serial.print("Device found at 0x");
        Serial.print(i, HEX);
        iDevice = I2CDiscoverDevice(&bbi2c, i);
        Serial.print(", type = ");
  #ifdef SHOW_NAME
        Serial.println(szNames[iDevice]); // show the device name as a string
  #else
        Serial.println(iDevice); // show the device name as the enum index
  #endif
      }
    } // for i
    Serial.print(iCount, DEC);
    Serial.println(" device(s) found");
  }
  delay(5000);
}

Thank you,

-richard

I don't see why you want to change the pins of a bus system.

Did you say "some" :wink:
Here is a list of software I2C libraries: https://github.com/Testato/SoftwareWire/wiki/Arduino-I2C-libraries
If you look in the table if that library has "Arduino Wire compatible functions", then you can choose a library that mimics the Arduino Wire library. Then you need to make minimal changes to the source code of the display library.

Do you use the "Pro Mini" board ? https://www.arduino.cc/en/pmwiki.php?n=Main/ArduinoBoardProMini

But first you have to answer DrDiettrich's question. It is probably easier to move LCD_RST to an other pin.

As I said, the LCD_RST pin uses A4. It didn't come to my mind, that changing the LCD_RST pin would be a possibility, too. I'll try to find any hints to this.
Thanks,
-richard

Is the secret contained in the MCUFRIEND_kbv.h (https://github.com/prenticedavid/MCUFRIEND_kbv/blob/master/MCUFRIEND_kbv.h)? This library has to be loaded for the TFT display. But I don't find the pin definition for RST, only a line which is commented out and a line with "RST = 0":

	public:
//	MCUFRIEND_kbv(int CS=A3, int RS=A2, int WR=A1, int RD=A0, int RST=A4); //shield wiring
	MCUFRIEND_kbv(int CS=0, int RS=0, int WR=0, int RD=0, int _RST=0);  //dummy arguments 

Can I delete the comment sign, put it before the last line and change int RST = A4 to int RST = 12? Have I to deal with pullup resistors?

-richard

If I recall correctly, you can disconnect the LCD_RST from A4 and tie it to a 5v source through a pullup resistor - use the RESET pin on the UNO and the display will reset when the UNO is reset. Initialize the display before the I2C bus, the library may set the pinMode of A4 or attempt a reset on initialization of the display, but if I remember a previous question correctly it is never used again.

1 Like

Try that. Or search for a better coded library.

Note that pins 10, 11, 12, and 13 are already in use on that display board for the SPI interface to the SD card. Of course if you are using this with a Pro Mini you can simply leave those disconnected.

I don't use the SD card. I did not connect these pins to the display.

No. That did not work. I modified the MCUFRIEND_kbv.h as described and saved it with a new name (MCUFRIEND_kbv_RST.h) in the library folder in my /home directory, changed the #include statement accordingly and got "Cannot compile for the Pro Mini"
;-(

You would need to check all the files in the library and modify the #include lines for your new file name. The parameters are not used anyway.

I connected LCD_RST to the Pro Mini's RST as recommended (and assigned it accordingly #define LCR_RST RST), and put the "#include <Wire.h>" at the end of the preface (I don't know how this part is called "officially").

Everything works, besides the main thing: the connection to the I2C object. Given the following code, it stops at ams.begin()
(The error message of line 83 appears "Could not connect to sensor"). Any ideas thankfully appreciated!

-richard

/* Software for simple Spectrometer
    working with a AS7262 sensor (visible light - 6 channels)
 
    Written by r.mueller@oeko-sorpe.de, 12. Nov. 2021 with the aid of the AS7262 example
    from Arduino IDE
 **************************************************************************
      Designed specifically to work with the Adafruit AS7262 breakout
  ----> http://www.adafruit.com/products/3779

  These sensors use I2C to communicate. The device's I2C address is 0x49
  Adafruit invests time and resources providing this open source code,
  please support Adafruit andopen-source hardware by purchasing products
  from Adafruit!

  Written by Dean Miller for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ***************************************************************************

*/
#include "Adafruit_AS726x.h"                  // sensor library
#include <Adafruit_GFX.h>                     // graphics library
#include <MCUFRIEND_kbv.h>                    // TFT library
MCUFRIEND_kbv tft;                            // create the object!

String version = "0.4";


Adafruit_AS726x ams;                          //create the object


float sensorValues[AS726x_NUM_CHANNELS];      //buffer to hold calibrated values


                                              // configure the Analog ports
#define LCD_CS A3                             // Chip Select goes to Analog 3
#define LCD_CD A2                             // Command/Data goes to Analog 2
#define LCD_WR A1                             // LCD Write goes to Analog 1
#define LCD_RD A0                             // LCD Read goes to Analog 0
#define LCD_RST RST                         // Can alternately just connect to Arduino's reset pin

                                              // Define some colours for use in screens (RS565)
#define  BLACK   0x0000
#define  VIOLET  0x895C
#define  BLUE    0x001F
#define  GREEN   0x07E0
#define  YELLOW  0xFFE0
#define  ORANGE  0xFD20
#define  WHITE   0xFFFF
#define  RED     0xF800

/*for help defining colours, go to: http://www.barth-dev.de/online/rgb565-color-picker/
  click on the colour square and pick your colour. Then look under the RGB565 heading
    and you'll get the hex byte representation for that colour
*/
#include <Wire.h>

void setup() {

  tft.reset();
  uint16_t ID = tft.readID();                 // get the screen's ID
  tft.begin(ID);                              // ID: 0x9341  assign the ID to the screen object

  tft.setRotation(0);                         // portrait

  tft.fillScreen(BLACK);                      // splash screen

  tft.drawRect(0, 0, 240, 319, WHITE);
  tft.setCursor(30, 50); tft.setTextColor(WHITE); tft.setTextSize(2);
  tft.print("Spektral-Sensor");
  tft.setCursor(30, 300); tft.setTextSize(2);
  tft.print(version);
  delay(1000);
  tft.fillScreen(BLACK);
  tft.setCursor(98, 50); tft.print("nE      %");
 
  tft.setCursor(14, 80); tft.setTextColor(VIOLET); tft.print("vi: ");
  tft.setCursor(14, 110); tft.setTextColor(BLUE); tft.print("bl: ");
  tft.setCursor(14, 140); tft.setTextColor(GREEN); tft.print("gn: ");
  tft.setCursor(14, 170); tft.setTextColor(YELLOW); tft.print("ge: ");
  tft.setCursor(14, 200); tft.setTextColor(ORANGE); tft.print("or: ");
  tft.setCursor(14, 230); tft.setTextColor(RED); tft.print("rt: ");
   if(!ams.begin()){
    tft.setCursor(0,260); tft.print("could not connect tosensor! Please checkyour wiring.");
    while(1);
  }
}

void loop() {
  ams.startMeasurement();                     //begin a measurement

  bool rdy = false;
  while (!rdy) {
    delay(5);
    rdy = ams.dataReady();
  }
  ams.readCalibratedValues(sensorValues);     // read the values!
                                              // sensorValues: values measured in µW/cm²
  float vi = sensorValues[AS726x_VIOLET];
  float bl = sensorValues[AS726x_BLUE];
  float gn = sensorValues[AS726x_GREEN];
  float yl = sensorValues[AS726x_YELLOW];
  float og = sensorValues[AS726x_ORANGE];
  float rd = sensorValues[AS726x_RED];

  float E_vi = vi * 3.762;                    // factor: wavelength * Planck's constant
  float E_bl = bl * 4.18;                     // eg. violet: 450 * 0.836e-2
  float E_gn = gn * 4.598;                    // for conversion into nE
  float E_yl = yl * 4.7652;
  float E_og = og * 5.016;
  float E_rd = rd * 5.434;
  float E_sum = E_vi + E_bl + E_gn + E_yl + E_og + E_rd;
                                              // show values in nanoEinstein (nE) and percent
  tft.setCursor(70, 80); tft.print("            ");
  tft.setCursor(70, 80); tft.setTextColor(VIOLET, BLACK); tft.print(E_vi, 1);
  tft.setCursor(184, 80); tft.print(E_vi * 100 / E_sum, 1);
  tft.setCursor(70, 110); tft.print("           ");
  tft.setCursor(70, 110); tft.setTextColor(BLUE, BLACK); tft.print(E_bl, 1);
  tft.setCursor(184, 110); tft.print(E_bl * 100 / E_sum, 1);
  tft.setCursor(70, 140); tft.print("           ");
  tft.setCursor(70, 140); tft.setTextColor(GREEN, BLACK); tft.print(E_gn, 1);
  tft.setCursor(184, 140); tft.print(E_gn * 100 / E_sum, 1);
  tft.setCursor(70, 170); tft.print("           ");
  tft.setCursor(70, 170); tft.setTextColor(YELLOW, BLACK); tft.print(E_yl, 1);
  tft.setCursor(184, 170); tft.print(E_yl * 100 / E_sum, 1);
  tft.setCursor(70, 200); tft.print("           ");
  tft.setCursor(70, 200); tft.setTextColor(ORANGE, BLACK); tft.print(E_og, 1);
  tft.setCursor(184, 200); tft.print(E_og * 100 / E_sum, 1);
  tft.setCursor(70, 230); tft.print("           ");
  tft.setCursor(70, 230); tft.setTextColor(RED, BLACK); tft.print(E_rd, 1);
  tft.setCursor(184, 230); tft.print(E_rd * 100 / E_sum, 1);
  delay(1000);
}```

Can you write a test program that connects to any I2C sensor? Then add the (modified) display library but not the display itself and try again.

Thanks to all. Everything is working now as expected.
@ DrDiettrich: As test program I used the I2C scanner from examples. It helped me to find the fault. I dare not to say, but it was a bad soldering. Everything checked twice, but not the connection in the plug :frowning:
The program told that there were no sensors, but there were... so I searched for a bad connection.

Your valuable time was not spent in vane, I learned how to use the TFT without connecting LCD_RST to A4. I connected LCD_RST to Arduino's RST. Leaving that connection open or tying it to Vcc (via pullup) put the TFT in unusable state.

1 Like