Schließen Sie den M5Stack an das Fernsehgerät an

Hallo! Heute lernen wir, wie man einen Fernseher an den M5STACK anschließt und mit einem analogen Videosignal Bilder und Text darauf anzeigt (Abb. 1).



Bild 1


, M5Stack BLACK https://openweathermap.org 433 , M5Stack GRAY .
M5Stack BLACK TF- Wi-Fi openweathermap.org.


. (. 1.1):


  • Wi-Fi- (system/wifi.ini);
  • (system/openweather.ini) (. 1.2).


1.1. system



1.2. openweather.ini



(. 2), .
, , , - .
. , . - . . . . . , . – . , ( ).



2. : 4 — , 8 — , 52 —



  • M5STACK (2 .);
  • USB-C ;
  • MicroSD 4 ;
  • ( -);
  • MX-JS-05V;
  • FS1000A;
  • PAL;
  • RCA-;
  • ;
  • .

!


1. openweathermap.org


, . (. 3).



3.


API keys Key .



3.1. API-


.


2.


— . , — RCA- (. 4 — 4.2).



4.



4.1



4.2


3. m5 black


, GET- . GET-, :


String GET(String url) {
  while (true)
  {
    if ((wifiMulti.run() == WL_CONNECTED))
    {
      HTTPClient http;
      http.begin(url);
      int httpCode = http.GET();
      if (httpCode > 0)
      {
          if (httpCode == HTTP_CODE_OK)
          {
            return http.getString();
          }
      }
      else
      {
        return (httpCode + "");
      }
      http.end();
    }
  }  
  return ""; 
}

openweathermap, , TF-. , GET-:


nl.sxgeo.city — IP-, GET-.

String configOpenWeather() {
  String file = TFReadFile("/system/openweather.ini");
  if (file != "")
  {  
    String city = "&q=" + parseString(1, '\"', parseString(1, ':', parseString(5, ',', GET("http://nl.sxgeo.city/?")))); 
    String api_key = "&APPID=" + parseString(0, ' ', file);
    String app_id = "&id=" + parseString(1, ' ', file);
    String lang = "&lang=" + parseString(2, ' ', file);
    String units = "&units=" + parseString(3, ' ', file);
    String host = "http://api.openweathermap.org/data/2.5/weather?";
    String url_ = host + city + api_key + app_id + lang + units;
    return url_;
  }
  return "";
}

, Wi-Fi TF-. . MacOS X. , Mac . , Windows — .


bool configWifiMulti() {
  /* Get WiFi SSID & password from wifi.ini from TF-card */
  String file = TFReadFile("/system/wifi.ini");
  if (file != "")
  {
    for (int i = 0; i < cntChrs(file, '\n'); i++)
    {
      String wifi = parseString(i, '\n', file);
      wifi = wifi.substring(0, (wifi.length()));
      if (wifi[wifi.length() - 1] == '\r') wifi = wifi.substring(0, (wifi.length() - 1));
      String ssid = parseString(0, ' ', wifi);
      String pswd = parseString(1, ' ', wifi);
      char* ssid_ = strToChar(ssid);
      char* pswd_ = strToChar(pswd);
      if (wifiMulti.addAP(ssid_, pswd_))
      {
        return true;
      }
    }
  }
  return false;
}

:


temp = parseString(2, ':', parseString(7, ',', weather));
pres = parseString(1, ':', parseString(8, ',', weather));
hum = parseString(1, ':', parseString(9, ',', weather));
desc = parseString(1, '"', parseString(1, ':', parseString(4, ',', weather))); 
weatherIcon = parseString(1, '"', parseString(1, ':', parseString(5, ',', weather)));

:


sendString("1" + String((char)0x1d) + temp);
delay(1);
sendString("2" + String((char)0x1d) + String(round(pres.toInt() * 0.75)));
delay(1);
sendString("3" + String((char)0x1d) + hum);
delay(1);
sendString("4" + String((char)0x1d) + desc);
delay(1);
sendString("5" + String((char)0x1d) + weatherIcon);
delay(1);   

- .


4. m5 gray


http://bitluni.net/esp32-composite-video/. , , . , m5stack_tv.h:


namespace m5stack_tv
{
  #include "CompositeGraphics.h"
  #include "Image.h"
  #include "CompositeOutput.h"
  #include <soc/rtc.h>
  #include "font6x8.h"

  const int XRES = 320;
  const int YRES = 200;

  CompositeGraphics graphics(XRES, YRES);
  CompositeOutput composite(CompositeOutput::NTSC, XRES * 2, YRES * 2);
  Font<CompositeGraphics> font(6, 8, font6x8::pixels);

  char* strToChar(String str) {
    int len = str.length() + 1;
    char* buf = new char[len];
    strcpy(buf, str.c_str());
    return buf;
  }

  void compositeCore(void *data) {  
    while (true)
    {
      composite.sendFrameHalfResolution(&graphics.frame);
    }
  }

