MicroPython op de ESP8266 en ESP32

Met enkele voorbeeldprogramma's

MicroPython

MicroPython is een variant van de programmeertaal Python, die is geoptimaliseerd voor gebruik in microprocessors. De nieuwste versie van MicroPython is klein en toch efficiënt en kan daarom gemakkelijk op allerlei apparaten worden gedraaid. Op een klassieke Arduino UNO kan dit echter niet. Het gaat wel goed op de EPS8266, de ESP32, de BBC microbit, STM32F4 discovery board, de LEGO EV3, de Raspberry Pi Pico, de pyBoard en nog veel andere microprocessors. Naast MicroPython bestaat ook CircuitPython. Dat is een systeem van Adafruit en werkt dan ook op processors van Adafruit, zoals de Trinket of de Metro M4. CircuitPython is een afgeleide van MicroPython, maar toch zijn deze talen niet volledig uitwisselbaar. Als je veel Adafruit spullen hebt dan loont het om CircuitPython te gebruiken. Dat werkt eenvoudiger dan MicroPython, maar toch raad ik MicroPython aan, onder andere omdat CircuitPython voor de ESP8266 niet langer ondersteund wordt.
☛ Hoewel de ondersteuning voor MicroPython met de dag beter wordt, is die lang niet zo goed als die van Arduino C++. Als je geen zin hebt allerlei problemen zelf te moeten oplossen, blijf dan bij de Arduino IDE en bijbehorende programmeertaal. ☚
Een groot voordeel van het gebruik van MicroPython is dat je commando's direct naar het ESP kunt sturen zonder dat je er eerst een programma voor moet maken. Handig bij het testen. Een ander voordeel is dat het uploaden van programma's erg snel is. Een nadeel is dat een gewoon MicroPython programma tot 100 keer langzamer draait dan een C++-programma. Bij verreweg de meeste toepassingen zul je dat niet merken. Als snelheid belangrijk is dan zijn er geavanceerde methoden om het programma sneller te krijgen, maar dat valt buiten het kader van mijn pagina's. Ik noem allen: gebruik lokale variabelen in plaats van globale.
Er zijn nog twee belangrijke voordelen van MicroPython:
  1. De code blijft leesbaar; je hoeft dus geen kopie op je computer te bewaren; als je ESP32's hebt, waarbij de interne led op verschillende pinnen zitten, dan kun je in je blink programma zien wat die pin is. Als je C++ met de Arduino IDE gebruikt zou je in dit geval voor elke ESP32 een kopie van het blinkprogramma met een ander led-nummer moeten bewaren.
  2. Je kunt verschillende programma's tegelijk op de ESP bewaren.
Nog iets om rekening mee te houden: MicroPython gebruikt de GPIO nummers van de pinnen, dat is anders (duidelijker) dan bij de Arduino. Dat betekent o.a. dat op de D1 mini pin D4 in MycroPython pin 2 is.

Ontwikkelomgevingen (IDE)

Ook voor programmeren in MicroPython is het handig om een IDE te gebruiken, vergelijkbaar met de Arduino IDE. Je kunt ook instructies geven en bestanden uploaden via een terminal programma als Putty en Tera Term (kies voor 115200 baud). Dat werkt in beide gevallen ook goed, maar je mist een aantal extra's zoals voorbeeldprogramma's. Bij Adafruit bordjes is het vaak mogelijk de Python programma's direct op de bordje te kopiëren. Het bordje wordt dan in je verkenner weergegeven alsof het een schijf is.
Welke IDE moet je gebruiken?
Dat is een moeilijke vraag, omdat er veel mogelijkheden zijn. Soms wordt de keuze bepaald door het bord dat je wilt programmeren. Zo kun je voor de LEGO EV3 het beste Visual Studio Code gebruiken. Ik heb ervaring met de volgende programma's: Thonny, Mu, PyCharm en uPyCraft.

uPyCraft

