Internet Radiowecker mit Touchscreen - AZ-Delivery


Basierend auf den erfolgreichen Blog-Beiträgen zum Internetradio (Teil 1, Teil 2) stelle ich heute einen Radiowecker vor. Das Besondere, es wird ein AZ-Touch mit 2,4 Zoll oder 2,8 Zoll Touchscreen verwendet. Die Bedienung erfolgt ausschließlich über den Touchscreen. Es gibt zwei Weckzeiten, welche beliebigen Wochentagen zugeordnet werden können. Natürlich ist auch ein Einschlaf-Timer vorhanden. Damit das Display in der Nacht nicht stört, kann die Helligkeit eingestellt werden. Mit einem optionalen LDR kann die Display-Helligkeit automatisch an die Raumhelligkeit angepasst werden. Lautstärke, Einschlafzeit, Display-Helligkeit und Senderwahl können über den Touchscreen eingestellt werden. Weckzeiten und die Stream-URLs der Radiostationen werden über ein Web-Interface konfiguriert.

Zum Blog bieten wir kurzzeitig ein Radiowecker Produktset an, mit dem Sie die Produkte im Vergleich zu den Einzelpreisen deutlich günstiger erhalten.

Benötigte Hardware

Anzahl Bauteil Anmerkung

1

AZ-Touch mit 2,4 Zoll Display oder 2,8 Zoll Display

 

1

ESP32 Dev-Kit C V4

 

2

I2S Digitalverstärker mit MAX98357A

 

1

Lautsprecher 2er Set

 

1

Widerstand 470 kOhm

 

1

DC-Einbaubuchse

 

1

LDR Modul

Optional

 

Schaltung

ACHTUNG!

Bis zum 17. Oktober war hier ein fehlerhafter Schaltplan abgebildet. Das gilt auch für das PDF zum Beitrag. Wenn Sie das PDF vorher heruntergeladen haben, sollten Sie es erneut herunterladen!

Der Schaltplan zeigt nur jene Teile, die im AZ-Touch nicht vorhanden sind.  Die folgenden Abbildungen zeigen, wie man die Platine des AZ-Touch entsprechend erweitert. Für die Audioverstärker werden zwei 7-polige Federleisten zum Aufstecken der Audioverstärker auf dem Lochrasterfeld des AZ-Touch angebracht. Ebenso ein 470 kΩ Widerstand. Wer den optionalen Lichtsensor verwenden will, sollte eine zweipolige Stiftleiste bei 3,3 V und GND, sowie eine einpolige bei A0 einlöten.

ACHTUNG: Der LDR R2 muss zwischen GPIO36 und 3.3V, der Widerstand R3 zwischen GPIO36 und GND angeschlossen werden. In einer älteren Variante des Schaltplans war dies andersherum dargestellt. Bei fdalschem Anschluss wird die Hintergrundbeleuchtung bei Dunkelheit heller.


Die zweite Abbildung zeigt, wie die Verdrahtung auf der Rückseite erfolgen sollte. In Gelb sind die Konturen der Federleisten und des Widerstands dargestellt. Der Anschluss des LDR Moduls ist wie dargestellt richtig. Der Pin mit dem Aufdruck "-" gehört an 3.3V !

 Zusammenbau

Zur Unterbringung der Lautsprecher gibt es für den AZ-Touch eine Rückwand, die ihn in ein Pultgehäuse verwandelt. Die Rückwand kann mit einem 3D-Drucker hergestellt werden. Sie hat auch eine Öffnung für Die DC-Einbaubuchse. Datei zum Drucken der Rückwand.

Pultgehäuse

 

Zusammenbau

Zum Einbau des optionalen LDR gibt es eine Befestigungsplatte, auf die das LDR-Modul geschraubt werden kann. Oben im Gehäuse wird ein 5mm Loch gebohrt und dann die Befestigungsplatte mit doppelseitigem Klebeband so an die Rückwand geklebt, dass der LDR in die Bohrung zu liegen kommt.

Software

Der Sketch wurde aus Gründen der Übersichtlichkeit in mehrere Teile zerlegt. Dazu wird eine Funktion genutzt, die die Arduino IDE zur Verfügung stellt. Gibt es neben dem Hauptsketch, der denselben Namen wie der Ordner hat, noch weitere „.ino“ oder „.h“ Dateien im selben Ordner, so werden diese vom Compiler in alphabetischer Reihenfolge an den Hauptsketch angehängt.
Da der gesamte Code sehr umfangreich geworden ist, gibt es diesen nur zum Herunterladen.

Sketch zum Herunterladen

