Teensy 4.1: Multiple I2c and SPI devices

Hey all,

Re: Teensy 4.1
I am having difficulty connecting multiple I2C devices (using the SDA, SCL, SDA1, and SCL1).
I am trying to connect a BMP390 via I2C and an LC709203F via I2C. I have the LC709203F connected to pins 19 and 18 and this works. The BMP390 is connected to 16 and 17 and is not recognized.

I am also trying to connect a BNO085 and an RFM95W via the corresponding SPI and SPI1 pins.

I had success using the BMP390 and the BNO085 with SPI, but the addition of the RFM95W led me to need to use I2C for the BMP390.

TLDR: I need to connect two I2C devices to the Teesny 4.1 and can't seem to get it to work with the Wire.h library.

I'd post all the code, but it is nearing 1000 lines... I am failing on setup, so here is the setup code. Something may be wrong with my RFM95W setup... But getting the two I2C devices working is my first priority. Don't mind all the variables, some of them will be removed once I figure out what I want:

Code:
/*

AVIONICS
Version: 0.1.0
Date: 2/2/2023


*/

// Included libraries
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO08x.h>
#include <SD.h>
#include <SdFat.h>
#include <TimeLib.h>
#include <Adafruit_BMP3XX.h>
#include <Adafruit_LC709203F.h>
#include <RH_RF95.h>
#include <cmath>


// Program details
String version = "v0.1.0";
String creationDate = "2/2/2023";
String description = "Dual Deployment Avionics.";

// Addresses for the RFM95W
#define CLIENT_ADDRESS 1
#define SERVER_ADDRESS 2

// BNO085 pin assignments
#define BNO08X_CS 10
#define BNO08X_INT 3
#define BNO08X_RESET 5

// BMP390 pin assignments for SPI ! IF USED !
/*
#define BMP_SCK 27
#define BMP_MISO 1
#define BMP_MOSI 26
#define BMP_CS 0
*/

// RFM95W pin assignments
#define RFM95_RST 8
#define RFM95_CS 0
#define RFM95_INT digitalPinToInterrupt (7)


// LED pin assignments
#define greenLED 41
#define yellowLED 40
#define redLED 39


// Recovery system pin assignments
#define drogueMatchPin 11
#define mainMatchPin 12


// Rocket mode pin assignments
#define standbySwitch 32
#define launchSwitch 35
#define armingSwitch 31

// Peizoelectric buzzer pin assignments
#define buzzer 2
#define locationBuzzer 3

// Ignition button pin assignments
#define ignitionButtonPin  16

// Set RFM95W frequency
#define RF95_FREQ 915.0

// Serial baud rate
const int serialBaud = 115200;

// Switch and button states
int armingSwitchState = LOW;
int drogueMatchState = LOW;
int mainMatchState = LOW;
int drogueMatchFiredState = LOW; // state for if the drogue fired
int mainMatchFiredState = LOW; // state for if the main fired
int ignitionButtonState = LOW;
int startLaunchSwitchState = 1;
int startStandbySwitchState = 1;
int newStandbySwitchState;
int newLaunchSwitchState;
int oldStandbySwitchState = 1;
int oldLaunchSwitchState = 1;

// Constant variables
const int matchDelay = 500;
const int standbyLoggingDelay = 1000;
const int launchLoggingDelay = 100;
const int mainChuteDeploymentAltitude = 500;
unsigned long timeT = 0;
unsigned long debounce = 250UL;

// Variables for calculations and logging
int batteryPercent;
double apogeeAltitude;
double mainChuteAltitude;
double currentAltitude;
double acceleration;
double timeZero;
double flightTime;
double currentTime;
double velocity;
double launchPadAltitude;
double relitiveAltitude;
double fallingAltitude;
double gravity = 9.81; // earth's gravitational constant
double gForce;
double calculatedAltitude;
double velocityX;
double velocityY;
double velocityZ;

// Variables for the data structure for transmission to the launch pad
struct dataStruct   {
    double flightTime;
    double currentAltitude;
    double apogeeAltitude;
    double gForce;
    double gForceCurrent;
    double gForcePrevious;
    unsigned long packetCounter;
    // may not need the following quaternions ???
    double quatX;
    double quatY;
    double quatZ;
    double quatW;
    // other posible calculations
    double linearAcceleration;
    double velocity;
    double burnTime;
} avionicsCalculations;

// Angulat velocity variables if needed
float angVeloX;
float angVeloY;
float angVeloZ;

/*

// Variables for calculation of linear acceleration (Raw accelerometer values)
double aX, aY, aZ;

// Quaternion variables
double qW, qZ, qX, qY;

// Variables to rotate the acceleration vector by the quaternion
double linearAccelerationX, linearAccelerationY, linearAccelerationZ;

*/

// Packet counter, we increment per transmission
int64_t packetnum = 0;

// Chip select for internal SD card
#define chipSelect BUILTIN_SDCARD

// Set sea level pressure
#define SEALEVELPRESSURE_HPA (1013.23)

// For teensy RTC
#define TIME_HEADER "T"

// Singleton instance of the radio driver
//RH_RF95 rf95;

File dataLog;
Adafruit_BMP3XX bmp;
Adafruit_BNO08x bno08x(BNO08X_RESET);
sh2_SensorValue_t sensorValue;
Adafruit_LC709203F lc;
RH_RF95 rf95(RFM95_CS, RFM95_INT);

