Sonoff-Tasmota icon indicating copy to clipboard operation
Sonoff-Tasmota copied to clipboard

Fast relay switching based on power increase

Open tobetobe66 opened this issue 4 years ago • 92 comments

Hi Gemu,

thanks a lot for the beautiful scripting feature.

I am using a Gosund SP1, GPIO4: 134, GPIO5: 132, GPIO12: 131, GPIO14: 21. I am monitoring power and switch off the relay as soon as power is over 1 Watt using the following code:

T _pow=ENERGY#Power

F . . . if ((_pow>1) and (_s==S)) { ->power1 0 e_eP=1 }

This works perfectly fine, however it takes sometimes way above 1 second for the relay to switch off. This is a bit too slow for me. The load is 800W, power rise should be instant. Is there a way to do this faster? Maybe it's not possible at all, because sampling rate of power measurement is too slow.

I would be grateful for some ideas. Thank you very much.

tobetobe66 avatar May 21 '20 08:05 tobetobe66

Hi,

you get the power in the >T section. this is normally sampled on teleperiod time only at max every 10 seconds. you can verify that by printing a time stamp in the >T section e.g. print tele var at %upsecs%

i dont know the internals of the gosund driver and how we could get a faster access to the power register.

as far as i know there is a tasmota cmd to set limits also.

you might set such a limit and receive the alarm in the >E section

this approach may be faster

Am 21.05.2020 um 10:09 schrieb tobetobe66 [email protected]:

Hi Gemu,

thanks a lot for the beautiful scripting feature.

I am using a Gosund SP1, GPIO4: 134, GPIO5: 132, GPIO12: 131, GPIO14: 21. I am monitoring power and switch off the relay as soon as power is over 1 Watt using the following code:

T _pow=ENERGY#Power

F . . . if ((_pow>1) and (_s==S)) { ->power1 0 e_eP=1 }

This works perfectly fine, however it takes sometimes way above 1 second for the relay to switch off. This is a bit too slow for me. The load is 800W, power rise should be instant. Is there a way to do this faster? Maybe it's not possible at all, because sampling rate of power measurement is too slow.

I would be grateful for some ideas. Thank you very much.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/gemu2015/Sonoff-Tasmota/issues/21, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACY3QY4FU2EXRLCW2FNUSH3RSTOSPANCNFSM4NGUNWAA.

gemu2015 avatar May 21 '20 08:05 gemu2015

Thank you. I will check.

tobetobe66 avatar May 21 '20 08:05 tobetobe66

OK, I found some cmds that might be of help. Have to do a bit of reading and testing. Will report back once done.

tobetobe66 avatar May 21 '20 09:05 tobetobe66

because if found this an interesting application i implemented direct access to some energy registers which are updated instantly. try my new version! i however don't know how they are mapped in gosund

enrg[0] = should be total energy enrg[1] = voltage p1 enrg[2] = voltage p2 enrg[3] = voltage p3 enrg[4] = current p1 enrg[5] = current p2 enrg[6] = current p3

gemu2015 avatar May 21 '20 09:05 gemu2015

you need to define #define USE_ENERGY_SENSOR

gemu2015 avatar May 21 '20 09:05 gemu2015

updated again after testing with my MODBus device added 3 power regs enrg[7] = power p1 enrg[8] = power p2 enrg[9] = power p3

for a single phase meter only p1 values should be > 0

gemu2015 avatar May 21 '20 10:05 gemu2015

OK,

what I tried so far is using cmd powerdelta and cmd powerhigh. I catch the event in the E-Section:

E print EVENT if ((_pow>PON) and (_s==S)) { ->power1 0 e_eP=1 }

_pow is still in T-Section.

The result is comparable to what I had before doing polling in the F-Section. 0.5-2 seconds.

My application is a network of Gosunds to do load managment of the devices attatched to them. I need this. because I am partly OFFGRID and my inverter is limited in power. Therefor I have to detect if a device attached to a Gosund is switched on by the user. This has to be done in a very short time, as the inverter can take some overload for a short amount of time.

tobetobe66 avatar May 21 '20 12:05 tobetobe66

Thank you for the energy registers. I will give it a try and report. Thanks a lot.

tobetobe66 avatar May 21 '20 12:05 tobetobe66

you may also speed up relay switching by directly setting the relay GPIO by spin(x 1) don't know how fast ->power1 is

gemu2015 avatar May 21 '20 13:05 gemu2015

