Fix/Update/Add

Add: ResetEnergy function with datetime
Update: led Class
Fix: many typo, errors
This commit is contained in:
zelogik 2021-01-19 11:00:09 +01:00 committed by GitHub
parent c1d076fbec
commit 7618e82c00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -2,6 +2,7 @@
#include <PZEM004Tv30.h> #include <PZEM004Tv30.h>
#include "wiring_private.h" // pinPeripheral() function #include "wiring_private.h" // pinPeripheral() function
#include <TimeLib.h>
//Sercom Stuff //Sercom Stuff
#define PIN_SERIAL2_RX (34ul) // Pin description number for PIO_SERCOM on D12 (34ul) #define PIN_SERIAL2_RX (34ul) // Pin description number for PIO_SERCOM on D12 (34ul)
@ -19,83 +20,159 @@ void SERCOM1_Handler()
#define PZEM004_NO_SWSERIAL #define PZEM004_NO_SWSERIAL
#define PZEM_DEFAULT_ADDR 0xF8 #define PZEM_DEFAULT_ADDR 0xF8
const uint8_t physicalCount = 6; // voltage,current,power_factor,power,energy,frequency
//knx stuff //knx stuff
#define goReset knx.getGroupObject(1) #define goReset knx.getGroupObject(1)
#define goDateTime knx.getGroupObject(2) #define goDateTime knx.getGroupObject(2)
#define goProgMode knx.getGroupObject(9) #define goProgMode knx.getGroupObject(9)
// Global Const
const uint16_t ets_timePeriod[7] = {0, 1, 5, 15, 1 * 60, 5 * 60, 15 * 60};
const uint8_t ets_startupTimeout[7] = {0, 1, 2, 3, 4, 5, 6}; const uint8_t ets_startupTimeout[7] = {0, 1, 2, 3, 4, 5, 6};
const int ets_timePeriod[7] = {0, 1, 5, 15, 1 * 60, 5 * 60, 15 * 60};
const uint8_t ets_percentCycle[6] = {0, 5, 10, 15, 20, 30}; //need knxprod update... ? const uint8_t ets_percentCycle[6] = {0, 5, 10, 15, 20, 30}; //need knxprod update... ?
int percentCycle = 0; // better to define a global or read knx.paramByte each time... ? const uint8_t ledPin = LED_BUILTIN;// the number of the LED pin
unsigned long timePeriod = 0; // same here, const uint8_t physicalCount = 6; // voltage,current,power_factor,power,energy,frequency
uint8_t resetFlag = 0; // and here...
// Global Variable
uint8_t percentCycle = 0; // better to define a global or read knx.paramByte each time... ?
uint32_t timePeriod = 0; // same here,
uint8_t resetPeriod = 0; //same here ...
uint8_t resetEnergy = 0; // and here... disabled/day/week/month
bool progMode = true; bool progMode = true;
// Issue on https://github.com/mandulaj/PZEM-004T-v30/issues/43 // Issue on https://github.com/mandulaj/PZEM-004T-v30/issues/43
PZEM004Tv30 pzem(Serial2, PZEM_DEFAULT_ADDR); PZEM004Tv30 pzem(Serial2, PZEM_DEFAULT_ADDR);
struct Physical { struct Physical {
void init(uint8_t GOaddr, Dpt type_dpt){ void init(uint8_t GOaddr, Dpt type_dpt){
_GOaddr = GOaddr; _GOaddr = GOaddr;
_dpt = type_dpt; _dpt = type_dpt;
} }
void loop(float value){ void loop(){
unsigned long currentMillis = millis(); // unsigned long currentMillis = millis();
// Delta Change update as defined in ETS // Delta Change update as defined in ETS
int32_t deltaPercent = ( 100 * ( _value - _lastValue ) / _value );
int deltaPercent = ( 100 * ( value - lastValue ) / value );
if ( percentCycle != 0 && abs(deltaPercent) >= percentCycle ) if ( percentCycle != 0 && abs(deltaPercent) >= percentCycle )
{ {
trigger = true; _trigger = true;
_lastValue = _value;
} }
// Refresh groupAddress value as defined in ETS since last update // Refresh groupAddress value as defined in ETS since last update
if ( timePeriod != 0 && currentMillis - lastUpdate >= timePeriod ) if ( timePeriod != 0 && millis() - _lastMillis >= timePeriod )
{ {
trigger = true; _trigger = true;
} }
// UpdateGO but send to bus only if triggered by time or value change percentage // UpdateGO but send to bus only if triggered by time or value change percentage
if (trigger){ if (_trigger){
knx.getGroupObject(_GOaddr).value(value, _dpt); knx.getGroupObject(_GOaddr).value(_value, _dpt);
lastUpdate = millis(); _lastMillis = millis();
trigger = false; _trigger = false;
}else{ }else{
knx.getGroupObject(_GOaddr).valueNoSend(value, _dpt); knx.getGroupObject(_GOaddr).valueNoSend(_value, _dpt);
}
}
void setValue(float value){
if (value != _value)
{
_value = value;
} }
lastValue = value;
} }
private: private:
uint8_t _GOaddr;
Dpt _dpt; Dpt _dpt;
bool trigger = false; float _value = 0;
float _lastValue = 0;
uint32_t _lastMillis = 0;
uint8_t _GOaddr;
bool _trigger = false;
// bool isUpdated = false; // bool isUpdated = false;
public: public:
float lastValue = 0;
unsigned long lastUpdate = 0;
} Physical[physicalCount]; } Physical[physicalCount];
class Blinker
{
private:
uint8_t ledPin_; // the number of the LED pin
uint32_t OnTime = 1000; // milliseconds of on-time
uint32_t OffTime = 1000; // milliseconds of off-time
bool ledState = LOW; // ledState used to set the LED
uint32_t previousMillis; // will store last time LED was updated
void setOutput(bool state_, uint32_t currentMillis_){
ledState = state_;
previousMillis = currentMillis_;
digitalWrite(ledPin_, state_);
}
public:
Blinker(uint8_t pin)
{
ledPin_ = pin;
pinMode(ledPin_, OUTPUT);
previousMillis = 0;
}
void set(uint32_t on, uint32_t off){
OnTime = on;
OffTime = off;
}
void loop(){
uint32_t currentMillis = millis();
if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
{
setOutput(LOW, currentMillis);
}
else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
{
setOutput(HIGH, currentMillis);
}
}
};
Blinker led = Blinker(ledPin);
void callBackProgMode(GroupObject& go){ void callBackProgMode(GroupObject& go){
progMode = (bool)go.value(); progMode = (bool)go.value();
} }
// callback from reset-GO void callBackDateTime(GroupObject& go){
static uint32_t lastUpdate = 0;
const uint32_t interval = (1000 * 60 * 60 * 24); // 1day
struct tm myTime;
myTime = go.value();
unsigned short tmp_sec = myTime.tm_sec;
unsigned short tmp_min = myTime.tm_min;
unsigned short tmp_hour = myTime.tm_hour;
unsigned short tmp_mday = myTime.tm_mday;
unsigned short tmp_month = myTime.tm_mon;
unsigned short tmp_year = myTime.tm_year;
if (millis() - lastUpdate >= interval && !timeStatus() == timeSet)
{
setTime(tmp_hour, tmp_min, tmp_sec, tmp_mday, tmp_month, tmp_year);
lastUpdate = millis();
}
}
void resetCallback(GroupObject& go) void resetCallback(GroupObject& go)
{ {
if (go.value()) if (go.value())
{ {
pzem.resetEnergy(); resetEnergy = true;
goReset.value(false); goReset.value(false);
} }
} }
@ -112,6 +189,7 @@ void setup() {
randomSeed(millis()); randomSeed(millis());
knx.readMemory(); knx.readMemory();
// led.set(5000, 5000);
if (knx.configured()) if (knx.configured())
{ {
@ -121,10 +199,11 @@ void setup() {
percentCycle = ets_percentCycle[knx.paramByte(1)]; percentCycle = ets_percentCycle[knx.paramByte(1)];
timePeriod = ets_timePeriod[knx.paramByte(2)] * 1000; timePeriod = ets_timePeriod[knx.paramByte(2)] * 1000;
resetFlag = knx.paramByte(3); resetPeriod = knx.paramByte(3);
goReset.callback(resetCallback); goReset.callback(resetCallback);
goReset.dataPointType(DPT_Trigger); goReset.dataPointType(DPT_Trigger);
goDateTime.dataPointType(DPT_DateTime); goDateTime.dataPointType(DPT_DateTime);
goProgMode.dataPointType(DPT_Trigger); goProgMode.dataPointType(DPT_Trigger);
@ -137,6 +216,7 @@ void setup() {
Physical[3].init(GOaddr += 1, DPT_Value_Power); Physical[3].init(GOaddr += 1, DPT_Value_Power);
Physical[4].init(GOaddr += 1, DPT_Value_Energy); Physical[4].init(GOaddr += 1, DPT_Value_Energy);
Physical[5].init(GOaddr += 1, DPT_Value_Frequency); Physical[5].init(GOaddr += 1, DPT_Value_Frequency);
led.set(2000, 1000);
} }
// is the led active on HIGH or low? Default is LOW // is the led active on HIGH or low? Default is LOW
@ -152,22 +232,17 @@ void setup() {
} }
void loop() { void loop() {
knx.loop(); knx.loop();
if (knx.configured() && !progMode) if (knx.configured() && !progMode)
{ {
unsigned long currentMillis = millis(); refreshValueLoop();
resetEnergyLoop();
for (uint8_t i=0; i< physicalCount; i++) for (uint8_t i=0; i< physicalCount; i++)
{ {
if (currentMillis - Physical[i].lastUpdate >= 1000) Physical[i].loop();
{
float isanValue = refreshValue(i);
if(!isnan(isanValue))
{
Physical[i].loop(isanValue);
}
}
} }
} }
else if (progMode) else if (progMode)
@ -176,45 +251,95 @@ void loop() {
} }
} }
float refreshValue(uint8_t physicalNumber){ void refreshValueLoop(){
float valueTemp; static const uint16_t pzemInterval = 500; // interval at which to blink (milliseconds)
switch (physicalNumber) { //maybe a pointer or reference could be nicer... static uint32_t lastPzemUpdate = 0;
if (millis() - lastPzemUpdate >= pzemInterval)
{
for (uint8_t i=0; i< physicalCount; i++)
{
float isaValue;
switch (i) { //maybe a pointer or reference could be nicer...
case 0: case 0:
valueTemp = pzem.voltage(); isaValue = pzem.voltage();
return valueTemp; break;
case 1: case 1:
valueTemp = pzem.current(); isaValue = pzem.current();
return valueTemp; break;
case 2: case 2:
valueTemp = pzem.pf(); isaValue = pzem.pf();
return valueTemp; break;
case 3: case 3:
valueTemp = pzem.power(); isaValue = pzem.power();
return valueTemp; break;
case 4: case 4:
valueTemp = pzem.energy(); isaValue = pzem.energy();
return valueTemp; break;
case 5: case 5:
valueTemp = pzem.frequency(); isaValue = pzem.frequency();
return valueTemp; break;
default: default:
break; break;
} }
if(!isnan(isaValue))
{
Physical[i].setValue(isaValue);
}
}
}
} }
void resetEnergy(){ void resetEnergyLoop(){
static time_t lastTime;
time_t samdTime = now();
if (timeStatus() == timeSet)
{
switch (resetPeriod)
{
case 1: //day
if (day(samdTime) != day(lastTime))
{
lastTime = samdTime;
pzem.resetEnergy(); pzem.resetEnergy();
}
break;
case 2: //week
if (weekday(samdTime) != weekday(lastTime) && weekday(samdTime) == 2) //monday
{
lastTime = samdTime;
pzem.resetEnergy();
}
break;
case 3: // month
if (month(samdTime) != month(lastTime))
{
lastTime = samdTime;
pzem.resetEnergy();
}
break;
case 4: // year
if (year(samdTime) != year(lastTime))
{
lastTime = samdTime;
pzem.resetEnergy();
}
default:
break;
}
}
} }
void prodModeLoop(){ // run Only if progMode triggered ( at start or callback) void prodModeLoop(){ // run Only if progMode triggered ( at start or callback)
const uint32_t timerProgMode = ( 15 * 60 * 1000 ) ; // 15min
static uint32_t timerProgPrevMillis = 0; static uint32_t timerProgPrevMillis = 0;
const uint32_t timerProgMode = ( 15 * 60 * 1000 ) ; // 15min
if (!knx.progMode() ) if (!knx.progMode())
{ {
knx.progMode(true); knx.progMode(true);
timerProgPrevMillis = millis(); timerProgPrevMillis = millis();
led.set(500, 250);
} }
else else
{ {