תכנות מיקרו-בקרים בשפת MicroPython · פרק 13 — חיישנים ומפעילים נפוצים⌂📚🏠
פרק 13

חיישנים ומפעילים נפוצים

Common Sensors and Actuators
3 שעות לימוד

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

בפרק הזה:
  • נקרא טמפרטורה ולחות מ-DHT11/22 בלי לעבור את מגבלת קצב הקריאה.
  • נדליק רצועת NeoPixel ונחשב את הזרם שלה לפני החיבור.
  • נפעיל ממסר דרך טרנזיסטור בבטחה, ונבין את תפקיד דיודת החופש.
  • נקרא מגע ב-ESP32 וג׳ויסטיק דרך שני ממירים.
  • נשתמש בחיישני I2C בעזרת ספרייה, ונבנה מערכת של חיישן, סף ותצוגה.
הרכיבסוגואיך מחבריםסעיף
DHT11 / DHT22טמפרטורה ולחותהדק ספרתי אחד13.1
HC-SR04מרחקשני הדקים ספרתיים, פולס13.2 ו-4.5
NeoPixelמפעיל: אור צבעוניהדק ספרתי אחד13.3
ממסרמפעיל: מתג לעומס נפרדהדק ספרתי וטרנזיסטור13.4
TouchPadמגעהדק אחד, ESP32 בלבד13.5
KY-023מיקום וכיווןשני ממירים והדק ספרתי13.6
BMP280 / AHT20לחץ, טמפרטורה ולחותI2C13.7

13.1 טמפרטורה ולחות: DHT11 ו-DHT22

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

DHT11DHT22
תחום הטמפרטורה (טיפוסי)0 – 50 °C−40 – 80 °C
תחום הלחות (טיפוסי)20 – 90 %0 – 100 %
הקריאה המהירה ביותר לפי התיעודפעם בשנייהפעם בשתי שניות
VCCDATAGNDDHT223V3DHTGNDR
הנגד R מושך את קו הנתונים למעלה. הערך הנפוץ שלו הוא 4.7 kΩ, ובמודולים מוכנים רבים הוא כבר מובנה.
מדידה כל שתי שניות. כדי למדוד עם DHT11 מחליפים רק את המחלקה.
import board
import dht
import time
from machine import Pin

sensor = dht.DHT22(Pin(board.DHT))

while True:
    try:
        sensor.measure()
        t = sensor.temperature()
        h = sensor.humidity()
        print("%.1f C  %.1f %%" % (t, h))
    except OSError:
        print("no answer from the sensor")
    time.sleep(2)
ESP32 + Pico W · MicroPython 1.29 · simulated board
24.0 C  55.0 %
24.5 C  56.0 %
25.0 C  57.0 %
...
אותה תוכנית בלי חיישן: היא לא קורסת, אלא מדווחת לנו.
import board
import dht
import time
from machine import Pin

sensor = dht.DHT22(Pin(board.DHT))

while True:
    try:
        sensor.measure()
        t = sensor.temperature()
        h = sensor.humidity()
        print("%.1f C  %.1f %%" % (t, h))
    except OSError:
        print("no answer from the sensor")
    time.sleep(2)
ESP32 + Pico W · MicroPython 1.29 · simulated board
no answer from the sensor
...
טעות נפוצה: ההוראה measure() היא שקוראת מן החיישן, ואילו temperature() מחזירה את הערך האחרון. מי ששוכח את measure יראה את אותו מספר לנצח. ואם קוראים מהר יותר מן המגבלה, התוצאה עלולה להיות לא מדויקת או שהמדידה תיכשל.

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

שואלים בכל שנייה, והחיישן נקרא רק אחת לשתי שניות.
import board
import dht
import time
from machine import Pin


class Climate:
    def __init__(self, pin, min_ms=2000):
        self.sensor = dht.DHT22(Pin(pin))
        self.min_ms = min_ms
        self.last = None

    def read(self):
        now = time.ticks_ms()
        if (self.last is None
                or time.ticks_diff(now, self.last) >= self.min_ms):
            self.sensor.measure()
            self.last = now
        return self.sensor.temperature()


