Getting closer…
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 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 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
}
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
I still have it plugged into the PC for testing… so it was nice to compare the two…
OH, Look… Something? happened after a really big number … Now all I need is a higher resolution LCD, or a nice wide format OLED… added to my Christmas list.
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?
I was using a massive 84x48 pixel display… so yours will be a tight squeeze, but workable
I think if you comment out or remove these lines, then everything will work “normal” with a larger display.
Thanks. Not sure when, but certainly will comment here my results.
I am too lazy to make a proper YouTube video … 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
I have since added in Blynk.config()
and re-connection routines
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
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
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();
}
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
//#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
}
@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:
Some of these similar looking OLEDS apparently can be set for SPI or i2c via soldered jumpers. Or at least the address used for i2c can be assigned in some.
But despite the extra SCL SDA pins, the color SSD1331 I have appears to be only a 4 pin SPI (VCC, GND, DC, CS - RST seems optional depending on the library) I successfully used these pins with my Wemos with that referenced library…
So VCC, GND, D0 and D8?
For VCC are you using 3.3V or 5V?
I have a feeling none of mine are color OLED’s.
I used 5v
Here is a snippet from another random example I used with the adafruit library… It wanted all the pins for Option 1, but I used the Option 2 Hardware SPI mode D0 and D8
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1331.h>
// You can use any (4 or) 5 pins - Wemos D1 Mini used here
#define sclk D5 //--- connect this to the display module SCL pin (Serial Clock)
#define mosi D7 //--- connect this to the display module SDA pin (Serial Data)
#define rst D6 //--- connect this to the display module RES pin (Reset)
#define dc D8 //--- connect this to the display module DC pin (Data or Command)
#define cs D0 //--- connect this to the display module CS pin (Chip Select)
// Option 1: use any pins but a little slower
// Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, mosi, sclk, rst);
// Option 2: must use the hardware SPI pins
// (for UNO thats sclk = 13 and sid = 11) and pin 10 must be
// an output. This is much faster - also required if you want
// to use the microSD card (see the image drawing example)
Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, rst);
OK I managed to get one of my 4 pin OLED’s working. 3,3V, GND, GPIO 5 SCL (WeMos D1) and GPIO 4 SDA (WeMos D2). This Adafruit sketch displays falling snowflakes on the screen.
/**************************************************************************
SSD1306.ino
This is an example for our Monochrome OLEDs based on SSD1306 drivers
Pick one up today in the adafruit shop!
------> http://www.adafruit.com/category/63_98
This example is for a 128x32 pixel display using I2C to communicate
3 pins are required to interface (two I2C and one reset).
Adafruit invests time and resources providing this open
source code, please support Adafruit and open-source
hardware by purchasing products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries,
with contributions from the open source community.
BSD license, check license.txt for more information
All text above, and the splash screen below must be
included in any redistribution.
**************************************************************************/
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET LED_BUILTIN //4 -1 // 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define NUMFLAKES 10 // Number of snowflakes in the animation example
#define LOGO_HEIGHT 16
#define LOGO_WIDTH 16
static const unsigned char PROGMEM logo_bmp[] =
{ B00000000, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000011, B11100000,
B11110011, B11100000,
B11111110, B11111000,
B01111110, B11111111,
B00110011, B10011111,
B00011111, B11111100,
B00001101, B01110000,
B00011011, B10100000,
B00111111, B11100000,
B00111111, B11110000,
B01111100, B11110000,
B01110000, B01110000,
B00000000, B00110000 };
void setup() {
Serial.begin(115200);
Serial.println(F("SSD1306 test"));
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
Serial.println(F("OK"));
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
display.display();
delay(2000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
// Draw a single pixel in white
display.drawPixel(10, 10, WHITE);
// Show the display buffer on the screen. You MUST call display() after
// drawing commands to make them visible on screen!
display.display();
delay(2000);
// display.display() is NOT necessary after every single drawing command,
// unless that's what you want...rather, you can batch up a bunch of
// drawing operations and then update the screen all at once by calling
// display.display(). These examples demonstrate both approaches...
testdrawline(); // Draw many lines
testdrawrect(); // Draw rectangles (outlines)
testfillrect(); // Draw rectangles (filled)
testdrawcircle(); // Draw circles (outlines)
testfillcircle(); // Draw circles (filled)
testdrawroundrect(); // Draw rounded rectangles (outlines)
testfillroundrect(); // Draw rounded rectangles (filled)
testdrawtriangle(); // Draw triangles (outlines)
testfilltriangle(); // Draw triangles (filled)
testdrawchar(); // Draw characters of the default font
testdrawstyles(); // Draw 'stylized' characters
testscrolltext(); // Draw scrolling text
testdrawbitmap(); // Draw a small bitmap image
// Invert and restore display, pausing in-between
display.invertDisplay(true);
delay(1000);
display.invertDisplay(false);
delay(1000);
testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
}
void loop() {
}
void testdrawline() {
int16_t i;
display.clearDisplay(); // Clear display buffer
for(i=0; i<display.width(); i+=4) {
display.drawLine(0, 0, i, display.height()-1, WHITE);
display.display(); // Update screen with each newly-drawn line
delay(1);
}
for(i=0; i<display.height(); i+=4) {
display.drawLine(0, 0, display.width()-1, i, WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
for(i=0; i<display.width(); i+=4) {
display.drawLine(0, display.height()-1, i, 0, WHITE);
display.display();
delay(1);
}
for(i=display.height()-1; i>=0; i-=4) {
display.drawLine(0, display.height()-1, display.width()-1, i, WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
for(i=display.width()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, i, 0, WHITE);
display.display();
delay(1);
}
for(i=display.height()-1; i>=0; i-=4) {
display.drawLine(display.width()-1, display.height()-1, 0, i, WHITE);
display.display();
delay(1);
}
delay(250);
display.clearDisplay();
for(i=0; i<display.height(); i+=4) {
display.drawLine(display.width()-1, 0, 0, i, WHITE);
display.display();
delay(1);
}
for(i=0; i<display.width(); i+=4) {
display.drawLine(display.width()-1, 0, i, display.height()-1, WHITE);
display.display();
delay(1);
}
delay(2000); // Pause for 2 seconds
}
void testdrawrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2; i+=2) {
display.drawRect(i, i, display.width()-2*i, display.height()-2*i, WHITE);
display.display(); // Update screen with each newly-drawn rectangle
delay(1);
}
delay(2000);
}
void testfillrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2; i+=3) {
// The INVERSE color is used so rectangles alternate white/black
display.fillRect(i, i, display.width()-i*2, display.height()-i*2, INVERSE);
display.display(); // Update screen with each newly-drawn rectangle
delay(1);
}
delay(2000);
}
void testdrawcircle(void) {
display.clearDisplay();
for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
display.drawCircle(display.width()/2, display.height()/2, i, WHITE);
display.display();
delay(1);
}
delay(2000);
}
void testfillcircle(void) {
display.clearDisplay();
for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
// The INVERSE color is used so circles alternate white/black
display.fillCircle(display.width() / 2, display.height() / 2, i, INVERSE);
display.display(); // Update screen with each newly-drawn circle
delay(1);
}
delay(2000);
}
void testdrawroundrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2-2; i+=2) {
display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
display.height()/4, WHITE);
display.display();
delay(1);
}
delay(2000);
}
void testfillroundrect(void) {
display.clearDisplay();
for(int16_t i=0; i<display.height()/2-2; i+=2) {
// The INVERSE color is used so round-rects alternate white/black
display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
display.height()/4, INVERSE);
display.display();
delay(1);
}
delay(2000);
}
void testdrawtriangle(void) {
display.clearDisplay();
for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
display.drawTriangle(
display.width()/2 , display.height()/2-i,
display.width()/2-i, display.height()/2+i,
display.width()/2+i, display.height()/2+i, WHITE);
display.display();
delay(1);
}
delay(2000);
}
void testfilltriangle(void) {
display.clearDisplay();
for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
// The INVERSE color is used so triangles alternate white/black
display.fillTriangle(
display.width()/2 , display.height()/2-i,
display.width()/2-i, display.height()/2+i,
display.width()/2+i, display.height()/2+i, INVERSE);
display.display();
delay(1);
}
delay(2000);
}
void testdrawchar(void) {
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(0, 0); // Start at top-left corner
display.cp437(true); // Use full 256 char 'Code Page 437' font
// Not all the characters will fit on the display. This is normal.
// Library will draw what it can and the rest will be clipped.
for(int16_t i=0; i<256; i++) {
if(i == '\n') display.write(' ');
else display.write(i);
}
display.display();
delay(2000);
}
void testdrawstyles(void) {
display.clearDisplay();
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(WHITE); // Draw white text
display.setCursor(0,0); // Start at top-left corner
display.println(F("Hello, world!"));
display.setTextColor(BLACK, WHITE); // Draw 'inverse' text
display.println(3.141592);
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(WHITE);
display.print(F("0x")); display.println(0xDEADBEEF, HEX);
display.display();
delay(2000);
}
void testscrolltext(void) {
display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(10, 0);
display.println(F("scroll"));
display.display(); // Show initial text
delay(100);
// Scroll in various directions, pausing in-between:
display.startscrollright(0x00, 0x0F);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrollleft(0x00, 0x0F);
delay(2000);
display.stopscroll();
delay(1000);
display.startscrolldiagright(0x00, 0x07);
delay(2000);
display.startscrolldiagleft(0x00, 0x07);
delay(2000);
display.stopscroll();
delay(1000);
}
void testdrawbitmap(void) {
display.clearDisplay();
display.drawBitmap(
(display.width() - LOGO_WIDTH ) / 2,
(display.height() - LOGO_HEIGHT) / 2,
logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
display.display();
delay(1000);
}
#define XPOS 0 // Indexes into the 'icons' array in function below
#define YPOS 1
#define DELTAY 2
void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
int8_t f, icons[NUMFLAKES][3];
// Initialize 'snowflake' positions
for(f=0; f< NUMFLAKES; f++) {
icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
icons[f][YPOS] = -LOGO_HEIGHT;
icons[f][DELTAY] = random(1, 6);
Serial.print(F("x: "));
Serial.print(icons[f][XPOS], DEC);
Serial.print(F(" y: "));
Serial.print(icons[f][YPOS], DEC);
Serial.print(F(" dy: "));
Serial.println(icons[f][DELTAY], DEC);
}
for(;;) { // Loop forever...
display.clearDisplay(); // Clear the display buffer
// Draw each snowflake:
for(f=0; f< NUMFLAKES; f++) {
display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, WHITE);
}
display.display(); // Show the display buffer on the screen
delay(200); // Pause for 1/10 second
// Then update coordinates of each flake...
for(f=0; f< NUMFLAKES; f++) {
icons[f][YPOS] += icons[f][DELTAY];
// If snowflake is off the bottom of the screen...
if (icons[f][YPOS] >= display.height()) {
// Reinitialize to a random position, just off the top
icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
icons[f][YPOS] = -LOGO_HEIGHT;
icons[f][DELTAY] = random(1, 6);
}
}
}
}
That’ll be your 7 day weather forecast then!
Up in the Troodos mountains, perhaps.
Yes it turns out that the 2 OLED’s I have with 7 pins can be configured differently if I get out the iron, which I’m reluctant to do. There is a default setting that should work but I haven’t got them running yet.
Of the 3 OLED’s I have with 4 pins one appears to be dead. One displays white text and the resolution is very poor. I have to set a fontsize of 2 for it to be clear enough to read but then it is too big to get very much text on the display.
The third one is quite nice and displays blue text with fontsize 1 being crystal clear if you have 20:20 vision, which I don’t.
I tweaked your code to display a line of text at a time rather than a single character. With the single character format it was like watching an IBM terminal from the 1970’s Also after displaying the Blynk logo I enable text wrapping to the display.
I have two versions of your code:
First version
Allows BLYNK_DEBUG to be sent to the OLED and has a separate class for CustomTerminal. As Terminal only works once the connection has been made you don’t get to see the logo in the Terminal so I have:
BLYNK_CONNECTED()
{
myTerminal.println(F("Connected to Blynk"));
myTerminal.print(F("Local IP: "));
myTerminal.println(WiFi.localIP());
}
Second version
Just one print class to send text to Serial Monitor or Terminal, without an OLED. Useful when your project doesn’t have access to a Serial Monitor. By using myConsole.println() you don’t have to edit a long sketch which might be littered with Serial.println() and Blynk.virtualWrite(Vx, “text to terminal”) commands.
/*************************************************************
SM2Terminal.ino Send Serial Monitor data to Blynk Terminal
Terminal widget on V0
*************************************************************/
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#define serialavailable // comment out when Serial Monitor is not available
class CustomConsole
: public Print
{
public:
CustomConsole() {}
virtual size_t write(uint8_t ch) // Grabs character from print
{
fulltext = fulltext + String(char(ch));
if (ch == '\n') // print a line at a time rather than a character at a time
{
Blynk.virtualWrite(V0, fulltext);
#ifdef serialavailable
Serial.print(fulltext);
#endif
fulltext = "";
}
return 1; // Sent a line of text to Serial Monitor and Terminal
}
private:
String fulltext = "";
};
CustomConsole myConsole;
#define BLYNK_PRINT myConsole
char auth[] = "xxx";
char ssid[] = "xxx";
char pass[] = "xxx";
char serv[] = "blynk-cloud.com";
BlynkTimer timer;
BLYNK_CONNECTED()
{
myConsole.println(F("Connected to Blynk"));
myConsole.print(F("Local IP: "));
myConsole.println(WiFi.localIP());
}
void myTimerEvent()
{
myConsole.println("Uptime: " + String(millis() / 1000));
}
void setup()
{
#ifdef serialavailable
Serial.begin(74880); // ESP8266 native baud rate
#endif
Blynk.begin(auth, ssid, pass, serv);
timer.setInterval(1000L, myTimerEvent);
}
void loop()
{
Blynk.run();
timer.run();
}