Skip to content

Commit

Permalink
Add PCA9546A support & glove imus list
Browse files Browse the repository at this point in the history
  • Loading branch information
Eirenliel committed Aug 30, 2024
1 parent 7ca16a2 commit 76b1aaa
Show file tree
Hide file tree
Showing 8 changed files with 183 additions and 16 deletions.
44 changes: 36 additions & 8 deletions src/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
// Set parameters of IMU and board used
#define IMU IMU_BNO085
#define SECOND_IMU IMU
#define BOARD BOARD_SLIMEVR
#define BOARD BOARD_GLOVE_IMU_SLIMEVR_DEV
#define IMU_ROTATION DEG_270
#define SECOND_IMU_ROTATION DEG_270

Expand All @@ -37,7 +37,7 @@

#define MAX_IMU_COUNT 2

#if BOARD != BOARD_GLOVE_IMU
#if BOARD != BOARD_GLOVE_IMU_SLIMEVR_DEV
// Axis mapping example
/*
#include "sensors/axisremap.h"
Expand All @@ -54,12 +54,22 @@ IMU_DESC_ENTRY(IMU_BMP160, PRIMARY_IMU_ADDRESS_ONE, IMU_ROTATION, PIN_IMU_SCL, P
#endif

#else
// Predefines for the GLOVE
#ifndef SENSOR_DESC_LIST
#define SENSOR_DESC_LIST \
IMU_DESC_ENTRY(IMU, PRIMARY_IMU_ADDRESS_ONE, IMU_ROTATION, DIRECT_WIRE(PIN_IMU_SCL, PIN_IMU_SDA), PRIMARY_IMU_OPTIONAL, DIRECT_PIN(PIN_IMU_INT), 0) \
IMU_DESC_ENTRY(IMU, SECONDARY_IMU_ADDRESS_TWO, SECOND_IMU_ROTATION, DIRECT_WIRE(PIN_IMU_SCL, PIN_IMU_SDA), SECONDARY_IMU_OPTIONAL, DIRECT_PIN(PIN_IMU_INT_2), 0)
#endif

// Predefines for the GLOVE
#ifndef SENSOR_DESC_LIST
#define SENSOR_DESC_LIST \
IMU_DESC_ENTRY(IMU, 0x4a ^ 0x02, IMU_ROTATION, DIRECT_WIRE(PIN_IMU_SCL, PIN_IMU_SDA), true, MCP_PIN(MCP_GPA6), 0) \
IMU_DESC_ENTRY(IMU, 0x4b ^ 0x02, IMU_ROTATION, DIRECT_WIRE(PIN_IMU_SCL, PIN_IMU_SDA), true, MCP_PIN(MCP_GPA7), 0) \
IMU_DESC_ENTRY(IMU, 0x4a, IMU_ROTATION, PCA_WIRE(PIN_IMU_SCL, PIN_IMU_SDA, PCA_ADDR, 0), true, MCP_PIN(MCP_GPA0), 0) \
IMU_DESC_ENTRY(IMU, 0x4b, IMU_ROTATION, PCA_WIRE(PIN_IMU_SCL, PIN_IMU_SDA, PCA_ADDR, 0), true, MCP_PIN(MCP_GPB1), 0) \
IMU_DESC_ENTRY(IMU, 0x4a, IMU_ROTATION, PCA_WIRE(PIN_IMU_SCL, PIN_IMU_SDA, PCA_ADDR, 1), true, MCP_PIN(MCP_GPB2), 0) \
IMU_DESC_ENTRY(IMU, 0x4b, IMU_ROTATION, PCA_WIRE(PIN_IMU_SCL, PIN_IMU_SDA, PCA_ADDR, 1), true, MCP_PIN(MCP_GPB3), 0) \
IMU_DESC_ENTRY(IMU, 0x4a, IMU_ROTATION, PCA_WIRE(PIN_IMU_SCL, PIN_IMU_SDA, PCA_ADDR, 2), true, MCP_PIN(MCP_GPB4), 0) \
IMU_DESC_ENTRY(IMU, 0x4b, IMU_ROTATION, PCA_WIRE(PIN_IMU_SCL, PIN_IMU_SDA, PCA_ADDR, 2), true, MCP_PIN(MCP_GPB5), 0) \
IMU_DESC_ENTRY(IMU, 0x4a, IMU_ROTATION, PCA_WIRE(PIN_IMU_SCL, PIN_IMU_SDA, PCA_ADDR, 3), true, MCP_PIN(MCP_GPB6), 0) \
IMU_DESC_ENTRY(IMU, 0x4b, IMU_ROTATION, PCA_WIRE(PIN_IMU_SCL, PIN_IMU_SDA, PCA_ADDR, 3), true, MCP_PIN(MCP_GPB7), 0)
#endif

#endif

// Battery monitoring options (comment to disable):
Expand Down Expand Up @@ -216,4 +226,22 @@ IMU_DESC_ENTRY(IMU_BMP160, PRIMARY_IMU_ADDRESS_ONE, IMU_ROTATION, PIN_IMU_SCL, P
#ifndef BATTERY_SHIELD_R2
#define BATTERY_SHIELD_R2 100
#endif
#elif BOARD == BOARD_GLOVE_IMU_SLIMEVR_DEV
#define PIN_IMU_SDA 1
#define PIN_IMU_SCL 0
#define PCA_ADDR 0x70
#define PIN_IMU_INT 16
#define PIN_IMU_INT_2 13
#define PIN_BATTERY_LEVEL 17
#define LED_PIN 2
#define LED_INVERTED true
#ifndef BATTERY_SHIELD_RESISTANCE
#define BATTERY_SHIELD_RESISTANCE 0
#endif
#ifndef BATTERY_SHIELD_R1
#define BATTERY_SHIELD_R1 10
#endif
#ifndef BATTERY_SHIELD_R2
#define BATTERY_SHIELD_R2 40.2
#endif
#endif
6 changes: 5 additions & 1 deletion src/sensorinterface/DirectPinInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
#include <PinInterface.h>
#include <Arduino.h>

/**
* Pin interface using direct pins
*
*/
class DirectPinInterface : public PinInterface
{
public:
Expand All @@ -40,4 +44,4 @@ class DirectPinInterface : public PinInterface
uint8_t _pinNum;
};