I already compared spin vs ->power, there is not much difference. However I still had relay 1 defined, because otherwise power measurement didn't work. Just found out today that there is a switch to enable power measurement when power is off. Might give that a try later and compare spin vs ->power again, however I do not expect any speedup. Just compiled your version, will check energy registers now.

tobetobe66 avatar May 21 '20 14:05 tobetobe66

Hi Gemu,

holy cow, it works!! It is fast and reliable with respect to switching time. I am way below 1 second all the time.

T ;_pow=ENERGY#Power

F if ((enrg[4]>0.01) and (_s==S)) { ;->power1 0 spin(14 0) e_eP=1 }

In the above example I used current instead of power, however that does not make a difference. Using the registers I can skip the T-Section, saving script space, which is prime to me. Will you include the registers feature in a PR? That would be very helpful.

Thank you so much.

I have another issue which is not bothering me anymore because I found a work around. Anyway, I noticed a strange behavior using the short form of if, then, else, i.e. if {} else {}. Once enclosed in a subroutine it was gone. I will do some further testing with respect to this and maybe come back to you.

Best regards Tobi

tobetobe66 avatar May 21 '20 14:05 tobetobe66

glad that it worked!

if script size is important, use the new compress option! #define USE_SCRIPT_COMPRESSION (script is deleted after 1. install, so have a copy) gives you about 50% more space

i do frequent prs every 2 or 3 days, until then use my fork

Am 21.05.2020 um 16:57 schrieb tobetobe66 [email protected]:

Hi Gemu,

holy cow, it works!! It is fast and reliable with respect to switching time. I am way below 1 second all the time.

T ;_pow=ENERGY#Power

F if ((enrg[4]>0.01) and (_s==S)) { ;->power1 0 spin(14 0) e_eP=1 }

In the above example I used current instead of power, however that does not make a difference. Using the registers I can skip the T-Section, saving script space, which is prime to me. Will you include the registers feature in a PR? That would be very helpful.

Thank you so much.

I have another issue which is not bothering me anymore because I found a work around. Anyway, I noticed a strange behavior using the short form of if, then, else, i.e. if {} else {}. Once enclosed in a subroutine it was gone. I will do some further testing with respect to this and maybe come back to you.

Best regards Tobi

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/gemu2015/Sonoff-Tasmota/issues/21#issuecomment-632133067, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACY3QY6Y54Z7R2AUCIAZTJLRSU6N5ANCNFSM4NGUNWAA.

gemu2015 avatar May 21 '20 15:05 gemu2015

I read about rule buffer being compressed. Was hoping for that to happen for scripting also. Great. Thanks a lot. Shall I close the Issue?

tobetobe66 avatar May 21 '20 15:05 tobetobe66

leave open, better to find for others

gemu2015 avatar May 21 '20 15:05 gemu2015

Hi Gemu,

Just noticed that every time I access a register a mqtt message is sent:

tele/DVES_XXXXX/SENSOR = {"Time":"2020-05-22T17:34:38","ENERGY":{"TotalStartTime":"2019-04-07T18:00:28","Total":0.085,"Yesterday":0.003,"Today":0.042,"Power":0,"ApparentPower":0,"ReactivePower":0,"Factor":0.00,"Voltage":238,"Current":0.000}}

Is there a way to switch this off as it is causing a lot of traffic? Am I missing a Tasmota switch to turn it off?

Thanks. Cheers tobi

tobetobe66 avatar May 22 '20 16:05 tobetobe66

Hi tobi, accessing the register should not generate a MQTT message. it is just the same as reading an internal variable. must be caused by something else. you may switch off MQTT completely but i guess that is not what you want.

this is a tele message that should be generated every teleperiod seconds.

Greets Gerhard

gemu2015 avatar May 22 '20 17:05 gemu2015

Hmmm, strange. Checking again. I was accessing the register in the >S section and I got mqtt messages every second. I will do some further testing. Teleperiod is definitely switched off (0). I cannot switch off mqtt, as this is the way may Gosunds communicate. I will be back. Thanks for fast reply

tobetobe66 avatar May 22 '20 17:05 tobetobe66

OK, got it. Running three Gosunds in parallel, one had teleperiod on 300. thats the one I checked. Sorry for bothering you.

tobetobe66 avatar May 22 '20 18:05 tobetobe66

Hi Gemu,

is it possible to change the last will and testament to a different topic from within the script? The standard seems to be: tele/DVES_XXXXXXX/LWT. I would like to change it for example to: abc/LWT.

Thanks a lot Tobi

tobetobe66 avatar May 23 '20 07:05 tobetobe66

Hi Tobi

