Hello,
I was wondering if anyone could help me or provide feedback on how to read two values of sensors that have totally opposite timing. One reading is coming from a DC motor, and another is coming from sprockets attached to the DC motor. The goal is to have both data at the same time.
I want to know how I can read the values coming from the AS5600 sensor and OPTO sensors simultaneously that does not affect any of the sensors; in this case, my AS5600 sensor reads data every 10th of a millisecond and the OPB745WZ sensor reads data every 1000 millisecond which is mounted on top of the 16 tooth sprocket. If I try to match the AS5600 sensor reading with OPTO sensor I will experience the Nyquist effect for the RPM of the dc motors at higher rpm where this dc motor is very effective by the voltage of batteries so the rpm of the dc motor will be at the higher pick of the 3000 rpm at 37 volts and can reach to the 800 rpm at 35.9 volts this relation can affect the gearbox that has two sets of the sprocket that are connected by a chain. So I would love to see both effects at the same time. Where later on, I can add my sensor on batties as well to get the reading of all three at the same time; I will attach my code here later on, I will be reading data through the IOT cloud arduino after figuring out the timing
//#define IR_LED_PIN 9 // Pin connected to the LED anode of QRB1114 (via 470Ω resistor)
//#include <WiFiNINA.h>
#include <Wire.h>
#include "AS5600.h"
// #include <rtc_clock.h>
//#include <TimeLib.h>
#define SENSOR_PIN1 A1 // Analog pin connected to the collector of the phototransistor (via 10kΩ pull-up resistor)
#define SENSOR_PIN2 A2 // Analog pin connected to the collector of the phototransistor (via 10kΩ pull-up resistor)
const int threshold1 = 100; // Adjust based on calibration
volatile int toothCount1= 0; // Counter for the number of teeth detected
int numberOfTeeth1 = 16; // Replace with the actual number of teeth on your sprocket
bool tooth_detection1 = false;
const int threshold2 = 150; // Adjust based on calibration
volatile int toothCount2= 0; // Counter for the number of teeth detected
int numberOfTeeth2 = 16; // Replace with the actual number of teeth on your sprocket
bool tooth_detection2 = false;
unsigned long previousMillis_IR = 0; // Store the last time RPM was calculated
const int measurementInterval_IR = 1000;//1000; // Time interval for RPM measurement in milliseconds
#define TCAADDR 0x70 // I2C multiplexer address
AS5600L sensor1; // Motor 1
AS5600L sensor2; // Motor 2
int I2CA = 5; // Sensor 1 channel
int I2CB = 7; // Sensor 2 channel
// Timing and filtering
unsigned long lastTime_magnet = 0;
const unsigned long intervalmag = 10; // 100 ms for stable RPM
float filteredRPM1 = 0, filteredRPM2 = 0;
const float alpha = 0.05; // Smoothing factor
int lastAngle =0;
int cumulativePos2 = 0;
void TCA9548(int bus) {
if (bus < 0 || bus > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << bus);
Wire.endTransmission();
delay(1);
}
void setup() {
// pinMode(IR_LED_PIN, OUTPUT); // Set the LED pin as an output
// digitalWrite(IR_LED_PIN, HIGH); // Turn on the IR LED continuously
pinMode(SENSOR_PIN1, INPUT); // Set sensor pin as input
pinMode(SENSOR_PIN2, INPUT); // Set sensor pin as input
Serial.begin(115200); // Begin serial communication for monitoring
Wire.begin();
Wire.setClock(400000);
// --- Sensor_magnet 1 Setup ---
TCA9548(I2CA);
sensor1.begin(4);
sensor1.setDirection(AS5600_CLOCK_WISE); // Match physical rotation
sensor1.setAddress(0x36);
sensor1.setConfigure(0x1f00);
if (!sensor1.isConnected()) {
while(1);
// {
// // Serial.println("Sensor 1 not found!");
// // delay(1000);
// }
}
sensor1.resetCumulativePosition(); // Reset internal tracking
// --- Sensor_magnet 2 Setup ---
TCA9548(I2CB);
sensor2.begin(4);
sensor2.setDirection(AS5600_CLOCK_WISE);
sensor2.setAddress(0x36);
// sensor1.setConfigure(0x1f00);
if (!sensor2.isConnected()) {
// Serial.println("Sensor 2 not found!");
while(1);
}
sensor2.resetCumulativePosition();
lastAngle = sensor2.rawAngle();
lastTime_magnet = millis();
// Serial.println("Setup complete.");
// setTime(8, 21, 0, 25, 2, 2025); // set initial time to 12:00:00 on January 1, 2020
}
void loop() {
// Read the sensor value (analog)
int sensorValue1 = analogRead(SENSOR_PIN1);
int sensorValue2 = analogRead(SENSOR_PIN2);
unsigned long currentTime1 = millis();
if (currentTime1 - lastTime_magnet >= intervalmag) {
lastTime_magnet = currentTime1;
// float dt = (currentTime - lastTime) / 5000.0; // Convert to seconds
// --- Read Sensor 1 ---
TCA9548(I2CA);
long cp1 = sensor1.getCumulativePosition();
float rev1 = sensor1.getRevolutions(); // Uses library's overflow handling
float rpm1 = sensor1.getAngularSpeed(AS5600_MODE_RPM); // Built-in RPM
// --- Read Sensor 2 ---
TCA9548(I2CB);
//int currentAngle = sensor2.rawAngle();
long cp2 = sensor2.getCumulativePosition()* float(-1);
float rev2 = sensor2.getRevolutions()* float(-1);
float rpm2 = sensor2.getAngularSpeed(AS5600_MODE_RPM) * float(-1);
// Apply low-pass filter
filteredRPM1 = (alpha * rpm1 + (1 - alpha) * filteredRPM1);
filteredRPM2 = (alpha * rpm2 + (1 - alpha) * filteredRPM2);
// lastAngle = currentAngle;
// lastTime_magnet = currentTime; // Update time for next interval
// --- Output ---
// Serial.print("time run (min):,");
// Serial.print(minute()); // print current second
// Serial.print(",");
// Serial.print("Sensor 1 - Raw CP:,");
// Serial.print(cp1);
// Serial.print("|Revolutions1:|,");
// Serial.print(rev1);
// Serial.print("|RPM1_no_filter:|,");
Serial.print("|,|");
// Serial.print("Sensor 1 - Raw CP:,");
Serial.print(cp1);
Serial.print("|,|");
// // Serial.print("|Revolutions1:|,");
Serial.print(rev1);
// // Serial.print("|RPM1_no_filter:|,");
Serial.print("|,|");
Serial.print(rpm1);
Serial.print("|,|");
// Serial.print("|RPM1_filter:|,");
Serial.print(filteredRPM1);
Serial.print("|,|");
// Serial.print("|,");
// Serial.print("Sensor 2 - Raw CP:,");
Serial.print(cp2);
// // // Output: diff, cumulative revolutions, rev2, rpm22, filteredRPM2
// // Serial.print(",");
// // Serial.print("|Revolutions2:|");
// // // Serial.print(cumulativePos2 / 4096.0);
// // // Serial.print(",");
// // //Serial.print("3800, -3800,");
Serial.print("|,|");
Serial.print(rev2);
Serial.print("|,|");
// // Serial.print("|RPM2_no_filter:|");
Serial.print(rpm2);
Serial.print("|,|");
// // Serial.print("|RPM2_no_filter:|,");
Serial.println(filteredRPM2);
}
//// Check if the sensor detects a tooth
if (sensorValue > threshold) { // Adjust this threshold based on your testing
toothCount++;
delayMicroseconds(50); // Use a microsecond delay instead of delay(10)
//delay(10); // Debounce delay to avoid counting the same tooth multiple times
}
if ((!tooth_detection1) && (sensorValue1 > threshold1)){
tooth_detection1 = true;
toothCount1++;
//delay(10);
}
if ((tooth_detection1) && (sensorValue1 < (threshold1-30) )){
tooth_detection1 = false;
}
if ((!tooth_detection2) && (sensorValue2 > threshold2)){
tooth_detection2 = true;
toothCount2++;
// delay(10);
}
if ((tooth_detection2) && (sensorValue2 < (threshold2-50) )){
tooth_detection2 = false;
// delayMicroseconds(10);
}
// Check if it's time to calculate RPM
// unsigned long currentTime = millis(); //millis();
unsigned long currentTime = millis();
if (currentTime - previousMillis_IR >= 1000) {
// Calculate RPM
previousMillis_IR = currentTime;
float rpm11 = 5.5*(toothCount1 / (float)numberOfTeeth1) * (73.3);
float rpm22 = 1.7*(toothCount2 / (float)numberOfTeeth2) * (60.7);
Serial.print("time run (min) :,");
Serial.print(minute()); // print current second
// Serial.print("tooth_Count1,");
Serial.print(",");
Serial.print(toothCount1);
Serial.print("RPM1,");
Serial.print(",");
Serial.print(rpm11);
Serial.print("|,");
Serial.print("|tooth_Count2|,");
Serial.print(",");
Serial.print(toothCount2);
Serial.print("RPM2,");
Serial.print(",");
Serial.println(rpm22);
// // Reset the tooth count for the next measurement
toothCount1 = 0;
toothCount2 = 0;
}
}
would appreciate any help.