Storing analog measurement values in an array using the ULP coprocessor
Posted: Sun Sep 17, 2017 4:59 pm
Hi,
I recently bought an Esp32 which I want to integrate into a low power project. I'd like it to use as little power as possible, so utilising the ULP coprocessor is a no-brainer for me. The analog measurements should be stored in an array, so I can later evaluate the data on the Esp32's main processors. Heres my code (I started off by copying the adc example):
adc_ulp.S
This code does work to some extent. It increments sample_counter every time it runs and it wakes up the main processor (or triggers the interrupt for now), but no measurements are stored in the respective arrays. Also, one thing I noticed is that when the processor measured a small voltage (it seems to be ~0.1V), it crashed. My guess is that my code storing the measurements in the arrays is misbehaving, which would instead of storing the values in the arrays corrupt the program with what it measured. Any ideas what I'm doing wrong?
I recently bought an Esp32 which I want to integrate into a low power project. I'd like it to use as little power as possible, so utilising the ULP coprocessor is a no-brainer for me. The analog measurements should be stored in an array, so I can later evaluate the data on the Esp32's main processors. Heres my code (I started off by copying the adc example):
adc_ulp.S
Code: Select all
/* ADC1 channel 6, GPIO34 */
.set adc_channel_1, 6
/* ADC1 channel 7, GPIO36 */
.set adc_channel_2, 0
/* Configure the number of ADC samples to average on each measurement.
For convenience, make it a power of 2. */
.set adc_oversampling_factor_log, 2
.set adc_oversampling_factor, (1 << adc_oversampling_factor_log)
.set max_sample_seconds, 10
.set sample_frequency, 5
.set max_samples, max_sample_seconds * sample_frequency
.set max_samples_bytes, max_samples * 4
/* Define variables, which go into .bss section (zero-initialized data) */
.bss
.global adc_channel_1_threshold
adc_channel_1_threshold:
.long 0
.global adc_channel_2_threshold
adc_channel_2_threshold:
.long 0
/* Counter of measurements done */
.global sample_counter
sample_counter:
.long 0
.global channel_1_measurements
channel_1_measurements:
.fill max_samples_bytes
.global channel_2_measurements
channel_2_measurements:
.fill max_samples_bytes
/* Code goes into .text section */
.text
.global entry
entry:
/* increment sample counter */
//move r1, sample_counter
//ld r0, r1, 0
//add r0, r0, 1
//st r0, r1, 0
// r0 holds the loop count, r1 can be used again
//r1 will hold the first channel measurement, r2 will hold the second
// initialize the loop counter, reset r1 and r2
move r1, 0
move r2, 0
stage_rst
measure:
// store temporary measurements in r3
// measure first channel
adc r3, 0, adc_channel_1 + 1
add r1, r1, r3
// measure second channel
adc r3, 0, adc_channel_2 + 1
add r2, r2, r3
// repeat if we haven't measure enough samples for oversampling
stage_inc 1
jumps measure, adc_oversampling_factor, lt
// r3 can be used again
// divide by oversampling factor. Since its a power of two, we can >> ^^
rsh r1, r1, adc_oversampling_factor_log
rsh r2, r2, adc_oversampling_factor_log
// load sample counter into r0
move r3, sample_counter
ld r0, r3, 0
// store measurements in respective arrays
move r3, channel_1_measurements // load its address
add r3, r3, r0 // offset by loop-counter (zero based)
st r3, r1, 0 // and store the value
move r3, channel_2_measurements // load its address
add r3, r3, r0 // offset by loop-counter (zero based)
st r3, r1, 0 // and store the value
// increment our sample counter and store the value
move r3, sample_counter
add r0, r0, 1
st r0, r3, 0
jumpr wake_up, max_samples, ge // wake up when we stored enough values (compares max_samples with r0)
/* compare with high_thr; wake up if value > high_thr */
move r3, adc_channel_1_threshold
ld r3, r3, 0
sub r3, r3, r1
jump wake_up, ov
move r3, adc_channel_2_threshold
ld r3, r3, 0
sub r3, r3, r2
jump wake_up, ov
halt
wake_up:
wake
halt