BLE Heartbeat Timeout (when using keypad)

Hi everyone,

I am using an Adafruit Feather 32u4 Bluefruit LE board and experience problems when I add a keypad.
I am getting Heartbeat Timeouts, but everything works without the keypad code.

The keypad code without Blynk works too.

I am using Blynk library 4.8 and the keypad library from here: https://github.com/Chris–A/Keypad

My code:

#define BLYNK_USE_DIRECT_CONNECT

#define BLYNK_PRINT Serial

#include <BlynkSimpleSerialBLE.h>
#include <Adafruit_BLE.h>
#include <Adafruit_BluefruitLE_SPI.h>
#include <SPI.h>
#include <Wire.h>
#include <SPI.h>

#include <Key.h>
#include <Keypad.h>

 
// State Variables:   Initialize to the locked state
int position = 0;
char key = "";

// Define your password key sequence here
char* secretCode = "1234";
 
// Keypad key matrix:
const byte rows = 4; 
const byte cols = 3; 
char keys[rows][cols] = 
{
   {'1','2','3'},
   {'4','5','6'},
   {'7','8','9'},
   {'*','0','#'}
};

// More pin definitions:
int LedPin = 13;

 
// Keypad pin definitions
byte rowPins[rows] = {15, A5, A4, A3}; //connect to the row pinouts of the keypad
byte colPins[cols] = {A2, A1, A0}; //connect to the column pinouts of the keypad

 
// Instantiate the keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);

//Adafruit_LIS3DH lis = Adafruit_LIS3DH();

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "my token";

// SHARED SPI SETTINGS (see adafruit webpages for details)
#define BLUEFRUIT_SPI_CS               8
#define BLUEFRUIT_SPI_IRQ              7
#define BLUEFRUIT_SPI_RST              4    // Optional but recommended, set to -1 if unused
#define BLUEFRUIT_VERBOSE_MODE         true

// Create ble instance, see pinouts above
Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);

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

    ble.begin(BLUEFRUIT_VERBOSE_MODE);
    ble.factoryReset(); // Optional
    ble.setMode(BLUEFRUIT_MODE_DATA);
    //all the Blynk magic happens here
    Blynk.begin(auth, ble);

  pinMode(LedPin, OUTPUT);
}

void loop()
{
  Blynk.run();
  key = keypad.getKey(); //Without this and the following three lines everything works
  if (key){
    Serial.println(key);
  }
}

BLYNK_WRITE(V0)
{   
  int value = param.asInt(); // Get value as integer
  Serial.println(value);
}

I would be very grateful if you could help me to find the bug! :slight_smile:

Probably because that is a blocking routine… no key press = no further processing = HB timeout. Blocking & delays are bad for Blynk.

Use a timer routine to scan for key presses… assuming there is a non-blocking command to do so in that library… you will need to check.

http://help.blynk.cc/getting-started-library-auth-token-code-examples/blynk-basics/how-to-display-any-sensor-data-in-blynk-app

Thank you very much for your replay and the hint about blocking code @Gunner
I have tested my code without Blynk and added a Serial.println(“test”); at the end to check that. And it is not blocking my loop. Also the Arduino Homepage http://playground.arduino.cc/Code/Keypad says the code is not blocking:

char getKey()

Returns the key that is pressed, if any. This function is non-blocking.

So this is really curious :thinking:

Are there any other ideas?

Yes… on the opposite end of the scale… instead of blocking (i.e. no processing causing timeout), there is flooding (too much data flow causes timeout).

As that getKey() command structure is directly embedded in the void loop() and thus running hundreds of times a second… a single key press may be pushing too much data and causing errors… although you would probably see at least a few printouts??

Anything with Blynk should follow certain coding practices, such as keeping the void loop() clear and using timers. So I recommend you put your key scan routine into a timer. Then add in another timer, perhaps with a seconds count, so you can see confirmation of data flow between Device/Server/App while testing the keypad.

Much easier to troubleshoot when you have a few observable interactions to compare with.

Please check out the link provided above (and other in that section) for more information and examples.

Thank you very much for your help so far @Gunner
I have now put the following part into a blynk timer that runs every second:

key = keypad.getKey();
  if (key){
    Serial.println(key);
  }

the result is that I am also getting a

[20555] Heartbeat timeout
[20555] Connecting...

without pressing any key on the keypad like before.
If I press a key I can see it in the serial monitor when I hit the 1s window. but there is no connection to the blynk app because of the heartbeat timeout.
I am really clueless because now there is no blocking and no flooding

There is something causing the timeout… but may not be Blynk related… library conflict perhaps?

