Published on

Blynk First Impressions

This is the notes describing the process of getting a basic dashboard interface controlling a blinking LED and displaying IMU data using the Blynk cloud ecosystem, app, and an ESP32.

Preparation and Installation

The Blynk onboarding flow after account creation was well designed and worked perfectly for me. I won't repeat that, read the official quickstart docs are here.

quickstart-flow

Blynk Console

I'll create a new template first. Templates are used to describe the hardware configuration and cloud connected variables for a particular hardware device - each project would specify a different template, allowing identical hardware devices to use a common template.

template-create

I then added some datastream entries for the accelerometer readings and blink duration control signal.

Blynk's data sharing teminology is based around the idea of 'Pins', and has native digital and analog pin definitions which map to physical IO pins on the hardware. For any other data, a 'Virtual Pin' is used.

datastream-create-type

'Pins are numerically indexed, appearing to support up to 255 virtual pins. A human friendly name can be assigned, along with the type of data and min/max/default values.

I do find it odd that virtual pins can only be typed as string, integer or double, and from what I can understand, are all encoded and transported as strings behind the scenes.

datastream-virtual-pin-configure

The unit selection looked promising, with a mix of weights, distances, temperatures, but unfortunately doesn't have acceleration or velocity types suitable for the IMU data, so I left the units setting blank.

Millisecond units were available for blink_ms though.

datastream-entries

It's now time to get the hardware connected and sending data to Blynk.

Hardware

To get the relevant device key and template config variables to use on hardware, I created a new device and chose the template with configured datastream settings from earlier.

device-add-method

Device creation hints at the larger scale design reasoning for separation of templates/datastream configuration from specific devices - products, community projects or educational kits could quickly provide templates via QR code.

device-choose-esp32

We now have the device configured and are issued the template ID and authorisation token that is needed for the Arduino sketch.

device-keys

It's a good time to mention that installing the Blynk library was easy with the Arduino Library Manager.

arduino-library-manager

After adding some IMU handling code and configuring a timer to sample and send accelerometer data, my Arduino sketch looks like this:

/* Fill-in information from Blynk Device Info here */
#define BLYNK_TEMPLATE_ID "abc123"
#define BLYNK_TEMPLATE_NAME "IMU Test"
#define BLYNK_AUTH_TOKEN "abc321"

#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>

#include "SparkFunLSM6DSO.h"
#include "Wire.h"

LSM6DSO myIMU; //Default constructor is I2C, addr 0x6B

bool led_on = false;
uint32_t led_timer  = 0;
uint32_t blink_interval_ms = 0;

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "WifiSSID";
char pass[] = "WifiPassword";

BlynkTimer imu_publish;

// Called when Virtual Pin 0 is changed by the app/web dashboard
BLYNK_WRITE(V0)
{
  blink_interval_ms = param.asInt();

  // Update state
  Blynk.virtualWrite(V0, blink_interval_ms);
}

// This function is called every time the device is connected to the Blynk.Cloud
BLYNK_CONNECTED()
{

}

// Called at 2Hz
void publish_imu_values()
{
  Blynk.virtualWrite(V2, myIMU.readFloatAccelX());
  Blynk.virtualWrite(V3, myIMU.readFloatAccelY());
  Blynk.virtualWrite(V4, myIMU.readFloatAccelZ());
}

void setup()
{
  Serial.begin(115200);

  Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);

  pinMode( LED_BUILTIN, OUTPUT );
  led_timer = millis();
  
  Wire.begin();
  myIMU.begin();
  myIMU.initialize(BASIC_SETTINGS);

  imu_publish.setInterval(500, publish_imu_values);
}

void loop()
{
  Blynk.run();
  imu_publish.run();
   
  if( millis() - led_timer >= blink_interval_ms )
  {
    led_on = !led_on;
    led_timer = millis();
    digitalWrite( LED_BUILTIN, led_on );
  }   
}

Building a dashboard

With hardware setup and publishing data to Blynk, we're ready to configure a web dashboard and a mobile app layout.

Blynk doesn't allow layout re-use between web and mobile, so I'll treat them as individual dashboards.

Web

The web builder provides a grid for UI components called 'widgets', and uses a drag and drop approach for layout with a grid for alignment and resize snapping.

editor-layout-blank

Adding a slider for the blink_ms functionality was easy, and it automatically added a "ms" suffix behind the value.

The configurable title, layout and handle color are nice to see compared to other web-dashboard builder products.

editor-slider-settings

Adding the value text and chart were similar, and I've now achieved the basic test requirements.

The chart is limited to one signal for the free plan.

dashboard-working

It looks professional and stylish by default.

The chart updates every second when the dashboard is set to "Latest", even though the ESP32 is publishing at twice that rate. For the longer timespans like "Last Hour", the charted data is decimated to one-minute resolution.

Mobile

After downloading and logging in, I could see the device I setup waiting. Once again, the onboarding experience looks good and explains everything well.

app-onboarding

Changing to 'developer mode' allows for a similar drag-and-drop layout experience. Just like the web builder, a lot of the widgets require a paid tier plan.

I was impressed with the wider range of widgets available, but the list is also cluttered with horizontal and vertical versions of the same widgets instead of using a styling toggle.

app-locked-widgets

The configuration for the Slider component worked well, selecting the datastream and allowing for visual customisation.

Slider behaviour settings
Style customisations

With the rest of the components dragged in, resized and configured, I can see how the mobile app handles presenting the UI for the basic test.

Developer mode dashboard layout
User mode dashboard with streaming data

This looks good, responds well to touch input, and behaves as expected when switching apps or closing the app.

The iPad app however, only runs in iPhone compatibility mode. Logging in on the iPad did allow for immediate use of the dashboard configured on the phone, so that's nice at least...

app-ipad

Summary

In general, the quality of documentation, onboarding flows and hardware setup was very good. The web and mobile interfaces look modern and feel performant, and everything worked as expected.

The mobile app has a larger set of widgets available for control and data visualisation. Some widgets which required a paid plan for use on the web are freely available on the mobile app. On the topic of the mobile app, seeing the iOS app run in phone compatibility mode was surprising given the otherwise high level of polish and attention to detail.

I'll also point out that editing interfaces on a phone is more tedious than the web interface, and feels like a missed win for improved usability.

The Blynk documentation suggests restricting hardware variable publish rate to not exceed 10 values per second. This is reasonable from the perspective of a cloud service, but shifts responsibility to catch important events to the firmware, rather than sending a wider stream for decimation at the database level.

I measured the time taken for Blynk to publish a single static double precision value at 1.9 milliseconds. The micro blocks during this time, so you might need to be careful when you publish values.