Go Down

Topic: If value is higher than for given time (Read 821 times) previous topic - next topic

Robin2

The circuit just needs to detect if the table saw, router or sander is running to turn on the vac.
I think that is the first time you have explained what you are trying to do. It makes everything a great deal clearer. I will look at your code in the morning.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Robin2

I have now had time to look at this. In the following version I have made a number of changes - including to the names of some variables. Apart from the  changed names I hope I have marked each change with a comment that begins // R2

I may have misunderstood your project and made a complete mess of the names, but they way I have done makes a lot more sense to me based on my present understanding.

When the logic became clearer it seemed to me necessary to update the variable noLoadTime after turning the vac circuit off. I suspect that that is the principal change needed to stop your flickering.

I have changed some references to millis() so they use currentMillis. That doesn't make any real difference. But there seems little point in creating currentMillis and then not using it. Reading the value from the variable will be marginally faster than calling the function.

Code: [Select]
#include <EmonLib.h>   // Get it here: github.com/openenergymonitor/EmonLib

/**************************************************************
* MISC SETUP                                                  *
**************************************************************/
#define DEBUG 1                      // Set to 1 for serial port output
const uint32_t SERIAL_BAUD = 9600;   // Set serial 0 speed
EnergyMonitor checkPower;            // Create an instance

const uint8_t vacCircuitRelay = 8;   // Relay circuit is connected to D8
const uint8_t SENSOR = A3; // ECS1030-L72 is connected to A3

// Define switch pins
const uint8_t pinS[] = {3, 4};                      // Array of used switch pins
uint8_t pinSCount = sizeof(pinS) / sizeof(pinS[0]); // Count used switch pins

// Define unused pins
const uint8_t pin[] = {2, 5, 6, 7, 9, 10, 11, 12, 13}; // Array of unused digital pins
const uint8_t pinA[] = {A0, A1, A2, A4, A5, A6, A7};   // Array of unused analog pins
uint8_t pinCount = sizeof(pin) / sizeof(pin[0]);       // Count unused digital pins
uint8_t pinACount = sizeof(pinA) / sizeof(pinA[0]);    // Count unused analog pins



unsigned long noLoadTime = 0;  // R2 MOVED
unsigned long loadRemoved = 0;
unsigned long turnOnDelay = 3000;
unsigned long turnOffDelay = 3000;
bool vacuumOn = false;



/**************************************************************
* SETUP                                                       *
**************************************************************/
void setup() {

    #ifdef DEBUG
     Serial.begin(SERIAL_BAUD); // Initialize serial communications
     while (!Serial) {;}        // Wait for serial port to connect
    #endif // END DEBUG
 
    for (uint8_t i = 0; i < pinCount; i++) {
     pinMode(pin[i], OUTPUT);    // Set unused digital pins as output
     digitalWrite(pin[i], LOW);  // Set unused digital pins state to low
    }

    for (uint8_t i = 0; i < pinACount; i++) {
     pinMode(pinA[i], OUTPUT);    // Set unused analog pins as output
     digitalWrite(pinA[i], LOW);  // Set unused analog pins state to low
    }

    for (uint8_t i = 0; i < pinSCount; i++) {
     pinMode(pinS[i], INPUT_PULLUP);  // Set switch pins as input and enable internal pull-up resistor
    }

    pinMode(vacCircuitRelay, OUTPUT);     // Set Relay pin (D8) as output
    digitalWrite(vacCircuitRelay, LOW);   // Set Relay to off
    vacuumOn = false;  // R2 NEW

    checkPower.current(SENSOR, 20);  // Sensor input pin (A3) and calibration
   
}

/**************************************************************
* AUTOMATIC LOOP                                              *
**************************************************************/


void automatic() {

    double Irms = checkPower.calcIrms(1480);   // Calculate Irms only
    unsigned long currentMillis = millis();

    if (vacuumOn == false) { // R2 no comment needed
            // R2 check if no appliance is running
        if(Irms < 0.03) {
            noLoadTime = currentMillis;
        }
            // R2 if appliance running for period
        if (currentMillis - noLoadTime >= turnOnDelay) {  // R2 use currentMillis
                                                        // If RMS is higher then 0.03A longer then 3 seconds
            digitalWrite(vacCircuitRelay, HIGH);                 // turn relay on
            vacuumOn = true;
        }

    }

    else  { // R2 if vacuum is ON
            // R2 check if no appliance is running
        if(Irms < 0.03) {
            loadRemoved = currentMillis;
         }
            // R2 turn off vac after interval
        if ((currentMillis - loadRemoved) >= turnOffDelay) {  // R2 use currentMillis
            digitalWrite(vacCircuitRelay, LOW);
            vacuumOn = false;
            noLoadTime =  currentMillis; // R2 NEW
        }
   
    }

    #ifdef DEBUG
        Serial.print(Irms*230.0);  // Apparent power
        Serial.print(" ");
        Serial.println(Irms);      // Irms
        Serial.println(currentMillis);
    #endif // END DEBUG

}