Enable Debug and repost current code along with Debug data.

http://docs.blynk.cc/#blynk-firmware-debugging

Looks like the keypad library blocks while waiting for a keypress…

2 Likes

I thought so… I didn’t see how else it would know a key was pressed. Never thought about digging into the library on this one… must be slipping into senility at the thought of my fast approaching mid-century checkpoint :stuck_out_tongue:

1 Like

Hi @Jamin,

the waitForKey() is blocking code but I am not using this.
getKey() is not blocking but I have no idea how it works.

thank you @Gunner Maybe there is some kind of library conflict :frowning:

I have enabled debug and this is my output in the serial console:

AT+FACTORYRESET

<- OK
[22018] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v0.4.10 on Arduino

[22022] Free RAM: 1402
[22024] Connecting...
[28022] Connecting...
[34023] Connecting...
[40024] Connecting...
[46024] Connecting...
[52025] Connecting...
[58025] Connecting...
[64026] Connecting...
[70027] Connecting...
[76027] Connecting...
[82028] Connecting...
[88029] Connecting...
[91766] >[02|00|01|00] 
[91795] >91371ed17bf443d2a002ed4790a59ce0
[91797] Ready
[91799] <[00|00|01|00|C8]
[101799] <[06|00|01|00|00]
[103843] <[06|00|02|00|00]
[105883] <[06|00|03|00|00]
[107925] Heartbeat timeout: 107925, 91797, 105883
[107927] Connecting...

Does this help?

My code:

#define BLYNK_USE_DIRECT_CONNECT

#define BLYNK_DEBUG // Optional, this enables lots of prints
#define BLYNK_PRINT Serial

#include <BlynkSimpleSerialBLE.h>
#include <Adafruit_BLE.h>
#include <Adafruit_BluefruitLE_SPI.h>
#include <SPI.h>
#include <Wire.h>
#include <SPI.h>

#include <Key.h>
#include <Keypad.h>

 
// State Variables:   Initialize to the locked state
int position = 0;
char key = "";

// Define your password key sequence here
char* secretCode = "1234";
 
// Keypad key matrix:
const byte rows = 4; 
const byte cols = 3; 
char keys[rows][cols] = 
{
   {'1','2','3'},
   {'4','5','6'},
   {'7','8','9'},
   {'*','0','#'}
};

// More pin definitions:
int LedPin = 13;

 
// Keypad pin definitions
byte rowPins[rows] = {15, A5, A4, A3}; //connect to the row pinouts of the keypad
byte colPins[cols] = {A2, A1, A0}; //connect to the column pinouts of the keypad

// Instantiate the keypad
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "91371ed17bf443d2a002ed4790a59ce0";

// SHARED SPI SETTINGS (see adafruit webpages for details)
#define BLUEFRUIT_SPI_CS               8
#define BLUEFRUIT_SPI_IRQ              7
#define BLUEFRUIT_SPI_RST              4    // Optional but recommended, set to -1 if unused
#define BLUEFRUIT_VERBOSE_MODE         true

// Create ble instance, see pinouts above
Adafruit_BluefruitLE_SPI ble(BLUEFRUIT_SPI_CS, BLUEFRUIT_SPI_IRQ, BLUEFRUIT_SPI_RST);

BlynkTimer timer;

// This function sends Arduino's up time every second to Virtual Pin (5).
// In the app, Widget's reading frequency should be set to PUSH. This means
// that you define how often to send data to Blynk App.
void myTimerEvent()
{
  key = keypad.getKey(); //Without this and the following three lines everything works
  if (key){
    Serial.println(key);
  }
}

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

    ble.begin(BLUEFRUIT_VERBOSE_MODE);
    ble.factoryReset(); // Optional
    ble.setMode(BLUEFRUIT_MODE_DATA);
    //all the Blynk magic happens here
    Blynk.begin(auth, ble);

    // Setup a function to be called every second
    timer.setInterval(10000L, myTimerEvent);

    pinMode(LedPin, OUTPUT);
}

void loop()
{
  Blynk.run();
  timer.run(); // Initiates BlynkTimer
}

BLYNK_WRITE(V0)
{   
  int value = param.asInt(); // Get value as integer
  Serial.println(value);
}

The BLYNK_WRITE(V0) is connected to button in the blynk app.

This might be an issue with BLE ? @vshymanskyy @Dmitriy ?

@hl68fx, do you have a a wifi device you can test it with? Such as an ESP8266

I have a Particle Photon, so I will check this in the next few days and report back :slight_smile:

1 Like