BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

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


#37

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


#38

#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 =====
BLYNK_WRITE(V0) {
  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…

image

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

image

image

image

To give this output…

image


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
  }
}

image


New Android Release 2.22.0
New iOS Release 2.22.0
#39

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


#42

#43

#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
The truth is out there! (Servo control)
[SOLVED] Reset interval SimpleTimer
#45

#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[] = "xxx.xxx.xxx.xxx";  // 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);
  Blynk.connect();

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



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



BLYNK_CONNECTED() {
  Blynk.syncVirtual(V0);
  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
#46

#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
#47

#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[] = "xxx.xxx.xxx.xxx";  // IP for your Local Server
char server[] = "blynk-cloud.com";  // 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() {
  Serial.begin(9600);

  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);
  Blynk.connect();

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


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



BLYNK_CONNECTED() {
  Blynk.syncVirtual(V0, V1);
}

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

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);
    }
  }
}


Blank code insertion point
Tutorial: ESP32 -- Non-Blocking and Concurrent Function Execution
#48

#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:


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

#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.


Tutorial: ESP32 -- Non-Blocking and Concurrent Function Execution