room = Climate(board.DHT)
for _ in range(5):
    print("%.1f C" % room.read())
    time.sleep(1)
ESP32 + Pico W · MicroPython 1.29 · simulated board
24.0 C
24.0 C
26.0 C
26.0 C
28.0 C

13.2 מרחק: HC-SR04

את החיישן הזה הסברנו בסעיף 4.5: העיקרון, מחלק המתח על ECHO והספרייה hcsr04.py. לחיבור חוזרים לשם, וכאן משתמשים בספרייה עם סף:

הספרייה מחזירה None אם לא חזר הד.
import board
import time
from hcsr04 import HCSR04

NEAR_CM = 30
sensor = HCSR04(board.TRIG, board.ECHO)

for _ in range(3):
    d = sensor.distance_cm()
    if d is None:
        print("no echo")
    else:
        print("%.1f cm" % d, "NEAR" if d < NEAR_CM else "far")
    time.sleep(1)
ESP32 + Pico W · MicroPython 1.29 · simulated board
20.0 cm NEAR
no echo
100.0 cm far
...
טעות נפוצה: לא שוכחים לבדוק None לפני ההשוואה: None < 30 היא שגיאה שעוצרת את התוכנית. בד או משטח משופע עשויים שלא להחזיר הד, ולכן אסור להסיק מ-None שהדרך פנויה.

13.3 הרצועה הצבעונית: NeoPixel (NeoPixel, WS2812)

העיקרון: בכל נורית ברצועה יש שבב קטן. הנתונים נכנסים לנורית הראשונה, והיא לוקחת לעצמה שלושה בתים: אדום, ירוק וכחול, ומעבירה את השאר לנורית הבאה. לכן הדק אחד מספיק לכל הרצועה. הצבעים משתנים רק ב-write().

DIN5VGNDWS2812 x 8NEOPIXELGNDR+5 V
הזנה חיצונית של 5 V ואדמה משותפת. הערך הנפוץ של הנגד R בקו הנתונים הוא כמה מאות אוהם.
דוגמה 13.1
כמה זרם צריכה רצועה של 8 נוריות? ניקח ערך טיפוסי: כ-60 mA לנורית אחת בלבן מלא, ונבדוק בגיליון הנתונים של הרצועה.
פתרון:
I = N · ILED
I = 8 · 60
I = 480 mA

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

I = 480 mA
הפוטנציומטר קובע כמה נוריות דולקות. אחרי התוכנית מופיע מה שיצא על החוט בבסיס הקסדצימלי: כל שש ספרות הן נורית אחת, לפי הסדר אדום, ירוק, כחול, ו-28 הוא המספר 40.
import board
import neopixel
import time
from machine import Pin

COUNT = 8
GREEN = (0, 40, 0)
OFF = (0, 0, 0)

strip = neopixel.NeoPixel(Pin(board.NEOPIXEL, Pin.OUT), COUNT)
pot = board.analog_in(board.POT)

while True:
    lit = pot.read_u16() * (COUNT + 1) // 65536
    for i in range(COUNT):
        strip[i] = GREEN if i < lit else OFF
    strip.write()
    print("lit:", lit)
    time.sleep(1)
ESP32 + Pico W · MicroPython 1.29 · simulated board
lit: 0
lit: 2
lit: 5
lit: 8
[neo]
000000 000000 000000 000000 000000 000000 000000 000000
002800 002800 000000 000000 000000 000000 000000 000000
002800 002800 002800 002800 002800 000000 000000 000000
002800 002800 002800 002800 002800 002800 002800 002800
...

בחרנו בצבע (0, 40, 0) ולא ב-255: הבהירות מספיקה, והזרם קטן יותר. בערך טיפוסי של כ-20 mA לצבע אחד בבהירות מרבית, זרם שמונה הנוריות יורד לכ-25 mA.

