Difference between revisions of "Manual:Flexible Logic"

From rusEfi
Jump to navigation Jump to search
(Case study #4: boost controller)
 
(27 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
''Flexible Logic'' is the fanciest-schmanciest feature of rusEfi.
 
''Flexible Logic'' is the fanciest-schmanciest feature of rusEfi.
 +
 +
For FSIO, rusEfi console provides a better user experience due
 +
to automated human to RPN conversion.
  
 
Flexible Logic allows advanced users to get unprecedented level of configurability for custom outputs and engine control. rusEfi supports up to 16 flexible outputs, each of these could be either an on/off or PWM signal. In case of a PWM signal the frequency is defined in the
 
Flexible Logic allows advanced users to get unprecedented level of configurability for custom outputs and engine control. rusEfi supports up to 16 flexible outputs, each of these could be either an on/off or PWM signal. In case of a PWM signal the frequency is defined in the
 
configuration and the duty cycle is dynamically controlled by the evaluated expression.
 
configuration and the duty cycle is dynamically controlled by the evaluated expression.
  
Fuel pump is already using this mechanism - see https://svn.code.sf.net/p/rusefi/code/trunk/firmware/controllers/core/le_functions.h
+
At the moment FSIO uses Reverse Polish Notation for technical reasons, so you would need to convert human-readable popular Infix notation to RPN using relevant rusEfi console features.
 +
 
 +
Fuel pump is already using this mechanism - see https://github.com/rusefi/rusefi/blob/master/firmware/controllers/system_fsio.txt
  
 
Here are some commands to try:
 
Here are some commands to try:
  
''eval "2 3 +"''
+
''eval "2 + 3"''
 +
 
 
Prints the result of "2 + 3"
 
Prints the result of "2 + 3"
  
''eval "rpm 100 max"''
+
 
 +
''eval "max (rpm, 100)"''
 +
 
 
Prints the result of "max(100, rpm)"
 
Prints the result of "max(100, rpm)"
  
''eval "100 200 1 if"''
+
 
 +
''eval "if(1, 200, 100)"''
 +
 
 
Prints the result of "if(1, 200, 100)"
 
Prints the result of "if(1, 200, 100)"
  
''set_fsio_expression 1 "rpm"''
+
 
Turn output #1 hi if rpm != 0
+
set_fsio_expression 1 "rpm > fsio_setting(4)"
 +
 
 +
Turn output #1 hi if rpm is greater than fsio setting #4
 +
 
  
 
''set_fsio_output_pin 1 pd11''
 
''set_fsio_output_pin 1 pd11''
 +
 
Tells output #1 to use pin PD11
 
Tells output #1 to use pin PD11
  
  
See https://svn.code.sf.net/p/rusefi/code/trunk/firmware/controllers/core/le_functions.cpp for list of available methods
+
See https://github.com/rusefi/rusefi/blob/master/firmware/controllers/core/fsio_impl.cpp for list of available methods
  
 
== More Examples ==
 
== More Examples ==
  
 
''set_fsio_output_frequency 1 100''
 
''set_fsio_output_frequency 1 100''
 +
 
Tells FSIO channel #1 to output 100Hz PWM
 
Tells FSIO channel #1 to output 100Hz PWM
  
 +
 +
''set_fsio_output_frequency 1 0''
  
  
Line 37: Line 54:
 
min(0.9, max(0.1, (rpm - 1000) / 4000 * 0.8))
 
min(0.9, max(0.1, (rpm - 1000) / 4000 * 0.8))
  
in RPN that's
 
 
rpm 1000 - 5000 / 0.1 max 0.9 min
 
  
 
We can use  
 
We can use  
  
''eval "rpm 1000 - 5000 / 0.1 max 0.9 min"''
+
''eval "min(0.9, max(0.1, (rpm - 1000) / 4000 * 0.8))"''
  
 
to validate and then
 
to validate and then
  
''set_fsio_expression 1 "rpm 1000 - 5000 / 0.1 max 0.9 min"''
+
''set_fsio_expression 1 "min(0.9, max(0.1, (rpm - 1000) / 4000 * 0.8))"''
  
  
Line 57: Line 71:
  
 
TODO
 
TODO
 
  
 
== FSIO parameters ==
 
== FSIO parameters ==
Line 67: Line 80:
 
To access for example setting #3 your FSIO expression is
 
To access for example setting #3 your FSIO expression is
  
''3 fsio_setting''
+
''fsio_setting(3)''
 
 
Please note that these indexes are starting with zero
 
  
 
== FSIO digital inputs ==
 
== FSIO digital inputs ==
 
These feature allows you to pull toggle switches state from your fsio expressions.
 
These feature allows you to pull toggle switches state from your fsio expressions.
  
 +
work in progress
 +
 +
== FSIO analog inputs ==
 +
As of Aug 1, 2018 only one analog input is implemented:
 +
 +
rpn_eval "fsio_analog_input 0"
 +
or
 +
set_fsio_expression 0 "((rpm > fsio_setting(4) & (fsio_analog_input 0 < fsio_setting(5)) | rpm > fsio_setting(1) | (coolant > fsio_setting(2)  > | (vbatt < fsio_setting(3)"
 +
 +
where input would be assigned via FSIO analog input #1
  
 
== Case study #1: shift light ==
 
== Case study #1: shift light ==
 
We want to turn on a warning light if RPM is above 4500
 
We want to turn on a warning light if RPM is above 4500
 +
 +
In order to set an output, three commands have to be invoked, also user has to decide which FSIO unit between 1 and 16 to use. Separate commands are used to set duty cycle, output pin, and condition. All three commands referencing the same FSIO index. This is poor usability and one day someone would improve this somehow.
  
 
First we need to configure user output, let's use pin PE5 and index #3 for this example:
 
First we need to configure user output, let's use pin PE5 and index #3 for this example:
Line 88: Line 111:
 
Now we will set FSIO expression to control this output pin:
 
Now we will set FSIO expression to control this output pin:
  
''set_fsio_expression 3 "rpm 4500 >"''
+
''set_fsio_expression 3 "rpm > 4500"''
 +
 
 +
here '''3''' is the index of the output pin
 +
 
 +
A configurable version of same would be
 +
 
 +
''set_fsio_expression 3 "rpm > fsio_setting(3)"
  
here '''3''' is the index of the output pin, and '''rpm 4500 >''' is RPN for ''rpm > 4500''
+
set_fsio_setting 3 4500''
  
 
== Case study #2: A/C compressor control ==
 
== Case study #2: A/C compressor control ==
Line 124: Line 153:
 
== Case study #4: boost controller ==
 
== Case study #4: boost controller ==
  
Solenoid-controlled boost controller would need variable duty cycle. For example, let's use fsio table #3 to define the desired duty cycle:
+
Solenoid-controlled boost controller would need variable duty cycle.  
 +
 
 +
For example, let's use fsio table #3 to define the desired duty cycle:
 +
 
 +
[[File:Fsio_table3.png]]
  
fsio_table
 
  
  
Let's set PE11@200Hz as FSIO output #4
+
Let's set PE11@300Hz as FSIO output #4
  
 
[[File:fsio_outputs.png]]
 
[[File:fsio_outputs.png]]
Line 135: Line 167:
 
And now the tricky part, let's set FSIO expression on that output using the following command
 
And now the tricky part, let's set FSIO expression on that output using the following command
  
''set_fsio_expression 4 "rpm map 3 fsio_table"''
+
''set_fsio_expression 4 "rpm map 3 fsio_table 100 /"''
 +
 
 +
Do not forget ''writeconfig''
 +
 
 +
 
 +
''fsioinfo'' could be used to monitor output value
 +
 
 +
[[File:Fsioinfo.png]]
 +
 
 +
 
 +
As for the magic expression, that's RPN for "fsio_table (3, rpm, map) / 100".
 +
 
 +
== Case study #5: solenoid exhaust cam actuator ==
 +
 
 +
Let's assume we want to turn on 200Hz solenoid at 80% duty cycle if RPM is above 6000.
 +
 
 +
Here is how this would look in Tuner Studio:
 +
 
 +
That's RPN notation for "(rpm > 6000) * 0.8"
 +
 
 +
See https://github.com/rusefi/rusefi/blob/master/firmware/controllers/system_fsio.txt see https://github.com/rusefi/rusefi/blob/master/firmware/controllers/system_fsio.h
 +
 
 +
 
 +
[[File:Fsio_TS.png]]
 +
 
 +
== See aslo ==
 +
 
 +
set debug_mode 23
 +
https://rusefi.com//wiki/index.php?title=Manual:Debug_fields
 +
 
 +
https://www.youtube.com/watch?v=nrIrtdn-Nc0
 +
 
 +
https://www.youtube.com/watch?v=eA4clVtklZ8
 +
 
 +
== Pin naming usability issue ==
 +
 
 +
We have a usability feature with microRusEfi where stm32 pin names are hidden from users. Unfortunately for FSIO these smt32 pin names are needed. Those are visible in https://github.com/rusefi/rusefi/blob/master/firmware/config/boards/microrusefi/mapping.yaml

Latest revision as of 20:07, 1 June 2020

Flexible Logic is the fanciest-schmanciest feature of rusEfi.

For FSIO, rusEfi console provides a better user experience due to automated human to RPN conversion.

Flexible Logic allows advanced users to get unprecedented level of configurability for custom outputs and engine control. rusEfi supports up to 16 flexible outputs, each of these could be either an on/off or PWM signal. In case of a PWM signal the frequency is defined in the configuration and the duty cycle is dynamically controlled by the evaluated expression.

At the moment FSIO uses Reverse Polish Notation for technical reasons, so you would need to convert human-readable popular Infix notation to RPN using relevant rusEfi console features.

Fuel pump is already using this mechanism - see https://github.com/rusefi/rusefi/blob/master/firmware/controllers/system_fsio.txt

Here are some commands to try:

eval "2 + 3"

Prints the result of "2 + 3"


eval "max (rpm, 100)"

Prints the result of "max(100, rpm)"


eval "if(1, 200, 100)"

Prints the result of "if(1, 200, 100)"


set_fsio_expression 1 "rpm > fsio_setting(4)"

Turn output #1 hi if rpm is greater than fsio setting #4


set_fsio_output_pin 1 pd11

Tells output #1 to use pin PD11


See https://github.com/rusefi/rusefi/blob/master/firmware/controllers/core/fsio_impl.cpp for list of available methods

More Examples

set_fsio_output_frequency 1 100

Tells FSIO channel #1 to output 100Hz PWM


set_fsio_output_frequency 1 0


Now, let's assume we want duty cycle to be 10% if rpm is below 1000, 90% if rpm is above 5000, and have it grow linearly from 10% to 90% between 1000 rpm and 5000 rpm. The human-readable expression for that would be

min(0.9, max(0.1, (rpm - 1000) / 4000 * 0.8))


We can use

eval "min(0.9, max(0.1, (rpm - 1000) / 4000 * 0.8))"

to validate and then

set_fsio_expression 1 "min(0.9, max(0.1, (rpm - 1000) / 4000 * 0.8))"


Another version of the same logic would be


if (rpm < 1000, 0.1, if (rpm > 5000, 0.9, 0.1 + (rpm - 1000) / 4000 * 0.8))

TODO

FSIO parameters

FSIO expressions could be customized using 16 user-defined 'settings' which are stored within the configuration. To change a setting from dev console your command is set_fsio_setting INDEX VAlUE

To access for example setting #3 your FSIO expression is

fsio_setting(3)

FSIO digital inputs

These feature allows you to pull toggle switches state from your fsio expressions.

work in progress

FSIO analog inputs

As of Aug 1, 2018 only one analog input is implemented:

rpn_eval "fsio_analog_input 0" or set_fsio_expression 0 "((rpm > fsio_setting(4) & (fsio_analog_input 0 < fsio_setting(5)) | rpm > fsio_setting(1) | (coolant > fsio_setting(2) > | (vbatt < fsio_setting(3)"

where input would be assigned via FSIO analog input #1

Case study #1: shift light

We want to turn on a warning light if RPM is above 4500

In order to set an output, three commands have to be invoked, also user has to decide which FSIO unit between 1 and 16 to use. Separate commands are used to set duty cycle, output pin, and condition. All three commands referencing the same FSIO index. This is poor usability and one day someone would improve this somehow.

First we need to configure user output, let's use pin PE5 and index #3 for this example:

set_fsio_output_frequency 3 0

this would disable PWM on channel #3 and set this port to simple digital output mode

set_fsio_output_pin 3 PE5

Now we will set FSIO expression to control this output pin:

set_fsio_expression 3 "rpm > 4500"

here 3 is the index of the output pin

A configurable version of same would be

set_fsio_expression 3 "rpm > fsio_setting(3)"

set_fsio_setting 3 4500

Case study #2: A/C compressor control

Say we want to use PE0 as A/C toggle button, and we want A/C compressor logic to be 'if (rpm > 1200 AND A/C button is depressed) then output 200Hz @ 80% duty cycle on PB1 else output nothing on PB1'.

First we need to configure A/C button input pin which is currently implemented as analog input (that's a temporary hack) - see engineConfiguration->acSwitchAdc

set_fsio_output_pin 3 PB1

Configure output #3 to use pin PB1

set_fsio_output_frequency 3 200

Configure output #3 to use 200Hz PWM

And finally set the expression:

'set_fsio_expression 3 "0 80 rpm 1200 > ac_on_switch AND IF"'

Which is RPN for if(rpm > 1200 AND ac_on_switch, 80, 0)

Case study #3: digital inputs for extra devices

TODO


First we need to configure A/C digital input pin, we will use index 0:

set_fsio_input_pin 0 PE0


Case study #4: boost controller

Solenoid-controlled boost controller would need variable duty cycle.

For example, let's use fsio table #3 to define the desired duty cycle:

Fsio table3.png


Let's set PE11@300Hz as FSIO output #4

Fsio outputs.png

And now the tricky part, let's set FSIO expression on that output using the following command

set_fsio_expression 4 "rpm map 3 fsio_table 100 /"

Do not forget writeconfig


fsioinfo could be used to monitor output value

Fsioinfo.png


As for the magic expression, that's RPN for "fsio_table (3, rpm, map) / 100".

Case study #5: solenoid exhaust cam actuator

Let's assume we want to turn on 200Hz solenoid at 80% duty cycle if RPM is above 6000.

Here is how this would look in Tuner Studio:

That's RPN notation for "(rpm > 6000) * 0.8"

See https://github.com/rusefi/rusefi/blob/master/firmware/controllers/system_fsio.txt see https://github.com/rusefi/rusefi/blob/master/firmware/controllers/system_fsio.h


Fsio TS.png

See aslo

set debug_mode 23 https://rusefi.com//wiki/index.php?title=Manual:Debug_fields

https://www.youtube.com/watch?v=nrIrtdn-Nc0

https://www.youtube.com/watch?v=eA4clVtklZ8

Pin naming usability issue

We have a usability feature with microRusEfi where stm32 pin names are hidden from users. Unfortunately for FSIO these smt32 pin names are needed. Those are visible in https://github.com/rusefi/rusefi/blob/master/firmware/config/boards/microrusefi/mapping.yaml