My attempts at transferring BLYNK_PRINT to Various Displays

Well, until I can suss out the proper EOL timing, this is the best I can get without flooding Debug data at it… and even then it doesn’t actually print in the proper line order all the time (note the ms times are out of order).

But something with the EOL must be automatically being accounted for in the buffer dump…everything lines up to the left margin properly… :thinking:

My dream of a “portable” Blynk status and debug monitor is still out of my grasp… with this cutting edge screen at least :wink: But as stated, it is good fearning… I am learning to not toss the thing out the window :stuck_out_tongue_winking_eye:

#include <SPI.h>  // For LCD
#include <U8g2lib.h>  // For LCD
U8G2_PCD8544_84X48_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 16, /* dc=*/ 4, /* reset=*/ 17);  // Nokia 5110 Display

#define BLYNK_PRINT u8g2
//#define BLYNK_DEBUG

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <ESPmDNS.h>  // For OTA
#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA
#include <TimeLib.h>
#include <WidgetRTC.h>
char auth[] = "xxxxxxxxxx";
char ssid[] = "xxxxxxxxxx";
char pass[] = "xxxxxxxxxx";
int line;
int height = 6;
BlynkTimer timer;
WidgetRTC rtc;

void setup() {
  u8g2.begin();
  u8g2.enableUTF8Print();  // Set for Arduino Print() support
  u8g2.setFont(u8g2_font_u8glib_4_hf);  // Choose a suitable font
  u8g2.drawFrame(0, 0, 83, 47);  // Draw Frame
  line = height;

  Blynk.begin(auth, ssid, pass, "xxx.xxx.xxx.xxx", 8442);

  rtc.begin();
  setSyncInterval(30);  // Show somthing on the screen every 30 seconds (Time Sync: OK)
 
  timer.setInterval(100, []() {  // Up Time
    Blynk.virtualWrite(V1, millis() / 1000);
  });
  
  ArduinoOTA.setHostname("Lolin32");  // For OTA
  ArduinoOTA.begin();  // For OTA
}

void loop()
{
  u8g2.setCursor(0, line);// Sets the left/bottom start point for first character
  u8g2.sendBuffer();  // this is what dumps data the th LCD

  // Makeshift... line shifter
  line += height;
  if (line > 48) {
    line = height;
  }

  Blynk.run();
  timer.run();
  ArduinoOTA.handle();  // For OTA
}

BLYNK_WRITE(V0) {  // Optional frame and screen clear
  if (param.asInt() == 1) {
    u8g2.drawFrame(0, 0, 83, 47);  // Draw Box
  } else {
    u8g2.clearDisplay();
  }
}
1 Like

off topic: How much does that heat-sink help?
Temps before/after?

@Gunner
which LCD are you using?
which library are you using?
i have used Adafruit_GFX & Adafruit_PCD8544 Libraries for my project.

Negligible at best… without it the metal casing never gets above 39°C I just put the heat sink there cuz it was rattling around on my desk otherwise :wink:

Now the little regulator, that gets hot :fire: … but then I am also using the ESP32 to power a 3.3v rail on the breadboard for a ESP-01 as I don’t have any other regulators.

1 Like

It is a Chineseium Nokia knockoff PCD-8544

And the library for this project is the aformentioned u8g2 because it has the needed, for this application, UTF8 support for the Arduino print function.

@vshymanskyy I think I am in the right direction in looking for syncing EOL and my own cursor positioning,

But I am not well versed in C++ to both discover the correct point (without insight) wherein I might intercept and and interpret (I am working on that via Google) the outgoing characters from BLYNK_PRINT to the target (i.e. Serial, Serial1, Screen, u8g2, etc).

At this point I would like to simultaneously and internally (via code) monitor the output as well as react to specific characters in said output.

I have found a few files locations in the Blynk Library, based on a simple search of BLYNK_PRINT, but can you, or someone, point me to the correct file, and perhaps correct segment of said file, where the characters are actually passed on?

@Gunner
The easiest way is to define your own custom console object:

// Lets define a custom console
class CustomConsole
    : public Print // This automatically adds functions like .println()
{
public:
    CustomConsole() {}

    virtual size_t write(uint8_t ch) {
        // Process symbols here:
        //if (ch == '\n') ...
        return 1; // <- this means we processed 1 symbol
    }
private:
    // Here you can define some variables you want to use in your console
    int cursorY = 0;
    int cursorX = 0;
};

// Now we instantiate it
CustomConsole myConsole;

// And use for Blynk output
#define BLYNK_PRINT myConsole

... [rest of the sketch] ...

These print(), println() functions are added from Print class, and it will call your write function every time it wants to print a symbol. You can then apply your own logic of any complexity :wink:

P.S. Another example of how this approach is used in Blynk library, is WidgetTerminal.

