Hardware
I settled on the ESP32 Mini for this project:
- It has a much smaller form factor than the canonical ESP32 dev board, yet have a good number of pins exposed through its double-row header layout.
- It is one of the cheaper ESP32 dev boards. I got mine for ~A$6 (including shipping) on AliExpress.
Generating Tick Pulses using the ULP
The platformio.ini file looks like this:
[platformio] default_envs = wemos_d1_mini32 [env:wemos_d1_mini32] platform = espressif32 framework = arduino platform_packages = framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git board = wemos_d1_mini32 upload_speed = 912600 monitor_speed = 115200
Here's the test code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | // Make 60 ticks on a non-sweeping clock and stop #include <Arduino.h> #include <esp32/ulp.h> #include <driver/adc.h> #include <driver/rtc_io.h> // Named indices into RTC_SLOW_MEM enum { TICK_PIN, // tick pin: 1 or 2 TICK_COUNT, // stop ticking after certain count to check that we have no missed ticks }; #define RTCVAR_OFFSET 2000 // RTC vars starts here in RTC_SLOW_MEM (32-bit/8KB => max range = 2047) #define RTCVAR(var) (RTC_SLOW_MEM[RTCVAR_OFFSET+var] & UINT16_MAX) #define RTCVAR_SET(var, value) RTC_SLOW_MEM[RTCVAR_OFFSET+var] = value #define TICK_INTERVAL 1000000 - 40000 // delay between calls to ULP code in usec (1sec - 40msec) #define TICKPIN1 RTCIO_GPIO25_CHANNEL #define TICKPIN2 RTCIO_GPIO27_CHANNEL #define TICKPIN1_GPIO GPIO_NUM_25 #define TICKPIN2_GPIO GPIO_NUM_27 // Load RTCMEM[var] into reg #define X_RTC_LOAD(var, reg) \ I_MOVI(R3, RTCVAR_OFFSET+var), \ |
The 2 pins assigned to emit the tick pulses are GPIO25 and GPIO27. The ULP code generates 60 tick pulses (30 on each pin, 40ms pulse width) and stops. Since this is exactly 1 minute, it allows me to easily check if there are any missed ticks. The pulses are fed into the diode bridge in the ESPCLOCK3 circuit, and makes the analog clock tick as expected.
Using the current meter, the current draw was determined to be 2.62mA.
Next, I used a precision side cutter to remove the red power LED that is always illuminated when power is applied and cannot be turned off.
After the power LED is removed, the current draw of the above code is now 1.37mA.So we are off to a good start! The power consumption is on par with the ~1.2mA drawn on the ESPCLOCK3, which I am sure can be reduced further through optimization.
Some observations about ULP programming
- I_END() only ends the RTC timer. It does not stop the ULP code. To do that, it needs to be followed by a I_HALT() command.
- Initially, I was under the impression that ulp_set_wakeup_period() is like Javascript's setInterval() i.e. it calls the ULP repeatedly at the specified interval eg. every second. Turns out I was wrong. The timer only starts counting down when I_HALT() is called. So if I want the ULP code to be called every second, and I know the ULP code takes ~40ms, then I need to subtract that from my wakeup period.
Jut for fun..
I connected the circuit to the sweeping clock that I modded previously, and modified the code slightly to pulse 16 times a second (8 pulses on each pin, 32ms pulse width, spaced 62.5ms apart).
The power draw is measured to be a whooping 14.7mA!
Comments
Post a Comment