BLYNK_WRITE() in for loop?

I’m using NodeMCU ESP8266 with Blynk v0.6.1 library; please help me to refactor my code.
I just need to know:

  1. Is there a way to define virtual pin array instead of multiple variables?
  2. Can we make BLYNK_WRITE(Vx) in for loop?
#define VPIN_BTN_0  V0
#define VPIN_BTN_1  V1
#define VPIN_BTN_2  V2

BLYNK_WRITE(VPIN_BTN_0) {
  relayState[0] = param.asInt();
  shiftWrite(0, relayState[0]);
}

BLYNK_WRITE(VPIN_BTN_1) {
  relayState[1] = param.asInt();
  shiftWrite(1, relayState[1]);
}

BLYNK_WRITE(VPIN_BTN_2) {
  relayState[2] = param.asInt();
  shiftWrite(2, relayState[2]);
}

Can you explain more about what you’re trying to achieve?

Pete.

Something like that ?

int Sync[] = {1, 3, 6, 7, 8, 15, 16, 17, 19, 23, 27, 28, 45, 46];

void setup(){
 const int vSync = ( sizeof Sync ) / ( sizeof Sync[0] );
 
  while (Vcount < vSync + 1) { 
    Vcount++;
    Blynk.syncVirtual(Sync[Vcount]);  // Generate a vPin sync for each count
     }

Basically I’m using SN74HC595 shift resistor for extending GPIOs of my ESP8266. The shiftWrite(1, relayState[1]); function is for addressing SN74HC595 pins. I’ve 6 relay with 6 physical buttons and I’m doing BLYNK_WRITE(VPIN_BTN) on every physical button, therefore my code is getting so lengthy and repetitive. So I want to know if there is a way to reduce my code.

Yeah, I think just like that example you’ve shared… I’ve defined my int relayState[] = { 1, 1, 1, 1, 1, 1 }; in array but how can I define a virtual pins array so I can use that array with index in BLYNK_WRITE(VPIN_BTN[i]) and group that 6 BLYNK_WRITE() handler into a for loop?

There was also repeated code in my void setup() function, but check code below; how I reduced it with for loop, this is what I need.

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

  // Set the three SPI pins to be outputs
  pinMode(DATA_PIN, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);

  for (int i = 0; i <= 5; i++) {
    // Turn off all relays
    shiftWrite(i, HIGH);
    // Restore previous states of relays
    pinMode(BTN_PIN[i], INPUT_PULLUP);
    shiftWrite(i, relayState[i]);
  }
}

I really don’t understand that statement at all. Do you mean on every widget button?

If you’re trying to reduce the code then you could look at BLYNK_WRITE_DEFAULT() :

https://docs.blynk.cc/#blynk-firmware-blynktimer-blynk_write_default

I’ve never used it, but it appears that it would allow to to parameterise the virtual pin that triggered the callback.

Pete.

Yes.

Have a look at my messy code :no_mouth:

#define BLYNK_PRINT Serial
#include "settings.h"
#include "wifimanagment.h"
#include "shiftwrite.h"
#include <BlynkSimpleEsp8266.h>

BlynkTimer timer;

/* SN74HC595 Connections */
/* Controls the internal transference of data in SN74HC595 internal registers */
const int LATCH_PIN = 16; // D0 - Connected to ST_CP
/* Generates the clock signal to control the transference of data */
const int CLOCK_PIN = 5;  // D1 - Connected to SH_CP
/* Outputs the byte to transfer */
const int DATA_PIN = 4;   // D2 - Connected to DS


/* NodeMCU to Push Button switch */
// D3, D4, D5, D6, D7, RX
int BTN_PIN[] = {0, 2, 14, 12, 13, 3};

/* Blynk Virtual Pin Assignment */
#define VPIN_BTN_0  V0
#define VPIN_BTN_1  V1
#define VPIN_BTN_2  V2
#define VPIN_BTN_3  V3
#define VPIN_BTN_4  V4
#define VPIN_BTN_5  V5

