我正在尝试使用ULP检测ESP32内部霍尔效应传感器读数的变化。
我尝试为ULP编写一些程序集,以从ADC获得4个样本,将它们相加,然后与上一个循环的总和进行比较。如果差异大于宏值(DELTA
),则循环结束,CPU唤醒。
到目前为止,这是我的代码:
#include "esp32/ulp.h"
#include "soc/rtc_cntl_reg.h"
#include "driver/rtc_io.h"
#include "driver/adc.h"
#define DELTA 10
void ulp_adc() {
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_11);
adc1_config_width(ADC_WIDTH_BIT_10);
adc1_ulp_enable();
rtc_gpio_init(GPIO_NUM_36);
const ulp_insn_t program[] = { //R0: LOOP HANLDER AND CONDITIONALS R1: NEW VALUE R2: PREVIOUS VALUE R3: ADC BUFFER
// SETUP
I_DELAY(32000), // Wait until ESP32 goes to deep sleep
//WE NEED TO INITIALIZE THE "PREVIOUS" VALUE TO A FIRST MULTISAMPLE
I_MOVI(R1, 0), // INITIALIZE R2 TO 0
I_MOVI(R0, 0), // INITIALIZE LOOP COUNTER (R0) TO 0
M_LABEL(1), // LABEL 1: INITIAL MULTISAMPLE LOOP
I_ADC(R3, 0, 0), // ADC READ TO R3 (TEMP BUFFER)
I_ADDI(R1, R1, R3), // ADD ADC (R3) TO TOTAL (R1)
I_ADDI(R0, R0, 1), // COUNTER++
M_BL(1, 4), // JUMP BACK TO LABEL 1 UNLESS COUNTER>4
// MAIN LOOP
M_LABEL(2), // LABEL 2: ADC SAMPLE LOOP SETUP
I_MOVI(R2, R1), // SET R2 (OLD SAMPLE) TO R1 ("NEW" VALUE)
I_MOVI(R1, 0), // SET R1 (NEW SAMPLE) TO 0 (TO PREP FOR ACCUMULATION)
I_MOVI(R0, 0), // INITIALIZE LOOP COUNTER (R0) TO 0
//BEGIN MULTISAMPLING
M_LABEL(3), // LABEL 3: ADC MULTISAMPLE LOOP
I_ADC(R3, 0, 0), // ADC READ TO R3 (TEMP BUFFER)
I_ADDI(R1, R1, R3), // ADD ADC (R3) TO TOTAL (R1)
I_ADDI(R0, R0, 1), // COUNTER++
M_BL(3, 4), // JUMP BACK TO LABEL 3 UNLESS COUNTER>4
//AT THIS POINT R1 IS THE SUM OF 4 ADC SAMPLES
I_SUBI(R0, R1, R2), // GET DIFFERENCE FROM NEW SUM AND LAST AND STORE IN R0 FOR CONDITIONALS
M_BGE(4, 0), // JUMP OVER THE INVERSION TO LABEL 4 IF WE ALREADY HAVE A POSITIVE VALUE
I_SUBI(R0, 0, R0), // R0 = 0 - R0
M_LABEL(4), // WE HAVE A POSITIVE VALUE, READY FOR COMPARISON
I_DELAY(1300000), // WAIT A LITTLE UNDER 1S, SO THAT EACH SAMPLE IS FAR ENOUGH AWAY FOR A DELTA TO MATTER
M_BL(2, DELTA), // JUMP BACK TO THE START IF WE ARE BELOW THE TARGET DELTA
// END PROGRAM, WAKE MAIN CPU
I_WAKE(), // Wake up ESP32
I_END(), // Stop ULP program timer
I_HALT() // Halt the coprocessor
};
size_t size = sizeof(program)/sizeof(ulp_insn_t);
ulp_process_macros_and_load(0, program, &size);
ulp_run(0);
esp_sleep_enable_ulp_wakeup();
esp_deep_sleep_start();
}
void setup() {
Serial.begin(115200);
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_11);
adc1_config_width(ADC_WIDTH_BIT_10);
Serial.println(adc1_get_raw(ADC1_CHANNEL_0));
}
void loop() {
ulp_adc();
}
将DELTA
设置为10会导致CPU立即唤醒,而与附近的磁体无关,而将其设置为11则会阻止CPU唤醒,即使钕磁体突然施加在ESP32的屏蔽层上也是如此。调整衰减或位深度无法解决此问题。