i have not much knowledge about this MQTT stuff. scripter may only manipulate those settings via tasmota cmds. if there is no Tasmota cmd for changing these items you might make a feature request to Tasmota dev.

Greets Gerhard

Am 23.05.2020 um 09:59 schrieb tobetobe66 [email protected]:

Hi Gemu,

is it possible to change the last will and testament to a different topic from within the script? The standard seems to be: tele/DVES_XXXXXXX/LWT. I would like to change it for example to: abc/LWT.

Thanks a lot Tobi

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/gemu2015/Sonoff-Tasmota/issues/21#issuecomment-633003847, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACY3QY4H5SGARN535CZQQGDRS565TANCNFSM4NGUNWAA.

gemu2015 avatar May 23 '20 08:05 gemu2015

OK. Thx a lot. I will check the code first. Maybe I can hard code it. Tobi

tobetobe66 avatar May 23 '20 08:05 tobetobe66

Hi Gerhard,

the following script gives me a hard time:

D m:p_array=0 10 x=1 cnt=1

B for cnt 1 10 1 if cnt<4 then print %cnt% else break endif next

print end print %cnt%

It seems like the break terminates the whole B section, as I get the following output: 1 2 3

and nothing else. I really do not get it.

Thx Tobi

tobetobe66 avatar May 23 '20 21:05 tobetobe66

Hi Tobi,

This was a bug! is fixed now.

Gerhard

gemu2015 avatar May 24 '20 05:05 gemu2015

Thanks Gerhard. glad I found one! :-)

Tobi

tobetobe66 avatar May 24 '20 06:05 tobetobe66

Hello Gerhard,

see below the result of a fast polling of enrg7 and enrg3 on my gosunds after switching off. Power (left column) still gives values long after switch off and is oscillating, whereas current is zero as it should be. As I use current it does not bother me, however the behaviour of enrg7 seems strange.

Tobi

08:25:26 P: 0.00 I: 0.00 08:25:26 P: 13.80 I: 0.00 08:25:26 P: 13.80 I: 0.00 08:25:26 P: 13.80 I: 0.00 08:25:26 P: 13.80 I: 0.00 08:25:26 P: 13.80 I: 0.00 08:25:26 P: 0.00 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 0.00 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:28 P: 13.80 I: 0.00 08:25:28 P: 0.00 I: 0.00

tobetobe66 avatar May 25 '20 07:05 tobetobe66

Hi Tobi

i get the values from the energy driver, do not know how this is wired with your device may be another register would be better, there a plenty of them, see below

could it be that your devices resolution is only 13.8 Watts? then 1 bit noise could produce this result

Gerhard

