תכנות מיקרו-בקרים בשפת MicroPython · פרק 6 — קלט אנלוגי⌂📚🏠
פרק 6

קלט אנלוגי

Analog Input (ADC)
6 שעות לימוד

כניסה ספרתית מכירה שני מצבים בלבד: 0 או 1. אבל העולם לא מדבר כך: טמפרטורה, אור ומיקום של ידית הם גדלים שמשתנים ברציפות, והחיישן מתרגם אותם למתח. בפרק הזה נקרא את המתח הזה בשלושה לוחות, ונגלה שההבדל ביניהם גדול ממה שנראה: אחד דורש כיוון, השני לא, ולשלישי אין ממיר בכלל.

בפרק הזה:
  • נחשב את הרזולוציה q ממספר הסיביות וממתח הייחוס.
  • נקרא פוטנציומטר ב-ESP32 וב-Pico W, ונבין למה אותה תוכנית נכשלת כשמעבירים אותה כמות שהיא.
  • נכתוב תוכנית אחת שעובדת בשני הלוחות בעזרת הקובץ board.py.
  • נמיר את הקריאה למתח, לאחוזים ולהתנגדות, ונפחית רעש בעזרת מיצוע.
  • נחבר את הממיר החיצוני ADS1115, הדרך היחידה לקלט אנלוגי ב-Raspberry Pi 4/5.

6.1 ממתח למספר (Analog to Digital)

התוכנית מבינה רק מספרים. לכן יש בתוך הבקר ממיר, שמודד את המתח בהדק ושומר את התוצאה באוגר, ומשם התוכנית קוראת אותה.

ממיר אנלוגי לספרתי (ממיר A/D): מעגל שממיר מתח שבין אפס למתח הייחוס למספר שלם. שמו באנגלית ADC.
חיישןמתח משתנההממירמתח ← מספראוגרמספר שלםהתוכניתread_u16()
הדרך מן החיישן אל התוכנית.

המספר שמתקבל תמיד שלם, ולכן הממיר אינו רואה את כל המתחים: הוא מחלק את התחום למדרגות שוות, וכל מתח בתוך אותה מדרגה נותן אותו מספר. הסרטוט הבא מראה זאת בממיר קטן של 3 סיביות, שיש לו 8 מדרגות בלבד. הקו המקווקו הוא התשובה שהיינו רוצים, והמדרגות הן מה שמתקבל. ההפרש ביניהם נקרא שגיאת קוונטיזציה.

123456781234567VinN
ממיר של 3 סיביות: הציר האופקי ביחידות של מדרגה q, והציר האנכי הוא המספר N.

6.2 רזולוציה, מתח ייחוס וזמן המרה (Resolution, Reference, Conversion Time)

שלושה גדלים מתארים כל ממיר:

רזולוציה: גודל של מדרגה אחת
q = Vref2n
סמלפירושיחידה
qהרזולוציה, השינוי הקטן ביותר במתח שהממיר רואה V
Vrefמתח הייחוס V
nמספר הסיביות של הממיר—
דוגמה 6.1
הממיר בשני הלוחות שבספר הוא של 12 סיביות, ומתח הייחוס 3.3 V. מהי הרזולוציה?
פתרון:
q = Vref2n
q = 3.3212 = 3.34096
q = 0.806 mV
q = 0.806 mV

ועכשיו נקודה חשובה במיקרו-פייתון. הממיר הוא של 12 סיביות, אבל הפקודה read_u16() נותנת תמיד מספר בין 0 ל-65535, כלומר בתחום של 16 סיביות, בכל הלוחות. כך התוכנית נשארת נכונה גם כשעוברים ללוח עם ממיר אחר. המחיר: המספר קופץ בצעדים של כ-16, ולא של 1:

מעלים את המתח ב-0.4 mV בכל שנייה. המספרים זזים רק כשעוברים מדרגה שלמה.
import board
import time

pot = board.analog_in(board.POT)

for i in range(6):
    print(pot.read_u16())
    time.sleep(1)
ESP32 + Pico W · MicroPython 1.29 · simulated board
19861
19861
19877
19877
19893
19893
מקריאה למתח
V = N · Vref65535
סמלפירושיחידה
Nהערך של read_u16(), מ-0 עד 65535—
Vהמתח בהדק V
דוגמה 6.2
בהדק מתח של 1.2 V, ו-read_u16() נתן את המספר 23829. מהו המתח המחושב?
פתרון:
V = N · Vref65535
V = 23829 · 3.365535
V = 1.1999 V

