3 This example code is in the Public Domain (or CC0 licensed, at your option.)
5 Unless required by applicable law or agreed to in writing, this
6 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7 CONDITIONS OF ANY KIND, either express or implied.
11 #include "esp_sleep.h"
13 #include "nvs_flash.h"
14 #include "soc/rtc_cntl_reg.h"
15 #include "soc/sens_reg.h"
16 #include "soc/rtc_periph.h"
17 #include "driver/gpio.h"
18 #include "driver/rtc_io.h"
19 #include "esp32/ulp.h"
22 extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
23 extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end");
25 static void init_ulp_program();
26 static void update_pulse_count();
30 esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
31 if (cause != ESP_SLEEP_WAKEUP_ULP) {
32 printf("Not ULP wakeup, initializing ULP\n");
35 printf("ULP wakeup, saving pulse count\n");
39 printf("Entering deep sleep\n\n");
40 ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
41 esp_deep_sleep_start();
44 static void init_ulp_program()
46 esp_err_t err = ulp_load_binary(0, ulp_main_bin_start,
47 (ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t));
50 /* GPIO used for pulse counting. */
51 gpio_num_t gpio_num = GPIO_NUM_0;
52 assert(rtc_gpio_desc[gpio_num].reg && "GPIO used for pulse counting must be an RTC IO");
54 /* Initialize some variables used by ULP program.
55 * Each 'ulp_xyz' variable corresponds to 'xyz' variable in the ULP program.
56 * These variables are declared in an auto generated header file,
57 * 'ulp_main.h', name of this file is defined in component.mk as ULP_APP_NAME.
58 * These variables are located in RTC_SLOW_MEM and can be accessed both by the
59 * ULP and the main CPUs.
61 * Note that the ULP reads only the lower 16 bits of these variables.
63 ulp_debounce_counter = 3;
64 ulp_debounce_max_count = 3;
66 ulp_io_number = rtc_gpio_desc[gpio_num].rtc_num; /* map from GPIO# to RTC_IO# */
67 ulp_edge_count_to_wake_up = 10;
69 /* Initialize selected GPIO as RTC IO, enable input, disable pullup and pulldown */
70 rtc_gpio_init(gpio_num);
71 rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_INPUT_ONLY);
72 rtc_gpio_pulldown_dis(gpio_num);
73 rtc_gpio_pullup_dis(gpio_num);
74 rtc_gpio_hold_en(gpio_num);
76 /* Disconnect GPIO12 and GPIO15 to remove current drain through
77 * pullup/pulldown resistors.
78 * GPIO15 may be connected to ground to suppress boot messages.
79 * GPIO12 may be pulled high to select flash voltage.
81 rtc_gpio_isolate(GPIO_NUM_12);
82 rtc_gpio_isolate(GPIO_NUM_15);
84 /* Set ULP wake up period to T = 20ms.
85 * Minimum pulse width has to be T * (ulp_debounce_counter + 1) = 80ms.
87 ulp_set_wakeup_period(0, 20000);
89 /* Start the program */
90 err = ulp_run((&ulp_entry - RTC_SLOW_MEM) / sizeof(uint32_t));
94 static void update_pulse_count()
96 const char* namespace = "plusecnt";
97 const char* count_key = "count";
99 ESP_ERROR_CHECK( nvs_flash_init() );
101 ESP_ERROR_CHECK( nvs_open(namespace, NVS_READWRITE, &handle));
102 uint32_t pulse_count = 0;
103 esp_err_t err = nvs_get_u32(handle, count_key, &pulse_count);
104 assert(err == ESP_OK || err == ESP_ERR_NVS_NOT_FOUND);
105 printf("Read pulse count from NVS: %5d\n", pulse_count);
107 /* ULP program counts signal edges, convert that to the number of pulses */
108 uint32_t pulse_count_from_ulp = (ulp_edge_count & UINT16_MAX) / 2;
109 /* In case of an odd number of edges, keep one until next time */
110 ulp_edge_count = ulp_edge_count % 2;
111 printf("Pulse count from ULP: %5d\n", pulse_count_from_ulp);
113 /* Save the new pulse count to NVS */
114 pulse_count += pulse_count_from_ulp;
115 ESP_ERROR_CHECK(nvs_set_u32(handle, count_key, pulse_count));
116 ESP_ERROR_CHECK(nvs_commit(handle));
118 printf("Wrote updated pulse count to NVS: %5d\n", pulse_count);