1 Like

Getting closer…

1 Like

Well thank you @vshymanskyy Once I got my head around it, I made it work with this wee little LCD.

Not much practical use on such a small screen, but all output is more or less readable :wink: Larger font at the start for a logo that, while truncated, is all lined up… then to a smaller font for “normal” serial output.

Nice thing is, this should work on any size LCD that the u8g2 Library supports.

And for anyone interested, here is the code.

Much of my if() checking is just for displaying the Blynk Logo the way I wanted it :stuck_out_tongue_winking_eye: and could be discarded to simplify the print output, which scrolls line by line until at the bottom, then clearing and starting from the top.

#include <SPI.h>  // For LCD
#include <U8g2lib.h>  // For LCD
U8G2_PCD8544_84X48_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 16, /* dc=*/ 4, /* reset=*/ 17);  // Nokia 5110 Display

// Define a custom console for LCD debug output
class CustomConsole
  : public Print // This automatically adds functions like .println()
{
  public:
    CustomConsole() {}
    virtual size_t write(uint8_t ch) {  // Grabs character from print?
      u8g2.print(char(ch));  // Add character to LCD buffer
      Serial.print(char(ch));  // Repeat all character output to Serial monitor
      if (char(ch) == ']') {  // Watch for closing brackets
        x++;  // Increment bracket count
        if (x == 4) {  // If after forth closing bracket on millis count...
          line -= height;  // ... backstep one line to fit Blynk Logo on screen
        }
      }
      if (ch == '\n') {  // End of line check
        line += height;  // Increment next line down
        u8g2.sendBuffer();  // Dump buffer to LCD
        if (line >= 49) {  // Last line on screen check
          if (x == 4) {  // If after fourth closing bracket on millis count...
            delay(10000);  // ... delay 10 seconds to view Blynk Logo
            u8g2.setFont(u8g2_font_u8glib_4_hf);  // set font to smaller size for remainder of debug prints
            u8g2.clearDisplay();  // Clear display
          }
          u8g2.sendBuffer();  // Dump buffer to LCD
          u8g2.setCursor(0, height);  // Reset line to top of screen
          line = height;  // Reset line counter
          delay(500);  // Small delay to allow visual of last line output on LCD
          u8g2.clearDisplay();  // Clear display
        } else {
          u8g2.sendBuffer();  // Dump buffer to LCD
          u8g2.setCursor(0, line);  // Set curser to next line down
        }
      }
      return 1; // Processed 1 character
    }
  private:
    // Here you can define some variables you want to use in your console
    int x = 0;  // bracket counter
    int line;  // line counter
    int height = 6;  // Line pixel height
};

// Now we instantiate it
CustomConsole myConsole;

#define BLYNK_PRINT myConsole
//#define BLYNK_DEBUG

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <ESPmDNS.h>  // For OTA
#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA
#include <TimeLib.h>
#include <WidgetRTC.h>
char auth[] = "xxxxxxxxxx";
char ssid[] = "xxxxxxxxxx";
char pass[] = "xxxxxxxxxx";
char server[] = "xxx.xxx.xxx.xxx";
int line;
int height = 6;  // Line pixel height
BlynkTimer timer;
WidgetRTC rtc;

void setup() {
  line = height;  // Reset line counter
  Serial.begin(115200);
  u8g2.begin();  // Start LCD library
  u8g2.enableUTF8Print();  // Activates UTF8 support for the Arduino print function
  u8g2.setFont(u8g2_font_micro_mr);  // choose a suitable font for Logo
  u8g2.setCursor(0, 6);  // Sratrt at top line of LCD

  //Blynk.connectWiFi(ssid, pass);
  //Blynk.config(auth, server, 8442);
  Blynk.begin(auth, ssid, pass, server, 8442);
  rtc.begin();
  setSyncInterval(30);  // Time Sync - not working with Blink.config()??
  BLYNK_LOG("Hello Gunner");  // Say Hello

  timer.setInterval(1000, []() {  // Up Time
    Blynk.virtualWrite(V1, millis() / 1000);  // Display Uptime in seconds
    BLYNK_LOG("Hello Gunner");  // Initial message
    //u8g2.print(WiFi.RSSI());  // Optional RSSI strength 
  });

  ArduinoOTA.setHostname("Lolin32");  // For OTA
  ArduinoOTA.begin();  // For OTA
}

void loop() {
  Blynk.run();
  timer.run();
  ArduinoOTA.handle();  // For OTA
}
5 Likes

Yes! it verx! … one of the purposes of this was to eventually have a localised (aka On Device) debug of things normally only seen on the Serial monitor…

So somehow, my device lost connection… considering it does nothing right now but (supposedly) regularly sync the time… but refuses to say so?? 'nother issue 'nother day :wink:

