Sonntag, 2. April 2023

AZ-Delivery 2.Advent Neues Internetradio mit ESP32 und MAX 98357A

 hier soll es darum gehen diese software von AZ-Delivery vorzustellen, anzupassen und zu erweitern. Im Thread von Jens (pintel) wurde sie schon gezeigt, und zwar in Verbindung mit pintel's ESP32 Audio Platine. Der sketch ist aber auch auf anderen ESP32-Boards einsetzbar. Und deshalb, und auch um den Thread von Jens nicht mit zu vielen Details aufzublähen, widme ich dem Programm einen eigenen Thread.

 

 Was macht das Radio so besonders? Da gibt es so einige Punkte.

- es basiert auf der Library von earlephilhower (Earle F. Philhower). Jens selbst bezeichnet die Library als die besten von allen.
- die Bedienung mit 2 Encodern ist "klassisch". Kein Gefummel mit Doppel- oder Dreifachklick wie z.B. bei Edzelf.
- als Kompiler eigenet sich die Arduino-IDE V1 oder V2, wobei die V2 zu bevorzugen ist. Es ist also kein aufwendiges Framework nötig.

Nachteile:
- die Software ist erst mal nur für ein LCD1602 bzw. LCD2004 per I2C geschrieben. Hier wird meine erste Änderung ansetzen.
- Das webinterface ist spartanisch. Es ist für die Erstinbetriebnahme brauchbar, sowie für das Ändern der Senderliste. Nicht aber für die Bedienung des Radio.

zum Einstieg in der Programm möchte ich auf o.a. Thread des pintel-audio-board verweisen, post#72

hier nochmal der direkte link:

2. Advent: Neues Internetradio mit ESP32 und MAX 98357A

voreingestellte GPIO-Definitionen:

I2S-DAC:

LRC 25
BCLK 26
DIN 27

LCD-Display:

SDA 21
SCL 22

Encoder Lautstärke

CLK 14
DT 13
SW

Encoder Senderwahl

CLK 33
DT 32
SW 35 (dieser PIN muss zwingend mit einem pullup versehen sein, sonst "pumpt" das Radio)

scrollt man auf der AZ-Delivery Seite weiter nach unten und hat deutsche Spache eingestellt entdeckt man ein Update von Andreas Kühn mit einem neuen Sketch, bei dem die Ausgabe auf ein 1,8 Zoll SPI-Display mit ST7735-Chip geändert wurde. Ist die Seite auf englische Sprache eingestellt ist das Udate nicht sichtbar!

Die Display-Verdrahtung ändert sich wie folgt:

CS GPIO 05
RESET EN
A0 GPIO 17
SDA GPIO 23
SCK GPIO 18
LED 3.3V (Backlight)

 


m nächsten Teil geht es etwas in die Eingeweide. Nämlich um die Änderungen im Sketch auf andere Display-Controller und andere Auflösungen.

Dafür ist der Programmteil display.ino zuständig. Der Quellcode beinhaltet die entsprechenden Hinweise, so dass auch ohne Informatik-Studium ein Umbau der Display-Ausgabe zu bewerkstelligen ist.

Code:
****************************************************************************************/

#include <U8g2lib.h>              // -> U8g2 font list: https://github.com/olikraus/u8g2/wiki/fntlistall
                                  //    U8g2 Unifont list: https://github.com/olikraus/u8g2/wiki/fntgrpunifont
#include <Arduino_GFX_Library.h>  // -> https://github.com/moononournation/Arduino_GFX
#define LS 25                    // line spacing

/* More data bus class: https://github.com/moononournation/Arduino_GFX/wiki/Data-Bus-Class */
Arduino_DataBus *bus = new Arduino_SWSPI(17 /* DC */, 5 /* CS */, 18 /* SCK */, 23 /* MOSI */, GFX_NOT_DEFINED /* MISO */);

/* More display class: https://github.com/moononournation/Arduino_GFX/wiki/Display-Class */

Wir erfahren dass die Arduino_GFX_Library zum Einsatz kommt, womit ein starkes, vielseitiges Werkzeug zur Verfügung steht.

Wir beginnen mit dem Grafik-Chipsatz am Beispiel eines ILI9341 Display mit der Auflösung 240x320. Dazu ist laut der Display Class-Liste dieser Block zu ersetzten. Er beinhaltet im wesentlichen den Chip, die Ausrichtung, und die Auflösung des TFT. Der erste Parameter -1 muss dabei beibehalten werden.

aus:

Code:
Arduino_GFX *gfx = new Arduino_ST7735(
  bus, -1 /* RST */, 3 /* rotation */, false /* IPS */, 128 /* width */, 160 /* height */,
  0 /* col offset 1 */, 0 /* row offset 1 */, 0 /* col offset 2 */, 0 /* row offset 2 */,
  false /* BGR */);               // for 1.8" BLACKTAB 128x160; Soft-SPI. Rotation: 3 -> pins left / 1 -> pins right

wird also:

Code:
Arduino_GFX *gfx = new Arduino_ILI9341(
  bus, -1 /* RST */, 3 /* rotation */, false /* IPS */);


bei richtiger Verdrahtung erhalten wir nun schon mal eine kleine Ausgabemaske auf einem großen Display.

