Storing analog measurement values in an array using the ULP coprocessor

Distjubo
Posts: 4
Joined: Sun Sep 17, 2017 4:45 pm

Storing analog measurement values in an array using the ULP coprocessor

Postby Distjubo » 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

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


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?

ESP_igrr
Posts: 1144
Joined: Tue Dec 01, 2015 8:37 am

Re: Storing analog measurement values in an array using the ULP coprocessor

Postby ESP_igrr » Sun Sep 17, 2017 9:08 pm

You probably want it to be:

Code: Select all

   // store measurements in respective arrays
   move r3, channel_1_measurements // load its address
   add r3, r3, r0                  // offset by loop-counter (zero based)
   st r1, r3, 0                    // and store the value

   move r3, channel_2_measurements // load its address
   add r3, r3, r0                  // offset by loop-counter (zero based)
   st r2, r3, 0                    // and store the value


(note the order of arguments in "st" instruction)

Distjubo
Posts: 4
Joined: Sun Sep 17, 2017 4:45 pm

Re: Storing analog measurement values in an array using the ULP coprocessor

Postby Distjubo » Mon Sep 18, 2017 9:48 am

Oooh derp. That's probably it. Thanks man :roll:

bthedead
Posts: 2
Joined: Mon Dec 11, 2017 8:47 am

Re: Storing analog measurement values in an array using the ULP coprocessor

Postby bthedead » Mon Dec 11, 2017 8:49 am

How can we access the data saved in array from the main program?

Distjubo
Posts: 4
Joined: Sun Sep 17, 2017 4:45 pm

Re: Storing analog measurement values in an array using the ULP coprocessor

Postby Distjubo » Mon Dec 11, 2017 10:56 am

You can access the variables just like you would access any other variable in the ulp memory. Note the

Code: Select all

.global channel_1_measurements
and

Code: Select all

.global channel_2_measurements
. You can access these by prefixing them with

Code: Select all

ulp_
in your main program. For example, to get the third measurement from the first channel, you'd do

Code: Select all

measurement = (uint16_t)(&ulp_channel_1_measurements)[2];
You have to cast the variable because the upper 2 bytes contain the address of the instruction that stored the variable.

bthedead
Posts: 2
Joined: Mon Dec 11, 2017 8:47 am

Re: Storing analog measurement values in an array using the ULP coprocessor

Postby bthedead » Tue Dec 12, 2017 8:01 am

Thanks! I had forgot the '&' before the address. This solved the issue

Distjubo
Posts: 4
Joined: Sun Sep 17, 2017 4:45 pm

Re: Storing analog measurement values in an array using the ULP coprocessor

Postby Distjubo » Tue Dec 12, 2017 10:01 pm

Nice. Glad someone could make use of my code ;)

BTW don't forget to reset the sample counter in your ISR.

Who is online

Users browsing this forum: No registered users and 9 guests