Die ZIP-Datei enthält den Ordner mit allen zugehörigen Dateien. Sie muss in den Ordner der Projektdateien (oft Dokumente\Arduino\) entpackt werden. Im Folgenden werden die einzelnen Teile kurz beschrieben. Eine detaillierte Beschreibung finden Sie als Kommentare im Code.

  • radiowecker.ino: Das ist der Hauptsketch. Es werden globale Variablen und Datenstrukturen definiert.
    • findNextAlarm() sucht Zeit und Wochentag an dem der Wecker aktiviert werden soll. Das Ergebnis wird in den globalen Variablen alarmday für den Wochentag und alarmtime für die Zeit in Minuten gespeichert. Wurde kein nächster Termin gefunden, wird alarmday auf 8 gesetzt.
    • setup() nach dem Initialisieren der seriellen Schnittstelle werden die Konfigurationsdaten aus den Präferenzen gelesen. Dann werden die Setupfunktionen der einzelnen Programmteile, mit Ausnahme des Webservers und OTA aufgerufen. Es folgt der Verbindungsaufbau zum lokalen WLAN. War die Verbindung nicht erfolgreich, werden auf dem Display Informationen zur Konfiguration angezeigt. Bei erfolgreicher Verbindung wird die Echtzeituhr initialisiert. Nun kann auch das Setup für Webserver und OTA aufgerufen werden.
    • loop() prüft zuerst, ob OTA-Anfragen vorliegen und dann, ob es Anfragen für den Webserver gibt. Es wird überprüft, ob die Verbindung zum WLAN noch besteht. Wenn die Verbindung besteht, werden der Audiostream und die beiden Encoder auf Ereignisse geprüft. Einmal pro Minute wird die Anzeige der Uhrzeit aktualisiert und überprüft, ob der Wecker aktiviert werden muss. Stimmen Weckzeit und Wochentag überein, wird der Radio-Stream gestartet und mit der eingestellten Lautstärke wiedergegeben. War die Verbindung mehr als 5 Minuten unterbrochen, wird der ESP32 neu gestartet.
  • 01_ziffern.ino: Definiert 11 Bitmaps mit 50 x 70 Pixeln. Es sind dies die Ziffern 0 bis 9 und der Doppelpunkt zur Darstellung der Uhrzeit.
  • audio.ino: In diesem Teil werden alle Funktionen im Zusammenhang mit den Audiostreams implementiert.
    • setup_audio() bereitet das System vor. Buffer und Stream-Ausgang werden initialisiert.
    • audio_loop() überprüft den Status des Audio-Streams.
    • MDCallback(void *cbData, const char *type, bool isUnicode, const char *string)
      wird immer dann aufgerufen, wenn im empfangenen Stream neue Metadaten verfügbar sind. Metadaten vom Typ „Title“ werden auf dem Display angezeigt.
    • stopPlaying() beendet das Abspielen des Streams und gibt die zugehörigen Ressourcen frei.
    • bool startUrl(String url) Startet das Abspielen eines Streams von einer gegebenen URL. Ist der Start nicht erfolgreich, wird false zurückgegeben.
    • setGain() setzt die Lautstärke auf den Wert der globalen Variablen
  • fonts.h: Hier werden zwei Fonts für die Textanzeige definiert. Einer hat eine Höhe von 9 Pixel, der andere 12 Pixel. Neben den 7-Bit ASCII Zeichen (Code 32 bis 126) gibt es auch die deutschen Umlaute Ä, Ö, Ü, ä, ö, ü, ß und das Grad Zeichen (Codes 127 bis 134). Zur Umwandlung gibt es im Modul tft_display.ino die Funktion encodeUnicode(const char* src, char* dst), die einen Text im UTF8 Format so umwandelt, dass er im Display richtig dargestellt wird. Zur einfacheren Handhabung werden zwei Makros definiert: FNT9 für den 9-Pixel Font und FNT12 für den 12-Pixel Font.
  • index.h: Enthält die HTML-Seiten für den Webserver. Mit der Befehlsfolge
    const char MAIN_page[] PROGMEM = R"=====(
    beliebiger Text………
    )=====";

    kann ein beliebiger Text direkt als Konstante in den Programmspeicher eingebaut werden. Das ist für HTML-Seiten sehr praktisch, da diese dann außerhalb der IDE entworfen und getestet werden können. Die vorliegenden Seiten nutzen jQuery, Ajax und JavaScript. Der Vorteil von Ajax für interaktive Seiten liegt darin, dass bei Änderungen nur der veränderte Teil der Seite aktualisiert wird. Es werden drei HTML-Konstanten definiert.
    • OPTION_entry ein Template für Einträge in der Auswahlliste für die Radiostationen
    • MAIN_page die Hauptseite mit Konfiguration und Wartung der Senderliste
    • CONFIG_page Seite zur Eingabe der Zugangsdaten, wenn der ESP32 zur Erstkonfiguration im Accesspoint Modus ist.
  • knoepfe.h: Hier wird eine Bitmap mit 320 x 64 Pixel definiert, die die Köpfe auf der Konfigurationsseite darstellt. Jeder der fünf Knöpfe hat eine Größe von 64 x 64 Pixel.
  • ota.ino: Hier sind die Funktionen zum Update der Firmware über WLAN zu finden.
    • setup_ota() es wird der Hostname und das Passwort festgelegt. Anschließend werden Callback-Funktionen registriert.
    • ota_onStart() wird beim Start eines OTA-Uploads aufgerufen. Das Display wird gelöscht und in der ersten Zeile eine entsprechende Meldung angezeigt
    • ota_onEnd() wird nach dem Beenden des Uploads aufgerufen. Eine entsprechende Meldung wird angezeigt.
    • ota_onProgress(unsigned int progress, unsigned int total) wird während des Uploads in regelmäßigen Abständen aufgerufen und liefert Informationen über den Fortgang. Auf dem Display wird der Fortgang in Prozent und als Balken angezeigt.
    • ota_onError(ota_error_t error) wird aufgerufen wenn ein Fehler auftritt. Die Fehlermeldung wird am Display angezeigt.
  • stations.ino: definiert eine Programmspeicherkonstante mit der Default-Senderliste.
    • setup_senderliste() füllt die Senderliste im RAM mit der Senderliste aus den Präferenzen. Gibt es dort keine Senderliste, so wird die Default-Senderliste verwendet.
    • restore(): Füllt die Senderliste aus der Default-Senderliste und speichert sie in den Präferenzen ab. Die Funktion ist hilfreich, wenn die Senderliste durcheinandergeraten ist.
    • saveList(): Speicher die Senderliste aus dem RAM in den Präferenzen ab.
    • reorder(uint8_t oldpos, uint8_t newpos): Verschiebt den Sendereintrag an der Position oldpos an die Position newpos. Dazwischen liegende Einträge werden entsprechend verschoben.
  • tft_display.ino: enthält alle Funktionen zum Ansteuern des Displays und des Touchscreens.
    • onTouchClick(TS_Point p): Callback-Funktion, die immer dann aufgerufen wird, wenn man kurz auf den Touchscreen tippt. Der Parameter p gibt den Punkt am Display an, auf den getippt wurde. Die Koordinaten sind x und p.y. Der Nullpunkt ist im linken oberen Eck.
    • setGainValue(uint16_t value): Der Schieberegler für die Lautstärke wird aktualisiert, sodass er auf dem übergebenen Wert steht.
    • setBrightness(uint16_t value): Der Schieberegler für die Helligkeit wird aktualisiert, sodass er auf dem übergebenen Wert steht.
    • setSnoozeTime(uint16_t value): Der Schieberegler für die Einschlafzeit wird aktualisiert, sodass er auf dem übergebenen Wert steht.
    • setBGLight(uint8_t prct): Die Helligkeit der Hintergrundbeleuchtung des Displays wird auf den übergebenen Wert in Prozent eingestellt. Ist der Wert 0, wird die Helligkeit abhängig vom Lichtsensor eingestellt.
    • selectStation(uint16_t x): Je nach x-Position wird auf der Konfigurationsseite der nächste oder der vorhergehende Eintrag in der Senderliste angezeigt. Nicht aktivierte Einträge werden übersprungen. Ist x < 50 wird der vorhergehende Eintrag angezeigt. Ist x > 270 wird der nächste Eintrag angezeigt. Für alle anderen Werte von x passiert nichts.
    • toggleRadio(boolean off) : Je nach Wert des Parameters off wird die Wiedergabe des MP3 Streams gestartet oder gestoppt. Danach wird auf die Anzeige der Uhr umgeschaltet.
    • toggleAlarm(): Die Wecker-Funktion wird umgeschaltet. Von aus auf ein und umgekehrt. Danach wird auf die Anzeige der Uhr umgeschaltet.
    • startSnooze(): Die Einschlaf-Zeit wird mit dem konfigurierten Wert gestartet. Danach wird auf die Anzeige der Uhr umgeschaltet. Falls notwendig, wird das Radio eingeschaltet.
    • changeStation(): Die mit selectStation ausgewählte Station wird als aktive Station gesetzt. Danach wird auf die Anzeige der Uhr umgeschaltet.
    • touch_loop(): Muss von der Hauptschleife aufgerufen werden und dient dazu den Status des Touchscreens abzufragen, um Berührungen zu erkennen.
    • setup_display(): Das Display und er Touchscreen werden initialisiert.
    • textInBox(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const char* text, uint8_t align = ALIGNLEFT, boolean big = false, uint16_t fc = ILI9341_WHITE , uint16_t bg = ILI9341_BLACK, uint8_t lines = 1 ): Der übergebene Text wird in einem Rechteck mit der Breite w und der Höhe h an der Position x, y (linke obere Ecke) ausgegeben. Ist der Text zu lang, wird er beim letzten Wortzwischenraum abgeschnitten. Die Ausrichtung kann links, rechts oder zentriert erfolgen. Default ist links. Mit dem Parameter big kann die Schriftgröße mit 12 Pixel gewählt werden. Default ist 9 Pixel. Schriftfarbe und Hintergrundfarbe können gewählt werden. Default ist weiß auf schwarz. Eine mehrzeilige Anzeige ist möglich. In diesem Fall erfolgt der Zeilenumbruch immer an einem Wortzwischenraum. Default ist einzeilig.
    • updateTime(boolean redraw): Die Anzeige von Datum und Uhrzeit wird aktualisiert. Ist redraw true, wird der gesamte Inhalt neu ausgegeben, sonst werden nur die Änderungen aktualisiert.
    • displayDateTime(): Ruft updateTime(false)
    • showProgress(uint32_t prc): Zeigt einen Fortschrittsbalken und den Wert in Prozent an. Wird im Zusammenhang mit dem Softwareupdate aufgerufen.
    • encodeUnicode(const char* src, char* dst): Wandelt im Text src die UTF8 Zeichen ÄÖÜäöüß° so um, dass sie im Display richtig dargestellt werden. Das Ergebnis wird in dst Der Zielstring muss in ausreichender Größe existieren.
    • showSlider(uint16_t y,float value, uint16_t vmax): Ein Schieberegler wird an der vertikalen Position y Der Schieber wird entsprechend dem übergebenen Wert value positioniert. Der Parameter vmax gibt den maximalen Wert an.
    • showGain(): Der Balken für die Lautstärkeeinstellung im Konfigurations-Display wird angezeigt.
    • showBrigthness(): Der Balken für die Helligkeitseinstellung im Konfigurations-Display wird angezeigt.
    • showSnoozeTime(): Der Balken für die Einstellung der Einschlafzeit im Konfigurations-Display wird angezeigt.
    • updateStation(): Der Name des Senders im Balken für die Senderauswahl wird aktualisiert.
    • showStationList(): Der Balken für die Senderauswahl im Konfigurations-Display wird angezeigt.
    • showCommand(): Das Konfigurations-Display wird mit voller Helligkeit angezeigt.
    • showStation(): Der Name des aktiven Senders wird im Radioblock angezeigt.
    • showTitle(): Die Metadaten zum gerade wiedergegebenen Streams werden im Radioblock angezeigt.
    • showRadio(): Der Radioblock wird angezeigt.
    • showNextAlarm(): Datum und Uhrzeit für das nächste Wecker-Ereignis werden in der untersten Zeile angezeigt.
    • showDebugInfo(int16_t v1, int16_t v2, int16_t v3): Diese Funktion wird nicht verwendet. Sie kann aber dazu benutzt werden, den Wert von drei Integer-Zahlen am Display in der untersten Zeile anzuzeigen.
    • showClock(): Die Uhrzeit wird angezeigt. Das Display wird vorher komplett gelöscht. Ist das Radio eingeschaltet, wird der Radioblock angezeigt. Ist die Wecker-Funktion aktiv, wird die nächste Weckzeit angezeigt.
  • webserver.ino: Enthält das Setup und die Funktionen, um auf http-Anfragen zu reagieren.
    • setup_webserver(): Es werden die einzelnen Funktionen zum Behandeln der http-Anfragen registriert und der Server auf Port 80 gestartet.
    • webserver_loop() es wird geprüft, ob neue Anfragen vorliegen.
    • handleRoot() bearbeitet eine Anfrage für die Hauptseite. Liegt eine Verbindung ins lokale WLAN vor, wird die Hauptseite an den Client gesendet. Ist der ESP32 für die Grundkonfiguration im Accesspoint Modus, wird die Konfigurationsseite übertragen. Zusätzlich müssen in diesem Fall noch eventuell vorhandene Parameter verarbeitet werden, um die Zugangsdaten zu speichern, oder einen Neustart auszulösen.
    • sendStations() reagiert auf das Ajax-Kommando mit der URL /cmd/stations. Sendet die Liste der Stationen als HTML-Optionlist. Diese Liste wird dann über Javascript im Client in das Dropdownelement eingebaut.
    • setAccessData() reagiert auf das Ajax-Kommando mit der URL /cmd/setaccess. Die Konfigurationsdaten SSID, PKEY und NTP-Server werden in den Präferenzen gespeichert.
    • getAccessData() reagiert auf das Ajax-Kommando mit der URL /cmd/getaccess. Die Konfigurationsdaten SSID, PKEY und NTP-Server werden als Antwort gesendet. Als Trennzeichen wird das Zeilenende verwendet.
    • getAlarms() reagiert auf das Ajax-Kommando mit der URL /cmd/getalarms. Die beiden Alarmzeiten sowie die jeweiligen Alarmtage werden als String gesendet. Als Trennzeichen wird das Zeilenende verwendet.
    • uint16_t stringToMinutes(String val): Wandelt einen String im Format hh:mm in die Anzahl der Minuten um.
    • setAlarms() reagiert auf das Ajax-Kommando mit der URL /cmd/setalarms. Die Alarmzeiten werden als Argument al0 und al8 im Format hh:mm erwartet. Die Alarmtage werden in den Argumenten al1 bis al7 und al9 bis al15 erwartet. Sie werden in eine 8-Bit Binärzahl umgewandelt.
    • getStationData() reagiert auf das Ajax-Kommando mit der URL /cmd/getstation. Die ID der gewünschten Station wird als Argument erwartet. Es wird der Name, die URL und das Enable-Flag der angegebenen Station als Antwort gesendet. Als Trennzeichen wird das Zeilenende verwendet.
    • setStationData() reagiert auf das Ajax-Kommando mit der URL /cmd/setstation. Die ID der gewünschten Station wird als Argument erwartet. Ist die ID gültig, werden die als Argument übergebenen Daten für den Namen, die URL und das Enable-Flag in der Senderliste gespeichert.
    • testStation() reagiert auf das Ajax-Kommando mit der URL /cmd/teststation. Die URL, die getestet werden soll, wird als Argument erwartet. Es wird versucht, die Wiedergabe der angegebenen URL zu starten. Ist der Versuch nicht erfolgreich, so wird wieder auf die aktuelle Station zurückgeschaltet und mit „ERROR“ geantwortet.
    • endTest() reagiert auf das Ajax-Kommando mit der URL /cmd/endtest. Der Test wird beendet, indem die Wiedergabe der aktuellen Station gestartet wird.
    • restoreStations(): Die Senderliste wird mit den Default Sendern gefüllt und in den Präferenzen abgespeichert.
    • restart() reagiert auf das Ajax-Kommando mit der URL /cmd/restart. Der ESP32 wird neu gestartet.
  • wlan.ino: Enthält die Funktion zum Herstellen einer Verbindung mit dem lokalen WLAN oder zur Bereitstellung eines Accesspoints, wenn eine Verbindung nicht möglich ist.
    • boolean initWiFi(String ssid, String pkey) versucht mit den angegebenen Zugangsdaten eine Verbindung zum lokalen WLAN herzustellen. Wenn keine SSID angegeben wurde, oder der Verbindungsversuch nicht gelingt, wird ein Accesspoint gestartet. Über diesen Accesspoint kann dann von einem Browser unter der Adresse 192.168.4.1 die Konfigurationsseite aufgerufen werden.

