Hardware doesn't function on command from app

Greetings

I have stared at this until my eyes are crossed and can’t figure it out, so I’m hoping one of you actual experts can help me out. This code runs a greenhouse, monitoring three DHT22 temp sensors. If the average temp (taveF) exceeds a set point (FanOnTemp), it turns on a fan and opens a louver. If it exceeds another set point (MIsterOnSetPt) it turns on a set of misters for (misterRunTime) minutes, with a pause of (misterPause) minutes in between mister-ings. There are two irrigation systems (Irr1 and Irr2); a pair of lines that spray water on two different sets of plants. And anytime the mister, Irr1, or Irr2 are turned on, a pump turns on to draw water from a pair of rain barrels.

The code is supposed to do two main things: 1) run autonomously, performing functions to control the temperature, and 2) respond to the Blynk app to turn the misters, Irr1, or Irr2 on on command. It also sends Tweets to my wife’s phone if the average temperature goes out of acceptable limits.

Everything works great, with one exception. There are three buttons on the Blynk app that are supposed to turn on the misters, Irr1, or Irr2. I have them set up to read a value into a variable when pressed, and then send an “off” to the button on the phone. The buttons are set to “switch” so that you press them and they light up ON, and then they turn OFF on command from the hardware to confirm that the hardware received the command.

Problem is - they turn off as commanded, but then nothing happens. The misters, Irr1, or Irr2 don’t actually turn on. The hardware is controlled with an eight-relay board, and is working fine. It comes on when commanded by the hardware via the autonomous monitoring as I’ve described above. It just won’t turn on when I press the button in the app.

So I can use your help - what am I missing?

This is running on a Sparkfun Redboard (UNO clone), with a CC3000 shield. Arduino IDE build is 1.6.3, and the CC3000’s firmware is v. 1.14. Blynk is the latest version. The command buttons on the Blynk app are set to 0 at OFF and to send 255 at ON.

I have written the code to run from three timers. One reads the temperature sensors once per second. Another checks the Blynk connection every five minutes and reconnects if necessary. Another runs a one-minute timer for timing the misters and irrigation systems.

Thanks in advance,
Q_Mech


// -----------
// Initialize iteration variables

//Defaults
float t1 = 22;                          //Top temp sensor initialize
float t2 = 22;                          //Middle temp sensor initialize
float t3 = 22;                          //Bottom temp sensor initialize
int t1F=70;                             //Top temp in F
int t2F=70;                             //Mid temp in F
int t3F=70;                             //Btm temp in F
int taveF = 60;                         //Average temperature
int FanOnTemp = 80;                     //set point for turning the fan on
int FanOffTemp = 75;                    //Fan set point for turning the fan off
int misterRunTime = 5;                  //how long to run the misters, in minutes
int misterPause =30;                    //how long to wait between mistings, in minutes
int MisterOnSetPt = 90;                 //set point for turning the Mister system on

//Controls
int MistersOn=0;                        //for running misters from Blynk commands
int Irr1On = 0;                         //for running Irr1 from Blynk commands
int Irr2On = 0;                         //for running Irr2 from Blynk commands
byte PumpNeeded1 = 0;                   //used to turn on pump when needed for misters
byte PumpNeeded2 = 0;                   //used to turn on pump when needed for Irr1
byte PumpNeeded3 = 0;                   //used to turn on pump when needed for Irr2

//Pins
int louverPin = 3;                      //digital pin to run the louver
int mainfanPin = 4;                     //digital pin to run the main fan
int pumpPin = 5;                        //digital pin to run the 110V outlet for the pump
int misterPin = 9;                      //digital pin to run the mister solenoid
int irr1Pin = A5;                       //digital pin to run the irr1 solenoid
int irr2Pin = A0;                       //digital pin to run the irr2 solenoid