I still have it plugged into the PC for testing… so it was nice to compare the two…

image

OH, Look… Something? happened after a really big number :stuck_out_tongue: … Now all I need is a higher resolution LCD, or a nice wide format OLED… added to my Christmas list.

1 Like

Need something compact, enough screen real estate… but affordable for individual device use…

Probably still not big enough?? But might work with reduced font.

I like the idea! In spare time will try to use my brand new (but already 2 years old…) UC1608 240x128 display supported by u8glib. Will Blynk logo fit on that? :laughing:

1 Like

I was using a massive 84x48 pixel display… so yours will be a tight squeeze, but workable :stuck_out_tongue_winking_eye:

I think if you comment out or remove these lines, then everything will work “normal” with a larger display.

1 Like

Thanks. Not sure when, but certainly will comment here my results.

I am too lazy to make a proper YouTube video :blush: … but here is a GIF of my current alliteration… I realise now that you can’t really see the data scrolling by in the top half of the LCD…

I merged in my above redirection code and a Virtual LED matrix code (not showing, but running in another tab) and now also containing random servo moves and CPU temp checks - Basically a programming test bench for my ESP32.

The top half of the screen is a scrolling account of any Blynk prints, logs & errors, plus any timer based “serial” prints I make, actually myConsole.println(), such as RSSI and time/date stamps.

While the bottom half is a direct screen print of real-time data like Servo position and CPU temp.

One benefit I have already noticed is that occasionally my ESP seemed to loose Blynk connection… but even while originally using Blynk.begin() and without any coded checks or Blynk.run() bypasses, somehow keep on running everything else in the code?? maybe an automatic dual core ESP32 thing??

Anyhow… so I never really knew it was disconnected until I checked the App. But now I can see the "connecting to… " message in the screen :wink:

I have since added in Blynk.config() and re-connection routines :stuck_out_tongue_winking_eye:

2 Likes

Well, I am not sure where my fascination with displays and LEDs comes from… probably the whole visual understanding thing… but I can’t leave this one alone :nerd_face:

So I finally managed to get my little SSD1331, a 96x64 Full Colour OLED display (that I had previously wired as a Wemos shield) and added in this Blynk print redirection… so far so good.

The best library I found for this OLED for speed is an older one. https://github.com/sumotoy/SSD_13XX But very fast and relatively easy to program for… just lousy / non-existent directions for all the commands… have to spend lots of time dissecting and testing from the library files.

It allows simpler Blynk Print setup and word wrapping… which makes it much nicer to just dump test to

It even has a small collection of external fonts. Unfortunately, the font that looks the best for the Blynk Logo (Terminal_9) is a bit too big… so only half a logo for me :frowning:

But the display (or libraries) built-in font is fairly OK, and shows more text.

And a sketch for the ESP8266 and the ssd1331 OLED

//#define BLYNK_DEBUG
#define BLYNK_NO_BUILTIN  // Disable Blynk's built-in analog & digital pin operations

#include <SPI.h>
#include <SSD_13XX.h>
#include "_fonts/Terminal_9.c"
#define __CS_TFT 16  // pin D0
#define __DC_TFT 15  // pin D8
SSD_13XX tft = SSD_13XX(__CS_TFT, __DC_TFT);

class CustomConsole
  : public Print // This automatically adds functions like .println()
{
  public:
    CustomConsole() {}
    virtual size_t write(uint8_t ch) {  // Grabs character from print
      tft.setTextWrap(false);  // Enable/disable word wrapping
      tft.setFontInterline(1);  // Add single pixel in-between lines
      tft.print(char(ch));  // print character to OLED
      Serial.print(char(ch));  // Repeat all character output to Serial monitor
      if (ch == '\n') {  // End of line check
        line ++;
        if (line >= 7 ) {  // Last line on screen check
          line = 0;  // Reset line counter
          if (firstScreen == 0) {
            firstScreen = 1;
            delay(5000);  // One-time delay to view Logo :)
          }
          tft.print(char(ch));  // print character to OLED
          delay(500);  // Small delay to allow viewing of last line befor screen clear
          tft.clearScreen();
        }  // End screen wrap
      }  // End line count
      return 1; // Processed 1 character
    }  // End character print
  private:
    int line = 0;
    int firstScreen = 0;
};

CustomConsole myConsole;

#define BLYNK_PRINT myConsole
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
BlynkTimer timer;

char auth[] = "xxxxxxxxxx";  // Local Server
char ssid[] = "xxxxxxxxxx";
char pass[] = "xxxxxxxxxx";
char server[] = "xxx.xxx.xxx.xxx";
int port = 8080;