Flashen van "firmware"
Zodra je uPyCraft opstart, moet je in het menu Tools een poort koppelen. Het programma geeft een lijstje met de gebruikte COM poorten. Als er geen geschikt OS aanwezig is (wanneer de ESP nieuw is, of wanneer deze is geprogrammeerd met de Arduino IDE) dan kom je automatisch in een menu waarbij je een binair bestand kunt flashen (zie hiernaast).
Als je van te voren een binair bestand hebt opgehaald1 kun je dat kiezen (vink Users aan), maar je kunt ook kiezen voor de uPyCraft versie. De standaardinstellingen werken bij veel ESP's goed. Na flashen moet je de microprocessor via het menu Tools opnieuw koppelen. Als alles goed is zie je in het raampje beneden de Python prompt  >>> . Om te testen kun je bijvoorbeeld 64**32 invoeren. Je ziet vrijwel direct het antwoord.
>>> 64**32
6277101735386680763835789423207666416102355444464034512896
>>>
Python kan nog veel grotere gehele getallen gebruiken. Met een gewone Arduino is dat bijna onmogelijk. Dat kan een reden zijn om over te stappen op een ESP en die te programmeren met MicroPython.

Voorbeelden
Je kunt nu via menu File → Examples → voorbeeldprogramma's kiezen, zoals het blinkprogramma of nog mooier: het breatheLight programma.
Het commentaar in deze voorbeelden klopt niet altijd, maar ze werken doorgaans prima.

Meer over uPyCraft

uPyCraft venster
Hier boven zie je hoe uPyCraft eruit ziet. Links zie je welke programma's aanwezig zijn op het "device", in mijn geval de ESP32-WROOM-32. Deze bestanden zijn aanwezig in bestandssysteem van de ESP32. Daaronder zie je wat er op de SD kaart staat, indien aanwezig. Daar weer onder zie je ingebouwde bibliotheken en tenslotte zie je in de "workSpace" eerder gemaakte programma's.
Rechts zie je icoontjes die het volgende betekenen: In het midden zie je het grote venster waarin je de programma's maakt. Je kunt programma's laden vanuit de lijst onder "device", maar als er nog een programma loopt moet je eerst op de STOP-knop klikken.
Onder dit grote venster zie je het mededelingen versie. Dit wordt ook wel de "terminal" of de "shell" genoemd. Hier worden ook resultaten van berekeningen en print opdrachten getoond en je kunt hier Python opdrachten voor de ESP geven.

MicroPython programma's

Als je een programma hebt gemaakt dan wil je misschien dat dit bij opstarten meteen wordt uitgevoerd. Dit gebeurt niet automatisch. Je kunt dit op twee manieren oplossen.
  1. Hernoem je programma in main.py. Run het eenmalig terwijl de ESP is aangesloten. Hierna zal het bestand elke keer bij opstarten worden uitgevoerd.
  2. Maak een bestand met de naam main.py op je ESP en roep van daaruit ssd1306test.py aan. Dat kan in één regel: exec(open('./ssd1306test.py').read(),globals()) .uPyCraft doet dit automatisch als je met rechts op de programmanaam in het linkse menu onder device klikt en kiest voor "default run". De naam wordt vervolgens rood weergegeven.

Hieronder beschrijf ik enkele voorbeeldprogramma's.

Meten van het magneetveld [ESP32]

Een ESP32 heeft een ingebouwd hallplaatje. Hiermee kan de grootte van een magneetveld worden bepaald. Je kunt ook zien in elke richting het magneetveld staat, want de waardes kunnen positief of negatief zijn. Hoewel de grootte van het magneetveld wordt aangegeven zul je hier niet veel aan hebben, onder andere omdat de nauwkeurigheid niet groot is. Toepassingen zijn: magnetische schakelaars en toerentellers. Hierbij hoef je niet te weten hoe groot het magneetveld is; alleen of het boven een drempel is gekomen. Om de magneetveldlezer te kunnen gebruiken moet de bibliotheek esp32 geïnstalleerd zijn. uPyCraft doet dat standaard niet in de huidige versie, maar als je een bin bestand download van http://micropython.org/download/ en dat op de esp flasht dan gaat dit wel automatisch goed met uPyCraft. Hieronder vind je de code die twee keer per seconde de sensor uitleest. Houd een sterke magneet tegen de sensor en kijk wat er gebeurt. Als je de magneet omdraait dan zie je als het goed is een groot verschil.
import esp32, time
while True:
  print(esp32.hall_sensor())
  time.sleep(0.5)

Micro blink (= knipper) programma

Knipper programma's worden vooral gebruikt om te testen of alles goed werkt. Je hebt hierboven al een knipper programma gezien. Het kan ook in 5 regels code.
import machine, time
led = machine.Pin(2, machine.Pin.OUT)
while True:
    led.value(not led.value())
    time.sleep(0.5)
