Page 1 of 1
generating pulsesequence on GPIO
Posted: 19 May 2022, 07:13
by stepfl
sorry - I'm very new with EspEasy - up to now I was using Tasmota or Micropython. BUT - EspEasy seems to be very interesting for my project(s)!
NOW I've to connect ESP to a special Controller which has only a kind of PulseCounter as entry. So I try to generate/convert the measured Value to a pulsesequence.
The MaxFrequency of the entry is fixed to 10Hz ....
It should be something like:
Value:= 15 ==> pulsecode: (Startsequence): 1s:ON + 1s:OFF + (Value): 15 x ( 50ms ON / 50 ms:OFF) + (EndSequence): 1s:ON + 1s:OFF => OFF (default)....
i tried to do it like:
Code: Select all
// [VAR#4] : measured Value / START:pulldown GPIO#2
on GPIO#2 do
if [VAR#4]>0 and [GPIO#2]=1
delay 50
gpio,2,0
elseif [VAR#4]>0 and [GPIO#2]=0
delay 50
let,4,[VAR#4]-1
gpio,2,1
elseif [VAR#4]=0 and [GPIO#2]=0
delay 1000
gpio,2,1
else
delay 1000
endif
EndOn
I did not find anything like "while....loop" or a trigger like "on VAR#2 do" ....
So I have no Idea how to realise this within EspEasy ... and need your support...
stepfl
ps. Sorry about my english - i'm not used to write english
Re: generating pulsesequence on GPIO
Posted: 19 May 2022, 09:46
by TD-er
Calling delay in rules is not a good idea as it is blocking everything else.
Also when handling an event sent by the GPIO (assuming you used "monitor" to trigger events on GPIO changes for that specific pins), the state of the pin from the moment the event was triggered is included in the event.
The event is like GPIO#2=1
This means it is better to evaluate using %eventvalue1% instead of [gpio#2] as the latter one may have changed in the mean time.
You can create a looptimer, even with a fixed nr of loops.
There is also a looptimerset_ms for millisec resolution.
See:
https://espeasy.readthedocs.io/en/lates ... oop-timers
Re: generating pulsesequence on GPIO
Posted: 19 May 2022, 10:01
by stepfl
thanks a lot ....
YES - i know ... to use delay is not a good idea ... and checking the GPIO too... this was the result of my "don't know how to..."
looptimerset_ms seems to be the solution - a easy one too ... I'll try it this evening ... thanks a lot!
AND .... the stuff of how it works with "eventvalue1% - i don't understand ... probably because my English is really not the best...
Re: generating pulsesequence on GPIO
Posted: 19 May 2022, 10:51
by TD-er
Just a very short explanation.
Events can have 0 or more event values.
For example, a task reporting a new sample of a sensor typically sends out events like this (task is called "bme", task value is "temp", or whatever you named them)
bme#temp=12.34
You can act on this in the rules like this:
Code: Select all
on bme#temp do
logentry,"Temperature is %eventvalue1% degree C"
endon
This will send out a log with a string like this: "Temperature is 12.34 degree C"
As you can see, the %eventvalue1% is replaced by the 1st event value (the first value after the = in the full event)
Other events may have multiple event values, like when you check the checkbox in a task to send all values in a single event:
bme#All=12.34,76.0,1023.4
If memory serves me well, then the order of the values from the BME280 sensor will be sent in the order of temp/hum/pressure.
Thus %eventvalue1% = 12.34
%eventvalue2% = 76.0 (humidity)
%eventvalue3% = 1023.4 (barometric pressure)
See also:
https://espeasy.readthedocs.io/en/lates ... eventvalue
Re: generating pulsesequence on GPIO
Posted: 19 May 2022, 10:52
by TD-er
By the way, if you need short timings for the looptimer, please use the latest build as the rules processing speed has significantly improved.
Re: generating pulsesequence on GPIO
Posted: 19 May 2022, 12:55
by stepfl
my first trial of ... :
actual i use GPIO2 becaus of the LED :_)
to change easily the TimeValues i use:
VAR#7:Time of Start-/StopSequencePulse (actual 2000ms),
VAR#6: Time of DataSequencePulse (actual 200ms) /
VAR#5: defines START / DATA / STOP
VAR#4: Value to be send
Code: Select all
// Output: PulseSequenz of VAR#4
On Rules#Timer=1 do
if [var#5] = [VAR#7] // START
timerset_ms,1,[VAR#5]*2
pulse,2,0,[VAR#5]
if [VAR#4]>0
let,5,[VAR#6] // Data
endif
elseif [var#5] = [VAR#6]
timerset_ms,1,[VAR#5]*2
pulse,2,0,[VAR#5]
let 4,[VAR#4]-1
if [VAR#4]= 0
let,5,0
pulse,2,0,[VAR#7] // STOP
timerset_ms,1,[VAR#7]*2
endif
else
GPIO,2,1
timerset_ms,1,0
endif
endon
it seems to work fine
Question:
Does "Pulse" also blocking everything else? ...
"by the way" .... yes I do it - i flashed just few days ago ... THANKS für your help!!!
Re: generating pulsesequence on GPIO
Posted: 19 May 2022, 13:40
by stepfl
probably you could be so nice and check the other part .... calulation of a moving average...
the Reason:
the Data of VL53L0X ( 100mmm ... 1600mm) jump a lot and I didn't want to wait too long for the first usable Data...
VAR#10: actual runnicng counter of MWs in the sum of MWs (VAR#1)
VAR#2: actual moving average
VAR#4: Data to be send per PulseSequence
Code: Select all
On System#Boot do
delay 50
let,3,50 // max Change (Messwert-Mittelwert)
let,6,500 // MW-Puls [ms]
let,7,1000 // Start/Stop-Pulse [ms]
let,9,30 // maxCount MWs
GPIO,2,1 //PulsData-Output
endon
// moving average:
On OilLevel#Distance Do // VL53L0X - LaserDistanceSensor
// (Re-)START
if [VAR#10]=0
let,1,0
Let,2,[VAR#1]
endif
// change to much > [VAR#3]
if abs([OilLevel#Distance]-[VAR#2]) > [VAR#3]
Let,10,1
let,1,[OilLevel#Distance]
let,2,[VAR#1]
endif
// Data-Sum
if [VAR#10]<[VAR#9]
Let,10,[VAR#10]+1
Let,1,[VAR#1]+[OilLevel#Distance]
else
Let,1,round([VAR#1]*([VAR#10]-1)/[VAR#10])+[OilLevel#Distance]
endif
// Calc.moving Average:
if round([VAR#1]/[VAR#10])!=[VAR#2]
Let,2,round([VAR#1]/[VAR#10])
if [VAR#5]=0 and [VAR#10] = [VAR#9]
// START ImpulsSequenz
Let,4,round([VAR#2]/10) //Ausgabewert
let,5,[VAR#7]
timerset_ms,1,0 // START PulsAusgabe
endif
endif
EndOn
It is probably not the best coding but it works ...
Have a good time !!!
Re: generating pulsesequence on GPIO
Posted: 19 May 2022, 14:03
by TD-er
stepfl wrote: ↑19 May 2022, 12:55
[...]
Question:
Does "Pulse" also blocking everything else? ...
"by the way" .... yes I do it - i flashed just few days ago ... THANKS für your help!!!
Yep pulse does "block" execution, where "longpulse" and "longpulse_ms" do not.
For very short pulses this does not really matter, but for those a bit longer than a few tens of msec it may be an issue.
On the other hand, the rules execution continues after starting the longpulse, so if you plan on doing things during this pulse with that GPIO pin, then you might see some unexpected behavior.
The same for "event" vs. "asyncevent"
It is best to call "asyncevent" from within the rules as that will queue the event to the eventqueue.
But on the other hand, sometimes you need to have things done right now, so then call "event".
Side effect is that it will block rules execution longer and when calling event from event recursively you may exceed the resources of the ESP and cause it to crash (or simply give an error...)
And for someone who just started with ESPEasy you're writing rather complex rules already.
Re: generating pulsesequence on GPIO
Posted: 19 May 2022, 14:28
by TD-er
stepfl wrote: ↑19 May 2022, 13:40
probably you could be so nice and check the other part .... calulation of a moving average...
the Reason:
the Data of VL53L0X ( 100mmm ... 1600mm) jump a lot and I didn't want to wait too long for the first usable Data...
VAR#10: actual runnicng counter of MWs in the sum of MWs (VAR#1)
VAR#2: actual moving average
VAR#4: Data to be send per PulseSequence
Code: Select all
On System#Boot do
delay 50
let,3,50 // max Change (Messwert-Mittelwert)
let,6,500 // MW-Puls [ms]
let,7,1000 // Start/Stop-Pulse [ms]
let,9,30 // maxCount MWs
GPIO,2,1 //PulsData-Output
endon
// moving average:
On OilLevel#Distance Do // VL53L0X - LaserDistanceSensor
// (Re-)START
if [VAR#10]=0
let,1,0
Let,2,[VAR#1]
endif
// change to much > [VAR#3]
if abs([OilLevel#Distance]-[VAR#2]) > [VAR#3]
Let,10,1
let,1,[OilLevel#Distance]
let,2,[VAR#1]
endif
// Data-Sum
if [VAR#10]<[VAR#9]
Let,10,[VAR#10]+1
Let,1,[VAR#1]+[OilLevel#Distance]
else
Let,1,round([VAR#1]*([VAR#10]-1)/[VAR#10])+[OilLevel#Distance]
endif
// Calc.moving Average:
if round([VAR#1]/[VAR#10])!=[VAR#2]
Let,2,round([VAR#1]/[VAR#10])
if [VAR#5]=0 and [VAR#10] = [VAR#9]
// START ImpulsSequenz
Let,4,round([VAR#2]/10) //Ausgabewert
let,5,[VAR#7]
timerset_ms,1,0 // START PulsAusgabe
endif
endif
EndOn
It is probably not the best coding but it works ...
Have a good time !!!
You can also use some tricks like this:
This can be used as an index over a row of variables.
So you know where to put the latest measured value and can subtract the old value at that position from the computed sum.
For example you have reserved var#101 .. 110 to keep track of the last 10 samples and #100 is the pointer to the current sample. (sum = #99 and count is #98
On a new sample you do something like this:
Code: Select all
if [int#98] > 0
let,98,[int#98]-1 // decrease count
let,99,[var#99] - [var#[int#100]] // Remove oldest from the sum
endif
let,98,[int#98]+1 // increment counter
let,99,[var#99] + %eventvalue1%
let,[int#100],%eventvalue1%
let,100,[int#100] + 1
if [int#100] > 110
let,100,101
endif
Re: generating pulsesequence on GPIO
Posted: 19 May 2022, 19:09
by stepfl
this project should measure the Level of Oil in the Tank.
The LX... works very fine in the rang up to 1m then it starts to jump around. => moving average ...
The HeatingController (Heizungssteuerung) has not so many possibilities to enter the Oillevel-Data - the best way is to send PulseCodes ... but has a website to see what is going on
The Event from the LX..Device and of the PulsSequence doesn't fit very well - makes the PulseSequence jumping (stolpern) a litte bit.
The Oillevel doesn't jump - for shure ... so it would be no problem to have times without measurements..
So - i would like to disable the Sensor while sending the PulseSequence... is there any possibility to turn off this/a device ... and later on restart it ...
In Tasmota it was very nice to have alternative rules which you could turn on or of ... I didn't find similar command in EspEasy ...
Your other hints - i'll try them next weekend...
AND - again - thanks a lot for .... (everything)
Have a good evening, stepfl
Re: generating pulsesequence on GPIO
Posted: 19 May 2022, 20:36
by Ath
stepfl wrote: ↑19 May 2022, 19:09
this project should measure the Level of Oil in the Tank.
The LX... works very fine in the rang up to 1m then it starts to jump around. => moving average ...
Have you tried the VL53L1X? That has a range up to 4 meter, where the VL53L0X has a max range of 2 meter, suggesting that a VL53L1X could give more stable results in the range you need. It uses a different plugin but with a very similar feature set. (I wrote both plugins, using tried and proven Arduino libraries) The VL53L1X also has a 'Trigger delta' setting to even out small measurement inaccuracies.
stepfl wrote: ↑19 May 2022, 19:09
So - i would like to disable the Sensor while sending the PulseSequence... is there any possibility to turn off this/a device ... and later on restart it ...
That is what the commands "taskenable,<taskname_or_tasknumber>" and "taskdisable,<taskname_or_tasknumber>" are for
Or an alternative could be to set a variable while sending out the pulse, so the event only starts a new send action if it is not set.
Code: Select all
on OilLevel#Distance do
if [var#999] = 0
... existing code
endif
endon
Then, just before starting the send action, use "Let,999,1" to inhibit a new trigger, and after completion of the send, use "Let,999,0" to re-enable it
Re: generating pulsesequence on GPIO
Posted: 19 May 2022, 22:20
by stepfl
Ath wrote: ↑19 May 2022, 20:36
Have you tried the VL53L1X? That has a range up to 4 meter, where the VL53L0X has a max range of 2 meter ...
Yes I did and I 'll use it .... but - in this case (dimesion of the "Platine") I'll prefere the LX53L0X...
and the moving Average with enough points ist slowlier but is good enough...
Ath wrote: ↑19 May 2022, 20:36
That is what the commands "taskenable,<taskname_or_tasknumber>" and "taskdisable,<taskname_or_tasknumber>" are for
hmmm ...
I'm not so trained in programming and even more in reading English texts ... for me it's hard work
...
I read this stuff - but ... Where can i find the tasknumber or the Taskname ...? causes stress in my head ...
(sorry) ... is it to be found in the device-table? ... or where???
Ath wrote: ↑19 May 2022, 20:36
Or an alternative could be to set a variable while sending out the pulse, so the event only starts a new send action if it is not set.
Code: Select all
on OilLevel#Distance do
if [var#999] = 0
... existing code
endif
endon
Then, just before starting the send action, use "Let,999,1" to inhibit a new trigger, and after completion of the send, use "Let,999,0" to re-enable it
This is the way i tried to realize it ... but it (PulsSequence) is still stumbling ... I think because other events needs their time too...
Have a good night - and I'm proud to talk woth one of the profies ...
)
Re: generating pulsesequence on GPIO
Posted: 19 May 2022, 23:42
by Ath
The Taskname is the Name you gave the device, the number is listed in the Devices list (1..12 on ESP8266, 1..32 for ESP32 device).
Time-critical stuff is quite hard to realize using rules, because of the text-processing of the script taking some time, even now that it has improved already very much in recent weeks.
The VL53L0X and VL53L1X are the same form-factor boards here, I had to use a magnifying glass to see the difference (and now I have marked them, of course
)
Re: generating pulsesequence on GPIO
Posted: 20 May 2022, 08:49
by stepfl
what is the reason formultible "rules set x" ?
Is there any difference in handling the code within different Rules Sets?
Thanks - stepfl
Re: generating pulsesequence on GPIO
Posted: 20 May 2022, 08:54
by TD-er
There used to be a limit of 2k on the size of the rules file.
This was due to the fact that when saving the file, it was sent as a HTTP POST, meaning it must be in memory of the ESP before saving it.
In practice on an ESP8266 this limit was even less (between 1500 and 1700 bytes) resulting in an incomplete saved file.
But now we use some JavaScript to "upload" the file in the background. So the ESP does not need to keep the entire file in memory and thus there is not really a limit in size anymore.
Still from a performance point of view, I would suggest to keep the file a bit small (<8k), expecially on ESP8266.
Re: generating pulsesequence on GPIO
Posted: 20 May 2022, 10:22
by stepfl
Thanks ....
so all rules sets are finally one big programm-area...
this is a big difference to Tasmota ... BUT EspEasy a a very nice stuff ... much to huge for my old brain ... THANKS A LOT !!!
AND: with <TaskDisable> and <TaskEnable> my project works fine .. THIS is the final code....(if somebody else is interested in) ...
Code: Select all
On System#Boot do
GPIO,2,1
delay 500
let,100,60 // PulsOutput every xx sec
let,110,3000 // Distance to ground to calc the real OilLevel
let,111, 1.272 // ltr per cm
TaskEnable,1 // Start LX53L0X
timerset,2,[VAR#100] // Start PulseSequenceTimer
endon
// moving Average:
On LX53L0X#Distance Do
GPIO,2,1
// change to much > [VAR#3] => RESTART
if abs([LX53L0X#Distance]-[VAR#2])>[VAR#3]
Let,10,0
endif
// (Re-)START
if [VAR#10]=0
GPIO,2,1
Let,1,[LX53L0X#Distance]
Let,2,[VAR#1]
Let,3,50 // max Change (measured Value - moving average)
Let,5,0
Let,6,100 // length of Data-Puls [ms]
Let,7,2000 // length of Start/Stop-Pulse [ms]
Let,9,30 // max Number of Elements in moving Average
Let,10,1
endif
// Calc of Moving Average and the reported Value VAR#4
if [VAR#10]<[VAR#9]
Let,10,[VAR#10]+1
Let,1,[VAR#1]+[LX53L0X#Distance]
else
Let,1,round([VAR#1]*([VAR#10]-1)/[VAR#10])+[LX53L0X#Distance]
endif
Let,2,round([VAR#1]/[VAR#10])
if [VAR#2]<=[VAR#110]-50
Let,4,round(([VAR#110]-[VAR#2])/10) // Oil [*10 ltr]
else
let,4,35 // limit min.OilLevel
endif
logentry,[VAR#4] "cm OilNiveau"
let,112, round([Var#4]*[VAR#111])
logentry,[VAR#112] "x10 ltr Heizöl"
EndOn
on Rules#Timer=2 do // Timer to start Report
GPIO,2,1
if [VAR#10]=[VAR#9] and [VAR#4]>30
TaskDisable,1
GPIO,2,1
Let,5,[VAR#7]
delay 500
timerset_ms,1,5
else
TaskEnable,1
endif
timerset,2,[VAR#100]
EndOn
// PulseSequenz- Output
On Rules#Timer=1 do
timerset_ms,1,[VAR#5]*2
pulse,2,0,[VAR#5]
if [VAR#5] = [VAR#7] // START
let,5,[VAR#6]
elseif [VAR#4]>0 // Data
let 4,[VAR#4]-1
if [VAR#4]=0 //STOP
let,5,0
timerset_ms,1,[VAR#7]*2
pulse,2,0,[VAR#7]
TaskEnable,1
endif
endif
endon
Finally I'll change the GPIO for Output ... and fit all parameter to the real situation ...
byby ,, until the next problems
Re: generating pulsesequence on GPIO
Posted: 20 May 2022, 10:34
by TD-er
Well you can see it as "a number of small program areas" as in principle you have a lot of blocks like these:
Each of these are called on events.
Some of them are system generated like WiFi#connected and many more.
Some are generated from tasks, so they have the names you made up yourself like garden#temperature.
And you can also call events you think of yourself and write a rules block for them like for example:
Code: Select all
// Calling the event from somewhere
// The "123" is an eventvalue you just give along with the event
event,MyEvent=123
on MyEvent do
logEntry,"Handling MyEvent, value is: %eventvalue1%"
endon
And on top of that, you can set variables which can be used anywhere else. These variables have a longer "lifespan" than the handling of the event itself.
It might seem a bit overwhelming at first, but what I'm trying to tell you is that you can start with very basic simple steps and then when you get the idea you can continue to expand.
It is nearly without limits and as soon as we found those I will make sure to help you overcome those limits by adding new features to it
Re: generating pulsesequence on GPIO
Posted: 20 May 2022, 11:04
by stepfl
thanks for all of this stuff....
BUT...
:
in Tasmote it is very fine to generate a kind of blocks of events (rule1 / rule2/ ...) - and by deactivating such a block all events written in it are disabled - or - activating/enable.
In my case I would have separated "DataCalculation" and "PulseCodeReport" in two "rules" and switched between them ....
This allows to write more variants of handling the same situation - depending on which block is activatet ...
Not necessary .. but sometimes helpful and nice
" waling on a high level"
( a kind of german saying "Jammern auf hohem Niveau")
Re: generating pulsesequence on GPIO
Posted: 20 May 2022, 11:12
by TD-er
Well all the rules files are parsed in order.
So if you want to disable an event block, you may need to edit it, or add some small check to it using a variable.
I guess it can be a nice feature to disable or suppress events.
Not many requests have been for it.
Re: generating pulsesequence on GPIO
Posted: 20 May 2022, 11:17
by Ath
TD-er wrote: ↑20 May 2022, 11:12
I guess it can be a nice feature to disable or suppress events.
Not many requests have been for it.
... only by some ppl migrating from Tasmota
Re: generating pulsesequence on GPIO
Posted: 20 May 2022, 11:19
by TD-er
Well there have been requests to disable whole rule files, even from before Tasmota had their rules system as they have now.
Re: generating pulsesequence on GPIO
Posted: 20 May 2022, 14:17
by stepfl
Ath wrote: ↑20 May 2022, 11:17
TD-er wrote: ↑20 May 2022, 11:12
I guess it can be a nice feature to disable or suppress events.
Not many requests have been for it.
... only by some ppl migrating from Tasmota
NO !!! .... normally I use python / micropython ...
But i found this method/possibility very help- and powerful ... a kind of "Master-Device" to handle several other devices/events as a group .....
On the other hand EspEasy has many really powerful commands ... f.e. <TaskDisable> ....
so don't mind ....
I'm glad ...