添加智能灯固件代码

This commit is contained in:
kerwincui
2021-07-13 17:14:51 +08:00
parent 332f74dd17
commit ecc0b91b8b
2568 changed files with 229441 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ulp-adc-example)

View File

@@ -0,0 +1,9 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := ulp-adc-example
include $(IDF_PATH)/make/project.mk

View File

@@ -0,0 +1,49 @@
| Supported Targets | ESP32 |
| ----------------- | ----- |
# ULP ADC Example
This example demonstrates how to use the ULP coprocessor to poll ADC in deep sleep.
ULP program periodically measures the input voltage on GPIO34. The voltage is compared to two thresholds. If the voltage is less than the low threshold, or higher than the high threshold, ULP wakes up the system.
By default, thresholds are set to 1.35V and 1.75V, approximately.
GPIO15 is connected to ground to supress output from ROM bootloader.
Average current drawn by the ESP32 in this example (with the default 4x averaging) depending on the measurement frequency is as follows:
Measurement frequency, Hz | Average current, uA
--------------------------|---------------------
10 | 8.5
50 | 20
100 | 37
In this example, the `CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP` Kconfig option is used, which allows you to reduce the boot time of the bootloader during waking up from deep sleep. The bootloader stores in rtc memory the address of a running partition and uses it when it wakes up. This example allows you to skip all image checks and speed up the boot.
## Example output
Below is the output from this example.
```
Not ULP wakeup
Entering deep sleep
Deep sleep wakeup
ULP did 1531 measurements
Thresholds: low=1500 high=2000
Value=973 was below threshold
Entering deep sleep
Deep sleep wakeup
ULP did 2 measurements
Thresholds: low=1500 high=2000
Value=0 was below threshold
Entering deep sleep
Deep sleep wakeup
ULP did 2 measurements
Thresholds: low=1500 high=2000
Value=0 was below threshold
Entering deep sleep
```

View File

@@ -0,0 +1,32 @@
from __future__ import unicode_literals
from tiny_test_fw import Utility
import re
import ttfw_idf
@ttfw_idf.idf_example_test(env_tag='Example_GENERIC')
def test_examples_ulp_adc(env, extra_data):
dut = env.get_dut('ulp_adc', 'examples/system/ulp_adc')
dut.start_app()
dut.expect_all('Not ULP wakeup',
'Entering deep sleep',
timeout=30)
for _ in range(5):
dut.expect('Deep sleep wakeup', timeout=60)
measurements_str = dut.expect(re.compile(r'ULP did (\d+) measurements'), timeout=5)[0]
assert measurements_str is not None
measurements = int(measurements_str)
Utility.console_log('ULP did {} measurements'.format(measurements))
dut.expect('Thresholds: low=1500 high=2000', timeout=5)
value_str = dut.expect(re.compile(r'Value=(\d+) was (above|below) threshold'), timeout=5)[0]
assert value_str is not None
value = int(value_str)
Utility.console_log('Value {} was outside the boundaries'.format(value))
dut.expect('Entering deep sleep', timeout=60)
if __name__ == '__main__':
test_examples_ulp_adc()

View File

@@ -0,0 +1,21 @@
idf_component_register(SRCS "ulp_adc_example_main.c"
INCLUDE_DIRS ""
REQUIRES soc nvs_flash ulp driver)
#
# ULP support additions to component CMakeLists.txt.
#
# 1. The ULP app name must be unique (if multiple components use ULP).
set(ulp_app_name ulp_${COMPONENT_NAME})
#
# 2. Specify all assembly source files.
# Files should be placed into a separate directory (in this case, ulp/),
# which should not be added to COMPONENT_SRCS.
set(ulp_s_sources "ulp/adc.S")
#
# 3. List all the component source files which include automatically
# generated ULP export file, ${ulp_app_name}.h:
set(ulp_exp_dep_srcs "ulp_adc_example_main.c")
#
# 4. Call function to build ULP binary and embed in project using the argument
# values above.
ulp_embed_binary(${ulp_app_name} "${ulp_s_sources}" "${ulp_exp_dep_srcs}")

View File

@@ -0,0 +1,23 @@
#
# ULP support additions to component makefile.
#
# 1. ULP_APP_NAME must be unique (if multiple components use ULP)
# Default value, override if necessary:
ULP_APP_NAME ?= ulp_$(COMPONENT_NAME)
#
# 2. Specify all assembly source files here.
# Files should be placed into a separate directory (in this case, ulp/),
# which should not be added to COMPONENT_SRCDIRS.
ULP_S_SOURCES = $(addprefix $(COMPONENT_PATH)/ulp/, \
adc.S \
)
#
# 3. List all the component object files which include automatically
# generated ULP export file, $(ULP_APP_NAME).h:
ULP_EXP_DEP_OBJECTS := ulp_adc_example_main.o
#
# 4. Include build rules for ULP program
include $(IDF_PATH)/components/ulp/component_ulp_common.mk
#
# End of ULP support additions to component makefile.
#

View File