scripter => switch ((uint32_t)fvar) { case 0: fvar=Energy.total; break; case 1: fvar=Energy.voltage[0]; break; case 2: fvar=Energy.voltage[1]; break; case 3: fvar=Energy.voltage[2]; break; case 4: fvar=Energy.current[0]; break; case 5: fvar=Energy.current[1]; break; case 6: fvar=Energy.current[2]; break; case 7: fvar=Energy.active_power[0]; break; case 8: fvar=Energy.active_power[1]; break; case 9: fvar=Energy.active_power[2]; break;

=> energy driver struct

struct ENERGY { float voltage[3] = { 0, 0, 0 }; // 123.1 V float current[3] = { 0, 0, 0 }; // 123.123 A float active_power[3] = { 0, 0, 0 }; // 123.1 W float apparent_power[3] = { NAN, NAN, NAN }; // 123.1 VA float reactive_power[3] = { NAN, NAN, NAN }; // 123.1 VAr float power_factor[3] = { NAN, NAN, NAN }; // 0.12 float frequency[3] = { NAN, NAN, NAN }; // 123.1 Hz

// float import_active[3] = { NAN, NAN, NAN }; // 123.123 kWh float export_active[3] = { NAN, NAN, NAN }; // 123.123 kWh

float start_energy = 0; // 12345.12345 kWh total previous float daily = 0; // 123.123 kWh float total = 0; // 12345.12345 kWh total energy

unsigned long kWhtoday_delta = 0; // 1212312345 Wh 10^-5 (deca micro Watt hours) - Overflows to Energy.kWhtoday (HLW and CSE only) unsigned long kWhtoday_offset = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily unsigned long kWhtoday; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily unsigned long period = 0; // 12312312 Wh * 10^-2 (deca milli Watt hours) - 5764 = 0.05764 kWh = 0.058 kWh = Energy.daily

uint8_t fifth_second = 0; uint8_t command_code = 0; uint8_t data_valid[3] = { 0, 0, 0 };

uint8_t phase_count = 1; // Number of phases active bool voltage_common = false; // Use single voltage bool frequency_common = false; // Use single frequency bool kWhtoday_offset_init = false;

bool voltage_available = true; // Enable if voltage is measured bool current_available = true; // Enable if current is measured

bool type_dc = false; bool power_on = true;

#ifdef USE_ENERGY_MARGIN_DETECTION uint16_t power_history[3] = { 0 }; uint8_t power_steady_counter = 8; // Allow for power on stabilization bool power_delta = false; bool min_power_flag = false; bool max_power_flag = false; bool min_voltage_flag = false; bool max_voltage_flag = false; bool min_current_flag = false; bool max_current_flag = false;

#ifdef USE_ENERGY_POWER_LIMIT uint16_t mplh_counter = 0; uint16_t mplw_counter = 0; uint8_t mplr_counter = 0; uint8_t max_energy_state = 0; #endif // USE_ENERGY_POWER_LIMIT #endif // USE_ENERGY_MARGIN_DETECTION } Energy;

Am 25.05.2020 um 09:46 schrieb tobetobe66 [email protected]:

Hello Gerhard,

see below the result of a fast polling of enrg7 and enrg3 on my gosunds after switching off. Power (left column) still gives values long after switch off and is oscillating, whereas current is zero as it should be. As I use current it does not bother me, however the behaviour of enrg7 seems strange.

Tobi

08:25:26 P: 0.00 I: 0.00 08:25:26 P: 13.80 I: 0.00 08:25:26 P: 13.80 I: 0.00 08:25:26 P: 13.80 I: 0.00 08:25:26 P: 13.80 I: 0.00 08:25:26 P: 13.80 I: 0.00 08:25:26 P: 0.00 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 0.00 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:27 P: 13.80 I: 0.00 08:25:28 P: 13.80 I: 0.00 08:25:28 P: 0.00 I: 0.00

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/gemu2015/Sonoff-Tasmota/issues/21#issuecomment-633430843, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACY3QYZADPOWVCR3P2OVOULRTIO33ANCNFSM4NGUNWAA.

gemu2015 avatar May 25 '20 08:05 gemu2015

Energy resolution is far better than 13.8Watts. I don't think its because of noise. I can only use two registers, as it is a one phase system. I can live with the current register.

Was just wondering about the readings of the power register. It reads 13.8W long after the device is switched off and also when current is already 0 for some time.

tobetobe66 avatar May 25 '20 08:05 tobetobe66

Dear Gerhard,

the docu states: There are two syntax alternatives for conditional statements (if, then, else or if {} else {}). You may NOT mix both formats.

Does this NOT mixing refer to the whole script or just to not nesting both formats?

Thx Tobi

tobetobe66 avatar May 26 '20 13:05 tobetobe66

Hi Tobi,

just messing in one condition is not supported.

Gerhard

Am 26.05.2020 um 15:38 schrieb tobetobe66 [email protected]:

Dear Gerhard,

the docu states: There are two syntax alternatives for conditional statements (if, then, else or if {} else {}). You may NOT mix both formats.

Does this NOT mixing refer to the whole script or just to not nesting both formats?

Thx Tobi

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/gemu2015/Sonoff-Tasmota/issues/21#issuecomment-634030707, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACY3QY6MQ7QT4MDPGVVRFWLRTPA55ANCNFSM4NGUNWAA.

gemu2015 avatar May 26 '20 13:05 gemu2015

Hi Gerhard,

I have a strange behavior in the following code if I change the highlighted section from if then to if{}. The function FSM is called from the F Section. It does not work with, however both variants should be equivalent. if e_eP==1 { _s=N sc=1 }

If I use {} the part with e_Te=0 e_Mr=0 e_eP=0

seems to be skipped. I.E. in the print statement e_Mr is 1 instead of zero. I do not see where I could have made an error as it works with if then.

Thx Tobi

#FSM print BEG FSM: sc:%sc% State:%_s% e_eP: %e_eP%, e_Te: %e_Te% e_Mr: %e_Mr% sc=0 switch _s case S print S ->power1 1 _if e_eP==1 then s=N sc=1 endif

case N print N ->power1 0 if r==1 then _s=O sc=1 endif

case O print O ->power1 1 ends

print clear events e_Te=0 e_Mr=0 e_eP=0

print EOF FSM: sc:%sc% State:%_s% e_eP: %e_eP%, e_Te: %e_Te% e_Mr: %e_Mr%

tobetobe66 avatar May 26 '20 15:05 tobetobe66