//Timing
int Irr1RunTime = 5;                    //time in minutes to run Irr1
int Irr2RunTime = 5;                    //time in minutes to run Irr2
int loopCount=0;                        //needed to query temps at regular intervals
int MisterTimer1=0;                     //minutes since last misting
int MisterTimer2=0;                     //run time for misters operation
int Irr1Timer=0;                        //run time for Irr1 operation
int Irr2Timer=0;                        //run time for Irr2 operation

//Connection
boolean checkBlynk = true;              //is GH connected to Blynk server?

// -----------
// Initialize connection to internet using CC3300 shield

#define BLYNK_PRINT Serial        // Comment this out to disable prints and save space
// #define BLYNK_NO_BUILTIN          // Disable built-in analog & digital pin operations
// #define BLYNK_NO_FLOAT            // Disable float operations
#define ADAFRUIT_CC3000_IRQ   2   // Needs to be an interrupt pin (D2/D3)
#define ADAFRUIT_CC3000_VBAT  7   // Can be any digital pin
#define ADAFRUIT_CC3000_CS    10  // Preferred is pin 10 on Uno

#include <SPI.h>
#include <Adafruit_CC3000.h>
#include <BlynkSimpleCC3000.h>
#include <SimpleTimer.h>

// -----------
// Initialize Blynk

[wifi and Blynk setup redacted]

SimpleTimer Timer;

// -----------
// Initialize DH22 sensors

#include <DHT.h> 
DHT dht1(A2, DHT22); //TOP sensor
DHT dht2(A3, DHT22); //MID sensor
DHT dht3(A1, DHT22); //BTM sensor

void setup() 
  {
  Serial.begin(115200);  //comment out once sketch is working properly
  
  // -----------
  // Set up digital output lines
  pinMode(3, OUTPUT);   //Louver, GRN/WHT wire
  pinMode(4, OUTPUT);   //Fan GRN wire
  pinMode(5, OUTPUT);   //Pump YLW wire
  pinMode(6, OUTPUT);   //(not used) ORN/WHT wire
  pinMode(9, OUTPUT);   //Misters ORN wire
  pinMode(A5, OUTPUT);  //Irr1 BLU/WHY wire
  pinMode(A0, OUTPUT);  //Irr2 BLU wire
  pinMode(A4, OUTPUT);  //(not used) GRN wire

  // -----------
  // Setup delay - allow board to settle
  delay(5000);
        
  // -----------
  // Set up Blynk
    Blynk.begin(auth, ssid, pass, wifi_sec);
      while (!Blynk.connect()) 
      { 
       //Wait until connected
      }
    // Tweet a message announcing startup    
    Blynk.tweet("Connected to Blynk");

  //Turn Blynk LEDS off, write default values
    Blynk.virtualWrite(V6,0);
    Blynk.virtualWrite(V7,0);
    Blynk.virtualWrite(V8,0);
    Blynk.virtualWrite(V9,0);
    Blynk.virtualWrite(V10,0);
    Blynk.virtualWrite(V21,0);
    Blynk.virtualWrite(V4,FanOnTemp);
    Blynk.virtualWrite(V5,FanOffTemp);
    Blynk.virtualWrite(V11,0);
    Blynk.virtualWrite(V12,0);
    Blynk.virtualWrite(V14,0);
    Blynk.virtualWrite(V15,misterRunTime);
    Blynk.virtualWrite(V21,0);    
  
  // -----------
  // Start up DH22 Temp/Humidity sensors  
  dht1.begin(); 
  dht2.begin();
  dht3.begin(); 

  // -----------
  // Run the main body of the sketch at half-second intervals for stability
  Timer.setInterval(1000, MainLoop); 
  
  // -----------
  // Set up one-minute timer
  Timer.setInterval(60000, minuteTimer);

  // -----------
  // Set up five-minute timer
  Timer.setInterval(300000, connectCheck);
  }

void loop()
  {
  // -----------
  // Start SimpleTimer
  Timer.run();
  }

