BLYNK
HOME       📲 GETTING STARTED       📗 DOCS       ❓HELP CENTER       👉 SKETCH BUILDER

Problem with my widgets led (I guess)

arduino

#1

Hi,

I’ve a 5 motors that when turned on energize a relay which N/O contactors are wired to an Arduino Yun board (using ethernet). Meaning that when the motors are ON, a DC ground is applied to the board’s pin. A LOW signal is detected and a LED is turned on in the Blynk app. I’m using analog lines because the digitals are all used up.

This process has been working for months but lately I had the brilliant idea to count the times the motors are turned on during a day and displaying the totals on the Blynk app as well. The counters are then reseted in the morning starting so a new process all over again. For troubleshooting purposes, I’m also storing, on a SD card, the counts (relays activations).

Well, since the addition of the counters, the LEDs on the Blynk app are not always turning on/off but the counters are adding up correctly.

I just cannot seem to find my error and I was wondering if it could be a timing issue between my Yun and the Blynk server. I also noticed that when I turn on the app, the Yun shows offline but always recovers within seconds. The latter it always been this way even before adding the countes to the app.

Here’s a test code…
TIA

//#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);       //check lavadora x status
  timer.setInterval(5000L, ledTimerXL);      //check lavadora x status
  timer.setInterval(5000L, ledTimerXXL);     //check lavadora x status
  timer.setInterval(5000L, ledTimerS1);      //check lavadora x status
  timer.setInterval(5000L, ledTimerS2);      //check lavadora x status

  Blynk.begin(auth);
}

void loop() {
  //--if it's 9AM resetCounters()---

  Blynk.run();
  timer.run();
}

void ledTimerS() {
  bool pinState = (digitalRead(statusPinS) == HIGH);

  if (pinState != lastRelayState[0]) {

    if (pinState) {
      ledS.off(); // maquina x led state
    }
    else {
      ledS.on();
      opCounter[0] += 1;

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

      Blynk.virtualWrite(V18, opCounter[0]);
    }
    delay(50);  //for debounce
  }
  lastRelayState[0] = pinState;
}

void ledTimerXL() {
  bool pinState = (digitalRead(statusPinXL) == HIGH);

  if (pinState != lastRelayState[1]) {

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

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

      Blynk.virtualWrite(V20, opCounter[1]);
    }
    delay(50);  //for debounce
  }
  lastRelayState[1] = pinState;
}

void ledTimerXXL() {
  bool pinState = (digitalRead(statusPinXXL) == HIGH);

  if (pinState != lastRelayState[2]) {

    if (pinState) {
      ledXXL.off(); // maquina x led status
    }
    else {
      ledXXL.on();
      opCounter[2] += 1;

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

      Blynk.virtualWrite(V21, opCounter[2]);
    }
    delay(50);  //for debounce
  }
  lastRelayState[2] = pinState;
}

void ledTimerS1() {
  bool pinState = (digitalRead(statusPinS1) == HIGH);

  if (pinState != lastRelayState[3]) {

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

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

      Blynk.virtualWrite(V22, opCounter[3]);
    }
    delay(50);  //for debounce
  }
  lastRelayState[3] = pinState;
}

void ledTimerS2() {
  bool pinState = (digitalRead(statusPinS2) == HIGH);

  if (pinState != lastRelayState[4]) {

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

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

      Blynk.virtualWrite(V23, opCounter[4]);
    }
    delay(50);  //for debounce
  }
  lastRelayState[4] = pinState;
}

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");
  }
}

void resetCounters() {
  //reset machines use counters & status in the morning

  for (int i = 0; i < 6; i++) {
    opCounter[i] = 0;
    lastRelayState[i] = 0;
  }

  Blynk.virtualWrite(V18, opCounter[0]);
  Blynk.virtualWrite(V20, opCounter[1]);
  Blynk.virtualWrite(V21, opCounter[2]);
  Blynk.virtualWrite(V22, opCounter[3]);
  Blynk.virtualWrite(V23, opCounter[4]);
}

// 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;
}

#2

All of your timers are set to run at the same time. You should stagger them.

Pete.


#3

Thanks Pete, will try that tomorrow but as a note: I didn’t have a problem with timers before modifying my code and, isn’t impossible that all timers start at same microprocessor’s clock? In other words, the start of each timer should differ at least one (if not several) microprocessor clock from each others. Just thinking out loud.


#4

There’s an excellent Timer tutorial by @Gunner here:

Pete.


#5

No, at least not even close enough for you to measure… each timer starts counting down to the 5 second mark as soon as those commands run (probably all within a fraction of a millisecond)… then each function tries to run at the exact same time, within the limits of a non-RTOS process… If they are simple enough, it will seem OK, but is still bad programing form.


#6

Ok, will stagger them at 200 microseconds something like…
4200,
4400
4600
4800
5000
and will report.


#7

No, don’t do that. Timers ‘shift’ over time so they will overlap from time to time. What you need to do is create ONE function where all those functions are grouped and run that function on a 5000L timer.

However I don’t think that there lies your issue. It looks similar to an issue I’ve had and if the cause is the same then you’ll need to add this line:

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

(curtosy of @Gunner )
at the top (really above all else) of your code. I can’t say for sure whether you have the same cause, but as with me it worked for months and all of a sudden (2 weeks ago?) relays started to fail. I don’t know whether this works the other way round as well, but doesn’t hurt to try

Here’s the post: Serious issue: Digitalwrite fails after 15 minutes


#8

OK, math is not my strongest field… but since all timers, in setup at least, start at the same time they should not drift short of issues like delay() and other processing stoppages (and even then it should equally affect all timers); Then the only time some should overlap is if there are multiples of another timer… i.e, a 1 second timer will run into a 2 second timer every time, but a 1.5 second timer will not, only every 4th iteration (multiples of 6)… but it will run into a 3 second timer every 2nd iteration and so on.

So by using smaller fractions like every 200ms, mixture of odd and even ending, etc, then the risk of crossing iterations lessons greatly.


#9

yes I thought so too…but for unknown reasons they don’t. Actually I’ve once delved into the timer lib and basically grouping everything in one functions and then using a timer as you (and now I) suggested is utter BS from how the lib works…except that that ‘BS’ solution works!! It does NOT make sense. To elaborate: the timer lib simply cycles through its ‘database’ every loop() and checks if a function is past the timer stamp; if so: run the function. Then check the next entry in the ‘database’, so all functions are run consecutively, except if you do it that way stuff goes haywire, while if you do it the ‘onefunction on a timer’ way it goes right…


#10

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:


#11

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.


#12

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:


#13

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.


#14

@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];
}

#15

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.


Hydroponic Greenhouse Management System Virtual PINs not responding
#16

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

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

Will look into heartbeat, thank you.


#17

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…


#18

Where’s the code that does the counting?

Pete.


#19

It’s in my original post.


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


#20

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

Pete.