Issues: Relay from one event goes off when a different event it triggered

I have some code that does multiple things and I would like some information pertaining to the various kinds of interrupts. Most of my code is event based. So I am using timers to call certain events. However, when some of the events occur, a relay that I have configured for a different event ends up going on and off for a brief period.

For example, a piece of code goes to the internet and reads the status of a text file in a folder in my server. If the value is 0 the relay is off, if the value is 1, the relay is on. Currently, I am polling every 20 seconds in order to read a change on the file. I have php script that allows me to write to that text file. Meanwhile, I have another event that sends data to the web every 6 minutes. When I send the data, for a brief moment, the status of the relay goes on or off depending on the initial state before the data is sent.

Its kinda annoying, since I know that relay should stay on or off when I know that text file didn’t change its state, because I didn’t write to it. So the other event somehow causes the relay to turn on or off without me telling it to. How is this so? Would interrupts work? Internal, external? I still want the data to be sent, and still want the status of the relay to say the same so they both have priority. How do you account for that in the code?

A piece of the code is posted below. As you can see every 6 min or 360 seconds, I make a request and send data and every 20 seconds I make a request to read a file. So when the time alarm for the 6 min event goes off, there is a brief 5-10 state where the relay from the other event goes on or off. If it was off before the 6 min event happened then it will go on for 5 or 10 seconds then go back off. If it was on before the 6 min event happened then it will go off for 5- 10 seconds then go back on. "Most" of the time it does this when the 6 min event it triggered

    #include "Wire.h"
    #include "DS1307RTC.h"
    #include "DHT.h"
    #include "PID_v1.h"
    #include "SPI.h"
    #include "Time.h"
    #include "TimeAlarms.h"
    #include "WiFi.h"
    
    
    
    #define SensorPin 2      
    #define Offset 0            
    #define DHTPIN 2
    #define DHTTYPE DHT11
    #define RELAY_ON 1
    #define RELAY_OFF 0
    #define Relay1  9  
    #define Relay2  8
    #define Relay3  6
    #define Relay4  5
    #define Relay5  4  
    #define Relay6  3
    #define Relay7  38
    #define Relay8  39  
    
    char server[] = "xx";  //IPAddress server
    char ssid[] = "xx";     //SSID Home Network Name
    char pass[] = "xx";  //Key or Network Password
    int status = WL_IDLE_STATUS;               
    int analogChannel0 = 0; //Soil Moisture Sensor
    int flag = 0;
    
    unsigned long int avgValue;
    WiFiClient client;
    
    
    
    int xx = 300;
    int zz = 20;
    int ww = 360;
    double Setpoint, Input, Output;
    DHT dht(DHTPIN, DHTTYPE);
    
    
    void setup() {
          Setpoint = 7;
          dht.begin();
          Wire.begin();
         //myPID.SetSampleTime(30000);
         digitalWrite(Relay1, RELAY_ON);
         digitalWrite(Relay2, RELAY_ON);
         digitalWrite(Relay3, RELAY_ON);
         digitalWrite(Relay4, RELAY_ON);  
         digitalWrite(Relay5, RELAY_ON);
         digitalWrite(Relay6, RELAY_ON);
         digitalWrite(Relay7, RELAY_ON);
         digitalWrite(Relay8, RELAY_ON);
         
         pinMode(Relay1, OUTPUT);   
         pinMode(Relay2, OUTPUT);  
         pinMode(Relay3, OUTPUT);  
         pinMode(Relay4, OUTPUT);    
         pinMode(Relay5, OUTPUT);   
         pinMode(Relay6, OUTPUT);  
         pinMode(Relay7, OUTPUT); 
         pinMode(Relay8, OUTPUT); 
          
         Serial.begin(9600); 
    
         setSyncProvider(RTC.get);
    
          Alarm.timerRepeat(ww, SendData);   
          Alarm.timerRepeat(zz, ReadData);
    
      
         while ( status != WL_CONNECTED) { 
                      status = WiFi.begin(ssid, pass);     
            }
         } //End of Void Setup
    
    void loop() {     
     
                Alarm.delay(0);           
                } //End of Loop   
                
                    void SendData(){            
                    if (client.connect(server, 80)) {
                  
                    
                                int SoilMoisture = analogRead(analogChannel0);            
    
                               client.print("GET xx");
                               client.print("&SoilMoisture=");
                               client.print(SoilMoisture);                             
                               client.print("&Setpoint=");
                               client.println(Setpoint);
                                  } 
                              }           
                    
                                               
                    void ReadData() 
                    {
                            if (client.connect(server, 80)) {
                                 client.println("GET xx.txt HTTP/1.1");
                                 client.println("Host: xx");
                                 client.println("Connection: close");  
                                client.println();
                              }
                                   flag = 0;
                       while (client.available()) {
                                        char c = client.read();
                                        Serial.write(c);
                       if (c == '0'){
                                 flag = 0;
                                  }
                       if (c == '1'){
                                 flag = 1;
                                  }              
                             } 
                       if (flag == 0) {
                             digitalWrite(Relay3, LOW);
                            }
                      if (flag == 1) {
                             digitalWrite(Relay3, HIGH);
                           }
                    }