אזהרה: לא מזינים רצועה ארוכה מ-3V3, ומחברים את שתי האדמות יחד. רצועות רבות מוזנות ב-5 V וצריכות בקו הנתונים מתח גבוה מ-3.3 V לפי גיליון הנתונים. אם מופיעים צבעים אקראיים, זה הדבר הראשון שבודקים. מומלץ גם קבל גדול על ההזנה, קרוב לרצועה.

13.4 ממסר: מתג לעומס נפרד (Relay)

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

LED_EXTGND1 kΩ+5 V+−12 V
הטרנזיסטור מפעיל את הסליל, והמגע מפעיל עומס במעגל נפרד במתח נמוך. הקו המקווקו הוא הקשר המכני.

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

דוגמה 13.2
סליל טיפוסי של 5 V שואב 70 mA. ההגבר hFE המינימלי של הטרנזיסטור הוא כ-100 לפי גיליון הנתונים שלו. נבחר RB = 1 kΩ. האם זרם הבסיס מספיק?
פתרון:
IB,min = IChFE = 70100 = 0.7 mA
IB = Vpin − VBERB = 3.3 − 0.71 = 2.6 mA

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

IB = 2.6 mA

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

ב-27 הממסר נשאר במצב הקודם שלו: פעם מנותק ופעם מחובר.
import board
import dht
import time
from machine import Pin

ON_ABOVE = 28
OFF_BELOW = 26

relay = Pin(board.LED_EXT, Pin.OUT, value=0)
sensor = dht.DHT22(Pin(board.DHT))

while True:
    sensor.measure()
    t = sensor.temperature()
    if t >= ON_ABOVE:
        relay.value(1)
    elif t <= OFF_BELOW:
        relay.value(0)
    print("%.1f C  relay=%d" % (t, relay.value()))
    time.sleep(2)
ESP32 + Pico W · MicroPython 1.29 · simulated board
25.0 C  relay=0
27.0 C  relay=0
28.5 C  relay=1
27.0 C  relay=1
26.0 C  relay=0
27.0 C  relay=0
...
אזהרה: בטיחות: בספר הזה לא מחברים מתח רשת לממסר, וגם לא על לוח ניסויים. מתח רשת קטלני, והעבודה איתו שמורה לבעלי מקצוע. מתנסים במתח נמוך ובמקור מתאים, כמו נורה של 12 V. את המתח והזרם המרביים של המגע קוראים בגיליון הנתונים, ולא ממה שכתוב באתר המכירה.
הערה: מודולי ממסר מוכנים כוללים את הטרנזיסטור והדיודה. חלקם פועלים ב-0 וחלקם ב-1, וחלקם צריכים מתח כניסה גבוה מ-3.3 V. לכן בודקים את המודול קודם בלי עומס.
שאלה 13.1: סליל שואב 40 mA, וההגבר hFE המינימלי הוא 100. מהו זרם הבסיס המינימלי?

13.5 מגע: TouchPad (Capacitive Touch)

העיקרון: כל גוף מוליך משנה את הקיבול החשמלי בהדק, והשבב מודד זאת. לכן מספיקים חוט וחתיכת נחושת, בלי לחצן. המחלקה TouchPad קיימת ב-ESP32 בלבד, וחלק מהדקיה: 0, 2, 4, 12–15, 27, 32, 33. ב-Pico W היא לא קיימת.

14 (ESP32)
חתיכה מוליכה וחוט להדק 14, אחרי שמנתקים ממנו את הלחצן.
ב-ESP32 בלבד: מודדים ברגע ההפעלה ולוקחים את מחצית הערך כסף.
import time
from machine import Pin, TouchPad

pad = TouchPad(Pin(14))
limit = pad.read() // 2
print("limit:", limit)

while True:
    value = pad.read()
    print(value, "touched" if value < limit else "free")
    time.sleep(1)
ESP32 · MicroPython 1.29 · simulated board
limit: 600
1200 free
1180 free
60 touched
55 touched
1190 free
...
אזהרה: המספרים יחסיים. לפי התיעוד הם בדרך כלל עשרות במגע ויותר מאלף בלעדיו, אבל הם משתנים מלוח ללוח ועם הסביבה. לכן לא כותבים סף קבוע, אלא מכיילים אותו בהפעלה, ולא נוגעים בחתיכה ברגע הזה.

