Blynk.connect() hangs forever

Hello friends. I’m just trying to get started on Blynk.io and not getting very far. I’m using an ESP32 dev board (TTGO T-Display). I already have code for connecting it to WiFi which is working perfectly. I prefer to leave this in place instead of having Blynk manage my WiFi connection. So I’m attempting to use blynk.connect() instead.

I’m working with the latest Blynk library and the Blynk server.

How do I get more verbose output to determine what’s breaking here? Bear in mind that I already have a working internet connection so this should work. I have verified the correct auth token and template ID are set. Here is an excerpt from my sketch showing the relevant bits.

#define BLYNK_TEMPLATE_ID            "TMPL7YmZ1ldk"
#define BLYNK_DEVICE_NAME           "TTGOTDisplay"
#define BLYNK_AUTH_TOKEN            "REDACTED"

void setup() {
  Blynk.config(BLYNK_AUTH_TOKEN);
  Blynk.connect();
  while (Blynk.connect() == false) {
    // Wait until connected
    Serial.println("Trying to connect...");
    delay(1000);
  }
  tft.println("Connected to Blynk server.");
}

This isn’t needed, but it’s difficult to comment further without seeing the rest of your sketch.

Adding #define BLYNK_PRINT Serial is a good start, but you obviously need to have a Seriall.begin command too, which isn’t included in your code snippet.

#define BLYNK_DEBUG will give more info, but you might struggle to understand it.

You can also turn on the debug level and debug port in the Arduino IDE.

Pete.

Thanks PeteKnight. Since you asked for it here’s the entire sketch. It was working perfectly until I added in Blynk. I’ve stripped out the Blynk auth token, wifi username and password for security. I do have serial print and debug enabled but neither have produced any clues that are useful for troubleshooting this.

#include <Arduino.h>
#include <TFT_eSPI.h>
#include <Button2.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <BlynkSimpleEsp32.h>
#include <WiFiUdp.h>
#include <NTPClient.h>
#include <driver/adc.h>
#include <TJpg_Decoder.h>
#include <FS.h>
#include "SPI.h"
#include "SPIFFS.h"
#include "esp_adc_cal.h"
#define FS_NO_GLOBALS
#define BLYNK_TEMPLATE_ID           "TMPL7YmZ1ldk"
#define BLYNK_DEVICE_NAME           "TTGOTDisplay"
#define BLYNK_AUTH_TOKEN            "REDACTED" 
#define BLYNK_PRINT Serial
#define BLYNK_DEBUG
#define BUTTON2_PIN 35
#define BUTTON1_PIN 0
Button2 button1;
Button2 button2;
// Define our tft and a single sprite
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite img = TFT_eSprite(&tft);
// define creates a mini function or alias
// need this for the wakeup function!
#define BUTTON_PIN_BITMASK 0x800000000 // 2^35 in hex
// Allows us to store data even during sleep
// https://savjee.be/videos/programming-esp32-with-arduino/using-rtc-memory/
RTC_DATA_ATTR int bootCount = 0;

// Text string for display of data
char text[] = "Hello World";

const char *SSID = "MYSSIDHERE";
const char *PASSWORD = "secretpassword";

// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);

// Variable for formatted time
String formattedTime;

unsigned long time_now = millis();

// Blynk timer
BlynkTimer timer;

// Function for use with TJpgDec.setCallback(img_output)
bool img_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
  if ( y >= img.height() ) return 0;
  img.pushImage(x, y, w, h, bitmap);
  return 1;
}