LET OP: bij de ESP32 bordjes kan een andere pin gebruikt worden voor de ingebouwde led. Vaak is dat aangegeven op het bord. Zo kwam ik naast pin 2 ook pin 1, pin 5, pin 22 en pin 24 tegen. Er zijn ook ESP32 bordjes zonder programmeerbare led (esp32_devkitc_v4 bijvoorbeeld).
Tip. Bij de meeste versies van microPython kun je in plaats van led.value() ook led() gebruiken. Bij veel ESP's zijn aan en uit echter omgekeerd led(1) of led.on() zet de led dan uit en led(0) of led.off() zet hem dan aan...

Asymmetrisch knipperprogramma

Als je een knipperprogramma wilt maken waarbij de led langer aanblijft dan uit (of omgekeerd) dan kan dat zoals in onderstaand programma. Bij diverse ESP8266 modules gaat de led aan als de spanning laag is. Dat kun je hiermee testen. Als het goed is blijft het ledje anderhalve seconde aan en blijft het een halve seconde uit.
import machine, time
led = machine.Pin(2, machine.Pin.OUT)
while True:
    led.on()
    time.sleep(1.5)
    led.off()
    time.sleep(0.5)

Allerlei schakelaars en drukknoppen

Aan/uit schakelaar

Het maakt niet uit of je een drukschakelaar hebt of een schuifschakelaar: elke schakelaar die schakelt door twee pootjes wel of niet met elkaar te verbinden kun je op dezelfde wijze aansluiten. Om de tekst niet te ingewikkeld te maken, beschrijf ik hier hoe het gaat met een drukknop, die als hij niet wordt ingedrukt verbroken is. Bij schuifschakelaars en drukknoppen die andersom werken verandert er verder niets. Als je een drukschakelaar met vier pootjes op een breadboard prikt houdt er dan rekening mee dat de pootjes twee aan twee met elkaar verbonden zijn. Je kunt hierdoor als je niet oplet gemakkelijk kortsluiting veroorzaken.
Er zijn twee mogelijkheden hoe je kunt schakelen: naar GND of naar VCC (= 3,3 V). Vaak maakt het niet uit welke van de twee mogelijkheden je kiest, maar soms kan het nodig zijn naar GND te schakelen.
  1. Schakelen naar GND.
    Sluit een van de pootjes aan op GND en de andere op een digitale pin, in mijn geval op pin 4. Pin 4 moet nu weten of de input 0 V (GND) is of niet. Je moet er dus voor zorgen dat als de schakelaar niet ingedrukt is er een voldoend hoge spanning op staat, bijvoorbeeld VCC. Dat kun je doen door een zogenaamde pull-up weerstand te gebruiken: een weerstand van enkele tientallen kilo-ohms tussen de gebruikte pin en VCC. Nu is het zo dat veel pinnen van de ESP32 en ESP 8266 al ingebouwde pull-up weerstanden hebben. Je kunt deze vanuit MicroPython aanzetten. Ik heb dat in het voorbeeld hieronder gedaan! Als je deze zeer eenvoudige schakeling bouwt dan zul je zien dat dit heel goed werkt. Als je andere pinnen wilt gebruiken dan zul je moeten uitzoeken welke pinnen een ingebouwde pull-up weerstand hebben, of je moet er zelf een aansluiten. In het laatste geval is de instructie Pin.PULL_UP overbodig, maar doet ook geen kwaad.
    from machine import Pin
    schakelaar = Pin(4, Pin.IN, Pin.PULL_UP)
    led = Pin(2, Pin.OUT)
    while True:
      if schakelaar.value() == 0:
        led.value(1)
      else:
        led.value(0)
    
  2. Schakelen naar VCC
    Sluit op een van de pootjes van de schakelaar de 3,3 V van de ESP32 of ESP8266 aan. Gebruik hiervoor geen externe voeding, tenzij deze hooguit 3,3 V geeft. Het andere pootje gaat naar een van de digitale pinnen van de ESP, in mijn geval pin 4. Bij mij werkt nu hetzelfde programma als hieronder staat (onder het volgende kopje). Eigenlijk kan dat niet, want als de knop niet wordt ingedrukt dan is kant die naar pin 4 gaat nergens op aangesloten. Het is niet vanzelfsprekend dat deze dan naar 0 gaat, maar kennelijk is dat toch het geval. Als jouw knop onbetrouwbaar werkt (in de uit-stand) dan kun je dit oplossen door een pull-down weerstand te gebruiken: een weerstand van enkele tientallen kilo-ohms van pin 4 naar aarde. In MicroPython kun je opgeven dat de interne pull-down weerstand moet worden gebuikt, maar dan moet je eerst uitzoeken welke pinnen überhaupt een interne pull-down weerstand hebben.