ההפרש מן המתח האמיתי קטן ממדרגה אחת, וזו שגיאת הקוונטיזציה.

V = 1.1999 V
שאלה 6.1: ממיר של 10 סיביות ומתח ייחוס 5 V: מהי הרזולוציה שלו? האם הוא מדויק יותר מן הממיר של שני הלוחות, או פחות?

6.3 מה יש בכל לוח?

ESP32Pico W / Pico 2 WPi 4 / Pi 5
שפהמיקרו-פייתוןמיקרו-פייתוןפייתון על לינוקס
ממיר פנימי12 סיביות12 סיביותאין
הדקים אנלוגיים32–39; 0, 2, 4, 12–15, 25–27GP26, GP27, GP28—
כיוון התחוםחובה: attenאין: תמיד עד 3.3 V—
קריאהread_u16(), read_uv()read_u16()ממיר חיצוני דרך I2C
מגבלה עם WiFiהדקים מחוץ ל-32–39 לא עובדיםאין מגבלה—
אזהרה: אין לחבר להדק מתח גבוה ממתח ההזנה של הבקר. המגבלה המוחלטת להדק של ESP32 היא 3.6 V לפי תיעוד מיקרו-פייתון. חיישן עם מוצא של 5 V צריך קודם מחלק מתח.
הערה: ב-ESP32 יש שני גושי ממירים, ובגוש השני משתמש ה-WiFi. אם התוכנית משתמשת ברשת, כל קריאה מהדק שמחוץ לתחום 32–39 תסתיים בשגיאה. לכן בוחרים מלכתחילה הדק מן התחום הזה.

6.4 התוכנית הראשונה: קריאת פוטנציומטר

פוטנציומטר הוא החיישן הפשוט ביותר: מחברים את שני ההדקים החיצוניים ל-3V3 ול-GND, וההדק האמצעי נותן מתח לפי מיקום הידית.

3V334 (ESP32)GNDGP26 (Pico W)10 kΩV
חיבור הפוטנציומטר: ההדק האמצעי אל ההדק האנלוגי של הלוח.
ב-ESP32: הדק 34, עם כיוון התחום.
from machine import ADC, Pin
import time

pot = ADC(Pin(34), atten=ADC.ATTN_11DB)

while True:
    raw = pot.read_u16()
    print(raw)
    time.sleep(1)
ESP32 · MicroPython 1.29 · simulated board
0
16388
32776
49147
65535
...

נקרא את התוכנית שורה אחר שורה:

פקודהמה היא עושה
from machine import ADC, Pinמייבאים את מחלקות הממיר וההדק מן הספרייה שבנויה בבקר.
ADC(Pin(34), atten=ADC.ATTN_11DB)יוצרים ממיר על הדק 34, עם תחום שמגיע למתח ההזנה.
pot.read_u16()לוקחים קריאה אחת, מספר בין 0 ל-65535.
time.sleep(1)ממתינים שנייה, כדי שנספיק לקרוא את המסך.
ב-Pico W: שורה אחת שונה, ואותו פלט.
from machine import ADC, Pin
import time

pot = ADC(Pin(26))

while True:
    raw = pot.read_u16()
    print(raw)
    time.sleep(1)
Pico W · MicroPython 1.29 · simulated board
0
16388
32776
49147
65535
...

לו העברנו את התוכנית של ESP32 כמות שהיא ל-Pico W, היא הייתה נעצרת בשורה הראשונה, כי אין שם הדק 34. השגיאה בכיוון ההפוך ערמומית יותר, כי היא לא עוצרת את התוכנית:

אותה תוכנית ב-ESP32 בלי atten: המתח עולה מ-1.65 V ל-3.3 V, והמספר לא משתנה.
from machine import ADC, Pin
import time

pot = ADC(Pin(34))

while True:
    print(pot.read_u16())
    time.sleep(1)