void setup() {
  Serial.begin(115200);
  tft.begin();
  WiFi.begin(ssid, pass);
  Blynk.config(auth, server, port);
  Blynk.connect();

  // Timed Lambda Function - UpTime counter
  timer.setInterval(1000L, []() {  // Run every second
    Blynk.virtualWrite(V0, millis() / 1000);  // Display the UpTime in Minutes to App
    myConsole.println(millis() / 1000);  // Display the UpTime in Minutes to OLED and Serial
  });  // END Timer Function
}



void loop() {
  Blynk.run();
  timer.run();
}
3 Likes

And my latest addition to this Blynk Serial Display phase I am on…

The TTG ESP32 with OLED & 18650

Tiny screen, but good resolution (128x64)… hard to focus up close :slight_smile:


//#define BLYNK_DEBUG
#define BLYNK_MAX_READBYTES 1024
#define BLYNK_MSG_LIMIT 0
#define BLYNK_HEARTBEAT 60
#define BLYNK_NO_BUILTIN  // Disable Blynk's built-in analog & digital pin operations

#include <U8g2lib.h>  // For OLED
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0,/* reset=*/ U8X8_PIN_NONE,/* clock=*/ 4, /* data=*/ 5);   // The all important setup for the TTGO's build in OLED

// Define a custom console for OLED debug output
class CustomConsole
  : public Print // This automatically adds functions like .println()
{
  public:
    CustomConsole() {}
    virtual size_t write(uint8_t ch) {  // Grabs character from print
      u8g2.print(char(ch));  // Add character to OLED buffer
      Serial.print(char(ch));  // Repeat all character output to Serial monitor
      if (ch == '\n') {  // End of line check
        u8g2.sendBuffer();  // Dump buffer to OLED
        line += height;  // Increment next line down
        if (line >= 72) {
          line = height;  // Reset line counter
        }
        u8g2.sendBuffer();  // Dump buffer to OLED
        u8g2.setCursor(0, line);  // Set curser to next line down
      }
      return 1; // Processed 1 character
    }
  private:
    // define variables used in myConsole
    int line = 8;  // line counter
    int height = 8;  // Line pixel height
};

// initiate myConsole
CustomConsole myConsole;

#define BLYNK_PRINT myConsole

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <ESPmDNS.h>  // For OTA
#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA
#include <TimeLib.h>
#include <WidgetRTC.h>

char auth[] = "xxxxxxxxxx";
char ssid[] = "xxxxxxxxxx";
char pass[] = "xxxxxxxxxx";
char server[] = "10.10.3.13";
int port = 8080;

char currentTime[9];
char currentDate[11];

BlynkTimer timer;
WidgetRTC rtc;



void setup() {
  pinMode(16, OUTPUT);
  u8g2.setFont(u8g2_font_micro_mr);  // choose a suitable font for Logo
  Serial.begin(115200);
  u8g2.begin();

  timer.setInterval(1010L, TimeDatecheck);
  timer.setInterval(2030L, RSSIcheck);
  timer.setInterval(3045L, FlashLED);

  WiFi.begin(ssid, pass);
  Blynk.config(auth, server, port);
  Blynk.connect();

  ArduinoOTA.setHostname("TTGO - OLED & 18650");  // For OTA
  ArduinoOTA.begin();  // For OTA
}



BLYNK_CONNECTED() {
  rtc.begin();
  setSyncInterval(360);  // Time Sync
}



void loop() {
  ArduinoOTA.handle();  // For OTA
  timer.run();
  Blynk.run();
}

//--------------------------------------------------//

void TimeDatecheck() {
  sprintf(currentTime, "%02d:%02d:%02d", hour(), minute(), second());
  sprintf(currentDate, "%02d/%02d/%04d", month(), day(), year());
  myConsole.print(currentTime);
  myConsole.print("  ");
  myConsole.print(currentDate);
  myConsole.println("                    ");
}



void RSSIcheck() {
  Blynk.virtualWrite(V67, WiFi.RSSI()); // RSSI
  //myConsole.print("Board #1 - RSSI  ");
  myConsole.print("Board #2 - RSSI  ");
  myConsole.print(WiFi.RSSI());
  myConsole.println("                    ");
}



void FlashLED() {
  digitalWrite(16, LOW);  // Turn ON
  delay(100);
  digitalWrite(16, HIGH);  // Turn OFF
}
3 Likes

@Gunner can you please provide the full pin details for the OLED you are using. I have 4 or 5 OLED’s that I haven’t used for a year or more. Some have 4 pins but with pins switched around between different models and some have 7 like yours. Might be my lack of soldering skills that’s a problem but I couldn’t get any of them to work. They were working when I last used them but I might have destroyed one of them.

In the old days you had to tweak the libraries to your particular OLED but it looks like most of that is now done in the sketch.

see also:

1 Like