Schaltwandler sind universelle Spannungversorgungseinheiten, die sich immer größerer Beliebtheit erfreuen und in den meisten Fällen den analogen Reglern vorgezogen werden, da sie wesentlich effektiver arbeiten. Leider erfolgt die Einstellung der Ausgangsspannung bisher immer noch analog mittels Potentiometer/Trimmer. Das ist ein Problem, wenn man die Ausgangsspannung mittels Microcontroller einstellen möchte. Ich habe mir drei Lösungsmöglichkeiten für dieses Problem angesehen:

  • Umschaltbare Widerstände
  • PWM
  • DAC mit externem Komparator

Hinweise zur Simulation

Ich habe die Simulationen mit dem kostenlosen LTspice XVII erstellt. Als Grundlage habe ich das Beispiel 1938.asc eingesetzt. Das habe ich ausgewählt, weil die Simulation damit relativ problemlos funktionierte. Es ist nur ein Beispiel und hat nichts mit dem später eingesetzten IC’s zu tun. Auch der Operationsverstärker OP07 ist nur ein Beispiel. Später werde ich eher den LM358 oder LM324 einsetzen. Diese sind aber bei LTspice nicht dabei.

Die Simulationen sind nur ein erster Versuch mit der Materie vertraut zu werden. Die wirklichen Ergebnisse werde ich später bei echten Aufbauten erhalten.

Die Bilder und Plots aus LTspice sind auf der Website nur sehr schlecht zu erkennen. Ein Linksklick mit der Mouse ins Bild zeigt es in voller Größe und dann ist auch alles gut zu erkennen.

Zum Nachvollziehen werde ich die Dateien am Ende der Kapitel anhängen, so dass Ihr sie herunterladen könnt.

Die Originalschaltung

In der Standardschaltung wird aus R1 und R2 ein Sapnnungsteiler gebildet der die Ausgangsspannung bestimmt.

Standardschaltung aus dem Beispielfile 1938.asc

Hier die Standardbeschaltung mit Impulslast.
Der Plot der Standardbeschaltung mit Impulslast.

Umschaltbare Widerstände

Noch nicht bearbeitet.

PWM

Noch nicht bearbeitet.

DAC mit externem Komparator

Die Schaltwandler IC’s besitzen einen eingebauten Komparator, der die mittels Spannungsteiler heruntergeteilte Ausgangsspannung mit einer internen Referenzspannung vergleicht und so den Schalttransistor ansteuert. Wenn eine externe Referenz möglich wäre, könnte man darüber die Ausgangsspannung mittels DAC einstellen. Da diese Möglichkeit nicht besteht, muss ein externer Komparator eingesetzt werden. Der besteht im einfachsten Fall aus einem Operationsverstärker. Der -Eingang wird mit dem DAC verbunden, der +Eingang mit der Ausgangsspannung und der Ausgang mit dem Feedback-Eingang (FB) des IC’s.

Schaltbild der Simulation in LTspice

Im obigen Schaltbild befindet sich der Operationsverstärker in der Bildmitte (OP07). V2 entspricht dem DAC. Rechts habe ich mi I1 eine Impulsstromsenke hinzugefügt. So wird der Strom zwischen 200 mA und 1,7A hin und her geschaltet. Das habe ich eingefügt, weil mich das Regelverhalten der veränderten Schaltung interessiert.

Das Ergebnis der Simulation für 3,3 Volt ausgangsspannung ist im folgenden Plot dargestellt:

Ergebnis der Simulation

Die blaue Line zeigt die Ausgangsspannung, die rote Linie den Ausgangsstrom und die grüne Linie die Spannung am FB-Eingang des IC’s. Die Reaktion der Ausgangsspannung auf die Laständerung ist dieser Darstellung kaum wahrnehmbar.

Plot mit besserer Auflösung der Ausgangsspannung.

Auch bei besserer Auflösung geht der Einfluß der Stromänderung in den systembedingten Spannungsschwankungen unter. Nur im Einschaltmoment bricht die Spannung kurz auf 3,0 Volt ein.

Allerdings ist deutlich angestiegener Rippel zu erkennen. Das dürfte an der Slew Rate von 0.3 V/μs des OP07 liegen. Für LM358/324 ist der selbe Wert im Datenblatt zu finden.

Ich habe die Simulation mit 5 Volt wiederholt. Auch dabei zeigte sich, dass die Pannung im Einschaltmoment für einen kurzen Zeitraum unter die -5%-Grenze (4,75 Volt) von 5 Volt absinkt.

Plot bei 5 Volt

Hier sind es 4,63 Volt. Nun interessiert mich, ob der 100R Widerstand in der FB-Zuleitung einen Einfluß hat:

Nun habe ich den Widerstand 0R gemacht. Da das bei LTspice nicht geht habe ich den Wert auf 0,000001R gesetzt. Damit ergibt sich tatsächlich eine kleine Veränderung. Der Wert liegt jetzt bei 4,69 Volt. 60 mV machen den Kohl nicht wirklich fett.

Dieser Spannungseinbruch dauert ca. 50 µS.

Wahrscheinlich lässt sich dieser Spannungseinbruch durch einen Stützkondensator direkt an der Last reduzieren.

Zusammenfassung und Ausblick

Grundsätzlich funktioniert dieses Konzept. Als Operationsverstärker kommen aber nur sehr schnelle Typen in Frage. Bei der Simulation wurden die Eigenschaften des IC’s durch den Operationsverstärker deutlich verschlechtert.

Simulation mit schnellem OP

ADA4891 mit 190 V/µs

Sonderbarerweise zeigte der erste Plot völlig absurde Linienzüge. Die 3,3 Volt wurden nicht erreicht. Schließlich konnte ich durch verlängern der Beobachtungszeit dann doch noch ein brauchbares Ergebnis sehen. Der Start dauert >3 ms bis die 3,3 Volt erreicht sind. Dann sieht alles normal aus.