void print_wakeup_reason(){
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch(wakeup_reason)
  {
    case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

void b1handler(Button2& btn) {
    switch (btn.getType()) {
        case single_click:
            Serial.println("b1 single");
            strcpy(text,"b1 single");
            img.drawString(text,20,20,4);
            img.pushSprite(0,0);
            time_now = millis();
            break;
        case double_click:
            Serial.println("b1 double");
            strcpy(text,"b1 double");
            img.drawString(text,20,20,4);
            img.pushSprite(0,0);
            time_now = millis();
            break;
        case triple_click:
            Serial.println("b1 triple");
            strcpy(text,"b1 triple");
            img.drawString(text,20,20,4);
            img.pushSprite(0,0);
            time_now = millis();
            break;
        case long_click:
            Serial.println("b1 long");
            strcpy(text,"b1 long");
            img.drawString(text,20,20,4);
            img.pushSprite(0,0);
            time_now = millis();
            //Serial.println("long press complete. Sleeping.");
            //esp_deep_sleep_start();
            break;
    }
    Serial.print("click");
    Serial.print(" (");
    Serial.print(btn.getNumberOfClicks());    
    Serial.println(")");
}

void b2handler(Button2& btn) {
    switch (btn.getType()) {
        case single_click:
            Serial.println("b2 single");
            strcpy(text,"b2 single");
            img.drawString(text,20,20,4);
            img.pushSprite(0,0);
            time_now = millis();
            break;
        case double_click:
            Serial.println("b2 double");
            strcpy(text,"b2 double");
            img.drawString(text,20,20,4);
            img.pushSprite(0,0);
            time_now = millis();
            break;
        case triple_click:
            Serial.println("b2 triple");
            strcpy(text,"b2 triple");
            img.drawString(text,20,20,4);
            img.pushSprite(0,0);
            time_now = millis();
            break;
        case long_click:
            Serial.println("b2 long");
            strcpy(text,"b2 long");
            img.drawString(text,20,20,4);
            img.pushSprite(0,0);
            Serial.println("long press complete. Sleeping.");
            esp_deep_sleep_start();
            time_now = millis();
            break;
    }
    Serial.print("click");
    Serial.print(" (");
    Serial.print(btn.getNumberOfClicks());    
    Serial.println(")");
}

void displayInit(){
  tft.begin();
  tft.setRotation(1);
  tft.setTextColor(TFT_DARKGREEN,TFT_BLACK); 
  tft.setSwapBytes(true);
  tft.fillScreen(TFT_BLACK);
  tft.setTextFont(2);
}

void gradientTest(){
  img.fillRectHGradient(0, 0, 240, 135, TFT_YELLOW, TFT_BLUE);
  img.pushSprite(0,0);
  delay(1000);
  img.fillRect(0,0,240,135,TFT_BLACK);
}

void batteryMonitorSetup(){
  esp_adc_cal_characteristics_t adc_chars;
  esp_adc_cal_value_t val_type = esp_adc_cal_characterize((adc_unit_t)ADC_UNIT_1, (adc_atten_t)ADC_ATTEN_DB_2_5, (adc_bits_width_t)ADC_WIDTH_BIT_12, 1100, &adc_chars);
  pinMode(14, OUTPUT);
}

void blynkTimerEvent()
{
  digitalWrite(14, HIGH);
  delay(1);
  float measurement = (float) analogRead(34);
  float battery_voltage = (measurement / 4095.0) * 7.26;
  digitalWrite(14, LOW);
  Serial.println(battery_voltage);
  Blynk.virtualWrite(battery_voltage, millis() / 1000);
}

void setup() {
  // Fire up the serial port
  Serial.begin(115200);
  while (!Serial) {
    delay(20);
  }

  // Initialise SPIFFS to enable access to files in /data
  if (!SPIFFS.begin()) {
    Serial.println("SPIFFS initialization failed!");
    while (1) yield();
  }
  Serial.println("\r\nSPIFFS initialization done.");

  // ESP32 will crash if any of the fonts are missing
  bool font_missing = false;
  if (SPIFFS.exists("/weathericons40.vlw")    == false) font_missing = true;

  if (font_missing)
  {
    Serial.println("\r\nFont missing in SPIFFS, did you upload it?");
    while(1) yield();
  }
  else Serial.println("\r\nFonts found OK.");

  batteryMonitorSetup();

  // Initialize our TFT display
  displayInit();
  tft.print("Connecting to ");
  tft.println(SSID);
  WiFi.begin(SSID, PASSWORD);
  while (WiFi.status() != WL_CONNECTED) {
    delay(300);
    tft.print(".");
  }
  tft.println("");
  tft.println("WiFi connected.");
  tft.println("IP address: ");
  tft.println(WiFi.localIP());
  timeClient.begin(); 
  timeClient.setTimeOffset(-18000);
  timeClient.update();
  timer.setInterval(1000L, blynkTimerEvent);
  formattedTime = timeClient.getFormattedTime();
  tft.print("The time is: ");
  tft.println(formattedTime);
  tft.println("Connecting to Blynk...");
  Blynk.config(BLYNK_AUTH_TOKEN);
  Blynk.connect();
  while (Blynk.connect() == false) {
    // Wait until connected
    Serial.println("Trying to connect...");
    delay(1000);
  }
  tft.println("Connected to Blynk server.");
  delay(3000);
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));
  print_wakeup_reason();
  // Right button on T-Display is GPIO_NUM_35
  // pinMode(GPIO_NUM_35, INPUT);
  //esp_sleep_enable_ext0_wakeup(GPIO_NUM_35,0); //1 = High, 0 = Low
  esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK,ESP_EXT1_WAKEUP_ALL_LOW);
  button1.begin(BUTTON1_PIN);
  button1.setClickHandler(b1handler);
  button1.setLongClickHandler(b1handler);
  button1.setDoubleClickHandler(b1handler);
  button1.setTripleClickHandler(b1handler);
  button2.begin(BUTTON2_PIN);
  button2.setClickHandler(b2handler);
  button2.setLongClickHandler(b2handler);
  button2.setDoubleClickHandler(b2handler);
  button2.setTripleClickHandler(b2handler);
  TJpgDec.setJpgScale(1);
  TJpgDec.setCallback(img_output);
  img.createSprite(240,135);
  //gradientTest();
  img.setTextColor(TFT_DARKGREEN, TFT_BLACK);
  img.setTextPadding(160);
  img.drawString(text,20,20,4);
  img.loadFont("weathericons40");
  img.setCursor(180,0);
  img.setTextColor(TFT_BLUE, TFT_BLACK);
  img.print("");
  img.unloadFont();
  img.setTextColor(TFT_DARKGREEN, TFT_BLACK);
  //TJpgDec.drawFsJpg(170, 0, "/battery_01.jpg");
  img.pushSprite(0,0);
  //delay(1000);
}