13.6 ג׳ויסטיק: KY-023 (Joystick)

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

GND+5VVRxVRySWKY-023GND3V3POTLDRBTN
החיבור לפי השמות ב-board.py. החוט האדום: ההדק שכתוב עליו +5V מחובר ל-3V3.
הולכים וחוזרים על שני הצירים, ואז לוחצים על הלחצן.
import board
import time
from machine import Pin

CENTER = 32768
DEAD = 6000

x_axis = board.analog_in(board.POT)
y_axis = board.analog_in(board.LDR)
button = Pin(board.BTN, Pin.IN, Pin.PULL_UP)


def axis(adc):
    d = adc.read_u16() - CENTER
    return 0 if abs(d) < DEAD else d


def direction(dx, dy):
    if dx == 0 and dy == 0:
        return "center"
    if abs(dx) >= abs(dy):
        return "right" if dx > 0 else "left"
    return "up" if dy > 0 else "down"


while True:
    name = direction(axis(x_axis), axis(y_axis))
    print(name, "pressed" if button.value() == 0 else "")
    time.sleep(1)
ESP32 + Pico W · MicroPython 1.29 · simulated board
center 
right 
up 
left 
center pressed
...
▶ניסוי חי — ג׳ויסטיקהפוטנציומטר הוא הציר האופקי, והנגד התלוי באור הוא הציר האנכי. מזיזים אותם ורואים את הכיוון, ומשנים את DEAD.
⚠
המעבדה אינה זמינה כעת. החומר בפרק שלם גם בלעדיה: ממשיכים לקרוא, וחוזרים לניסוי מאוחר יותר, או פותחים אותו ישירות מן הקישור שמתחת למסגרת.
https://fahed-lab.com/books/micropython/lab/mpy_lab?prog=ch13_joystick
פותחים את המעבדה בדף נפרד ↗ fahed-lab.com/books/micropython/lab/mpy_lab?prog=ch13_joystick
טעות נפוצה: לא מחברים את המודול ל-5 V למרות מה שכתוב עליו: אז מוצא הצירים מגיע ל-5 V, וזה מעל מה שההדק מוכן לשאת. והמרכז אינו בדיוק 32768, ולכן צריך אזור מת: DEAD = 6000 שווה בערך ל-0.3 V. ייתכן גם שכיוון הציר הפוך, בהתאם לאופן שבו המודול מורכב, ולכן בודקים אותו והופכים את הסימן.

13.7 חיישני I2C: BMP280 ו-AHT20

העיקרון: שני החיישנים האלה עובדים על האפיק שהכרנו בפרק 9. BMP280 מודד לחץ וטמפרטורה, ו-AHT20 מודד טמפרטורה ולחות. הכתובות שלהם שונות: 0x76 או 0x77 בראשון, ו-0x38 בשני, ולכן אפשר לחבר אותם יחד לאותם שני חוטים.

VCCSCLSDAGNDBMP2803V3SCLSDAGND
ארבעה חוטים, וזהים לשני החיישנים.

כתבנו לכל אחד מהם ספרייה קצרה: common/bmp280.py ו-common/aht20.py, והן נמצאות עם ספריות הספר. הספרייה BMP280 מיישמת את נוסחאות התיקון מגיליון הנתונים של היצרן, כי לכל שבב יש מקדמי כיול משלו, ולכן היא קוראת אותם קודם ורק אחר כך מחשבת.

הכנסנו למדמה את המקדמים ואת הקריאות של הדוגמה הפתורה בגיליון הנתונים. התוצאה היא התוצאה שלו.
import board
from bmp280 import BMP280

i2c = board.i2c()
print("found:", [hex(a) for a in i2c.scan()])

