本文提供了 ESP32 - ULP 協(xié)處理器如何在低功耗模式下讀片內(nèi)霍爾傳感器的例子
1. 霍爾傳感器
根據(jù)霍爾效應(yīng),當(dāng)電流垂直于磁場通過 N 型半導(dǎo)體時(shí),會(huì)在垂直于電流和磁場的方向產(chǎn)生附加電場,從而在半導(dǎo)體兩端形成電勢差,具體高低與電磁場的強(qiáng)度和電流大小有關(guān)。當(dāng)恒定電流穿過磁場或電流存在于恒定磁場時(shí),霍爾效應(yīng)傳感器可用于測量磁場強(qiáng)度。霍爾傳感器的應(yīng)用場合非常廣泛,包括接近探測、定位、測速與電流檢測等。
2. 霍爾傳感器讀取示例
本例子 ULP 協(xié)處理器每隔 3 S 喚醒一次,喚醒后在低功耗模式下讀取霍爾傳感器值, 通過 hall phase shift 兩次,讀取 vp 和 vn 值 各兩次一共四個(gè)值,減去共模的部分可以得出 offset 值,這個(gè)值可以用來表征環(huán)境對霍爾傳感器的影響。如圖,第一次打印的數(shù)值是周圍未有強(qiáng)磁場的情況下測得的霍爾傳感器數(shù)值;第二次打印的數(shù)值是使用了一枚釹鐵硼磁鐵的 N 極接近 ESP32 時(shí)獲取的數(shù)值;第三次打印的數(shù)值是釹鐵硼磁鐵的 S 極接近 ESP32 時(shí)獲取的數(shù)值,可以看出霍爾傳感器的數(shù)值發(fā)生了較大的變化。
3. 系統(tǒng)連接
HALL SENSOR 和 SAR ADC 連接情況見下圖,HALL SENSOR 的 SENSOR_VP 和 SENSOR_VN 管腳分別連接到 SAR ADC1 的 SAR_MUX = 1 和 SAR_MUX = 4 上。
下表是 SAR ADC1 的輸入信號(hào)及 SAR_MUX 通道
信號(hào)名/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 語言編譯環(huán)境安裝和配置參照 鏈接地址,另外 ULP 協(xié)處理器目前只支持匯編編程,所以還需要安裝匯編工具鏈,下面介紹匯編工具鏈的安裝和配置。
4.1 匯編環(huán)境的配置
ULP 協(xié)處理器配置匯編編譯工具鏈,只需兩步即可安裝配置完畢,下面給出 ubuntu 操作系統(tǒng)下配置的步驟,或者點(diǎn)擊 鏈接地址 獲得更多 ULP 編程信息
第一步, 下載工具鏈 binutils-esp32ulp toolchain 鏈接地址, 解壓到需要安裝的目錄
第二步,添加工具鏈的 bin 目錄到系統(tǒng)環(huán)境變量 PATH 中。例如我的解壓目錄是 /opt/esp32ulp-elf-binutils 那么添加 export PATH=/opt/esp32ulp-elf-binutils/bin:$PATH 這一行到 /home 目錄的隱藏文件 .bashrc 文件最后一行,保存關(guān)閉文件并使用命令 source .bashrc 使上述環(huán)境變量生效
4.2 配置編譯燒錄
至此,匯編編譯環(huán)境就安裝好了,在 esp-iot-solution /examples/ulp_hall_sensor/ 目錄下依次運(yùn)行以下命令,進(jìn)行 default config 配置并編譯、燒錄程序。
make defconfig
make all -j8 && make flash monitor
5. 軟件分析
ULP 協(xié)處理器沒有內(nèi)置讀霍爾傳感器相關(guān)的匯編指令,所以我們需要設(shè)置相關(guān)寄存器來讀取片內(nèi)霍爾傳感器。
在 void init_ulp_program() 函數(shù)中設(shè)置 ADC1 通道 1/2 輸入電壓衰減,用戶可以自己定義這個(gè)衰減值,較大的衰減將得到較小的 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
在超低功耗模式下,需要預(yù)先設(shè)置相關(guān)的寄存器之后才可以通過 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 指令多次讀取片內(nèi)霍爾傳感器 phase_vp 和 phase_vn 的值,累加并計(jì)算平均值后,將霍爾傳感器值保存到 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,設(shè)置寄存器 RTC_IO_HALL_SENS_REG 的 RTC_IO_HALL_PHASE 位置 1 , 并再次讀取片內(nèi)霍爾傳感器 phase_vp 和 phase_vn 的值,同上,累加并計(jì)算平均值后,保存到 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 后,通過以上四個(gè)數(shù)值計(jì)算出 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. 總結(jié)
ESP32 中的霍爾傳感器經(jīng)過專門設(shè)計(jì),可向低噪放大器和 SAR ADC 提供電壓信號(hào),實(shí)現(xiàn)磁場傳感功能。在超低功耗模式下,該傳感器可由 ULP 協(xié)處理器控制。ESP32 內(nèi)置了霍爾傳感器在位置傳感、接近檢測、測速以及電流檢測等應(yīng)用場景下成為一種極具吸引力的解決方案。