ADC 模數轉換器¶
概要¶
本文講解了ADC的概念,以及MicroPython-ESP32中的ADC實現, 最后在綜合例程里面,使用ADC采集點位計的數值,然后通過PWM控制LED的亮度。
keywords ADC Encoder PWM LED sample
ADC是什么¶
ADC的英文全稱是Analog / Digital Converter,是將模擬信號轉換為數字信號的轉換器,ADC是單片機讀取傳感器信號的常見方式。
在GPIO輸出與控制LED亮滅這一章里面,我們知道了數字信號與模擬信號之間的區別。 我們日常生活中的信號,例如光照強度,聲波,電池電壓 這些都是模擬值。 如果我們想通過單片機對模擬信號(電壓,光照強度,聲波)進行測量,用數字信號進行表達,這個時候我們就需要ADC 模擬數字信號轉換器。
ADC-常用API¶
硬件資源¶
在ESP32里面ADC一共有兩組,分為ADC 1
還有ADC 2
, 其中又因為ESP32的ADC2
不能與WIFI聯網同時存在,當連接WIFI的時候ADC 2
的管腳就不能進行ADC采樣,所以MicroPython-ESP32固件里面,并沒有實現對ADC 2的支持,大家看引腳圖的時候留意一下這個問題。
NodeMCU-32S的32-39
管腳具備ADC功能:
GPIO編號 | ADC編號 | 通道編號 |
---|---|---|
39 | 1 | 3 |
36 | 1 | 0 |
35 | 1 | 7 |
33 | 1 | 5 |
34 | 1 | 6 |
32 | 1 | 4 |
為了方便大家和實際的管腳布局進行比對,我們1Z實驗室為大家制作了下圖:
此圖待ZR PS
實例化¶
從machine
模塊里面導入兩個類 Pin
還有ADC
from machine import Pin,ADC
第一步還是創建一個Pin
的對象:
adc_pin = Pin(34)
解下來創建一個ADC的對象,直接把pin對象傳入到ADC的構造器里面。
adc = ADC(adc_pin)
設置衰減比¶
衰減器在功能上和放大器相反,放大器提供大于1的增益,衰減器提供小于1的增益。原理上衰減器由簡單的分壓電路組成。
ADC采樣有兩個重要的參數,一個是滿量程電壓是多少,顯然不可能超過ESP32的管腳電壓3.3v. 可以設定0-3.3v之間的一個值。
宏定義 | 數值 | 滿量程電壓 |
---|---|---|
ADC.ATTN_0DB | 0 | 1.2v |
ADC.ATTN_2_5DB | 1 | 1.5v |
ADC.ATTN_6DB | 2 | 2.0v |
ADC.ATTN_11DB | 3 | 3.3v |
演示樣例:
adc.atten(ADC.ATTN_11DB)
設置分辨率¶
ADC的分辨率是指能夠將采集的模擬信號轉化為數字信號的精度,通常我們用“位”來表述,比如8位就是指ADC可以將制定量程內的電壓信號,分別對應到0 - 2^8-1,即 0-255這256個數字上。分辨率位數越高,能夠表示的也就越精確,信息丟失的也就越少。
再舉個例子,如果分辨率是10位,那么ADC采樣的取值范圍就是0 - 1023
.
1023 = 2^10 - 1
宏定義 | 數值 | 分辨率 |
---|---|---|
ADC.WIDTH_9BIT | 0 | 9 |
ADC.WIDTH_10BIT | 1 | 10 |
ADC.WIDTH_11BIT | 2 | 11 |
ADC.WIDTH_12BIT | 3 | 12 |
ADC采樣¶
使用read
函數進行ADC采樣
adc.read()
ADC采集電位計的數據¶
如圖便是一個簡單的電位計。
注意¶
這種電位計很多都有上下兩排引腳,按照上圖所標注的,選擇一排接線即可
將電位計的OUT管腳與ESP32的34號引腳相連。以下是筆者為大家畫出的面包板接線圖:
按照上面的接線,我們編寫如下的代碼配置好一個ADC:
from machine import ADC,Pin import utime adc = ADC(Pin(34)) # 聲明ADC對象 設置D34號引腳作為ADC采樣引腳 adc.atten(ADC.ATTN_11DB) # 設置衰減比 滿量程3.3v adc.width(ADC.WIDTH_10BIT) # 設置數據寬度為10bit
運行以上的代碼,我們便可以使用read()
函數來讀取電位計的數值了,你可以試著轉動你的電位計到某一個位置,看看讀數:
你是不是也發現了,盡管你沒有碰電位計了,但是每次的ADC采樣,得到的讀數都不一樣。在模擬信號轉化為數字信號的過程中,會存在諸多的因素導致信號中可能存在噪聲,使得結果帶有一定的誤差,因此我們需要一些方法或手段來減小這種誤差對我們帶來的負面作用,接下來就為大家介紹最樸素的均值濾波。
ADC采樣均值濾波¶
檢測ADC采樣值是否發生變化,如果發生變化就打印出來, 采用均值濾波對噪聲進行過濾。 所謂均值濾波就是多次采集數據然后求取平均值。
原理如此簡單,那我們就嘗試著寫一個均值濾波的函數吧
def adc_mean(adc, sample_times): # 注意,這行代碼很不適合給Python新手觀看(屬于Python裝逼炫技) # 因為普通的循環累加再求平均,誰都會寫 # 所以筆者在這里使用Python的列表推倒式來完成這些事 return int(sum([adc.read() for i in range(sample_times)])/sample_times)
簡單的解釋:
-
sum()
函數,用于求和,可以接受列表作為參數, 返回求和之后的值 -
[adc.read() for i in range(sample_times)]
這時Python的列表推倒式
,返回一個列表,列表中的元素為10次循環中每次adc讀取的值。
挑戰:電位計控制LED亮度¶
現在你已經學習完了定時器,延時函數以及最基本的ESP32的GPIO控制,PWM等內容,為什么不嘗試嘗試使用電位計來控制控制LED燈的亮度呢?