void loop() {
  if ( (millis() - time_now) > 60000) {
    // Serial.println("Time has passed.");
    // esp_deep_sleep_start();
    ;
  }
  button1.loop();
  button2.loop();
  img.drawString(timeClient.getFormattedTime(),5,70,7);
  img.pushSprite(0,0);
  Blynk.run();
  timer.run();
  //Serial.println(blevel);
}

If it’s helpful, I am using version 1.1.0 of the library. From my platformio.ini:

	blynkkk/Blynk@^1.1.0

And here’s what I see in the serial output. You can see that I’ve already succesfully connected to the network.

[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 0 - WIFI_READY
[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 2 - STA_START
[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 4 - STA_CONNECTED
[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 7 - STA_GOT_IP
[D][WiFiGeneric.cpp:385] _eventCallback(): STA IP: 192.168.86.39, MASK: 255.255.255.0, GW: 192.168.86.1
Trying to connect...
Trying to connect...
Trying to connect...

These have to be the first lines of your sketch.

Pete.

Tried moving these three lines to the top of my sketch, same results. My loop just tries over and over to connect.

How do you folks get error messages or troubleshoot these situations? I’m seeing zero output from the Blynk.connect() line which is presumably failing for some reason.

Ok I finally managed to get some Serial output. The fix was to also move these lines to the top of the sketch. Blynk team, please document this better. I’m sure I’m not the only newb who has tripped on this banana peel.

#define BLYNK_PRINT Serial
#define BLYNK_DEBUG

Now I have identified the real problem, the auth token is invalid. I copied this verbatim right from the Device page on Blynk. Why would the Auth token be invalid?

Trying to connect...
[96271] Connecting to blynk-cloud.com:8080
[96323] <[1D|00|01|00] XXXXXXXX
[96372] >[00|00|01|00|09]
[96372] Invalid auth token

I finally got a connection but I had to hard code the auth token into the Blynk.connect() command.

This works:

Blynk.connect("asCFUcZB1BPxXXXXXXrtFsFcybcLwtU4");

but this does not:

Blynk.connect(BLYNK_AUTH_TOKEN);

And now it is working with BLYNK_AUTH_TOKEN. I have no idea why it started working but wasn’t before, maybe a hidden character in the auth token… :shrug:

No, the real problem is that you were trying to connect to the legacy server…

And your Blynk IoT token isn’t recognised by that server.

Putting the template name etc at the top of the sketch tells the compiler to use the Blynk IoT server (blynk.cloud) rather than the legacy server (this is documented in the area where you copy these credentials from the web console).

Pete.

Thanks, Pete. I didn’t realize there was a legacy server. Kind of a kludgy way to redirect the query but it works now! Thanks for all your help.

It’s done that way to facilitate backwards comparability with the legacy system.

Pete.

Yea, I sort of figured it was something like that. I’d last played with Blynk a few years ago and am just now coming back to it. Hopefully v2 solves whatever was missing in the legacy app…