void minuteTimer()
  {
  // -----------
  // Add one to minute counter once every minute (60,000 ms)
    MisterTimer1=MisterTimer1+1;
    MisterTimer2=MisterTimer2+1;
    Irr1Timer=Irr1Timer+1;
    Irr2Timer=Irr2Timer+1;
  }
  
void MainLoop()
  {
    // -----------
    // Iterate Blynk
    Blynk.run();
  
    // -----------
    // Operate the DH22 sensors
    if (loopCount>10)
      {
       TempRead();
       loopCount=0;
      } else 
       {
         loopCount=loopCount+1;
       }
  
    // -----------
    // Temperature-based control:
    // Control fan and louver
    if (taveF>FanOnTemp) // If average temp exceeds set point, turn on fan and louver
      { 
      digitalWrite(louverPin,HIGH);
      digitalWrite(mainfanPin,HIGH);
      Blynk.virtualWrite(V6,255);  //inform Blynk that the Fan is on
      Blynk.virtualWrite(V7,255);  //inform Blynk that the Louver is on
      } else
        {
         if (taveF<FanOffTemp) // If average temp drops below lower set point, turn off fan and louver
          {
           digitalWrite(louverPin,LOW);
           digitalWrite(mainfanPin,LOW);
           Blynk.virtualWrite(V6,0);  //inform Blynk that the Fan is off
           Blynk.virtualWrite(V7,0);  //inform Blynk that the Louver is off    
          } 
        }

    // -----------
    // Operate the misters if average T is over the set point
    // If this is the first time over the set point (MisterToggle=0), then
    // Run misters immediately then start 30-min timer for repeated mistings
    // When the temperature drops below the set point, set MisterToggle back to zero
    if (taveF>MisterOnSetPt) // if temp is above the mister set point...
      {
       if (MisterTimer1>misterPause) // ...and it has been at least misterPause minutes since the last misting
         { 
          MistersOn=1;          //trigger the misters 
          MisterTimer1=0;            // reset the count of number of minutes since last misting   
         } 
       }


    // -----------
    // If Misters are triggered, turn them on for MisterRunTime length of time
    if (MistersOn>0)
      {
        if (MisterTimer1<misterRunTime)   //If the misters are triggered but the timer hasn't run out..
          {
            digitalWrite(misterPin,HIGH);
            PumpNeeded1=1;
            Blynk.virtualWrite(V8,255);   //inform Blynk that the Misters are ON
          } else                          // If the timer has run out, turn misters off
            {
            digitalWrite(misterPin,LOW);
            PumpNeeded1=0;
            Blynk.virtualWrite(V8,0);     //inform Blynk that the Misters are OFF
            }
      } else
        {
          MisterTimer1=0; //keep resetting MisterTimer1 to zero if MistersOn isn't triggered
        }


    // -----------
    // If Irr1 is triggered, turn them on for Irr1RunTime length of time
    if (Irr1On>0)
      {
        if (Irr1Timer<Irr1RunTime)   //If Irr1 is triggered but the timer hasn't run out..
          {
            digitalWrite(irr1Pin,HIGH);
            PumpNeeded2=1;
            Blynk.virtualWrite(V9,255);   //inform Blynk that Irr1 is ON
          } else                          // If the timer has run out, turn Irr1 off
            {
            digitalWrite(irr1Pin,LOW);
            PumpNeeded2=0;
            Blynk.virtualWrite(V9,0);     //inform Blynk that Irr1 is OFF
            }
      } else
        {
          Irr1Timer=0; //keep resetting Irr1Timer to zero if Irr1On isn't triggered
        }

    // -----------
    // If Irr2 is triggered, turn them on for Irr2RunTime length of time
    if (Irr2On>0)
      {
        if (Irr2Timer<Irr2RunTime)   //If Irr2 is triggered but the timer hasn't run out..
          {
            digitalWrite(irr2Pin,HIGH);
            PumpNeeded3=1;
            Blynk.virtualWrite(V10,255);   //inform Blynk that Irr2 is ON
          } else                          // If the timer has run out, turn Irr2 off
            {
            digitalWrite(irr2Pin,LOW);
            PumpNeeded3=0;
            Blynk.virtualWrite(V10,0);     //inform Blynk that the Irr2 is OFF
            }
      } else
        {
          Irr2Timer=0; //keep resetting Irr2Timer to zero if Irr2On isn't triggered
        }
        
    // -----------
    // If Misters, Irr1, or Irr2 are on, turn on the pump
    if ((PumpNeeded1+PumpNeeded2+PumpNeeded3)>0)
    {
      digitalWrite(pumpPin,HIGH);
      Blynk.virtualWrite(V21,255);  //inform Blynk that the pump is ON
    } else
      {
        digitalWrite(pumpPin,LOW);
        Blynk.virtualWrite(V21,0);  //inform Blynk that the pump is OFF      
      } 
             
    // -----------
    // Send a tweet if TaveF goes out of bounds
    if (taveF>95)
      {
      Blynk.tweet("Greenhouse is over 95 degrees F!");
      }  

    if (taveF<50)
      {
      Blynk.tweet("Greenhouse is under 50 degrees F!");
      } 
  }