Damit der Sketch kompiliert werden kann, muss die Arduino IDE entsprechend vorbereitet werden. Die Arduino IDE unterstützt standardmäßig eine große Anzahl von Boards mit unterschiedlichen Mikrocontrollern, nicht aber den ESP32. Damit man Programme für diese Controller erstellen und hochladen kann, muss daher ein Softwarepaket für die Unterstützung installiert werden.

Zuerst müssen Sie der Arduino IDE mitteilen, wo sie die zusätzlich benötigten Daten findet. Dazu öffnen Sie im Menü Datei den Punkt Voreinstellungen. Im Voreinstellungs-Fenster gibt es das Eingabefeld mit der Bezeichnung „Zusätzliche Boardverwalter URLs“. Wenn Sie auf das Icon rechts neben dem Eingabefeld klicken, öffnet sich ein Fenster, in dem Sie die URL https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json eingeben können.

Nun wählen Sie in der Arduino IDE unter Werkzeug → Board die Boardverwaltung.

Es öffnet sich ein Fenster, in dem alle zur Verfügung stehenden Pakete aufgelistet werden. Um die Liste einzugrenzen, gibt man im Suchfeld „esp32“ ein. Dann erhält man nur noch einen Eintrag in der Liste. Installieren Sie das Paket „esp32“. Falls das Paket schon installiert war, prüfen Sie bitte, ob Sie die Version 2.0.9 haben.

 ESP32 Package

Für das Display benötigen Sie zwei Bibliothek, die über die Arduino Bibliotheksverwaltung installiert werden können. Das ist die Bibliothek „Adafruit_ILI9341“ in der Version 1.5.10

ILI-9341

und die Bibliothek „Adafruit_GFX“ in der Version 1.10.14.

GFX-Bibliothek

Zwei weitere Bibliotheken werden für den Touchscreen benötigt. Das ist „XPT2046_Touchscreen“ in der Version 1.4.0

XPT-2046

und  „Touchevent“ in der Version 1.3.0

Touch Event

Kernstück dieses Projekts ist aber die Bibliothek „ESP8266Audio“ von Earle F. Philhower in der Version 1.9.7.

ESP8266 Audio

Diese Bibliothek ermöglicht es, verschiedene digitale Audiostreams zu lesen, zu dekodieren und über verschiedene Ausgangskanäle wiederzugeben. Als Eingang, kann der Programmspeicher, der interne RAM, ein Filesystem, eine SD-Karte, ein HTTP-Stream, oder ein ICY-Stream genutzt werden. Der ICY-Stream wird typisch von Internet-Radios genutzt.
Dekodiert werden können WAV, MOD, MIDI, FLAC, AAC und MP3 Dateien. Für das Webradio wird MP3 benötigt. Die Ausgabe kann schließlich in Speicher, Files oder I2S erfolgen.

Wenn alle Bibliotheken installiert sind, kann der Sketch kompiliert und auf die Hardware hochgeladen werden.
Achtung! Da sich der Sketch aus zahlreichen Teilen zusammensetzt, kann das Kompilieren, insbesondere beim ersten Mal, lange dauern. Für das ESP32 Package und die ESP8266audio Bibliothek ist es wichtig, die angegebenen Versionen zu benutzen, da die Audio-Bibliothek sehr hardwarenahe programmiert wurde.

Wer sich das Kompilieren ersparen will, kann hier die fertig kompilierte Firmware herunterladen und direkt auf den ESP32 hochladen.

Binärfile zum Herunterladen

Zum Hochladen des Binärfiles benötigt man ein Hilfsprogramm, das bei Espressif kostenlos heruntergeladen werden kann.  Flash Download Tools


Sie müssen die ZIP-Datei herunterladen und entpacken. Dann können Sie das enthaltene Programm flash_download_tool_3.9.5.exe starten. Es erscheint ein Fenster zur Auswahl des Controllers.

Controller Auswahl
Hier wählen Sie als Chip-Type ESP32 und als Work-Mode Develop. Mit OK wird das Programm fortgesetzt. Es erscheint das Arbeitsfenster des Tools.

Flash Tool
Verbinden Sie den ESP32 über ein USB-Kabel mit dem Computer und wählen Sie unten rechts die verwendete serielle Schnittstelle aus. In der obersten Zeile setzen Sie den Pfad zur heruntergeladenen BIN-Datei für den Radiowecker. Als Zieladresse muss 0x10000 eingegeben werden. Alle anderen Einstellungen wählen Sie wie auf der Abbildung gezeigt. Nun können Sie auf „START“ klicken. Der Upload beginnt. Wenn alles fertig ist, wechselt die grüne Fläche „IDLE“ auf Blau mit dem Text „FINISH“.  Der ESP32 hat nun die Firmware für den Radiowecker und die Inbetriebnahme kann erfolgen. Die fertig kompilierte BIN-Datei funktioniert nur mit der aktuellen Version des AZ-Touch.

Inbetriebnahme

Bei der ersten Inbetriebnahme sind noch keine Präferenzen vorhanden. Es kann daher keine Verbindung zum lokalen WLAN hergestellt werden. Ein Accesspunkt mit der SSID „radioweckerconf“ ohne Passwort wird gestartet. Auf dem Display erscheint eine entsprechende Meldung.

Not Connected
Mit z.B. einem Smartphone kann nun eine Verbindung zu diesem Accesspoint hergestellt werden. Danach kann in einem Browser über die Adresse 192.168.4.1 die Konfigurationsseite aufgerufen werden.

Konfigurationsseite

Nach dem Neustart sollte die Verbindung zum lokalen WLAN erfolgreich hergestellt werden können. Am Display sollte die aktuelle Uhrzeit und das Datum angezeigt werden.

Zeitanzeige 

Tippt man irgendwo auf das Display, erscheint die Bedienungsseite.

Bedienungsseite

