Read from multiple sensors
Closed this issue · 13 comments
I would like to know if it is possible to modify somehow the library in order to let Arduino UNO reads from three Adafruit_AS7341 sensors. I see that it reads from I2C, but I think the address 0x39 is the same for all the sensors.
Not seeing a way to set any alternate address for the AS7341:
despite this library having the address as a parameter to begin()
.
Using a TCA muxer is probably the easiest way to use three AS7341's.
https://learn.adafruit.com/working-with-i2c-devices/address-conflicts
Thank you a lot for your super fast reply!
I checked the link you suggested and I think that TCA9548A I2C Multiplexer should help the integration of three sensors.
The only problem is: how should I integrate this multiplexer with Adafruit_AS7341 library?
there's a guide for our breakout here
https://learn.adafruit.com/adafruit-tca9548a-1-to-8-i2c-multiplexer-breakout
Should I call three times the begin() function and pass it the I2C address from the TCA9548A Multiplexer?
@ladyada Can you please respond I do not believe this issue is closed as @robodyne-robotics is experiencing issues with the documentation you provided, as am I.
The guide linked has an example showing how to use two HMC5883 breakouts. It shows how to call begin()
on each instance. It also provides a simple helper function for switching TCA channels.
https://learn.adafruit.com/adafruit-tca9548a-1-to-8-i2c-multiplexer-breakout/wiring-and-test
You just need to adapt that to the AS7341 and expand to how ever many AS7341's are in use.
Thank you for your quick response, so I am having issues with adapting the begin call where I pass in the sensor_id like so:
Adafruit_AS7341 sensor1 = Adafruit_AS7341.begin(sensor_id = 1);
This yields 2 errors:
- Adafruit_AS7341 (that I call .begin on) error is: type name is not allowed
- sensor_id error is: identifier "sensor_id" is undefined
Could it be that for issue 1 I simply I have to instantiate the sensor differently?
And for issue 2 am I just blundering passing in a named argument (as the begin function for my sensor has many arguments)?
There are multiple things wrong there. You don't want to call begin()
at the same time as making the assignment. First make the instance:
Adafruit_AS7341 as7341;
and then later call begin()
:
as7341.begin()
See library examples for reference.
Also, C++ does not support named arguments, so this syntax is not valid:
Adafruit_AS7341.begin(sensor_id = 1);
The begin()
interface in this library is a bit klunky. It only has the one signature:
bool begin(uint8_t i2c_addr = AS7341_I2CADDR_DEFAULT, TwoWire *wire = &Wire,
int32_t sensor_id = 0);
So you will need to explicitly specify the first two parameters, even if using defaults:
//
// code to switch TCA channel to sensor1
//
sensor1.begin(AS7341_I2CADDR_DEFAULT, &Wire, 1);
//
// code to switch TCA channel to sensor2
//
sensor2.begin(AS7341_I2CADDR_DEFAULT, &Wire, 2);
However, the sensor_id
does not actually get used. So you can probably get away with:
//
// code to switch TCA channel to sensor1
//
sensor1.begin();
//
// code to switch TCA channel to sensor2
//
sensor2.begin();
@caternuson Thank you very much for the detailed response and explanations. This got me off the ground, much appreciated.
I tried to read two AS7341 sensors with the multiplexer in this way:
#include <Adafruit_AS7341.h>
#include "Wire.h"
#define TCAADDR 0x70
void tcaselect(uint8_t i) {
if (i > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}
Adafruit_AS7341 as7341_0;
Adafruit_AS7341 as7341_1;
void setup() {
Serial.begin(115200);
// Wait for communication with the host computer serial monitor
while (!Serial) {
delay(1);
}
tcaselect(1);
if (!as7341_0.begin(AS7341_I2CADDR_DEFAULT, &Wire, 1)){
Serial.println("Could not find AS7341");
while (1) { delay(10); }
}
as7341_0.setATIME(100);
as7341_0.setASTEP(999);
as7341_0.setGain(AS7341_GAIN_256X);
}
void loop() {
// Read all channels at the same time and store in as7341 object
if (!as7341_0.readAllChannels()){
Serial.println("Error reading all channels!");
return;
}
// Print out the stored values for each channel
Serial.print("F1 415nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_415nm_F1));
Serial.print("F2 445nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_445nm_F2));
Serial.print("F3 480nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_480nm_F3));
Serial.print("F4 515nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_515nm_F4));
Serial.print("F5 555nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_555nm_F5));
Serial.print("F6 590nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_590nm_F6));
Serial.print("F7 630nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_630nm_F7));
Serial.print("F8 680nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_680nm_F8));
Serial.print("Clear : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_CLEAR));
Serial.print("Near IR : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_NIR));
Serial.println("");
}
But I always get: Could not find AS7341
I'm correctly able to see that there are two sensors attached to the multiplexer:
TCAScanner ready!
TCA Port #0
Found I2C 0x39
TCA Port #1
Found I2C 0x39
TCA Port #2
TCA Port #3
TCA Port #4
TCA Port #5
TCA Port #6
TCA Port #7
done
At the moment, I'm just trying to read the first sensor, but it seems that something is wrong.
You need to call Wire.begin()
before calling tcaselect
.
Wire.begin();
tcaselect(1);
It only needs to be called once.
Also note how that is done in the example scanner sketch.
https://learn.adafruit.com/adafruit-tca9548a-1-to-8-i2c-multiplexer-breakout/wiring-and-test
Thank you a lot!
I'm able to read from two or three sensors by using a single Arduino MEGA board and the multiplexer.
However, when I try to add ROS library with rosserial, the code compiles correctly, but then I cannot read the published topics since it goes out of synchronization.
Usually, when this happens, it's because the code takes too much time to run and in fact I noticed that the function that reads from each sensor is really slow.
Is there a way to speed up the reading process, please?
This is my code used to read from two sensors and print to the serial console without using ROS:
`/* This example will read all channels from the AS7341 and print out reported values */
#include <Adafruit_AS7341.h>
#include "Wire.h"
#include <ros.h>
#include <std_msgs/String.h>
#define TCAADDR 0x70
ros::NodeHandle nh;
std_msgs::String str_msg;
ros::Publisher spettrometro_centrale("spettrometro_centrale", &str_msg);
ros::Publisher spettrometro_sinistro("spettrometro_sinistro", &str_msg);
ros::Publisher spettrometro_destro("spettrometro_destro", &str_msg);
unsigned int len;
void tcaselect(uint8_t i) {
if (i > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}
Adafruit_AS7341 as7341_0;
Adafruit_AS7341 as7341_1;
Adafruit_AS7341 as7341_2;
void setup() {
Serial.begin(115200);
Wire.begin();
// Wait for communication with the host computer serial monitor
tcaselect(0);
if (!as7341_0.begin()){
//Serial.println("Could not find AS7341 - LEFT");
}
tcaselect(0);
as7341_0.setATIME(100);
as7341_0.setASTEP(999);
as7341_0.setGain(AS7341_GAIN_256X);
tcaselect(1);
if (!as7341_1.begin()){
//Serial.println("Could not find AS7341 - CENTER");
}
as7341_1.setATIME(100);
as7341_1.setASTEP(999);
as7341_1.setGain(AS7341_GAIN_256X);
tcaselect(2);
if (!as7341_2.begin()){
//Serial.println("Could not find AS7341 - RIGHT");
}
as7341_2.setATIME(100);
as7341_2.setASTEP(999);
as7341_2.setGain(AS7341_GAIN_256X);
}
void loop() {
// Read all channels at the same time and store in as7341 object
String sinistro;
String centrale;
String destro;
int num1 = random(150, 300);
int num2 = random(150, 300);
int num3 = random(150, 300);
int num4 = random(150, 300);
int num5 = random(150, 300);
int num6 = random(150, 300);
int num7 = random(150, 300);
int num8 = random(150, 300);
tcaselect(0);
if (!as7341_0.readAllChannels()){
//Serial.println("Error reading all channels for LEFT!");
return;
}
Serial.println("Sensor 0");
// Print out the stored values for each channel
Serial.print("F1 410nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_415nm_F1));
Serial.print("F2 435nm : ");
int f2 = as7341_0.getChannel(AS7341_CHANNEL_415nm_F1) + num1;
Serial.println(f2);
Serial.print("F3 445nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_445nm_F2));
Serial.print("F4 460nm : ");
int f3 = as7341_0.getChannel(AS7341_CHANNEL_445nm_F2) + num2;
Serial.println(f3);
Serial.print("F5 480nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_480nm_F3));
Serial.print("F6 515nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_515nm_F4));
Serial.print("F7 535nm : ");
int f4 = as7341_0.getChannel(AS7341_CHANNEL_515nm_F4) + num3;
Serial.println(f4);
Serial.print("F8 555nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_555nm_F5));
Serial.print("F9 590nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_590nm_F6));
Serial.print("F10 610nm : ");
int f5 = as7341_0.getChannel(AS7341_CHANNEL_590nm_F6) + num4;
Serial.println(f5);
Serial.print("F11 630nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_630nm_F7));
Serial.print("F12 645nm : ");
int f6 = as7341_0.getChannel(AS7341_CHANNEL_630nm_F7) + num5;
Serial.println(f6);
Serial.print("F13 680nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_680nm_F8));
Serial.print("F14 715nm : ");
int f7 = as7341_0.getChannel(AS7341_CHANNEL_680nm_F8) + num6;
Serial.println(f7);
Serial.print("F15 730nm : ");
int f8 = as7341_0.getChannel(AS7341_CHANNEL_680nm_F8) + num7;
Serial.println(f8);
Serial.print("F16 780nm : ");
Serial.println(as7341_0.getChannel(AS7341_CHANNEL_NIR));
Serial.print("F17 860nm : ");
int f9 = as7341_0.getChannel(AS7341_CHANNEL_CLEAR) - num2;
Serial.println(abs(f9));
Serial.print("F18 940nm : ");
int f10 = as7341_0.getChannel(AS7341_CHANNEL_CLEAR) + num3;
Serial.println(abs(f10));
Serial.println("");
tcaselect(1);
if (!as7341_1.readAllChannels()){
Serial.println("Error reading all channels for CENTER!");
return;
}
Serial.println("Sensor 1");
// Print out the stored values for each channel
Serial.print("F1 410nm : ");
Serial.println(as7341_1.getChannel(AS7341_CHANNEL_415nm_F1));
Serial.print("F2 435nm : ");
int f2_1 = as7341_1.getChannel(AS7341_CHANNEL_415nm_F1) + num1;
Serial.println(f2_1);
Serial.print("F3 445nm : ");
Serial.println(as7341_1.getChannel(AS7341_CHANNEL_445nm_F2));
Serial.print("F4 460nm : ");
int f3_1 = as7341_1.getChannel(AS7341_CHANNEL_445nm_F2) + num2;
Serial.println(f3_1);
Serial.print("F5 480nm : ");
Serial.println(as7341_1.getChannel(AS7341_CHANNEL_480nm_F3));
Serial.print("F6 515nm : ");
Serial.println(as7341_1.getChannel(AS7341_CHANNEL_515nm_F4));
Serial.print("F7 535nm : ");
int f4_1 = as7341_1.getChannel(AS7341_CHANNEL_515nm_F4) + num3;
Serial.println(f4_1);
Serial.print("F8 555nm : ");
Serial.println(as7341_1.getChannel(AS7341_CHANNEL_555nm_F5));
Serial.print("F9 590nm : ");
Serial.println(as7341_1.getChannel(AS7341_CHANNEL_590nm_F6));
Serial.print("F10 610nm : ");
int f5_1 = as7341_1.getChannel(AS7341_CHANNEL_590nm_F6) + num4;
Serial.println(f5_1);
Serial.print("F11 630nm : ");
Serial.println(as7341_1.getChannel(AS7341_CHANNEL_630nm_F7));
Serial.print("F12 645nm : ");
int f6_1 = as7341_1.getChannel(AS7341_CHANNEL_630nm_F7) + num5;
Serial.println(f6_1);
Serial.print("F13 680nm : ");
Serial.println(as7341_1.getChannel(AS7341_CHANNEL_680nm_F8));
Serial.print("F14 715nm : ");
int f7_1 = as7341_1.getChannel(AS7341_CHANNEL_680nm_F8) + num6;
Serial.println(f7_1);
Serial.print("F15 730nm : ");
int f8_1 = as7341_1.getChannel(AS7341_CHANNEL_680nm_F8) + num7;
Serial.println(f8_1);
Serial.print("F16 780nm : ");
Serial.println(as7341_1.getChannel(AS7341_CHANNEL_NIR));
Serial.print("F17 860nm : ");
int f9_1 = as7341_1.getChannel(AS7341_CHANNEL_CLEAR) - num3;
Serial.println(abs(f9_1));
Serial.print("F18 940nm : ");
int f10_1 = as7341_1.getChannel(AS7341_CHANNEL_CLEAR) + num2;
Serial.println(abs(f10_1));
Serial.println("");
tcaselect(2);
if (!as7341_2.readAllChannels()){
//Serial.println("Error reading all channels for RIGHT!");
return;
}
//Serial.println("Sensor 2");
// Print out the stored values for each channel
//Serial.print("F1 410nm : ");
//Serial.println(as7341_2.getChannel(AS7341_CHANNEL_415nm_F1));
//Serial.print("F2 435nm : ");
int f2_2 = as7341_2.getChannel(AS7341_CHANNEL_415nm_F1) + num1;
//Serial.println(f2_2);
//Serial.print("F3 445nm : ");
//Serial.println(as7341_2.getChannel(AS7341_CHANNEL_445nm_F2));
//Serial.print("F4 460nm : ");
int f3_2 = as7341_2.getChannel(AS7341_CHANNEL_445nm_F2) + num2;
//Serial.println(f3_2);
//Serial.print("F5 480nm : ");
//Serial.println(as7341_2.getChannel(AS7341_CHANNEL_480nm_F3));
//Serial.print("F6 515nm : ");
//Serial.println(as7341_2.getChannel(AS7341_CHANNEL_515nm_F4));
//Serial.print("F7 535nm : ");
int f4_2 = as7341_2.getChannel(AS7341_CHANNEL_515nm_F4) + num3;
//Serial.println(f4_2);
//Serial.print("F8 555nm : ");
//Serial.println(as7341_2.getChannel(AS7341_CHANNEL_555nm_F5));
//Serial.print("F9 590nm : ");
//Serial.println(as7341_2.getChannel(AS7341_CHANNEL_590nm_F6));
//Serial.print("F10 610nm : ");
int f5_2 = as7341_2.getChannel(AS7341_CHANNEL_590nm_F6) + num4;
//Serial.println(f5_2);
//Serial.print("F11 630nm : ");
//Serial.println(as7341_2.getChannel(AS7341_CHANNEL_630nm_F7));
//Serial.print("F12 645nm : ");
int f6_2 = as7341_2.getChannel(AS7341_CHANNEL_630nm_F7) + num5;
//Serial.println(f6_2);
//Serial.print("F13 680nm : ");
//Serial.println(as7341_2.getChannel(AS7341_CHANNEL_680nm_F8));
//Serial.print("F14 715nm : ");
int f7_2 = as7341_2.getChannel(AS7341_CHANNEL_680nm_F8) + num6;
//Serial.println(f7_2);
//Serial.print("F15 730nm : ");
int f8_2 = as7341_2.getChannel(AS7341_CHANNEL_680nm_F8) + num7;
//Serial.println(f8_2);
//Serial.print("F16 780nm : ");
//Serial.println(as7341_2.getChannel(AS7341_CHANNEL_NIR));
//Serial.print("F17 860nm : ");
int f9_2 = as7341_2.getChannel(AS7341_CHANNEL_CLEAR) - num3;
//Serial.println(abs(f9_2));
//Serial.print("F18 940nm : ");
int f10_2 = as7341_2.getChannel(AS7341_CHANNEL_CLEAR) + num2;
//Serial.println(abs(f10_2));
//Serial.println("");
}`