void TempRead()
  {
    // Read DHTs and push to Blynk app
    // Reading temperature or humidity takes about 250 milliseconds! 
    // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
    // float h1 = dht1.readHumidity();
    float t1 = dht1.readTemperature(); 
    // float h2 = dht2.readHumidity(); 
    float t2 = dht2.readTemperature();   
    // float h3 = dht3.readHumidity(); 
    float t3 = dht3.readTemperature();  
    t1F=(int)(1.8*t1)+32;
    t2F=(int)(1.8*t2)+32;
    t3F=(int)(1.8*t3)+32; 
    taveF = (int)((t1F+t2F+t3F)/3);
    Blynk.virtualWrite(V0, t1F); 
    Blynk.virtualWrite(V1, t2F);
    Blynk.virtualWrite(V2, t3F);
    Blynk.virtualWrite(V3, taveF);

    Serial.print("Top temp = ");  //comment out once sketch is working properly
    Serial.println(t1F);
    Serial.print("Mid temp = ");
    Serial.println(t2F);
    Serial.print("Btm temp = ");
    Serial.println(t3F);
    Serial.print("Average = ");
    Serial.println(taveF);                
  }

void connectCheck()
  {
    boolean checkBlynk = Blynk.connected();
    if (checkBlynk = false)  //check Blynk connection. If absent, reconnect
      {
        Blynk.connect(); //Try to reconnect, but don't stop running the greenhouse       
        Blynk.tweet("Reconnection attempt"); // Tweet a message announcing startup  
      }
  }

// -----------
// Set up calls for when values are entered on the Blynk app

BLYNK_WRITE(V4) //read Fan On setpoint from Blynk
  {
  int FanOnTemp = param.asInt(); // assigning incoming value from pin V4 to a variable
  }

BLYNK_WRITE(V5) //read Fan Off setpoint from Blynk
  {
  int FanOffTemp = param.asInt(); // assigning incoming value from pin V5 to a variable
  }

BLYNK_WRITE(V11) //read Mister control from Blynk
  {
  int MistersOn = param.asInt(); // assigning incoming value from pin V11 to a variable
  Blynk.virtualWrite(V11,0);   // once the hardware has received the command, reset the app button to "OFF"
                               // set button to "switch" - it will turn off to confirm the command was received
  }

BLYNK_WRITE(V12) //run irr1 when control button is pressed on Blynk
  {
  int Irr1On = param.asInt(); // assigning incoming value from pin V12 to a variable
  Blynk.virtualWrite(V12,0);   // once the hardware has received the command, reset the app button to "OFF"
                               // set button to "switch" - it will turn off to confirm the command was received
  }