// The folowing is required for using the builtin RTC on the Teensy 4.1
time_t getTeensy3Time()
{
  return Teensy3Clock.get();
}

unsigned long processSyncMessage() {

  unsigned long pctime = 0L;
  const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013

  if(Serial.find(TIME_HEADER)) {
    pctime = Serial.parseInt();
    return pctime;
    if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
      pctime = 0L; // return 0 to indicate that the time is not valid
    }
  }
  return pctime;
}

void setup () {
	  setSyncProvider(getTeensy3Time);

	// RFM 95W setup
    pinMode(RFM95_RST, OUTPUT);
    digitalWrite(RFM95_RST, LOW);

    Serial.begin(serialBaud);
    Wire.begin();
	  SD.begin(chipSelect);
    SPI.begin();

    // Peizoelectric buzzer pin setups
    pinMode(buzzer, OUTPUT);
    pinMode(locationBuzzer, OUTPUT);

	    delay(1000);
    Serial.print(F("Teensy 4.1 Dual Deployment Avionics "));
    Serial.print(version);
    Serial.println("");
    Serial.print(creationDate);
    Serial.println("");
    Serial.print(description);
    Serial.println("");
        digitalWrite(buzzer, HIGH);
            delay(500);
        digitalWrite(buzzer, LOW);
        delay(500);

	// Set up oversampling and filter initialization
    bmp.setTemperatureOversampling(BMP3_OVERSAMPLING_8X);
    bmp.setPressureOversampling(BMP3_OVERSAMPLING_4X);
    bmp.setIIRFilterCoeff(BMP3_IIR_FILTER_COEFF_3);
    bmp.setOutputDataRate(BMP3_ODR_100_HZ);

    //LED setup
    pinMode(greenLED, OUTPUT);
    pinMode(redLED, OUTPUT);
    pinMode(yellowLED, OUTPUT);

    // E-match setup
    pinMode(drogueMatchPin, OUTPUT);
    pinMode(mainMatchPin, OUTPUT);

    //Piezoelectric speaker setup
    //pinMode(beacon, HIGH);
    //const int beaconDelay = 500;

    // Safety/mode selection switch setup
    pinMode(standbySwitch, INPUT_PULLUP);
    pinMode(launchSwitch, INPUT_PULLUP);

    // Peizoelectric buzzer pin setups
    pinMode(buzzer, OUTPUT);
    pinMode(locationBuzzer, OUTPUT);

    // Recovery system setup
    pinMode(armingSwitch, INPUT_PULLUP);

    // Ignition pin setup
    pinMode(ignitionButtonPin, OUTPUT);

    

	// Rest the RFM95W manually; LOW starts the radio
    digitalWrite(RFM95_RST, HIGH);
        delay(10);
    digitalWrite(RFM95_RST, LOW);

	// Set power level for the RFM95W
    //rf95.setTxPower(20, true);

	// read batter percent and assign it to the below variable
/* 
    batteryPercent = lc.cellPercent ();
    if (batteryPercent << 35)   {
        Serial.print(F("Batter percent below 50"));
        While(1);
    }
*/
        

    if (timeStatus() != timeSet)    {
        Serial.println(F("RTC failed to initialized."));
            delay(750);
    }

    else{
        Serial.println(F("RTC initialized."));
            delay(750);
    }

    if (!bno08x.begin_SPI(BNO08X_CS, BNO08X_INT))   {
        Serial.println(F("BNO085 failed to initialized."));
            delay(750);
    }

    else{
        Serial.println(F("BNO085 initialized."));
            delay(750);
    }

    //if (!bmp.begin_SPI(BMP_CS, BMP_SCK, BMP_MISO, BMP_MOSI))    {
    if (!bmp.begin_I2C())   {
        Serial.println(F("BMP390 IMU failed to initialized."));
            delay(750);
    }

    else{
        Serial.println(F("BMP390 IMU initialized."));
            delay(750);
    }

    if (!SD.begin(chipSelect))   {
        Serial.println(F("SD card failed to initialized."));
            delay(750);
    }

    else{
        Serial.println(F("SD card initialized."));
            delay(750);
    }

    if (!rf95.init())    {
        Serial.println(F("RF95W failed to initialized."));
            delay(750);
    }

    else{
        Serial.println(F("RFM95W initialized."));
            delay(750);
    }

    if (!rf95.setFrequency(RF95_FREQ))  {
        Serial.println(F("RFM05W frequency failed to set."));
            delay(750);
    }

    else{
        Serial.println(F("RFM95W frequency set."));
            delay(750);
    }

    if (!lc.begin)  {
        Serial.println(F("Battery not found."));
            delay(750);
    }

    else    {
        Serial.println(F("Battery connected."));
            delay(750);
    }


}
 
The BMP390 is connected to 16 and 17 and is not recognized.
SDA1 and SCL1 are addressed as Wire2.
You need to change line 308 :- if (!bmp.begin_I2C()) { to include the Wire2 assignment.
So something like if (!bmp.begin(BMP3XX_ADDRESS, &Wire2){.
NOTE:
I am not sure about the need for the &. I still get confused with the use of pointers.
 
Back
Top