sensor = BMP280(i2c)
t, p = sensor.read()
print("%.2f C" % t)
print("%.1f hPa" % (p / 100))
ESP32 + Pico W · MicroPython 1.29 · simulated board
found: ['0x76']
25.08 C
1006.5 hPa
שימוש ב-AHT20.
import board
from aht20 import AHT20

sensor = AHT20(board.i2c())
t, h = sensor.read()
print("%.1f C  %.1f %%" % (t, h))

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

אזהרה: מודולים דומים: BME280 אינו BMP280, ויש לו מספר זיהוי אחר, ולכן הספרייה נעצרת בהודעת שגיאה ולא נותנת מספרים שגויים. ייתכן גם שנמצא כתובת שאיננו מצפים לה, ולכן תמיד מתחילים בהוראה i2c.scan(). מספרים עשרוניים על הלוח פחות מדויקים מאשר במדמה, ולכן לא קוראים את הספרות האחרונות של הלחץ.

13.8 פרויקט: חלון חממה

עכשיו מחברים חיישן, שני ספים, תצוגה ומפעיל. החממה פותחת את החלון שלה אם הטמפרטורה עולה, והצבע מראה את המצב. את הסרבו מכירים מסעיף 7.4, יחד עם הספרייה servo.py.

DHT22הטמפרטורהההחלטהשני ספיםNeoPixelהצבעServoפתיחת החלון
מהחיישן להחלטה, ומשם לשני המפעילים.
ההחלטה בפונקציה אחת שאינה יודעת דבר על החומרה, ולכן קל לבדוק אותה ולשנות אותה.
import board
import dht
import neopixel
import time
from machine import Pin
from servo import Servo

WARM = 26
HOT = 30
GREEN, AMBER, RED = (0, 40, 0), (40, 20, 0), (40, 0, 0)

sensor = dht.DHT22(Pin(board.DHT))
strip = neopixel.NeoPixel(Pin(board.NEOPIXEL, Pin.OUT), 8)
window = Servo(board.pwm(board.SERVO, 50))


def decide(t):
    if t >= HOT:
        return RED, 90
    if t >= WARM:
        return AMBER, 45
    return GREEN, 0


while True:
    try:
        sensor.measure()
    except OSError:
        print("sensor error")
        time.sleep(2)
        continue
    t = sensor.temperature()
    color, angle = decide(t)
    strip.fill(color)
    strip.write()
    window.angle(angle)
    print("%.1f C  window %d" % (t, angle))
    time.sleep(2)
ESP32 + Pico W · MicroPython 1.29 · simulated board
24.0 C  window 0
27.0 C  window 45
31.0 C  window 90
28.0 C  window 45
24.0 C  window 0
[neo]
002800 002800 002800 002800 002800 002800 002800 002800
281400 281400 281400 281400 281400 281400 281400 281400
280000 280000 280000 280000 280000 280000 280000 280000
281400 281400 281400 281400 281400 281400 281400 281400
002800 002800 002800 002800 002800 002800 002800 002800
...
אזהרה: הרצועה והסרבו שואבים זרם גדול: צריך מקור חיצוני של 5 V ואדמה משותפת עם הלוח. אם הלוח מתאפס כשהסרבו זז, זו בדרך כלל נפילת מתח בהזנה ולא שגיאה בתוכנית.
פעילות: הוסיפו רישום CSV מפרק 12 שכותב את הטמפרטורה והזווית אחת לעשר קריאות, והביאו את WARM ו-HOT מקובץ הגדרות.

13.9 בחירת חיישן

רוצים למדודבוחריםשואלים לפני הקנייה
טמפרטורה ולחות בחדרDHT22 או AHT20האם איטיות הקריאה מספיקה? האם יש לי אפיק I2C?
לחץ וגובה יחסיBMP280האם זה BMP או BME? מה המתח שלו?
אור בלי דיוק רבנגד תלוי אור, פרק 6האם מחלק מתח מספיק?
מרחק של כמה מטריםHC-SR04האם המתח הוא 5 V? האם המשטח מחזיר את הקול?
זרימת מיםחיישן עם מאוורר שנותן פולסיםכמה פולסים לליטר לפי גיליון הנתונים? סופרים אותם בפסיקה, פרק 5
מגע בלי לחצןTouchPadהאם הלוח הוא ESP32?
מיקום בידפוטנציומטר או KY-023כמה ממירים פנויים?

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