void checkPhysicalButton();

int relayState[] = { 1, 1, 1, 1, 1, 1 };
int btnState[] = { 1, 1, 1, 1, 1, 1 };

// Every time we connect to the cloud...
BLYNK_CONNECTED() {
  // Request the latest state from the server
  //for (int i = 0; i <= 5; i++) {
  //  Blynk.syncVirtual(VPIN_BTN[i]);
  //}
  Blynk.syncVirtual(VPIN_BTN_0, VPIN_BTN_1, VPIN_BTN_2, VPIN_BTN_3, VPIN_BTN_4, VPIN_BTN_5);
}

// When App button is pushed - switch the state
BLYNK_WRITE(VPIN_BTN_0) {
  relayState[0] = param.asInt();
  shiftWrite(0, relayState[0]);
}

BLYNK_WRITE(VPIN_BTN_1) {
  relayState[1] = param.asInt();
  shiftWrite(1, relayState[1]);
}

BLYNK_WRITE(VPIN_BTN_2) {
  relayState[2] = param.asInt();
  shiftWrite(2, relayState[2]);
}

BLYNK_WRITE(VPIN_BTN_3) {
  relayState[3] = param.asInt();
  shiftWrite(3, relayState[3]);
}

BLYNK_WRITE(VPIN_BTN_4) {
  relayState[4] = param.asInt();
  shiftWrite(4, relayState[4]);
}

BLYNK_WRITE(VPIN_BTN_5) {
  relayState[5] = param.asInt();
  shiftWrite(5, relayState[5]);
}

void checkPhysicalButton() {
  if (digitalRead(BTN_PIN[0]) == 0) {
    // btnState[] is used to avoid sequential toggles
    if (btnState[0] != 0) {

      // Toggle RELAY state
      relayState[0] = !relayState[0];
      shiftWrite(0, relayState[0]);

      // Update Button Widget
      Blynk.virtualWrite(VPIN_BTN_0, relayState[0]);
    }
    btnState[0] = 0;
  } else {
    btnState[0] = 1;
  }

  if (digitalRead(BTN_PIN[1]) == 0) {
    // btnState[] is used to avoid sequential toggles
    if (btnState[1] != 1) {

      // Toggle RELAY state
      relayState[1] = !relayState[1];
      shiftWrite(1, relayState[1]);

      // Update Button Widget
      Blynk.virtualWrite(VPIN_BTN_1, relayState[1]);
    }
    btnState[1] = 0;
  } else {
    btnState[1] = 1;
  }

  if (digitalRead(BTN_PIN[2]) == 0) {
    // btnState[] is used to avoid sequential toggles
    if (btnState[2] != 0) {

      // Toggle RELAY state
      relayState[2] = !relayState[2];
      shiftWrite(2, relayState[2]);

      // Update Button Widget
      Blynk.virtualWrite(VPIN_BTN_2, relayState[2]);
    }
    btnState[2] = 0;
  } else {
    btnState[2] = 1;
  }

  if (digitalRead(BTN_PIN[3]) == 0) {
    // btnState[] is used to avoid sequential toggles
    if (btnState[3] != 0) {

      // Toggle RELAY state
      relayState[3] = !relayState[3];
      shiftWrite(3, relayState[3]);

      // Update Button Widget
      Blynk.virtualWrite(VPIN_BTN_3, relayState[3]);
    }
    btnState[3] = 0;
  } else {
    btnState[3] = 1;
  }

  if (digitalRead(BTN_PIN[4]) == 0) {
    // btnState[] is used to avoid sequential toggles
    if (btnState[4] != 0) {

      // Toggle RELAY state
      relayState[4] = !relayState[4];
      shiftWrite(4, relayState[4]);

      // Update Button Widget
      Blynk.virtualWrite(VPIN_BTN_4, relayState[4]);
    }
    btnState[4] = 0;
  } else {
    btnState[4] = 1;
  }

  if (digitalRead(BTN_PIN[5]) == 0) {
    // btnState[] is used to avoid sequential toggles  
    if (btnState[5] != 0) {

      // Toggle RELAY state
      relayState[5] = !relayState[5];
      shiftWrite(5, relayState[5]);

      // Update Button Widget
      Blynk.virtualWrite(VPIN_BTN_5, relayState[5]);
    }
    btnState[5] = 0;
  } else {
    btnState[5] = 1;
  }
}