#endif // _H_DIRECT_PIN_INTERFACE_
#endif // _H_DIRECT_PIN_INTERFACE_
41 changes: 41 additions & 0 deletions src/sensorinterface/I2CPCAInterface.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
SlimeVR Code is placed under the MIT license
Copyright (c) 2024 Eiren & SlimeVR Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "I2CPCAInterface.h"

void SlimeVR::I2CPCASensorInterface::init()
{
_wire.init();
}

void SlimeVR::I2CPCASensorInterface::swapIn()
{
_wire.swapIn();
Wire.beginTransmission(_address);
Wire.write(1 << _channel);
Wire.endTransmission();
// On ESP32 we need to reconnect to I2C bus for some reason
#if ESP32
_wire.disconnect();
_wire.swapIn();
#endif
}
51 changes: 51 additions & 0 deletions src/sensorinterface/I2CPCAInterface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
SlimeVR Code is placed under the MIT license
Copyright (c) 2024 Eiren & SlimeVR Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef I2C_PCA_INTERFACE_H
#define I2C_PCA_INTERFACE_H

#include "I2CWireSensorInterface.h"

namespace SlimeVR
{
/**
* I2C Sensor interface for use with PCA9547 (8-channel I2C-buss multiplexer)
* or PCA9546A (4-channel I2C-bus multiplexer) or analogs
*/
class I2CPCASensorInterface : public SensorInterface {
public:
I2CPCASensorInterface(uint8_t sda, uint8_t scl, uint8_t address, uint8_t channel) :
_wire(I2CWireSensorInterface(sda, scl)), _address(address), _channel(channel){};
~I2CPCASensorInterface(){};

void init() override final;
void swapIn() override final;
protected:
uint8_t _address;
uint8_t _channel;
I2CWireSensorInterface _wire;
};


}

#endif
8 changes: 8 additions & 0 deletions src/sensorinterface/I2CWireSensorInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,12 @@ namespace SlimeVR
isI2CActive = true;
}
}

