Dear learned crew,
I am developing a project which will prevent a 40A breaker from tripping by measuring the current being drawn, and thereby calculating how much capacity is available to use on an electric heating system. I am developing it in small parts, adding functionality to it at each stage. For reasons of speed I have tried to use integer maths rather than floating point maths, as recommended in the Arduino.cc reference section.
Today I appear to be having problems around the result of this sum:
int maxCurrent = ((tripCurrent - rmsCurrent)/1000); //use this value to CONSTRAIN the finalOutput below
tripCurrent and rmsCurrent are both unsigned integers, because each can be greater than 32,768, but never negative.
maxCurrent is a plain old integer, because its value will never exceed 40, but may have a brief negative value in reality (see serial monitor output below).
-
Please will someone indicate where I am going wrong, and/or suggest a correction, preferrably sticking to integer maths.
-
On a different subject, refering to the function at the end of my full code below, I tried to make a local variable
int SP = 60;
but that would not compile. This is strange, because a similar variableint MV = 61;
did compile.
What could be the reason for this apparent anomaly?
The results when rmsCurrent > tripCurrent are incorrect, as shown in the clip from the serial monitor, shown below:
14:03:26.201 -> Irms = 42.27
14:03:26.201 -> rmsCurrent = 42265
14:03:26.201 -> 40000
14:03:26.201 -> 42265
14:03:26.201 -> Output = 4
14:03:26.201 -> maxCurrent = 63 but (40000-42265)/1000 = -2 as an integer
14:03:26.255 -> Final Output = 4
14:03:26.255 ->
14:03:31.467 -> Irms = 16.60
14:03:31.467 -> rmsCurrent = 16604
14:03:31.514 -> 40000
14:03:31.514 -> 16604
14:03:31.514 -> Output = 4
14:03:31.514 -> maxCurrent = 23
14:03:31.514 -> Final Output = 4
For those who wish to view it, the full code is below. Some is commented out and some variables are given arbitrary values for testing purposes - they will be replaced with sensors indue course. Nothing is connected to analogue input 0, so the value of rmsCurrent floats around - also useful for proving the maths
#include "EmonLib.h" //external libraries have " ", internal have < >
EnergyMonitor emon1;
int output;
void setup()
{
Serial.begin (9600);
pinMode (A0,INPUT);
emon1.current(0,50);
}
void loop()
{
double Irms = emon1.calcIrms (1480);
unsigned int rmsCurrent = Irms * 1000;
Serial.print ("Irms = ");
Serial.println (Irms);
Serial.print ("rmsCurrent = ");
Serial.println (rmsCurrent);
const unsigned int tripCurrent = 40000; //40A trip value, *1000 to use integer maths
int maxCurrent = ((tripCurrent - rmsCurrent)/1000); //use this value to CONSTRAIN the finalOutput below
calcOutput (); //calls function to calc heating output before CONSTRAINing it
int finalOutput = constrain (output, 0 , maxCurrent);
Serial.println (tripCurrent);
Serial.println (rmsCurrent);
Serial.print ("Output = ");
Serial.println (output);
Serial.print ("maxCurrent = ");
Serial.println (maxCurrent);
Serial.print ("Final Output = ");
Serial.println (finalOutput);
Serial.println();
delay (5000);
}
void calcOutput ()
{
int setPoint = 60; //will be modulated by outsideTemp in future version
int MV = 61; //will be measured by DS18B20 sensor in future version
int deviation = (setPoint - MV); //could also be a negative number
int span = 50; //equals maxTempSetting (75C)minus minTempSetting (25C)
const int offset = 20; //equals 20% output when MV = setPoint
const int gain = 8; //equivalent to 12.5% proportional band
output = (gain * deviation *100 / span) + offset;
}