ESP32 · MicroPython 1.29 · simulated board
32776
65535
65535
65535
65535
...
טעות נפוצה: בלי atten הממיר של ESP32 עובד בתחום הקטן ביותר, כ-1 V. כל מתח גבוה יותר נותן 65535. התוכנית לא נעצרת ולא מציגה שגיאה, ואנחנו חושבים שהפוטנציומטר מקולקל.
הקבועהתחום הלינארי לפי התיעוד
ADC.ATTN_0DB100 mV – 950 mV
ADC.ATTN_2_5DB100 mV – 1250 mV
ADC.ATTN_6DB150 mV – 1750 mV
ADC.ATTN_11DB150 mV – 2450 mV

שימו לב לעמודה השנייה: גם בתחום הגדול ביותר, הקריאה מהימנה רק בין 0.15 V ל-2.45 V. מחוץ לזה לוח אמיתי קורא פחות מן המתח בפועל. הסימולציה בספר אידיאלית ואינה מראה זאת. למדידה מדויקת משתמשים ב-read_uv(), שקיים רק ב-ESP32 ומפעיל את הכיול של השבב.

הערה: בחומרים רבים ברשת מופיעות הפקודות adc.width(), adc.read() ו-adc.atten(). אלה פקודות ישנות שעובדות ב-ESP32 בלבד, ואינן קיימות ב-Pico W. לכן הספר משתמש ב-read_u16(), הפקודה המשותפת.
שאלה 6.2: מה תדפיס התוכנית האחרונה בקירוב אם המתח הוא 0.275 V? הניחו תחום של 1.1 V.

6.5 תוכנית אחת לכל הלוחות

בפרק 3 הכרנו את הקובץ board.py, שבו כל מה ששייך ללוח. וההבדל שראינו עכשיו מקומו שם: הפונקציה analog_in מסתירה את כיוון התחום, והתוכנית לא מזכירה מספרים, רק שמות.

ב-ESP32
# board.py - ESP32 DevKit
from machine import ADC, I2C, PWM, SPI, UART, Pin, Timer

POT = 34
LDR = 35


def analog_in(pin):
    # 11 dB attenuation: the input range reaches the 3.3 V supply.
    return ADC(Pin(pin), atten=ADC.ATTN_11DB)
ב-Pico W
# board.py - Raspberry Pi Pico W / Pico 2 W
from machine import ADC, I2C, PWM, SPI, UART, Pin, Timer

POT = 26
LDR = 27


def analog_in(pin):
    # The range of the Pico is fixed at 0 to 3.3 V: nothing to configure.
    return ADC(Pin(pin))

ומוסיפים ספרייה קטנה נוספת, analog.py, עם חישובים שאינם תלויים בלוח:

הקובץ analog.py, בכל הלוחות
# analog.py - helpers for analog readings, the same on every board.
# (c) 2026 Fahed Ghanem - MIT License - fahed-lab.com

VREF = 3.3


def to_volts(raw):
    return raw * VREF / 65535


def scale(x, in_min, in_max, out_min, out_max):
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min


def average(adc, n=16):
    total = 0
    for _ in range(n):
        total += adc.read_u16()
    return total // n
אותה תוכנית בדיוק בשני הלוחות. הרצנו אותה בשניהם בזמן בניית הספר, ובדקנו שהפלט זהה.
import board
import time
from analog import to_volts, scale

pot = board.analog_in(board.POT)

while True:
    raw = pot.read_u16()
    volts = to_volts(raw)
    percent = scale(raw, 0, 65535, 0, 100)
    print("raw = %5d   V = %.3f   %3.0f%%" % (raw, volts, percent))
    time.sleep(1)
ESP32 + Pico W · MicroPython 1.29 · simulated board
raw =     0   V = 0.000     0%
raw = 16388   V = 0.825    25%
raw = 32776   V = 1.650    50%
raw = 49147   V = 2.475    75%
raw = 65535   V = 3.300   100%
...

הפונקציה scale מעבירה מספר מתחום לתחום, וכאן היא נותנת את האחוזים. נזדקק לה שוב ושוב.