Es gibt drei Schieberegler für Lautstärke, Helligkeit und Einschlafzeit. Verändert werden die Einstellungen, indem man auf die gewünschte Position tippt. Eine Besonderheit gilt für die Helligkeit. Wird die auf 0 eingestellt, wird, falls der optionale LDR vorhanden ist, die Helligkeit an die Umgebungshelligkeit angepasst.

In der vierten Zeile sieht man die aktuelle Radiostation. Mit den zwei Knöpfen links und rechts können Sender aus der Senderliste ausgewählt werden.

Ganz unten ist eine Reihe von Knöpfen.

Knopf1 Das Radio wird ein- oder ausgeschaltet. Die Anzeige kehrt zur Zeitanzeige zurück. Wurde das Radio eingeschaltet, erscheint unter der Zeitanzeige der Radioblock mit dem Sendernamen und den Metadaten (z.B. Name des geraden gespielten Liedes).
Knopf2 Die Einschlafzeit wird gestartet. Falls das Radio nicht eingeschaltet ist, wird es eingeschaltet. Die Anzeige kehrt zur Zeitanzeige zurück. Wenn die eingestellte Einschlafzeit vorüber ist, wird das Radio automatisch ausgeschaltet.

Knopf3 Die Wecker-Funktion wird ein- oder ausgeschaltet. Die Anzeige kehrt zur Zeitanzeige zurück. Wurde der Wecker eingeschaltet, erscheint ganz unten im Display der Wochentag und die Uhrzeit, wann der Wecker das nächste Mal ausgelöst wird. Wenn der angezeigte Wochentag und die Uhrzeit zutreffen, wird das Radio automatisch eingeschaltet.

Knopf4 Der ausgewählte Sender wird als aktiver Sender übernommen. Ist das Radio gerade eingeschaltet, so wechselt der Stream automatisch auf den neuen Sender. Die Anzeige kehrt zur Zeitanzeige zurück.

Knopf5 Die Anzeige kehrt zur Zeitanzeige zurück.

 Erfolgt 10 Sekunden keine Aktivität, so kehrt die Anzeige automatisch zur Zeitanzeige zurück. Alle Einstellungsänderungen werden in den Präferenzen gespeichert. Die Bedienungsseite wird immer mit voller Helligkeit dargestellt.

Konfiguration und Bearbeitung der Weckzeiten und der Senderliste

Über die URL http://radiowecker/ sollte die Konfigurationsseite abrufbar sein.

Konfiguration

Im oberen Teil können die Zugangsdaten und der NTP-Server geändert werden. Die Änderungen werden erst dann wirksam, wenn der Knopf „Speichern“ geklickt wurde.
Mit dem Knopf „Neustart“ kann ein Neustart ausgelöst werden.
Als Nächstes folgen die Weckzeiten. Es können zwei Weckzeiten eingestellt werden. Für jede der Weckzeiten können die Wochentage gewählt werden, an denen die Weckzeiten anzuwenden sind.
Die Dropdown-Liste darunter enthält alle Sender der Senderliste. Auswählbare Sender haben vor dem Namen einen schwarzen Punkt. Im Formular darunter werden die Daten zur ausgewählten Station angezeigt und können geändert werden. Ist das Häkchen bei „Verwenden“ nicht gesetzt, kann die Station im Gerät nicht ausgewählt werden. Da manche URLs nicht funktionieren, sollte eine neue URL mit dem Knopf „Testen“ getestet werden. Ein Klicken auf diesen Knopf startet die Wiedergabe der URL am Gerät. Achtung! Am Gerät muss das Radio zum Testen eingeschaltet sein. Sollte die Wiedergabe nicht funktionieren, wird sofort wieder auf den aktuellen Sender zurückgeschaltet und eine Meldung angezeigt. Ist die Wiedergabe möglich, wird eine Box mit einem Knopf angezeigt. Klicken auf diesen Knopf schließt die Box und beendet den Test. Es wird wieder die aktuelle Station wiedergegeben. Im Eingabefeld „Position“ wird die Position der ausgewählten Station innerhalb der Senderliste angezeigt. Durch eine Änderung dieses Wertes, kann die Station auf die angegebene Position verschoben werden. Mit dem Knopf „Ändern“ können die Änderungen für die ausgewählte Station dauerhaft geändert werden.

Firmware Update über OTA

Um das Programm zu aktualisieren, ist es nicht notwendig, das Gerät zu öffnen und eine USB-Verbindung herzustellen. In der Arduino IDE sollten Sie bei den Ports den folgenden Eintrag sehen.

OTA Port

Über diesen Port können Sie nun einen Sketch hochladen. Zum Schutz muss nach Aufforderung das Passwort „weckerupdate“ eingegeben werden. Da die Serielle Schnittstelle nicht genutzt werden kann, werden Meldungen am Display angezeigt.

OTA Progress

Hier gibt es den Beitrag als PDF

Viel Spaß beim Nachbauen.

Nachtrag:

Ziffern in rot, gelb, grün und blau

Dieser Download enthält eine neue Variante von 01_ziffern.ino. Wenn die original Datei 01_ziffern.ino durch diese ersetzt wird, kann in der Datei tft_display.ino in Zeile 335, im Befehl drawRGBBitmap ziffern_rot durch ziffern_gelb, ziffern_gruen oder ziffern_blau ersetzt werden.

Monochrom-Bitmap:

Ich habe noch eine andere Variante, angeregt durch den Kommentar von kunigunde, die Farbe der Ziffern beliebig zu ändern. Dabei wird statt des RGB-Bitmaps ein monochromes Bitmap benutzt, das dann beliebig eingefärbt werden kann. Sie müssen dazu die Dateien 01_ziffern.ino und tft_display.ino durch die entsprechenden aus dem folgenden Link ersetzen.

Variante

In der Datei tft_display.ino in der Funktion updateTime() kann man die Hintergrundfarbe und die Schriftfarbe einstellen.

      if ((z<11) && (redraw || (tim[i] != lasttime[i]))) {
        tft.fillRect(30+i*55,30,50,70,ILI9341_BLACK); //Hintergrund
        tft.drawBitmap(30+i*55,30,ziffern[z],50,70,ILI9341_GREEN);  //Schrift
      }

Hier als Beispiel grün auf schwarzem Hintergrund.

WICHTIGER HINWEIS:

In der Hauptdatei radiowecker.ino liegt ein Fehler vor, der es verhindert, dass nach einem Verbindungsverlust das Gerät neu gestartet wird.

Die Bedingung in den Zeilen 232 bis 238 muss inklusive "else" Teil entfallen. Sie muss wie folgt aussehen:

    getLocalTime(&ti);
    minutes = ti.tm_hour * 60 + ti.tm_min;
    weekday = ti.tm_wday;

DisplaysEsp-32Projekte für fortgeschrittene

146 comentarios

Anton Mayr

Anton Mayr

Tolles Projekt, habe die Teile erhalten, zusammengebaut -super!
Wie komme ich zu den Links der Sender (Österreich)?

kunigunde

kunigunde

kleiner Verbesserung Vorschlag:
Wenn zwar ein Alarm eingestellt, dieser jedoch deaktiviert ist sieht man es nicht.
Um auch dies angezeigt zu bekommen muss in der Datei tft_display.ino die function showNextAlarm(){
….
}
angepasst werden zu:
-————————————
void showNextAlarm(){
char txt100 = "";
uint8_t h,m;
if (clockmode) {
if (alarmday < 8){
h = alarmtime / 60;
m = alarmtime % 60;
sprintf(txt,“Wecker: %s um %i:%02i”,days[alarmday],h,m);
textInBox(0,220,320,20,txt,ALIGNCENTER,false,0xC000,ILI9341_BLACK,1);
}else{
sprintf(txt,“WECKER AUSGESCHALTEN !!!”);
textInBox(0,220,320,20,txt,ALIGNCENTER,false,ILI9341_RED,ILI9341_BLACK,1);
}
}
}
-——————————-

kunigunde

kunigunde

@Bernd-Steffen Großmann
dies steht dir zur Verfügung:
#define ILI9341_BLACK 0×0000 ///< 0, 0, 0
#define ILI9341_NAVY 0×000F ///< 0, 0, 123
#define ILI9341_DARKGREEN 0×03E0 ///< 0, 125, 0
#define ILI9341_DARKCYAN 0×03EF ///< 0, 125, 123
#define ILI9341_MAROON 0×7800 ///< 123, 0, 0
#define ILI9341_PURPLE 0×780F ///< 123, 0, 123
#define ILI9341_OLIVE 0×7BE0 ///< 123, 125, 0
#define ILI9341_LIGHTGREY 0xC618 ///< 198, 195, 198
#define ILI9341_DARKGREY 0×7BEF ///< 123, 125, 123
#define ILI9341_BLUE 0×001F ///< 0, 0, 255
#define ILI9341_GREEN 0×07E0 ///< 0, 255, 0
#define ILI9341_CYAN 0×07FF ///< 0, 255, 255
#define ILI9341_RED 0xF800 ///< 255, 0, 0
#define ILI9341_MAGENTA 0xF81F ///< 255, 0, 255
#define ILI9341_YELLOW 0xFFE0 ///< 255, 255, 0
#define ILI9341_WHITE 0xFFFF ///< 255, 255, 255
#define ILI9341_ORANGE 0xFD20 ///< 255, 165, 0
#define ILI9341_GREENYELLOW 0xAFE5 ///< 173, 255, 41
#define ILI9341_PINK 0xFC18 ///< 255, 130, 198