Um alle Störfaktoren auszuschalten hatte ich die Impulsstromsenke abgekniffen. Nun da alles Funktioniert miot einem neuen Timing ein neuer Versuch:

Sonderbarer Weise schaft es die Schaltung nicht die Last von 1,5A auszuregeln. Bei den vorherigen Simulationen funktionierte das einwandfrei.

Das Problem hat der Elko C5 mit 220µF gemacht, den ich bei den ersten Simulationen mit einem OP hinzugefügt hatte, um den Rippel zu reduzieren. Warum dort das Problem nicht aufgetreten ist, erschließt sich mir nicht.

Mit nur 22µF funktioniert es wie es soll. Die FB-Spannung habe ich ausgeblendet weilsie sonst alles andere überdeckt.

Nun ist der Rippel wieder größer aber die Schaltung funktioniert.

Hier wurde C1 von 22 auf 100 µF erhöht. Das funktioniert auch noch Problemlos. Der Spannungseinbruch bei Last ist < 20 mV.
Der Schaltplan der obigen Simulation.

Einen LDO-Regler nachschalten

Es wird empfohlen für eine besonders saubere Spannung einen analogen LDO-Regler nachzuschalten. Das wollte ich natürlich auch simulieren.

Links:

Es werden von chinesischen Herstellern und Händlern diverse günstige AC/DC-Wandler angeboten. Die Frage ist wie es um Störspannungen auf der Netz- und Niederspannungsseite bestellt. Kürzlich bin ich auf Schaltungsvorschläge zur Entstörung dieser kleinen Netzteile gestoßen. Das habe ich mir bei Hi-Link einmal näher angesehen:

und die entsprechenden Bauteileempfehlungen:

Hi-Link schlägt für alle Modelle diese Entstörmaßnahme vor.

Wobei ich aber auch andere Vorschläge gefunden habe. So findet sich bei FEIYANG für das HKL-5M05 Modul diese asymmetrische Entstörung:

DC/DC-Wandler