Aanraakschakelaars en dergelijke

Als je een schakelaar hebt die een signaal geeft zodra hij geactiveerd wordt dan kan het programma eenvoudiger worden. In het voorbeeld gebruik ik pin 4 om het signaal in te lezen. Om het eenvoudig te houden gebruik ik de ingebouwde led op pin 2 om te zien of de schakelaar werkt. Ik heb dit getest met twee verschillende soorten aanraakschakelaars.
from machine import Pin
schakelaar = Pin(4, Pin.IN)
led = Pin(2, Pin.OUT)
while True:
  if schakelaar.value() == 1:
    led.value(1)
  else:
    led.value(0)

I²C scanner

Als je niet weet wat het adres is van een I²C apparaat, dan kun je dat vinden via dit programma. Zoals het hier is werkt het met de standaardaansluiting van een nodeMCU ESP32. Je moet dan SCA aansluiten op pin 21 en SCL op pin 22. Als je andere pinnen kiest dan moet je dat in de tweede regel aanpassen.
LET OP: de MicroPython bibliotheek is nogal kritisch. Daarom kan deze gemakkelijk een I²C apparaat missen. Dit kun je voorkomen door een weerstand van enkele kΩ's tussen SDA en VCC en een tussen SCL en VCC te zetten. Bij de vergelijkbare Arduino software is dat zelden nodig.
from machine import Pin, I2C
i2c = I2C(scl=Pin(22), sda=Pin(21)) # Zet hier de feitelijke I2C pinnen.

adres = i2c.scan()

if len(adres) == 0:
  print("Geen i2c apparaten gevonden !")
else:
  print("Gevonden!")
  for a in adres:  
    print("Decimaal adres: ", a, " | Hexadecimaal adres: ", hex(a))

Vind de grootte van het flash geheugen

Hieronder staat een eenvoudig programma, waarmee je kunt bepalen hoe groot het flash geheugen is. De uitkomst wordt weergegeven in de terminal/shell.
import esp
print("De grootte van je flash geheugen is", esp.flash_size(), "bytes")
De uitkomst:
De grootte van je flash geheugen is 4194304 bytes
>>>
De ESP8266 heeft 4 MB geheugen. Bij harde schijven wordt 4 MB vertaald als 4000000 byte, maar bij ESP's is het 4×220 = 4194304 bytes. Officieel heet dit 4 MiB (4 Mebibyte).

I2C display SSD1306

uPyCharm heeft een voorbeeldprogramma voor dit display dat goed werkt, maar een beetje rare tekst laat zien. In de bijbehorende (al aanwezige) bibliotheek vind je ook functies om lijnen, rechthoeken e.d. te tekenen, maar die zitten niet in de demo. Ik heb de demo aangepast, zodat je ook kunt zien hoe je een rechthoek tekent. Het tekenen van een gevulde rechthoek (met fillrect) is me niet gelukt. Op de foto rechts zie je hoe de tekst wordt weergegeven. Ik heb om overbelichting te voorkomen bij deze foto de lichtsterkte sterk onderdrukt met de instructie lcd.contrast(1), die ook in de bibliotheek zit.
from machine import Pin, I2C
import ssd1306, time

i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000)  # Zet hier welke pinnen je gebruikt voor I2C
lcd = ssd1306.SSD1306_I2C(128, 64,i2c)          # Geef de breedte en hoogte (in pixels) van het scherm op
for i in range(0, 32, 2):
  lcd.rect(i, i, 128 - 2 * i, 64 - 2 * i, 1)
  lcd.show()                                    # Laat de lijn zien
  time.sleep(0.5)
lcd.fill(0)                                     # Maak het display schoon
lcd.text("Hallo", 0, 0)                        
lcd.text("allemaal !", 24, 16)                       
lcd.text("1306-test klaar.", 0, 32)                       
lcd.show()                                      # Laat de tekst zien

Numeriek 7-segments display met 4 cijfers

