Hello!
I'm trying to read 2 analog inputs at 1kHz, and send them (+ the time between reads) over serial to a python script. I got it working, but can't get the time to correspond to 1 ms. Board has a SAMD51 chip.
I tried with a timed loop, which didn't give me the expected results. Then I tried with the SAMDTimer library example, by sampling with an interrupt, and then send the data over serial, which didn't work either. Can someone point me in the right direction?
What works, but at a 2ms (commented out) or 5-10ms at the moment:
unsigned long t0 = 0;
long loopTime = 1000; // microseconds = 1ms loop
float tmp1, tmp2 = 0; // variables at conversion
float val1, val2 = 0; // variables after filtering
float timer = 0;
unsigned long sampleTimer = 0;
unsigned long sampleInterval = 1000; //100 us = 100Hz rate
void setup() {
Serial.begin(115200); // baudrate
analogReadResolution(12); // ADC resolution
}
void loop() {
// unsigned long tnow;
// do
// tnow = micros();
// while ( (tnow - t0) < 1000 ); // waits until time has come
// t0 += 1000;
// tmp1 = analogRead(A0) * 3.3 / 4095.0; // convert reading into volts
// tmp2 = analogRead(A1) * 3.3 / 4095.0;
// val1 = 0.9875 * val1 + 0.01249 * tmp1; // filter variables
// val2 = 0.9875 * val2 + 0.01249 * tmp2;
// sendToPC(&val1, &val2, &tnow);
unsigned long currMicros = micros();
if (currMicros - sampleTimer >= sampleInterval) // is it time for a sample?
{
sampleTimer = currMicros;
timer = (float)sampleTimer;
tmp1 = analogRead(A0) * 3.3 / 4095.0; // convert reading into volts
tmp2 = analogRead(A1) * 3.3 / 4095.0;
val1 = 0.9875 * val1 + 0.01249 * tmp1; // filter variables
val2 = 0.9875 * val2 + 0.01249 * tmp2;
sendToPC(&val1, &val2, &timer);
}
}
void sendToPC(float* data1, float* data2, float* data3)
{
byte* byteData1 = (byte*)(data1);
byte* byteData2 = (byte*)(data2);
byte* byteData3 = (byte*)(data3);
byte buf[12] = {byteData1[0], byteData1[1], byteData1[2], byteData1[3],
byteData2[0], byteData2[1], byteData2[2], byteData2[3],
byteData3[0], byteData3[1], byteData3[2], byteData3[3]
};
Serial.write(buf, 12);
}
The code using an ISR:
#include "SAMDTimerInterrupt.h"
#define TIMER0_INTERVAL_MS 1
volatile uint32_t preMillisTimer0 = 0;
volatile uint32_t preMillisTimer1 = 0;
volatile float tmp1, tmp2 = 0; // variables at conversion
volatile float val1, val2 = 0; // variables after filtering
// SAMD51 Hardware Timer only TC3
SAMDTimer ITimer0(TIMER_TC3);
void TimerHandler0() {
tmp1 = analogRead(A0) * 3.3 / 4095.0; // convert reading into volts
tmp2 = analogRead(A1) * 3.3 / 4095.0;
val1 = 0.9875 * val1 + 0.01249 * tmp1; // filter variables
val2 = 0.9875 * val2 + 0.01249 * tmp2;
}
void setup() {
Serial.begin(115200);
analogReadResolution(12); // ADC resolution
while (!Serial);
delay(100);
Serial.print(F("\nStarting TimerInterruptTest on ")); Serial.println(BOARD_NAME);
Serial.println(SAMD_TIMER_INTERRUPT_VERSION);
Serial.print(F("CPU Frequency = ")); Serial.print(F_CPU / 1000000); Serial.println(F(" MHz"));
// Interval in microsecs
if (ITimer0.attachInterruptInterval(TIMER0_INTERVAL_MS * 1000, TimerHandler0)) {
preMillisTimer0 = millis();
Serial.print(F("Starting ITimer0 OK, millis() = ")); Serial.println(preMillisTimer0);
}
else
Serial.println(F("Can't set ITimer0. Select another freq. or timer"));
}
void loop() {
static unsigned long lastTimer0 = 0;
if (millis() - lastTimer0 > TIMER0_INTERVAL_MS) {
lastTimer0 = millis();
preMillisTimer0 = millis();
// Serial.print(F("Start ITimer0, millis() = ")); Serial.println(preMillisTimer0);
ITimer0.restartTimer();
sendToPC(&val1, &val2, &preMillisTimer0);
}
}
void sendToPC(volatile float* data1, volatile float* data2, volatile uint32_t* data3)
{
byte* byteData1 = (byte*)(data1);
byte* byteData2 = (byte*)(data2);
byte* byteData3 = (byte*)(data3);
byte buf[12] = {byteData1[0], byteData1[1], byteData1[2], byteData1[3],
byteData2[0], byteData2[1], byteData2[2], byteData2[3],
byteData3[0], byteData3[1], byteData3[2], byteData3[3]
};
Serial.write(buf, 12);
}
I just can't get the data at a 1kHZ sampling rate in my csv data. I don't understand datasheets well enough to program this using registers.
Thank you for your input.