Hello,
I am having an issue with figuring out how to read four wheatstone bridge pressure sensors as quickly and accurately as possible over one I2C bus to an arduino mega. Essentially, four wheatstone bridge pressure sensors interface with an NAU7802 ADC and communicate with a TC9548A mux over four seperate channels, and the mux communicates directly with arduino mega over one I2C bus. There is only one mux that utilises one I2C line on the Mega (connects to one SDA/SCL line) as I originally planned to use an uno. The goal is to read pressure data from 1 and 2, 2 and 3 as quickly as possible to estimate differential pressure between sensor1 & 2, sensor 3& 4. As the system replicates blood flow by pulsing a small pump. So far I have delayed the mux by 5ms (delay(5)) and a simple moving average (SMA) has been applied to reduce noise but I know this is not accurate and is only delaying the whole system, how could I use timer interrupts instead or is there a better method?
#include <math.h>
#include <Adafruit_NAU7802.h>
#include <Wire.h>
// PWM motor control variables
const int pwmPin = 6; // Main pump PWM pin
const int secondaryPumpPin = 5; // Secondary pump PWM pin
float frequency = 1.5; // Frequency can be adjusted dynamically if needed
unsigned long previousMillis = 0;
const long interval = 10;
float phase = 0.0;
// NAU7802 setup
Adafruit_NAU7802 nau2; // NAU7802 for channel 2
Adafruit_NAU7802 nau3; // NAU7802 for channel 3
Adafruit_NAU7802 nau4; // NAU7802 for channel 4
Adafruit_NAU7802 nau5; // NAU7802 for channel 5
#define TCAADDR 0x70
#define NUM_READINGS 10
int readings2[NUM_READINGS];
int readings3[NUM_READINGS];
int readings4[NUM_READINGS];
int readings5[NUM_READINGS];
int readIndex = 0;
long total2 = 0;
long total3 = 0;
long total4 = 0;
long total5 = 0;
int average2 = 0;
int average3 = 0;
int average4 = 0;
int average5 = 0;
float conversion2; // Converted pressure value for channel 2
float conversion3; // Converted pressure value for channel 3
float conversion4; // Converted pressure value for channel 4
float conversion5; // Converted pressure value for channel 5
void tcaSelect(uint8_t i) {
if (i > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
delay(5);
}
void setup() {
Serial.begin(115200);
pinMode(pwmPin, OUTPUT);
pinMode(secondaryPumpPin, OUTPUT);
// Initialize NAU7802 for channel 2
tcaSelect(2);
if (!nau2.begin()) {
Serial.println("Failed to find NAU7802 on channel 2");
} else {
Serial.println("Found NAU7802 on channel 2");
nau2.setLDO(NAU7802_4V5);
nau2.setGain(NAU7802_GAIN_1);
nau2.setRate(NAU7802_RATE_80SPS);
if (nau2.calibrate(NAU7802_CALMOD_INTERNAL) && nau2.calibrate(NAU7802_CALMOD_OFFSET)) {
Serial.println("NAU7802 calibration successful for channel 2");
} else {
Serial.println("NAU7802 calibration failed for channel 2");
}
}
// Initialize NAU7802 for channel 3
tcaSelect(3);
if (!nau3.begin()) {
Serial.println("Failed to find NAU7802 on channel 3");
} else {
Serial.println("Found NAU7802 on channel 3");
nau3.setLDO(NAU7802_4V5);
nau3.setGain(NAU7802_GAIN_1);
nau3.setRate(NAU7802_RATE_80SPS);
if (nau3.calibrate(NAU7802_CALMOD_INTERNAL) && nau3.calibrate(NAU7802_CALMOD_OFFSET)) {
Serial.println("NAU7802 calibration successful for channel 3");
} else {
Serial.println("NAU7802 calibration failed for channel 3");
}
}
// Initialize NAU7802 for channel 4
tcaSelect(4);
if (!nau4.begin()) {
Serial.println("Failed to find NAU7802 on channel 4");
} else {
Serial.println("Found NAU7802 on channel 4");
nau4.setLDO(NAU7802_4V5);
nau4.setGain(NAU7802_GAIN_1);
nau4.setRate(NAU7802_RATE_80SPS);
if (nau4.calibrate(NAU7802_CALMOD_INTERNAL) && nau4.calibrate(NAU7802_CALMOD_OFFSET)) {
Serial.println("NAU7802 calibration successful for channel 4");
} else {
Serial.println("NAU7802 calibration failed for channel 4");
}
}
// Initialize NAU7802 for channel 5
tcaSelect(5);
if (!nau5.begin()) {
Serial.println("Failed to find NAU7802 on channel 5");
} else {
Serial.println("Found NAU7802 on channel 5");
nau5.setLDO(NAU7802_4V5);
nau5.setGain(NAU7802_GAIN_1);
nau5.setRate(NAU7802_RATE_80SPS);
if (nau5.calibrate(NAU7802_CALMOD_INTERNAL) && nau5.calibrate(NAU7802_CALMOD_OFFSET)) {
Serial.println("NAU7802 calibration successful for channel 5");
} else {
Serial.println("NAU7802 calibration failed for channel 5");
}
}
// Initialize pressure readings
for (int i = 0; i < NUM_READINGS; i++) {
readings2[i] = 0;
readings3[i] = 0;
readings4[i] = 0;
readings5[i] = 0;
}
}
void loop() {
unsigned long currentMillis = millis();
// Motor control for main pump
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
float sinValue = sin(2 * PI * frequency * phase);
int pwmValue = (int)((sinValue + 1) * 127.5);
analogWrite(pwmPin, pwmValue);
phase += frequency * (interval / 1000.0);
if (phase >= (1.0 / frequency)) {
phase = 0;
}
}
// Run secondary pump at a constant PWM value
analogWrite(secondaryPumpPin, 100);
// Read pressure data for channel 2
tcaSelect(2);
if (nau2.available()) {
total2 -= readings2[readIndex];
readings2[readIndex] = nau2.read();
total2 += readings2[readIndex];
readIndex = (readIndex + 1) % NUM_READINGS;
if (readIndex >= NUM_READINGS) {
readIndex = 0;
}
average2 = total2 / NUM_READINGS;
conversion2 = average2 * 1; // Apply conversion factor and offset for channel 2,cal factor to be added
}
// Read pressure data for channel 3
tcaSelect(3);
if (nau3.available()) {
total3 -= readings3[readIndex];
readings3[readIndex] = nau3.read();
total3 += readings3[readIndex];
readIndex = (readIndex + 1) % NUM_READINGS;
if (readIndex >= NUM_READINGS) {
readIndex = 0;
}
average3 = total3 / NUM_READINGS;
conversion3 = average3 * 1; // Apply conversion factor and offset for channel 3
}
// Read pressure data for channel 4
tcaSelect(4);
if (nau4.available()) {
total4 -= readings4[readIndex];
readings4[readIndex] = nau4.read();
total4 += readings4[readIndex];
readIndex = (readIndex + 1) % NUM_READINGS;
if (readIndex >= NUM_READINGS) {
readIndex = 0;
}
average4 = total4 / NUM_READINGS;
conversion4 = average4 * 1; // Apply conversion factor and offset for channel 4
}
// Read pressure data for channel 5
tcaSelect(5);
if (nau5.available()) {
total5 -= readings5[readIndex];
readings5[readIndex] = nau5.read();
total5 += readings5[readIndex];
readIndex = (readIndex + 1) % NUM_READINGS;
if (readIndex >= NUM_READINGS) {
readIndex = 0;
}
average5 = total5 / NUM_READINGS;
conversion5 = average5 * 1; // Apply conversion factor and offset for channel 5
}
// Calculate differential pressure and print
float differentialPressure23 = conversion2 - conversion3;
float differentialPressure45 = conversion4 - conversion5;
Serial.print(differentialPressure23);
Serial.print(",");
Serial.println(differentialPressure45);
}