Voor dit display zul je een bibliotheek moeten gebruiken. Dit gaat anders dan bij de Arduino, waarbij je als je een bibliotheek hebt geïstalleerd hebt vanuit de IDE voorbeelden kunt kiezen. Een probleem bij minder gebruikte MicroPython bibliotheken is dat deze soms lastig zijn te downloaden. Dat geldt ook voor deze bibliotheek. Download hem hier. (Bij sommige browsers wordt de file geopend als tekst file. Je moet dan mogelijk nog rechts klikken en voor "Sla op als...." kiezen.) Er zijn verschillende manieren om de bibliotheek op je ESP te krijgen. In uPyCraft kan het zo: kies en zoek de bibliotheek. Run deze via . Als het goed is, is de bibliotheek nu op je ESP opgeslagen. Om de bibliotheek te testen kun je een nieuw programma maken via . Kopieer eventueel de onderstaande code en plak deze in het nieuwe programma. Bewaar het programma met met een door jou te kiezen naam (bijvoorbeeld tm1637_test.py). Kijk nog even na of de SDA en CLK pin kloppen. Bij de ESP32 zul je doorgaans de pinnen 22 (voor SCL) en 21 (voor DIO -- dit is SDA) kiezen. Als het niet werkt draai dan deze pinnen om of test met het eerder beschreven programma of je minstens een adres kunt vinden. Bij de ESP8266 kies je normaal gesproken voor de pinnen 4 en 5 (= D1 en D2).
import tm1637, time
from machine import Pin
tm = tm1637.TM1637(clk=Pin(5), dio=Pin(4))
tm.brightness(1)                # voorkom overbelichting als je een foto maakt. Laat anders weg.
tm.write([127, 255, 127, 127])  # alle LEDS aan "88:88"
time.sleep(1)

tm.write([0, 0, 0, 0])          # alle LEDS uit
time.sleep(1)

tm.write([63, 6, 91, 79])       # toon "0123"
time.sleep(1)

tm.write([57, 63, 63, 56])      # toon "COOL". tm.show('cool') mag ook!
time.sleep(1)

tm.show('help')                 # toon "HELP"
time.sleep(1)

tm.numbers(12, 59)              # toon "12:59"
time.sleep(1)

tm.number(-123)                 # toon "-123"
time.sleep(1)

tm.temperature(24)              # toon temperatuur '24 °C'
Dit demoprogramma laat vrijwel alle mogelijkheden van het display zien.

LCD Tekstdisplay [ESP8266]

Deze zeer populaire displays zijn te koop met een I²C interface. Dat maakt het werken ermee erg veel makkelijker. Er zijn diverse bibliotheken voor dit display gemaakt, maar vaak werken deze niet goed. Ik gebruikte een interface die speciaal bedoeld is voor de ESP8266. Ik heb er een onnodige (verwarrende) regel uitgehaald. U kunt de twee benodigde bestanden in de volgende regel downloaden. Run eerst lcd_api.py en daarna esp8266_i2c_lcd.py. Vervolgens kunt u het testprogramma hieronder uittesten. Als u een foutmelding krijgt probeer dan het andere adres. Controleer ook goed of u de I²C interface goed hebt aangesloten. Ik heb de bibliotheek getest met de WeMos mini D1 en met tekst displays met 2 × 16, 2 × 20, 2 × 24 en 4 × 20 regels (met beide mogelijke adressen). Bij alle displays wordt ook het eigengemaakte lachebek symbool goed weergegeven. Ik heb deze bibliotheek ook uitgeprobeerd met een ESP32, en dat bleek bij enkele displays goed te gaan, maar ook bij enkele niet. Ik vermoed dat hier twee weerstanden nodig zijn, zoals bij de I²C scanner beschreven, maar dat heb ik nog niet getest.
from time import sleep
from esp8266_i2c_lcd import I2cLcd
from machine import Pin, I2C
I2C_ADDR = 0x27 # Kies het juiste adres (0x27 = 39 of 0x3F = 63)

i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000)  # Op de WeMos D1 mini zijn dit de pinnen D1 en D2