הערה: בלוח אמיתי מדפיסים מספרים עשרוניים תמיד בתבנית קבועה, כמו "%.3f". המספרים העשרוניים ב-ESP32 וב-Pico W פחות מדויקים מאשר במחשב, ובלי תבנית יופיעו ספרות אחרונות שונות.
▶ניסוי חי — מעבדת הקלט האנלוגיכותבים את התוכנית במיקרו-פייתון האמיתי בתוך הדפדפן, בוחרים לוח, ומזיזים את הפוטנציומטר בעכבר.
⚠
המעבדה אינה זמינה כעת. החומר בפרק שלם גם בלעדיה: ממשיכים לקרוא, וחוזרים לניסוי מאוחר יותר, או פותחים אותו ישירות מן הקישור שמתחת למסגרת.
https://fahed-lab.com/books/micropython/lab/mpy_lab?prog=shared
פותחים את המעבדה בדף נפרד ↗ fahed-lab.com/books/micropython/lab/mpy_lab?prog=shared

6.6 חיישן אמיתי: נגד תלוי אור (LDR)

נגד תלוי אור לא נותן מתח, אלא משנה את התנגדותו: ככל שיש יותר אור, ההתנגדות קטנה. לכן מחברים אותו עם נגד קבוע RF במחלק מתח, והממיר קורא את המתח ביניהם.

3V335 (ESP32)GNDGP27 (Pico W)RLDRRF10 kΩV
מחלק המתח: ככל שיש יותר אור, V עולה.
התנגדות החיישן מן המתח הנמדד
V = Vref · RFRLDR + RF
RLDR = RF · (VrefV − 1)
סמלפירושיחידה
RLDRהתנגדות החיישן Ω
RFהנגד הקבוע Ω
Vהמתח הנמדד V
דוגמה 6.3
קראנו V = 2.2 V, ו-RF = 10 kΩ. מהי התנגדות החיישן?
פתרון:
RLDR = RF · (VrefV − 1)
RLDR = 10000 · (3.32.2 − 1)
RLDR = 5000 Ω
RLDR = 5 kΩ
מכסים את החיישן בהדרגה. כשהמתח מתקרב לאפס התוצאה מתנפחת, ולכן בודקים לפני החילוק.
import board
import time
from analog import to_volts

R_FIXED = 10000

ldr = board.analog_in(board.LDR)

while True:
    v = to_volts(ldr.read_u16())
    if v < 0.05:
        print("V = %.2f   too dark to measure" % v)
    else:
        r = R_FIXED * (3.3 / v - 1)
        print("V = %.2f   R = %6.0f ohm" % (v, r))
    time.sleep(1)
ESP32 + Pico W · MicroPython 1.29 · simulated board
V = 3.00   R =    999 ohm
V = 2.20   R =   5000 ohm
V = 1.10   R =  20000 ohm
V = 0.40   R =  72559 ohm
V = 0.00   too dark to measure
...
טעות נפוצה: לו מחקנו את התנאי if v < 0.05 והמתח היה V = 0, התוכנית הייתה נעצרת בחילוק באפס. כל חילוק בקריאה של חיישן דורש בדיקה.

6.7 רעש: למה המספרים רועדים? (Noise)

השאירו את הפוטנציומטר במקום וקראו: המספרים רועדים. הרעש הזה טבעי, ומקורו במעגל עצמו. התרופה הפשוטה ביותר היא לקחת כמה קריאות ולחשב ממוצע, כי העליות מבטלות את הירידות.

הוספנו לסימולציה רעש אקראי של ±20 mV, ומודדים את ההפרש בין הקריאה הגבוהה לנמוכה.
import board
from analog import average

pot = board.analog_in(board.POT)


def single():
    return pot.read_u16()


def smooth():
    return average(pot, 16)


def spread(read):
    low = high = read()
    for _ in range(49):
        x = read()
        low = min(low, x)
        high = max(high, x)
    return high - low


print("single reads, spread  :", spread(single))
print("average of 16, spread :", spread(smooth))
ESP32 + Pico W · MicroPython 1.29 · simulated board
single reads, spread  : 785
average of 16, spread : 266

המחיר של המיצוע הוא זמן: 16 קריאות לוקחות פי 16. בגודל איטי כמו טמפרטורה זה לא משנה, אבל באות מהיר המיצוע מטשטש את מה שרוצים למדוד.

פעילות: בלוח אמיתי: הריצו את התוכנית כשהפוטנציומטר במקום. אחר כך שנו את 16 ל-4 ול-64, ורשמו את ההפרשים בטבלה.

6.8 מקריאה להחלטה: בקרה דו-מצבית (On/Off Control)