@@ -0,0 +1,115 @@
/* ULP Example: using ADC in deep sleep
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
measures input voltage on the given ADC channel 'adc_oversampling_factor'
times. Measurements are accumulated and average value is calculated.
Average value is compared to the two thresholds: 'low_thr' and 'high_thr'.
If the value is less than 'low_thr' or more than 'high_thr', ULP wakes up
the chip 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/soc_ulp.h"
/* ADC1 channel 6, GPIO34 */
.set adc_channel, 6
/* 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)
/* Define variables, which go into .bss section (zero-initialized data) */
.bss
/* Low threshold of ADC reading.
Set by the main program. */
.global low_thr
low_thr:
.long 0
/* High threshold of ADC reading.
Set by the main program. */
.global high_thr
high_thr:
.long 0
/* Counter of measurements done */
.global sample_counter
sample_counter:
.long 0
.global last_result
last_result:
.long 0
/* Code goes into .text section */
.text
.global entry
entry:
/* increment sample counter */
move r3, sample_counter
ld r2, r3, 0
add r2, r2, 1
st r2, r3, 0
/* do measurements using ADC */
/* r0 will be used as accumulator */
move r0, 0
/* initialize the loop counter */
stage_rst
measure:
/* measure and add value to accumulator */
adc r1, 0, adc_channel + 1
add r0, r0, r1
/* increment loop counter and check exit condition */
stage_inc 1
jumps measure, adc_oversampling_factor, lt
/* divide accumulator by adc_oversampling_factor.
Since it is chosen as a power of two, use right shift */
rsh r0, r0, adc_oversampling_factor_log
/* averaged value is now in r0; store it into last_result */
move r3, last_result
st r0, r3, 0
/* compare with low_thr; wake up if value < low_thr */
move r3, low_thr
ld r3, r3, 0
sub r3, r0, r3
jump wake_up, ov
/* compare with high_thr; wake up if value > high_thr */
move r3, high_thr
ld r3, r3, 0
sub r3, r3, r0
jump wake_up, ov
/* value within range, end the program */
.global exit
exit:
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 exit, eq
/* Wake up the SoC, end program */
wake
WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
halt

View File

@@ -0,0 +1,100 @@
/* ULP Example
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.
*/
#include <stdio.h>
#include <string.h>
#include "esp_sleep.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "driver/gpio.h"
#include "driver/rtc_io.h"
#include "driver/adc.h"
#include "driver/dac.h"
#include "esp32/ulp.h"
#include "ulp_main.h"
extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end");
/* This function is called once after power-on reset, to load ULP program into
* RTC memory and configure the ADC.
*/
static void init_ulp_program(void);
/* This function is called every time before going into deep sleep.
* It starts the ULP program and resets measurement counter.
*/
static void start_ulp_program(void);
void app_main(void)
{
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
if (cause != ESP_SLEEP_WAKEUP_ULP) {
printf("Not ULP wakeup\n");
init_ulp_program();
} else {
printf("Deep sleep wakeup\n");
printf("ULP did %d measurements since last reset\n", ulp_sample_counter & UINT16_MAX);
printf("Thresholds: low=%d high=%d\n", ulp_low_thr, ulp_high_thr);
ulp_last_result &= UINT16_MAX;
printf("Value=%d was %s threshold\n", ulp_last_result,
ulp_last_result < ulp_low_thr ? "below" : "above");
}
printf("Entering deep sleep\n\n");
start_ulp_program();
ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() );
esp_deep_sleep_start();
}
static void init_ulp_program(void)
{
esp_err_t err = ulp_load_binary(0, ulp_main_bin_start,
(ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t));
ESP_ERROR_CHECK(err);
/* Configure ADC channel */
/* Note: when changing channel here, also change 'adc_channel' constant
in adc.S */
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_DB_11);
#if CONFIG_IDF_TARGET_ESP32
adc1_config_width(ADC_WIDTH_BIT_12);
#elif CONFIG_IDF_TARGET_ESP32S2
adc1_config_width(ADC_WIDTH_BIT_13);
#endif
adc1_ulp_enable();
/* Set low and high thresholds, approx. 1.35V - 1.75V*/
ulp_low_thr = 1500;
ulp_high_thr = 2000;
/* Set ULP wake up period to 20ms */
ulp_set_wakeup_period(0, 20000);
/* Disconnect GPIO12 and GPIO15 to remove current drain through
* pullup/pulldown resistors.
* GPIO12 may be pulled high to select flash voltage.
*/
rtc_gpio_isolate(GPIO_NUM_12);
rtc_gpio_isolate(GPIO_NUM_15);
#if CONFIG_IDF_TARGET_ESP32
esp_deep_sleep_disable_rom_logging(); // suppress boot messages
#endif
}
static void start_ulp_program(void)
{
/* Reset sample counter */
ulp_sample_counter = 0;
/* Start the program */
esp_err_t err = ulp_run(&ulp_entry - RTC_SLOW_MEM);
ESP_ERROR_CHECK(err);
}

View File

@@ -0,0 +1,9 @@
# Enable ULP
CONFIG_ESP32_ULP_COPROC_ENABLED=y
CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=1024
# Set log level to Warning to produce clean output
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
CONFIG_BOOTLOADER_LOG_LEVEL=2
CONFIG_LOG_DEFAULT_LEVEL_WARN=y
CONFIG_LOG_DEFAULT_LEVEL=2
CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y