lcd = I2cLcd(i2c, I2C_ADDR, 2, 16) # zet hier de juiste gegevens (aantal rijen, aantal kolommen) 
lcd.putstr("Display werkt!\nHet adres is " + hex(I2C_ADDR))
sleep(3)
lcd.clear()
lcd.putstr("Ik zet de achter\ngrond even uit")
sleep(1)
lcd.backlight_off()
sleep(1)
lcd.backlight_on()
lcd.clear()
lcd.putstr("En weer aan...")
lachebek = bytearray([0, 0, 0x0A, 0, 0, 0x11, 0x0E, 0]) # maak lachebek symbool
lcd.custom_char(0, lachebek)  # zet dit symbool op plaats 0 in het geheugen van het display
lcd.move_to(7, 1)             # ga naar het midden van regel 2
lcd.putstr(chr(0))            # zet daar het lachebekje
sleep(2)
lcd.clear()
count = 0
while True:
        lcd.move_to(0, 0)
        lcd.putstr(str(count))
        sleep(1)
        count += 1

21 lucifers spel met een 20 bij 4 display

Het 21 lucifers spel in bedrijf
Als voorbeeld van wat je met een tekst display kunt doen, laat ik hier een simpele uitvoering van het 21 lucifers spel zien. Er liggen 21 lucifers op de tafel. Het is de bedoeling dat jij en de computer omstebeurt maximaal drie lucifers wegnemen. Degene die de laatste lucifer wegneemt verliest. In deze uitvoering wint de computer altijd en jij weet als programmeur goed hoe dat werkt. Je moet het dan ook laten spelen door mensen die dit spel niet kennen.
Ik heb bij dit spel aanraakschakelaars gebruikt. Deze gaan naar VCC als je ze aanraakt. Als je een gewone drukknop wilt gebruiken, zorg dan dat deze normaal op GND staat en bij indrukken naar VCC gaat.
Let op: dit display werkt niet goed met 3,3 V, gebruik daarom de 5V uitgang of gebruik een step-up converter.
Ik ben van plan meer spelen te gaan ontwikkelen voor het 20 × 4 display, maar dat doe ik waarschijnlijk in C++, zodat het ook werkt met Arduino's.
from time import sleep
from esp8266_i2c_lcd import I2cLcd
from machine import Pin, I2C

strKeus = [chr(1) + chr(1) + 'n\nlucifer', 'twee\nlucifers', 'drie\nlucifers']
def ZetLucifers(aantal):
  lcd.clear()
  for i in range(21):
    if i >= aantal:
      lcd.putstr('-')
    else:
      lcd.putstr(chr(0))
    if i == 10:
      lcd.move_to(0, 1)
  
I2C_ADDR = 0x27 # Kies het juiste adres (0x27 = 39 of 0x3F = 63)

i2c = I2C(scl=Pin(5), sda=Pin(4), freq=400000)  # Op veel ESP8266 modules zijn dit de pinnen D1 en D2

lcd = I2cLcd(i2c, I2C_ADDR, 4, 20) # zet hier de juiste gegevens (4 rijen, 20 kolommen) 
lcd.clear()

L = bytearray([14, 31, 14, 4, 4, 4, 4, 4]) # maak lucifer symbool
lcd.custom_char(0, L)  # zet dit symbool op plaats 0 in het geheugen van het display
E = bytearray([2, 4, 14, 17, 31, 16, 14, 0]) # maak het é symbool
lcd.custom_char(1, E)  # zet dit symbool op plaats 1 in het geheugen van het display
  
aantalLucifers = 21
Pin1 = Pin(14, Pin.IN) # D5 (Lolin nodeMCU ESP8266)
Pin2 = Pin(12, Pin.IN) # D6
Pin3 = Pin(13, Pin.IN) # D7

lcd.putstr('    21 Lucifers')
sleep(2)
ZetLucifers(aantalLucifers)
lcd.move_to(0, 2)
lcd.putstr('Kies 1 2 of 3\nlucifers')
while True:
  P1 = P2 = P3 = 0
  while P1 == 0 and P2 == 0 and P3 == 0:
    P1 = Pin1.value()
    P2 = Pin2.value()
    P3 = Pin3.value()
  if P1 == 1:
    Keus = 1
  elif P2 == 1:
    Keus = 2
  else:
    Keus = 3
  ZetLucifers(aantalLucifers - Keus)
  lcd.move_to(0, 2)
  lcd.putstr('U nam ' + strKeus[Keus - 1] + ' weg')
  sleep(3)
  lcd.move_to(0, 2)
  lcd.putstr('Ik neem ' + strKeus[3 - Keus] + ' weg  ')
  sleep(1)
  aantalLucifers -= 4
  ZetLucifers(aantalLucifers)
  lcd.move_to(0, 2)
  lcd.putstr('Kies 1 2 of 3\nlucifers')
  if aantalLucifers == 1:
    ZetLucifers(1)
    lcd.move_to(0, 2)
    lcd.putstr('U hebt verloren')
    break
