Pulse Counting and sleeping

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

Re: Pulse Counting and sleeping

Postby ESP_igrr » Sat Mar 04, 2017 5:35 am

Binutils are ready, but not integrated into the build system.
I'll get back to you on the time it takes to run the wake stub and go back to sleep. Currently this time is limited by debouncing, mostly. Maybe need to consider some other example use case where the stub can actually run quickly.

WiFive
Posts: 3529
Joined: Tue Dec 01, 2015 7:35 am

Re: Pulse Counting and sleeping

Postby WiFive » Sat Mar 04, 2017 1:39 pm

ESP_igrr wrote:Binutils are ready, but not integrated into the build system.
I'll get back to you on the time it takes to run the wake stub and go back to sleep. Currently this time is limited by debouncing, mostly. Maybe need to consider some other example use case where the stub can actually run quickly.
Sounds good thanks.

For binutils, it doesn't need to be nice and tidy, just looking for a quick template and build script to generate the blob that can be manually copied to an idf project.

User avatar
rudi ;-)
Posts: 1727
Joined: Fri Nov 13, 2015 3:25 pm

Re: Pulse Counting and sleeping

Postby rudi ;-) » Sat Mar 04, 2017 2:54 pm

ESP_igrr wrote:I have created an example which illustrates deep sleep'ing and counting low pulses on GPIO0:
https://gist.github.com/igrr/54f7fbe051 ... d7fbecfeab
more example on this way please,
ivan, this is very welcome and think
the most "energy" guys ( like me )
were waiting for it.

thanks, now the thinks goes more and more clear

best wishes
rudi ;-)
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

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

Re: Pulse Counting and sleeping

Postby ESP_igrr » Mon Mar 27, 2017 9:18 am

ULP pulse counting example is now in ESP-IDF master:
https://github.com/espressif/esp-idf/tr ... system/ulp

With a 20ms sampling interval average supply current is 10uA.

User avatar
rudi ;-)
Posts: 1727
Joined: Fri Nov 13, 2015 3:25 pm

Re: Pulse Counting and sleeping

Postby rudi ;-) » Mon Mar 27, 2017 10:11 am

ESP_igrr wrote:ULP pulse counting example is now in ESP-IDF master:
https://github.com/espressif/esp-idf/tr ... system/ulp

With a 20ms sampling interval average supply current is 10uA.
hi ivan
only for info
fetch with sub modules fails just in time
( helped by hand )
fetch-mistake_subs.png
fetch-mistake_subs.png (38.17 KiB) Viewed 13134 times

will test it - thank you!!

best wishes
rudi ;-)
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

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

Re: Pulse Counting and sleeping

Postby ESP_igrr » Mon Mar 27, 2017 11:00 am

Hi rudi, thanks for the heads up regarding missing submodule. Please try again, should be fixed now.

User avatar
rudi ;-)
Posts: 1727
Joined: Fri Nov 13, 2015 3:25 pm

Re: Pulse Counting and sleeping

Postby rudi ;-) » Mon Mar 27, 2017 11:19 am

hi ivan,
thanks for fast response and fixed - now ok.
best wishes
rudi ;-)
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

User avatar
rudi ;-)
Posts: 1727
Joined: Fri Nov 13, 2015 3:25 pm

Re: Pulse Counting and sleeping

Postby rudi ;-) » Mon Mar 27, 2017 8:55 pm

ESP_igrr wrote:ULP pulse counting example is now in ESP-IDF master:
https://github.com/espressif/esp-idf/tr ... system/ulp

With a 20ms sampling interval average supply current is 10uA.
nice work ivan!

short test:
-------------

Code: Select all

rst:0x5 (DEEPSLEEP_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0x00
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0008,len:8
load:0x3fff0010,len:2488
load:0x40078000,len:7128
load:0x40080000,len:252
entry 0x40080034
ULP wakeup, saving pulse count
Read pulse count from NVS:    85
Pulse count from ULP:     5
Wrote updated pulse count to NVS:    90
Entering deep sleep
tested on ESP32_Demo_Board V2, it work's. ( the push button need a revision )

i must look deeper here, can be that we have differences to DevKitCV2, Nano32, ...
got 0x7 rst sometimes with other boards.

next steps on weekend measurements


best wishes
rudi ;-)