עיקרי הפרק:

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

הכללהנוסחה
זרם הרצועהI = N · ILED
זרם בסיס מינימליIB,min = IChFE
זרם הבסיסIB = Vpin − VBERB

פקודות הפרק:

פקודהמה היא עושה
dht.DHT22(Pin(n)), dht.DHT11(Pin(n))חיישן טמפרטורה ולחות.
sensor.measure()מדידה חדשה. אחריה temperature() ו-humidity().
neopixel.NeoPixel(Pin(n, Pin.OUT), count)רצועה של count נוריות.
strip[i] = (r, g, b), strip.fill(c)צבע של נורית אחת או של כולן, בזיכרון.
strip.write()שליחת הצבעים לרצועה.
TouchPad(Pin(n)).read()מדידת מגע, ב-ESP32 בלבד.
BMP280(i2c).read()טמפרטורה ולחץ, מ-bmp280.py.
AHT20(i2c).read()טמפרטורה ולחות, מ-aht20.py.

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

עבריתEnglishערבית
ממסרRelayالمرحّل
מגעContactالملامس
חממהGreenhouseالدفيئة
אזור מתDead Zoneالمنطقة الميتة
לחותHumidityالرطوبة
לחץ אטמוספריAtmospheric Pressureالضغط الجوي
ג׳ויסטיקJoystickعصا التحكّم
התשובות הסופיות לשאלות הפרק
13.1 IB,min = 0.4 mA.

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

רמה ראשונה — בסיס
1.
מה ההבדל בין measure() ל-temperature()?
תשובות: הראשונה קוראת מן החיישן, והשנייה מחזירה את הערך האחרון שנקרא.
2.
קבענו את צבעי הרצועה ושום דבר לא השתנה. איזו הוראה חסרה?
תשובות: strip.write().
3.
למה תוכנית TouchPad לא עובדת ב-Pico W?
תשובות: כי המחלקה הזאת קיימת ב-ESP32 בלבד.
4.
מה תפקיד דיודת החופש במעגל הממסר?
תשובות: היא מעבירה את זרם הסליל בזמן הניתוק, וכך מגינה על הטרנזיסטור מקפיצת המתח.
רמה שנייה — יישום
5.
רצועה של 30 נוריות, בערך טיפוסי של 60 mA לנורית. כמה זרם צריך בלבן מלא?
תשובות: I = 1.8 A.
6.
שנו את joystick.py כך שיפעיל את LED_EXT כל עוד הלחצן לחוץ.
תשובות: מוסיפים Pin(board.LED_EXT, Pin.OUT), ובלולאה: led.value(1 - button.value()).
7.
למה משתמשים בשני ספים בתוכנית הממסר? מה קורה עם סף אחד כשהטמפרטורה מתנדנדת סביבו?
תשובות: עם סף אחד המגע נפתח ונסגר שוב ושוב, מקשקש ונשחק. שני הספים מונעים זאת.
רמה שלישית — העמקה
8.
הוסיפו ל-decide ב-greenhouse.py שני ספים לכל מצב, כדי שהחלון לא יתנדנד.
תשובות: שומרים את המצב הנוכחי, ועוברים ממנו רק כשהטמפרטורה עוברת סף גבוה יותר בעלייה או נמוך יותר בירידה.
9.
תכננו פרויקט שמדליק רצועה ככל שגוף מתקרב: כמה נוריות לכל מרחק?
תשובות: למשל: lit = COUNT - d * COUNT // 100 בין 0 ל-100 ס״מ, עם בדיקת None והגבלת התוצאה בין 0 ל-COUNT.
נוסחאון הספר: כל נוסחאות הפרק הזה מרוכזות, עם סרטוטיהן וטבלאות הסמלים שלהן, בפרק 25 — נוסחאון הספר.