sleep(5)
lcd.clear()

Temperatuurmeter met 1-Wire protocol [ESP8266]

Hieronder zie je een simpel programma om de temperatuur uit te lezen van een Dallas DS18B20 thermometer. Dat kunnen transistors zijn, of thermometers die zijn ingebouwd in een waterdichte behuizing. In beide gevallen moet je tussen VCC en de signaalleiding een weerstand van ca. 4,7 kΩ monteren.
Het programma zou ook moeten werken met een ESP32 module, maar... bij mij werkte dit niet en ik heb op internet gevonden dat er mogelijk een probleem is met het nieuwste MicroPython systeem. Het kan dus goed zijn dat dit bij jou ook met een ESP32 wel goed werkt.
Dit programma werkt leest alleen de eerste aangesloten thermometer uit. Het 1-Wire protocol maakt het mogelijk om tientallen apparaten tegelijk uit te lezen. Als je dat wil doen dan moet kun je daar het array roms voor gebruiken dat je in de zesde regel met ds_sensor.scan() terugkrijgt.
import machine, onewire, ds18x20, time

ds_pin = machine.Pin(4)
ds_sensor = ds18x20.DS18X20(onewire.OneWire(ds_pin))

roms = ds_sensor.scan()

if roms == []:
  print('Geen DS thermometers gevonden')
  raise SystemExit         # Stop het programma
elif len(roms) == 1:
  print('Er is een DS thermometer gevonden')  
else: 
  print('Meer dan een DS thermometer gevonden. Ik gebruik alleen de eerste')

rom = roms[0]              # Gebruik alleen de eerste thermometer
while True:
  ds_sensor.convert_temp()
  time.sleep_ms(750)
  print(round(ds_sensor.read_temp(rom), 1))
  time.sleep(1) 
Nota bene. Er zijn ook thermometers zoals de TMP36, die een spanning geven die lineair toeneemt met de temperatuur. Dat is in principe makkelijker. Om de spanning om te zetten in een digitaal signaal heb je een Analoog naar Digitaal Converter (ADC) nodig. De ESP8266 heeft één ADC en de ESP32 heeft vele ADC's aan boord. Helaas werken deze zo slecht dat ze in alleen bruikbaar zijn als je ze goed kunt ijken. Ik heb beide systemen getest met het volgende resultaat: ESP8266: temperatuur bijna 10 graden te hoog; ESP32 temperatuur bijna 10 graden te laag. Ik heb dat met verschillende uitvoeringen getest met steeds vergelijkbaar slechte resultaten. Ook op internet zie je veel negatieve recensies over de ADC's van de ESP32. Met de Dallas 1-Wire thermometer heb je deze problemen niet.

Temperatuur en vochtigheid met de DHT11 (1-Wire protocol)

De DHT11 gebruikt evenals de Dallas thermometer een 1-Wire protocol, maar dit werkt net iets anders. De benodigde bibliotheek is kennelijk direct aanwezig, want mijn demo werkte meteen. Hieronder zie je de demo. Ik heb het getest met een ESP32-WROOM-32 en een WeMos ESP8266 D1 mini.
import dht, machine, time
d = dht.DHT11(machine.Pin(2))

while True:
  time.sleep(1)  # Kies (ingeval van de DHT11 minimaal 1 seconde
  d.measure() 
  print("Temperatuur: ", d.temperature(), "C | Vochtigheid: ", d.humidity(), "%")
Je ziet dat ik een seconde wacht voor ik de eerste keer ga meten. Daarmee voorkom je dat de eerste waarde niet klopt.
Ik heb geen moeite gedaan om een °-teken te maken, want of en hoe dit werkt hangt af van de terminal die je gebruikt.


1Je kunt binaire bestanden ophalen bij http://micropython.org/download/ voor diverse microprocessoren; voor de ESP32 bij http://micropython.org/download/esp32/ en voor de esp8266 bij http://micropython.org/download/esp8266/. Kies altijd de laatste stabiele versie. Terug.