char server = "xx"; //IPAddress server(54,200,69,220);
char ssid = "xx"; //SSID Home Network Name
char pass = "xx"; //Key or Network Password

You only want 2 charaters in each array?

They are just place holders so I dont show everyone all of my info

If your code were Auto Formatted and in code tags as suggested in the stickies for this forum (above) it would be much easier to give help. As it is, I can't be bothered to read it.

Is your power supply to the relays sufficient? Could it be that operating several relays at once is causing a drop-out?

Yes, I have a 9 volt 1A power supply. Its powering a 8 channel relay shield. There more than enough juice to turn those guys on. It seems like I need an interrupt, but both events are a priority so I am stuck on how to approach this

I suspect the problem lies in the way you are using two times. At the 360 second mark they will both trigger because 360 is a multiple of 20. They may be tripping over each other.

For a quick test change the 20 to 23 seconds (which is a prime number) and see what happens.

If that makes a difference I suggest you use only the 20 second timer and count the calls it makes so that every 18 calls you also run the sendData() function after the readData() function.

As someone else said - format your code properly and also use informative variable names rather than zz and ww.

By the way, you could also manage the timing using the concept in the "blink without delay" sketch without bothering with the TimeAlarms stuff. But the potential problem (and solution) I have suggested would still be relevant.

...R

I can see where there might be an issue since 20 goes into 360 18 times evenly and they both will go off. If the blink without delay runs into the same issue with regards to timing; then what should I do? Mathematically, are there two numbers when repeating will never cross into each other to avoid the issue i am having now? Interrupts will take one event first over the other depending which one I have an interrupt on so that wont work for me.

I also have a relay on a PID that will go on or off depending on a particular ph level. This means it can go off without notice at any given second. There may be a possibility where that relay goes off at the same time i send data. Is there any work around this? Can I not have two things achieve two different events at the same time? What function, or command assists with this situation. Thanks

If the blink without delay runs into the same issue with regards to timing; then what should I do?

As suggested, use one interval and count how many times it occurs. When the 2 events coincide you can decide which will happen and in what order.

Hi, what voltage levels are you switching with the relay outputs?
Can we have a picture of your project to see your layout, are you using a shield or have you got your components on protoboard or soldered to board.
What are the relay types, do you have bypassing caps fitted to help with any glitches.

Hope to help..
Tom....... :slight_smile:

(UKHeliBob), I will research what you are talking about. It makes sense. So would I have to do this for the alarms I have that are set 12 to 20 hours apart and are called daily or would the TimeAlarms work for this? What happens when an event from a Alarm goes off at the same time the blink without delay millis thing occur? If they coincide do i have the possibility f choosing which order comes first?

(TomGeorge), 120 VAC is the output voltage, I am not using bypassing capacitors, that is something I did not think of, thank you for suggesting that, I will definitely look into this. The link for the relays are posted below. I am using a a WIFI shield but am currently searching for something with one of those black antennas connected to the board for better range and a more reliable websocket strength. Sensors and small components will be soldered most likley to a board of some kind. Haven't gotten that far, but getting close.

Have you tried my suggestion for testing the problem by changing the 20 secs to 23 secs. There is not much point going further until you are sure that the coincidence of the timers is the problem.

Assuming it is the problem you can expect the same issue to arise whenever there are coincident timer calls.

And, as I said earlier, the simple solution is to use a (say) 20 second timer and count how many times it triggers as a method of determining longer times.

...R

(UKHeliBob), I will research what you are talking about. It makes sense. So would I have to do this for the alarms I have that are set 12 to 20 hours apart and are called daily or would the TimeAlarms work for this? What happens when an event from a Alarm goes off at the same time the blink without delay millis thing occur? If they coincide do i have the possibility f choosing which order comes first?

Firstly I think that you should give Robin2 the credit for suggesting the idea.

The suggestion is that you use only one time period and count how many of them occur. Once the desired multiple of the short period has occurred then do whatever is appropriate. I would do the timing with millis() if an RTC is not being used or TimeAlarms if one is. Without an RTC the timing will not be very accurate.

Have you tried my suggestion for testing the problem by changing the 20 secs to 23 secs. There is not much point going further until you are sure that the coincidence of the timers is the problem.

