🎛️ ADC رزبری پای پیکو با میکروپایتون: خواندن پتانسیومتر با read_u16 و تبدیل به ولتاژ

✍️ تیم ووکوی فارسی ·

دنیای واقعی صفر و یک نیست: نور، دما، صدا و چرخش یک ولوم همه مقدارهای پیوسته‌اند. برای خواندن این مقدارها میکروکنترلر یک مبدل آنالوگ به دیجیتال (ADC) دارد. در این آموزش ADC پیکو را با میکروپایتون یاد می‌گیری: یک پتانسیومتر را با read_u16 می‌خوانیم، عددش را به ولتاژ و درصد تبدیل می‌کنیم، نویزش را با میانگین‌گیری صاف می‌کنیم و با آن نور یک LED را کنترل می‌کنیم.

ADC چه کار می‌کند؟

ADC ولتاژ یک پایه را اندازه می‌گیرد و یک عدد تحویل می‌دهد. در رزبری پای پیکو ولتاژ ۰ تا ۳٫۳ ولت به عددی بین ۰ تا ۴۰۹۵ تبدیل می‌شود (۱۲ بیت). میکروپایتون برای اینکه کدها روی همه‌ی بردها یکسان باشند، این عدد را به بازه‌ی ۰ تا ۶۵۵۳۵ می‌برد و با read_u16() به تو می‌دهد. پس:

پیکو سه پایه‌ی آنالوگ بیرونی دارد: GP26، GP27 و GP28. جای دقیقشان روی برد در پین اوت رزبری پای پیکو آمده.

پتانسیومتر چطور ولتاژ می‌سازد؟

پتانسیومتر (ولوم) یک مقاومت با سه پایه است. دو پایه‌ی کناری به دو سر یک نوار مقاومتی وصل‌اند و پایه‌ی وسط یک «جاروبک» است که روی نوار حرکت می‌کند. اگر یک سر را به ۳٫۳ ولت و سر دیگر را به زمین بدهی، پایه‌ی وسط هر ولتاژی بین ۰ و ۳٫۳ را بسته به جای پیچ می‌دهد. این همان تقسیم ولتاژ است.

قطعه‌ها و سیم‌کشی

قطعهپایه‌ی قطعهپایه‌ی پیکو
پتانسیومترپایه‌ی کناری اول3V3(OUT)، پایه‌ی فیزیکی ۳۶
پتانسیومترپایه‌ی وسطGP26 / ADC0، پایه‌ی فیزیکی ۳۱
پتانسیومترپایه‌ی کناری دومAGND، پایه‌ی فیزیکی ۳۳
LEDآند از راه ۲۲۰ اهمGP15
LEDکاتدGND
پتانسیومتر را هرگز به VBUS یا VSYS نزن. ورودی ADC بیشتر از ۳٫۳ ولت را تحمل نمی‌کند. برای اندازه‌گیری ولتاژهای بالاتر (مثلاً باتری ۹ ولت) اول با دو مقاومت ولتاژ را پایین بیاور؛ ماشین‌حساب تقسیم ولتاژ مقاومت‌ها را حساب می‌کند.

کد کامل میکروپایتون

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 پیکو کامل نیست: کمی خطای صفر (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

بردتابعبازه‌ی عددولتاژ بیشینه
آردوینو UnoanalogRead(A0)۰ تا ۱۰۲۳۵ ولت
ESP32analogRead(34)۰ تا ۴۰۹۵حدود ۳٫۳ ولت
رزبری پای پیکوADC(26).read_u16()۰ تا ۶۵۵۳۵۳٫۳ ولت

اگر با ESP32 هم کار می‌کنی، analogRead در ESP32 تفاوت‌ها و دام ADC2 را توضیح می‌دهد.

اجرا در شبیه‌ساز

در تینکرکد فارسی مثال آماده‌ی دیمر LED با MicroPython روی پیکو دقیقاً همین مدار را دارد: پتانسیومتر روی GP26 و LED روی GP15. پیچ ولوم را با ماوس بچرخان و عددها را در سریال مانیتور ببین. پیکو و میکروپایتون جزو اشتراک پلاس هستند؛ مثال برای خواندن رایگان باز می‌شود و برای اجرا پلاس لازم داری. همین مفهوم روی آردوینو رایگان است: درس سنسور آنالوگ.

اشکال‌های رایج

حالا که هم ورودی آنالوگ و هم خروجی 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 با آردوینو: سیم‌کشی، کد کامل و ترموستات کوچک

همه‌ی آموزش‌های رزبری پای پیکو و میکروپایتون ← · همه‌ی مقاله‌ها