Я пытаюсь обнаружить изменения в показаниях внутреннего датчика Холла ESP32 с использованием ULP.
Я попытался написать некоторую сборку для ULP, чтобы получить 4 образца из АЦП, добавить ихи сравните с суммой предыдущего цикла.Если разница больше, чем значение макроса (DELTA
), цикл заканчивается, и процессор просыпается.
Вот мой код:
#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 заставляет ЦП мгновенно просыпаться независимо от соседних магнитов, а установка на 11 предотвращает пробуждение ЦП, даже когда неодимовый магнит внезапно прикладывается к экранированию ESP32.Регулировка затухания или битовой глубины не смогла это исправить.