Für DC/DC-Wandler habe ich sogar diesen aufwändigen Vorschlag gefunden (https://de.aliexpress.com/item/4000418841792.html?spm=a2g0o.store_pc_groupList.8148356.2.657672e6qpr5vC):

Bauteile

Das der ADC der ESP’s ziemlich umbrauchbar ist ist inzwischen hinlänglich bekannt. Allerdings benötigt man ja nicht immer eine hohe Genauigkeit. Zum Ein- und Ausschalten eines Lüfters kommt es meist ein 1, 2 Grad nicht an. Genau das ist meine Anwendung. Ich möchte einen Lüfter bei ca 45 °C ein- und bei ca. 35 °C wieder ausschalten. Dazu bedarf es keiner exakten Werte, sondern nur Schwellwerte, die ggf. per Test ermittelt werden können. Genauigkeit und Linearität des ADC spielen hier keine Rolle. Deshalb scheint mir der intere ADC des ESP32 dafür geeignet zu sein. Das möchte ich hier ausprobieren.

Hier noch ein paar interessante Infos über den ADC aus dem Programmierhandbuch von Espressif (Link unten):

Rauschen minimieren

Der ESP32 ADC kann empfindlich auf Rauschen reagieren, was zu großen Diskrepanzen in den ADC-Messwerten führen kann. Um das Rauschen zu minimieren, kann der Anwender einen 0,1uF-Kondensator an das verwendete ADC-Eingangspad anschließen. Multisampling kann auch verwendet werden, um die Auswirkungen des Rauschens weiter zu minimieren.

ADC-Kalibrierung

Die API esp_adc_cal/include/esp_adc_cal.h bietet Funktionen zur Korrektur von Unterschieden in den gemessenen Spannungen, die durch Variation der ADC-Referenzspannungen (Vref) zwischen den Chips verursacht werden. Per Design ist die ADC-Referenzspannung 1100mV, die tatsächliche Referenzspannung kann jedoch zwischen 1000mV und 1200mV bei verschiedenen ESP32 liegen.

Die Kurve von randomnerdtutorials.com zeigt auch noch eine ausgeprägte Nichtlinearität im oberen Bereich:

Test

Für den Test habe ich eine kleine Platine gebaut. Sie ist für einen M5Stack C bzw. M5Stack C Plus vorgesehen. Sie enthält eine Reihe Vorwiderstände, die mittels Jumper umgesteckt werden können, einen 3poligen Sockel für den NTC. Der parallele Sockel ermöglicht es die Spannung am NTC direkt zu messen.

Um die Temperatur am NTC zu messen habe ich ein Termoelement daran montiert.

Für den Test habe ich eine Heissluftpistole benutzt und für die Temperatureinstellung den Abstand zum NTC variiert.

Diese Schaltung habe ich angewendet:

Meine Tests haben die folgenden Werte erbracht.

  • 21,4 °C – 2850
  • 35 °C – 2200
  • 45 °C – 1750
  • 50 °C – 1500
  • 60 °C – 1150

Dabei muss man berücksichtigen, dass die Messwerte des ADC schwanken (siehe oben).

Software:

Dieses Programm ließt die Temperatur und reagiert auf das Über- und Unterschreiten der Grenzwerte, die ich hier als Raw-Werte des ADC eingesetzt habe.

Das die Abfragen in einer Interrupt-Service-Routine laufen hat mit diesem Thema hier nichts zu tun. Sie gehören üblicherweise in die Mainloop.

Links:

Schraubendreher u.ä.

Hier habe ich eine Aufstellung gemacht welche Werkzeuge für Schrauben von M2, M2,5 und M3 sinnvoll sind um alle Erfordernisse abzudecken:

  • Imbus
    • M2 => SW1,5
    • M2,5 => SW2,0
    • M3 => SW2,5
  • 6-Kant Mutter und Schraubenkopf
    • M2 SW4
    • M2,5 SW5
    • M3 SW5,5
  • Kreuzschlitz (PH)
    • M2 PH1
    • M2,5 PH1
    • M3 PH1
  • Protzi (PZ)
    • M2 PZ1
    • M2,5 PZ1
    • M3 PZ2
  • Schlitz
    • M2 0,5×3,8
    • M2,5 0,6×4,5
    • M3 0,8×5,5
  • Torx
    • M2 T6
    • M2,5 T8
    • M3 T10
  • Maul- und Ringschlüssel
    • M2 SW4
    • M2,5 SW5
    • M3 SW5,5

Zangen und Greifwerkzeuge

  • Seitenschneider
  • Kombizange
  • Spitzzange
  • Pinzetten
  • Abisolierer

Lötutensilien

Fixierungen

Als Basis für die PEL035 dient das Chinamodul XY-FZ35. Dieses Modul kann Spannungen von 1,5 V ~ 25 V und Ströme bis 5A bei einer maximalen Belastung von 35W verarbeiten. Die Einstellung des Laststromes erfolgt mittels Drehimpulsgeber an der Frontplatte oder über eine serielle Schnittstelle. Siehe: https://www.peters-bastelkiste.de/elektronische-last-xy-fz35/

Für die drahtlose Steuerung kommt ein M5ATOM Lite zum Einsatz. Eine ADC-Unit zur Messung der Spannung am Lasteingang. Das FZ-35-Modul ermittelt diese Spannung zwar auch, verwendet sie aber nur intern. Ausserhalb steht sie nicht zur Verfügung. Die Lüftersteuerung erfolgt vom M5ATOM aus. Ein Spannungsteiler aus Widerstand und NTC liefert eine der Temperatur umgekehrt proportinale Spannung die vom internen ADC des M5ATOM gemessen wird. Dieser Wert wird zur 2-Punkt-Steuerung des Lüfters herangezogen (siehe https://www.peters-bastelkiste.de/temperaturmessung-mit-esp32-und-ntc/).

Netzteil

Das Netzteil liefert 5 Volt für den M5Atom und 12 Volt für den Lüfter und das FZ-35-Modul. Es ist ganz einfach mit AC/DC-Modulen aufgebaut. Allerdings habe ich es noch um einen Tiefpassfilter zum Netz hin und Kondensatoren am Ausgang ergänzt. Diese Maßnahmen werden von einigen Anbietern vorgeschlagen. Hi-Link schlägt sogar eine stromkompensierte Drossel vor.

M5Atom Adapter

Der M5ATOM bekommt einen Adapter, der zum Einen die Befestigung an der Frontplatte ermöglicht, zum Anderen die Anschlüsse des M5ATOM auf einer 14-poligen 2,54mm Stiftleiste sammelt.

PINBedeutung
1Ground
2Ground
3+ 3,3 Volt vom M5ATOM
4+ 3,3 Volt vom M5ATOM
5+ 5 Volt – Stromversorgung für M5ATOM
6+ 5 Volt – Stromversorgung für M5ATOM
7GPIO 23
8GPIO 19
9GPIO 33 – ADC1-5
10GPIO 22
11GPIO 21 – TX
12GPIO 25 – RX
13Grove – SCL
14Grove – SDA

Platine für den Adapter

Erste Version der Platine
V. 1.1 mit Lötads für 0,1µF Kondensator am ADC Eingang unten rechts

Steuerung

Die Steuerungsplatine dient in erster Linie der Signalverteilung zwischen den verschiedenen Baugruppen. Weiterhin enthält sie den NTC zur Temperaturmessung und einen Transistor zum Schalten des Lüfters.

Die Platine

Inzwischen habe ich eine Platine entworfen und fertigen lassen.

Fehler auf der Platine

  • Eine eventuelle Pegelanpassung der RX/TX-Signale zwischen FZ35 und M5ATOM fehlt.
  • Positive Spannung für FZ35 an PIN 4 der 5-poligen Verbindung fehlt.
Die korrigierte Version 1.1

Die Geschichte von einem der auszog ein Abenteuer zu erleben.

Elementare Grundkenntnisse vom Netzwerk sind mir ja bekannt. Meine LAN-Verkabelung habe ich alleine hinbekommen. Das beschränkte sich aber überwiegend darauf Stecker in Buchsen zu stecken, Kabel zu verlegen und die Kabelenden in die richtigen Kontakte zu pressen.

Mit der Softwareseite, geschweige denn WLAN habe ich mich bisher nicht auseinander gesetzt. Nun möchte ich aber, dass die M5Stack Geräte über WLAN kommunizieren. Dafür sind sie schließlich gemacht.

Die UIFlow-IDE bietet dazu unter Blockly nur sehr begrenzte Möglichkeiten. Also wenn es über HTTP gehen soll. MQTT z.B. funktioniert gut. Die HTTP-Blöcke habe ich aber noch nicht verstanden. Micropython hingegen bietet da eine ganze Menge.

Es sind offenbar mehre Schritte erforderlich:

  • Mit dem Netzwerk verbinden
  • Ein Socket installieren
  • Ein Übertragungsprotokoll installieren

Mit einem Netzwerk verbinden.

Meistens verbindet sich ein M5Stack Gerät gleich nach dem Einschalten mit dem Netzwerk, da diese Verbindung für die Programmierung benötigt wird.

<< Ausprobieren, ob auch bei USB-Betrieb, bzw. wenn eine App läuft eine WLAN-Verbindung hergestellt wird. >>

Damit ein eine WLAN-Verbindung eingerichtet oder eine vorhandene erkannt wird ist diese der Software bekannt zu machen. Dazu dient die Library network.

# network Library importieren
>>> import network

# WLAN Interface erzeugen und aktivieren
>>> wlan = network.WLAN(network.STA_IF)
>>> wlan.active(True)

# Mit Wlan verbinden
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'
wlan.connect(ssid, password)

# auf bestehende Verbindung prüfen
>>> wlan.isconnected()
True
# Oder auf Verbindung warten und ausgeben
>>> while wlan.isconnected() == False:
>>>   pass
>>> print('Connection successful')
>>> print(station.ifconfig())

# WLAN Daten abfragen (Geräte-IP, Netzwerkmaske, Gateway, DNS-Server)
>>> wlan.ifconfig()
('192.168.5.89', '255.255.255.0', '192.168.5.1', '192.168.5.1')

# Eigene IP-Adresse ermitteln
>>> netzwerk = wlan.ifconfig()
>>> netzwerk
('192.168.5.89', '255.255.255.0', '192.168.5.1', '192.168.5.1')
>>> netzwerk[0]
'192.168.5.89'
# So gehts am Kürzesten
>>> wlan.ifconfig()[0]
'192.168.5.89'

# Die vorhandenen Accesspoint suchen
>>> wlan.scan()
[(b'ESP_9235A1', b'P\x02\x91\x925\xa1', 1, -50, 0, False), (b'Kapest-Fritz', b'\x94\xb9~\x8d<e', 1, -55, 3, False), (b'Kapest-Fritz', b'\x9c\xc7\xa6\x16\xe51', 1, -77, 4, False)]

# WLAN Interface beenden
>>> wlan.active(False)

# MAC Adresse ermitteln
>>> wlan.config('mac')
b'\x94\xb9~\x8b\xb9X'

Nun kennt das Netzwerk meinen M5Stack und dieser das Netzwerk zu dem er jetzt gehört.

In mehrere bekannte Netzwerke automatisch einloggen.

Die Überschrift ist etwas irreführend. Natürlich kann sich der M5Stack immer nur in ein Netzwerk zur Zeit einloggen, aber es gibt vielleicht mehrere räumlich getrennte Netzwerke in die es sich automatisch einloggen soll, so wie wir das vom Handy kennen. Z.B. ins WLAN bei mir zu Hause oder in das des Attraktor, je nachdem, wo ich mich gerade befinde.

# zuerst immer ein WLAN erzeugen sonst geht nichts.
>>> import network
>>> wlan = network.WLAN(network.STA_IF)

# nun kann ich nach WLAN-AP's suchen
>>> wlan.scan()
[(b'ESP_9235A1', b'P\x02\x91\x925\xa1', 1, -50, 0, False), (b'Kapest-Fritz', b'\x94\xb9~\x8d<e', 1, -55, 3, False), (b'Kapest-Fritz', b'\x9c\xc7\xa6\x16\xe51', 1, -77, 4, False)]

# Das sieht nicht sehr übersichtlich aus. Mal sehen ob Micropython das auch so sieht:
>>> wlans = wlan.scan()
>>> wlans
[(b'ESP_9235A1', b'P\x02\x91\x925\xa1', 1, -45, 0, False), (b'Kapest-Fritz', b'\x9c\xc7\xa6\x16\xe51', 1, -77, 4, False)]
>>> type(wlans)
<class 'list'>

# Es wird also eine Liste mit den Daten der AP's in Tupels zurückgegeben.
# Ich benötige nur den String der SSID.

# Der versuch die AP-Tupel in einer Schleife auszulesen scheitert.
>>> wlans
[(b'ESP_9235A1', b'P\x02\x91\x925\xa1', 1, -45, 0, False), (b'Kapest-Fritz', b'\x9c\xc7\xa6\x16\xe51', 1, -77, 4, False)]

# So lassen sich alle erreichbaren AP's auflisten:
>>> for i in wlan.scan():
    print(i[0].decode("utf-8"))
    
ESP_9235A1
Kapest-Fritz
WILLY.TEL-71IU1DHQNW
FRITZ!Box 7560 LY
Brian
WLAN-807195
WLAN-372270
Telekom_FON
o2-WLAN79

# Eine einfache Version für Home und Attraktor sähe dann so aus:
>>> for i in wlan.scan():
    if (i[0].decode("utf-8")) == "Kapest-Fritz":
        print("Zu Hause")
    elif (i[0].decode("utf-8")) == "attraktor":
        print("Attraktor")
WARNING:root:Unexpected echo. Expected b'\r\n', got b''
# Es wird \r\n also eine neue Zeile Schaltung vermisst. Funktioniert ansonsten aber:
Zu Hause

''' Nachdem ich mit .decode("utf-8", errors='ignore') herumgespielt habe aber weiterhin diese Warnung erhalten habe. Habe ich aufgegeben und beschlossen die Warnung zu ignorieren. Seitdem ist sie weg.
'''
# Stefan May gab den Tip es mit "ascii" anstatt "utf-8" zu versuchen. Das klappt auch:
>>> for i in wlan.scan():
    if (i[0].decode("ascii")) == "Kapest-Fritz":
        print("Zu Hause")
    elif (i[0].decode("ascii")) == "attraktor":
        print("Attraktor")
        
Zu Hause

Einen Socket einrichten.

Ein Übertragungsprotokoll installieren

Übersetzung des entsprechenden Artikels von Lukasmaximus89 auf Hackster.io aus dem Englischen mit DeepL.com.

Link zum Orginal: https://www.hackster.io/lukasmaximus89/m5stack-micropython-simple-web-server-20a4c4

Verwenden Sie MicroPython, um Ihren M5Stack mit WiFi oder ein Gerät mit AP zu verbinden und eine einfache Webseite zu erstellen, um einige Funktionen des M5Stack zu steuern.

M5Stack MicroPython Simple Web Server

In diesem Projekt verwendete Dinge

Hardware-Komponenten

M5Stack Gerät: https://www.hackster.io/m5stack/products/esp32-basic-core-iot-development-kit?ref=project-20a4c4

Software-Apps und Online-Dienste

Micropython: https://www.hackster.io/micropython/products/micropython?ref=project-20a4c4

Visual Studio Code: https://www.hackster.io/microsoft/products/vs-code?ref=project-20a4c4

Geschichte

ESP32 ist fast zum De-facto-Standard für die IoT-Entwicklung geworden und es sieht nicht so aus, als würde sich das ändern. Egal, ob wir unseren ESP32-basierten M5Stack für die Automatisierung unseres Hauses, die Überwachung unserer Haustiere oder was auch immer Sie mit Ihrem M5Stack machen möchten, wir könnten eine Art Schnittstelle verwenden, auf die wir sowohl über einen Computer als auch über ein Mobiltelefon zugreifen können.

Der einfachste Weg, dies zu tun, ist das Hosten einer einfachen Webseite auf dem M5Stack mit Schaltflächen und Textfeldern, die die Hardware des M5Stack ansteuern und auch Anzeigen seines Verhaltens anzeigen können. Dabei können wir auch einige Grundlagen über Server, Clients und andere Netzwerkterminologie lernen.

Zu Beginn benötigen wir eine MicroPython-Firmware, die wir auf unser Gerät flashen müssen. Zum Zeitpunkt des Schreibens wird die Uiflow-Version 1.3.2 empfohlen. Flashen Sie Ihr Gerät mit dem Programm M5Burner, das Sie im Download-Bereich der M5Stack-Website finden. Wenn der Brenner aus irgendeinem Grund nicht funktioniert, können Sie immer das esptool aus der Kommandozeile verwenden, um es zu flashen.

Sobald Sie die Firmware geflasht haben, müssen Sie sich entscheiden, welche IDE Sie verwenden möchten, um den M5Stack in MicroPython zu programmieren. Es gibt Uiflow, unsere Online-Plattform für die Programmierung mit Blöcken und MicroPython (in diesem Tutorial werden wir nur die Python-Seite verwenden) oder unser neues Plugin für vscode. Sehen Sie hier, wie Sie es einrichten können.

Sobald Sie sich in der MicroPython-IDE Ihrer Wahl eingerichtet haben, können wir mit dem Schreiben des Programms beginnen, aber zuerst wollen wir versuchen, ein wenig über die Server-Client-Beziehung zu verstehen.

Sie denken bei einem Server vielleicht an einen großen, sperrigen, leistungsstarken Computer, der in einem supergekühlten Rechenzentrum untergebracht ist, aber tatsächlich kann auch ein so winziges Gerät wie Ihr M5Stack ein Server sein, der eine Website hostet. Wenn wir Ihren M5Stack kurz an Ihren Router anschließen, wird ihm eine IP-Adresse zugewiesen. Sie müssen Ihre IP-Adresse kennen, um sie in den Code einzugeben und auch um sie in den Browser auf Ihrem Computer einzugeben, um auf die auf dem M5Stack gehostete Website zuzugreifen. Der M5Stack fungiert als Webserver, der HTTP (Hyper Text Transfer Protocol) verwendet, ein Protokoll zur Weiterleitung von Webseiten, das Port 80 verwendet, um eine Kopie dieser Webseite jedem anderen Gerät (dem Client) zu zeigen, das eine Anfrage an seine IP-Adresse sendet. Um mit dem Gerät zu interagieren, setzen wir einige Schaltflächen auf der Seite im html. Wenn diese Schaltflächen gedrückt werden, wird eine http-Anfrage an das Gerät gesendet, das dann die RGB-Balken ein- oder ausschaltet oder den Lautsprecher piepsen lässt. Werfen wir einen Blick auf den Code. Hier importieren wir alle notwendigen Bibliotheken.

from m5stack import *  
from uiflow import *  
from m5ui import *  
import network ##only import if you want to connect to M5Stack AP
import wifiCfg  
import socket  

Hier setzen wir eine Variable für den Zustand der RGB-LED-Balken.

state = 0

Richten Sie eine Funktion zur Anzeige der Webseite ein.

#function for displaying the html   
def web_page():  
    if state == 0:  
        led_state="Off"  
    else:  
        led_state="On"  
    
 html = """<html><head> <title>M5Stack Web Server</title> <meta name="viewport" content="width=device-width, initial-scale=1">  
 <link rel="icon" href="data:,"> <style>html{font-family: Comic Sans MS; display:inline-block; margin: 0px auto; text-align: center;}  
 h1{color: #0F3376; padding: 2vh;}p{font-size: 1.5rem;}.button{display: inline-block; background-color: #0000FF; border: none;   
 border-radius: 4px; color: white; padding: 16px 40px; text-decoration: none; font-size: 40px; margin: 2px; cursor: pointer;}  
 .button2{background-color: #ff0000;}.button3{background-color: #ff00ff</style></head><body> <h1>M5Stack Web Server</h1>   
 <p>state: <strong>""" + str(state) + """</strong></p><p><a href="/?led=on"><button class="button">ON</button></a></p>  
 <p><a href="/?btn=on"><button class="button button3">Speaker</button></a></p>  
 <p><a href="/?led=off"><button class="button button2">OFF</button></a></p>  
 </html>"""  
 return html  

Weisen Sie die ifconfig-Funktion einer Variablen zu, damit wir unsere M5Stacks IP-Adresse auf dem Bildschirm ausgeben können.

ip = wifiCfg.wlan_sta.ifconfig()  

Erstellen Sie einige Beschriftungen, um einige Statusmeldungen auf dem M5Stack-Bildschirm anzuzeigen.

label1 = M5TextBox(0, 0, "Text", lcd.FONT_Default,0xFFFFFF, rotate=0)  
label2 = M5TextBox(0, 12, "Text", lcd.FONT_Default,0xFFFFFF, rotate=0)  
label3 = M5TextBox(0, 24, "Text", lcd.FONT_Default,0xFFFFFF, rotate=0)  
label4 = M5TextBox(0, 50, "Text", lcd.FONT_Default,0xFFFFFF, rotate=0)  
label5 = M5TextBox(120, 200, "Text", lcd.FONT_Default,0xFFFFFF, rotate=0)  

Geben Sie Ihr WiFi-Netzwerk und Passwort ein und richten Sie die Steckdose ein. HINWEIS: Lassen Sie die Zeichenfolge „Geben Sie Ihre IP hier ein, sobald Sie sie kennen“ leer, führen Sie das Programm einmal aus und geben Sie dann, sobald Sie die IP-Adresse auf dem Bildschirm Ihres M5Stack sehen, diese in dieses Feld ein.

response = None  
wifiCfg.doConnect('yournetwork', 'yourpassword')  
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  
s.bind(('enter your IP here once you know it', 80))  
s.listen(5)  

Wenn Sie Ihren M5Stack nicht mit dem Internet verbinden wollen und lieber

mit dem AP des Geräts verbinden möchten, entfernen Sie die Zeile wifiCfg und ersetzen Sie sie durch

ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(essid='ESP32')
ap.config(authmode=3, password='123456789') 

Bei Verbindung IP-Adresse anzeigen.

if wifiCfg.wlan_sta.isconnected():  
    label1.setText('wifi connected')  
    label2.setText('Your IP Address is: ' + str(ip[0]))  
else:  
    label1.setText('wifi not connected')  
    wait_ms(2)  

Hauptschleife, richten Sie die http-Anfragen und Statusmeldungen ein.

while True:  
    conn, addr = s.accept()  
    request = conn.recv(1024)  
    request = str(request)  
    label4.setText('Content = %s' % request)  
    label3.setText('Got a connection from %s' % str(addr))  
    led_on = request.find('/?led=on')  
    led_off = request.find('/?led=off')  
    btn_press = request.find('/?btn=on')  

Prüfen Sie, ob die http-Anfrage empfangen wurde, wenn ja, schalten Sie die LED oder den Lautsprecher ein/aus.

    if led_on == 6:  
        state = 1  
        label5.setText('LED ON')  
        rgb.setColorAll(0xFF0000)  
    if led_off == 6:  
        state = 0  
        label5.setText('LED OFF')  
        rgb.setColorAll(0x000000)  
    if btn_press == 6:  
        speaker.tone(400,200)  
    response = web_page()  
    conn.send('HTTP/1.1 200 OK\n')  
    conn.send('Content-Type: text/html\n')  
    conn.send('Connection: close\n\n')  
    conn.sendall(response)  
    conn.close()      

Und das ist alles, was es zu tun gibt. Sie können dieses Tutorial auch mit demjenigen kombinieren, das ich zuvor für MIT APP Inventor geschrieben habe, um Ihren M5Stack über eine App Inventor-App zu steuern, die auf http-Anfragen antwortet. Ich hoffe, dieses Tutorial hat Ihnen gefallen, bleiben Sie dran für mehr.

Code

M5Stack Webserver

MicroPython
Code, um den Webserver einzurichten, die IP des Host-Geräts anzuzeigen und einige Statusmeldungen auf dem M5Stack zu drucken

from m5stack import *
from m5ui import *
from uiflow import *
import network

try:
    import usocket as socket
except:
    import socket

def web_page():
  html = """<html><head> <title>M5Stack Web Server</title> <meta name        ="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,"> <style>html{font-family: Comic Sans MS;    display:inline-block; margin: 0px auto; text-align: center;}
  h1{color: #0F3376; padding: 2vh;}p{font-size: 1.5rem;}.button{display:     inline-block; background-color: #0000FF; border: none; 
  border-radius: 4px; color: white; padding: 16px 40px; text-decoration:     none; font-size: 40px; margin: 2px; cursor: pointer;}
  .button2{background-color: #ff0000;}.button3{background-color: #ff00ff     </style></head><body> <h1>M5Stack Web Server</h1> 
  <p>state: <strong>""" + str(state) + """</strong></p><p><a href="/?led     =on"><button class="button">ON</button></a></p>
  <p>Button State: <strong>""" + str(btnstate) + """</strong></p><p><a href   ="/?btn=on"><button class="button button3">Speaker</button></a></p>
  <p><a href="/?led=off"><button class="button button2">OFF</button></a></p   >
  </html>"""
  return html


ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(essid='M5Stack')
ap.config(authmode=3, password='123456789')
lcd.clear()

response = None
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.4.1',80))
s.listen(5)

while True:
    conn, addr = s.accept()
    request = conn.recv(1024)
    request = str(request)
    print ('Content = %s' % request)
    lcd.print('Content = %s' % request,0,50,0xffffff)
    if ap.isconnected() == True:
        lcd.print('connected',0,0,0xffffff)
    else:
        lcd.print('not connected',0,0,0xffffff)
    response = web_page()
    conn.send('HTTP/1.1 200 OK\n')
    conn.send('Content-Type: text/html\n')
    conn.send('Connection: close\n\n')
    conn.sendall(response)
    conn.close()

M5Stack Acess Point Webserver

MicroPython
Richten Sie Ihren M5Stack als Zugangspunkt ein und erlauben Sie Geräten den Zugriff auf eine darauf gehostete Webseite

from m5stack import *
from m5ui import *
from uiflow import *
import network

try:
    import usocket as socket
except:
    import socket

def web_page():
  html = """<html><head> <title>M5Stack Web Server</title> <meta name        ="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,"> <style>html{font-family: Comic Sans MS;    display:inline-block; margin: 0px auto; text-align: center;}
  h1{color: #0F3376; padding: 2vh;}p{font-size: 1.5rem;}.button{display:     inline-block; background-color: #0000FF; border: none; 
  border-radius: 4px; color: white; padding: 16px 40px; text-decoration:     none; font-size: 40px; margin: 2px; cursor: pointer;}
  .button2{background-color: #ff0000;}.button3{background-color: #ff00ff     </style></head><body> <h1>M5Stack Web Server</h1> 
  <p>state: <strong>""" + str(state) + """</strong></p><p><a href="/?led     =on"><button class="button">ON</button></a></p>
  <p>Button State: <strong>""" + str(btnstate) + """</strong></p><p><a href   ="/?btn=on"><button class="button button3">Speaker</button></a></p>
  <p><a href="/?led=off"><button class="button button2">OFF</button></a></p   >
  </html>"""
  return html


ap = network.WLAN(network.AP_IF)
ap.active(True)
ap.config(essid='M5Stack')
ap.config(authmode=3, password='123456789')
lcd.clear()

response = None
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('192.168.4.1',80))
s.listen(5)

while True:
    conn, addr = s.accept()
    request = conn.recv(1024)
    request = str(request)
    print ('Content = %s' % request)
    lcd.print('Content = %s' % request,0,50,0xffffff)
    if ap.isconnected() == True:
        lcd.print('connected',0,0,0xffffff)
    else:
        lcd.print('not connected',0,0,0xffffff)
    response = web_page()
    conn.send('HTTP/1.1 200 OK\n')
    conn.send('Content-Type: text/html\n')
    conn.send('Connection: close\n\n')
    conn.sendall(response)
    conn.close()
So ähnlich soll das Systemgehäuse aussehen.

Das Gehäuse soll aus 3mm MDF/HDF oder Plexiglas gefertigt werden. Die möglichen Größen sollen in einem Raster liegen. Dadurch werden die Gehäuse stapelbar. Die Gehäuse sind so gestaltet, dass die Kühlluft von unten oder vorne ins Gehäuse strömt und nach hinten abgegeben wird. Die Gestaltung des Gehäuses verhindert, dass warme Luft von hinten in die Kühlluftzufuhr gelangen kann.

Material:

  • MDF/HDF 3mm
  • Pexiglas 3mm
  • andere Kunststoffe 3mm – sofern sie mit dem Lasercutter geschnitten werden können.

Mindestabmaße für ein Raster.

Damit mehrere Gehäuse über- und nebeneinander angeordnet werden können ist es erforderlich ihre Größen durch ein Raster festzulegen. Die Rastergrößen machen mir z.Z. noch Probleme. Für das Tiefenraster habe ich mich auf 200 mm, 250 mm und 300 mm festgelegt. Für das Breiten- und Höhenraster tue ich mich noch schwer ein Maß zu finden. Es gibt Lösungen für eher flache und breite Gehäuse oder hohe und schmale Gehäuse. Die goldene Mitte habe ich bisher noch nicht gefunden.

Rasterentschluß: Breite 100/50 mm, Höhe 135 mm

100 mm, 150 mm, 200 mm, 250 mm, 300 mm, 400 mm, 500 mm (passt für 19″ Baugruppenträger – 482,6 x 133,35 mm)

Höhenraster:

Das Höhenraster sollte auf der einen Seite flache Gehäuse ermöglichen, auf der anderen Seite aber auch nicht zu sehr hohen Gehäusen führen.

Wahrscheinlich werden Höhen von 2/3 – 1 – 4/3 angemessen sein.

  • 1 – 2/3 – 4/3 – 1/2 – 1,5 – 5/3 – 2
  • 100: 66,7(50,7) – 133,3(117,3)
  • 125: 83,3(67,3) – 166,7(150,7)
  • 135: 90(74) – 180(164) – 67,5(51,5) – 209(193) – 225(209) – 270(254)
  • 67,5(51,5) – 90(74) – 135(119) – 180(164) – 209(193) – 225(209) – 270(254)

Bezugsgrößen:

  • 4×4 Folientastatur – 75mm
  • M5Stick C – 50mm / mit USB-C-Winkeladapter 70mm
  • 1-3 Zellen 18650 USB-Stromversorgungsplatine (5V und 3,3V) –

Daraus ergibt sich eine lichte Höhe von mindestens 80 mm.

Flaches Gehäuse:

  • Lichte Höhe ca. 50 mm
  • => Systemhöhe = 50 mm + 2 * 3 mm + 10 mm = 66 mm
  • => Standarthöhe = 2 * 66 mm = 132 mm

Standardgehäuse:

  • Lichte Höhe 80 – 120 mm
  • => Systemhöhe = 80 mm + 16 mm = 96 mm
  • => Systemhöhe = 120 mm + 16 mm = 136 mm

Hohes Gehäuse:

  • Lichte Höhe ab 150 mm
  • => Systemhöhe = 150 mm + 16 mm = 166 mm

Breitenraster:

  • M5Stack Core – 55mm
  • M5Sick C + 4×4 Folientastatur = 25 + 70 = 95mm

Daraus ergibt sich eine lichte Breite von mindestens 100 mm. In 50 mm Schritten.

Tieferaster:

Für die Tiefe habe ich 3 Abmaße überlegt:

  • 200 mm
  • 250 mm
  • 300 mm

Design:

Das Gehäuse ist in der DIY-üblichen Art mit ineinandergreifenden Fingern gestaltet. Rückwand, Bodenplatte und Front werden zu einer U-förmigen Grundstruktur verleimt. Der Deckel wird von oben, ebenfalls mit Fingern eingesetzt. Die Stabilität erhält das Gehäuse durch die Seitenwände. Diese haben Aussparungen für die seitlichen Finger der anderen Teile. Im Boden und im Deckel sind M3-Gewindebuchsen eingearbeitet. Durch die Seitenwände geführte M3-Senkschrauben wird das Gehäuse verschraubt.

Seitenteile:

Für die beiden Seitenteile wird eine gemeinsame Zeichnung erstellt. Sie liegt auf der rechten ansicht auf der Symmetrieachse des Gehäuses. Es ist jeweils eine Zeichnung zur Erstellung der Füsse und für die Durchbrüche erforderlich.

Die Seitenteile unterscheiden sich je nach Tiefe des Gehäuses erheblich. Die Zeichnungen müssen für jede Gehäusetiefe erstellt werden.

Kontur für 200 mm Tiefe.

Aussparrungen für 200 mm Tiefe.

Boden:

Boden und Deckel sind von der Geometrie identisch. Während der Boden die Befestigungslöcher für zu Montierenden Baugruppen bekommt, bleibt der Deckel unbearbeitet. Warme Luft soll nach Hinten und nicht nach Oben entweichen.

Die blauen Linien kennzeichnen die maximale Größe der Boden-/Deckelplatte. Die Zinken gehen nach Innen.

Zinken für 80 mm Rasterbreite.
Zinken für 100 mm Rasterbreite.
Zinken vorne und hinten für Rasterbreite 125 mm
Änderung für 160 mm Rasterbreite.
Zinken bei 187,5 mm Rasterbreite.
Zinen bei 200 mm Rasterbreite.
Zinken bei 240 mm Rasterbreite.
Zinken links und rechts für Tiefe 200 mm

Frontplatte:

Deckel:

S. Boden.

Rückwand:

Die Rückwand ist bis zur Oberkante eines ggf. darunter stehenden Gehäuses herunter gezogen. So wird verhindert, das warme Luft von hinten in die Kühlluftzufuhr gerät.

Einpressmuttern:

Das Maß für die Einpressmuttern ist recht kritisch.

  • Bei 5,3 mm waren die Muttern locker.
  • 5,2 mm hielte sich gerade so.
  • 5,1 mm gingen nur mit Kraft in den Schlitz. Ging aber noch.
  • 5,15 mm als Kompromis.
  • Die Werte dürften auch von der Leistung und Geschwindigkeit des Lasers abhängen.
Das Zen von Python, von Tim Peters

Schön ist besser als hässlich.
Explizit ist besser als implizit.
Einfach ist besser als komplex.
Komplex ist besser als kompliziert.
Flach ist besser als verschachtelt.
Spärlich ist besser als dicht.
Lesbarkeit zählt.
Spezialfälle sind nicht speziell genug, um die Regeln zu brechen.
Obwohl Praktikabilität die Reinheit schlägt.
Fehler sollten niemals stillschweigend passieren.
Es sei denn, sie werden explizit zum Schweigen gebracht.
Im Angesicht von Mehrdeutigkeit, widerstehen Sie der Versuchung zu raten.
Es sollte einen - und vorzugsweise nur einen - offensichtlichen Weg geben, es zu tun.
Auch wenn dieser Weg anfangs vielleicht nicht offensichtlich ist, es sei denn, Sie sind Niederländer.
Jetzt ist besser als nie.
Obwohl "nie" oft besser ist als "jetzt".
Wenn die Implementierung schwer zu erklären ist, ist es eine schlechte Idee.
Wenn die Implementierung einfach zu erklären ist, kann es eine gute Idee sein.
Namensräume sind eine verdammt gute Idee - lasst uns mehr davon machen!

Übersetzt mit www.DeepL.com/Translator (kostenlose Version)

Durch den Touchscreen des M5Stack Core 2 bieten sich viele Eingabemöglichkeiten die bei den Geräten ohne Touchscreen extern nachgerüstet werden müssen. Mein erster Versuch gilt einem nummerschen Keyboard auf dem Touchscreen.

Ehrlich gesagt ist mein zweiter Versuch. Der Erste war nur mal zum probieren wie das überhaupt geht. So war die GUI nach einem LCD_clear oder Clear_screen verschwunden und nicht wieder herstellbar. Auch war mir nicht klar, ob die Touch-Button wenn sie unsichtbar sind noch reagieren. Das alles habe ich beim ersten Austesten herausbekommen und ist in diesen Beitrag eingeflossen.

Auf diese Erfahrungen aufbauend ist dieser Versuch am Ende wirklich einsetzbar.

Das Ergebnis des zweiten Anlaufs kann sich sehen lassen:

Darstellung des Versuchsprogramms

Die Nutzung des Touchscreens geht am einfachsten mit dem UI-Simulator der UIFlow-IDE. Der ist aber nicht sonderlich komfortabel. Ich habe mich deshalb zu folgender Vorgehensweise entschlossen:

  • Die Darstellung der GUI und die erforderlichen Objekte werden vorher entworfen.
  • Die GUI-Elemente mit dem UI-Simulator erzeugen und nur die wesentlichen Eigenschaften festlegen.
  • Sie werden platzsparend irgenwie und -wo im UI-Simulator angelegt.
  • Die Anordnung auf dem Display wird vom Programm vorgenommen.
  • Sie werden im Programm sichtbar bzw. unsichtbar geschaltet. Dadurch wird ihre Funktion aktiviert bzw. deaktiviert.
So sehen die grafischen Elemente beim Erstellen aus.
Das ist ein Programmausschnitt der die Objekte anordnet.

Die Blöcke der Buttons und Labels bieten eine große Gestaltungsmöglichkeit. Diese sollte man nutzen um ein ansprechendes Aussehen zu erzeugen. Vor allem kann man die Objekte sichtbar (show) und unsichtbar (hide) machen. Unsichtbare Button reagieren nicht auf Berührung. So kann man auch verschiedene Objekte übereinander legen. Aktiv ist immer nur das sichtbare Objekt. Eine sehr interessante Gestaltungsmöglichkeit für eine GUI.

Ich habe im Testprogramm die Button „show“ und „hide“ eingebaut, mit denen ich die Tastatur ein- und ausschalten kann. Die Anzeige der Eingabe „label_input_show“ bleibt aber und so kann überprüft werden, dass tasächlich keine Eingabe erfolgt, wenn die Tastatur unsichtbar ist.

Die Funktionen und Buttom-Aktivities zum sichtbar und unsichtbar machen der Tastatur.

Hier kann die Programmdatei für die UIFlow-IDE heruntergeladen werden:

Bearbeitung zur Einsatzreife

Nachdem die wesentliche Funktionaltät erreicht war habe ich Anpassungen vorgenommen, die dieses Programm für Projekte einsatzfähig machen soll.