/**************************************************************
* MAIN LOOP                                                   *
**************************************************************/
void loop() {
 
    uint8_t switchState_1 = digitalRead(3);  // Read the switch value (pin D3)
    uint8_t switchState_2 = digitalRead(4);  // Read the switch value (pin D4)
 
    if(switchState_1 == LOW) {           // If pin 3 is low
        digitalWrite(vacCircuitRelay, HIGH);         // turn relay on
        vacuumOn = true;      // R2 CHANGED
    }
   
    else if (switchState_2 == LOW) {   // If pin 4 is low
        digitalWrite(vacCircuitRelay, LOW); // R2 NEW
        vacuumOn = false;
        automatic();                       // and run the automatic loop
    }
   
    else {
        digitalWrite(vacCircuitRelay, LOW);          // Turn relay off
        vacuumOn = false;                 // and reset load detection state
    }

    #ifdef DEBUG
        Serial.println(vacuumOn);      // Irms
    #endif // END DEBUG

}


...R
Two or three hours spent thinking and reading documentation solves most programming problems.

MrGlasspoole

Sorry still flickering. Brighter but still :(

Robin2

Sorry still flickering. Brighter but still :(
Are you using the EXACT code in Reply #31? If so please confirm that. If not then post the code you are actually using.

What steps have you taken to try to figure out the problem after studying the code in Reply #31 and my comments? I can't do everything from this distance.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

MrGlasspoole

#34
May 19, 2017, 11:55 pm Last Edit: May 20, 2017, 03:20 am by MrGlasspoole
I tried the exact code.

But i found the flicker part:
Code: [Select]
   else if (switchState_2 == LOW) {   // If pin 4 is low
        // digitalWrite(vacCircuitRelay, LOW); // <<<<< if there then FLICKER
        vacuumOn = false;
        automatic();                       // and run the automatic loop
    }

Sure automatic turns on and this part turns off at the same time.
Will test the rest now...

EDIT
Ok i changed some things.
I removed the boolean's and did connect the relay output pin to another pin (input) so i have feedback.
Everything works expect one thing:
If the sensor detects load and i remove pin 4 from ground (switchState_2) the relay goes off as it should.
But if i reconnect pin 4 to ground (low) the relay turns on instantaneously. The 3 seconds delay is missing.
I tried resetting "noLoadTime" with
Code: [Select]
noLoadTime = 0;
in all the places i can thing of but nothing works.
Printing "noLoadTime" shows, the time is running from the point when automatic stopped.

Code: [Select]
#include <EmonLib.h>   // Get it here: github.com/openenergymonitor/EmonLib

/**************************************************************
* MISC SETUP                                                  *
**************************************************************/
#define DEBUG 1                    // Set to 1 for serial port output
const uint32_t SERIAL_BAUD = 9600; // Set serial 0 speed
EnergyMonitor checkPower;          // Create an instance

const uint8_t vacRelay = 8;        // Relay circuit is connected to D8
const uint8_t SENSOR = A3;         // ECS1030-L72 is connected to A3

// Define switch pins
const uint8_t pinS[] = {3, 4};                      // Array of used switch pins
uint8_t pinSCount = sizeof(pinS) / sizeof(pinS[0]); // Count used switch pins

// Define unused pins
const uint8_t pin[] = {2, 5, 6, 9, 10, 11, 12, 13};  // Array of unused digital pins
const uint8_t pinA[] = {A0, A1, A2, A4, A5, A6, A7}; // Array of unused analog pins
uint8_t pinCount = sizeof(pin) / sizeof(pin[0]);     // Count unused digital pins
uint8_t pinACount = sizeof(pinA) / sizeof(pinA[0]);  // Count unused analog pins

/**************************************************************
* SETUP                                                       *
**************************************************************/
void setup() {

    #ifdef DEBUG
     Serial.begin(SERIAL_BAUD); // Initialize serial communications
     while (!Serial) {;}        // Wait for serial port to connect
    #endif // END DEBUG
 
    for (uint8_t i = 0; i < pinCount; i++) {
     pinMode(pin[i], OUTPUT);    // Set unused digital pins as output
     digitalWrite(pin[i], LOW);  // Set unused digital pins state to low
    }

    for (uint8_t i = 0; i < pinACount; i++) {
     pinMode(pinA[i], OUTPUT);    // Set unused analog pins as output
     digitalWrite(pinA[i], LOW);  // Set unused analog pins state to low
    }

    for (uint8_t i = 0; i < pinSCount; i++) {
     pinMode(pinS[i], INPUT_PULLUP);  // Set switch pins as input and enable internal pull-up resistor
    }

    pinMode(vacRelay, OUTPUT);   // Set Relay pin (D8) as output
    digitalWrite(vacRelay, LOW); // Set Relay to off

    checkPower.current(SENSOR, 20);  // Sensor input pin (A3) and calibration
   
}

/**************************************************************
* AUTOMATIC LOOP                                              *
**************************************************************/
unsigned long noLoadTime = 0;
unsigned long loadTime = 0;
unsigned long turnOnDelay = 3000;
unsigned long turnOffDelay = 3000;

void automatic() {

  double Irms = checkPower.calcIrms(1480); // Calculate Irms only
  uint8_t feedBack = digitalRead(7);       // Read feedback (pin D7)
  unsigned long currentMillis = millis();

  if(feedBack == LOW) { // Relay is off < feedback

    if(Irms < 0.03) {
      noLoadTime = currentMillis;
    }

    if ((currentMillis - noLoadTime) >= turnOnDelay) { // If RMS is higher then 0.03A longer then 3 seconds
      digitalWrite(vacRelay, HIGH);                    // turn relay on
    }

  } else { // Relay is on < feedback

    if(Irms > 0.03) {
      loadTime = currentMillis;
    }

    if ((currentMillis - loadTime) >= turnOffDelay) { // If RMS is lower then 0.03A longer then 3 seconds
      digitalWrite(vacRelay, LOW);                    // turn relay on
    }

  }

  #ifdef DEBUG
    Serial.print(Irms*230.0);  // Apparent power
    Serial.print(" ");
    Serial.println(Irms);      // Irms
    Serial.println(noLoadTime);
  #endif // END DEBUG

}

/**************************************************************
* MAIN LOOP                                                   *
**************************************************************/
void loop() {

  uint8_t switchState_1 = digitalRead(3);  // Read the switch value (pin D3)
  uint8_t switchState_2 = digitalRead(4);  // Read the switch value (pin D4)

  if(switchState_1 == LOW) {      // If pin 3 is low

    digitalWrite(vacRelay, HIGH); // turn relay on
    #ifdef DEBUG
      Serial.println("Manual");
    #endif // END DEBUG

  } else if (switchState_2 == LOW) { // If pin 4 is low

    automatic();                     // run the automatic loop
    #ifdef DEBUG
      Serial.println("Automatic");
    #endif // END DEBUG

  } else {

    digitalWrite(vacRelay, LOW); // Turn relay off
    #ifdef DEBUG
      Serial.println("Off");
    #endif // END DEBUG

  }

}

Robin2

#35
May 20, 2017, 08:36 am Last Edit: May 20, 2017, 08:38 am by Robin2
But i found the flicker part:
Code: [Select]
  else if (switchState_2 == LOW) {   // If pin 4 is low
        // digitalWrite(vacCircuitRelay, LOW); // <<<<< if there then FLICKER
        vacuumOn = false;
        automatic();                       // and run the automatic loop
    }

Sure automatic turns on and this part turns off at the same time.
Will test the rest now...

Your IF logic is very confused. I had not studied that because I assumed the problem was elsewhere. What sort of switches are connected to pis 3 and 4? This is another example where meaningful variable names (rather than switchState) would make the logic much clearer and might have avoided the problem in the first place.

I suspect if you sort that out the version of automatic() that I suggested will work.

I have no idea why you thought that removing the booleans would help. That sounds like the scatter-gun approach to debugging - Do something! Anything!

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

MrGlasspoole

What sort of switches are connected to pis 3 and 4?
Its a on/off/on switch.

I suspect if you sort that out the version of automatic() that I suggested will work.
Sure that was the first thing i tested (removing that part in switchState_2) in your code - but it does not work.

I have no idea why you thought that removing the booleans would help.
The thing with booleans is that they don't really tell you the real state and that is something i don't understand in most stuff others are doing.
Why does nobody look for the state of a pin with another pin (feedback - if something is on/off)?

With the words from somebody else:
Quote
Reading the internal register will always return for you what the controller is trying to put on the pin, not the actual pin value. If you are doing this to validate that the pin is really high, this will not confirm it to you, because maybe there is a short circuit on the high pin from the external circuit, the best way is to create a feedback through another pin; configure another pin as input, and connect the output pin to the new input pin, and read its value.
But what i really don't get is why "noLoadTime = 0" does not work.

MrGlasspoole

GOT IT WORKING

No need for boolean or feedback and i don't know why it took me so long.
Now if i look at it it's not complicated.

Code: [Select]
#include <EmonLib.h>   // Get it here: github.com/openenergymonitor/EmonLib

/**************************************************************
* MISC SETUP                                                  *
**************************************************************/
#define DEBUG 1                    // Set to 1 for serial port output
const uint32_t SERIAL_BAUD = 9600; // Set serial 0 speed
EnergyMonitor checkPower;          // Create an instance

const uint8_t vacRelay = 8;        // Relay circuit is connected to D8
const uint8_t SENSOR = A3;         // ECS1030-L72 is connected to A3

// Define switch pins
const uint8_t pinS[] = {3, 4};                      // Array of used switch pins
uint8_t pinSCount = sizeof(pinS) / sizeof(pinS[0]); // Count used switch pins

// Define unused pins
const uint8_t pin[] = {2, 5, 6, 7, 9, 10, 11, 12, 13};  // Array of unused digital pins
const uint8_t pinA[] = {A0, A1, A2, A4, A5, A6, A7};    // Array of unused analog pins
uint8_t pinCount = sizeof(pin) / sizeof(pin[0]);        // Count unused digital pins
uint8_t pinACount = sizeof(pinA) / sizeof(pinA[0]);     // Count unused analog pins

/**************************************************************
* SETUP                                                       *
**************************************************************/
void setup() {

    #ifdef DEBUG
     Serial.begin(SERIAL_BAUD); // Initialize serial communications
     while (!Serial) {;}        // Wait for serial port to connect
    #endif // END DEBUG
 
    for (uint8_t i = 0; i < pinCount; i++) {
     pinMode(pin[i], OUTPUT);    // Set unused digital pins as output
     digitalWrite(pin[i], LOW);  // Set unused digital pins state to low
    }

    for (uint8_t i = 0; i < pinACount; i++) {
     pinMode(pinA[i], OUTPUT);    // Set unused analog pins as output
     digitalWrite(pinA[i], LOW);  // Set unused analog pins state to low
    }

    for (uint8_t i = 0; i < pinSCount; i++) {
     pinMode(pinS[i], INPUT_PULLUP);  // Set switch pins as input and enable internal pull-up resistor
    }

    pinMode(vacRelay, OUTPUT);   // Set Relay pin (D8) as output
    digitalWrite(vacRelay, LOW); // Set Relay to off

    checkPower.current(SENSOR, 20);  // Sensor input pin (A3) and calibration
   
}

/**************************************************************
* AUTOMATIC LOOP                                              *
**************************************************************/
float Irms;
unsigned long noLoadTime = 0;
unsigned long loadTime = 0;
unsigned long turnOnDelay = 3000;
unsigned long turnOffDelay = 3000;

void automatic() {

  unsigned long currentMillis = millis();

  if(Irms < 0.03) {
    noLoadTime = currentMillis;
  }

  if ((currentMillis - noLoadTime) >= turnOnDelay) { // If RMS is higher then 0.03A longer then 3 seconds 
    digitalWrite(vacRelay, HIGH);                    // turn relay on
  }

  if(Irms > 0.03) {
    loadTime = currentMillis;
  }

  if ((currentMillis - loadTime) >= turnOffDelay) { // If RMS is lower then 0.03A longer then 3 seconds
    digitalWrite(vacRelay, LOW);                    // turn relay off
  }

}

/**************************************************************
* MAIN LOOP                                                   *
**************************************************************/
void loop() {

  Irms = checkPower.calcIrms(1480);            // Calculate Irms only
  uint8_t switchPositionOn = digitalRead(3);   // Read the switch value (pin D3)
  uint8_t switchPositionAuto = digitalRead(4); // Read the switch value (pin D4)

  if(switchPositionOn == LOW) {   // If pin 3 is low

    digitalWrite(vacRelay, HIGH); // turn relay on
    #ifdef DEBUG
      Serial.println("Mode: On");
    #endif // END DEBUG

  } else if (switchPositionAuto == LOW) { // If pin 4 is low
   
    automatic();                          // run the automatic loop
    #ifdef DEBUG
      Serial.println("Mode: Automatic");
    #endif // END DEBUG

  } else {

    digitalWrite(vacRelay, LOW); // Turn relay off
    noLoadTime = millis();       // and set noLoadTime
    #ifdef DEBUG
      Serial.println("Mode: Off");
    #endif // END DEBUG

  }
 
  #ifdef DEBUG
    Serial.print(Irms*230.0);  // Apparent power
    Serial.print(" ");
    Serial.println(Irms);      // Irms
  #endif // END DEBUG

}

Robin2

Glad to hear it is working. Perhaps using meaningful variable names helped?

The comment here is incorrect
Code: [Select]
} else if (switchPositionAuto == LOW) { // If pin 4 is low

It should be // if pin3 is HIGH and pin 4 is LOW

It would be even better if it said // if ON switch is OFF (high) and AUTO switch is ON (low)

And that suggests to me that it would be more meaningful to use constantVacSwitch rather than switchPositionOn and autoVacSwitch instead of switchPositionAuto.

Using switchPositionOn and switchPositionAuto conveys the notion of a single multi-way switch - for example a rotary switch.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

Go Up