Die Grafik für die Lautstärekanzeige (gain) ist auf dem Bild bereits an den rechten Rand verschoben. Zuständig ist die Koordinate x0:

Code:
void displayGain() {
  uint8_t g = 5 * log(curGain / 2);
  uint16_t x0,x1,x2,y0,y1,y2;
  x0 = 285;

es folgt die Schriftauswahl der ersten Zeile (Datum/Uhrzeit) anhand der u8g2 Font-Liste. Es wird eine zeilenfüllende Schriftgröße gewählt. Zuständig ist die Funktion void displayDateTime().

Ich habe eine 24px Schrift ausgesucht. Wichtig ist dass die Schrift auch alle Zeichen beinhaltet die dargestellt werden sollen. Desweiteren sind hier Änderungen auf die neuen Koordinaten ersichtlich. LS ist die Zeilenhöhe und orientiert sich an der größten benutzten Schrift. Im Deklarationsteil habe ich den Wert auf 25 gesetzt:

Code:
#define LS 25                    // line spacing


Die Date/Time-Zeile und die zugehörige Löschfunktion verschiebe ich um 7px nach unten, um gain nicht zu überschreiben. Die Löschfunktion (fillRect) soll natürlich bis zum Ende der Zeile (320px) reichen.

Code:
//show date, time and loudness in the first line
void displayDateTime() {
  Serial.println("Show Time");
  char sttime[21];
  gfx->fillRect(0, LS+7, 320, LS, BLACK);
  gfx->setFont(u8g2_font_ncenB24_tr);
  gfx->setTextColor(GREEN);
  gfx->setCursor(2, 2*LS+7);                                     // 1st line
  struct tm timeinfo;
  if (getLocalTime(&timeinfo)) {
  //get date and time as a string
    strftime(sttime, sizeof(sttime), "%d. %b %Y", &timeinfo);
    // MyLcdPrint(String(sttime));
    gfx->print(String(sttime));
    strftime(sttime, sizeof(sttime), " %H:%M", &timeinfo);
    // MyLcdPrint(String(sttime));
    gfx->setTextColor(WHITE);
    gfx->print(String(sttime));
  } else {gfx->print("??. ??? ???? ??:??");}               // if no result from RTC -> "??.???" is displayed
  //display loudness
  displayGain();
}

in der Funktion void showStation() ersetze ich die Löschfunktion clearLine() durch fillRect(). clearLine ließ sich einfach nicht korrekt positionieren. Ich wähle eine 14px-Schrift aus lasse sie in die 4. Zeile schreiben. Am Ende der Funktion bekommen die Trennstriche neue Koordinaten.

Code:
//show name of current station on TFT display
void showStation() {
  //clearLine(4);
  gfx->fillRect(0, (LS*3), 320, LS+5, BLACK); 
  //gfx->setFont(u8g2_font_prospero_bold_nbp_tf);
  gfx->setFont(u8g2_font_helvB14_te);
  gfx->setTextWrap(false);
  gfx->setCursor(2,(LS*4));                               // 2nd lime!
  String name = String(stationlist[curStation].name);
  if (curStation == actStation) {
    gfx->setTextColor(RED);
    gfx->print(name);                       // limit length to 19 chars
  } else {
    gfx->setTextColor(RED);
    gfx->print(" ?");
    gfx->setTextColor(YELLOW);
    gfx->print(name);                       // limit length to 17 chars + "?"
  }
  gfx->drawFastHLine(0, 2*LS+14, 320, WHITE);                  // Coordinate Beginn x, y; Länge
  gfx->drawFastHLine(0, (4 * LS) + 6, 320, WHITE);
}

die Funktion für mehrzeilige Ausgaben displayMessage2(), die für die Begleitinformationen der Sender zuständig ist, erfährt ebenfalls einige Änderungen bezgl. Schriftauswahl und Koordinaten:

Code::
//show a two OR MORE line message with line wrap
void displayMessage2(uint8_t line, String msg) {
  // delete 3 compressed lines (real line high 15)
  uint8_t L = (line * LS) + 9;
  //gfx->fillRect(0, L, 160, (LS + 15 + 15 -3), BLACK);       // coordinates upper left corner x, y; Breite; Höhe
  //gfx->fillRect(0, L, 160, 128-L, BLACK);
  gfx->fillRect(0, (4*LS+9), 320, (4*LS+9), BLACK);
  //gfx->setFont(u8g2_font_DigitalDiscoThin_tf);
  gfx->setFont(u8g2_font_helvB14_te);
  gfx->setTextColor(CYAN); 
  gfx->setCursor(2, (6 * LS));
  gfx->setTextWrap(true);
  gfx->print(msg);

das Endergebnis:

zum Schluss die komplette display.ino:


.zip   display.zip

Wie funktioniert die Bedienung?

ein Encoder ist für Lautstärke, ein weiterer für die Senderwahl. Dabei scrollt der Encoder in der Liste. Der Text der Senderanzeige ändert sich auf gelb, und ein Fragezeichen wird vorangestellt. Wird der passende Sender angezeigt so wird er durch Tastendruck auf den Encoder übernommen. Deshalb musste ich ja auch bei der Libelle eine extra Taste einbauen.


eine Alternative zur den Encodern gibt es nicht. 


   


 

Keine Kommentare:

Kommentar veröffentlichen