I have thought about what you said and want to say thank you for init ally coming up with this. Over lunch, I have been determining what 2 values would never coincide with one another over an infinite amount of time. at some point in time, 360 seconds and 23 seconds may eventually catch up and go off together. I am in my office, but will try for sure when I get home. Thank you for taking the time in responding to my post.

I still run into the same issue however. I have a relay on a PID that will go on or off depending on a particular ph level. This means it can go off without notice at any given second in the delay. There may be a possibility where that relay goes off at the same time i send data. Is there any work around this? Will the millis work around this issue as well?

HI, try two prime number, 1,3,5,7,11,13,17, 23

http://www.mathsisfun.com/prime_numbers.html

Tom...... :slight_smile:

It does not matter which 2 numbers you choose because at the time when the sum of the 2 intervals occurs they will, by definition, coincide.

An example. Choose 3 seconds and 23 seconds. After 3*23 seconds (one minute and 9 seconds) they will coincide, but you decide in which order to check whether the required time has passed so they will never be checked at exactly the same time.

There may be a possibility where that relay goes off at the same time i send data. Is there any work around this? Will the millis work around this issue as well?

That will never happen because the Arduino can only do one thing at a time. One of your events will always precede the other Only an interrupt can cause program execution to change unexpectedly and you can even prevent that by disabling interrupts temporarily.

Using millis() you decide when to check if the required time has passed so you are in full control.

Sorry if I wasn't clear enough.

The idea of changing 20 to 23 is just to do a quick test to see if the output changes. It will take a long time for 23 and 360 to coincide so the problem at 360 secs (and 720) should appear to go away. The point of this test is that if it does NOT work properly at 360 secs the problem is being caused by something different.

I never intended the change to 23 to be a permanent solution. It is just a quick way to save you wasting time pursuing the wrong permanent solution.

I don't think pairs of prime numbers can be a permanent solution either. Using one timer is a simple and reliable solution if the problem is the coincidence of the events using multiple timers.

...R

So last night I was able to test a few things. First, I set the time I read the text file to 23 seconds and I set the time I send the data to 367 seconds. I still am getting the relay from the event that’s 23 seconds go on and off randomly. I literally have nothing else in the code at the moment. I even discovered that when the relay did go on or off for a brief period, this was not at the exact time as when the 367 seconds were up and it was time to send the data. The relay just randomly went on and off during in the program. It lasts for the same amount of time, always. I also tried closing all browsers I had open thinking maybe a bug or something could be the culprit in clicking on the turn on button on my page. Even with the computer off and the Arduino running purely off of wall power, I still got a random relay on and off period.

Suggestion perhaps:
I think I might need to layers for security purposes. What about If I do click the button on my webpage to turn on the relay, then that signal should be interpreted from the Arduino and Arduino should send a “confirmation” stating in a msgbox “Are you sure you want to turn this on?” When that button is confirmed then the relay should be enabled or disabled. By having a sort of confirmation and extra layer to get through in order to turn off the relay, this may allow the relay to stay on and off when its supposed to. Does anyone else have any other ideas? I want to try the millis function as well. I do have an RTC DS1307 so I have a time to sync and reference. Any other possible reasons, and or solutions?

Using millis() you decide when to check if the required time has passed so you are in full control.

Using one timer is a simple and reliable solution if the problem is the coincidence of the events using multiple timers.

So it seems like the millis is my best option to test for full control. So even if I have an additional relay that goes on at 8 am and off every 8pm; the millis function has long enough numbers to account for 1000ms * 60 seconds * 60 minutes * 20 Hours? I think thats past the number limit. Can I use a long, double, or dint then? Or do I need to separate it to high byte low byte? How do I sync up the millis function to the RTC so I am not just getting a timer but I am getting a timer that goes on or of at a certain time

Why, oh WHY, did you confuse things by changing 360 to 367? When trying to figure out computer problems ONLY CHANGE ONE THING AT A TIME.

I can't figure from

I still am getting the relay from the event that’s 23 seconds go on and off randomly.

when, exactly, the random stuff happens.

From what you said previously it was only happening when the 20 and 360 coincided (but perhaps not on every occasion).

Now I presume they are not coinciding - although I suppose it's possible they overlap - 367 / 23 is 15.956 which is nearly an even 16. Whereas, if you had left it at 360 you would have got 360/23 = 15.65 which would give a bigger gap between events.

But, as I said, your description could be interpreted to mean it randomly happens at the 23 intervals or it randomly happens when the 23 and the 367 nearly coincide.

Try it with 23 and 360 or even with 29 and 360.

What I want to establish is whether I am correct to assume that the problem is caused by the coincidence of the two separate timer events. When we have a clear answer to that we can move forward.

And please post your latest version of the code.

...R