mirror of https://github.com/arendst/Tasmota.git
Merge pull request #10521 from marcvs/pid-branch-revived
Pid branch revived
This commit is contained in:
commit
279b88b08e
|
@ -828,10 +828,10 @@
|
||||||
#define THERMOSTAT_TEMP_BAND_NO_PEAK_DET 1 // Default temperature band in thenths of degrees celsius within no peak will be detected
|
#define THERMOSTAT_TEMP_BAND_NO_PEAK_DET 1 // Default temperature band in thenths of degrees celsius within no peak will be detected
|
||||||
#define THERMOSTAT_TIME_STD_DEV_PEAK_DET_OK 10 // Default standard deviation in minutes of the oscillation periods within the peak detection is successful
|
#define THERMOSTAT_TIME_STD_DEV_PEAK_DET_OK 10 // Default standard deviation in minutes of the oscillation periods within the peak detection is successful
|
||||||
|
|
||||||
// -- PID and Timeprop ------------------------------
|
// -- PID and Timeprop ------------------------------ // Both together will add +12k1 code
|
||||||
//#define USE_TIMEPROP // Add support for the timeprop feature (+0k8 code)
|
// #define use TIMEPROP // Add support for the timeprop feature (+9k1 code)
|
||||||
// For details on the configuration please see the header of tasmota/xdrv_48_timeprop.ino
|
// For details on the configuration please see the header of tasmota/xdrv_48_timeprop.ino
|
||||||
//#define USE_PID // Add suport for the PID feature (+11k1 code)
|
// #define USE_PID // Add suport for the PID feature (+11k2 code)
|
||||||
// For details on the configuration please see the header of tasmota/xdrv_49_pid.ino
|
// For details on the configuration please see the header of tasmota/xdrv_49_pid.ino
|
||||||
// -- End of general directives ---------------------
|
// -- End of general directives ---------------------
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef USE_TIMEPROP
|
#ifdef USE_TIMEPROP
|
||||||
|
#ifndef FIRMWARE_MINIMAL
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Code to drive one or more relays in a time proportioned manner give a
|
* Code to drive one or more relays in a time proportioned manner give a
|
||||||
* required power value.
|
* required power value.
|
||||||
|
@ -79,7 +80,23 @@
|
||||||
#define TIMEPROP_RELAYS 1, 2 // which relay to control 1:8
|
#define TIMEPROP_RELAYS 1, 2 // which relay to control 1:8
|
||||||
|
|
||||||
* Publish values between 0 and 1 to the topic(s) described above
|
* Publish values between 0 and 1 to the topic(s) described above
|
||||||
\*********************************************************************************************/
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define D_CMND_TIMEPROP "timeprop_"
|
||||||
|
#define D_CMND_TIMEPROP_SETPOWER "setpower_" // add index no on end (0:8) and data is power 0:1
|
||||||
|
|
||||||
|
#include "Timeprop.h"
|
||||||
|
|
||||||
|
enum TimepropCommands { CMND_TIMEPROP_SETPOWER };
|
||||||
|
const char kTimepropCommands[] PROGMEM = D_CMND_TIMEPROP_SETPOWER;
|
||||||
|
|
||||||
|
static Timeprop timeprops[TIMEPROP_NUM_OUTPUTS];
|
||||||
|
static int relayNos[TIMEPROP_NUM_OUTPUTS] = {TIMEPROP_RELAYS};
|
||||||
|
static long currentRelayStates = 0; // current actual relay states. Bit 0 first relay
|
||||||
|
|
||||||
|
|
||||||
#ifndef TIMEPROP_NUM_OUTPUTS
|
#ifndef TIMEPROP_NUM_OUTPUTS
|
||||||
#define TIMEPROP_NUM_OUTPUTS 1 // how many outputs to control (with separate alogorithm for each)
|
#define TIMEPROP_NUM_OUTPUTS 1 // how many outputs to control (with separate alogorithm for each)
|
||||||
|
@ -103,8 +120,6 @@
|
||||||
#define TIMEPROP_RELAYS 1 // which relay to control 1:8
|
#define TIMEPROP_RELAYS 1 // which relay to control 1:8
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "Timeprop.h"
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
Timeprop timeprops[TIMEPROP_NUM_OUTPUTS];
|
Timeprop timeprops[TIMEPROP_NUM_OUTPUTS];
|
||||||
int relay_nos[TIMEPROP_NUM_OUTPUTS] = {TIMEPROP_RELAYS};
|
int relay_nos[TIMEPROP_NUM_OUTPUTS] = {TIMEPROP_RELAYS};
|
||||||
|
@ -162,7 +177,51 @@ void TimepropXdrvPower(void) {
|
||||||
/* char *data; */
|
/* char *data; */
|
||||||
/* } XdrvMailbox; */
|
/* } XdrvMailbox; */
|
||||||
|
|
||||||
// To get here post with topic cmnd/timeprop_setpower_n where n is index into Tprop.timeprops 0:7
|
// To get here post with topic cmnd/timeprop_setpower_n where n is index into timeprops 0:7
|
||||||
|
bool TimepropCommand()
|
||||||
|
{
|
||||||
|
char command [CMDSZ];
|
||||||
|
bool serviced = true;
|
||||||
|
uint8_t ua_prefix_len = strlen(D_CMND_TIMEPROP); // to detect prefix of command
|
||||||
|
/*
|
||||||
|
snprintf_P(log_data, sizeof(log_data), "Command called: "
|
||||||
|
"index: %d data_len: %d payload: %d topic: %s data: %s\n",
|
||||||
|
XdrvMailbox.index,
|
||||||
|
XdrvMailbox.data_len,
|
||||||
|
XdrvMailbox.payload,
|
||||||
|
(XdrvMailbox.payload >= 0 ? XdrvMailbox.topic : ""),
|
||||||
|
(XdrvMailbox.data_len >= 0 ? XdrvMailbox.data : ""));
|
||||||
|
|
||||||
|
AddLog(LOG_LEVEL_INFO);
|
||||||
|
*/
|
||||||
|
if (0 == strncasecmp_P(XdrvMailbox.topic, PSTR(D_CMND_TIMEPROP), ua_prefix_len)) {
|
||||||
|
// command starts with timeprop_
|
||||||
|
int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + ua_prefix_len, kTimepropCommands);
|
||||||
|
if (CMND_TIMEPROP_SETPOWER == command_code) {
|
||||||
|
/*
|
||||||
|
snprintf_P(log_data, sizeof(log_data), "Timeprop command timeprop_setpower: "
|
||||||
|
"index: %d data_len: %d payload: %d topic: %s data: %s",
|
||||||
|
XdrvMailbox.index,
|
||||||
|
XdrvMailbox.data_len,
|
||||||
|
XdrvMailbox.payload,
|
||||||
|
(XdrvMailbox.payload >= 0 ? XdrvMailbox.topic : ""),
|
||||||
|
(XdrvMailbox.data_len >= 0 ? XdrvMailbox.data : ""));
|
||||||
|
AddLog(LOG_LEVEL_INFO);
|
||||||
|
*/
|
||||||
|
if (XdrvMailbox.index >=0 && XdrvMailbox.index < TIMEPROP_NUM_OUTPUTS) {
|
||||||
|
timeprops[XdrvMailbox.index].setPower( atof(XdrvMailbox.data), Tprop.current_time_secs );
|
||||||
|
}
|
||||||
|
snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"" D_CMND_TIMEPROP D_CMND_TIMEPROP_SETPOWER "%d\":\"%s\"}"),
|
||||||
|
XdrvMailbox.index, XdrvMailbox.data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
serviced = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
serviced = false;
|
||||||
|
}
|
||||||
|
return serviced;
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Interface
|
* Interface
|
||||||
|
@ -180,6 +239,9 @@ bool Xdrv48(byte function) {
|
||||||
case FUNC_EVERY_SECOND:
|
case FUNC_EVERY_SECOND:
|
||||||
TimepropEverySecond();
|
TimepropEverySecond();
|
||||||
break;
|
break;
|
||||||
|
case FUNC_COMMAND:
|
||||||
|
result = TimepropCommand();
|
||||||
|
break;
|
||||||
case FUNC_SET_POWER:
|
case FUNC_SET_POWER:
|
||||||
TimepropXdrvPower();
|
TimepropXdrvPower();
|
||||||
break;
|
break;
|
||||||
|
@ -187,4 +249,5 @@ bool Xdrv48(byte function) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // FIRMWARE_MINIMAL
|
||||||
#endif // USE_TIMEPROP
|
#endif // USE_TIMEPROP
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef USE_PID
|
#ifdef USE_PID
|
||||||
|
#ifndef FIRMWARE_MINIMAL
|
||||||
/*********************************************************************************************\
|
/*********************************************************************************************\
|
||||||
* Uses the library https://github.com/colinl/process-control.git from Github
|
* Uses the library https://github.com/colinl/process-control.git from Github
|
||||||
* In user_config_override.h include code as follows:
|
* In user_config_override.h include code as follows:
|
||||||
|
@ -117,11 +118,6 @@
|
||||||
#define PID_REPORT_MORE_SETTINGS // If defined, the SENSOR output will provide more extensive json
|
#define PID_REPORT_MORE_SETTINGS // If defined, the SENSOR output will provide more extensive json
|
||||||
// output in the PID section
|
// output in the PID section
|
||||||
|
|
||||||
// #define PID_BACKWARD_COMPATIBLE // Preserve the backward compatible reporting of PID power via
|
|
||||||
// `%topic%/PID {"power":"0.000"}` This is now available in
|
|
||||||
// `%topic$/SENSOR {..., "PID":{"PidPower":0.00}}`
|
|
||||||
// Don't use unless you know that you need it
|
|
||||||
|
|
||||||
* Help with using the PID algorithm and with loop tuning can be found at
|
* Help with using the PID algorithm and with loop tuning can be found at
|
||||||
* http://blog.clanlaw.org.uk/2018/01/09/PID-tuning-with-node-red-contrib-pid.html
|
* http://blog.clanlaw.org.uk/2018/01/09/PID-tuning-with-node-red-contrib-pid.html
|
||||||
* This is directed towards using the algorithm in the node-red node node-red-contrib-pid but the algorithm here is based on
|
* This is directed towards using the algorithm in the node-red node node-red-contrib-pid but the algorithm here is based on
|
||||||
|
@ -271,26 +267,27 @@ void CmndSetPv(void) {
|
||||||
// this runs it at the next second
|
// this runs it at the next second
|
||||||
Pid.run_pid_now = true;
|
Pid.run_pid_now = true;
|
||||||
}
|
}
|
||||||
|
ResponseCmndFloat(atof(XdrvMailbox.data), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmndSetSp(void) {
|
void CmndSetSp(void) {
|
||||||
Pid.pid.setSp(atof(XdrvMailbox.data));
|
Pid.pid.setSp(atof(XdrvMailbox.data));
|
||||||
ResponseCmndNumber(atof(XdrvMailbox.data));
|
ResponseCmndFloat(atof(XdrvMailbox.data), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmndSetPb(void) {
|
void CmndSetPb(void) {
|
||||||
Pid.pid.setPb(atof(XdrvMailbox.data));
|
Pid.pid.setPb(atof(XdrvMailbox.data));
|
||||||
ResponseCmndNumber(atof(XdrvMailbox.data));
|
ResponseCmndFloat(atof(XdrvMailbox.data), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmndSetTi(void) {
|
void CmndSetTi(void) {
|
||||||
Pid.pid.setTi(atof(XdrvMailbox.data));
|
Pid.pid.setTi(atof(XdrvMailbox.data));
|
||||||
ResponseCmndNumber(atof(XdrvMailbox.data));
|
ResponseCmndFloat(atof(XdrvMailbox.data), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmndSetTd(void) {
|
void CmndSetTd(void) {
|
||||||
Pid.pid.setTd(atof(XdrvMailbox.data));
|
Pid.pid.setTd(atof(XdrvMailbox.data));
|
||||||
ResponseCmndNumber(atof(XdrvMailbox.data));
|
ResponseCmndFloat(atof(XdrvMailbox.data), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmndSetInitialInt(void) {
|
void CmndSetInitialInt(void) {
|
||||||
|
@ -300,7 +297,7 @@ void CmndSetInitialInt(void) {
|
||||||
|
|
||||||
void CmndSetDSmooth(void) {
|
void CmndSetDSmooth(void) {
|
||||||
Pid.pid.setDSmooth(atof(XdrvMailbox.data));
|
Pid.pid.setDSmooth(atof(XdrvMailbox.data));
|
||||||
ResponseCmndNumber(atof(XdrvMailbox.data));
|
ResponseCmndFloat(atof(XdrvMailbox.data), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmndSetAuto(void) {
|
void CmndSetAuto(void) {
|
||||||
|
@ -310,7 +307,7 @@ void CmndSetAuto(void) {
|
||||||
|
|
||||||
void CmndSetManualPower(void) {
|
void CmndSetManualPower(void) {
|
||||||
Pid.pid.setManualPower(atof(XdrvMailbox.data));
|
Pid.pid.setManualPower(atof(XdrvMailbox.data));
|
||||||
ResponseCmndNumber(atof(XdrvMailbox.data));
|
ResponseCmndFloat(atof(XdrvMailbox.data), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CmndSetMaxInterval(void) {
|
void CmndSetMaxInterval(void) {
|
||||||
|
@ -391,14 +388,14 @@ void PIDShowValues(void) {
|
||||||
|
|
||||||
void PIDRun(void) {
|
void PIDRun(void) {
|
||||||
double power = Pid.pid.tick(Pid.current_time_secs);
|
double power = Pid.pid.tick(Pid.current_time_secs);
|
||||||
#ifdef PID_BACKWARD_COMPATIBLE
|
#ifdef PID_DONT_USE_PID_TOPIC
|
||||||
// This part is left inside to regularly publish the PID Power via
|
// This part is left inside to regularly publish the PID Power via
|
||||||
// `%topic%/PID {"power":"0.000"}`
|
// `%topic%/PID {"power":"0.000"}`
|
||||||
char str_buf[FLOATSZ];
|
char str_buf[FLOATSZ];
|
||||||
dtostrfd(power, 3, str_buf);
|
dtostrfd(power, 3, str_buf);
|
||||||
snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"%s\":\"%s\"}"), "power", str_buf);
|
snprintf_P(TasmotaGlobal.mqtt_data, sizeof(TasmotaGlobal.mqtt_data), PSTR("{\"%s\":\"%s\"}"), "power", str_buf);
|
||||||
MqttPublishPrefixTopic_P(TELE, "PID", false);
|
MqttPublishPrefixTopic_P(TELE, "PID", false);
|
||||||
#endif // PID_BACKWARD_COMPATIBLE
|
#endif // PID_DONT_USE_PID_TOPIC
|
||||||
|
|
||||||
#if defined PID_SHUTTER
|
#if defined PID_SHUTTER
|
||||||
// send output as a position from 0-100 to defined shutter
|
// send output as a position from 0-100 to defined shutter
|
||||||
|
@ -443,4 +440,5 @@ bool Xdrv49(byte function) {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#endif //FIRMWARE_MINIMAL
|
||||||
#endif // USE_PID
|
#endif // USE_PID
|
||||||
|
|
Loading…
Reference in New Issue