void setup() {
  EEPROM.begin(memalloc);
  Serial.begin(115200);
  delay(100);

  // Set the three SPI pins to be outputs
  pinMode(DATA_PIN, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);

  for (int i = 0; i <= 5; i++) {
    // Turn off all RELAYS
    shiftWrite(i, HIGH);
    // Restore previous RELAYS states
    pinMode(BTN_PIN[i], INPUT_PULLUP);
    shiftWrite(i, relayState[i]);
  }

  // Setup a function to be called every 100 ms
  timer.setInterval(100L, checkPhysicalButton);

  if(connectWifi()){
    Blynk.begin(auth, ssid, password);
  } else {
    startAP();
    Blynk.begin(auth, ssid, password);
  }
}

void loop() {
  if(WiFi.status() == WL_CONNECTED){
    Blynk.run();
    timer.run();
  } else{
    startAP();
  }
}

Okay, looks like the BLYNK_WRITE_DEFAULT() callback would tidy-up that part of your code, and a ‘for’ loop on your physical switch polling would help a lot.

Pete.

1 Like

Thanks you @PeteKnight for enlighten my day, now…
My previous code:

// When App button is pushed - switch the state
BLYNK_WRITE(VPIN_BTN_0) {
  relayState[0] = param.asInt();
  shiftWrite(0, relayState[0]);
}

BLYNK_WRITE(VPIN_BTN_1) {
  relayState[1] = param.asInt();
  shiftWrite(1, relayState[1]);
}

BLYNK_WRITE(VPIN_BTN_2) {
  relayState[2] = param.asInt();
  shiftWrite(2, relayState[2]);
}

BLYNK_WRITE(VPIN_BTN_3) {
  relayState[3] = param.asInt();
  shiftWrite(3, relayState[3]);
}

BLYNK_WRITE(VPIN_BTN_4) {
  relayState[4] = param.asInt();
  shiftWrite(4, relayState[4]);
}

BLYNK_WRITE(VPIN_BTN_5) {
  relayState[5] = param.asInt();
  shiftWrite(5, relayState[5]);
}

Will become:

// When App button is pushed - switch the state
BLYNK_WRITE_DEFAULT() {
  int pin = request.pin; // determines what vPin is triggering this response
  relayState[pin] = param.asInt();
  shiftWrite(pin, relayState[pin]);
}

You can use array of struct to do the job more efficient this way"

#define BLYNK_PRINT Serial
// Comment out as no full code exists
//#include "settings.h"
//#include "wifimanagment.h"
//#include "shiftwrite.h"
#include <BlynkSimpleEsp8266.h>
#include <EEPROM.h>

BlynkTimer timer;

/* SN74HC595 Connections */
/* Controls the internal transference of data in SN74HC595 internal registers */
const int LATCH_PIN = 16; // D0 - Connected to ST_CP
/* Generates the clock signal to control the transference of data */
const int CLOCK_PIN = 5;  // D1 - Connected to SH_CP
/* Outputs the byte to transfer */
const int DATA_PIN = 4;   // D2 - Connected to DS

// Pin GPIO3
#define RX    3

/* Blynk Virtual Pin Assignment */
#define VPIN_BTN_0  V0
#define VPIN_BTN_1  V1
#define VPIN_BTN_2  V2
#define VPIN_BTN_3  V3
#define VPIN_BTN_4  V4
#define VPIN_BTN_5  V5

void checkPhysicalButton();

#define NUM_OF_RELAYS      6

