ESP32 - ULP 協處理器在低功耗模式下讀片内霍爾傳感器 HALL SENSOR
本文提供了 ESP32 - ULP 協處理器如何在低功耗模式下讀片内霍爾傳感器的例子
1. 霍爾傳感器
根據霍爾效應,當電流垂直于磁場通過 N 型半導體時,會在垂直于電流和磁場的方向産生附加電場,進而在半導體兩端形成電勢差,具體高低與電磁場的強度和電流大小有關。當恒定電流穿過磁場或電流存在于恒定磁場時,霍爾效應傳感器可用于測量磁場強度。霍爾傳感器的應用場合非常廣泛,包括接近探測、定位、測速與電流檢測等。
2. 霍爾傳感器讀取示例
本例子 ULP 協處理器每隔 3 S 喚醒一次,喚醒後在低功耗模式下讀取霍爾傳感器值, 通過 hall phase shift 兩次,讀取 vp 和 vn 值 各兩次一共四個值,減去共模的部分可以得出 offset 值,這個值可以用來表征環境對霍爾傳感器的影響。如圖,第一次列印的數值是周圍未有強磁場的情況下測得的霍爾傳感器數值;第二次列印的數值是使用了一枚钕鐵硼磁鐵的 N 極接近 ESP32 時擷取的數值;第三次列印的數值是钕鐵硼磁鐵的 S 極接近 ESP32 時擷取的數值,可以看出霍爾傳感器的數值發生了較大的變化。
3. 系統連接配接
HALL SENSOR 和 SAR ADC 連接配接情況見下圖,HALL SENSOR 的 SENSOR_VP 和 SENSOR_VN 管腳分别連接配接到 SAR ADC1 的 SAR_MUX = 1 和 SAR_MUX = 4 上。
下表是 SAR ADC1 的輸入信号及 SAR_MUX 通道
信号名/GPIO | SAR_ADC1,SAR_MUX |
---|---|
SENSOR_VP (GPIO36) | 1 |
SENSOR_CAPP (GPIO37) | 2 |
SENSOR_CAPN (GPIO38) | 3 |
SENSOR_VN (GPIO39) | 4 |
32K_XP (GPIO33) | 5 |
32K_XN (GPIO32) | 6 |
VDET_1 (GPIO34) | 7 |
VDET_2 (GPIO35) | 8 |
4. 編譯配置及燒錄程式
ESP32 的 C 語言編譯環境安裝和配置參照 連結位址,另外 ULP 協處理器目前隻支援彙編程式設計,是以還需要安裝彙編工具鍊,下面介紹彙編工具鍊的安裝和配置。
4.1 彙編環境的配置
ULP 協處理器配置彙編編譯工具鍊,隻需兩步即可安裝配置完畢,下面給出 ubuntu 作業系統下配置的步驟,或者點選 連結位址 獲得更多 ULP 程式設計資訊
- 第一步, 下載下傳工具鍊
連結位址, 解壓到需要安裝的目錄
binutils-esp32ulp toolchain
- 第二步,添加工具鍊的
目錄到系統環境變量
bin
中。例如我的解壓目錄是
PATH
那麼添加
/opt/esp32ulp-elf-binutils
這一行到 /home 目錄的隐藏檔案
export PATH=/opt/esp32ulp-elf-binutils/bin:$PATH
檔案最後一行,儲存關閉檔案并使用指令
.bashrc
使上述環境變量生效
source .bashrc
4.2 配置編譯燒錄
至此,彙編編譯環境就安裝好了,在 esp-iot-solution /examples/ulp_hall_sensor/ 目錄下依次運作以下指令,進行 default config 配置并編譯、燒錄程式。
- make defconfig
- make all -j8 && make flash monitor
5. 軟體分析
ULP 協處理器沒有内置讀霍爾傳感器相關的彙編指令,是以我們需要設定相關寄存器來讀取片内霍爾傳感器。
在
void init_ulp_program()
函數中設定 ADC1 通道 1/2 輸入電壓衰減,使用者可以自己定義這個衰減值,較大的衰減将得到較小的 ADC 值。
/* The ADC1 channel 0 input voltage will be reduced to about 1/2 */
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_6);
/* The ADC1 channel 3 input voltage will be reduced to about 1/2 */
adc1_config_channel_atten(ADC1_CHANNEL_3, ADC_ATTEN_DB_6);
/* ADC capture 12Bit width */
adc1_config_width(ADC_WIDTH_BIT_12);
/* enable adc1 */
adc1_ulp_enable();
在超低功耗模式下,需要預先設定相關的寄存器之後才可以通過 SAR ADC1 來讀取 HALL SENSOR 值。
/* SENS_XPD_HALL_FORCE = 1, hall sensor force enable, XPD HALL is controlled by SW */
WRITE_RTC_REG(SENS_SAR_TOUCH_CTRL1_REG, SENS_XPD_HALL_FORCE_S, 1, 1)
/* RTC_IO_XPD_HALL = 1, xpd hall, Power on hall sensor and connect to VP and VN */
WRITE_RTC_REG(RTC_IO_HALL_SENS_REG, RTC_IO_XPD_HALL_S, 1, 1)
/* SENS_HALL_PHASE_FORCE = 1, phase force, HALL PHASE is controlled by SW */
WRITE_RTC_REG(SENS_SAR_TOUCH_CTRL1_REG, SENS_HALL_PHASE_FORCE_S, 1, 1)
/* RTC_IO_HALL_PHASE = 0, phase of hall sensor */
WRITE_RTC_REG(RTC_IO_HALL_SENS_REG, RTC_IO_HALL_PHASE_S, 1, 0)
/* SENS_FORCE_XPD_SAR, Force power up */
WRITE_RTC_REG(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR_S, 2, SENS_FORCE_XPD_SAR_PU)
之後,使用
ADC
指令多次讀取片内霍爾傳感器 phase_vp 和 phase_vn 的值,累加并計算平均值後,将霍爾傳感器值儲存到
Sens_Vp0
,
Sens_Vn0
這兩變量中。
/* do measurements using ADC */
/* r2, r3 will be used as accumulator */
move r2, 0
move r3, 0
/* initialize the loop counter */
stage_rst
measure0:
/* measure Sar_Mux = 1 to get vp0 */
adc r0, 0, 1
add r2, r2, r0
/* measure Sar_Mux = 4 to get vn0 */
adc r1, 0, 4
add r3, r3, r1
/* increment loop counter and check exit condition */
stage_inc 1
jumps measure0, adc_oversampling_factor, lt
/* divide accumulator by adc_oversampling_factor.
Since it is chosen as a power of two, use right shift */
rsh r2, r2, adc_oversampling_factor_log
/* averaged value is now in r2; store it into Sens_Vp0 */
move r0, Sens_Vp0
st r2, r0, 0
/* r3 divide 4 which means rsh 2 bits */
rsh r3, r3, adc_oversampling_factor_log
/* averaged value is now in r3; store it into Sens_Vn0 */
move r1, Sens_Vn0
st r3, r1, 0
接下來,需要 shift 霍爾傳感器的 phase,設定寄存器
RTC_IO_HALL_SENS_REG
的
RTC_IO_HALL_PHASE
位置 1 , 并再次讀取片内霍爾傳感器 phase_vp 和 phase_vn 的值,同上,累加并計算平均值後,儲存到
Sens_Vp1
,
Sens_Vn1
中。
/* RTC_IO_HALL_PHASE = 1, phase of hall sensor */
WRITE_RTC_REG(RTC_IO_HALL_SENS_REG, RTC_IO_HALL_PHASE_S, 1, 1)
最後,在喚醒主 CPU 後,通過以上四個數值計算出 offset 的值并列印出來。
static void print_hall_sensor()
{
printf("ulp_hall_sensor:Sens_Vp0:%d,Sens_Vn0:%d,Sens_Vp1:%d,Sens_Vn1:%d\r\n",
(uint16_t)ulp_Sens_Vp0,(uint16_t)ulp_Sens_Vn0,(uint16_t)ulp_Sens_Vp1,(uint16_t)ulp_Sens_Vn1);
printf("offset:%d\r\n", ((uint16_t)ulp_Sens_Vp0 - (uint16_t)ulp_Sens_Vp1) - ((uint16_t)ulp_Sens_Vn0 - (uint16_t)ulp_Sens_Vn1));
}
6. 總結
ESP32 中的霍爾傳感器經過專門設計,可向低噪放大器和 SAR ADC 提供電壓信号,實作磁場傳感功能。在超低功耗模式下,該傳感器可由 ULP 協處理器控制。ESP32 内置了霍爾傳感器在位置傳感、接近檢測、測速以及電流檢測等應用場景下成為一種極具吸引力的解決方案。
7. 參考文檔
- esp32_technical_reference_manual_cn.pdf 文檔的 27.5 霍爾傳感器
- esp32_technical_reference_manual_cn.pdf 文檔的 27.3 逐次逼近數字模拟轉換器