Du kannst jedoch auch jede andere Farbe einfach selbst erstellen, statt ILI9341_XXXX gibst du dort direkt den Hex wert ein.
um den Hex wert zu bekommen gehts du am besten hier hin (du benötigst den RGB565 Wert unten):
https://barth-dev.de/online/rgb565-color-picker/

kunigunde

kunigunde

@Gerald Lechner
@Dennis
nochmal zum Weckzeit Anzeige Fehler.
Gerald’s korrigierte Version:
sprintf(txt,“Wecker: %s um %i:%02.0i”,days[alarmday],h,m);
Anzeige:
Wecker: Dienstag um 6:1 bzw Wecker Dienstag 6:_
-——————-
meine Version:
sprintf(txt,“Wecker: %s um %i:%02i”,days[alarmday],h,m);
Anzeige:
Wecker: Dienstag um 6:01 bzw Wecker Dienstag 6:00

P.S.: auf Github aktualisiert

Bernd-Steffen Großmann

Bernd-Steffen Großmann

@kunigunde: Super, besten Dank! Jetzt kann ich alles nach persönlichem Geschmack einstellen. Bleibt nur noch die Frage: welche Farben sind bei dem ILI934-Treiber alle möglich?
@Heiko Janisch: Ich hab jetzt mal einen anderen ESP32 geflasht. Mal sehen, ob die Konnektivitäts-Probleme damit beseitigt sind; der erste ESP hatte schon wieder die Verbindung verloren!? Und: Die Lautsprecher hab ich einfach mit 2-Komp.kleber eingeklebt.

Gerald Lechner

Gerald Lechner

@Konrad: Wenn das Radio über das Symbol mit der Glocke eingeschaltet wird, läuft es bis die Einschlafzeit abgelaufen ist. Über das Lautsprechersymbol kann man es auch vorzeitig abschalten. Um das Radio dauerhaft einzuschalten, darf man nicht das Symbol mit der Glocke sonder muss man das Lautsprechersymbol benutzen.
@Heiko Janisch: Ich habe nur zwei Schrauben verwendet. Oben vorne und unten hinten.

Heiko Janisch

Heiko Janisch

“Heureka – ich habe es!” würde Archimedes jetzt an meiner Stelle sagen. Mit dem Spiegeln der X- und Y-Achse funktioniert nun auch das 2.4" TFT.
Leider stören mich auch noch viele Verbindungsabbrüche im WLAN, obwohl ich eine sehr schnelle Leitung habe und der Abstand zum Router nur ca. 4 Meter beträgt. Wenn es dazu Neuigkeiten gibt, wäre ich für Lösungsansätze sehr dankbar.
@ Gerald Lechner: Vielen Dank für die STL-Dateien. Dazu noch eine Frage: Wie haben Sie die Lautsprecher im Pultgehäuse befestigt? An die hinteren Schrauben kommt man ja fast nicht ran?

kunigunde

kunigunde

@Bernd-Steffen Großmann
Ich habe eine Version auf GitHub hinterlegt bei der sämtliche Farben des Haupt Bildschirms angepasst werden können.

Link:
https://github.com/beabel/radiowecker

Konrad

Konrad

Hallo Herr Lechner,
Sie haben sich mal wieder selbst übertroffen! Was für ein tolles Projekt! Ein großes Dankeschön.
Ich bin was das Löten speziell bei Platinen angeht nicht der große Könner, aber es hat sich Gott sei Dank in Grenzen gehalten und ich habe es auf Anhieb ohne mich zu “verlöten” geschafft (bei der 2. Variante des Radios bin ich ganz schön an meine Grenzen gekommen).
Zu folgendem kann ich aktuell noch nichts sagen:
1. Das Rückteil muss ich erst noch bei meinem Schwager in “Auftrag” geben.
2. Die Photodiode habe ich noch nicht installiert. Könnte also sein, dass ich da nochmal mich melde.

Meinen kleinen Wünsche:
1. Könnte man kunigunde ’s index Datei auch runterladen? Die Original index Datei hat teilweise kleinere Formatierprobleme in der Darstellung (vermutlich ein CSS Thema).
2. Das mit der Einschlafzeit einstellen ist mir noch nicht klar. Ich hatte Sie Testweise mal auf 5 min eingestellt. Das hat dann auch super geklappt. Aber ich habe das dann nicht mehr abgestellt bekommen. Immer nach 5 Minuten ging es aus; – egal welchen Knopf ich gedrückt habe. Aktuell habe ich einfach auf 60 min eingestellt, – was jetzt nicht so störend ist. Danke für eine Klärung.

Nochmals ein RIESENGROßES Dankeschön.

Konrad

Gerald Lechner

Gerald Lechner

@kunigunde: Eine entsprechede Variante mit der Originalschrift ist am Ende des Blogbeitrags zum Download bereitgestellt.
@Heiko Janisch: Am einfachsten in der Datei tft_display.ino, Funktion onTouchClick(TPoint p) die Werte umkehren p.x = 320 – p.x; und p.y = 240 – p.y;
@Dennis: Danke für den Hinweis. In der Datei tft_display.ino in der Funktion showNextAlarm() muss der Formatstring geändert werden
sprintf(txt,“Wecker: %s um %i:%02.0i”,days[alarmday],h,m);

Dennis

Dennis

Beim Anzeigen der Weckzeit gibt es eine Fehler wenn bei den Minuten 00-09 ausgewählt wird. Z.B. es wird 6:00 Uhr als Weckzeit eingestellt, dann wird 6:0 angezeigt, bei 6:09 Uhr als Weckzeit wird 6:9 angezeigt, erst bei einer Weckzeit 6:10 Uhr und mehr wird die Zeit richtig angezeigt. Der Fehler tritt auch bei allen anderen Möglichkeiten auf (1:09, 5:09 usw.)

Heiko Janisch

Heiko Janisch

Die Ursache habe ich gefunden, die X und Y Achsen sind spiegelverkehrt. Damit reagiert das 2.4 Touch immer diagonal gespiegelt. Damit stellt sich die Frage, wo muss ich im Code welche Parameter ändern?

kunigunde

kunigunde

@Gerald Lechner

Ich habe das Problem mit den Wunschfarben der Uhrzeit gelöst.
1. es ist nur eine einzige ziffern.ino nötig
2. die Farbe kann an einer einzigen Stelle angepasst werden
Dazu werden jeweils schwarz/weiße Bitmaps (01234567890:) benötigt (schwarz = Hintergrund)
Ich stelle meine unter dem Download- Link mit zur Verfügung, jedoch habe ich zum test jetzt nur eine Standard Schriftart benutzt.
was man am Programm tun muss ist:
1. ==> 01_ziffern.ino austauschen
2. dies:
tft.drawRGBBitmap(30+i*55,30,ziffern_rot[z],50,70);
ändern zu:
tft.drawBitmap(30+i*55,30,ziffern_rot[z],50,70,ILI9341_BLUE,ILI9341_BLACK);

Download Link:
01_ziffern.ino:
https://github.com/beabel/radiowecker/blob/main/01_ziffern.ino
tft_display.ino:
https://github.com/beabel/radiowecker/blob/main/tft_display.ino

Bernd-Steffen Großmann

Bernd-Steffen Großmann