  void begin() {
    rtc_clk_cpu_freq_set(RTC_CPU_FREQ_240M);
    composite.init();
    graphics.init();
    graphics.setFont(font);
    xTaskCreatePinnedToCore(compositeCore, "c", 2048, NULL, 1, NULL, 0);
  }

  void setTextColor(int c) {
    graphics.setTextColor(c);
  }

  void setCursor(int x, int y) {
    graphics.setCursor(x, y);
  }

  void print(String str) {
    graphics.print(strToChar(str));
  }

  void drawBitmap(int x, int y, int w, int h, const unsigned char* img) {   
    Image<CompositeGraphics> img_(w, h, img);
    img_.draw(graphics, x, y);
  }

  void fillRect(int x, int y, int w, int h, int color = 0) {
    graphics.fillRect(x, y, w, h, color);
  }

  void drawDot(int x, int y, int color) {
    graphics.dotFast(x, y, color);
  }

  void clearScreen(int color = 0) {
    fillRect(0, 0, XRES, YRES, color);
  }
}

: , . , "Downloads".

, :


void drawWeatherIcon(int x, int y, String str) {
  if (str == "01d") m5stack_tv::drawBitmap(x, y, _01d::xres, _01d::yres, _01d::pixels);
  else if (str == "01n") m5stack_tv::drawBitmap(x, y, _01n::xres, _01n::yres, _01n::pixels);
  else if (str == "02d") m5stack_tv::drawBitmap(x, y, _02d::xres, _02d::yres, _02d::pixels);
  else if (str == "02n") m5stack_tv::drawBitmap(x, y, _02n::xres, _02n::yres, _02n::pixels);
  else if (str == "03d") m5stack_tv::drawBitmap(x, y, _03d::xres, _03d::yres, _03d::pixels);
  else if (str == "03n") m5stack_tv::drawBitmap(x, y, _03n::xres, _03n::yres, _03n::pixels);
  else if (str == "04d") m5stack_tv::drawBitmap(x, y, _04d::xres, _04d::yres, _04d::pixels);
  else if (str == "04n") m5stack_tv::drawBitmap(x, y, _04n::xres, _04n::yres, _04n::pixels);
  else if (str == "09d") m5stack_tv::drawBitmap(x, y, _09d::xres, _09d::yres, _09d::pixels);
  else if (str == "09n") m5stack_tv::drawBitmap(x, y, _09n::xres, _09n::yres, _09n::pixels);
  else if (str == "10d") m5stack_tv::drawBitmap(x, y, _10d::xres, _10d::yres, _10d::pixels);
  else if (str == "10n") m5stack_tv::drawBitmap(x, y, _10n::xres, _10n::yres, _10n::pixels);
  else if (str == "11d") m5stack_tv::drawBitmap(x, y, _11d::xres, _11d::yres, _11d::pixels);
  else if (str == "11n") m5stack_tv::drawBitmap(x, y, _11n::xres, _11n::yres, _11n::pixels);
  else if (str == "13d") m5stack_tv::drawBitmap(x, y, _13d::xres, _13d::yres, _13d::pixels);
  else if (str == "13n") m5stack_tv::drawBitmap(x, y, _13n::xres, _13n::yres, _13n::pixels);
  else if (str == "50d") m5stack_tv::drawBitmap(x, y, _50d::xres, _50d::yres, _50d::pixels);
  else if (str == "50n") m5stack_tv::drawBitmap(x, y, _50n::xres, _50n::yres, _50n::pixels);
}

:


#include "weatherIcons/main.h"

:


m5stack_tv::begin();

Somit werden nach Erhalt der Wetterinformationen sofort im Fernsehen angezeigt:


void loop() { 
  if (radioRX.available(&k))
  {
    message("data accepted");
    radioRX.read(&j, sizeof(j));
    delay(1);
    message(j);
    int type = (parseString(0, (char)0x1d, j)).toInt();
    String data = parseString(1, (char)0x1d, j);
    if (type == 1) temp = data;
    else if (type == 2) pres = data;
    else if (type == 3) hum = data;
    else if (type == 4) desc = data; 
    else if (type == 5) icon = data;

    if (type > 0)
    {
      m5stack_tv::setTextColor(0);
      m5stack_tv::clearScreen(54);
      message("drawing on TV");  
      m5stack_tv::setCursor(140, 60);
      m5stack_tv::print("Temperature, C: " + temp);
      m5stack_tv::setCursor(140, 80);
      m5stack_tv::print("Humidity, %: " + hum);
      m5stack_tv::setCursor(140, 100);
      m5stack_tv::print("Pressure, mm Hg: " + pres);
      m5stack_tv::setCursor(140, 120);
      m5stack_tv::print(desc);
      drawWeatherIcon(30, 45, icon);
    }
  }
}

Schritt 5. Starten Sie!


Im Abschnitt "Download" beigefügtes Video, das die Arbeit demonstriert. Damit ist die Lektion abgeschlossen.


Downloads \ Links



All Articles