BLYNK_WRITE(V14) //run irr2 when control button is pressed on Blynk
  {
  int Irr2On = param.asInt(); // assigning incoming value from pin V14 to a variable
  Blynk.virtualWrite(V14,0);   // once the hardware has received the command, reset the app button to "OFF"
                               // set button to "switch" - it will turn off to confirm the command was received
  }

BLYNK_WRITE(V15) //read Mister run time control from Blynk
  {
  int misterRunTime = param.asInt(); // assigning incoming value from pin V15 to a variable
  }

BLYNK_WRITE(V16) //read Irr1 time from Blynk
  {
  int Irr1RunTime = param.asInt(); // assigning incoming value from pin V16 to a variable
  }

BLYNK_WRITE(V17) //read Irr2 time from Blynk
  {
  int Irr2RunTime = param.asInt(); // assigning incoming value from pin V17 to a variable
  }

BLYNK_WRITE(V18) //run irr1 when Time Input widget activates on Blynk
  {
  int Irr1On = param.asInt(); // assigning incoming value from pin V18 to a variable
  }

BLYNK_WRITE(V19) //run irr2 when Time Input widget activates on Blynk
  {
  int Irr2On = param.asInt(); // assigning incoming value from pin V19 to a variable
  }

BLYNK_WRITE(V20) //read mister set temp
  {
  int MisterOnSetPt = param.asInt(); // assigning incoming value from pin V19 to a variable
  }

I just noticed - it isn’t sending Tweets, either. It should send one whenever it starts up, at least.

It does send the four temperature readings (t1F, t2F, t3F, and taveF) correctly, and lights up the LEDs in the Blynk app whenever the fan and louver come on automatically.

I see at least one = that should be ==
Review and update us.

I found and fixed this, on line 340… Any others?

    if (checkBlynk == false)  //check Blynk connection. If absent, reconnect

I also found a subtle but important error. An argument in the Misters Blynk code is wrong:

if (MisterTimer1<misterRunTime)   //If the misters are triggered but the timer hasn't run out..

That should be MisterTimer2, not 1. 2 keeps time for the amount of time the misters are running, and 1 keeps time for the 30-minute lag between using the misters. I thought I had it there, but correcting the error had no effect.

I just noticed that NONE of my app widgets are sending data to the hardware. I can read data from hardware --> app just fine, but moving sliders and pressing buttons in the app has no effect.

Am I using BLYNK_WRITE incorrectly?

Not really, you send HIGH (1) from the app and then you immediately send a LOW (0) with your virtualWrite’s. When I read your OP I wondered how you were switching the buttons off. Never tried it but fix the next part and see how you go.

Your other major bug looks to be the definition of lots of variables in your BLYNK_WRITE() functions. These should almost certainly be global, not local, variables. Unless you are just collecting the data for the fun of it.

1 Like

That would explain it. I’m confused, though (and new to C and Arduino IDE). I thought if you declared variables above setup then they were global. I declared them all there thinking that’s how it worked.

Oh, wait a second (light bulb comes on!)… I see it. When I put the “int” in front of those variables in the functions, it re-defined them and left the values stranded as local variables. Bingo. Changing it and trying it out now…

1 Like

It works! Brilliant, thank you!!

That was my Newb Mistake of the Day. The rest of my day will be filled with professional masterworks. Or something.

So now the hardware responds to the app. I ran the misters a couple of times and they started and stopped as intended. The new problem is that it crashed both times when it turned OFF the misters. Perhaps I need to add a slight pause between writing to the digital pin and writing to Blynk…? Or perhaps the hardware isn’t communicating with the Blynk server while the mister is running, and the server dropped the connection…?

But the second helping of good news is that when it crashed, it reconnected with Blynk and worked correctly.

My eyes crossed just glancing at your code… so all I can do is make a suggestion :slight_smile:

Adding a Blynk.run(); somewhere in the middle of a longish loop should keep Blink communication going.

1 Like

That’s helpful, thank you. I’ll give it a go.