shookti
Member
I have a program that acquires time multiplexed analog data from a single pin (pin #27) on a Teensy 4.1.
Each measurement is a single value that's reported using Serial.print averaged over ~500 microseconds, with some values being averaged by setting analogReadAveraging(32) and the remaining by averaging by code shown below.
The problem I am facing is that - while testing the code by putting my finger on pin #27, just to see the noise readout, the noise values read by the "excitation" section jumps to around -40 (set to 12 bit resolution) and slowly veering to zero instead of being centred around 0 like how the 'isosbestic' section is.
For some context this program modulates 2 LEDs of different wavelengths that are exciting certain proteins in populations of neurons in live rat brains that fluoresce at different intensities based on the concentration of calcium ions in the population (method known as "in-vivo fibre photometry" in neuroscience).
One important feature of the program is that the fluorescence values are analog-read with baseline subtraction to account for noise in the fluorescence activity in the brain
There might be some unused / undeclared variables in the following code snippet because I have erased a lot of repetitive code to make it easier to read, and some declarations are in another header file. I don't think this code has anything to do with this problem.
I have verified that all the modulation steps are being executed correctly.
What could be the reason for this behaviour where noise created by my finger is not centred around Zero for one type of analogReads?
Another issue I am facing is that sometimes (randomly) the values reported are NaN, hence the reason for the "val == val" checks, which only NaNs fail.
Each measurement is a single value that's reported using Serial.print averaged over ~500 microseconds, with some values being averaged by setting analogReadAveraging(32) and the remaining by averaging by code shown below.
The problem I am facing is that - while testing the code by putting my finger on pin #27, just to see the noise readout, the noise values read by the "excitation" section jumps to around -40 (set to 12 bit resolution) and slowly veering to zero instead of being centred around 0 like how the 'isosbestic' section is.
For some context this program modulates 2 LEDs of different wavelengths that are exciting certain proteins in populations of neurons in live rat brains that fluoresce at different intensities based on the concentration of calcium ions in the population (method known as "in-vivo fibre photometry" in neuroscience).
One important feature of the program is that the fluorescence values are analog-read with baseline subtraction to account for noise in the fluorescence activity in the brain
There might be some unused / undeclared variables in the following code snippet because I have erased a lot of repetitive code to make it easier to read, and some declarations are in another header file. I don't think this code has anything to do with this problem.
I have verified that all the modulation steps are being executed correctly.
C++:
#include "config.hpp"
IntervalTimer timer;
volatile int timeCounter = 0;
int totalTime = MEASURE + LED_ON + ISO_EXC_GAP + MEASURE + LED_ON + (TIME_PERIOD * 1000);
float baselines [MAX_MEASUREMENTS] = { };
int baselineCounter = 0;
volatile bool recording = false;
volatile uint64_t timestamp = 0;
bool timestampSet = false;
void setup() {
Serial.begin(SERIAL_BAUD);
Serial.println("START");
// irl540n switches in the circuit are active LOW, so start with HIGH
pinMode(ISO_LED, OUTPUT);
digitalWriteFast(ISO_LED, HIGH);
pinMode(EXC_LED, OUTPUT);
digitalWriteFast(EXC_LED, HIGH);
pinMode(OPTO_LED, OUTPUT);
digitalWriteFast(OPTO_LED, HIGH);
if (BIT_DEPTH != -1) analogReadResolution(BIT_DEPTH);
if (BUILTIN_AVG != -1) analogReadAveraging(BUILTIN_AVG);
timer.begin(incrementTimeCounter, 1);
}
void loop() {
if (!(recording || RECORD_ON_POWERUP)) return;
if (RECORD_ON_POWERUP && (!timestampSet)) {
timestamp = 0;
timestampSet = true;
}
// measure iso baseline
if (timeCounter >= isoBaselineMeasureOn && timeCounter <= isoBaselineMeasureOff) {
baselines[baselineCounter] = measure(MEASURE_PIN, NOT_BUILTIN_AVG);
baselineCounter++;
}
// turn on iso LED
if (timeCounter >= isoLedOn and timeCounter <= isoLedOff) {
digitalWriteFast(ISO_LED, LOW);
}
// measure iso emission
if (timeCounter >= isoEmmMeasureOn && timeCounter <= isoEmmMeasureOff) {
float val = 0.0;
for (int i = 0; i < baselineCounter; i++) {
val = val + measure(MEASURE_PIN, NOT_BUILTIN_AVG) - baselines[i];
baselines[i] = 0;
}
val = val / baselineCounter;
if (val == val) {
// sometimes the values are nans, unknown reason
Serial.print("i,");
Serial.print(timestamp);
Serial.print(',');
Serial.println(val / baselineCounter, 4);
}
baselineCounter = 0;
}
// turn off iso LED
if (timeCounter >= isoLedOff) {
digitalWriteFast(ISO_LED, HIGH);
}
// measure exc baseline
if (timeCounter >= excBaselineMeasureOn && timeCounter <= excBaselineMeasureOff) {
baselines[baselineCounter] = measure(MEASURE_PIN, NOT_BUILTIN_AVG);
baselineCounter++;
}
// turn on exc LED
if (timeCounter >= excLedOn && timeCounter <= excLedOff) {
digitalWriteFast(EXC_LED, LOW);
}
// measure exc emission
if (timeCounter >= excEmmMeasureOn && timeCounter <= excEmmMeasureOff) {
float val = 0.0;
for (int i = 0; i < baselineCounter; i++) {
val = val + measure(MEASURE_PIN, NOT_BUILTIN_AVG) - baselines[i];
baselines[i] = 0;
}
val = val / baselineCounter;
if (val == val) {
// sometimes the values are nans, unknown reason
Serial.print("e,");
Serial.print(timestamp);
Serial.print(',');
Serial.println(val / baselineCounter, 4);
}
baselineCounter = 0;
}
// turn off exc LED
if (timeCounter >= excLedOff) {
digitalWriteFast(EXC_LED, HIGH);
}
}
void incrementTimeCounter() {
timestamp++;
if (timeCounter != totalTime) {
timeCounter++;
} else {
timeCounter = 0;
}
}
int measure(int pin, int avgx) {
if (avgx == 1 || avgx == -1) {
return analogRead(pin);
}
float val = 0;
for (int i = 0; i < avgx; i++) {
val += analogRead(pin);
}
return (val / avgx);
}
What could be the reason for this behaviour where noise created by my finger is not centred around Zero for one type of analogReads?
Another issue I am facing is that sometimes (randomly) the values reported are NaN, hence the reason for the "val == val" checks, which only NaNs fail.
Last edited: