Problem with my widgets led (I guess)

Ok, I kind like the idea to group all the functions in one eliminating so any doubts with overlapping timing. I guess I’ll need to use many IF statements. Will try that and staggering timers as well.

However, I’m not sure I understand the function

#define BLYNK_NO_BUILTIN // Disable built-in analog & digital pin operations.

Because I’m using all pins, Virtual, Digital and Analog, won’t that turn my board useless? :thinking:

well…that was my initial thought as well. But no. And TBH its less applicable in your case cause you have failing ‘software leds’ while I had faileing ‘hardware leds’. But what this disables is direct acces from the app to the digital pin, so you can use digitalwrite() in your code but you can’t manipulate a physical pin directly from the app. Neither write not read! You can only work with Virtual pins in your app and your code is the one that makes the changes to the pins. But as you have ‘worked for months and recently stuff started to fail after an update’ issue like I did…it doesn’t hurt to try.

I run multiple functions on one timer, and I run multiple timers with one function per… depends on my needs actually.

And then I often run many separate short term timers inside those functions.

So far, with careful tweeking and spacing (even creating multiple named timers for certain instances, even though each one can have up to 16 instances, can have a profound difference), I have been able to keep my testbench running with 26+ separate timers (admittedly not all running all the time), even though it is only on a 16Mhz Arduino Mega.

It is kinda fun trying to make all these different timers behave properly with little tricks :stuck_out_tongue_winking_eye:

Just be careful that the code within that function doesn’t take too long to execute. If it does then you’ll run into Blynk timeout and disconnection issues again.
There’s a happy compromise in there somewhere, it just needs some careful though and planning.

Pete.

1 Like

@Gunner that Mega must be smoking with all those timers :laughing:

@PeteKnight As I mentioned in my first post, my board does disconnect often. Perhaps it’s what’s causing the problem.

Will try to run one function on one timer and I don’t think it’ll take too many recourses from the server to disconnect me. Here’s the change… will try it this afternoon as I´m away from the board.

void ledTimer() {
  bool pinState[5] {
    digitalRead(statusPinS) == HIGH,
    digitalRead(statusPinXL) == HIGH,
    digitalRead(statusPinXXL) == HIGH,
    digitalRead(statusPinS1) == HIGH,
    digitalRead(statusPinS2) == HIGH
  };

  delay(50);  //for debounce

  if (pinState[0] != lastRelayState[0]) {

    if (pinState[0]) {
      ledS.off(); 
    }
    else {
      ledS.on();
      opCounter[0] += 1;

      dataString = "";
      dataString += showTime();
      dataString += " S cnt: ";
      dataString += opCounter[0];
      writeSD(dataString);

      Blynk.virtualWrite(V18, opCounter[0]);
    }
  }

  if (pinState[1] != lastRelayState[1]) {

    if (pinState[1]) {
      ledXL.off();
    }
    else {
      ledXL.on();
      opCounter[1] += 1;

      dataString = "";
      dataString += showTime();
      dataString += " XL cnt: ";
      dataString += opCounter[1];
      writeSD(dataString);

      Blynk.virtualWrite(V20, opCounter[1]);
    }
  }

  if (pinState[2] != lastRelayState[2]) {

    if (pinState[2]) {
      ledXXL.off(); 
    }
    else {
      ledXXL.on();
      opCounter[2] += 1;

      dataString = "";
      dataString += showTime();
      dataString += " XXL cnt: ";
      dataString += opCounter[2];
      writeSD(dataString);

      Blynk.virtualWrite(V21, opCounter[2]);
    }
  }

  if (pinState[3] != lastRelayState[3]) {

    if (pinState[3]) { //led off
      ledS1.off();
    }
    else {
      ledS1.on();
      opCounter[3] += 1;

      dataString = "";
      dataString += showTime();
      dataString += " S1 cnt: ";
      dataString += opCounter[3];
      writeSD(dataString);

      Blynk.virtualWrite(V22, opCounter[3]);
    }
  }

  if (pinState != lastRelayState[4]) {

    if (pinState) {
      ledS2.off();
    }
    else {
      ledS2.on();
      opCounter[4] += 1;

      dataString = "";
      dataString += showTime();
      dataString += " S2 cnt: ";
      dataString += opCounter[4];
      writeSD(dataString);

      Blynk.virtualWrite(V23, opCounter[4]);
    }
  }

  lastRelayState[0] = pinState[0];
  lastRelayState[1] = pinState[1];
  lastRelayState[2] = pinState[2];
  lastRelayState[3] = pinState[3];
  lastRelayState[4] = pinState[4];
}

two things I did to (partially) solve that issue:

  1. put blynk.run() inbetween the functions so
void oneFunctionToLaunchThemAll(){
theDwarves();
theElves();
blynk.run();
theHumans();
}

The other is:

#define BLYNK_HEARTBEAT 60

often the ‘disconnects’ aren’t actual disconnects, its just that your functions take too long to hit the blynk.run() again which resets the blynk heartbeat (10s time out) resulting in a ‘disconnect’. Stretching that time gives your device to reset that heartbeat before it runs out.

1 Like

How does that differs from the code below?:thinking:

void loop(){
theDwarves();
theElves();
theHumans();
blynk.run();
}

Will look into heartbeat, thank you.

Ok, I still cannot get my code to work and does not look like it’s a timer issue.

My original code where LEDs light up in Blynk app work fine.

timer.setInterval(5000L, ledTimers);

....

void ledTimers() {
  bool pinState[5] {
    digitalRead(statusPinS) == HIGH,
    digitalRead(statusPinXL) == HIGH,
    digitalRead(statusPinXXL) == HIGH,
    digitalRead(statusPinS1) == HIGH,
    digitalRead(statusPinS2) == HIGH
  };

  delay(50);  //for debounce just in case

  if (pinState[0]) {
    ledS.off();
  }
  else {
    ledS.on();
  }

  if (pinState[1]) {
    ledXL.off();
  }
  else {
    ledXL.on();
  }

  if (pinState[2]) {
    ledXXL.off();
  }
  else {
    ledXXL.on();
  }

  if (pinState[3]) {
    ledS1.off();
  }
  else {
    ledS1.on();
  }

  if (pinState[4]) {
    ledS2.off();
  }
  else {
    ledS2.on();
  }
}

So I still cannot get to count the times the LEDs come on. I can only suppose that the functions led.on()/off() do not get along with Blynk.virtualWrite(pin, value). Will keep trying…

Where’s the code that does the counting?

Pete.

It’s in my original post.


else {
ledS.on();
opCounter[0] += 1;

So can you post the full updated code that should be working, but isn’t?
No code snippets please.

Pete.

Sure, it’s shown below. I’m using two timers: one to turn on leds on the app which is working and the other, to count and display the total of times the leds come on.

//#define BLYNK_DEBUG // Optional, this enables lots of prints
//#define BLYNK_PRINT Serial // Comment this out to disable prints and save space

#include <Bridge.h>
#include <BlynkSimpleYun.h>
#include <Process.h>

#include <FileIO.h>
String dataString;

/* Blynk */
char auth[] = "*******";

BlynkTimer timer;

//LEDs on counters
// S XL XXL S1 S2
int opCounter[5] = {0, 0, 0, 0, 0};
int lastRelayState[5] = {0, 0, 0, 0, 0};

//Blynk LEDs
WidgetLED ledS(V11);
WidgetLED ledXL(V12);
WidgetLED ledXXL(V13);
WidgetLED ledS1(V14);
WidgetLED ledS2(V15);

//hardware arduino Yun
//lines connected to N/O relays contactors
const int statusPinS = A5;
const int statusPinXL = A4;
const int statusPinXXL = A3;
const int statusPinS1 = A2;
const int statusPinS2 = A1;

void setup() {
  Bridge.begin();
  Console.begin();

  pinMode(statusPinS, INPUT_PULLUP);
  pinMode(statusPinXL, INPUT_PULLUP);
  pinMode(statusPinXXL, INPUT_PULLUP);
  pinMode(statusPinS1, INPUT_PULLUP);
  pinMode(statusPinS2, INPUT_PULLUP);

  timer.setInterval(5000L, ledTimers);    //used to turn on leds on app
  timer.setInterval(6000L, ledCounters);   //used to count times leds turn on

  Blynk.begin(auth);
}

void loop() {
  Blynk.run();
  timer.run();
}

void ledTimers() {
  bool pinState[5] {
    digitalRead(statusPinS) == HIGH,
    digitalRead(statusPinXL) == HIGH,
    digitalRead(statusPinXXL) == HIGH,
    digitalRead(statusPinS1) == HIGH,
    digitalRead(statusPinS2) == HIGH
  };

  delay(50);  //for debounce just in case

  if (pinState[0]) {
    ledS.off();
  }
  else {
    ledS.on();
  }

  if (pinState[1]) {
    ledXL.off();
  }
  else {
    ledXL.on();
  }

  if (pinState[2]) {
    ledXXL.off();
  }
  else {
    ledXXL.on();
  }

  if (pinState[3]) {
    ledS1.off();
  }
  else {
    ledS1.on();
  }

  if (pinState[4]) {
    ledS2.off();
  }
  else {
    ledS2.on();
  }
}

void ledCounters() {

  bool pinState[5] {
    digitalRead(statusPinS),
    digitalRead(statusPinXL),
    digitalRead(statusPinXXL),
    digitalRead(statusPinS1),
    digitalRead(statusPinS2)
  };

  delay(50);  //for debounce just in case

  if (!pinState[0] != lastRelayState[0]) {
    lastRelayState[0] = !pinState[0];

    opCounter[0] += 1;

    dataString = "";
    dataString += getTimeStamp();
    dataString += " S cnt: ";
    dataString += opCounter[0];
    writeSD(dataString);

    Blynk.virtualWrite(V18, opCounter[0]);
  }

  if (!pinState[1] != lastRelayState[1]) {
    lastRelayState[1] = !pinState[1];
    opCounter[1] += 1;

    dataString = "";
    dataString += getTimeStamp();
    dataString += " XL cnt: ";
    dataString += opCounter[1];
    writeSD(dataString);

    Blynk.virtualWrite(V20, opCounter[1]);
  }

  if (!pinState[2] != lastRelayState[2]) {
    lastRelayState[2] = !pinState[2];
    opCounter[2] += 1;

    dataString = "";
    dataString += getTimeStamp();
    dataString += " XXL cnt: ";
    dataString += opCounter[2];
    writeSD(dataString);

    Blynk.virtualWrite(V21, opCounter[2]);
  }

  if (!pinState[3] != lastRelayState[3]) {
    lastRelayState[3] = !pinState[3];
    opCounter[3] += 1;

    dataString = "";
    dataString += getTimeStamp();
    dataString += " S1 cnt: ";
    dataString += opCounter[3];
    writeSD(dataString);

    Blynk.virtualWrite(V22, opCounter[3]);
  }

  if (!pinState != lastRelayState[4]) {
    lastRelayState[4] = !pinState[4];
    opCounter[4] += 1;

    dataString = "";
    dataString += getTimeStamp();
    dataString += " S2 cnt: ";
    dataString += opCounter[4];
    writeSD(dataString);

    Blynk.virtualWrite(V23, opCounter[4]);
  }
}

void writeSD(String data) {
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  // The FileSystem card is mounted at the following "/mnt/FileSystema1"
  File dataFile = FileSystem.open("/mnt/sd/cntlog.txt", FILE_APPEND);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(data);
    dataFile.close();
    // print to the Console port too:
    Console.print("Data written to SD: ");
    Console.println(data);
  }
  // if the file isn't open, pop up an error:
  else {
    Console.println("error opening datalog.txt");
  }
}

// This function return a string with the time stamp
String getTimeStamp() {
  String result;
  Process time;
  // date is a command line utility to get the date and the time
  // in different formats depending on the additional parameter
  time.begin("date");
  time.addParameter("+%D-%T");  // parameters: D for the complete date mm/dd/yy
  //             T for the time hh:mm:ss
  time.run();  // run the command

  // read the output of the command
  while (time.available() > 0) {
    char c = time.read();
    if (c != '\n') {
      result += c;
    }
  }
  return result;
}