typedef struct
{
  const int vPin;
  const int buttonPin; 
  bool relayState;
  bool btnState;
} Relay_Property_t;

Relay_Property_t relayArray[NUM_OF_RELAYS] =
{
  { V0, D3, true, true },
  { V1, D4, true, true },
  { V2, D5, true, true },
  { V3, D6, true, true },
  { V4, D7, true, true },
  { V5, RX, true, true }
};


// Every time we connect to the cloud...
BLYNK_CONNECTED() { 
 for (int i = 0; i < NUM_OF_RELAYS; i++)
 {
  Blynk.syncVirtual(relayArray[i].vPin);
 }
}

// When App button is pushed - switch the state
// BLYNK_WRITE can't be optimized by putting in a loop
// Can't use BLYNK_WRITE(relayArray[0].vPin) 

BLYNK_WRITE(VPIN_BTN_0) 
{
  int index = 0;
  relayArray[index].relayState = param.asInt();
  shiftWrite(index, relayArray[index].relayState);
}

BLYNK_WRITE(VPIN_BTN_1) 
{
  int index = 1;
  relayArray[index].relayState = param.asInt();
  shiftWrite(index, relayArray[index].relayState);
}

BLYNK_WRITE(VPIN_BTN_2) 
{
  int index = 2;
  relayArray[index].relayState = param.asInt();
  shiftWrite(index, relayArray[index].relayState);
}

BLYNK_WRITE(VPIN_BTN_3) 
{
  int index = 3;
  relayArray[index].relayState = param.asInt();
  shiftWrite(index, relayArray[index].relayState);
}

BLYNK_WRITE(VPIN_BTN_4) 
{
  int index = 4;
  relayArray[index].relayState = param.asInt();
  shiftWrite(index, relayArray[index].relayState);
}

BLYNK_WRITE(VPIN_BTN_5) 
{
  int index = 5;
  relayArray[index].relayState = param.asInt();
  shiftWrite(index, relayArray[index].relayState);
}

void checkPhysicalButton() 
{
  for (int i = 0; i < NUM_OF_RELAYS; i++)
  {
    if (digitalRead(relayArray[i].buttonPin) == 0) 
    {
        // btnState[] is used to avoid sequential toggles
        if (relayArray[i].btnState) 
        {
          // Toggle RELAY state
          relayArray[i].relayState = !relayArray[i].relayState;
          shiftWrite(0, relayArray[i].relayState);

          // Update Button Widget
          Blynk.virtualWrite(relayArray[i].vPin, relayArray[i].relayState);
        }
        relayArray[i].btnState = false;
    } 
    else 
    {
      relayArray[i].btnState = true;
    }    
  }  
}

// Fake function to satisfy compiler
void shiftWrite(int i, bool relayState)
{

}

// Fake function to satisfy compiler
bool connectWifi()
{
  return true;
}

// Fake function to satisfy compiler
void startAP()
{
  
}

char auth[]     = "***"; 
char ssid[]     = "***"; 
char password[] = "***"; 

void setup() 
{
  //EEPROM.begin(memalloc);
  EEPROM.begin(2048);
  
  Serial.begin(115200);
  delay(100);

  // Set the three SPI pins to be outputs
  pinMode(DATA_PIN, OUTPUT);
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);

  for (int i = 0; i < NUM_OF_RELAYS; i++)
  {
    // Turn off all RELAYS
    shiftWrite(i, HIGH);
    // Restore previous RELAYS states
    pinMode(relayArray[i].buttonPin, INPUT_PULLUP);
    shiftWrite(i, relayArray[i].relayState);
  }

  // Setup a function to be called every 100 ms
  timer.setInterval(100L, checkPhysicalButton);

  if(connectWifi()){
    Blynk.begin(auth, ssid, password);
  } else {
    startAP();
    Blynk.begin(auth, ssid, password);
  }
}

void loop() {
  if(WiFi.status() == WL_CONNECTED){
    Blynk.run();
    timer.run();
  } else{
    startAP();
  }
}

3 Likes