RPICT Full Output Firmware: Difference between revisions
No edit summary |
|||
(30 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
The Full Output Firmware provide the most complete and accurate way to use the RPICT card. | |||
The differences to the factory firmware are: | |||
* Serial data do not have an output rate but are streamed out as soon as a sampling & computation is performed. | |||
* All computed values are sent out. | |||
* Field format differ line to line depending on the type of computation performed. | |||
* Each line provide the coordinate of the reading (i.e. which sensors are involved) | |||
* Some extra fields are computed like E+ E- and Total Power in 3 phase. | |||
=Installation= | =Installation= | ||
We assume | We assume the Raspberrypi has been prepared with the guide below. | ||
[[Howto_setup_Raspbian_for_serial_read]] | [[Howto_setup_Raspbian_for_serial_read]] | ||
Line 42: | Line 50: | ||
==Plain output== | ==Plain output== | ||
The lcl-run shows the plain output of the serial port. | |||
lcl-run | lcl-run | ||
Line 50: | Line 58: | ||
The output format is described in detail in the next part of this guide. | The output format is described in detail in the next part of this guide. | ||
There is one line per computation node. | There is one line per computation node. | ||
==Decoded Output== | ==Decoded Output== | ||
Line 129: | Line 137: | ||
[[File:Fulloutput_001.png]] | [[File:Fulloutput_001.png]] | ||
=rpictpylib usage= | |||
==Library import== | |||
The library is imported using | |||
<syntaxhighlight lang="python"> | |||
import rpictpylib as rpict | |||
</syntaxhighlight> | |||
==decode_full_output(line, model_list)== | |||
This function decodes the data from the RPICT serial stream and convert each line into a dictionary. | |||
<syntaxhighlight lang="python"> | |||
dec = decode_full_output(line, model_list) | |||
</syntaxhighlight> | |||
'''line''' is the text string string received by the serial port obtained with serial.readline(). <br> | |||
'''model_list''' is the list of RPICT model used. This must be a list and it defaults to ['rpict8']. The list must contain any of rpict7v1 or rpict4v3 or rpict8. If using a staked system the parameter could be for example ['rpict7v1', 'rpict8']. | |||
The function returns a dictionary. The content of the dictionary depends on the computation node type used. | |||
'''Single Signal'''<br> | |||
<span style="font-family: courier;"> | |||
'type_idx'<br> | |||
'type_txt'<br> | |||
'port_idx'<br> | |||
'port_txt'<br> | |||
'level_idx'<br> | |||
'level_txt'<br> | |||
'time_start'<br> | |||
'time_end'<br> | |||
'rms'<br> | |||
'pest'<br> | |||
'e_plus'<br> | |||
</span> | |||
'''Power'''<br> | |||
<span style="font-family: courier;"> | |||
'type_idx'<br> | |||
'type_txt'<br> | |||
'port_I_idx'<br> | |||
'port_I_txt'<br> | |||
'level_I_idx'<br> | |||
'level_I_txt'<br> | |||
'port_V_idx'<br> | |||
'port_V_txt'<br> | |||
'level_V_idx'<br> | |||
'level_V_txt'<br> | |||
'time_start'<br> | |||
'time_end'<br> | |||
'irms'<br> | |||
'vrms'<br> | |||
'active_power'<br> | |||
'apparent_power'<br> | |||
'reactive_power'<br> | |||
'power_factor'<br> | |||
'e_plus'<br> | |||
'e_minus'<br> | |||
</span> | |||
'''3Phase'''<br> | |||
<span style="font-family: courier;"> | |||
'type_idx'<br> | |||
'type_txt'<br> | |||
'port_I1_idx'<br> | |||
'port_I1_txt'<br> | |||
'level_I1_idx'<br> | |||
'level_I1_txt'<br> | |||
'port_V1_idx'<br> | |||
'port_V1_txt'<br> | |||
'level_V1_idx'<br> | |||
'level_V1_txt'<br> | |||
'port_I2_idx'<br> | |||
'port_I2_txt'<br> | |||
'level_I2_idx'<br> | |||
'level_I2_txt'<br> | |||
'port_V2_idx'<br> | |||
'port_V2_txt'<br> | |||
'level_V2_idx'<br> | |||
'level_V2_txt'<br> | |||
'port_I3_idx'<br> | |||
'port_I3_txt'<br> | |||
'level_I3_idx'<br> | |||
'level_I3_txt'<br> | |||
'port_V3_idx'<br> | |||
'port_V3_txt'<br> | |||
'level_V3_idx'<br> | |||
'level_V3_txt'<br> | |||
'time_start'<br> | |||
'time_end'<br> | |||
'irms_1'<br> | |||
'irms_2'<br> | |||
'irms_3'<br> | |||
'vrms_1'<br> | |||
'vrms_2'<br> | |||
'vrms_3'<br> | |||
'active_power_1'<br> | |||
'active_power_2'<br> | |||
'active_power_3'<br> | |||
'apparent_power_1'<br> | |||
'apparent_power_2'<br> | |||
'apparent_power_3'<br> | |||
'reactive_power_1'<br> | |||
'reactive_power_2'<br> | |||
'reactive_power_3'<br> | |||
'power_factor_1'<br> | |||
'power_factor_2'<br> | |||
'power_factor_3'<br> | |||
'active_power_total'<br> | |||
'apparent_power_total'<br> | |||
'reactive_power_total'<br> | |||
'e_plus_1'<br> | |||
'e_minus_1'<br> | |||
'e_plus_2'<br> | |||
'e_minus_2'<br> | |||
'e_plus_3'<br> | |||
'e_minus_3'<br> | |||
</span> | |||
'''Frequency'''<br> | |||
<span style="font-family: courier;"> | |||
'type_idx'<br> | |||
'type_txt'<br> | |||
'port_idx'<br> | |||
'port_txt'<br> | |||
'level_idx'<br> | |||
'level_txt'<br> | |||
'time_start'<br> | |||
'time_end'<br> | |||
'frequency'<br> | |||
</span> | |||
'''Temperature'''<br> | |||
<span style="font-family: courier;"> | |||
'type_idx'<br> | |||
'type_txt'<br> | |||
'address'<br> | |||
'port_txt'<br> | |||
'time_start'<br> | |||
'time_end'<br> | |||
'temperature'<br> | |||
</span> | |||
Note all the e_plus and e_minus above are only created once the update_storage() function has been used. See below. | |||
==rpict.print_sequential(dec)== | |||
<syntaxhighlight lang="python"> | |||
rpict.print_sequential(dec) | |||
</syntaxhighlight> | |||
The function prints out the decoded data in a nice humen readable way. | |||
==realtime_storage()== | |||
The decoding function explained above only decode the data but does not have any storage functionality. We have created a class to store the latest data received. This is handy to display the data on demand and calculate energy. | |||
<syntaxhighlight lang="python"> | |||
rt_data = rpict.realtime_storage() | |||
</syntaxhighlight> | |||
This creates an instance of realtime storage called rt_data. | |||
==rt_data.update_storage(dec)== | |||
<syntaxhighlight lang="python"> | |||
rt_data.update_storage(dec) | |||
</syntaxhighlight> | |||
This function takes the decoded data as input and update it in the realtime storage class. | |||
This function also computes accumulated energy using previous power and time data. | |||
==rt_data.display_matrix()== | |||
<syntaxhighlight lang="python"> | |||
rt_data.display_matrix() | |||
</syntaxhighlight> | |||
Displays the realtime storage in a matrix way. | |||
=Output Format= | =Output Format= | ||
Line 171: | Line 365: | ||
|Three Phase Node. | |Three Phase Node. | ||
|Same as pnode but for three phase. | |Same as pnode but for three phase. | ||
|- | |||
|7 | |||
| | |||
|Temperature | |||
| | |||
|} | |} | ||
Line 264: | Line 463: | ||
|- | |- | ||
|} | |} | ||
==Time== | |||
This is the time in milliseconds since MCU boot of the beginning and end of the computation. | |||
<span style="font-family: courier;">time_start time_end</span> | |||
Note the time return to zero after 4'294'967 seconds. This is about 49 days and 17 hours. | |||
==Data== | |||
These are the physical data being measured and computed. The format depends on the type of node type. | |||
* Single Signal node: <span style="font-family: courier;">Irms estimated_power</span> | |||
* Power node: <span style="font-family: courier;">Irms Vrms active_power apparent_power reactive_power power_factor</span> | |||
* Frequency: <span style="font-family: courier;">frequency</span> | |||
* 3phase: <span style="font-family: courier;">Irms1 Irms2 Irms3 Vrms1 Vrms2 Vrms3 active_power1 active_power2 active_power3 apparent_power1 apparent_power2 apparent_power3 reactive_power1 reactive_power2 reactive_power3 power_factor1 power_factor2 power_factor3</span> |
Latest revision as of 21:10, 10 November 2023
The Full Output Firmware provide the most complete and accurate way to use the RPICT card. The differences to the factory firmware are:
- Serial data do not have an output rate but are streamed out as soon as a sampling & computation is performed.
- All computed values are sent out.
- Field format differ line to line depending on the type of computation performed.
- Each line provide the coordinate of the reading (i.e. which sensors are involved)
- Some extra fields are computed like E+ E- and Total Power in 3 phase.
Installation
We assume the Raspberrypi has been prepared with the guide below.
Howto_setup_Raspbian_for_serial_read
We also assume the packages to flash the Arduino have been setup.
Upload_Arduino_sketch_from_Raspberrypi_to_RPICT
Get the firmware:
wget lechacal.com/RPICT/sketch/RPICT_FULL_OUTPUT_001_v4.1.0.ino.hex
Flash it with:
lcl-upload-sketch.sh RPICT_FULL_OUTPUT_001_v4.1.0.ino.hex
Configuration
The configuration mechanism remain the same as for the default factory firmware.
Over_Serial_Configuration_-_Sketch_4
The web tool can be used in exactly the same way.
The use lcl-rpict-config.py command line tool can also be used with this firmware.
Ignored parameters
The section 'Output Channels' in the web tool can be left empty as the full output firmware will not use this and have its own control of the output. In the actual configuration file this corresponds to parameters CHID CH_node_type CH_field_type.
The parameter output_rate has no effect on this firmware. Data are sent out as soon as computation is done. Only the number of cycles Ncycles affects how long a computation last.
Usage
Plain output
The lcl-run shows the plain output of the serial port.
lcl-run
The output format is described in detail in the next part of this guide.
There is one line per computation node.
Decoded Output
We have created a small python library to decode the data.
The zip package downloaded above contains a very simple example usage.
import rpictpylib as rpict
import serial
if __name__ == "__main__":
ser = serial.Serial("/dev/ttyAMA0", 38400)
ser.flush()
while True:
try:
line = ser.readline().decode().strip()
dec = rpict.decode_full_output(line, ['rpict4v3'])
if dec != None:
print("---------------------------------")
print(dec)
except KeyboardInterrupt:
ser.close()
break
except UnicodeDecodeError:
pass
The serial port is read and stores each received line in the 'line' parameter. The parameter 'dec' is the decoded information in the form of a python dictionary.
decode_full_output() function is used to decode the line. It takes a list of the stack of RPICT cards used which is a list composed of any 'rpict7v1' 'rpict8' 'rpict4v3'.
Run it using
python3 fulloutput-demo.py
This prints out python dictionary containing the data like below.
Clearly this is not the most human readable form. This is why we have created a couple of additional functions.
- print_sequential(dec)
- display_matrix()
Sequential Print Out
We invite you to look inside the python script called lcl-fulloutput-decode.py which demonstrate how these are used.
To present the data in sequential form you can run
lcl-fulloutput-decode rpict4v3 -s
(replace rpict4v3 with whatever you have. If you have a stacked setup use for example rpict4v3,rpict8)
The text below will be shown.
This is a little bit easier to read and you can see the complete information. Note for example that you can see the time which is the time since the microcontroller started.
In the above command replace rpict4v3 with the card model that is used. For example if a stacked system is used one would run
lcl-fulloutput-decode rpict4v3,rpict8 -s
Matrix Print Out
The matrix display is certainly the most comfortable for real time monitoring. The time information disappear as several computation output are shown and are not from the same computation time.
Just use the command without the -s option.
lcl-fulloutput-decode rpict4v3
rpictpylib usage
Library import
The library is imported using
import rpictpylib as rpict
decode_full_output(line, model_list)
This function decodes the data from the RPICT serial stream and convert each line into a dictionary.
dec = decode_full_output(line, model_list)
line is the text string string received by the serial port obtained with serial.readline().
model_list is the list of RPICT model used. This must be a list and it defaults to ['rpict8']. The list must contain any of rpict7v1 or rpict4v3 or rpict8. If using a staked system the parameter could be for example ['rpict7v1', 'rpict8'].
The function returns a dictionary. The content of the dictionary depends on the computation node type used.
Single Signal
'type_idx'
'type_txt'
'port_idx'
'port_txt'
'level_idx'
'level_txt'
'time_start'
'time_end'
'rms'
'pest'
'e_plus'
Power
'type_idx'
'type_txt'
'port_I_idx'
'port_I_txt'
'level_I_idx'
'level_I_txt'
'port_V_idx'
'port_V_txt'
'level_V_idx'
'level_V_txt'
'time_start'
'time_end'
'irms'
'vrms'
'active_power'
'apparent_power'
'reactive_power'
'power_factor'
'e_plus'
'e_minus'
3Phase
'type_idx'
'type_txt'
'port_I1_idx'
'port_I1_txt'
'level_I1_idx'
'level_I1_txt'
'port_V1_idx'
'port_V1_txt'
'level_V1_idx'
'level_V1_txt'
'port_I2_idx'
'port_I2_txt'
'level_I2_idx'
'level_I2_txt'
'port_V2_idx'
'port_V2_txt'
'level_V2_idx'
'level_V2_txt'
'port_I3_idx'
'port_I3_txt'
'level_I3_idx'
'level_I3_txt'
'port_V3_idx'
'port_V3_txt'
'level_V3_idx'
'level_V3_txt'
'time_start'
'time_end'
'irms_1'
'irms_2'
'irms_3'
'vrms_1'
'vrms_2'
'vrms_3'
'active_power_1'
'active_power_2'
'active_power_3'
'apparent_power_1'
'apparent_power_2'
'apparent_power_3'
'reactive_power_1'
'reactive_power_2'
'reactive_power_3'
'power_factor_1'
'power_factor_2'
'power_factor_3'
'active_power_total'
'apparent_power_total'
'reactive_power_total'
'e_plus_1'
'e_minus_1'
'e_plus_2'
'e_minus_2'
'e_plus_3'
'e_minus_3'
Frequency
'type_idx'
'type_txt'
'port_idx'
'port_txt'
'level_idx'
'level_txt'
'time_start'
'time_end'
'frequency'
Temperature
'type_idx'
'type_txt'
'address'
'port_txt'
'time_start'
'time_end'
'temperature'
Note all the e_plus and e_minus above are only created once the update_storage() function has been used. See below.
rpict.print_sequential(dec)
rpict.print_sequential(dec)
The function prints out the decoded data in a nice humen readable way.
realtime_storage()
The decoding function explained above only decode the data but does not have any storage functionality. We have created a class to store the latest data received. This is handy to display the data on demand and calculate energy.
rt_data = rpict.realtime_storage()
This creates an instance of realtime storage called rt_data.
rt_data.update_storage(dec)
rt_data.update_storage(dec)
This function takes the decoded data as input and update it in the realtime storage class.
This function also computes accumulated energy using previous power and time data.
rt_data.display_matrix()
rt_data.display_matrix()
Displays the realtime storage in a matrix way.
Output Format
The output format follow the following group rule.
{node_type}{coordinates}{time}{data}
- node_type is an id describing the type of computation used. See table below.
- coordinates provides information on which ports are used.
- time gives the start and end time since mcu boot.
- data are all usual data like Irms Vrms Active Power etc.
Node Types
We call a node a single computation performed by the mcu. They are all listed below.
code | Node Type | Description | |
---|---|---|---|
2 | snode | Signal Node. | Compute RMS only of a single channel. Efficient and lightweight computation. |
3 | pnode | Power Node. | Computes all power related values of a current/voltage pair. Requires definition of both current and voltage sensor ports. |
4 | fnode | Frequency Node. | Computes frequency only on a given sensor port. |
5 | tnode | Three Phase Node. | Same as pnode but for three phase. |
7 | Temperature |
Using the very first output we see on this page (plain output) we can see the first code for each line is 2 4 4 4 and 5. This means we are using one single signal node then three frequency node and one 3phase node.
Coordinates
The coordinates are used to point to the ports used to read the signals. For example CT1 on slave 1 and V1 on master card.
We call CT1 CT2 V1 V2 etc 'ports'.
We call slave 1 slave 2 master etc 'levels'.
In the output they are given as integer with a specific code shown in tables below. Each node type has different coordinates structure.
- Single Signal node: port level
- Power node: port_I level_I port_V level_V
- Frequency: port level
- 3phase: port_I1 level_I1 port_V1 level_V1 port_I2 level_I2 port_V2 level_V2 port_I3 level_I3 port_V3 level_V3
Codes are given below.
Code | RPICT7V1 | RPICT8 | RPICT4V3 |
---|---|---|---|
0 | V1 | CT8 | V3 |
1 | CT7 | CT7 | V2 |
2 | CT6 | CT6 | V1 |
3 | CT5 | CT5 | nc |
4 | CT4 | CT4 | CT4 |
5 | CT3 | CT3 | CT3 |
6 | CT2 | CT2 | CT2 |
7 | CT1 | CT1 | CT1 |
Code | Board type |
---|---|
10 | Master |
6 | Slave 1 |
7 | Slave 2 |
8 | Slave 3 |
9 | Slave 4 |
Time
This is the time in milliseconds since MCU boot of the beginning and end of the computation.
time_start time_end
Note the time return to zero after 4'294'967 seconds. This is about 49 days and 17 hours.
Data
These are the physical data being measured and computed. The format depends on the type of node type.
- Single Signal node: Irms estimated_power
- Power node: Irms Vrms active_power apparent_power reactive_power power_factor
- Frequency: frequency
- 3phase: Irms1 Irms2 Irms3 Vrms1 Vrms2 Vrms3 active_power1 active_power2 active_power3 apparent_power1 apparent_power2 apparent_power3 reactive_power1 reactive_power2 reactive_power3 power_factor1 power_factor2 power_factor3