@Harald – Ich habe ebenfalls Probleme mit der Stabilität der WLAN-Verbindung (connection lost), obwohl der Router (Fr.Box 7490) keine 3 m entfernt auf der selben Ebene steht. Mir scheint, dass der ESP32 WROOM (von AZ-Del.) Stabilitäts- und Probleme mit dem Speichern der Konfigurationsdaten hat. Heute morgen waren sogar die WLAN-Daten komplett “weg”! Ich musste sie über die Start-Konfiguration (192.168.4.1) neu eingeben. Ich werde mal einen anderen ESP32 ausprobieren.
@Gerald Lechner: Zitat: “Der LDR wird zwischen GND und GPIO34 angeschlossen. GPIO34 wird über einen Pullup Widerstand von 10kOhm mit 3.3V verbunden.” Zitat Ende.
Laut Konfiguration (//pin to be used for light sensor , #define LDR 36), Stromlauf- und Bestückungsplan muss der LDR an GPIO36 (A0). Und: Mein LDR (der KY-018 – aus dem 35-in1 Sensor-Kit von AZ-Del.) hat bereits einen 10kOhm Widerstand von S nach +!
Ich habe gerade auch die neue Ziffern01.ino eingespielt und jetzt zeigt das Display schöne blaue Ziffern bei der Zeit (passt sehr gut zum blauen Gehäuse), nur das Datum ist weiter in roter Schrift. Wenns nicht zu viel Aufwand macht: wie kann man das ändern?

Gerald Lechner

Gerald Lechner

@Heiko Janisch: Es hat auch ein 2.4 Zoll Display gegeben, bei dem eine der beiden Achsen der Touchfolie um 180° gedreht war. Erkenntlich war das an einer gelben Stiftleiste. In dem Fall müsste das bei der verarbeitung der Events berücksichtigt werden. Von einer unterschiedlichen Firmwarebhabe ich nichts gehört. Es wird bei beiden Displays der Controller XPT2046 verwendet.
@kunigunde: Das mit den eingefärbten schwarz/weiß Bitmaps finde ich eine hervorragende Idee. Es erfordert ein wenig Programmänderung. Ich werde eine entsprechende Version erstellen und zum Download zur Verfügung stellen.

kunigunde

kunigunde

@Gerald Lechner
@Harald Valeri
Bezugnehmend auf die Wunschfarben der Ziffern,
habe ich eine Frage? Ist es möglich die Bitmaps der ziffern als schwarz/weiß zu integrieren, und dann statt drawRGBBitmap die drawBitmap funktion zu nutzen, bei welcher man die Farbe anpassen kann?
drawRGBBitmap(int16_t x, int16_t y, uint16_t *pcolors, int16_t w, int16_t h);
vs.
drawBitmap(int16_t x, int16_t y, uint8_t *bitmap, int16_t w, int16_t h, uint16_t color)

Heiko Janisch

Heiko Janisch

Danke für den Hinweis. Das AZ-Touch Board ist die Version 01-03, sollte also aktuell sein.
Die Pin-Definitionen habe ich mit der Hardware überprüft, das passt auch. Wie schon geschrieben, funktionieren beim 2.8 Zoll Display und Touch tadellos. Beim 2.4 funktioniert das Display auch ohne Fehler, nur die Touch-Funktion ist fehlerbehaftet. Der Druckpunkt auf dem Display löst ganz andere Funktionen aus. In der Anleitung zum AZ-Touch MOD wird ein Beispiel zum Testen der Funktionalität, ein einfaches Code-Schloss, aufgeführt. Dabei benötigt jedes TFT (2.4 und 2.8 Zoll) jeweils einen eigene Firmware für den ESP32. Insofern denke ich, dass es einen Unterschied bei der Touch-Funktionalität zwischen beiden TFT-Displays gibt. Ich weiß nur nicht, wo ich ansetzen soll.

Gerald Lechner

Gerald Lechner

@Peter Lauber: Es gibt da noch einen weiterern Fehler, der den angezeigten Fehler auslöst. Überprüfen Sie die Anzeige auf weitere Fehler.
@Manfred: Ich habe dieses Problem fallweise auch gesehen, hab aber leider auch keine Idee wodurch diese Aussetzer verursacht werden.
@Harald Valeri: Die Ziffern sind Bitmaps die in der Datei 01_ziffern.ino als Array definiert werden. Ich werde Varianten der Datei für die Faben blau, grün und gelb erstellen und zum Download anbieten. Den Download werden Sie am Ende des Blog-Beitrags finden.
@Heiko: Das 2.4 Zoll Display sollte ohne Änderung funktionieren. Es könnte aber sein, dass Sie eine ältere Variante des AZ-Touch haben, der eine Abweichende Belegung für den Touch Interrupt hatte. Überprüfen Sie die Pin-Definitionen am Beginn der Datei tft_display.ino
@Peter: Der LDR wird zwischen GND und GPIO34 angeschlossen. GPIO34 wird über einen Pullup Widerstand von 10kOhm mit 3.3V verbunden.

Peter

Peter

Der Schaltplan beinhaltet 3 Widerstände.
R1 = 470 kOhm
R2 = LDR03 selbst?
R3 (Pin 1 an LDR und auch an Pin 3).
Es ist unklar (nicht lesbar), um welchen Widerstand es sich handelt und wo er auf der Platine montiert werden kann.

Könnten Sie das bitte klären?

Heiko

Heiko

Ein wirklich tolles Projekt, was nach Fertigstellung meinen Schreibtisch im HomeOffice bereichern wird. Mit dem 2,8 Zoll Display funktioniert es tadellos. Ich habe aber auch noch ein 2,4 Zoll Display und würde dieses gerne verwenden. Die Anzeige funktioniert hier auch einwandfrei, nur die Touch-Bedienung haut nicht hin. Wo im Sketch habe ich die Möglichkeit, das 2,4" Touch zu konfigurieren bzw. auszuwählen?

Harald Valeri

Harald Valeri

Hallo Herr Lechner,
wie kann ich die Uhrzeit-Ziffer-Farbe ändern? Von aktuell Rot auf z.B. Grün oder Blau?
Für einen Hinweis wäre wäre ich dankbar.
Schöne Grüße
Harald

Manfred

Manfred

Habe das Paket bestellt und zusammengebaut und es hat auf anhieb funktioniert.
Leider läuft das Radio nicht lange und es gibt Aussetzer bis zum connection lost …
was kann das sein.
habe ein stabiles Internet und Plan
lg. Manfred

Peter Lauber

Peter Lauber

Ich erhalte beim Kompilieren die Fehlermeldung "expected initializer bevfore “[” Token" aus der 01-zeichen.ino Markiert ist die Zeile const uint16_t ziffern_rot PROGMEM 11 3500 = {

Wo steckt der Fehler?

Wolfgang Schneider

Wolfgang Schneider

Das set ist heute angekommen, leider fehlt ein MAX98357A – es war nur ein Tütchen in der Box. Mal sehen, wie schnell die Nachlieferung kommt.
die beiden Lautsprecher lagen lose und unverpackt in der Box, bin gespannt, ob die noch funktionieren, es sind erst mal keine offensichtlichen Schäden erkennbar.
An den Lautsprechern sind schöne JST Steckerchen angebracht, leider liegen dem MAX98357A nur Schraubportale bei. Wäre eigentlich schöner gewesen, wenn man dafür eine passende JST Buchse beigelegt hätte. (Ich muss mal schauen, ob ich noch welche rumliegen hab).

Volker

Volker

Hallo, kann mir jemand sagen, wie das TFT-Display auf die Platine kommt? Lötet man es direkt darauf? Wenn ja, würde es mich wundern, denn man bekommt zumindest bei meiner eigenartigen Produktlieferung die Display-Pins weder auf der einen Seite noch auf der anderen Seite der Platine wegen der dort bereits aufgelöteten Bauelemente in die vorgesehenen Lötstellen.

Jakub

Jakub

Das Set ist heute angekommen und ich wollte es gleich mit meinem Sohn aufbauen.
Die Anleitung finde ich etwas dürftig, auf jeden Fall könnten die Bilder eine höhere Auflösung haben.

In das mitgelieferte Wandgehäuse passen nicht alle Teile rein, es muss also das größere gedruckt werden.

Ich habe das LDR Modul mitbestellt, würde es lieber mit 1-2 Schrauben befestigen, als mit dem doppelseitigen Klebeband.
Die DC Buchse war im Shop leider nicht lieferbar. Die 10 Stück bei Amazon sind mir zu viel.

Die Lautsprecher haben konfektionierte Zuleitungen, die Stecker passen nicht zu den Verstärkerplatinen und müssen abgeschnitten werden, schade.

Den 470kR Wiederstand hätte ich gern im Set gesehen.

Eine nette Option wäre ein Batteriebetrieb.
Mit einer 18650 kommt man da schon recht weit.

Der Eindruck ist allerdings ziemlich positiv.
Wenn alles zum Schluss funktioniert kann ich das Set weiterempfehlen.

Gerald Lechner

Gerald Lechner

@Thomas: In der Datei tft_display.ino kannn die Darstellung in Zeile 233 mit tft.setRotation(1); um 180 Grad gedreht werden. Das Speichern und Ändern der Sender funktioniert bei mir wie es soll. Eventuell ist die Senderliste durcheinandergekommen. Mit dem Knopf “Senderliste zurücksetzen” erhalten Sie wieder die Defaultliste.

Gerald Lechner

Gerald Lechner

@Gottfried Karner: Das wäre grundsätzlich möglich, stellt aber einen erheblichen Programmieraufwand dar. Die Anpassung müsste in der Datei tft_display.ino erfolgen. allerdings müsste dann die Darstellung des aktiven Senders ebenfalls angepasst werden.

Gerald Lechner

Gerald Lechner

@Manfred: Sie haben eventuell eine alte version von AZ-Touch bei der die Hintergrundbeleuchtung mit High eingeschaltet werden muss. In diesem Fall müssen Sie den Sketch selber kompilieren. Überprüfen Sie vor dem Kompilieren in der Datei tft_display.ino die Pin Zuordnung. LED_ON müssen Sie in diesem Fall auf 1 setzen.

Gerald Lechner

Gerald Lechner

@Bernd-Steffen Großmann: Wenn Sie die Datei 01_ziffern.ino mit der aus dem folgenden Link austauschen wird die “3” richtig dargestellt.
https://drive.google.com/file/d/1v3vGvkQTqI4Wcixp4Wk12-nT8bRs2jLc/view?usp=share_link

Manfred

Manfred

Hallo
Habe das .bin heruntergeladen und lt. Anleitung geflasht. Hat auch ohne Fehler funktioniert.
leider bleibt das Display schwarz …
passen die Einstellungen am falscher ? 0×10000 ?
bitte um Info
lg. Manfred

Bernd-Steffen Großmann

Bernd-Steffen Großmann

Noch eine kurze Ergänzung: nachdem ich heute die Schaltung entsprechend dem Verdrahtungsplan aufgebaut habe, funktioniert jetzt fast alles wie beschrieben, außer einigen Sendern: wie z.B. Hessen, u.a. Da muss ich noch mal im Netz nach den richtigen URLs suchen, und es fehlt ja auch noch der (für Senioren wie mich wichtige) WDR4 ;0)
Eins war mir auch noch aufgefallen: die Dreien in der Uhrzeit scheinen auf dem Kopf zu stehen, haben den großen Bogen oben und den kleinen unten. Das sieht etwas „schräg“ aus. Kann man das korrigieren? Wenn ja, wie? Ansonsten alles super! Noch mal besten Dank für tolle Arbeit und die super Anleitung! Mfg

Gerald Lechner

Gerald Lechner

@Werner: Ich habe es mit mehreren Browsern getestet und keine Probleme gehabt. Die ZIP Datei enthält nur Textdateien.

Gerald Lechner

Gerald Lechner

@Michael:
@Bernd-Steffen Großmann:
Danke für den Hinweis. Da ist mir leider ein Fehler passiert. Ich habe den Schaltplan korrigiert im Web und im PDF.
@Bernd-Burkhard BBB Borys:
Erstens muss ich darauf hinweisen, dass der Schaltplan einen Fehler enthielt, den ich korrigiert habe. Und nun zur Frage. Gain auf GND bedeutet 12dB Verstärkung. Die Lautstärke kann über die Software geregelt werden. An Vin wäre die Verstärkung 6dB. Der Anschluss SD dient zur Auswahl, welcher Kanal ausgegeben werden soll an Vin = linker Kanal, über 470 kOhm an Vin = rechter Kanal.
@Wolfgang Schneider:
Ich nutze ein Steckernetzteil mit 9V und 300mA.
@neil:
You are right, there was an error in the schematic. I have corrected it. You see now the correct schematicon web page and in the PDF.

Bernd-Steffen Großmann

Bernd-Steffen Großmann

Hallo Herr Lechner, sehr schönes Projekt. Jetzt kann ich endlich meinen doch recht einfachen Testaufbau eines Webradio mit Display und Touch-Bedienung ausstatten und das Az-Touch-Teil, was bisher nur mit Testsoftware ausgestattet war, einer sinnvollen Anwendung zuführen. Die Programmierung vom ESP32 ging mit der Arduino IDE problemlos, nachdem ich mit dem direkten Flashen des bin-Files keinen Erfolg hatte. Es wurde vom Py-Flasher ein Fehler im Header angezeigt!? Das Einrichten mit den WLAN-Daten und der Konfiguration funktionierte auch einwandfrei. Jetzt bin ich an der Tonausgabe-Seite dran und stolpere über einige Unstimmigkeiten zwischen dem Schaltplan und der Verdrahtung. Im Schaltplan geht der DIN-Anschluss vom MAX-IC an GPIO32 und in der Verdrahtung an GPIO33? Und auch der SD-Pin geht in der Schaltung an GPIO32 und in der Verdrahtung an 5V? Was ist richtig? Mit freundlichen Grüßen, Bernd-Steffen Großmann

Gottfried Karner

Gottfried Karner

Wunderbares Projekt und perfekt dokumentiert.
Möchte ich sofort nachbauen.
Da ich nachts ohne Brille nicht gut sehe, eine Anfrage. Könnte man ein etwas größeres Display mit analoger Uhr in das Projekt integrieren?
mfg G.K.

neil

neil

Hello
Is there not an error in your circuit diagram, it shows the SD pin (and resistor connected to the DIM line and not +5vs.
The board layout looks correct.
Thanks
Neil

kunigunde

kunigunde

Ich habe mir die Konfiguration’s Seite ein wenig moderner gestaltet.
Dazu habe ich die index.h bearbeitet.
[code]
//html for web pages
const char OPTION_entry[] PROGMEM =
“<option value=‘%i’ %s>%s %s”;

const char MAIN_page[] PROGMEM = R"=(




<link href = “https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css” rel = "stylesheet">
<script src = “https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js”>
<br /> $(function() {<br /> $(document).ready(getAll);<br /> $(&#8220;#btn_save&#8221;).click(saveSSID);<br /> $(&#8220;#btn_reset&#8221;).click(restartHost);<br /> $(&#8220;#btn_test&#8221;).click(testStation);<br /> $(&#8220;#btn_updt&#8221;).click(updateStation);<br /> $(&#8220;#btn_restore&#8221;).click(restoreStations);<br /> $(&#8220;#btn_savealarm&#8221;).click(setAlarms);<br /> $(&#8220;#btn_cancelalarm&#8221;).click(getAlarms);<br /> $(&#8220;#stationlist&#8221;).change(getStation);<br /> });</p> <p>function getAll() {<br /> getSSID();<br /> getStationList();<br /> getAlarms();<br /> }</p> <p>function getStationList() {<br /> $.ajax({<br /> type:&#8220;<span class="caps">GET</span>&#8221;,<br /> url:&#8220;/cmd/stations&#8221;,<br /> data:{},<br /> success: function(data){<br /> $(&#8220;#stationlist&#8221;).html(data);<br /> getStation();<br /> }<br /> });<br /> }</p> <p>function getStation() {<br /> $.ajax({<br /> type:&#8220;<span class="caps">GET</span>&#8221;,url:&#8220;/cmd/getstation&#8221;,<br /> data:{&quot;stationid&quot;:$(&#8220;#stationlist&#8221;).val()},<br /> success: function(data){<br /> const parts = data.split(&#8220;\n&#8221;);<br /> $(&#8220;#name_input&#8221;).val(parts<sup class="footnote" id="fnr0"><a href="#fn0">0</a></sup>);<br /> $(&#8220;#url_input&#8221;).val(parts<sup class="footnote" id="fnr1"><a href="#fn1">1</a></sup>);<br /> $(&#8220;#enable_input&#8221;).prop(&#8220;checked&#8221;,(parts<sup class="footnote" id="fnr2"><a href="#fn2">2</a></sup> == 1));<br /> $(&#8220;#pos_input&#8221;).val(parts<sup class="footnote" id="fnr3"><a href="#fn3">3</a></sup>);<br /> }<br /> });<br /> }</p> <p>function updateStation() {<br /> const checked = $(&#8220;#enable_input&#8221;).prop(&#8220;checked&#8221;)?1:0;<br /> $.ajax({<br /> type:&#8220;<span class="caps">GET</span>&#8221;,<br /> url:&#8220;/cmd/setstation&#8221;,<br /> data:{&quot;stationid&quot;:$(&#8220;#stationlist&#8221;).val(),<br /> <a href="">name</a>$(&#8220;#name_input&#8221;).val(),<br /> <a href="">url</a>$(&#8220;#url_input&#8221;).val(),<br /> <a href="checked">enabled</a>,<br /> <a href="">position</a>$(&#8220;#pos_input&#8221;).val()},<br /> success: function(data){<br /> const n = ( $(&#8220;#enable_input&#8221;).prop(&#8220;checked&#8221;))?&quot;&amp;#x25cf; &#8220;:&#8221;&amp;#x2002; &quot;<br /> $( &#8220;#stationlist option:selected&#8221; ).html(n + $(&#8220;#name_input&#8221;).val());<br /> alert(data);<br /> getStationList();<br /> }<br /> });<br /> }</p> <p>function restoreStations() {<br /> $.ajax({<br /> type:&#8220;<span class="caps">GET</span>&#8221;,<br /> url:&#8220;/cmd/restorestations&#8221;,<br /> data:{},<br /> success: function(data){<br /> getStationList();<br /> }<br /> });<br /> }</p> <p>function testStation() {<br /> const checked = $(&#8220;#enable_input&#8221;).prop(&#8220;checked&#8221;)?1:0;<br /> $.ajax({<br /> type:&#8220;<span class="caps">GET</span>&#8221;,<br /> url:&#8220;/cmd/teststation&#8221;,<br /> data:{&quot;url&quot;:$(&#8220;#url_input&#8221;).val()},<br /> success: function(data){<br /> alert(&#8220;Mit OK beenden Sie den Test&#8221;);<br /> endTest();<br /> },<br /> error: function() {<br /> alert(&#8220;<span class="caps">ERROR</span>&#8221;);<br /> }<br /> });<br /> }</p> <p>function endTest() {<br /> const checked = $(&#8220;#enable_input&#8221;).prop(&#8220;checked&#8221;)?1:0;<br /> $.ajax({<br /> type:&#8220;<span class="caps">GET</span>&#8221;,<br /> url:&#8220;/cmd/endtest&#8221;,<br /> data:{},<br /> success: function(data){<br /> }<br /> });<br /> }</p> <p>function getSSID() {<br /> $.ajax({<br /> type:&#8220;<span class="caps">GET</span>&#8221;,<br /> url:&#8220;/cmd/getaccess&#8221;,<br /> data:{},<br /> success: function(data){<br /> const parts = data.split(&#8220;\n&#8221;);<br /> $(&#8220;#ssid_input&#8221;).val(parts<sup class="footnote" id="fnr0"><a href="#fn0">0</a></sup>);<br /> $(&#8220;#pkey_input&#8221;).val(parts<sup class="footnote" id="fnr1"><a href="#fn1">1</a></sup>);<br /> $(&#8220;#ntp_input&#8221;).val(parts<sup class="footnote" id="fnr2"><a href="#fn2">2</a></sup>);<br /> }<br /> });<br /> }</p> <p>function getAlarms() {<br /> $.ajax({<br /> type:&#8220;<span class="caps">GET</span>&#8221;,<br /> url:&#8220;/cmd/getalarms&#8221;,<br /> data:{},<br /> success: function(data){<br /> const parts = data.split(&#8220;\n&#8221;);<br /> for (var i = 0; i &lt; 16; i++) {<br /> if ((i0) || (i8)) {<br /> $(&#8220;#al&#8221;<ins>i).val(parts[i]);<br /> } else {<br /> if (parts[i]==&#8216;1&#8217;) {<br /> $(&#8220;#al&#8221;</ins>i).prop(&#8216;checked&#8217;,true);<br /> } else {<br /> $(&#8220;#al&#8221;+i).prop(&#8216;checked&#8217;,false);<br /> }<br /> }<br /> }<br /> }<br /> });<br /> }</p> <p>function saveSSID() {<br /> $.ajax({<br /> type:&#8220;<span class="caps">GET</span>&#8221;,<br /> url:&#8220;/cmd/setaccess&#8221;,<br /> data:{&quot;ssid&quot;:$(&#8220;#ssid_input&#8221;).val(),<a href="">pkey</a>$(&#8220;#pkey_input&#8221;).val(),<a href="">ntp</a>$(&#8220;#ntp_input&#8221;).val()},<br /> success: function(data){<br /> alert(data);<br /> }<br /> });<br /> }</p> <p>function setAlarms() {<br /> const vals = new Object();<br /> for (var i = 0; i &lt; 16; i++) {<br /> if ((i == 0) || (i == 8)) {<br /> vals[&#8217;al&#8217;+i] = $(&#8220;#al&#8221;<ins>i).val();<br /> } else {<br /> vals[&#8216;al&#8217;</ins>i] = $(&#8220;#al&#8221;+i).prop(&#8220;checked&#8221;)?&#8216;1&#8217;:&#8216;0&#8217;;<br /> }<br /> }</p> $.ajax({ type:&#8220;<span class="caps">GET</span>&#8221;, url:&#8220;/cmd/setalarms&#8221;, data:vals, success: function(data){ alert(data); } }); <p>}</p> <p>function restartHost() {<br /> $.ajax({<br /> type:&#8220;<span class="caps">POST</span>&#8221;,<br /> url:&#8220;/cmd/restart&#8221;,<br /> data:{},<br /> });<br /> }<br />
<br /> body {<br /> width:300px;<br /> background-color: silver;<br /> }<br /> label { <br /> display: inline-block;<br /> margin-top: 5px;<br /> width: 100%;<br /> float: left; <br /> }<br /> button {<br /> width:45%;<br /> margin: 5px;<br /> height: 2.0em; <br /> }<br /> input {<br /> width:100%;<br /> }<br /> /* einzelnen Abschnitte moderner */<br /> fieldset {<br /> background-color: white;<br /> border: 2px solid orange;<br /> margin: 0 auto;<br /> margin-top: 20px;<br /> }<br /> legend {<br /> color: white;<br /> background-color: orange;<br /> width: 100%;<br /> text-align: center;<br /> }</p> <p>/* checkboxen Wochentage als &#8220;Button&#8221; */<br /> .categorie{<br /> background-color: white;<br /> overflow: hidden;<br /> float: left;<br /> }<br /> .categorie label {<br /> float: left;<br /> line-height: 2.0em;<br /> width: 2.0em; <br /> height: 2.0em;<br /> margin: 2px;<br /> }<br /> .categorie label span {<br /> text-align: center;<br /> padding: 2px 0;<br /> display: block;<br /> cursor: pointer;<br /> border: 1px solid silver;<br /> }<br /> .categorie label input {<br /> position: absolute;<br /> display: none;<br /> }<br /> .categorie input:checked + span {<br /> color: white; <br /> }<br /> .categorie input:checked + span{background-color: #82D44E;}</p>

Web Radiowecker WLAN / WIFI: SSID:

PKEY:

NTP:

Speichern Neustart
Senderliste Reset Wecker: Weckzeit 1:

Mo Di Mi Do Fr Sa So
Weckzeit 2:

Mo Di Mi Do Fr Sa So
Speichern Rückgängig Radio Stationen: Liste:

Name:

URL:

Verwenden:

Position:

Testen Ändern

)=";

//*****************************************************************************************************************
const char CONFIG_page[] PROGMEM = R"=(
<!DOCTYPE html>




<br /> body {<br /> width:300px;<br /> font-family:arial;<br /> }<br /> button {<br /> width:110px;<br /> background-color:silver;<br /> border-radius:10px;<br /> }<br /> .theme {<br /> background-color:cadetblue;<br /> padding:10px;<br /> border-radius: 10px;<br /> border: 2px solid silver;<br /> }<br /> .confpane {<br /> width:280px;<br /> height:75px;<br /> }<br /> .txtinput {<br /> position:absolute;<br /> left:90px;<br /> width:200px;<br /> }<br /> .label {<br /> color:white;<br /> font-family:arial;<br /> }</p>

Internet Radio SSID: PKEY: Neustart

)=";

[/code]
Bild:
https://drive.google.com/file/d/19i58HMTt3gapNuI2ZW17agT1Tr4vgEBl/view?usp=sharing

P.S.: Ihr habt einen Schreibfehler hier über dem Kommentarfeld:
“Nächser Beitrag” da ist das t verloren gegangen

Thomas

Thomas

Hallo. Ich habe ein Problem mit dem Touch, dieser ist bei mir um 180° gedreht. Wie kann ich das ändern?
Zudem kann ich über das Web-Interface neue Sender nicht richtig zuordnen, 2 funktionieren, beim 3. wird der erste wieder überschrieben. Ich kann die Stationsnummer zwar angeben, aber es wird nicht nachvollziehbar auf den ersten 3 Stationen gespeichert, teils auch Station 1 überschrieben, obwohl ich Station 3 ausgewählt habe.

Werner

Werner

Hallo Herr Lechner. Die “radiowecker.zip” scheint wohl einen virus zu enthalten … zumindest blockt der download mit der Meldung “Konnte nicht herunter geladen werden – Virus erkannt” beim ende-browser sowohl ach beim google chrome.

Wolfgang Schneider

Wolfgang Schneider

Wie muss das 9V Netzteil ausgelegt werden? Reicht ein 1A Netzteil ?

Michael Kirk

Michael Kirk

Hallo,
Kompliment, ein wirklich tolles Projekt!

Ich habe gerade das Set bestellt und freue mich schon aufs Bauen.

Vorher habe ich allerdings versucht die Toolchain zu erstellen.
Schliesslich nützt das schönste Projekt nichts, wenn die Software nicht läuft.

Man sollte sich schon genau an die Versionshinweise zu den verwendeten
Bibliotheken halten, sonst klappt das Erstellen nicht.
Aber das ist ja hervorragend dokumentiert.

Keinen Hinweis habe zur Einstellung für das Board gefunden.
Im Kit enhalten ist das “ESP-32 Dev Kit C V4”.
Das Kompilieren klappt mit dem universalen “ESP32 Dev Module”
und dem “ESP32C3 Dev Modul”.

Das STL-File für das Pult-Gehäuse ist natürlich das Sahnehäubchen.
Aber eben mit dem Äusseren hadere ich ein Bischen.

Versteht mich nicht falsch, dies soll keine Kritik sein.
Aber eine Schönheit ist die Kombination aus Gehäuse
und Display-Case wahrlich nicht.
Und wenn man es nicht gerade als Küchenradio plant,
wäre Weiss auch nicht die Farbe meiner Wahl.

Vielleicht gibt es ja einmal Alternativen zum originalen Display-Gehäuse.
Oder jemand erklärt, wie man ohne Paintbrush-Equipment,
dem weissen Gehäuse eine neue Farbe gibt.

Aber das ist wohl meine persönliche Zukunftmusik.
Wir werden sehen, was da noch kommt.

Danke, für dieses wunderbare, detaillierte Projekt.

Michael

Bernd-Burkhard BBB Borys

Bernd-Burkhard BBB Borys

Ich hätte gerne eine eigene Anwendung mit ESP32, den Verstärkern und Lautsprechern gebaut, aber ich verstehe den Schaltplan nicht. Wieso ist GAIN bei einem Verstärker an GND, beim anderen an VIN angeschlossen und DIN einmal direkt an SD, das andere Mal über einen Widerstand?

Michael

Michael

super projekt,
es sieht für mich nur so aus, als ob sich in der schaltplan zeichnung, ein fehler ist, der R1 ist dort falsch angeschlossen, die “verdrahtung” auf dem lochraster dagegen ist richtig.

Hannes

Hannes

Hi, I tried to download the source files – Windows Defender has found a virus in the zip file. Can you confirm this?

Ian

Ian

Can you produce a PDF in English, please?

Deja un comentario

Todos los comentarios son moderados antes de ser publicados