רוצים נורית שנדלקת בחושך. התוכנית הפשוטה משווה לסף אחד, אבל ליד הסף די ברעש כדי להדליק ולכבות את הנורית שוב ושוב. הפתרון הוא שני ספים מרוחקים: מדליקים מתחת לראשון, מכבים מעל השני, וביניהם לא משנים דבר. זו היסטרזיס.

המתח מתנדנד סביב 1 V בשניות האמצעיות, והנורית לא רועדת.
import board
import time
from machine import Pin
from analog import to_volts

DARK = 1.0
BRIGHT = 1.4

led = Pin(board.LED, Pin.OUT)
ldr = board.analog_in(board.LDR)

while True:
    v = to_volts(ldr.read_u16())
    if v < DARK:
        led.on()
    elif v > BRIGHT:
        led.off()
    print("V = %.2f   LED = %d" % (v, led.value()))
    time.sleep(1)
ESP32 + Pico W · MicroPython 1.29 · simulated board
V = 1.60   LED = 0
V = 1.20   LED = 0
V = 0.95   LED = 1
V = 1.05   LED = 1
V = 0.95   LED = 1
V = 1.20   LED = 1
V = 1.30   LED = 1
V = 1.50   LED = 0
...

שימו לב לשורת ההדק: Pin(board.LED, Pin.OUT). ב-ESP32 הערך הוא 2, וב-Pico W הוא השם "LED", כי נורית הלוח שם מחוברת לשבב האלחוטי. התוכנית לא צריכה לדעת זאת.

שאלה 6.3: בפלט הקודם: באיזו שנייה כבתה הנורית? למה היא לא כבתה ב-1.05 V?

6.9 ממיר חיצוני: ADS1115 (External ADC)

כשהממיר הפנימי לא מספיק, או שאינו קיים, מחברים שבב ממיר חיצוני. ADS1115 הוא שבב נפוץ וזול, עם 4 כניסות ודיוק של 16 סיביות, והוא מדבר באפיק I2C שנלמד בפרק 9. כאן נשתמש בו כמו שהוא.

A0ADDRVDDSCLSDAGNDADS11153V3SCLSDAGND
חיבור ADS1115: ההדק ADDR אל GND נותן את הכתובת 0x48.

הדבר הראשון שעושים עם כל שבב I2C הוא סריקת האפיק, כדי לוודא את החיבור ואת הכתובת:

אם הודפסה רשימה ריקה, הבעיה בחיבור ולא בתוכנית.
import board

i2c = board.i2c()
print([hex(a) for a in i2c.scan()])
ESP32 + Pico W · MicroPython 1.29 · simulated board
['0x48']

ועכשיו הספרייה. כתבנו אותה בעצמנו כי היא קצרה, וכי הקריאה בה מלמדת איך מדברים עם שבב:

הקובץ ads1115.py
# ads1115.py - driver for the ADS1115 16-bit converter.
# ESP32 and Pico: pass a machine.I2C. Raspberry Pi 4/5: pass a pi_i2c.PiI2C.
# (c) 2026 Fahed Ghanem - MIT License - fahed-lab.com
import time

REG_CONV = 0
REG_CONFIG = 1
START = 0x8000
SINGLE_ENDED = 4
RANGE_4V = 0x0200
ONE_SHOT = 0x0100
RATE_128 = 0x0080
NO_COMPARATOR = 0x0003
LSB = 4.096 / 32768


class ADS1115:
    def __init__(self, i2c, addr=0x48):
        self.i2c = i2c
        self.addr = addr

    def _write(self, reg, value):
        self.i2c.writeto(self.addr, bytes([reg, value >> 8, value & 0xFF]))

    def _read(self, reg):
        self.i2c.writeto(self.addr, bytes([reg]))
        data = self.i2c.readfrom(self.addr, 2)
        return (data[0] << 8) | data[1]

    def read_raw(self, channel):
        mux = (SINGLE_ENDED + channel) << 12
        config = START | mux | RANGE_4V | ONE_SHOT | RATE_128 | NO_COMPARATOR
        self._write(REG_CONFIG, config)
        while not self._read(REG_CONFIG) & START:
            time.sleep(0.001)
        value = self._read(REG_CONV)
        return value - 65536 if value & 0x8000 else value

    def read_volts(self, channel):
        return self.read_raw(channel) * LSB
