[SOLVED] Timer and vPins

Hey all,

I’m wrestling with the timers and vpins. @rapgar pointed me in the right direction, but I’m still having issues with it. It was working at some point but it also stopped and now it’s totally not working anymore :’(

I’m, for now, only using IOS app in the cloud, but my timer responds really weird. I’ve set it from 06.00 to 22.30 for testing and when I press it, it says “16.31.59s to timer” and it starts counting down from there. I’m thinking something with timezones, but not quite sure, could be my code.

Anyway, here is the relevant part of said code.

int enableTimer;   // Defaults to disable timer (button on vPin 3)
int timer1Running;   // Defaults to timer is running (timer widget on vPin 4)

int manualTree;    // Tree lamp thingie override (right of couch), default via timer
int manualLamp;    // Normal lamp override (left of couch), default via timer

setup stuff() { here }

BLYNK_WRITE(3)  // Timer enable/disable for lights
{
  enableTimer = param.asInt();
  
  lcd.clear();
  lcd.setCursor(0,0);
  
  if(enableTimer == 1)
  {
    lcd.print("Timer on");
  }
  else
  {
    lcd.print("Timer off");
  }
}

BLYNK_WRITE(4)  // Actual timer to vPin for lights
{
  timer1Running = param.asInt();

  lcd.clear();
  lcd.setCursor(0,0);

  if(timer1Running == 1)
  {
    lcd.print("Timer running");
  }
  else
  {
    lcd.print("Timer n/ running");
  }
}

BLYNK_WRITE(22)  // Manual override for Tree
{
  manualTree = param.asInt();
  
  lcd.clear();
  lcd.setCursor(0,0);
  
  if(manualTree == 1)
  {
    lcd.print("Tree on");
  }
  else
  {
    lcd.print("Tree off");
  }
}

BLYNK_WRITE(23)  // Manual override for Lamp
{
  manualLamp = param.asInt();
  
  lcd.clear();
  lcd.setCursor(0,0);
  
  if(manualLamp == 1)
  {
    lcd.print("Lamp on");
  }
  else
  {
    lcd.print("Lamp off");
  }
}

void loop()
{
  // Run Blynk
  Blynk.run();
}

void checkTimer()
{
  // If timer is on and timer is running, turn lights on or if manual override is on
  if(((enableTimer == 1) && (timer1Running == 1)) || (manualTree == 1))
  {
    // Timer is running, so lights on!
    digitalWrite(22, HIGH);
  }
  else
  {
    digitalWrite(22, LOW);
  }

  if(((enableTimer == 1) && (timer1Running == 1)) || (manualLamp == 1))
  {
    // Timer is running, so lights on!
    digitalWrite(23, HIGH);
  }
  else
  {
    digitalWrite(23, LOW);
  }
}

As for my dashboard config, I’m using 3 buttons (vpins 3, 22 and 23) and a timer to vpin 4.

I’m using the latest library (0.3.1). I have no idea why it goes wrong. When I press the manual override button the lights flick on as they should, but when I enable the timer and the time has come, nothing. When I output serial data the timer always returns “0” and not “1” when running. Has it got to do with vPins, IOS, time zones or something else? I have absolutely no idea. I’ve been messing with it for a couple weeks now and I need a second opinion. Many thanks in advance!

Quick answer: if you tap on Timer after you activate your project, you’ll cycle through options:

  1. time when timer will activate the pin
  2. how much time left to activate the pin

For the rest of the issues - will need to check what’s happening.

Please don’t wait for weeks to ask - ask as you have a question :wink:

It’s not that urgent and I’d like to try for myself first, lol.

Anyway, the timer options are clear, they just don’t seem to make sense and I’m not sure why. This is by the way both on IOS and Android.

Hey Licht,

I have not loaded up your script as yet, but will be happy to do so if you are still having problems. In the meantime, here are some thoughts…

I have now experienced several instances in Blynk where when reassigning virtual pins, the ones that have become unused do not then become available again in the drop down menu. In other words, I am using v30 and v31, but then switch them to v23 and v24. You would think that v30 and v31 would then be available in the drop down but they are not and the entire project becomes unstable. This has happened a number of times where everything was working fine and I decided to clean up the code a little bit and make things more logical. After just the minor changes, the project stopped working as expected. The workaround is to create another project on your iOS device and do a clean assignment of the virtual pins.

Alternatively, I noticed you set enableTimer to “1” which is arguably more correct given that enableTimer is declared as an integer. This may conflict however with the boolean logic of “&&”. You might try setting it to state “HIGH” which seems to be certainly recognized by the arduino.

Also, I note that you have a double instance of the IF test statement. I would think that this should work but consider simplifying with the two digitalWrite statements together if it really is the same IF test.

Good Luck,
R

Quick Reference:
https://www.arduino.cc/en/Reference/Boolean

I’ll try to simplify stuff first by removing the enable/disable procedure entirely and just let the timer do it’s work. The assigment of vPins is quit clean. These two are the only ones I used in this project, so that should be ok.

Either that or I’ll just assign the timer to the physical pics instead of virtual ones, that shouldn’t make any difference for my logic, come to think of it. But in that case I need more than 1 timer because of the multiple relays I need to address.

The enableTimer button works as expected. When I use serial output I can see the state change and the boolean logic which is behind it (the LCD for one) works as it should, but I’ll try and see what different setups do. I think I tried “HIGH” and “LOW” in stead of 1 / 0, but I’ll try again.

Even directly attached to a physical pin the timer doesn’t work. I made the timer check logic as follows:

void checkTimer()
{
  // If timer is on and timer is running, turn lights on or if manual override is on
  if((enableTimer == 1) && (timer1Running == 1))
  {
    // Timer is running, so lights on!
    digitalWrite(22, HIGH);
  }
  else if((enableTimer == 1) && (timer1Running == 0))
  {
    // Timer is running, so lights on!
    digitalWrite(22, HIGH);
  }

  if(manualTree == 1)
  {
    digitalWrite(22, HIGH);
  }
  else
  {
    digitalWrite(22, LOW);
  }

  if((enableTimer == 1) && (timer1Running == 1))
  {
    // Timer is running, so lights on!
    digitalWrite(23, HIGH);
  }
  else if((enableTimer == 1) && (timer1Running == 0))
  {
    // Timer is running, so lights on!
    digitalWrite(23, HIGH);
  }

  if(manualLamp == 1)
  {
    digitalWrite(23, HIGH);
  }
  else
  {
    digitalWrite(23, LOW);
  }
  
}

But it still works as before, when pressing the override button the relay flicks on and off, but nothing when enabling or disabling the timer. I created a couple screenies with the timer and this where it becomes weird, it, doesn’t work with the set time. It’s a bit hard to see, but if you compare the phone time to the timer, there is something wrong with it as far as I can see.

I see there is a HIGH where there should be a LOW (timer not running and enabled), but even that is not working. I definitely suspecting something with the timer widget to be honest.

Hey Licht,

Your problem was bothering me so I decided to load it up this afternoon on an ESP8266. I changed very little in your code and it has been up and stably running for about 6 hours now. I think the problem may be that I don’t see your “checkTimer” function ever being called. Make sure to include the SimpleTimer library. Here it is;

int enableTimer = LOW;
int timer1Running = LOW;
int manualTree = LOW;

SimpleTimer timer;


void setup()
{
  Serial.begin(9600);
  Blynk.begin(auth, "xxx", "xxx");
  timer.setInterval(2000, checkTimer);  //  be sure to call the function

BLYNK_WRITE(29){ 
  enableTimer = param.asInt();  
  }
BLYNK_WRITE(30){ 
  timer1Running = param.asInt();  
  }
BLYNK_WRITE(31){ 
  manualTree = param.asInt();  
  }
  
   
void loop()
{
  Blynk.run();
  timer.run();  //  call function
}

void checkTimer()
{
  // If timer is on and timer is running, turn lights on or if manual override is on
  if(((enableTimer == 1) && (timer1Running == 1)) || (manualTree == 1))
  {
    // Timer is running, so lights on!
    digitalWrite(4, LOW); // inverted to operate relay correctly (for my relay board)
  }
  else
  {
    digitalWrite(4, HIGH);  // inverted to operate relay correctly (for my relay board)
  }
}

Jeez, could it be that? I never realized I needed to loop it that via a timer. I just figured the void loop() would go on and it seems to do that, because my other functions do work. I also included a check to display on my LCD if the thing is still connected and that works fine, like so:

void loop()
{
  // Run Blynk
  Blynk.run();

  // Keep NRF network going and fetch data
  network.update();
  getNetworkData();
  
  // Check timer for lights, not functional yet
  checkTimer();

  // Display message on LCD if connected or not
  checkConnect();
}

This could explain some stability issues I’m having though.

On the other hand, the virtual pin selection does work for the override, so the loop definitely gets called as far as I can see.

I’ll try and do it with the timer instead of the main loop. Maybe it’ll work.

I changed it now. Maybe it’ll become more stable because it disconnects quits frequently (every ten hours or so) so I hope that is fixed, but maybe I just want too much stuff for Blynk to handle. I’ll post my whole code later, maybe there are some other flaws.

It’s still not ok. The timer widget just doesn’t function correctly. I have no idea why. Any suggestions would be appreciated.

Furthermore, it’s not running stable at all. There is latency and sometimes the whole stuff just crashes and disconnects. I’m gonna let it go for a while and try later. For now I’m putting the plug back on my lights :frowning:

What board and connection do you use? Could you please test timer with very simple setup? Just 1 timer and just 1 virtual function that handles it? Also - why would you need checkTimer() function if you already has BLYNK_WRITE(4)?

Just do :

BLYNK_WRITE(4)  // Actual timer to vPin for lights
{
  lcd.clear();
  lcd.setCursor(0,0);

  if (param.asInt())
  {
    lcd.print("Timer running");
    //DO ANY ON OPERATIONS
  }
  else
  {
    lcd.print("Timer n/ running");
    //DO ANY OFF OPERATIONS
  }
}

I use a Arduino Mega with the ENC28J60 ethernet port.

I use a seperate routine because I need to do more logic than just a simple write.

1st I need to see of the timer function is actually on (vPin 3), then check of the timer is actually running (vPin 4) and if so, switch all on. BUT, in case of manual On button, the relays also need to go on.

I will try and check with a simple program, but the timer it self is just wrong. If I press it to see how much time remains before it’s engaged it’s just wrong. I set it, for example, for 6 in the morning untill 22.30 in the evening, but when I press it at ten past six, it says “14 hours remaining or more”. Or at least something which is all wrong and way off.

Besides, I tried to output some serial data like “timer running” on vPin 4, that also didn’t work. It just looks like the whole timer is just doing nothing or is in the wrong timezone.

The whole code and nothing but the code as it is running now:

/****************************************************************************************
 * Changelog:
 * v0.1 initial setup
 * v0.2 using simple timer instead of calling functions from main loop
 */

// Physical Pin assignments

/*
 * 6          = not used, linked to port on backside
 * 7          = not used, linked to port on backside
 * 8          = not used, linked to port on backside
 * 9          = Infrared, linked to port on backside, 1 / 2 (VCC / GND)
 * 10         = CE NRF
 * 11         = CSN NRF
 * 20         = I2C Display SDA (Data)
 * 21         = I2C Display SCK (Clock)
 * 22 t/m 30  = 230v Relays (same as virtual pins)
 * 50         = (MI)SO Ethernet   / NRF
 * 51         = (MO)SI Ethernet   / NRF
 * 52         = SCK Ethernet      / NRF
 * 53         = CS Ethernet       / NRF
 */

// Virual Pin assignments

/*
 * 1          = Audio/video off
 * 2          = Audio/video on
 * 3          = Lights timer on/off (Doesn't work yet)
 * 4          = Lights timer (Doesn't work yet)
 * 7          = LCD backlight on/off
 * 22         = Override Tree
 * 23         = Override Lamp
 */

// Basic

#define BLYNK_PRINT Serial 

// Includes

#include <UIPEthernet.h>                  // Ethernet lib
#include <BlynkSimpleUIPEthernet.h>       // Blynk Ethernet add-ons
#include <IRLib.h>                        // Infrared for audio/video
#include <Wire.h>                         // Wire for I2C communications
#include <LiquidCrystal_I2C.h>            // Matrix display
#include <RF24Network.h>                  // NRF communications
#include <RF24.h>                         // NRF communications
#include <SPI.h>                          // NRF communications
#include <SimpleTimer.h>                  // Timer lib

/****************************************************************************************
 * Blynk Stuff
 */

char auth[] = "bla";

/****************************************************************************************
 * IR stuff for turning on/off Audio/Video equipment (IR Led on Pin3, hardcoded!)
 */

IRsend irsend;

/****************************************************************************************
 * End IR Stuff
 */

/****************************************************************************************
 * Timer and light stuff
 */
 
int enableTimer;   // Defaults to disable timer (button on vPin 3)
int timer1Running;   // Defaults to timer is running (timer widget on vPin 4)

int manualTree;    // Tree lamp thingie override (right of couch), default via timer
int manualLamp;    // Normal lamp override (left of couch), default via timer

/****************************************************************************************
 * End timer and light stuff
 */

/****************************************************************************************
 * LCD Matrix display
 */

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

char text1[] = {'I','n','i','t','i','a','l','i','z','i','n','g'};
char text2[] = {'M','e','g','a','D','o','m','o',' ','v','0','.','2'};
const char* server = "cloud.blynk.cc";
bool backLight = 1;

/****************************************************************************************
 * End LCD Matrix Stuff
 */

/****************************************************************************************
 * NRF24 Radio
 */

RF24 radio(10, 11);
RF24Network network(radio);

struct controlMessage
{
  // int stores 2 bytes, adjust payload if this grows
  float messageData;
};

/****************************************************************************************
 * End NRF24 Radio Stuff
 */

SimpleTimer timerOne;

void setup()
{
  // Serial output for debugs
  Serial.begin(9600);
  delay(10);
  
  timerOne.setInterval(1000, timerStuff);
  
  // Init pins for output (230v relays)
  for(int i=22;i<30;i++)
  {
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);
  }

  // Start Blynk
  Blynk.begin(auth);

  // Init LCD display (16x2)
  lcd.begin(16,2);
  lcd.backlight();
  
  initLCD();

  // Init NRF24 Components
  
  SPI.begin();
  radio.begin();
  radio.setDataRate(RF24_250KBPS);                  // Lowest speed for best transmission
  radio.setPayloadSize(32);                         // Smallest payload for best performance
  network.begin(90, 0);                             // Get networking running on this controller
}

// Do audio/video stuff when pressing button to vPin 1
BLYNK_WRITE(1)
{
  for(int i=0;i<4;i++)
  {
    irsend.send(RC5,0x140F, 13); // AMP off
    irsend.send(SONY,0xA90, 12); // TV off
  }
}

// Do audio/video stuff when pressing button to vPin 2
BLYNK_WRITE(2)
{
  for(int i=0;i<4;i++)
  {
    irsend.send(RC5,0x1C0E, 13); // AMP on
    irsend.send(SONY,0xA90, 12); // TV on
  }
}

/*
 * Set lights on/off with respect to timer on vPin 4
 */
 
BLYNK_WRITE(3)  // Timer enable/disable for lights
{
  enableTimer = param.asInt();
  
  lcd.clear();
  lcd.setCursor(0,0);
  
  if(enableTimer == 1)
  {
    lcd.print("Timer on");
  }
  else
  {
    lcd.print("Timer off");
  }
}

BLYNK_WRITE(4)  // Actual timer to vPin for lights
{
  timer1Running = param.asInt();

  lcd.clear();
  lcd.setCursor(0,0);

  if(timer1Running == 1)
  {
    lcd.print("Timer running");
  }
  else
  {
    lcd.print("Timer n/ running");
  }
}

BLYNK_WRITE(7)  // Backlight on/off
{
  if(backLight)
  {
    lcd.noBacklight();
    backLight = 0;
  }
  else
  {
    lcd.backlight();
    backLight = 1;
  }
}

BLYNK_WRITE(22)  // Manual override for Tree
{
  manualTree = param.asInt();
  
  lcd.clear();
  lcd.setCursor(0,0);
  
  if(manualTree == 1)
  {
    lcd.print("Tree on");
  }
  else
  {
    lcd.print("Tree off");
  }
}

BLYNK_WRITE(23)  // Manual override for Lamp
{
  manualLamp = param.asInt();
  
  lcd.clear();
  lcd.setCursor(0,0);
  
  if(manualLamp == 1)
  {
    lcd.print("Lamp on");
  }
  else
  {
    lcd.print("Lamp off");
  }
}

void loop()
{
  // Run Blynk
  Blynk.run();
  timerOne.run();

  /*
  // Keep NRF network going and fetch data
  network.update();
  getNetworkData();
  
  // Check timer for lights, not functional yet
  checkTimer();

  // Display message on LCD if connected or not
  checkConnect();
  */
}

void timerStuff()
{
  // Keep NRF network going and fetch data
  network.update();
  getNetworkData();
  
  // Check timer for lights, not functional yet
  checkTimer();

  // Display message on LCD if connected or not
  checkConnect();
}

void checkTimer()
{
  // If timer is on and timer is running, turn lights on or if manual override is on
  if(((enableTimer == 1) && (timer1Running == 1)) || (manualTree == 1))
  {
    // Timer is running, so lights on!
    digitalWrite(22, HIGH);
  }
  else
  {
    // Timer is not running, so lights off!
    digitalWrite(22, LOW);
  }
  
  if(((enableTimer == 1) && (timer1Running == 1)) || (manualLamp == 1))
  {
    // Timer is running, so lights on!
    digitalWrite(23, HIGH);
  }
  else
  {
    // Timer is not running, so lights off!
    digitalWrite(23, LOW);
  }
}

void checkConnect()
{
  if(Blynk.connected())
  {
    lcd.setCursor(0,1);
    lcd.print("Connected!   ");
  }
  else
  {
    lcd.setCursor(0,1);
    lcd.print("Disconnected!");
  }
}

void initLCD()
{
  lcd.clear();
  lcd.setCursor(0,0);
   
  for(int i = 0; i< 4; i++)
  {
    lcd.noBacklight();
    delay(100);
    lcd.backlight();
    delay(100);
  }

  for(int i=0;i<sizeof(text1);i++)
  {
    lcd.print(text1[i]);
    //Serial.println(text1[i]);
    delay(100);
  }

  for(int i=0;i<sizeof(text1);i++)
  {
    lcd.setCursor(i,0);
    lcd.print(" ");
    delay(100);  
  }

  lcd.setCursor(0,0);
  
  for(int i=0;i<sizeof(text2);i++)
  {
    lcd.print(text2[i]);
    //Serial.println(text2[i]);
    delay(100);
  }

  for(int i=0;i<sizeof(text2);i++)
  {
    lcd.setCursor(i,0);
    lcd.print(" ");
    delay(100);  
  }

  for(int i = 0; i< 4; i++)
  {
    lcd.noBacklight();
    delay(100);
    lcd.backlight();
    delay(100);
  }
  
  lcd.clear();
}

void getNetworkData()
{
  // Receive network data
  while(network.available())
  {
    RF24NetworkHeader header;                       // Create header
    controlMessage message;                         // Define message

    bool receiveOK = network.read(header,&message,sizeof(message));  // Read message from network

    // If message is received, return data and exit function
    if(receiveOK)
    {
      lcd.setCursor(0,0);
      lcd.print("Temp: " );
      lcd.setCursor(6,0);
      lcd.print((int)message.messageData);
      Blynk.virtualWrite(0, message.messageData); 
    }
  }
}

How do you check this?

Timer works in next way. When “start time” happens it just sends HIGH/1 value once on selected pin. When “stop time” happens is just sends LOW/0 value once on selected pin. Maybe you have different understanding of how it should work?

No, if you click the time widget you can see it with either the start/end time or the time remaining to start/end, right? This is wat Pavel told me. When I check that, it doesn’t make sense. At the time it should be on, it is not. It says "TImer in ". And the value is really weird.

When I set it to go on at 6 and it actually is 6, it doesn’t go on, it says something like “Timer in 14.30h”

No =). Timer works as I described. By selecting “start time”, “end time” you just select exactly time in a day when to trigger action.

I just checked the timer on iOS. It works as I described.

Could you please use a Simple ethernet example.
Connect 1 LED to Arduino
Put just 1 timer widget in the app.Nothing else
Choose digital pin
Check if it works

I’ll try that. I think I have some LED around somewhere. It’s not gonna be today though. We’re having a major VMWare crisis at work, LOL.

@Dmitriy: but the timer display changes when you touch it? It says “in” or “at”, what’s the difference with that? I think Pavel explained that.

yes.

“in” means how much time left before action. “at” - is exaclty time of action.

yes, that’s what I’ve been trying to say, the values don’t make sense in my dashboard.

  1. I set it 6am
  2. When it is 6am, nothing happens
  3. When I touch it at 6am it says “Timer IN 14 hours” or some ridiculous value like that

So it LOOKS like the timer widget is off.