Hey, I have run into a programming question, if someone might be able to help me. I'm trying to work with an Adafruit TCA9548A multiplexer, but haven't yet been able to control / or read a motor / sensor connected to it.
I am trying to send messages to a DRV2605 haptic motor driver. The attached code works where I connect the haptic driver directly to the Lolin ESP32 module I'm using - I am sending 1 / 0s over serial from a music software programme to trigger the pre-programmed waveforms on the LRA motor attached to the haptic driver.
I don't think it's a hardware issue - I have run a scanner sketch on the I2C device and the microcontroller recognises a multiplexer at the 0X70 address. So, it's more likely that there is an error in my code.
Would greatly appreciate any feedback on where I may be going wrong
The OP may want to go to the Github Adafruit site for the AdaFruit library that is being used. There the OP can read about recent issues with the library and see if they apply to the OP.
OP as the TCA9548A operating voltage is between 1.8 and 5V, would you happen to be running the TCA9548A at 5V and the O/P lines of the TCA9548A are directly connected to the ESP32? I ask because the ESP32 is NOT 5V tolerant.
After zooming the image, I see 3.3V is being used.
And you may need pull up resistors on the SCL/SDA lines.
Hi, sorry I added the code as an attachment... here it is..
#include <Wire.h>
#include <drv2605.h>
#define TCAADDR 0x70
DRV2605 haptic;
int incomingByte = 0; // for incoming serial data
void tcaselect(uint8_t i2c_bus) {
if (i2c_bus > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i2c_bus);
Wire.endTransmission();
}
void setup() {
Serial.begin(115200); // opens serial port, sets data rate
if (haptic.init(false, true) != 0) Serial.println("init failed!");
if (haptic.drv2605_AutoCal() != 0) Serial.println("auto calibration failed!");
delay(2000);
}
// Initialize the displays
void hapticInit(){
for (int i = 0; i < 7; i++) {
tcaselect(i); // Loop through each connected displays on the I2C buses
haptic.drv2605_Play_Waveform(4);
}
}
void loop()
{
tcaselect(0);
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
if(incomingByte == 0) {
haptic.drv2605_Play_Waveform(1); // play xx
//haptic.goWait();
}
else{
if(incomingByte == 1) {
haptic.drv2605_Play_Waveform(4); // play xx
// haptic.goWait();
}
}
}
}
The TCA Multiplexer breakout board is connected to 3.3V, Ground, SCL and SDA on the microcontroller. I use a 3.3V supply because that is the operating voltage of the Lolin D32 board and adafruit recommend connecting the multiplexer at the power supply of the controller. The DRV2605 haptic driver board is then connected to the SC0/SD0 pins on the multiplexer.
I asked the adafruit customer support forum about resistors for the circuit for a setup of 8 haptic driver / LRA pairs with their multiplexer (Multiple DRV2605 project - adafruit industries). I will be independently powering the LRAs, but for now I'm using the microcontroller's power with just have the one haptic driver / LRA pair setup while I'm working on the coding. I am using a 2ohm 2 watt resistor and I have this connected in-between the DRV2605 driver and the LRA attached to it.
In terms of testing - if I connect the haptic driver / LRA setup directly to the D32 controller, it works fine. It is only when I add the multiplexer as an intermediary that I am encountering a problem. I have also run some basic setup tests on the multiplexer and the controller is able to detect an I2C device attached to the D32 at the 0x70 address.
An Adafruit Metro, as pictured in post #5 is not a Lolin ESP32 module. Which only serves to confuse the issue and is a step backwards in trying to solve your issue.
Hi,
Can I suggest you;
Get a pen(cil).
Get a piece of paper.
And DRAW your circuit.
Include pin labels and component names.
Then post a picture of your circuit.
You are in troubleshooting mode and need to produce a diagram that will help us all.
Picture of your project does help, but actual connections are hard ti see and comprehend.
Thanks PaulRB - I don't receive either of the error messages, but I was wondering about that too. I tried the following modification to the code, interestingly the "I received: 1" etc is now printing to the serial monitor in-line with the messages I am sending over serial from the music software programme. However, the LRA motor is still not activating.
#include <Wire.h>
#include <drv2605.h>
#define TCAADDR 0x70
DRV2605 haptic;
int incomingByte = 0; // for incoming serial data
void tcaselect(uint8_t i2c_bus) {
if (i2c_bus > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i2c_bus);
Wire.endTransmission();
}
// Initialize the displays
void hapticInit(){
for (int i = 0; i < 7; i++) {
tcaselect(i); // Loop through each connected displays on the I2C buses
if (haptic.init(false, true) != 0) Serial.println("init failed!");
if (haptic.drv2605_AutoCal() != 0) Serial.println("auto calibration failed!");
delay(2000);
}
}
void setup() {
Serial.begin(115200); // opens serial port, sets data rate
}
void loop()
{
tcaselect(0);
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
if(incomingByte == 0) {
haptic.drv2605_Play_Waveform(1); // play xx
//haptic.goWait();
}
else{
if(incomingByte == 1) {
haptic.drv2605_Play_Waveform(4); // play xx
// haptic.goWait();
}
}
}
}
When I first upload a new code to the D32 with the DRV haptic driver and LRA attached directly to the microcontroller the LRA buzzes when the code is done uploading, but when I have it attached to the multiplexer it does not.
(yes not trying to be unfriendly with my breadboard! - just keeping space for the extra haptic drivers I'll be adding and not sure on the layout yet.)
Hi Tom, I don't no. I had assumed that the adafruit multiplexer breakout would have pull-ups integrated, but I've gone through their data sheets and I can't find confirmation that they are built in. It's odd though, that the tutorial diagram doesn't show any resistors being used. But perhaps you are right.
Paul RB, ah ok, thanks I added the hapticInit function to the void setup.
I did go through the resistors / circuit in some detail with adafruit, and the wiring is standard, so I suspect the issue is with the code. I pieced it together from examples off the internet and some existing code I had for triggering the DRV waveforms. But, perhaps, I'm missing something?
Currently you have one haptic driver attached to channel 0 of the multiplexer?
I think Adafruit made a special version of the i2c scanner sketch which scans all the channels of a multiplexer and detects all devices attached to each channel. Does that pick up your haptic driver? The standard i2c scanner sketch will only detect the multiplexer itself.
If not, you may have a hardware problem. If it does detect the haptic driver, maybe try changing your code so it does not loop round all 8 multiplexer channels, just limit it to using channel 0 only ( i < 1 in the for loops).
oh yes, you are right, thanks I checked the Adafruit scanner and it does recognise the haptic driver at "TCA Port #0 Found I2C 0x5A" so at least that confirms its not a hardware issue.
It must be my code. I'll keep looking into other examples to see if I can figure out what I'm missing. Ideally I'd like to preserve the cycling through functions because I will be adding other haptic drivers to the setup.
What I'm thinking is that it the code might be failing because it is trying to access 7 haptic drivers that are not there. If you limit the for-loop in hapticInit() to just the one that exists, does that work?
oh of course, yes I see thanks. I've got a bit further with the code, making some edits - I tested it with and without cycling through the haptic drivers and got the same result. Now, when I upload the code the LRA buzzes when the code is uploaded when it is connected via the multiplexer. Also, if I load the code when the DRV / LRA is directly connected to the D32 controller, and then switch over the connection to the multiplexer, when I send serial bytes to the controller the waveforms play through the LRA.
(New code - full)
#include <Wire.h>
#include <drv2605.h>
#define TCAADDR 0x70
DRV2605 haptic0;
DRV2605 haptic1;
DRV2605 haptic2;
DRV2605 haptic3;
DRV2605 haptic4;
DRV2605 haptic5;
DRV2605 haptic6;
DRV2605 haptic7;
int incomingByte = 0; // for incoming serial data
void useLRA();
void tcaselect(uint8_t i) {
if (i > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}
void setup() {
while (!Serial);
delay(1000);
Wire.begin();
Serial.begin(115200); // opens serial port, sets data rate
hapticInit(); // Initialize the motors
}
void hapticInit(){
for (uint8_t t=0; t<8; t++) {
tcaselect(t); // Loop through each connected displays on the I2C buses
//tcaselect(0);
if (haptic0.init(false, true) != 0) Serial.println("init failed!");
if (haptic0.drv2605_AutoCal() != 0) Serial.println("auto calibration failed!");
delay(2000);
}
}
void loop() {
tcaselect(0);
// send data only when you receive data:
if (Serial.available() > 0) {
// read the incoming byte:
incomingByte = Serial.read();
// say what you got:
Serial.print("I received: ");
Serial.println(incomingByte, DEC);
if(incomingByte == 0) {
haptic0.drv2605_Play_Waveform(1); // play Strong Click 1 - 100%
//haptic.goWait();
}
else{
if(incomingByte == 1) {
haptic0.drv2605_Play_Waveform(4); // play Pulsing Medium 1 – 60%
// haptic.goWait();
}
}
}
}
What's not yet working though, is if I try to upload the code with the DRV / LRV connected via the multiplexer. The message in the console says that initialisation failed, (although it also says this when the DRV / LRA is directly connected to the controller and then works ok), which suggests it's to do with this part of the code..
(New code - exert)
void setup() {
while (!Serial);
delay(1000);
Wire.begin();
Serial.begin(115200); // opens serial port, sets data rate
hapticInit(); // Initialize the motors
}
void hapticInit(){
for (uint8_t t=0; t<8; t++) {
tcaselect(t); // Loop through each connected displays on the I2C buses
//tcaselect(0);
if (haptic0.init(false, true) != 0) Serial.println("init failed!");
if (haptic0.drv2605_AutoCal() != 0) Serial.println("auto calibration failed!");
delay(2000);
}
}