פקודהמה היא עושה
config = START | mux | ...בונים את אוגר ההגדרות משדותיו: התחל המרה, איזו כניסה, איזה תחום, איזו מהירות.
self._write(REG_CONFIG, config)שולחים את האוגר, וההמרה מתחילה.
while not ... & STARTממתינים עד שהשבב מודיע שההמרה הסתיימה.
value - 65536 if value & 0x8000המספר מסומן: הסיבית העליונה מציינת מספר שלילי.
דוגמה 6.4
מהי הרזולוציה בתחום ±4.096 V? ומהו זמן ההמרה ב-128 דגימות בשנייה?
פתרון:
q = 4.096215 = 4.09632768
q = 125 µV
t = 1128
t = 7.81 ms

המעריך כאן 15 ולא 16, כי סיבית אחת מיועדת לסימן.

q = 125 µV, t = 7.81 ms

קטן בערך פי 6 מן המדרגה של הממיר הפנימי, אבל כל קריאה לוקחת כמה אלפיות שנייה. אין ממיר שעדיף בכל דבר.

ב-ESP32 וב-Pico W.
import board
import time
from ads1115 import ADS1115

adc = ADS1115(board.i2c())

while True:
    print("A0 = %.4f V" % adc.read_volts(0))
    time.sleep(1)
ESP32 + Pico W · MicroPython 1.29 · simulated board
A0 = 0.5000 V
A0 = 1.2500 V
A0 = 2.5000 V
...

6.10 ב-Raspberry Pi 4/5

ב-Raspberry Pi 4/5 אין ממיר אנלוגי לספרתי, וגם machine לא עובד בו: זה מחשב עם לינוקס, וכותבים לו פייתון רגיל. ובכל זאת אפשר להשתמש באותה ספרייה ads1115.py. היא מבקשת מן האפיק שתי פעולות בלבד: writeto ו-readfrom, ולכן כותבים קובץ קטן שנותן לאפיק את שתי הפעולות האלה בעזרת הספרייה smbus2.

הקובץ pi_i2c.py, ב-Raspberry Pi בלבד
# pi_i2c.py - gives the Pi 4/5 I2C bus the two methods of machine.I2C
# that the book's drivers use, so the same driver runs on all boards.
# Needs: pip install smbus2, and I2C enabled in raspi-config.
# (c) 2026 Fahed Ghanem - MIT License - fahed-lab.com
from smbus2 import SMBus, i2c_msg


class PiI2C:
    def __init__(self, bus=1):
        self.bus = SMBus(bus)

    def writeto(self, addr, data):
        self.bus.i2c_rdwr(i2c_msg.write(addr, data))

    def readfrom(self, addr, n):
        msg = i2c_msg.read(addr, n)
        self.bus.i2c_rdwr(msg)
        return bytes(msg)

ההכנה נעשית פעם אחת, בחלון הפקודות: מפעילים את I2C דרך sudo raspi-config (בחלק Interface Options), ואז מתקינים את הספרייה בסביבה נפרדת:

python3 -m venv ~/lab
~/lab/bin/pip install smbus2
~/lab/bin/python ads_read_pi.py
רק שתי שורות שונות מן התוכנית של הבקר, והמספרים זהים.
import time
from ads1115 import ADS1115
from pi_i2c import PiI2C

adc = ADS1115(PiI2C())

while True:
    print("A0 = %.4f V" % adc.read_volts(0))
    time.sleep(1)
Raspberry Pi 4/5 · Python 3 · simulated bus
A0 = 0.5000 V
A0 = 1.2500 V
A0 = 2.5000 V
...
הערה: החיבור: SDA אל GPIO2, SCL אל GPIO3, ו-VDD אל 3V3 ולא אל 5V. למי שמעדיף אפיק SPI, בספרייה gpiozero יש מחלקה מוכנה לממיר MCP3008.

עיקרי הפרק:

סיכום הכללים בפרק:

הכללהנוסחה
רזולוציהq = Vref2n
מקריאה למתחV = N · Vref65535
התנגדות חיישן במחלקRLDR = RF · (VrefV − 1)

פקודות הפרק:

פקודהמה היא עושה
ADC(Pin(n), atten=ADC.ATTN_11DB)ממיר על הדק ב-ESP32.
ADC(Pin(n))ממיר על הדק ב-Pico W.
adc.read_u16()קריאה בין 0 ל-65535, בכל הלוחות.
adc.read_uv()מתח מכויל במיקרו-וולט, ב-ESP32 בלבד.
i2c.scan()רשימת הכתובות של השבבים המחוברים לאפיק.

