Hi,
I am generating an on-off keyed square wave of varying pulse widths (all quite short!) to encode a signal. I've used an Arduino R3 Uno to measure the pulse widths (in number of clock cycles), however it struggles below pulse widths of approximately 8us. My thought is to try it on the R4, which has a 48MHz clock and should provide a better resolution (I need to measure pulse widths down to approx 4us). However, I am unfamiliar with the code on the new microcontroller, and struggling to find sufficient resources to learn. Could anyone help, either below or by providing links, on how to implement a similar system as to the R3 code I have attached?
// === CONFIGURATION ===
#define MAX_EDGES 30 // Number of edges we will store
#define THRESH_LONG 10000
// === GLOBAL VARIABLES ===
volatile uint16_t timing[MAX_EDGES]; // Array to store time differences
volatile uint16_t sequence[MAX_EDGES]; // Array to store time differences
volatile uint16_t i_glob = 0, i_thresh = 0; // Index in timing array
volatile uint16_t last_capture = 0; // Stores the last captured time
int goThresh = 0;
void setup() {
// Start serial for debugging (you won't use it yet)
Serial.begin(2000000);
// === TIMER1 SETUP ===
TCCR1A = 0; // Normal mode
TCCR1B = (0 << ICES1) | (1 << CS10); // Rising edge, no prescaler
TIMSK1 |= (1 << ICIE1); // Enable input capture interrupt
DDRD |= (1 << PD5); // Set pin 5 as output
}
void loop() {
if (i_glob >= MAX_EDGES) {
cli(); // Pause interrupts
uint16_t local_timing[MAX_EDGES];
for (uint16_t j = 0; j < MAX_EDGES; j++) {
local_timing[j] = timing[j];
Serial.println(local_timing[j]);
}
i_glob = 0;
memset(timing, 0, sizeof(timing)); // Reset answer
sei(); // Enable interrupts
}
}
// === INPUT CAPTURE INTERRUPT ===
// This runs every time there's a rising (or falling) edge on pin 8
ISR(TIMER1_CAPT_vect) {
uint16_t current_capture = ICR1; // Read current timer value
uint16_t time_diff = current_capture - last_capture;
last_capture = current_capture;
if (time_diff > THRESH_LONG){
goThresh = 1;
i_thresh = i_glob;
i_glob = 0;
}
// Store the timing if there's room and the long threshold has been detected!
if (i_glob < MAX_EDGES && goThresh == 1) {
timing[i_glob] = time_diff;
i_glob = i_glob + 1;
}
// Toggle edge detection: rising <-> falling
TCCR1B ^= (1 << ICES1);
}
The code above works by detecting rising/falling edges on pin 8, measuring the pulse widths in clock cycles, and if a long cycle has occurred ( > 10,000 cycles), it will record a buffer of the next cycles. This is because the input signal is duty cycled and has a long low between data.
Many thanks.
