Good afternoon good and helpful people of the web.
I have a problem that I have been struggling to correct this afternoon. The program should read an analog input on A0 (which it shows when I open the Serial Monitor). It should then switch ON one or more of three leds when the ADC conversion integer (0-1023) exceeds a set value.
My problem is that I cannot seem to get the hysteresis to work, and the outputs will flicker if the input varies around the switch point. Please may I have some help/pointers to make this work.
The relevant code is below:
//The electrical supply to this flat trips at about 40A, and cannot be upgraded easily. This code is intended to shed low priority electrical
//loads in favour of keeping on the higher priority ones. The Arduino will take several readings of an analogue input at regular time intervals using
//millis(). These readings (called samples here) represent the electrical loadings of all appliances except the heating (6kW electric boiler).
//Thus when appliance loads exceed approx. 4kW we will restrict or inhibit heating to keep total power load below 10kW (40A).
int ctPin = A0; //pin connected to current transformer (CT)
int currentCurrent = 0; //present value of current measurement
int sampleCount = 0; //number of current readings taken. Used to calc average
int total = 0; //the cumulative total of several current samples
int count = 0; //the number of samples to average
int averageCurrent = 0; //the result of averaging
unsigned long millisLast = 0; //Time of last reading
unsigned long interval = 0; //Duration since last reading taken
unsigned long samplePeriod = 100; //Period between taking current readings in milliseconds
const int relayStage1 = 10; //minimum load shedding relay
const int relayStage2 = 11; //medium load shedding relay
const int relayStage3 = 12; //maximum load shedding relay
const int resetDetectTrip = 2; //pushbutton used in diagnostics
void setup()
{
Serial.begin(9600); //start Serial in case we need to print debugging info
pinMode (resetDetectTrip, INPUT); //resets the time interval since peak current was detected
pinMode (ctPin, INPUT); //pin mode to allow analogue readings
pinMode (relayStage1, OUTPUT);//pin mode for outputs to relays
pinMode (relayStage2, OUTPUT);
pinMode (relayStage3, OUTPUT);
millisLast = millis(); //This is so that interval is relative to the time now
}
void loop()
{
interval = millis() - millisLast; //time interval since last reading taken
if (interval >= samplePeriod) //if true it's time to take a reading of current
{
currentCurrent = analogRead(ctPin); //read the CT input and return the value as an integer 0 - 1023
total = total + currentCurrent; //Each new sample added to a starting total of zero
count ++; //increment count value to use for average value later
}
if (count >= 10)
{
averageCurrent = total / count; //used in the decision making code later
Serial.println(averageCurrent);
total = 0; //reset ready for the next samples
count = 0; //reset ready for the next samples too
}
loadReduction(); //call function to turn off electrical items based on the values of
//averageCurrent and userPreferences and otherModifiers which haven't been coded yet!
}
void loadReduction() //function to energise relays through Arduino outputs, add hysteresis, and
//take the decisions as to what stays on and what is turned off.
//There are 3 discrete load reducing settings and actions.
{
static int hysteresis3 = 0;
static int hysteresis2 = 0;
static int hysteresis1 = 0; //set all hysteresis values to zero initially
int actionStage3 = 1000; //Empirical setting, the highest load reduction action required.
int actionStage2 = 600;
int actionStage1 = 300;
if (relayStage3 == HIGH) //each action has its own hysteresis value
{
Serial.println("relay 3 is ON");
hysteresis3 = 50;
}
if (relayStage2 == HIGH)
{
hysteresis2 = 40;
}
if (relayStage1 == HIGH)
{
hysteresis1 = 30;
}
if (averageCurrent > (actionStage3 - hysteresis3)) //hysteresis3 is 0 on first test, 30 if relay already energised
//Used to prevent rapid on-off switching of outputs
{
digitalWrite (relayStage3, HIGH); //Energises outputs to shed the maximum load
}
else digitalWrite (relayStage3, LOW); //de-energises relay and returns hysteresis to zero
if (averageCurrent > (actionStage2 - hysteresis2)) //hysteresis is 0 on first test, 20 if relay already energised
//Used to prevent rapid on-off switching of outputs
{
digitalWrite (relayStage2, HIGH); //Energises outputs to shed a medium load
}
else digitalWrite (relayStage2, LOW);
if (averageCurrent > (actionStage1 - hysteresis1)) //hysteresis is 0 on first test, 10 if relay already energised
//Used to prevent rapid on-off switching of outputs
{
digitalWrite (relayStage1, HIGH); //Energises outputs to shed the minimum load
}
else digitalWrite (relayStage1, LOW);
}
void detectTripValue() //function to record the maximum current measured,
//useful to adjust loadReduction switch points in case of nuisance trips
//Record the time interval since the last maxValue was measured
{ //DO NOT reset time interval at setup()!!
//Reset time interval only after pushbutton is pressed
}
Regards, GM