C++ Blynk - Code Examples for Basic Tasks (Work in Progress)


A post was split to a new topic: How to repeat the same activity or stop the activity form a function that is called by a BLYNK_WRITE(V?) function


#19 - Modified Text Input Widget performance - Now with 100% more line feed :stuck_out_tongue:

Well, here is another modification to make a widget work how I at least think it could (and possibly temporary… see my supplanted multi-coloured button above :wink: )

NOTE: This is NOT intended to undermine what Blynk has made… just add in my own personal preferences to somthing I wish to use in a particular way.

The text Input widget is great… easy to use and compact, compared to the Terminal input option. Only one thing… It doesn’t act like a ‘true’ (IMHO) text input. No EOL, ‘carriage return’ or clearing upon hitting return. All by design? Perhaps :smiley:

Well, here is my simple code mod to supply all those “missing” features :sunglasses:

You can still use the Widget as intended, or with the addition of a space and two periods (customisable) followed by the return key. you can get a cleared widget and a new line in the resulting string.

Due to the need for a SPACE to “clear” the widget… some post processing is used to remove a single leading SPACE from your string, if present.

String textIn; // declare global variable

//===== Modified Text Input Widget - BLYNK Function =====
  String textIn = param.asStr(); // Get string from Text Input Widget
  if (textIn.startsWith(" ")) {  // If it has a leading SPACE...
    textIn.remove(0, 1);  // ...remove it.
  if (textIn.endsWith(" ..")) {  // If it has customisable EOL indicator, In my case SPACE and 2 PERIODS...
    textIn.replace(" ..", "\n"); // ...replace with newline command
    Blynk.virtualWrite(V0, " ");  // "clear" the Text Input field.  A null "" will not work, so needs a space
  Serial.print(textIn);  // Show string output as intended, or do whatever you want with the string.
  Blynk.virtualWrite(vPin, textIn);  // Like send it to a terminal Widget

So if you want or need a truer text entry feeling, with carriage return effects… this…


…can become this, just by ending with a SPACE and 2 PERIODS (customisable)




To give this output…


And for the fun of it, here is some code to add a Clear Terminal button.

//===== Clear Terminal Widget =====
BLYNK_WRITE(vPin) {  // Button Widget
  if (param.asInt()) {
    Blynk.virtualWrite(vPin, "clr");  // Clears terminal if button state is 1


New iOS Release 2.22.0
New Android Release 2.22.0

5 posts were merged into an existing topic: Server connection dropouts


Photocell Delayed Action

#20 - Variable timer

There has been a few discussions about how to vary the interval time of a timer… I have even used one way in an earlier post above with the adjustable servo sweep.

But here is an easier way… use a one-shot Timeout Timer instead…

Create your function that you want to run on a variable interval, but don’t call that function with an outside timer, just call it the first time (if you want) in your setup or upon Blynk connect, or even wait until you chose a time, etc.

Then, using a global variable acquired from some other source (Slider, Step Control, Numeric input, etc.) end your custom timed function with a timeout timer, set to the required variable, that calls the same function it is already in.

If you really want to get fancy, you can setup Timer IDs and run a delete timer at the beginning of the function, thus allowing you to interrupt and cancel whatever previous setting… preventing duplicate function runs from leftover timeout timers.

long variableTime = 1000; // default interval time of 1 second
int varTimer;  // Setup Timeout Timer ID 
BLYNK_WRITE(V0) { // Widget for interval timing
  variableTime = param.asInt();
  if (variableTime <= 0) { // prevents a timer from becoming 0 or less
    variableTime = 1;
  timerLoop();  // Call your timed loop

void timerLoop() {
  timer.deleteTimer(varTimer);  // Cancel previous Timeout Timer
  //  Do your stuff here every (variableTime) seconds
  varTimer = timer.setTimeout(variableTime, timerLoop);  // Set new Timeout timer

Concurrent BLYNK_WRITE's
[SOLVED] Reset interval SimpleTimer
The truth is out there! (Servo control)

#21 - Sonoff Basic - Blynk and physical button control - with LED (showing ON status), OTA and displaying device specifics.

This is just a simple sketch for a Blynkified Sonoff Basic. Use either App or physical button to toggle the Sonoff. Physical button works even if no Server connected.

   Sonoff Basic
   1MB (No SPIFS) flash size
   115200 BAUD
   MUST USE DOUT for Flash Mode!!

   sonoff header
   1 - vcc 3v3
   2 - rx
   3 - tx
   4 - gnd
   5 - gpio 14

   esp8266 connections
   gpio  0 - button
   gpio 12 - relay
   gpio 13 - green led - active low
   gpio 14 - pin 5 on header

#include <ESP8266WiFi.h>  // for ESP8266
#include <BlynkSimpleEsp8266.h>  // for ESP8266
#include <ESP8266mDNS.h>  // For OTA w/ ESP8266
#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA

char auth[] = "xxxxxxxxxx";  // Sonoff
char ssid[] = "xxxxx";
char pass[] = "xxxxx";
char server[] = "";  // IP for your Local Server
int port = 8080;

int pinState = LOW;
int btnState = HIGH;

BlynkTimer timer;
void PhysButton();

void setup() {
  pinMode(0, INPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);  // Turn OFF LED

  timer.setInterval(250L, PhysButton);  // scan for physical button press

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

  ArduinoOTA.setHostname("Sonoff");  // For OTA - Use your own device identifying name
  ArduinoOTA.begin();  // For OTA

void loop() {;;
  ArduinoOTA.handle();  // For OTA

  Blynk.virtualWrite(V1, BLYNK_VERSION);
  Blynk.virtualWrite(V2, ESP.getCoreVersion());
  Blynk.virtualWrite(V3, WiFi.macAddress());
  Blynk.virtualWrite(V4, WiFi.localIP().toString());

BLYNK_WRITE(V0) { // Button Widget in switch mode
  digitalWrite(12, param.asInt());  // Toggle relay
  digitalWrite(13, !param.asInt());  // Toggle LED

void PhysButton() {
  if (digitalRead(0) == LOW) {
    // btnState is used to avoid sequential toggles
    if (btnState != LOW) {

      // Toggle LED state
      pinState = !pinState;
      digitalWrite(12, pinState);
      digitalWrite(13, !pinState);  // Toggle LED

      // Update Button Widget
      Blynk.virtualWrite(V0, pinState);
    btnState = LOW;
  } else {
    btnState = HIGH;

My simple display used to fit everything the way I wanted (centered columns under the buttons)… but now it looks lopsided with extended displays, that still crop on some devices… Boo!! Hiss!!

The sketch fits on the Sonoff, with a bit of room for more code :smiley:

Sonoff T1-Like switch
Amazon Echo ESP8266 control, with natural speech commands
Node Red and Blynk

#22 - Super Simple Duration Counter

OK, 'fess up time… I have rarely used millis() unless it was already included in some example or snippet copied from elsewhere, so I just assumed using it for actual human readable time was difficult… Well, it is not!! :blush:

V0 is a Button Widget set to switch mode
V1 is a Display Widget

And that is it… If all you need is a readable Hours/Minutes/Seconds duration display, without using Time library, RTC, etc. then here you go.

EDIT - Updated to count days as well, should your MCU stay running without reset that long :stuck_out_tongue_winking_eye:

You can take the key commands & process and implement them in any other type of displayable duration routine you want.

int runDays;
int runHours;
int secsRemaining;
int runMinutes;
int runSeconds;
char buf[21];
unsigned long startMillis;
unsigned long endMillis;
unsigned long allSeconds;

BLYNK_WRITE(V0) { // Switch Widget
  if (param.asInt() == 1) {
    startMillis = millis();  // The key command for starting the count
    Blynk.virtualWrite(V1, "Counting...");  // Display Widget
  } else {
    endMillis = millis();  // The key command for ending the count

    // The key process for displaying the converted duration
    allSeconds = (endMillis - startMillis) / 1000;
    runDays = allSeconds / 86400;
    secsRemaining = allSeconds % 86400;
    runHours = secsRemaining / 3600;
    secsRemaining = allSeconds % 3600;
    runMinutes = secsRemaining / 60;
    runSeconds = secsRemaining % 60;
    sprintf(buf, "Duration: %02d D : %02d H : %02d M : %02d S", runDays, runHours, runMinutes, runSeconds);
    Blynk.virtualWrite(V1, buf);  // Display Widget showing duration the Switch was 

Measuring the period

#23 - Basic Stepper Motor Control

Who says Blynk can’t control Stepper motors… well, OK, I have said it may require fancy non-blocking timing… so here it is (disclaimer, not all that fancy after all :stuck_out_tongue_winking_eye: )

Yes, it is using the old and decrepit Stepper.h library… only because I was too lazy to learn simple accelStepper commands at this moment :blush:

I am also controlling a 4.29v 1.8deg NEMA 17 stepper with an equally old L298D motor controller… Hey, I works with what I gots :wink:

UPDATE - Chose the commented out commands for ESP8266 (default) or ESP32, both with OTA (no I haven’t mastered #ifndef yet :blush: )

Uses a Slider Widget for speed - Slider V0 set with 0-100 and Send On Release ON (But if you really want it OFF, preferably at around 300-500ms, so you don’t flood the connection unnecessarily).

And a Button Widget for direction - Button V1 set as Switch with 0-1

#define BLYNK_PRINT Serial // This prints to Serial Monitor
//#define BLYNK_DEBUG  // Optional, this enables more detailed prints

////  Pick one Blynk Device Library group or other
// #include <WiFi.h>  // for ESP32
// #include <WiFiClient.h>  // for ESP32
// #include <BlynkSimpleEsp32.h>  // for ESP32
#include <ESP8266WiFi.h>  // for ESP8266
#include <BlynkSimpleEsp8266.h>  // for ESP8266

////  Pick one OTA Library or other
// #include <ESPmDNS.h>  // For OTA w/ ESP32
#include <ESP8266mDNS.h>  // For OTA w/ ESP8266

#include <WiFiUdp.h>  // For OTA
#include <ArduinoOTA.h>  // For OTA

char auth[] = "xxxxxxxxxx";
char ssid[] = "xxxxx";
char pass[] = "xxxxx";
//char server[] = "";  // IP for your Local Server
char server[] = "";  // URL for Blynk Cloud Server
int port = 8080;

BlynkTimer timer;

#include <Stepper.h>
const int stepsPerRevolution = 200;  // change this to fit the number of steps per revolution for your motor

// ESP8266 use GPIO pin designation, not silk-screened labeling
Stepper myStepper(stepsPerRevolution, 5, 4, 0, 2); // ESP8266 - initialize the stepper library for IN1, IN2, IN3, IN4

// ESP32 GPIO/Silk-screened pin designation
//Stepper myStepper(stepsPerRevolution, 15,2,0,4); // ESP32 - initialize the stepper library for IN1, IN2, IN3, IN4

int motorSpeed;
int motorDirection;

void setup() {

  timer.setInterval(10, stepperControl);  // This here is all the fancy timing part... it just updates the stepper control every 5ms

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

  ArduinoOTA.setHostname("ESP Blynk Stepper");  // For OTA - Use your own device identifying name
  ArduinoOTA.begin();  // For OTA

void loop() {;;
  ArduinoOTA.handle();  // For OTA

  Blynk.syncVirtual(V0, V1);

BLYNK_WRITE(V0) {  // Motor Speed - Slider set with 0-100 and Send On Relese OFF
  motorSpeed = param.asInt();

BLYNK_WRITE(V1) {  // Motor Direction - Button set as Switch with 0-1
  motorDirection = param.asInt();

void stepperControl() {
  if (motorSpeed > 0) {
    if (motorDirection == 0) {  // Rotate Clockwise
      myStepper.step(stepsPerRevolution / 100);
    } else {  // Rotate CounterClockwise
      myStepper.step(-stepsPerRevolution / 100);

Steppermotor control with blynk
[SOLVED] Connection lost at 50 seconds (controlling Stepper Motor)
Blank code insertion point
Tutorial: ESP32 -- Non-Blocking and Concurrent Function Execution

#24 - Timed Button Widget

Just cuz it keeps getting asked for :stuck_out_tongue_winking_eye: It is an improved & simplified version of my Latch & indicator example in my #12 - Timers Simplified post above.

Set your vPin, dPin and timeout accordingly… And exchange the digitalWrite() for whatever you want to happen for the timed duration

int latchButton;
int latchFlag;

//===== Timeed latching button =====
BLYNK_WRITE(vPin) {  // Button Widget set as switch
  latchButton = param.asInt();
  if (latchButton == 1 && latchFlag == 0) {
    latchFlag = 1;  // Keeps from allowing button press more then once while relay activated
    // ----- Start your timed thing here
    digitalWrite(dPin, HIGH); // Activate digital pin
    // -----
    timer.setTimeout(5000L, []() {  // Timed Lambda Function - Latching Button release after 5 seconds
      // ----- Stop your timed thing here
      digitalWrite(dPin, LOW); // Deactivate digital pin
      // -----
      Blynk.virtualWrite(vPin, 0);  // Reset Latching Button to OFF
      latchFlag = 0;  // resets to allow next interaction
    });  // END Timer Function
  } else {
    if (latchButton == 0 && latchFlag == 1) {  // If you try to tun off the button before time is up
      Blynk.virtualWrite(vPin, 1);  // Restore Latching Button ON until timer is finished

If you add in timer ID and some different } else { coding you can make the timer reset if you turn OFF the button before the timer is finished.

If you do nothing in the ON mode and only activate your “thing” once the timeout occurs, you can call this a delayed reaction button… a little more code and you can make it so you MUST hold the button for the timeout to occur

But for now I will leave all that experimenting to you :stuck_out_tongue_winking_eye:

ESP8266 Timed Button (Mimic a button press for a duration)
New Blynk Server Release
Code don't work on ESP8266 e01

#25 - Das Timed Blinkin’ LED… Without any delay() - AKA Timerception :sleeping::timer_clock:

This is simply just two nested Lambda functions using BlynkTimer and two different timer types to flash a Virtual LED ON for 1/2 second and Off for 1/2 second… If this is placed in the void setup() it just repeats in the background… marquee style.

LED Widget set to V0

  timer.setInterval(1000L, []() {  // 1st Timed Lambda Function - Turn ON LED every second (repeating)
    Blynk.virtualWrite(V0, 255);  // Turn Virtual LED ON
    timer.setTimeout(500L, []() {  // 2nd Timed Lambda Function - Turn OFF LED 1/2 second later (once per loop)
      Blynk.virtualWrite(V0, 0);  // Turn Virtual LED OFF
    });  // END 2nd Timer Function
  });  // END 1st Timer Function

So… why…?

Well I have heard that it is too complicated to make or understand the code to blink an LED without using delay() You be the judge :stuck_out_tongue_winking_eye:

Also, because it is a nice, non-blocking (payload depending), simple package of code that can be used to repeatedly do just about anything you want, as many times as you need (E.g. replace the first setInterval() timer with a setTimer() and designate your total loops to run. See - timer.setTimer()

Challenge - I am nesting only two functions here… How many nested lambda timed functions can you make use of? Either for practical or just visual purposes.

How to flashing 2 physical LED of mobile Robot
Tutorial: ESP32 -- Non-Blocking and Concurrent Function Execution
Blynk and Nextion
Help me to rotating this fan
Help for a noob please

#26 - Adjustable pulsing LED that fades in and out with Timers

And now for more Timerception tricks… A variable timed, flashing (pulsing) physical LED that fades in and out, all with nested timers in lambda functions.

One of the lambda tricks I had to discover, via trial and error, was using a “fixed call” interval timer called simply setTimer(long d, timer_callback f, int n) that will run its timed interval course as normal, but only n many times before stopping… the key was finding where to put the integer n in a Lambda.

Note the necessary preceding comma…

int timer.setTimer(long d, []() {
  // your code in lew of timer_callback f
}, int n);


timerId = timer.setTimer(1000L, []() {
// Repeat me every second but only five times
}, 5);

Another glitch in SimpleTimer (of which BlynkTimer is based) is that when using timer ID labels, needed to do things like disable, enable, delete, etc. timers, it seems like the first timer in your code will also get ‘deleted’… I found making a simple “Sacrificial Timer” solves that little issue :slight_smile:

In this example each chosen interval time, measured in quarter “seconds” (measured in binary units of 256, starting at 512 for shortest setting - all due to the math) will result in half that time fading up and the other half fading down. The longer the total duration, the slower the fade will appear.

Due to the fast pace of the active fade count and analogWrite() from 0-255-0, there will be timing constraints needed to mimic this with a virtual LED… Perhaps I will figure that out later :thinking:

  • Display Widget on V0 for uptime in seconds
  • Built in LED (GPIO2) on NodeMCU and Wemos will blink as a “sign of life” indicator.
  • Display Widget on V1 for current interval value
  • Button Widget V2 for changing the interval
  • Physical button bringing GPIO0 to GND will “sync” with virtual button… and thus you can control this without Server connection.
#define BLYNK_PRINT Serial
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

char auth[] = "xxxxxxxxxx";
char ssid[] = "xxxxxxxxxx";
char pass[] = "xxxxxxxxxx";
//char server[] = "";  // IP for Local Server
char server[] = "";  // IP for Cloud Server
int port = 8080;

int i;  // PWM count ID
int fadeUP;  // Timer ID
int fadeDOWN;  // Timer ID
int countUP;  // Timer ID
int countDOWN;  // Timer ID
int pulseTime = 256;  // Initial interval, not valid until incremented, else causes divide error
int btnState = HIGH; // Flag
int VbtnPin = LOW; // Flag
int buttonBlock = LOW; // Flag
const int btnPin = 0;  // Pin ID
const int ledPin = 14;  // Pin ID
const int builtinledPin = 2;  // Pin ID

BlynkTimer timer;

void setup() {
  Serial.begin(9600);  // BLYNK_PRINT data
  pinMode(btnPin, INPUT);
  pinMode(builtinledPin, OUTPUT);
  pinMode(ledPin, OUTPUT);

  WiFi.begin(ssid, pass);  // Connect to WiFi
  Blynk.config(auth, server, port);
  Blynk.connect();  // Initialise Connection to Server

  // "Sacrificial" Timer - needed when deleting timers as using that feature will also kill first timer created...
  timer.setTimeout(10L, []() {
    Blynk.virtualWrite(V0, "START");
  });  // END sacrificial Function

  // Timed Lambda Function - UpTime & Heartbeat...
  timer.setInterval(1000L, []() { // Run every second
    Blynk.virtualWrite(V0, millis() / 1000);  // Display the UpTime in seconds
    digitalWrite(builtinledPin, !digitalRead(builtinledPin));  // For "heartbeat" indicator on device
  });  // END UpTime Function

  // Timed Button watcher...
  timer.setInterval(100L, buttonScan);

Blynk.virtualWrite(V1, "OFF");  // display the pulse interval as OFF

void loop() {;;

void buttonScan() {  // Change interval time via Physical Button
  if (digitalRead(btnPin) == LOW || VbtnPin == HIGH && buttonBlock == LOW) {
    if (btnState != LOW) {  // btnState is used to avoid sequential toggles
      timer.deleteTimer(fadeUP);  // Stop Timer
      timer.deleteTimer(fadeDOWN);  // Stop Timer
      timer.deleteTimer(countUP);  // Stop Timer
      timer.deleteTimer(countDOWN);  // Stop Timer
      pulseTime += 256;  // Increment pulse interval
      if (pulseTime > 5120) {  // Loop the pulse interval time back to the beginning
        pulseTime = 256;
        Blynk.virtualWrite(V1, "OFF");  // display the pulse interval as OFF
        analogWrite(ledPin, 0);  // Turn off LED
      Blynk.virtualWrite(V1, pulseTime);  // display the pulse interval
      fadeLEDFunction();  // Start the pulsed fading
    btnState = LOW;
  } else {
    btnState = HIGH;

BLYNK_WRITE(V2) {  // Change interval time via Blynk button
  VbtnPin = param.asInt();  // Set the virtual button flag
  buttonScan();  // Run the actual button processing function.

void fadeLEDFunction() {
  firstPulse();  // Starts the initial pulse right away, while waiting for interval timer to start.
  delay(5);  // subtle delay to make sure initial pulse is finished before interval timer starts
  // Start fade up Lambda timer...
  fadeUP = timer.setInterval(pulseTime, []() {
    // Start count up Lambda counter...
    i = 11;  // Don't go totally dark
    countUP = timer.setTimer(pulseTime / 512, []() {
      i++;  // Count up
      analogWrite(ledPin, i);  // PWM to Fade LED
    }, 245); // END countUP Function
    // Start fade down Lambda timer...
    fadeDOWN = timer.setTimeout(pulseTime / 2, []() {
      // Start count down Lambda counter...
      i = 256;
      countDOWN = timer.setTimer(pulseTime / 512, []() {
        i--;  // Count down
        analogWrite(ledPin, i);  // PWM to fade LED
      }, 245); // END countDOWN Function
    });  // END fadeDOWN Function
  });  // END fadeUP Function

void firstPulse() {  // Starts the initial pulse
  buttonBlock = HIGH;  // Lockout flag for preventing further button press until done, else can cause timer duplication
  // Start first fade down Lambda timer...
  fadeDOWN = timer.setTimeout(pulseTime / 2, []() {
    // Start count down Lambda counter...
    i = 256;
    countDOWN = timer.setTimer(pulseTime / 512, []() {
      i--;  // Count down
      analogWrite(ledPin, i);  // PWM to fade LED
    }, 245); // END firstDOWN Function
  });  // END fadeDOWN Function
  // Start first fade up Lambda counter...
  i = 11;  // Don't go totally dark
  fadeUP = timer.setTimer(pulseTime / 512, []() {
    i++;  // Count up
    analogWrite(ledPin, i);  // PWM to fade LED
  }, 245); // END fadeUP Function
  buttonBlock = LOW;  // release lockout Flag