@all binutils-esp32ulp
if you not knowed, we have ready2go esp32ulp toolchain in the meantime here cause ESP32 ULP binutils port is under development.
follow the port for up2date links on repo
-------------------------------------
love it, change it or leave it.
-------------------------------------
問候飛出去的朋友遍全球魯迪

beg_dk
Posts: 34
Joined: Thu Apr 06, 2017 5:57 am

Re: Pulse Counting and sleeping

Postby beg_dk » Wed Aug 02, 2017 6:02 am

ESP_igrr wrote:I have created an example which illustrates deep sleep'ing and counting low pulses on GPIO0:
https://gist.github.com/igrr/54f7fbe051 ... d7fbecfeab

Comments are welcome. If there is positive feedback we will add this example to the ESP-IDF.

Each time you press "Boot" button (which brings GPIO0 low), ESP32 will wake up, increment a counter, and go back to sleep. Once the counter reaches certain number, application will start up.
Application can then connect to WiFi and send data somewhere, for example (not shown in this sample).
This example is very interesting as you have a workaround for the missing edge trigger support for deep sleep wakeup. However I find it a bit difficult to fully grasp your use of REG_GET_FIELD, RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT, REG_WRITE, TIMG_WDTFEED_REG, RTC_ENTRY_ADDR_REG and the like. Is there anywhere in the documentation I can find explanations on the use of these?

Thanks a lot for the example provided.

paddynoob
Posts: 9
Joined: Tue Sep 24, 2019 10:08 am

Re: Pulse Counting and sleeping

Postby paddynoob » Tue Sep 24, 2019 10:34 am

Hi there,

sorry for bringing up this old thread, but it fits best to my question. Thanks to you guys to provide ULP pulse count example. I tried it out and it worked like expected. However, I need to count two GPIOs instead of just one meaning I need to count two distinct inputs while ESP32 sleeps. It should wake up based on timer and read out the counting of ULP.

ESP32 code is not that hard to me but I'm struggling with ULP assembler code. I tried to understand what happens in the example but there are a few things I don't understand. I commented the example with // and capital letters.

Especially the part where you read GPIO (read_done) and check the edge (changed) I don't understand completely.

May I ask you guys to enlight me. One way for me is just to copy & paste the jump targets to something like read_done_a, read_done_b but this might not be the best solution. Last time I had to develop assembler was before decades, so it would be great if someone has a better solution.

Code: Select all

/* ULP Example: pulse counting

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.

   This file contains assembly code which runs on the ULP.

   ULP wakes up to run this code at a certain period, determined by the values
   in SENS_ULP_CP_SLEEP_CYCx_REG registers. On each wake up, the program checks
   the input on GPIO0. If the value is different from the previous one, the
   program "debounces" the input: on the next debounce_max_count wake ups,
   it expects to see the same value of input.
   If this condition holds true, the program increments edge_count and starts
   waiting for input signal polarity to change again.
   When the edge counter reaches certain value (set by the main program),
   this program running triggers a wake up from deep sleep.
*/

/* ULP assembly files are passed through C preprocessor first, so include directives
   and C macros may be used in these files 
 */
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_io_reg.h"
#include "soc/soc_ulp.h"

	/* Define variables, which go into .bss section (zero-initialized data) */
	.bss
	/* Next input signal edge expected: 0 (negative) or 1 (positive) */
	.global next_edge
next_edge:
	.long 0

	/* Counter started when signal value changes.
	   Edge is "debounced" when the counter reaches zero. */
	.global debounce_counter
debounce_counter:
	.long 0

	/* Value to which debounce_counter gets reset.
	   Set by the main program. */
	.global debounce_max_count
