From 58d37215711b3e214d39cfc426eaede3981e62d0 Mon Sep 17 00:00:00 2001 From: zelogik Date: Thu, 21 Jan 2021 18:41:55 +0100 Subject: [PATCH] Add: 'Demo example for PZEM004t-V3 (#120) * knx-pzem004v30 Add first draft of a pzem-004t power/current/tension/etc.. on your main line (BE CAREFUL WITH VOLTAGE!) PZEM-004t-v30 wired on a samd21 with the use of Sercom2 Use with slight modification of: https://github.com/mandulaj/PZEM-004T-v30 View issue: https://github.com/mandulaj/PZEM-004T-v30/issues/43 * Rename examples/knx-pzem0004t.xml to examples/knx-pzem004/knx-pzem0004t.xml * Delete knx-pzem004t.knxprod * Delete pzem-004t-v30.ino * Update: 'just move to right directory' * Update knx-pzem0004t.xml * Add: ProgMode * Fix/Update/Add Add: ResetEnergy function with datetime Update: led Class Fix: many typo, errors --- examples/knx-pzem004/knx-pzem0004t.xml | 163 ++++++++++ examples/knx-pzem004/knx-pzem004t.knxprod | Bin 0 -> 36595 bytes examples/knx-pzem004/pzem-004t-v30.ino | 352 ++++++++++++++++++++++ 3 files changed, 515 insertions(+) create mode 100644 examples/knx-pzem004/knx-pzem0004t.xml create mode 100644 examples/knx-pzem004/knx-pzem004t.knxprod create mode 100644 examples/knx-pzem004/pzem-004t-v30.ino diff --git a/examples/knx-pzem004/knx-pzem0004t.xml b/examples/knx-pzem004/knx-pzem0004t.xml new file mode 100644 index 0000000..9059c5f --- /dev/null +++ b/examples/knx-pzem004/knx-pzem0004t.xml @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/knx-pzem004/knx-pzem004t.knxprod b/examples/knx-pzem004/knx-pzem004t.knxprod new file mode 100644 index 0000000000000000000000000000000000000000..4881a2669561f1105cec2177961f1facaa38d741 GIT binary patch literal 36595 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 TVG;n?$zPB2KM$l|`Ly*rQ5}?> literal 0 HcmV?d00001 diff --git a/examples/knx-pzem004/pzem-004t-v30.ino b/examples/knx-pzem004/pzem-004t-v30.ino new file mode 100644 index 0000000..2bc92ff --- /dev/null +++ b/examples/knx-pzem004/pzem-004t-v30.ino @@ -0,0 +1,352 @@ +#include +#include +#include "wiring_private.h" // pinPeripheral() function + +#include + +//Sercom Stuff +#define PIN_SERIAL2_RX (34ul) // Pin description number for PIO_SERCOM on D12 (34ul) +#define PIN_SERIAL2_TX (36ul) // Pin description number for PIO_SERCOM on D10 (36ul) +#define PAD_SERIAL2_TX (UART_TX_PAD_2) // SERCOM pad 2 +#define PAD_SERIAL2_RX (SERCOM_RX_PAD_3) // SERCOM pad 3 +Uart Serial2(&sercom1, PIN_SERIAL2_RX, PIN_SERIAL2_TX, PAD_SERIAL2_RX, PAD_SERIAL2_TX); //TX D10, RX D12 + +void SERCOM1_Handler() +{ + Serial2.IrqHandler(); +} + +//PZEM stuff +#define PZEM004_NO_SWSERIAL +#define PZEM_DEFAULT_ADDR 0xF8 + + +//knx stuff +#define goReset knx.getGroupObject(1) +#define goDateTime knx.getGroupObject(2) +#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_percentCycle[6] = {0, 5, 10, 15, 20, 30}; //need knxprod update... ? + +const uint8_t ledPin = LED_BUILTIN;// the number of the LED pin +const uint8_t physicalCount = 6; // voltage,current,power_factor,power,energy,frequency + +// 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; + +// Issue on https://github.com/mandulaj/PZEM-004T-v30/issues/43 +PZEM004Tv30 pzem(Serial2, PZEM_DEFAULT_ADDR); + +struct Physical { + void init(uint8_t GOaddr, Dpt type_dpt){ + _GOaddr = GOaddr; + _dpt = type_dpt; + } + + void loop(){ +// unsigned long currentMillis = millis(); + // Delta Change update as defined in ETS + int32_t deltaPercent = ( 100 * ( _value - _lastValue ) / _value ); + if ( percentCycle != 0 && abs(deltaPercent) >= percentCycle ) + { + _trigger = true; + _lastValue = _value; + } + + // Refresh groupAddress value as defined in ETS since last update + if ( timePeriod != 0 && millis() - _lastMillis >= timePeriod ) + { + _trigger = true; + } + + // UpdateGO but send to bus only if triggered by time or value change percentage + if (_trigger){ + knx.getGroupObject(_GOaddr).value(_value, _dpt); + _lastMillis = millis(); + _trigger = false; + }else{ + knx.getGroupObject(_GOaddr).valueNoSend(_value, _dpt); + } + } + + void setValue(float value){ + if (value != _value) + { + _value = value; + } + } + + private: + Dpt _dpt; + float _value = 0; + float _lastValue = 0; + uint32_t _lastMillis = 0; + uint8_t _GOaddr; + bool _trigger = false; + +// bool isUpdated = false; + + public: + +} 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){ + progMode = (bool)go.value(); +} + +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) +{ + if (go.value()) + { + resetEnergy = true; + goReset.value(false); + } +} + +void setup() { + pinPeripheral(PIN_SERIAL2_RX, PIO_SERCOM); + pinPeripheral(PIN_SERIAL2_TX, PIO_SERCOM); + + SerialUSB.begin(9600); + Serial2.begin(9600); + + ArduinoPlatform::SerialDebug = &SerialUSB; + + randomSeed(millis()); + + knx.readMemory(); +// led.set(5000, 5000); + + if (knx.configured()) + { + int confStartupTime = ets_startupTimeout[knx.paramByte(0)] * 1000; + delay(confStartupTime); // the only delay used, why make a withoutDelay function for that? + + percentCycle = ets_percentCycle[knx.paramByte(1)]; + timePeriod = ets_timePeriod[knx.paramByte(2)] * 1000; + + resetPeriod = knx.paramByte(3); + + goReset.callback(resetCallback); + goReset.dataPointType(DPT_Trigger); + + goDateTime.dataPointType(DPT_DateTime); + + goProgMode.dataPointType(DPT_Trigger); + goProgMode.callback(callBackProgMode); + + uint8_t GOaddr = 3; + Physical[0].init(GOaddr, DPT_Value_Electric_Potential); // voltage + Physical[1].init(GOaddr += 1, DPT_Value_Electric_Current); + Physical[2].init(GOaddr += 1, DPT_Value_Power_Factor); + Physical[3].init(GOaddr += 1, DPT_Value_Power); + Physical[4].init(GOaddr += 1, DPT_Value_Energy); + Physical[5].init(GOaddr += 1, DPT_Value_Frequency); + led.set(2000, 1000); + } + + // is the led active on HIGH or low? Default is LOW + knx.ledPinActiveOn(HIGH); + // pin or GPIO programming button is connected to. Default is 0 + knx.ledPin(5); + knx.buttonPin(9); + + knx.start(); +// while (!SerialUSB) { //wait for DEBUGING +// ; // wait for serial port to connect. Needed for native USB port only +// } +} + +void loop() { + + knx.loop(); + + if (knx.configured() && !progMode) + { + refreshValueLoop(); + resetEnergyLoop(); + + for (uint8_t i=0; i< physicalCount; i++) + { + Physical[i].loop(); + } + } + else if (progMode) + { + prodModeLoop(); + } +} + +void refreshValueLoop(){ + static const uint16_t pzemInterval = 500; // interval at which to blink (milliseconds) + 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: + isaValue = pzem.voltage(); + break; + case 1: + isaValue = pzem.current(); + break; + case 2: + isaValue = pzem.pf(); + break; + case 3: + isaValue = pzem.power(); + break; + case 4: + isaValue = pzem.energy(); + break; + case 5: + isaValue = pzem.frequency(); + break; + default: + break; + } + if(!isnan(isaValue)) + { + Physical[i].setValue(isaValue); + } + } + } +} + +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(); + } + 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) + static uint32_t timerProgPrevMillis = 0; + const uint32_t timerProgMode = ( 15 * 60 * 1000 ) ; // 15min + + if (!knx.progMode()) + { + knx.progMode(true); + timerProgPrevMillis = millis(); + led.set(500, 250); + } + else + { + if (millis() - timerProgPrevMillis > timerProgMode) { + knx.progMode(false); + goProgMode.value(false); + progMode = 0; + } + } +}