I set this up to test my basic code, but I'm not sure if I have a coding problem, or a hardware issue. When I run this on my Mega2560, the display scrolls showing "angle 1" and "angle 2" but the reading are identical, and never change. I'm unsure if my readings are identical because the code is reading the same sensor (TCA9548A reading channel 1 for both, instead of 1 and 2) or if the code is correct, is my wiring faulty (very possible).
Wanting to askw if my code looks right.
#include <Wire.h>
#include <AS5600.h>
#define TCAADDR 0x70
int Actang1;
int Actang2;
int Actang3;
int Actang4;
int Actang5;
int Actang6;
int a1;
int a2;
AS5600 as5600;
void TCA9548A(uint8_t bus)
{
Wire.beginTransmission(0x70);
Wire.write(1 <<bus);
Wire.endTransmission();
}
void setup() {
Serial.begin(9600);
//Wire.begin(TCAADDR);
}
void loop() {
TCA9548A(1);
float a1 = as5600.readAngle();
Serial.print("Angle 1,");
Serial.println(a1);
TCA9548A(2);
float a2 = as5600.readAngle();
Serial.print("Angle 2,");
Serial.println(a2);
delay(300);
}
I can run an example sketch that I found on Github. However, it is only a simple read the sensor, and does not include anything about the multiplexer. All the multiplexer examples I can find are all output to things like 2 LCD screens. I ran the scan code from Adafruit and it shows the 2 sensors on ports 1 and 2. I guess that means my wiring is ok. So I'm left with my multiplexer code being faulty, which doesn't surprise me. lol Any ideas on what I should look at? The readings are always 3839.00
//
// FILE: AS5600_demo.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo
// DATE: 2022-05-28
#include "AS5600.h"
#include "Wire.h"
AS5600 as5600; // use default Wire
void setup()
{
Serial.begin(115200);
Serial.println(__FILE__);
Serial.print("AS5600_LIB_VERSION: ");
Serial.println(AS5600_LIB_VERSION);
Wire.begin();
as5600.begin(4); // set direction pin.
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
}
void loop()
{
Serial.print(millis());
Serial.print("\t");
Serial.print(as5600.readAngle());
Serial.print("\t");
Serial.println(as5600.rawAngle() * AS5600_RAW_TO_DEGREES);
delay(1000);
}
// -- END OF FILE --
There are thousands of multiplexers which one are you using. Also post a schematic so we can determine how the system is configured and what else is there. Posting links to "Technical" information on the hardware would be a big help.
Ok, here is the current wiring, and components. All grounds are connected. The TCA9548A Multiplexer is a Chinese brand bought from Amazon. Here is a link to the best info I can find on the AS5600 sensor. AS5600 Sensor Data
So how would you expect a multiplexer to work?
A multiplexer needs pins to be wired up that select what channel your multiplexer is transferring to its output.
So those wires must be included in your circuit along with code to change those pins to the required values to select what you want to read.
Hi,
I had at one stage 2 I2C devices with the same address and multiplexed them.
The trick is to do the initialization, in your case with two sensors, TWICE.
Each time with one of the sensors selected in the multiplexer.
I basically ran the setup of the I2C components twice and switch I2C comms for each device.
Then you can command a read from either with the appropriate sensor selected.
Now conspicuously absent (!) from @MrDoggss' first sketch are those two lines we see in the simpler example
as5600.begin(4); // set direction pin.
as5600.setDirection(AS5600_CLOCK_WISE); // default, just be explicit.
which need to be done for each sensor. However that is done through the I2C multiplexer. I take @TomGeorge's experience for that - select, begin and setDirection for every I2C device.
Once with the first sensor selected, then again with the second selected.
This is to wakeup the sensors for comms.
I added these lines for each sensor. It works! I get a good reading from each one now. Here is my current code. Thank you TomGeorge and Alto777 for the help. Now to the next step, programming the AS5600. I think...
#include <Wire.h>
#include <AS5600.h>
#define TCAADDR 0x70
int Actang1;
int Actang2;
int Actang3;
int Actang4;
int Actang5;
int Actang6;
int a1;
int a2;
AS5600 as5600;
void TCA9548A(uint8_t bus)
{
Wire.beginTransmission(0x70);
Wire.write(1 <<bus);
Wire.endTransmission();
}
void setup() {
Serial.begin(9600);
}
void loop() {
TCA9548A(1);
as5600.begin();
as5600.setDirection(AS5600_CLOCK_WISE);
float a1 = as5600.readAngle();
Serial.print("Angle 1,");
Serial.println(a1);
TCA9548A(2);
as5600.begin();
as5600.setDirection(AS5600_CLOCK_WISE);
float a2 = as5600.readAngle();
Serial.print("Angle 2,");
Serial.println(a2);
delay(300);
}
I am sure enough to ask you to try placing those lines, and the ones that do the other sensor setup into your setup() function.
You'll still need just the
TCA9548A(1);
to set the multiplexer later in you loop(), or wherever, but the initial stuff usually wants to be done just once.
TCA9548A(2); // select unit 2
float a2 = as5600.readAngle();
I do not know how quickly the mux catches up with a change of address. My instinct is that it is without any need to delay in any way after selected a new I2C device to talk with.
I managed to do it, and here's a working code for people with the same problem that end up in this thread.
// include as5600 and wire libraries
#include <Wire.h>
#include <AS5600.h>
// Define three as5600 objects as X, Y and Z for further use
AS5600 stpA;
AS5600 stpB;
AS5600 stpC;
int I2CA=2;
int I2CB=3;
int I2CC=1;
float radA=0;
float radB=0;
float radC=0;
float newradA;
float newradB;
float newradC;
float initA;
float initB;
float initC;
float dradA=0,dradB=0,dradC=0;
float drevA=0,drevB=0,drevC=0;
float X=0,Y=0,Z=0;
// assign constants values
float pitch = 8 / (2*M_PI); // mm/radian of stepper motor
float radius = 12.73 / 2; //3D printer A and B stepper polley radius
void setup()
{
// Start serial communication
Serial.print("setup initializing");
Serial.begin(115200);
while (!Serial)
{
// wait for serial port to connect. Needed for native USB port only
}
Wire.begin();
// Set up and check if X is connected
Serial.println("X setup initializing");
TCA9548(I2CA);
stpA.begin(4);
stpA.setDirection(AS5600_CLOCK_WISE);
int b = stpA.isConnected();
Serial.print("Connect: ");
Serial.println(b);
Serial.println("X setup done");
initA=stpA.getCumulativePosition()*AS5600_RAW_TO_RADIANS;
radA=0;
delay(20);
// Set up and check if Y is connected
TCA9548(I2CB);
stpB.begin(4);
stpB.setDirection(AS5600_CLOCK_WISE);
int c = stpB.isConnected();
Serial.print("Connect: ");
Serial.println(c);
initB=stpB.getCumulativePosition()*AS5600_RAW_TO_RADIANS;
radB=0;
delay(20);
// Set up and check if Z is connected
TCA9548(I2CC);
stpC.begin(4);
stpC.setDirection(AS5600_CLOCK_WISE);
int d = stpC.isConnected();
Serial.print("Connect: ");
Serial.println(d);
initC=stpC.getCumulativePosition()*AS5600_RAW_TO_RADIANS;
radC=0;
delay(20);
X = 0;
Y = 0;
Z = 0;
delay(5000);
Serial.println("setup done");
}
void loop()
{
static uint32_t lastTime = 0;
if (millis() - lastTime >= 5)
{
TCA9548(I2CA);
newradA = stpA.getCumulativePosition()*AS5600_RAW_TO_RADIANS-initA;
dradA=newradA-radA;
radA=newradA;
TCA9548(I2CB);
newradB=stpB.getCumulativePosition()*AS5600_RAW_TO_RADIANS-initB;
dradB=newradB-radB;
radB=newradB;
TCA9548(I2CC);
newradC=stpC.getCumulativePosition()*AS5600_RAW_TO_RADIANS-initC;
dradC = newradC-radC;
radC=newradC;
X = X + (dradA + dradB) * radius / 2; //specific kinematic equations for corexy 3dprinter
Y = Y + (dradA - dradB) * radius / 2;
Z = Z + dradC * pitch;
//Serial.print("X: ");
Serial.print(X, 3);
Serial.print(" , ");
// Serial.print(radA);
//Serial.print(",Y: ");
Serial.print(Y, 3);
Serial.print(" , ");
//Serial.print(radB);
//Serial.print(",Z: ");
Serial.println(Z, 3);
// Serial.print(" : ");
// Serial.println(radC);
}
}
void TCA9548(int bus)
{
Wire.beginTransmission(0x70);
Wire.write(1 << bus);
Wire.endTransmission();
}