debounce_max_count:
	.long 0

	/* Total number of signal edges acquired */
	.global edge_count
edge_count:
	.long 0

	/* Number of edges to acquire before waking up the SoC.
	   Set by the main program. */
	.global edge_count_to_wake_up
edge_count_to_wake_up:
	.long 0

	/* RTC IO number used to sample the input signal.
	   Set by main program. */
	.global io_number
io_number:
	.long 0

	/* Code goes into .text section */
	.text
	.global entry
entry:
	/* Load io_number */
	move r3, io_number     // LOAD ADDRESS OF VARIABLE IO_NUMBER INTO R3
	ld r3, r3, 0           // READ LOWER BYTES OF R3 INTO R3, MEANS READ VALUE OF VARIABLE IO_NUMBER INTO R3

	/* Lower 16 IOs and higher need to be handled separately,
	 * because r0-r3 registers are 16 bit wide.
	 * Check which IO this is.
	 */
	move r0, r3			   // MOVE VALUE OF IO_NUMBER TO R0
	jumpr read_io_high, 16, ge  // IF IO_NUMBER(R0) > 16 JUMP TO READ FURTHER

	/* Read the value of lower 16 RTC IOs into R0 */
	READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S, 16)	// READ GPIO PINS 0-15 INTO R0
	rsh r0, r0, r3         // RIGHT SHIFT WHAT? R3 STILL CONTAINS NUMBER OF IO PIN
	jump read_done

	/* Read the value of RTC IOs 16-17, into R0 */
read_io_high:
	READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + 16, 2)
	sub r3, r3, 16
	rsh r0, r0, r3

read_done:
	and r0, r0, 1   // R0 CONTAINS PIN STATUS OF ALL PINS, AFTER AND, IT CONTAINS ONLY STATUS OF ONE PIN?
	/* State of input changed? */
	move r3, next_edge  // LOAD ADDRESS OF VARIABLE NEXT_EDGE
	ld r3, r3, 0        // LOAD VALUE OF NEXT_EDGE TO R3
	add r3, r0, r3		// WHY/WHAT HAPPENS HERE?
	and r3, r3, 1       // WHY/WHAT HAPPENS HERE?
	jump changed, eq    // JUMP TO CHANGED, IF PREVIOUS AND RETURNS TRUE
	/* Not changed */
	/* Reset debounce_counter to debounce_max_count */
	move r3, debounce_max_count  
	move r2, debounce_counter
	ld r3, r3, 0
	st r3, r2, 0
	/* End program */
	halt

	.global changed
changed:
	/* Input state changed */
	/* Has debounce_counter reached zero? */
	move r3, debounce_counter
	ld r2, r3, 0
	add r2, r2, 0 /* dummy ADD to use "jump if ALU result is zero" */
	jump edge_detected, eq
	/* Not yet. Decrement debounce_counter */
	sub r2, r2, 1
	st r2, r3, 0
	/* End program */
	halt

	.global edge_detected
edge_detected:
	/* Reset debounce_counter to debounce_max_count */
	move r3, debounce_max_count
	move r2, debounce_counter
	ld r3, r3, 0
	st r3, r2, 0
	/* Flip next_edge */
	move r3, next_edge
	ld r2, r3, 0
	add r2, r2, 1
	and r2, r2, 1
	st r2, r3, 0
	/* Increment edge_count */
	move r3, edge_count
	ld r2, r3, 0
	add r2, r2, 1
	st r2, r3, 0
	/* Compare edge_count to edge_count_to_wake_up */
	move r3, edge_count_to_wake_up
	ld r3, r3, 0
	sub r3, r3, r2
	jump wake_up, eq
	/* Not yet. End program */
	halt

	.global wake_up
wake_up:
	/* Check if the system can be woken up */
	READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
	and r0, r0, 1
	jump wake_up, eq

	/* Wake up the SoC, end program */
	wake
	halt

Who is online

Users browsing this forum: No registered users and 63 guests