מילון מונחים:

עבריתEnglishערבית
ממיר אנלוגי לספרתיAnalog-to-Digital Converterالمحوّل التماثلي الرقمي
רזולוציהResolutionالتمييز
מתח ייחוסReference Voltageجهد المرجع
זמן המרהConversion Timeزمن التحويل
שגיאת קוונטיזציהQuantization Errorخطأ التكميم
פוטנציומטרPotentiometerمقياس الجهد
נגד תלוי אורLight Dependent Resistorمقاومة ضوئية
מחלק מתחVoltage Dividerمجزّئ الجهد
רעשNoiseالضجيج
היסטרזיסHysteresisالتخلّف
אפיקBusالناقل
התשובות הסופיות לשאלות הפרק
6.1 q = 4.88 mV, כלומר פחות מדויק מ-0.81 mV.
6.2 כ-16400, כלומר רבע מן התחום.
6.3 היא כבתה רק בשורה האחרונה (V = 1.50), כי 1.05 V נמצא בין שני הספים, ושם לא משתנה דבר.

שאלות לתרגול:

רמה ראשונה — בסיס
1.
ממיר של 8 סיביות ומתח ייחוס 3.3 V. מהי הרזולוציה?
תשובות: q = 12.89 mV.
2.
read_u16() נתן את המספר 20000. מהו המתח בהדק?
תשובות: V = 1.007 V.
3.
אילו הדקים מתאימים לקריאה אנלוגית ב-Pico W: 26, 34, 27, 5? למה?
תשובות: רק 26 ו-27: הדקים 34 ו-5 אינם הדקי ממיר, והדק 34 בכלל לא קיים.
רמה שנייה — יישום
4.
כתבו תוכנית שמציירת את מצב הפוטנציומטר בסימני #: מאפס סימנים עד 10.
תשובות:
import board
import time
from analog import scale

pot = board.analog_in(board.POT)

while True:
    level = scale(pot.read_u16(), 0, 65535, 0, 10)
    print("#" * int(level))
    time.sleep(1)
5.
קראנו במחלק של הנגד תלוי האור V = 0.8 V, ו-RF = 10 kΩ. מהי התנגדות החיישן?
תשובות: RLDR = 31.25 kΩ.
6.
החיישן LM35 נותן 10 mV לכל מעלת צלזיוס. כתבו תוכנית שמדפיסה את הטמפרטורה, ומצאו מה היא מדפיסה ב-25 מעלות.
תשובות:
import board
import time
from analog import to_volts

sensor = board.analog_in(board.POT)

while True:
    v = to_volts(sensor.read_u16())
    print("T = %.1f C" % (v * 100))
    time.sleep(1)
מודפס: T = 25.0 C
רמה שלישית — העמקה
7.
התוכנית הקודמת קוראת 0.25 V בתחום של 3.3 V.
(א) כמה מעלות שווה מדרגה אחת?
(ב) למה תחום קטן יותר משתלם ב-ESP32?
תשובות: (א) 0.81 mV שוות 0.08 מעלות. (ב) עם ATTN_0DB התחום קטן לכ-1 V, המדרגה קטנה באותו יחס, ומתח החיישן נשאר בתחום הלינארי.
8.
התוכנית שלכם משתמשת ב-WiFi ובהדק 25 לקריאה. מה יקרה? איך מתקנים?
תשובות: הקריאה תסתיים בשגיאה, כי הדק 25 בגוש השני שבו משתמש ה-WiFi. מעבירים את החיישן להדק בין 32 ל-39.
9.
(א) למה הספרייה ads1115.py עובדת ב-Raspberry Pi בלי שינוי?
(ב) איזו פקודה הייתה נכשלת לו השתמשנו ב-time.sleep_ms?
תשובות: (א) כי היא מבקשת מן האפיק רק writeto ו-readfrom, ואינה מייבאת machine. (ב) sleep_ms קיימת רק במיקרו-פייתון, ולא בפייתון רגיל.
נוסחאון הספר: כל נוסחאות הפרק הזה מרוכזות, עם סרטוטיהן וטבלאות הסמלים שלהן, בפרק 25 — נוסחאון הספר.