diff --git a/build-flags/build_flags_lighthub21 b/build-flags/build_flags_lighthub21 index b8748f1..5c57c77 100644 --- a/build-flags/build_flags_lighthub21 +++ b/build-flags/build_flags_lighthub21 @@ -8,4 +8,4 @@ #-DWiz5500 -DSTATUSLED -DMCP23017 --DPID_DISABLE +#-DPID_DISABLE diff --git a/lighthub/item.cpp b/lighthub/item.cpp index 897288b..d88685b 100644 --- a/lighthub/item.cpp +++ b/lighthub/item.cpp @@ -98,6 +98,7 @@ int txt2subItem(char *payload) { else if (strcmp_P(payload, HUE_P) == 0) cmd = S_HUE; else if (strcmp_P(payload, SAT_P) == 0) cmd = S_SAT; else if (strcmp_P(payload, TEMP_P) == 0) cmd = S_TEMP; + else if (strcmp_P(payload, VAL_P) == 0) cmd = S_VAL; return cmd; } @@ -328,7 +329,7 @@ long int Item::getVal() //Return Val if val is int or first elem of Value array uint8_t Item::getSubtype() { if (!itemVal) return 0;//-1; - if (itemVal->type == aJson_Int) return itemVal->subtype; + if (itemVal->type == aJson_Int || itemVal->type == aJson_Float) return itemVal->subtype; else if (itemVal->type == aJson_Array) { aJsonObject *t = aJson.getArrayItem(itemVal, 0); if (t) return t->subtype; @@ -349,14 +350,15 @@ void Item::setVal(short n, int par) // Only store if VAL is array defined in c void Item::setVal(long int par) // Only store if VAL is int (autogenerated or config-defined) { - if (!itemVal || itemVal->type != aJson_Int) return; + if (!itemVal || (itemVal->type != aJson_Int && itemVal->type != aJson_Float)) return; //debugSerial<Ctrl(st, subItem, toExecute); + debugSerial<isActive(); + if (driver) { + bool active = driver->isActive(); + printActiveStatus(active); + return active; + } + // No driver - check value st.aslong = getVal(); switch (itemType) { @@ -996,9 +1015,8 @@ int Item::isActive() { val = st.v; //Light volume break; - case CH_DIMMER: //Everywhere, in flat VAL + case CH_DIMMER: //Legacy channels case CH_MODBUS: - // case CH_THERMO: case CH_VC: case CH_VCTEMP: case CH_PWM: @@ -1008,6 +1026,7 @@ int Item::isActive() { debugSerial<")<itemVal->type) + { + case aJson_Int: + Int(item->itemVal->valueint); + return true; + + case aJson_Float: + Float(item->itemVal->valueint); + return true; + } + } return false; } diff --git a/lighthub/itemCmd.h b/lighthub/itemCmd.h index 811c2bd..373580b 100644 --- a/lighthub/itemCmd.h +++ b/lighthub/itemCmd.h @@ -189,6 +189,7 @@ public: itemCmd Int(int32_t i); itemCmd Int(uint32_t i); + itemCmd Float(float f); itemCmd Tens(int32_t i); itemCmd Cmd(uint8_t i); itemCmd HSV(uint16_t h, uint8_t s, uint8_t v); diff --git a/lighthub/main.cpp b/lighthub/main.cpp index 953496f..a7e544c 100644 --- a/lighthub/main.cpp +++ b/lighthub/main.cpp @@ -926,16 +926,20 @@ void resetHard() { void Changed(int i, DeviceAddress addr, float currentTemp) { char addrstr[32] = "NIL"; //char addrbuf[17]; - char valstr[16] = "NIL"; - char *owEmitString = NULL; + //char valstr[16] = "NIL"; + //char *owEmitString = NULL; char *owItem = NULL; SetBytes(addr, 8, addrstr); addrstr[17] = 0; if (!root) return; - printFloatValueToStr(currentTemp,valstr); - debugSerial<")<")<")<itemArg || (item->itemArg->type != aJson_Array) || aJson.getArraySize(item->itemArg)<2) + if (!store || !item || !item->itemArg || (item->itemArg->type != aJson_Array) || aJson.getArraySize(item->itemArg)<1) { errorSerial<itemArg<itemArg->type != aJson_Array)<itemArg)<2)<type == aJson_Float) outMax=param->valuefloat; + else if (param->type == aJson_Int) outMax=param->valueint; + case 4: + param = aJson.getArrayItem(kPIDObj, 3); + if (param->type == aJson_Float) outMin=param->valuefloat; + else if (param->type == aJson_Int) outMin=param->valueint; case 3: param = aJson.getArrayItem(kPIDObj, 2); if (param->type == aJson_Float) kD=param->valuefloat; + else if (param->type == aJson_Int) kD=param->valueint; case 2: param = aJson.getArrayItem(kPIDObj, 1); if (param->type == aJson_Float) kI=param->valuefloat; + else if (param->type == aJson_Int) kI=param->valueint; case 1: param = aJson.getArrayItem(kPIDObj, 0); if (param->type == aJson_Float) kP=param->valuefloat; + else if (param->type == aJson_Int) kP=param->valueint; if (kP<0) { kP=-kP; @@ -50,20 +61,28 @@ bool out_pid::getConfig() switch (item->itemVal->type) { - case aJson_Int: item->itemVal->valuefloat = item->itemVal->valueint; + case aJson_Int: + store->setpoint = item->itemVal->valueint; break; case aJson_Float: + store->setpoint = item->itemVal->valuefloat; break; default: - + store->setpoint = 20.; } - item->itemVal->type = aJson_Float; - if (!store->pid) store->pid= new PID (&store->input, &store->output, &item->itemVal->valuefloat, kP, kI, kD, direction); + if (!store->pid) + + {store->pid= new PID (&store->input, &store->output, &store->setpoint, kP, kI, kD, direction); + if (!store->pid) return false; + store->pid->SetMode(AUTOMATIC); + store->pid->SetOutputLimits(outMin,outMax); + + return true;} + else errorSerial<addr=item->getArg(0); + return false; } @@ -73,12 +92,10 @@ if (!store) store= (pidPersistent *)item->setPersistent(new pidPersistent); if (!store) { errorSerial<pid=NULL; //store->timestamp=millis(); if (getConfig()) { - //item->clearFlag(ACTION_NEEDED); - //item->clearFlag(ACTION_IN_PROCESS); infoSerial<itemArr->name<driverStatus = CST_INITIALIZED; return 1; @@ -93,8 +110,8 @@ else int out_pid::Stop() { -Serial.println("Modbus De-Init"); -if (store) delete (store->pid()); +Serial.println("PID De-Init"); +if (store) delete (store->pid); delete store; item->setPersistent(NULL); store = NULL; @@ -110,99 +127,78 @@ return CST_UNKNOWN; int out_pid::isActive() { -return item->getVal(); +return (item->getCmd()!=CMD_OFF); } int out_pid::Poll(short cause) { -if ((Status() == CST_INITIALIZED) && isTimeOver(store->timestamp,millis(),store->pollingInterval)) - { - - store->timestamp=millisNZ(); - debugSerial<itemArr->name << endl; +if (store && store->pid && (Status() == CST_INITIALIZED) && item && (item->getCmd()!=CMD_OFF)) + { + double prevOut=store->output; + store->pid->Compute(); + if (abs(store->output-prevOut)>OUTPUT_TRESHOLD) + { + aJsonObject * oCmd = aJson.getArrayItem(item->itemArg, 1); + itemCmd value((float) store->output); + executeCommand(oCmd,-1,value); + } - } + } -return store->pollingInterval; +return 1;//store->pollingInterval; }; + int out_pid::getChanType() { - return CH_MODBUS; + return CH_THERMO; } -//!Control unified Modbus item -// Priority of selection sub-items control to: -// 1. if defined standard suffix Code inside cmd -// 2. custom textual subItem -// 3. non-standard numeric suffix Code equal param id +//!Control unified PID controller item +// /set suffix - to setup setpoint +// /val suffix - to put value into controller +// accept ON and OFF commands int out_pid::Ctrl(itemCmd cmd, char* subItem, bool toExecute) { -//int chActive = item->isActive(); -//bool toExecute = (chActive>0); -//itemCmd st(ST_UINT32,CMD_VOID); +if (!store || !store->pid || (Status() != CST_INITIALIZED)) return 0; + + int suffixCode = cmd.getSuffix(); -aJsonObject *templateParamObj = NULL; -short mappedCmdVal = 0; - -// trying to find parameter in template with name == subItem (NB!! standard suffixes dint working here) -if (subItem && strlen (subItem)) templateParamObj = aJson.getObjectItem(store->parameters, subItem); - -if (!templateParamObj) -{ - // Trying to find template parameter where id == suffixCode - templateParamObj = store->parameters->child; - - while (templateParamObj) - { - //aJsonObject *regObj = aJson.getObjectItem(paramObj, "reg"); - aJsonObject *idObj = aJson.getObjectItem(templateParamObj, "id"); - if (idObj->type==aJson_Int && idObj->valueint == suffixCode) break; - - aJsonObject *mapObj = aJson.getObjectItem(templateParamObj, "mapcmd"); - if (mapObj && (mappedCmdVal = cmd.doReverseMappingCmd(mapObj))) break; - - templateParamObj=templateParamObj->next; - } -} - - -// aJsonObject *typeObj = aJson.getObjectItem(paramObj, "type"); -// aJsonObject *mapObj = aJson.getObjectItem(paramObj, "map"); -// aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2); -// uint16_t data = node.getResponseBuffer(posInBuffer); - - if (cmd.isCommand() && !suffixCode) suffixCode=S_CMD; //if some known command find, but w/o correct suffix - got it switch(suffixCode) { -case S_NOTFOUND: - // turn on and set -toExecute = true; -debugSerial<input=cmd.getFloat(); +debugSerial<input<setpoint=cmd.getFloat(); +debugSerial<setpoint<SendStatus(SEND_PARAMETERS); +return 1; +//break; case S_CMD: switch (cmd.getCmd()) { case CMD_ON: - + case CMD_OFF: + item->setCmd(cmd.getCmd()); + item->SendStatus(SEND_COMMAND); return 1; - - case CMD_OFF: - - return 1; - default: debugSerial< #include +#define OUTPUT_TRESHOLD 1 class pidPersistent : public chPersistent { public: - PID pid; + PID * pid; double output; double input; + double setpoint; int driverStatus; }; diff --git a/lighthub/textconst.h b/lighthub/textconst.h index 097ac3f..e6d0b36 100644 --- a/lighthub/textconst.h +++ b/lighthub/textconst.h @@ -114,6 +114,7 @@ const char SAT_P[] PROGMEM = "sat"; const char TEMP_P[] PROGMEM = "temp"; const char HSV_P[] PROGMEM = "HSV"; const char RGB_P[] PROGMEM = "RGB"; +const char VAL_P[] PROGMEM = "val"; /* const char RPM_P[] PROGMEM = "rpm"; diff --git a/lighthub/utils.cpp b/lighthub/utils.cpp index e83a011..9883f56 100644 --- a/lighthub/utils.cpp +++ b/lighthub/utils.cpp @@ -532,6 +532,7 @@ bool executeCommand(aJsonObject* cmd, int8_t toggle) bool executeCommand(aJsonObject* cmd, int8_t toggle, itemCmd _itemCmd) //bool executeCommand(aJsonObject* cmd, int8_t toggle, char* defCmd) { +if (!cmd) return 0; switch (cmd->type) { case aJson_String: //legacy - no action @@ -572,17 +573,21 @@ switch (toggle) if (!ecmd) ecmd = aJson.getObjectItem(cmd, "ecmd"); } -char * itemCommand; +char * itemCommand = NULL; char Buffer[16]; if(icmd && icmd->type == aJson_String) itemCommand = icmd->valuestring; - else itemCommand = _itemCmd.toString(Buffer,sizeof(Buffer)); + //else itemCommand = _itemCmd.toString(Buffer,sizeof(Buffer)); char * emitCommand; if(ecmd && ecmd->type == aJson_String) emitCommand = ecmd->valuestring; else emitCommand = _itemCmd.toString(Buffer,sizeof(Buffer)); //debugSerial << F("IN:") << (pin) << F(" : ") <valuestring<< F(" -> ")<valuestring<< F(" -> ")<valuestring<< F(" -> ");_itemCmd.debugOut(); + } if (emit) debugSerial << emit->valuestring<< F(" -> ")<valuestring,sizeof(addrstr)); if (mqttClient.connected() && !ethernetIdleCount) @@ -610,12 +615,17 @@ if (mqttClient.connected() && !ethernetIdleCount) if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring); mqttClient.publish(addrstr, emitCommand , true); } -} + } // emit -if (item && itemCommand && item->type == aJson_String) { + +if (item && item->type == aJson_String) { //debugSerial <valuestring <valuestring); - if (it.isValid()) it.Ctrl(itemCommand); + if (it.isValid()) + { + if (itemCommand) it.Ctrl(itemCommand); + else it.Ctrl(_itemCmd); + } } return true; } diff --git a/platformio.ini b/platformio.ini index 3b56a76..6f0b4c5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,7 +13,7 @@ src_dir = lighthub default_envs = ; ****** UNCOMMENT single environment name for target platform below ******* ; Arduino Mega (without onewire) + Ethernet shield Wiznet 5100 - mega2560slim-5100 +; mega2560slim-5100 ; Arduino Mega + Ethernet shield Wiznet 5100 ; mega2560-5100 @@ -22,7 +22,7 @@ default_envs = ; mega2560-5500 ; LightHub controller HW revision 2.1 and above (Wiznet 5500 CS on pin 53) -; lighthub21 + lighthub21 ; Arduino DUE + Ethernet shield Wiznet 5100 ; due-5100 @@ -583,8 +583,8 @@ framework = arduino board = due build_flags = !python get_build_flags.py lighthub21 ;upload_command = arduinoOTA -address 192.168.11.172 -port 65280 -username arduino -password password -b -upload /sketch -sketch $SOURCE -;upload_command = arduinoOTA -address 192.168.88.34 -port 65280 -username arduino -password password -b -upload /sketch -sketch $SOURCE -;upload_protocol = custom +upload_command = arduinoOTA -address 192.168.88.64 -port 65280 -username arduino -password password -b -upload /sketch -sketch $SOURCE +upload_protocol = custom lib_ignore = ;DS2482_OneWire //UNCOMMENT for software 1-wire driver DHT sensor library for ESPx