🎛️ ADC رزبری پای پیکو با میکروپایتون: خواندن پتانسیومتر با read_u16 و تبدیل به ولتاژ
دنیای واقعی صفر و یک نیست: نور، دما، صدا و چرخش یک ولوم همه مقدارهای پیوستهاند. برای خواندن این مقدارها میکروکنترلر یک مبدل آنالوگ به دیجیتال (ADC) دارد. در این آموزش ADC پیکو را با میکروپایتون یاد میگیری: یک پتانسیومتر را با read_u16 میخوانیم، عددش را به ولتاژ و درصد تبدیل میکنیم، نویزش را با میانگینگیری صاف میکنیم و با آن نور یک LED را کنترل میکنیم.
ADC چه کار میکند؟
ADC ولتاژ یک پایه را اندازه میگیرد و یک عدد تحویل میدهد. در رزبری پای پیکو ولتاژ ۰ تا ۳٫۳ ولت به عددی بین ۰ تا ۴۰۹۵ تبدیل میشود (۱۲ بیت). میکروپایتون برای اینکه کدها روی همهی بردها یکسان باشند، این عدد را به بازهی ۰ تا ۶۵۵۳۵ میبرد و با read_u16() به تو میدهد. پس:
- ۰ ولت ← حدود ۰
- ۱٫۶۵ ولت (نصف) ← حدود ۳۲۷۶۸
- ۳٫۳ ولت ← حدود ۶۵۵۳۵
پیکو سه پایهی آنالوگ بیرونی دارد: GP26، GP27 و GP28. جای دقیقشان روی برد در پین اوت رزبری پای پیکو آمده.
پتانسیومتر چطور ولتاژ میسازد؟
پتانسیومتر (ولوم) یک مقاومت با سه پایه است. دو پایهی کناری به دو سر یک نوار مقاومتی وصلاند و پایهی وسط یک «جاروبک» است که روی نوار حرکت میکند. اگر یک سر را به ۳٫۳ ولت و سر دیگر را به زمین بدهی، پایهی وسط هر ولتاژی بین ۰ و ۳٫۳ را بسته به جای پیچ میدهد. این همان تقسیم ولتاژ است.
قطعهها و سیمکشی
- رزبری پای پیکو
- یک پتانسیومتر ۱۰ کیلواهم
- یک LED و یک مقاومت ۲۲۰ اهم
| قطعه | پایهی قطعه | پایهی پیکو |
|---|---|---|
| پتانسیومتر | پایهی کناری اول | 3V3(OUT)، پایهی فیزیکی ۳۶ |
| پتانسیومتر | پایهی وسط | GP26 / ADC0، پایهی فیزیکی ۳۱ |
| پتانسیومتر | پایهی کناری دوم | AGND، پایهی فیزیکی ۳۳ |
| LED | آند از راه ۲۲۰ اهم | GP15 |
| LED | کاتد | GND |
کد کامل میکروپایتون
from machine import Pin, ADC, PWM
import time
knob = ADC(26) # ADC0 on GP26 (physical pin 31)
led = PWM(Pin(15))
led.freq(1000)
VREF = 3.3 # the ADC reference on the Pico
def read_avg(adc, samples=8):
# average a few readings to calm the noise
total = 0
for i in range(samples):
total += adc.read_u16()
return total // samples
def map_range(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) // (in_max - in_min) + out_min
while True:
raw = read_avg(knob) # 0 .. 65535
volts = raw * VREF / 65535
percent = map_range(raw, 0, 65535, 0, 100)
led.duty_u16(raw) # knob -> brightness
print(f"raw={raw} volts={volts:.2f} percent={percent}")
time.sleep_ms(200)
توضیح خطهای مهم
ADC(26): ورودی آنالوگ روی GP26 را میسازد.ADC(0)هم همین است، چون GP26 کانال صفر است. GP27 کانال ۱ و GP28 کانال ۲.read_u16(): یک خوانش، عددی بین ۰ و ۶۵۵۳۵. خواندن خیلی سریع است (چند میکروثانیه)، پس میانگینگیری از ۸ خوانش هزینهای ندارد.read_avg: نویز را صاف میکند. هر خوانش تکی ممکن است چند ده واحد بالا و پایین برود؛ میانگین آرامتر است. اگر نوسان هنوز اذیتت میکند،samplesرا به ۱۶ یا ۳۲ برسان.raw * VREF / 65535: تبدیل عدد به ولتاژ. عدد ۳۲۷۶۸ یعنی حدود ۱٫۶۵ ولت.map_range: همانmap()آردوینو. هر بازه را به بازهی دیگر میبرد؛ اینجا به درصد، و در سروو با میکروپایتون به زاویهی ۰ تا ۱۸۰.led.duty_u16(raw): جالبترین خط! چون بازهی ADC و بازهی PWM هر دو ۰ تا ۶۵۵۳۵ است، عدد را مستقیم میدهیم و ولوم نور را کنترل میکند. توضیح PWM در PWM با میکروپایتون آمده.f"{volts:.2f}": ولتاژ را با دو رقم اعشار چاپ میکند.
چرا عدد دقیقاً به ۰ یا ۶۵۵۳۵ نمیرسد؟
ADC پیکو کامل نیست: کمی خطای صفر (offset) دارد، رگولاتور برد نویز اضافه میکند و خود پتانسیومتر هم در دو سر کمی مقاومت باقیمانده دارد. نتیجه این است که ولوم در کمترین حالت ممکن است ۳۰۰ یا ۵۰۰ بخواند، نه صفر. برای پروژههایی که باید واقعاً خاموش شوند، یک «ناحیهی مرده» بگذار:
from machine import ADC
import time
knob = ADC(26)
while True:
raw = knob.read_u16()
if raw < 1000:
raw = 0 # treat the bottom as a clean zero
elif raw > 64500:
raw = 65535 # and the top as a clean maximum
print(raw)
time.sleep_ms(100)
روی برد واقعی دو کار دیگر هم نویز را کم میکند: زمین پتانسیومتر را به AGND (پایهی ۳۳) بزن، و اول برنامه بنویس Pin(23, Pin.OUT, value=1) تا رگولاتور برد در حالت کمنویز (PWM) کار کند.
سنسورهای دیگر، همان کد
هر سنسوری که خروجیاش ولتاژ متغیر است با همین روش خوانده میشود: فتوسل LDR با یک مقاومت ۱۰ کیلو به شکل تقسیم ولتاژ، جویاستیک (دو پتانسیومتر روی GP26 و GP27)، سنسور رطوبت خاک و سنسور دمای آنالوگ. فقط ضریب تبدیل عدد به کمیت واقعی فرق میکند. پیکو یک سنسور دمای داخلی هم روی کانال ۴ دارد که با ADC(4) خوانده میشود و فرمولش 27 - (volts - 0.706) / 0.001721 است؛ این سنسور دمای خود تراشه را میدهد، نه اتاق را، و آن را روی برد واقعی امتحان کن.
مقایسه با آردوینو و ESP32
| برد | تابع | بازهی عدد | ولتاژ بیشینه |
|---|---|---|---|
| آردوینو Uno | analogRead(A0) | ۰ تا ۱۰۲۳ | ۵ ولت |
| ESP32 | analogRead(34) | ۰ تا ۴۰۹۵ | حدود ۳٫۳ ولت |
| رزبری پای پیکو | ADC(26).read_u16() | ۰ تا ۶۵۵۳۵ | ۳٫۳ ولت |
اگر با ESP32 هم کار میکنی، analogRead در ESP32 تفاوتها و دام ADC2 را توضیح میدهد.
اجرا در شبیهساز
در تینکرکد فارسی مثال آمادهی دیمر LED با MicroPython روی پیکو دقیقاً همین مدار را دارد: پتانسیومتر روی GP26 و LED روی GP15. پیچ ولوم را با ماوس بچرخان و عددها را در سریال مانیتور ببین. پیکو و میکروپایتون جزو اشتراک پلاس هستند؛ مثال برای خواندن رایگان باز میشود و برای اجرا پلاس لازم داری. همین مفهوم روی آردوینو رایگان است: درس سنسور آنالوگ.
اشکالهای رایج
- عدد همیشه حدود ۶۵۵۳۵ یا همیشه صفر است: پایهی وسط پتانسیومتر را به GP26 نزدهای؛ احتمالاً یکی از پایههای کناری وصل است.
- عدد بیمعنی و پرنوسان است: زمین پتانسیومتر وصل نیست و ورودی «شناور» مانده.
- ValueError: invalid pin: پایهای غیر از GP26 تا GP28 را به
ADCدادهای. - جهت چرخش برعکس است: دو پایهی کناری را جابهجا کن، یا در کد بنویس
65535 - raw. - ولتاژ محاسبهشده کمی با مولتیمتر فرق دارد: مرجع واقعی دقیقاً ۳٫۳۰ نیست؛
VREFرا با ولتاژی که مولتیمتر روی 3V3 نشان میدهد تنظیم کن.
حالا که هم ورودی آنالوگ و هم خروجی PWM را بلدی، سراغ کنترل سروو با پتانسیومتر برو. اگر هنوز با پایههای زبان راحت نیستی، آموزش میکروپایتون از صفر را مرور کن. همهی آموزشهای پیکو در بخش رزبری پای پیکو هستند.
ولوم و LED را روی پیکو امتحان کن 🎛️سؤالهای رایج
چرا read_u16 تا ۶۵۵۳۵ میرود وقتی ADC پیکو ۱۲ بیتی است؟
میکروپایتون همهی بردها را یکدست کرده و عدد ADC را به بازهی ۱۶ بیتی میبرد. ADC پیکو در واقع ۰ تا ۴۰۹۵ میخواند و میکروپایتون آن را ضرب در حدود ۱۶ میکند. پس کد تو روی بردهای دیگر هم بدون تغییر کار میکند.
کدام پایههای پیکو آنالوگ هستند؟
سه پایه: GP26 (ADC0، پایهی فیزیکی ۳۱)، GP27 (ADC1، پایهی ۳۲) و GP28 (ADC2، پایهی ۳۴). ADC(26) و ADC(0) هر دو همان GP26 را میخوانند.
چرا عدد ADC حتی وقتی ولوم را تکان نمیدهم کمی بالا و پایین میرود؟
نویز طبیعی است. چند خوانش را میانگین بگیر، زمین پتانسیومتر را به AGND (پایهی ۳۳) وصل کن و روی برد واقعی با Pin(23, Pin.OUT, value=1) رگولاتور را در حالت کمنویز بگذار.
مقالههای مرتبط
سروو موتور با میکروپایتون روی رزبری پای پیکو: PWM پنجاه هرتز و کنترل زاویه
سنسور اولتراسونیک HC-SR04 با میکروپایتون روی رزبری پای پیکو (time_pulse_us)
راهاندازی LCD I2C با میکروپایتون روی رزبری پای پیکو (درایور i2c_lcd)
سنسور دما و رطوبت DHT22 و DHT11 با آردوینو: سیمکشی، کد کامل و ترموستات کوچک
همهی آموزشهای رزبری پای پیکو و میکروپایتون ← · همهی مقالهها