本文提供了 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 通道
信號名/GPIOSAR_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 那么添加 export PATH=/opt/esp32ulp-elf-binutils/bin:$PATH 這一行到 /home 目錄的隱藏文件 .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(); 12345678
在超低功耗模式下,需要預先設置相關的寄存器之后才可以通過 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)1234567891011121314
之后,使用 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, 01234567891011121314151617181920212223242526272829303132
接下來,需要 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)12
最后,在喚醒主 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));
}123456
6. 總結
ESP32 中的霍爾傳感器經過專門設計,可向低噪放大器和 SAR ADC 提供電壓信號,實現磁場傳感功能。在超低功耗模式下,該傳感器可由 ULP 協處理器控制。ESP32 內置了霍爾傳感器在位置傳感、接近檢測、測速以及電流檢測等應用場景下成為一種極具吸引力的解決方案。