void disconnectI2C()
{
isI2CActive = false;
#if ESP32
Wire.end();
#endif
}
}
20 changes: 14 additions & 6 deletions src/sensorinterface/I2CWireSensorInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,29 +25,37 @@
#define SENSORINTERFACE_I2CWIRE_H

#include "globals.h"
#include <Wire.h>
#include <Arduino.h>
#include "SensorInterface.h"
#include <i2cscan.h>

namespace SlimeVR
{
void swapI2C(uint8_t sclPin, uint8_t sdaPin);
void disconnectI2C();

/**
* I2C Sensor interface using direct arduino Wire on provided pins
*
*/
class I2CWireSensorInterface : public SensorInterface {
public:
I2CWireSensorInterface(uint8_t sdapin, uint8_t sclpin) :
sdaPin(sdapin), sclPin(sclpin){};
_sdaPin(sdapin), _sclPin(sclpin){};
~I2CWireSensorInterface(){};

void init() override final {
I2CSCAN::clearBus(sdaPin, sclPin);
I2CSCAN::clearBus(_sdaPin, _sclPin);
}
void swapIn() override final {
swapI2C(sclPin, sdaPin);
swapI2C(_sclPin, _sdaPin);
}
void disconnect() {
disconnectI2C();
}
protected:
uint8_t sdaPin;
uint8_t sclPin;
uint8_t _sdaPin;
uint8_t _sclPin;
};


Expand Down
22 changes: 21 additions & 1 deletion src/sensorinterface/MCP23X17PinInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,26 @@
#include <PinInterface.h>
#include <Adafruit_MCP23X17.h>

#define MCP_GPA0 0
#define MCP_GPA1 1
#define MCP_GPA2 2
#define MCP_GPA3 3
#define MCP_GPA4 4
#define MCP_GPA5 5
#define MCP_GPA6 6
#define MCP_GPA7 7
#define MCP_GPB0 8
#define MCP_GPB1 9
#define MCP_GPB2 10
#define MCP_GPB3 11
#define MCP_GPB4 12
#define MCP_GPB5 13
#define MCP_GPB6 14
#define MCP_GPB7 15

/**
* Pin interface to use MCP23008/17 I2C GPIO port extenders
*/
class MCP23X17PinInterface: public PinInterface
{

Expand All @@ -42,4 +62,4 @@ class MCP23X17PinInterface: public PinInterface
uint8_t _pinNum;
};

#endif // _H_MCP23X17PinInterface_
#endif // _H_MCP23X17PinInterface_
7 changes: 7 additions & 0 deletions src/sensors/SensorManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
#include "softfusion/drivers/mpu6050.h"

#include "softfusion/i2cimpl.h"
#include "sensorinterface/MCP23X17PinInterface.h"
#include "sensorinterface/I2CPCAInterface.h"

namespace SlimeVR
{
Expand All @@ -53,15 +55,20 @@ namespace SlimeVR
using SoftFusionLSM6DSR = SoftFusionSensor<SoftFusion::Drivers::LSM6DSR, SoftFusion::I2CImpl>;
using SoftFusionMPU6050 = SoftFusionSensor<SoftFusion::Drivers::MPU6050, SoftFusion::I2CImpl>;

Adafruit_MCP23X17 mcp;

void SensorManager::setup()
{

uint8_t sensorID = 0;
uint8_t activeSensorCount = 0;
mcp.begin_I2C();

#define NO_PIN nullptr
#define DIRECT_PIN(pin) std::make_shared<DirectPinInterface>(pin)
#define DIRECT_WIRE(scl, sda) std::make_shared<I2CWireSensorInterface>(sda, scl)
#define MCP_PIN(pin) std::make_shared<MCP23X17PinInterface>(&mcp, pin)
#define PCA_WIRE(scl, sda, addr, ch) std::make_shared<I2CPCASensorInterface>(scl, sda, addr, ch)

#define IMU_DESC_ENTRY(ImuType, ...) \
{ \
Expand Down

0 comments on commit 76b1aaa

Please sign in to comment.