As those functions start in sequential order, the placement of the Blynk.run() can allow the Blynk Library to maintain housekeeping in the middle of the functions instead of waiting until they all finish, at which time it is possibly too late.

If you have a particularly long function running, then just place a Blynk.run() somewhere in the midst of that functions code.

Also, this is in the void loop:

whereas the alternative example was in a function being called by a timer.

But maybe it was a rhetorical question?

Pete.

Good catch, I was referring to the placement of extra Blynk.run() commands, I didn’t notice the overall placement in the void loop().

So in that case the difference is all those functions trying to run thousands of times a second in the void loop() vs trying to run at a more reasonable pace via a timed call :stuck_out_tongue:

1 Like

That seems a bit of a cumbersome way to do it. Wouldn’t it make more sense just to increment your counter at the same time that you activate your LED/Motors?

In your original post you said:

then later you said:

So I’m confused about exactly what is and isn’t working in Blynk, and also what data you’re getting on your SD card compared to Blynk.

Also, you said:

but all of your pin declarations and reads are digital rather than analogue. I have to admit that I’ve never tried doing a digital read on an analogue pin, but it seems a bit strange to me!

Pete.

I think the answer has already been given, but let me elaborate nonetheless:

What you suggest is running those functions a few 1000 times a second, thats one hell of a way to brea it. What I’m suggesting is to replace ALL timed function with theOneThatLaunchesThemAll, so:

void setup(){
...
  timer.setInterval(5000L, oneFunctionToLaunchThemAll);
...
}

AND place a blynk.run() in the middle for good measure (to keep the heartbeat)

This is interesting and I’d never considered doing this. What is considered to be “a particularly long function”?

I have a timing issue with a PM sensor that sends out serial data every 2.3 seconds regardless, this means that my program could wait at the first “if start character == 0x**” statement for 4.6 seconds (minus a little bit) before continuing with the rest of the function. Because this timer function has to sometimes wait it then effects the rest of the timed functions and possibly Blynk.run, I don’t know.

I don’t fully understand how the Blynk timers work, even after reading the excellent tutorial by @Gunner several times. I realize inserting a Blynk.run() command before this possible delay won’t have any effect, but maybe I should insert it once the start character has been read.

My CO2 and CH2O sensors both require a serial request command to get data which is great because I can control the event rather than the sensor controlling me!

Richard

They are based on SimpleTimer, an Arduino library you can read a bit more about here…

https://playground.arduino.cc/Code/SimpleTimer#Functions

If you have long runs or Blocking code in which you can insert them, then additional Blynk.run() and timer.run() calls could be placed there to help keep the rest of the code ticking away as they basically call each’s respective library and keeps them updated and “in the loop”. Trial and error is a good way to see what works where.

Hi @PeteKnight,

When a thread gets long, the likelihood to produce errors or confusion is high so, I summarize my dilemma as follow:

I’m using 5 analog pins programmed as INPUT_PULLUP and connected to the N/O contactor of a relay. So, there’s a constant HIGH on the input. When the relay is actuated, a LOW is applied to the analog pins. I’m using analog pins because all my digital once are in use.

//hardware arduino Yun
//lines connected to N/O relays contactors
const int statusPinS = A5;
const int statusPinXL = A4;
const int statusPinXXL = A3;
const int statusPinS1 = A2;
const int statusPinS2 = A1;

In my original code which is not posted, I used 5 timers to read the inputs and turn on the LEDs on the Blynk app and that worked fine for months. Then I decided to count the times the LEDs come on. The code to do that is shown on my first post. The modification applied caused the LEDs not to turn on as designed but, the counter did work.

Based on suggestions received on this thread, I consolidated the timers into one and tested the turn on of LEDs only and worked. Then I tested the counters and didn’t work.

For troubleshooting purposes, I created two timers, one to turn on the LEDs and the other to count the times the LEDs are turned on. I know it’s a cumbersome way of programming but it’s an easy way to identify the problem, at least for me.

So, that’s where I’m now, trying to understand why the counters are producing an erratic reading.

1 Like