Pins A6 & A7 are analog input ONLY, don't know what effect (if any) pinModing them to OUTPUT will have.
756E6C:
Pins A6 & A7 are analog input ONLY, don't know what effect (if any) pinModing them to OUTPUT will have.
just read the specs...
Pin mapping
The analog pins can be used identically to the digital pins, using the aliases A0 (for analog input 0), A1, etc. For example, the code would look like this to set analog pin 0 to an output, and to set it HIGH:
pinMode(A0, OUTPUT);
digitalWrite(A0, HIGH);
Pullup resistorsThe analog pins also have pullup resistors, which work identically to pullup resistors on the digital pins. They are enabled by issuing a command such as
digitalWrite(A0, INPUT_PULLUP); // set pullup on analog pin 0
Be aware however that turning on a pullup will affect the values reported by analogRead().
@BulldogLowell:
So, I can set pin A7 as digital output and blink an LED with it?
756E6C:
@BulldogLowell:
So, I can set pin A7 as digital output and blink an LED with it?
what happened when you tried?
I woke up in an alternate universe, it was nice knowing you all.
Robin2:
Are you saying that the LED goes on for 3 seconds and then goes off for a very brief interval before going on for another 3 seconds?
If i use
if (loadState == true) { // There is load
if(Irms < 0.03) {
the LED flickers fast. Really fast. But so weak that i can see it only if it's nearly dark in the room.
And i did not think about baby steps - i just had the New Kids on the Block song in my head ![]()
MrGlasspoole:
the LED flickers fast. Really fast. But so weak that i can see it only if it's nearly dark in the room.
You have waited just the right amount of time to reply so that the thing has gone completely out of my head. I will bookmark this to look at it more closely this evening or tomorrow when I have more time.
I am still confused by your use of the variable name "loadState" because it does not actually seem to coincide with the state of the load. What does it really represent?
...R
loadState = if there is load.
If the sensor recognizes there is something (load) connected to the 230v outlet.
I also at the circuit:
MrGlasspoole:
loadState = if there is load.
If the sensor recognizes there is something (load) connected to the 230v outlet.
I still have not had / do not have time to study your code - but I have not forgotten.
I wonder if circuitActivated might be a more meaningful name than loadState - because it seems that the purpose of your code is to turn off the circuit (de-activate it) if there in no load. I think the line double Irms = checkPower.calcIrms(1480); is what actually determines if there is a load.
Please correct me if I have misunderstood your system.
IMHO having names for variables that properly describes their roles makes it much easier to spot silly mistakes in logic.
...R
checkPower.calcIrms(1480) is explained at the Emon Library like so:
The sketch reads approximately 106 samples of current in each cycle of mains at 50 Hz. 1480 samples therefore works out at 14 cycles of mains. That will give you a good average reading.
But since i'm not building a "Kill A Watt" it's not critical how much the sensor is reading.
The circuit just needs to detect if the table saw, router or sander is running to turn on the vac.
And without the on/off delay it works. But i can't figure out how to but that delay in there ![]()
MrGlasspoole:
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
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.
#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
Sorry still flickering. Brighter but still ![]()
MrGlasspoole:
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
I tried the exact code.
But i found the flicker part:
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
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.
#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
}
}
MrGlasspoole:
But i found the flicker part: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
Robin2:
What sort of switches are connected to pis 3 and 4?
Its a on/off/on switch.
Robin2:
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.
Robin2:
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:
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.
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.
#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
}
Glad to hear it is working. Perhaps using meaningful variable names helped?
The comment here is incorrect
} 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
