Compare commits
11 Commits
891e3d03cd
...
23a7de4d02
| Author | SHA1 | Date | |
|---|---|---|---|
| 23a7de4d02 | |||
| 79ab4613f6 | |||
| d4c12cce25 | |||
| 70335c54be | |||
| 5d4035f98f | |||
| 7941ceeb51 | |||
| dedb811aab | |||
| 07245df732 | |||
| 3fc3dbaae8 | |||
| a3a2386dc2 | |||
| 3668d9b80d |
39
.gitignore
vendored
39
.gitignore
vendored
@ -1,6 +1,45 @@
|
||||
#-------------------------------------------------------------------------------
|
||||
# Rust
|
||||
|
||||
**/*.rs.bk
|
||||
.#*
|
||||
.gdb_history
|
||||
Cargo.lock
|
||||
target/
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# For PCBs designed using KiCad: https://www.kicad.org/
|
||||
# Format documentation: https://kicad.org/help/file-formats/
|
||||
|
||||
# Temporary files
|
||||
*.000
|
||||
*.bak
|
||||
*.bck
|
||||
*.kicad_pcb-bak
|
||||
*.kicad_sch-bak
|
||||
*-backups
|
||||
*.kicad_prl
|
||||
*.sch-bak
|
||||
*~
|
||||
_autosave-*
|
||||
\#auto_saved_files\#
|
||||
*.tmp
|
||||
*-save.pro
|
||||
*-save.kicad_pcb
|
||||
fp-info-cache
|
||||
|
||||
# Netlist files (exported from Eeschema)
|
||||
*.net
|
||||
|
||||
# Autorouter files (exported from Pcbnew)
|
||||
*.dsn
|
||||
*.ses
|
||||
|
||||
# Exported BOM files
|
||||
*.xml
|
||||
*.csv
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# LibreOffice
|
||||
*.~lock*
|
||||
|
||||
|
||||
@ -8,15 +8,16 @@ version = "0.1.0"
|
||||
[dependencies]
|
||||
embedded-hal = "0.2.6"
|
||||
nb = "0.1.2"
|
||||
cortex-m = "0.6.0"
|
||||
cortex-m-rt = "0.6.10"
|
||||
cortex-m-semihosting = "0.3.3"
|
||||
cortex-m = "0.7.4"
|
||||
cortex-m-rt = "0.7.1"
|
||||
cortex-m-semihosting = "0.3.7"
|
||||
panic-halt = "0.2.0"
|
||||
hd44780-driver = "0.3.0"
|
||||
libm = "0.2.1"
|
||||
half = "1.8.2"
|
||||
|
||||
[dependencies.stm32f1xx-hal]
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
features = ["stm32f103", "rt", "medium"]
|
||||
|
||||
# this lets you use `cargo fix`!
|
||||
|
||||
BIN
cad/BOM.ods
BIN
cad/BOM.ods
Binary file not shown.
26085
cad/fan_monitor/fan_monitor.kicad_pcb
Normal file
26085
cad/fan_monitor/fan_monitor.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
484
cad/fan_monitor/fan_monitor.kicad_pro
Normal file
484
cad/fan_monitor/fan_monitor.kicad_pro
Normal file
@ -0,0 +1,484 @@
|
||||
{
|
||||
"board": {
|
||||
"design_settings": {
|
||||
"defaults": {
|
||||
"board_outline_line_width": 0.09999999999999999,
|
||||
"copper_line_width": 0.19999999999999998,
|
||||
"copper_text_italic": false,
|
||||
"copper_text_size_h": 1.5,
|
||||
"copper_text_size_v": 1.5,
|
||||
"copper_text_thickness": 0.3,
|
||||
"copper_text_upright": false,
|
||||
"courtyard_line_width": 0.049999999999999996,
|
||||
"dimension_precision": 4,
|
||||
"dimension_units": 3,
|
||||
"dimensions": {
|
||||
"arrow_length": 1270000,
|
||||
"extension_offset": 500000,
|
||||
"keep_text_aligned": true,
|
||||
"suppress_zeroes": false,
|
||||
"text_position": 0,
|
||||
"units_format": 1
|
||||
},
|
||||
"fab_line_width": 0.09999999999999999,
|
||||
"fab_text_italic": false,
|
||||
"fab_text_size_h": 1.0,
|
||||
"fab_text_size_v": 1.0,
|
||||
"fab_text_thickness": 0.15,
|
||||
"fab_text_upright": false,
|
||||
"other_line_width": 0.15,
|
||||
"other_text_italic": false,
|
||||
"other_text_size_h": 1.0,
|
||||
"other_text_size_v": 1.0,
|
||||
"other_text_thickness": 0.15,
|
||||
"other_text_upright": false,
|
||||
"pads": {
|
||||
"drill": 3.2,
|
||||
"height": 5.6,
|
||||
"width": 5.6
|
||||
},
|
||||
"silk_line_width": 0.15,
|
||||
"silk_text_italic": false,
|
||||
"silk_text_size_h": 1.0,
|
||||
"silk_text_size_v": 1.0,
|
||||
"silk_text_thickness": 0.15,
|
||||
"silk_text_upright": false,
|
||||
"zones": {
|
||||
"45_degree_only": false,
|
||||
"min_clearance": 0.508
|
||||
}
|
||||
},
|
||||
"diff_pair_dimensions": [
|
||||
{
|
||||
"gap": 0.0,
|
||||
"via_gap": 0.0,
|
||||
"width": 0.0
|
||||
}
|
||||
],
|
||||
"drc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 2
|
||||
},
|
||||
"rule_severities": {
|
||||
"annular_width": "error",
|
||||
"clearance": "error",
|
||||
"copper_edge_clearance": "error",
|
||||
"courtyards_overlap": "error",
|
||||
"diff_pair_gap_out_of_range": "error",
|
||||
"diff_pair_uncoupled_length_too_long": "error",
|
||||
"drill_out_of_range": "error",
|
||||
"duplicate_footprints": "warning",
|
||||
"extra_footprint": "warning",
|
||||
"footprint_type_mismatch": "error",
|
||||
"hole_clearance": "error",
|
||||
"hole_near_hole": "error",
|
||||
"invalid_outline": "error",
|
||||
"item_on_disabled_layer": "error",
|
||||
"items_not_allowed": "error",
|
||||
"length_out_of_range": "error",
|
||||
"malformed_courtyard": "ignore",
|
||||
"microvia_drill_out_of_range": "error",
|
||||
"missing_courtyard": "ignore",
|
||||
"missing_footprint": "warning",
|
||||
"net_conflict": "warning",
|
||||
"npth_inside_courtyard": "ignore",
|
||||
"padstack": "error",
|
||||
"pth_inside_courtyard": "ignore",
|
||||
"shorting_items": "error",
|
||||
"silk_over_copper": "ignore",
|
||||
"silk_overlap": "warning",
|
||||
"skew_out_of_range": "error",
|
||||
"through_hole_pad_without_hole": "error",
|
||||
"too_many_vias": "error",
|
||||
"track_dangling": "warning",
|
||||
"track_width": "error",
|
||||
"tracks_crossing": "error",
|
||||
"unconnected_items": "error",
|
||||
"unresolved_variable": "error",
|
||||
"via_dangling": "warning",
|
||||
"zone_has_empty_net": "error",
|
||||
"zones_intersect": "error"
|
||||
},
|
||||
"rules": {
|
||||
"allow_blind_buried_vias": false,
|
||||
"allow_microvias": false,
|
||||
"max_error": 0.005,
|
||||
"min_clearance": 0.0,
|
||||
"min_copper_edge_clearance": 0.0,
|
||||
"min_hole_clearance": 0.25,
|
||||
"min_hole_to_hole": 0.25,
|
||||
"min_microvia_diameter": 0.19999999999999998,
|
||||
"min_microvia_drill": 0.09999999999999999,
|
||||
"min_silk_clearance": 0.0,
|
||||
"min_through_hole_diameter": 0.3,
|
||||
"min_track_width": 0.15,
|
||||
"min_via_annular_width": 0.049999999999999996,
|
||||
"min_via_diameter": 0.39999999999999997,
|
||||
"solder_mask_clearance": 0.0,
|
||||
"solder_mask_min_width": 0.0,
|
||||
"use_height_for_length_calcs": true
|
||||
},
|
||||
"track_widths": [
|
||||
0.0,
|
||||
0.5,
|
||||
0.8
|
||||
],
|
||||
"via_dimensions": [
|
||||
{
|
||||
"diameter": 0.0,
|
||||
"drill": 0.0
|
||||
},
|
||||
{
|
||||
"diameter": 0.6,
|
||||
"drill": 0.3
|
||||
},
|
||||
{
|
||||
"diameter": 0.9,
|
||||
"drill": 0.6
|
||||
}
|
||||
],
|
||||
"zones_allow_external_fillets": false,
|
||||
"zones_use_no_outline": true
|
||||
},
|
||||
"layer_presets": []
|
||||
},
|
||||
"boards": [],
|
||||
"cvpcb": {
|
||||
"equivalence_files": []
|
||||
},
|
||||
"erc": {
|
||||
"erc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"pin_map": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
],
|
||||
"rule_severities": {
|
||||
"bus_definition_conflict": "error",
|
||||
"bus_entry_needed": "error",
|
||||
"bus_label_syntax": "error",
|
||||
"bus_to_bus_conflict": "error",
|
||||
"bus_to_net_conflict": "error",
|
||||
"different_unit_footprint": "error",
|
||||
"different_unit_net": "error",
|
||||
"duplicate_reference": "error",
|
||||
"duplicate_sheet_names": "error",
|
||||
"extra_units": "error",
|
||||
"global_label_dangling": "warning",
|
||||
"hier_label_mismatch": "error",
|
||||
"label_dangling": "error",
|
||||
"lib_symbol_issues": "warning",
|
||||
"multiple_net_names": "warning",
|
||||
"net_not_bus_member": "warning",
|
||||
"no_connect_connected": "warning",
|
||||
"no_connect_dangling": "warning",
|
||||
"pin_not_connected": "error",
|
||||
"pin_not_driven": "error",
|
||||
"pin_to_pin": "warning",
|
||||
"power_pin_not_driven": "error",
|
||||
"similar_labels": "warning",
|
||||
"unannotated": "error",
|
||||
"unit_value_mismatch": "error",
|
||||
"unresolved_variable": "error",
|
||||
"wire_dangling": "error"
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"pinned_footprint_libs": [],
|
||||
"pinned_symbol_libs": []
|
||||
},
|
||||
"meta": {
|
||||
"filename": "fan_monitor.kicad_pro",
|
||||
"version": 1
|
||||
},
|
||||
"net_settings": {
|
||||
"classes": [
|
||||
{
|
||||
"bus_width": 12.0,
|
||||
"clearance": 0.2,
|
||||
"diff_pair_gap": 0.25,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.2,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.3,
|
||||
"microvia_drill": 0.1,
|
||||
"name": "Default",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.5,
|
||||
"via_diameter": 0.6,
|
||||
"via_drill": 0.35,
|
||||
"wire_width": 6.0
|
||||
},
|
||||
{
|
||||
"bus_width": 12.0,
|
||||
"clearance": 2.4,
|
||||
"diff_pair_gap": 0.25,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.2,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.3,
|
||||
"microvia_drill": 0.1,
|
||||
"name": "380AC",
|
||||
"nets": [
|
||||
"Net-(F1-Pad1)",
|
||||
"Net-(F1-Pad2)"
|
||||
],
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.8,
|
||||
"via_diameter": 0.9,
|
||||
"via_drill": 0.6,
|
||||
"wire_width": 6.0
|
||||
},
|
||||
{
|
||||
"bus_width": 12.0,
|
||||
"clearance": 0.2,
|
||||
"diff_pair_gap": 0.25,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.2,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.3,
|
||||
"microvia_drill": 0.1,
|
||||
"name": "5V_main",
|
||||
"nets": [
|
||||
"Net-(J4-Pad1)"
|
||||
],
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.8,
|
||||
"via_diameter": 0.6,
|
||||
"via_drill": 0.35,
|
||||
"wire_width": 6.0
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 2
|
||||
},
|
||||
"net_colors": null
|
||||
},
|
||||
"pcbnew": {
|
||||
"last_paths": {
|
||||
"gencad": "",
|
||||
"idf": "",
|
||||
"netlist": "",
|
||||
"specctra_dsn": "",
|
||||
"step": "",
|
||||
"vrml": ""
|
||||
},
|
||||
"page_layout_descr_file": ""
|
||||
},
|
||||
"schematic": {
|
||||
"annotate_start_num": 0,
|
||||
"drawing": {
|
||||
"default_line_thickness": 6.0,
|
||||
"default_text_size": 50.0,
|
||||
"field_names": [],
|
||||
"intersheets_ref_own_page": false,
|
||||
"intersheets_ref_prefix": "",
|
||||
"intersheets_ref_short": false,
|
||||
"intersheets_ref_show": false,
|
||||
"intersheets_ref_suffix": "",
|
||||
"junction_size_choice": 3,
|
||||
"label_size_ratio": 0.375,
|
||||
"pin_symbol_size": 25.0,
|
||||
"text_offset_ratio": 0.15
|
||||
},
|
||||
"legacy_lib_dir": "",
|
||||
"legacy_lib_list": [],
|
||||
"meta": {
|
||||
"version": 1
|
||||
},
|
||||
"net_format_name": "",
|
||||
"ngspice": {
|
||||
"fix_include_paths": true,
|
||||
"fix_passive_vals": false,
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"model_mode": 0,
|
||||
"workbook_filename": ""
|
||||
},
|
||||
"page_layout_descr_file": "",
|
||||
"plot_directory": "",
|
||||
"spice_adjust_passive_values": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
"subpart_first_id": 65,
|
||||
"subpart_id_separator": 0
|
||||
},
|
||||
"sheets": [
|
||||
[
|
||||
"6475547d-3216-45a4-a15c-48314f1dd0f9",
|
||||
""
|
||||
]
|
||||
],
|
||||
"text_variables": {}
|
||||
}
|
||||
3574
cad/fan_monitor/fan_monitor.kicad_sch
Normal file
3574
cad/fan_monitor/fan_monitor.kicad_sch
Normal file
File diff suppressed because it is too large
Load Diff
638
cad/fan_monitor/fan_monitor.kicad_sym
Normal file
638
cad/fan_monitor/fan_monitor.kicad_sym
Normal file
@ -0,0 +1,638 @@
|
||||
(kicad_symbol_lib (version 20211014) (generator kicad_symbol_editor)
|
||||
(symbol "1SS315" (pin_numbers hide) (pin_names (offset 1.016) hide) (in_bom yes) (on_board yes)
|
||||
(property "Reference" "D" (id 0) (at 0 2.54 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(property "Value" "1SS315" (id 1) (at 0 -2.54 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(property "Footprint" "Diode_SMD:D_SOD-323_HandSoldering" (id 2) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "~" (id 3) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_keywords" "diode CMS SOD-323" (id 4) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_description" "Diode CMS Toshiba, 30mA, 5V, SOD-323" (id 5) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_fp_filters" "TO-???* *_Diode_* *SingleDiode* D_*" (id 6) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(symbol "1SS315_0_1"
|
||||
(polyline
|
||||
(pts
|
||||
(xy -1.27 1.27)
|
||||
(xy -1.27 -1.27)
|
||||
)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 1.27 0)
|
||||
(xy -1.27 0)
|
||||
)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 1.27 1.27)
|
||||
(xy 1.27 -1.27)
|
||||
(xy -1.27 0)
|
||||
(xy 1.27 1.27)
|
||||
)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
)
|
||||
(symbol "1SS315_1_1"
|
||||
(pin passive line (at -3.81 0 0) (length 2.54)
|
||||
(name "K" (effects (font (size 1.27 1.27))))
|
||||
(number "1" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 3.81 0 180) (length 2.54)
|
||||
(name "A" (effects (font (size 1.27 1.27))))
|
||||
(number "2" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "2N4401" (pin_names (offset 0) hide) (in_bom yes) (on_board yes)
|
||||
(property "Reference" "Q" (id 0) (at 5.08 1.905 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left))
|
||||
)
|
||||
(property "Value" "2N4401" (id 1) (at 5.08 0 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left))
|
||||
)
|
||||
(property "Footprint" "Package_TO_SOT_THT:TO-92_Inline" (id 2) (at 5.08 -1.905 0)
|
||||
(effects (font (size 1.27 1.27) italic) (justify left) hide)
|
||||
)
|
||||
(property "Datasheet" "https://www.onsemi.com/pub/Collateral/2N3903-D.PDF" (id 3) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) (justify left) hide)
|
||||
)
|
||||
(property "ki_keywords" "NPN Transistor" (id 4) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_description" "0.2A Ic, 40V Vce, Small Signal NPN Transistor, TO-92" (id 5) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_fp_filters" "TO?92*" (id 6) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(symbol "2N4401_0_1"
|
||||
(polyline
|
||||
(pts
|
||||
(xy 0.635 0.635)
|
||||
(xy 2.54 2.54)
|
||||
)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 0.635 -0.635)
|
||||
(xy 2.54 -2.54)
|
||||
(xy 2.54 -2.54)
|
||||
)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 0.635 1.905)
|
||||
(xy 0.635 -1.905)
|
||||
(xy 0.635 -1.905)
|
||||
)
|
||||
(stroke (width 0.508) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 1.27 -1.778)
|
||||
(xy 1.778 -1.27)
|
||||
(xy 2.286 -2.286)
|
||||
(xy 1.27 -1.778)
|
||||
(xy 1.27 -1.778)
|
||||
)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type outline))
|
||||
)
|
||||
(circle (center 1.27 0) (radius 2.8194)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
)
|
||||
(symbol "2N4401_1_1"
|
||||
(pin passive line (at 2.54 -5.08 90) (length 2.54)
|
||||
(name "E" (effects (font (size 1.27 1.27))))
|
||||
(number "1" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at -5.08 0 0) (length 5.715)
|
||||
(name "B" (effects (font (size 1.27 1.27))))
|
||||
(number "2" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 2.54 5.08 270) (length 2.54)
|
||||
(name "C" (effects (font (size 1.27 1.27))))
|
||||
(number "3" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "HE10-16" (pin_names (offset 1.016) hide) (in_bom yes) (on_board yes)
|
||||
(property "Reference" "J" (id 0) (at 1.27 10.16 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(property "Value" "HE10-16" (id 1) (at 1.27 -12.7 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(property "Footprint" "" (id 2) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "~" (id 3) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_keywords" "connector" (id 4) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_description" "Generic connector, double row, 02x08, odd/even pin numbering scheme (row 1 odd numbers, row 2 even numbers), script generated (kicad-library-utils/schlib/autogen/connector/)" (id 5) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_fp_filters" "Connector*:*_2x??_*" (id 6) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(symbol "HE10-16_1_1"
|
||||
(rectangle (start -1.27 -10.033) (end 0 -10.287)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start -1.27 -7.493) (end 0 -7.747)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start -1.27 -4.953) (end 0 -5.207)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start -1.27 -2.413) (end 0 -2.667)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start -1.27 0.127) (end 0 -0.127)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start -1.27 2.667) (end 0 2.413)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start -1.27 5.207) (end 0 4.953)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start -1.27 7.747) (end 0 7.493)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start -1.27 8.89) (end 3.81 -11.43)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type background))
|
||||
)
|
||||
(rectangle (start 3.81 -10.033) (end 2.54 -10.287)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start 3.81 -7.493) (end 2.54 -7.747)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start 3.81 -4.953) (end 2.54 -5.207)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start 3.81 -2.413) (end 2.54 -2.667)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start 3.81 0.127) (end 2.54 -0.127)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start 3.81 2.667) (end 2.54 2.413)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start 3.81 5.207) (end 2.54 4.953)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(rectangle (start 3.81 7.747) (end 2.54 7.493)
|
||||
(stroke (width 0.1524) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(pin passive line (at -5.08 7.62 0) (length 3.81)
|
||||
(name "Pin_1" (effects (font (size 1.27 1.27))))
|
||||
(number "1" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 7.62 -2.54 180) (length 3.81)
|
||||
(name "Pin_10" (effects (font (size 1.27 1.27))))
|
||||
(number "10" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at -5.08 -5.08 0) (length 3.81)
|
||||
(name "Pin_11" (effects (font (size 1.27 1.27))))
|
||||
(number "11" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 7.62 -5.08 180) (length 3.81)
|
||||
(name "Pin_12" (effects (font (size 1.27 1.27))))
|
||||
(number "12" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at -5.08 -7.62 0) (length 3.81)
|
||||
(name "Pin_13" (effects (font (size 1.27 1.27))))
|
||||
(number "13" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 7.62 -7.62 180) (length 3.81)
|
||||
(name "Pin_14" (effects (font (size 1.27 1.27))))
|
||||
(number "14" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at -5.08 -10.16 0) (length 3.81)
|
||||
(name "Pin_15" (effects (font (size 1.27 1.27))))
|
||||
(number "15" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 7.62 -10.16 180) (length 3.81)
|
||||
(name "Pin_16" (effects (font (size 1.27 1.27))))
|
||||
(number "16" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 7.62 7.62 180) (length 3.81)
|
||||
(name "Pin_2" (effects (font (size 1.27 1.27))))
|
||||
(number "2" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at -5.08 5.08 0) (length 3.81)
|
||||
(name "Pin_3" (effects (font (size 1.27 1.27))))
|
||||
(number "3" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 7.62 5.08 180) (length 3.81)
|
||||
(name "Pin_4" (effects (font (size 1.27 1.27))))
|
||||
(number "4" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at -5.08 2.54 0) (length 3.81)
|
||||
(name "Pin_5" (effects (font (size 1.27 1.27))))
|
||||
(number "5" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 7.62 2.54 180) (length 3.81)
|
||||
(name "Pin_6" (effects (font (size 1.27 1.27))))
|
||||
(number "6" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at -5.08 0 0) (length 3.81)
|
||||
(name "Pin_7" (effects (font (size 1.27 1.27))))
|
||||
(number "7" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 7.62 0 180) (length 3.81)
|
||||
(name "Pin_8" (effects (font (size 1.27 1.27))))
|
||||
(number "8" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at -5.08 -2.54 0) (length 3.81)
|
||||
(name "Pin_9" (effects (font (size 1.27 1.27))))
|
||||
(number "9" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "HF152FD{slash}5-1H" (in_bom yes) (on_board yes)
|
||||
(property "Reference" "K" (id 0) (at 11.43 3.81 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(property "Value" "HF152FD{slash}5-1H" (id 1) (at 18.415 1.27 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(property "Footprint" "fan_monitor:HF152FD_Form_A" (id 2) (at 33.655 -1.27 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "" (id 3) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_keywords" "SPST 1P1T" (id 4) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_description" "Hongfa, Small Non-Latching Power Relay, Single coil, 400VAC, 1 Form A" (id 5) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "ki_fp_filters" "Relay*1P1T*NO*Panasonic*ADW11xxxxW*" (id 6) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(symbol "HF152FD{slash}5-1H_0_0"
|
||||
(text "?" (at -3.81 3.175 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
)
|
||||
(symbol "HF152FD{slash}5-1H_1_1"
|
||||
(rectangle (start -10.16 5.08) (end 10.16 -5.08)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type background))
|
||||
)
|
||||
(rectangle (start -8.255 1.905) (end -1.905 -1.905)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy -7.62 -1.905)
|
||||
(xy -2.54 1.905)
|
||||
)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy -5.08 -5.08)
|
||||
(xy -5.08 -1.905)
|
||||
)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy -5.08 5.08)
|
||||
(xy -5.08 1.905)
|
||||
)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy -1.905 0)
|
||||
(xy -1.27 0)
|
||||
)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy -0.635 0)
|
||||
(xy 0 0)
|
||||
)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 0.635 0)
|
||||
(xy 1.27 0)
|
||||
)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 0.635 0)
|
||||
(xy 1.27 0)
|
||||
)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 1.905 0)
|
||||
(xy 2.54 0)
|
||||
)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 3.175 0)
|
||||
(xy 3.81 0)
|
||||
)
|
||||
(stroke (width 0.254) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 5.08 -2.54)
|
||||
(xy 3.175 3.81)
|
||||
)
|
||||
(stroke (width 0.508) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 5.08 -2.54)
|
||||
(xy 5.08 -5.08)
|
||||
)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 7.62 3.81)
|
||||
(xy 7.62 5.08)
|
||||
)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(polyline
|
||||
(pts
|
||||
(xy 7.62 3.81)
|
||||
(xy 7.62 2.54)
|
||||
(xy 6.985 3.175)
|
||||
(xy 7.62 3.81)
|
||||
)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
(pin passive line (at -5.08 7.62 270) (length 2.54)
|
||||
(name "~" (effects (font (size 1.27 1.27))))
|
||||
(number "1" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at -5.08 -7.62 90) (length 2.54)
|
||||
(name "~" (effects (font (size 1.27 1.27))))
|
||||
(number "2" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 5.08 -7.62 90) (length 2.54)
|
||||
(name "~" (effects (font (size 1.27 1.27))))
|
||||
(number "3" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin passive line (at 7.62 7.62 270) (length 2.54)
|
||||
(name "~" (effects (font (size 1.27 1.27))))
|
||||
(number "4" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
)
|
||||
)
|
||||
(symbol "blue_pill" (pin_names (offset 1.016)) (in_bom yes) (on_board yes)
|
||||
(property "Reference" "U" (id 0) (at -12.7 22.86 0)
|
||||
(effects (font (size 1.524 1.524)))
|
||||
)
|
||||
(property "Value" "blue_pill" (id 1) (at 7.62 -24.13 0)
|
||||
(effects (font (size 1.524 1.524)))
|
||||
)
|
||||
(property "Footprint" "Module:blue_pill" (id 2) (at -2.54 19.05 0)
|
||||
(effects (font (size 1.524 1.524)) hide)
|
||||
)
|
||||
(property "Datasheet" "https://www.electronicshub.org/getting-started-with-stm32f103c8t6-blue-pill/" (id 3) (at -2.54 19.05 0)
|
||||
(effects (font (size 1.524 1.524)) hide)
|
||||
)
|
||||
(symbol "blue_pill_0_1"
|
||||
(rectangle (start -13.97 21.59) (end 13.97 -21.59)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type none))
|
||||
)
|
||||
)
|
||||
(symbol "blue_pill_1_1"
|
||||
(pin power_out line (at 0 26.67 270) (length 5.08)
|
||||
(name "3.3V" (effects (font (size 1.27 1.27))))
|
||||
(number "3V3" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin power_out line (at 3.81 26.67 270) (length 5.08)
|
||||
(name "5V" (effects (font (size 1.27 1.27))))
|
||||
(number "5V" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin input line (at -3.81 -26.67 90) (length 5.08)
|
||||
(name "BOOT0" (effects (font (size 1.27 1.27))))
|
||||
(number "BOOT" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin power_out line (at 3.81 -26.67 90) (length 5.08)
|
||||
(name "GND" (effects (font (size 1.27 1.27))))
|
||||
(number "G" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin input line (at -19.05 -20.32 0) (length 5.08)
|
||||
(name "RESET" (effects (font (size 1.27 1.27))))
|
||||
(number "NRST" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 12.7 0) (length 5.08)
|
||||
(name "PA0" (effects (font (size 1.27 1.27))))
|
||||
(number "PA0" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 10.16 0) (length 5.08)
|
||||
(name "PA1" (effects (font (size 1.27 1.27))))
|
||||
(number "PA1" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 -5.08 180) (length 5.08)
|
||||
(name "PA10" (effects (font (size 1.27 1.27))))
|
||||
(number "PA10" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 -2.54 180) (length 5.08)
|
||||
(name "PA11" (effects (font (size 1.27 1.27))))
|
||||
(number "PA11" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 0 180) (length 5.08)
|
||||
(name "PA12" (effects (font (size 1.27 1.27))))
|
||||
(number "PA12" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 2.54 180) (length 5.08)
|
||||
(name "PA15" (effects (font (size 1.27 1.27))))
|
||||
(number "PA15" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 7.62 0) (length 5.08)
|
||||
(name "PA2" (effects (font (size 1.27 1.27))))
|
||||
(number "PA2" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 5.08 0) (length 5.08)
|
||||
(name "PA3" (effects (font (size 1.27 1.27))))
|
||||
(number "PA3" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 2.54 0) (length 5.08)
|
||||
(name "PA4" (effects (font (size 1.27 1.27))))
|
||||
(number "PA4" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 0 0) (length 5.08)
|
||||
(name "PA5" (effects (font (size 1.27 1.27))))
|
||||
(number "PA5" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 -2.54 0) (length 5.08)
|
||||
(name "PA6" (effects (font (size 1.27 1.27))))
|
||||
(number "PA6" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 -5.08 0) (length 5.08)
|
||||
(name "PA7" (effects (font (size 1.27 1.27))))
|
||||
(number "PA7" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 -10.16 180) (length 5.08)
|
||||
(name "PA8" (effects (font (size 1.27 1.27))))
|
||||
(number "PA8" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 -7.62 180) (length 5.08)
|
||||
(name "PA9" (effects (font (size 1.27 1.27))))
|
||||
(number "PA9" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 -7.62 0) (length 5.08)
|
||||
(name "PB0" (effects (font (size 1.27 1.27))))
|
||||
(number "PB0" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 -10.16 0) (length 5.08)
|
||||
(name "PB1" (effects (font (size 1.27 1.27))))
|
||||
(number "PB1" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 -12.7 0) (length 5.08)
|
||||
(name "PB10" (effects (font (size 1.27 1.27))))
|
||||
(number "PB10" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 -15.24 0) (length 5.08)
|
||||
(name "PB11" (effects (font (size 1.27 1.27))))
|
||||
(number "PB11" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 -20.32 180) (length 5.08)
|
||||
(name "PB12" (effects (font (size 1.27 1.27))))
|
||||
(number "PB12" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 -17.78 180) (length 5.08)
|
||||
(name "PB13" (effects (font (size 1.27 1.27))))
|
||||
(number "PB13" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 -15.24 180) (length 5.08)
|
||||
(name "PB14" (effects (font (size 1.27 1.27))))
|
||||
(number "PB14" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 -12.7 180) (length 5.08)
|
||||
(name "PB15" (effects (font (size 1.27 1.27))))
|
||||
(number "PB15" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin input line (at -1.27 -26.67 90) (length 5.08)
|
||||
(name "BOOT1" (effects (font (size 1.27 1.27))))
|
||||
(number "PB2" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 5.08 180) (length 5.08)
|
||||
(name "PB3" (effects (font (size 1.27 1.27))))
|
||||
(number "PB3" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 7.62 180) (length 5.08)
|
||||
(name "PB4" (effects (font (size 1.27 1.27))))
|
||||
(number "PB4" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 10.16 180) (length 5.08)
|
||||
(name "PB5" (effects (font (size 1.27 1.27))))
|
||||
(number "PB5" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 12.7 180) (length 5.08)
|
||||
(name "PB6" (effects (font (size 1.27 1.27))))
|
||||
(number "PB6" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 15.24 180) (length 5.08)
|
||||
(name "PB7" (effects (font (size 1.27 1.27))))
|
||||
(number "PB7" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 17.78 180) (length 5.08)
|
||||
(name "PB8" (effects (font (size 1.27 1.27))))
|
||||
(number "PB8" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at 19.05 20.32 180) (length 5.08)
|
||||
(name "PB9" (effects (font (size 1.27 1.27))))
|
||||
(number "PB9" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 20.32 0) (length 5.08)
|
||||
(name "PC13" (effects (font (size 1.27 1.27))))
|
||||
(number "PC13" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 17.78 0) (length 5.08)
|
||||
(name "PC14" (effects (font (size 1.27 1.27))))
|
||||
(number "PC14" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -19.05 15.24 0) (length 5.08)
|
||||
(name "PC15" (effects (font (size 1.27 1.27))))
|
||||
(number "PC15" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin power_in line (at -3.81 26.67 270) (length 5.08)
|
||||
(name "Vbat" (effects (font (size 1.27 1.27))))
|
||||
(number "VBAT" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
29
cad/fan_monitor/fan_monitor.pretty/CR2032_Holder.kicad_mod
Normal file
29
cad/fan_monitor/fan_monitor.pretty/CR2032_Holder.kicad_mod
Normal file
@ -0,0 +1,29 @@
|
||||
(footprint "CR2032_Holder" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 62261CA8)
|
||||
(descr "Coin Cell PV Battery Holder")
|
||||
(tags "CR2032")
|
||||
(attr through_hole)
|
||||
(fp_text reference "REF**" (at 7.3 -6.2 unlocked) (layer "F.SilkS")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp 23c65112-425a-4ada-b1ca-3a5e5f538f08)
|
||||
)
|
||||
(fp_text value "CR2032_Battery_Holder" (at 7.3 -4.7 unlocked) (layer "F.Fab")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp 4ef94bb9-2e0a-4fb6-a2da-03965e6f684d)
|
||||
)
|
||||
(fp_text user "${REFERENCE}" (at 7.3 -3.2 unlocked) (layer "F.Fab")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp 65867e2e-3f24-4116-aeeb-b7c0d0114cc2)
|
||||
)
|
||||
(fp_line (start 2.54 -2.54) (end -1.7 -2.54) (layer "F.SilkS") (width 0.12) (tstamp 476b1128-2a06-4418-8c4e-6e9ca4d7e5b7))
|
||||
(fp_line (start 2.54 2.54) (end 2.54 -2.54) (layer "F.SilkS") (width 0.12) (tstamp 533854f6-ac37-46ef-b665-ba2d8aac1c93))
|
||||
(fp_line (start -1.7 2.54) (end 2.54 2.54) (layer "F.SilkS") (width 0.12) (tstamp b2600e4c-aec5-41d4-a697-836066376dce))
|
||||
(fp_circle (center -15.38 0) (end -1.5 0) (layer "F.SilkS") (width 0.12) (fill none) (tstamp 5b0557b9-b3ad-49ce-b3bc-d9e1ab30942e))
|
||||
(fp_line (start 3.4 3.4) (end 3.4 -3.4) (layer "F.CrtYd") (width 0.1) (tstamp 07d95c75-cc60-460d-8e32-ab4c50dd8b25))
|
||||
(fp_line (start -0.82 3.4) (end 3.4 3.4) (layer "F.CrtYd") (width 0.1) (tstamp 21b8ac40-eadf-4191-b4e4-7b4932f275a8))
|
||||
(fp_line (start 3.4 -3.4) (end -0.82 -3.4) (layer "F.CrtYd") (width 0.1) (tstamp 9add2b14-349f-4255-8bc9-6867c4ac3e1c))
|
||||
(fp_circle (center -15.38 0) (end -0.5 0) (layer "F.CrtYd") (width 0.1) (fill none) (tstamp 9e528cce-46ff-4bf2-83ab-a1ec37fb2e1f))
|
||||
(pad "1" thru_hole circle (at 0 0) (size 2 2) (drill oval 1.3 1.2) (layers *.Cu *.Mask) (tstamp 48d89f06-d1fb-4760-981e-831543f25182))
|
||||
(pad "2" thru_hole circle (at -20.49 0) (size 2 2) (drill 1.3) (layers *.Cu *.Mask) (tstamp 04216d84-e824-4bb3-b463-ea6199a58c8c))
|
||||
)
|
||||
42
cad/fan_monitor/fan_monitor.pretty/HE10-16.kicad_mod
Normal file
42
cad/fan_monitor/fan_monitor.pretty/HE10-16.kicad_mod
Normal file
@ -0,0 +1,42 @@
|
||||
(footprint "HE10-16" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 62261CF8)
|
||||
(descr "HE10-16 straight connector")
|
||||
(tags "CONN HE10")
|
||||
(attr through_hole)
|
||||
(fp_text reference "HE10-16" (at -5.588 -6.096) (layer "F.SilkS")
|
||||
(effects (font (size 1.778 1.778) (thickness 0.3048)))
|
||||
(tstamp 89ef1cf6-a73d-4c50-90d3-6c27b7f0cb41)
|
||||
)
|
||||
(fp_text value "Val**" (at 12.7 6.096) (layer "F.SilkS")
|
||||
(effects (font (size 1.778 1.778) (thickness 0.3048)))
|
||||
(tstamp 0c0726bc-34f3-42e8-9a5f-0ffe16108e71)
|
||||
)
|
||||
(fp_line (start -12.7 -3.556) (end 12.7 -3.556) (layer "F.SilkS") (width 0.12) (tstamp 003a5141-e200-4e63-b032-3dc8d3c60607))
|
||||
(fp_line (start -2.54 3.556) (end -12.7 3.556) (layer "F.SilkS") (width 0.12) (tstamp 092f439c-150d-415b-8b93-adf5f43b88bb))
|
||||
(fp_line (start 12.7 3.556) (end 2.54 3.556) (layer "F.SilkS") (width 0.12) (tstamp 11338925-1d78-44eb-8945-bafb4bea6979))
|
||||
(fp_line (start -11.684 0.508) (end -11.684 2.032) (layer "F.SilkS") (width 0.3048) (tstamp 48016a16-8602-46dd-bd85-d3687867709e))
|
||||
(fp_line (start -2.54 4.318) (end 2.54 4.318) (layer "F.SilkS") (width 0.12) (tstamp 5a96ec7d-775a-4197-bd3a-b35afffc8167))
|
||||
(fp_line (start -12.7 3.556) (end -12.7 -3.556) (layer "F.SilkS") (width 0.12) (tstamp 62572e48-123e-40e3-bbac-e4ee3d41f626))
|
||||
(fp_line (start 12.7 -3.556) (end 12.7 3.556) (layer "F.SilkS") (width 0.12) (tstamp 6c09dd4e-4b6b-4d6d-bc2f-6d45b2513087))
|
||||
(fp_line (start 2.54 3.556) (end 2.54 4.318) (layer "F.SilkS") (width 0.12) (tstamp 8ffd1010-e240-4259-9498-37bf8e52f29e))
|
||||
(fp_line (start -2.54 4.318) (end -2.54 3.556) (layer "F.SilkS") (width 0.12) (tstamp c62d4278-6b5d-4e14-a6ad-d17662e7c6cc))
|
||||
(fp_line (start -10.414 1.27) (end -11.684 0.508) (layer "F.SilkS") (width 0.3048) (tstamp e02cc154-2e4b-4cc3-94d2-75105d00954f))
|
||||
(fp_line (start -11.684 2.032) (end -10.414 1.27) (layer "F.SilkS") (width 0.3048) (tstamp e9b94cbb-b6a7-43f9-a9af-38d866bd1cb6))
|
||||
(pad "1" thru_hole circle (at -8.89 1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp 754700b8-82bc-4d0e-926c-196988658878))
|
||||
(pad "2" thru_hole circle (at -8.89 -1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp 57c102eb-b177-4220-ac3e-15a5da0e4ef6))
|
||||
(pad "3" thru_hole circle (at -6.35 1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp 8f7a1c62-e866-4146-b861-025badda20d3))
|
||||
(pad "4" thru_hole circle (at -6.35 -1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp 2b71dc2a-4c96-42a0-bd46-95937452e3f3))
|
||||
(pad "5" thru_hole circle (at -3.81 1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp 9bc1f9b0-8c47-431f-99ec-8a9b89e7b1d6))
|
||||
(pad "6" thru_hole circle (at -3.81 -1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp 439749f2-96d3-44a8-bdc0-e4c1c8bbc1ad))
|
||||
(pad "7" thru_hole circle (at -1.27 1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp c39b5135-fbe0-4931-ad80-ed9c1070d5dd))
|
||||
(pad "8" thru_hole circle (at -1.27 -1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp a15870b4-20f7-4f81-83ab-93da37c2d447))
|
||||
(pad "9" thru_hole circle (at 1.27 1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp 003ad17d-831b-4d0b-96cd-c4dc99e2314f))
|
||||
(pad "10" thru_hole circle (at 1.27 -1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp 79d5e4ae-1bbc-4f06-959e-391f5b194e0e))
|
||||
(pad "11" thru_hole circle (at 3.81 1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp a4523af0-9cc4-4355-96d1-c401269d0754))
|
||||
(pad "12" thru_hole circle (at 3.81 -1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp 8ee69a29-e666-41b5-8ae6-a4a1a8687d7c))
|
||||
(pad "13" thru_hole circle (at 6.35 1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp 6d37ba34-3704-4806-86e1-7fae824ef21b))
|
||||
(pad "14" thru_hole circle (at 6.35 -1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp 20f6e38c-67a5-4644-b9a7-6ec89b3b64fd))
|
||||
(pad "15" thru_hole circle (at 8.89 1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp 92c15745-902a-4afa-9c24-dd3fb8f004e2))
|
||||
(pad "16" thru_hole circle (at 8.89 -1.27) (size 1.524 1.524) (drill 0.9144) (layers *.Cu *.Mask) (tstamp 59147bef-e7d3-42c9-9796-6326ea61071b))
|
||||
)
|
||||
25
cad/fan_monitor/fan_monitor.pretty/HF152FD_Form_A.kicad_mod
Normal file
25
cad/fan_monitor/fan_monitor.pretty/HF152FD_Form_A.kicad_mod
Normal file
@ -0,0 +1,25 @@
|
||||
(footprint "HF152FD_Form_A" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 62261D25)
|
||||
(attr through_hole)
|
||||
(fp_text reference "REF**" (at 6 -5.5 unlocked) (layer "F.SilkS")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp 801b2c57-3824-49e5-89e3-7099dacfe6d1)
|
||||
)
|
||||
(fp_text value "HF152FD_Form_A" (at 6.4 -3.7 unlocked) (layer "F.Fab")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp 208846ef-9d16-4aea-8884-4ad489287be5)
|
||||
)
|
||||
(fp_line (start 17 13.9) (end 17 -2) (layer "F.SilkS") (width 0.12) (tstamp 049a0d59-31c4-4e8e-8965-d3040279d0ae))
|
||||
(fp_line (start 12.2 6.15) (end 12.2 10.85) (layer "F.SilkS") (width 0.12) (tstamp 20b31638-a6e0-490f-9160-2d6a76791db0))
|
||||
(fp_line (start -0.8 6) (end 8.1 6) (layer "F.SilkS") (width 0.12) (tstamp a577a535-624f-49ce-91f3-34c1213746d8))
|
||||
(fp_line (start 17 -2) (end -4.2 -2) (layer "F.SilkS") (width 0.12) (tstamp c1d01f2b-f45c-4cb9-b5bf-219aa60b0ea2))
|
||||
(fp_line (start -4.2 14) (end 17 14) (layer "F.SilkS") (width 0.12) (tstamp c8348631-404d-4e66-a92f-6abdda5d5496))
|
||||
(fp_line (start -4.2 -2) (end -4.2 14) (layer "F.SilkS") (width 0.12) (tstamp d169ccd3-ab8c-409f-8140-98ac4d80171c))
|
||||
(fp_line (start 13 3.75) (end 8.1 6) (layer "F.SilkS") (width 0.12) (tstamp fb9c178b-f3d0-4b11-be23-163bfb0daeef))
|
||||
(fp_rect (start -5.2 -3) (end 18 15) (layer "F.CrtYd") (width 0.05) (fill none) (tstamp 30abb9a4-6a70-4e36-840d-453db3cb840e))
|
||||
(pad "1" thru_hole circle (at 0 0) (size 2.3 2.3) (drill 1.3) (layers *.Cu *.Mask) (tstamp da302846-016d-4be2-af55-6d603d02eb89))
|
||||
(pad "2" thru_hole circle (at 0 12) (size 2.3 2.3) (drill 1.3) (layers *.Cu *.Mask) (tstamp c9b530ce-e490-420e-928e-df4bf9bc5adc))
|
||||
(pad "3" thru_hole circle (at -2 6) (size 2.3 2.3) (drill 1.3) (layers *.Cu *.Mask) (tstamp c164a52d-67af-4765-976d-f02114341851))
|
||||
(pad "4" thru_hole circle (at 12.2 12) (size 2.3 2.3) (drill 1.3) (layers *.Cu *.Mask) (tstamp c518c217-c92c-446b-ac12-3b43c18b8312))
|
||||
)
|
||||
@ -0,0 +1,58 @@
|
||||
(footprint "RotaryEncoder_Alps_EC12E-Switch_Vertical_H20mm" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 6220DEE8)
|
||||
(descr "Alps rotary encoder, EC12E... with switch, vertical shaft, http://www.alps.com/prod/info/E/HTML/Encoder/Incremental/EC12E/EC12E1240405.html & http://cdn-reichelt.de/documents/datenblatt/F100/402097STEC12E08.PDF")
|
||||
(tags "rotary encoder")
|
||||
(attr through_hole)
|
||||
(fp_text reference "REF**" (at -4.7 -7.2) (layer "F.SilkS")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp 3230eb40-7bc6-4e5e-9d9e-ed2d003f678f)
|
||||
)
|
||||
(fp_text value "RotaryEncoder_Alps_EC12E-Switch_Vertical_H20mm" (at 0 7.9) (layer "F.Fab")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp d2467a1a-9475-484b-816d-d3278d65b6ae)
|
||||
)
|
||||
(fp_text user "${REFERENCE}" (at 4 4.1) (layer "F.Fab")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp fa348cbb-8f00-4f00-86b6-34a42c5da4b2)
|
||||
)
|
||||
(fp_line (start 6.7 3.7) (end 6.7 6.3) (layer "F.SilkS") (width 0.12) (tstamp 13bda85d-bdb4-4028-8655-ca62082bbd0e))
|
||||
(fp_line (start -1.9 -6.3) (end -6.7 -6.3) (layer "F.SilkS") (width 0.12) (tstamp 28877f51-a477-4be7-81a8-44ee712ec7d3))
|
||||
(fp_line (start -7.2 -4.1) (end -7.5 -3.8) (layer "F.SilkS") (width 0.12) (tstamp 2d38f326-70be-48c0-9620-f374e6b44553))
|
||||
(fp_line (start 6.7 6.3) (end 1.8 6.3) (layer "F.SilkS") (width 0.12) (tstamp 38834dde-49a4-4749-b387-93717fe74f4e))
|
||||
(fp_line (start 6.7 -6.3) (end 6.7 -3.7) (layer "F.SilkS") (width 0.12) (tstamp 39160ce7-41b6-4f4c-925c-316217a932c4))
|
||||
(fp_line (start 0 -0.5) (end 0 0.5) (layer "F.SilkS") (width 0.12) (tstamp 6ccf62e1-00c5-4e79-a745-289343765f26))
|
||||
(fp_line (start -6.7 -6.3) (end -6.7 -3.8) (layer "F.SilkS") (width 0.12) (tstamp 7a92dacf-b8e9-4fc9-b96c-8a353418d4e1))
|
||||
(fp_line (start -7.8 -4.1) (end -7.2 -4.1) (layer "F.SilkS") (width 0.12) (tstamp 9ddf10e3-9a31-4929-b680-2824fd2c0b53))
|
||||
(fp_line (start 1.8 -6.3) (end 6.7 -6.3) (layer "F.SilkS") (width 0.12) (tstamp ccbb416c-3309-48c4-93c5-907d5564b1e9))
|
||||
(fp_line (start 6.7 -1.3) (end 6.7 1.3) (layer "F.SilkS") (width 0.12) (tstamp db916804-132c-4833-8e4e-e331d03795fe))
|
||||
(fp_line (start -7.5 -3.8) (end -7.8 -4.1) (layer "F.SilkS") (width 0.12) (tstamp e4b61a90-9fdc-4218-9938-e16c6f7c1ca6))
|
||||
(fp_line (start -1.8 6.3) (end -6.7 6.3) (layer "F.SilkS") (width 0.12) (tstamp eceb0525-a06c-4fa4-a0f2-8145028606d4))
|
||||
(fp_line (start -6.7 6.3) (end -6.7 3.5) (layer "F.SilkS") (width 0.12) (tstamp f4ce0425-7c60-4743-a869-ee9f6d7040b0))
|
||||
(fp_line (start -0.5 0) (end 0.5 0) (layer "F.SilkS") (width 0.12) (tstamp f733798e-9aaa-4c97-9f3c-157847976754))
|
||||
(fp_circle (center 0 0) (end 3 0) (layer "F.SilkS") (width 0.12) (fill none) (tstamp df367f70-b410-4873-ad4b-63a9c86a05ca))
|
||||
(fp_line (start -9 -7.35) (end -9 7.35) (layer "F.CrtYd") (width 0.05) (tstamp 4f32e0aa-f6fb-4cf3-831e-4b12621e63dc))
|
||||
(fp_line (start 8.5 7.35) (end 8.5 -7.35) (layer "F.CrtYd") (width 0.05) (tstamp 732685a8-328e-432e-8c85-ee4b2fffe0b0))
|
||||
(fp_line (start -9 -7.35) (end 8.5 -7.35) (layer "F.CrtYd") (width 0.05) (tstamp 82d0b3be-eea8-4bc5-8533-79dfb04cc7cb))
|
||||
(fp_line (start 8.5 7.35) (end -9 7.35) (layer "F.CrtYd") (width 0.05) (tstamp 8e1082f7-21b2-416f-8e96-fe3bbc69296c))
|
||||
(fp_line (start 6.6 -6.2) (end 6.6 6.2) (layer "F.Fab") (width 0.12) (tstamp 271d4529-d8e6-4856-bebe-d720a70a7c07))
|
||||
(fp_line (start 6.6 6.2) (end -6.6 6.2) (layer "F.Fab") (width 0.12) (tstamp 36010ca5-cfa5-465a-8dc7-6635522cbf65))
|
||||
(fp_line (start -5.6 -6.2) (end 6.6 -6.2) (layer "F.Fab") (width 0.12) (tstamp 5e1aadb2-931a-493b-9ac2-eb23274a2317))
|
||||
(fp_line (start -3 0) (end 3 0) (layer "F.Fab") (width 0.12) (tstamp 6ab1e2c5-9404-47fc-9b40-3a7a764a6b49))
|
||||
(fp_line (start -6.6 -5.1) (end -5.6 -6.2) (layer "F.Fab") (width 0.12) (tstamp bc10529c-c01c-4e90-a8ac-d5dae8a36dc8))
|
||||
(fp_line (start 0 -3) (end 0 3) (layer "F.Fab") (width 0.12) (tstamp c9b8d358-c79a-4379-833f-0ced5eb8dee0))
|
||||
(fp_line (start -6.6 6.2) (end -6.6 -5.1) (layer "F.Fab") (width 0.12) (tstamp fd4b24da-969c-4c00-b821-9c55ad3429fa))
|
||||
(fp_circle (center 0 0) (end 3 0) (layer "F.Fab") (width 0.12) (fill none) (tstamp 8e42c692-a244-40c3-90a4-95d7f4220979))
|
||||
(pad "A" thru_hole rect (at -7.5 -2.5) (size 2 2) (drill 1) (layers *.Cu *.Mask) (tstamp 959d1fc3-a140-4705-aad1-4aeaa394a1e6))
|
||||
(pad "B" thru_hole circle (at -7.5 2.5) (size 2 2) (drill 1) (layers *.Cu *.Mask) (tstamp 84789112-335a-4624-b647-9a9c525f08b3))
|
||||
(pad "C" thru_hole circle (at -7.5 0) (size 2 2) (drill 1) (layers *.Cu *.Mask) (tstamp 016d7760-6329-438b-8502-f5fbd25e0c16))
|
||||
(pad "MP" thru_hole rect (at 0 5.6) (size 3 2.5) (drill oval 2.5 2) (layers *.Cu *.Mask) (tstamp 7caeec3f-9b1c-4bb8-930b-1529be94c357))
|
||||
(pad "MP" thru_hole rect (at 0 -5.6) (size 3 2.5) (drill oval 2.5 2) (layers *.Cu *.Mask) (tstamp e030cdbc-437e-432d-9c29-74b330e45d14))
|
||||
(pad "S1" thru_hole circle (at 7 -2.5) (size 2 2) (drill 1) (layers *.Cu *.Mask) (tstamp f38003a7-92db-4262-a7f0-21b2df95ac2a))
|
||||
(pad "S2" thru_hole circle (at 7 2.5) (size 2 2) (drill 1) (layers *.Cu *.Mask) (tstamp 47686dc9-b9b5-4ae5-868a-c868ae958872))
|
||||
(model "${KICAD6_3DMODEL_DIR}/Rotary_Encoder.3dshapes/RotaryEncoder_Alps_EC12E-Switch_Vertical_H20mm.wrl"
|
||||
(offset (xyz -7.5 2.5 0))
|
||||
(scale (xyz 1 1 1))
|
||||
(rotate (xyz 0 0 0))
|
||||
)
|
||||
)
|
||||
65
cad/fan_monitor/fan_monitor.pretty/blue_pill.kicad_mod
Normal file
65
cad/fan_monitor/fan_monitor.pretty/blue_pill.kicad_mod
Normal file
@ -0,0 +1,65 @@
|
||||
(footprint "blue_pill" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 62261D40)
|
||||
(attr through_hole)
|
||||
(fp_text reference "REF**" (at 9.525 12.7) (layer "F.SilkS")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp f8c2bdc8-0f14-44b8-96a1-6b3ede9c5b64)
|
||||
)
|
||||
(fp_text value "blue_pill" (at 8.255 14.105) (layer "F.Fab")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp 6fee9d9c-f0c8-4edf-980b-473836d5c178)
|
||||
)
|
||||
(fp_line (start -1.3 -2.5) (end -1.3 50.3) (layer "F.SilkS") (width 0.12) (tstamp 03b7ea59-04ff-4bfc-a26f-17e4b04b9d62))
|
||||
(fp_line (start 9.75 -2.75) (end 5.5 -2.75) (layer "F.SilkS") (width 0.12) (tstamp 1df5d875-8a9c-43e5-b202-fc86872522cf))
|
||||
(fp_line (start 16.5 -2.5) (end -1.3 -2.5) (layer "F.SilkS") (width 0.12) (tstamp 2a047ba3-1265-48c2-9aba-747f2aba922c))
|
||||
(fp_line (start -1.3 50.3) (end 16.6 50.3) (layer "F.SilkS") (width 0.12) (tstamp 3597f731-eae6-47ca-8690-cde5f7bdb161))
|
||||
(fp_line (start 9.75 0.75) (end 9.75 -2.75) (layer "F.SilkS") (width 0.12) (tstamp 6577e2d6-e771-4f1a-b78b-c897f7ae89cb))
|
||||
(fp_line (start 5.5 -2.75) (end 5.5 0.75) (layer "F.SilkS") (width 0.12) (tstamp bf3dac99-ac50-4ac6-bfbd-9ed628e3720e))
|
||||
(fp_line (start 16.6 50.3) (end 16.6 -2.5) (layer "F.SilkS") (width 0.12) (tstamp c719e44a-a7cf-4402-b739-a46a404f89a2))
|
||||
(fp_line (start 5.5 0.75) (end 9.75 0.75) (layer "F.SilkS") (width 0.12) (tstamp ced23a17-cc8a-4c5d-95f6-018b51394a9f))
|
||||
(fp_line (start 18.6 54) (end -3.3 54) (layer "F.CrtYd") (width 0.05) (tstamp 7889cf67-d749-4721-9a05-b8f106a0c34d))
|
||||
(fp_line (start -3.3 -3) (end -3.3 54) (layer "F.CrtYd") (width 0.1) (tstamp b1bbb12a-19e6-4036-b1b0-c1d0661cdfd6))
|
||||
(fp_line (start -3.3 -3) (end 18.6 -3) (layer "F.CrtYd") (width 0.05) (tstamp ebb85895-3703-4d7d-81db-0607e5c7c87e))
|
||||
(fp_line (start 18.6 -3) (end 18.6 54) (layer "F.CrtYd") (width 0.05) (tstamp f85d8a88-cc20-4a57-91db-da57a46bd0e8))
|
||||
(pad "3V3" thru_hole circle (at 15.24 5.08) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 9429d18d-18ba-4899-a864-514af21c1c9e))
|
||||
(pad "3V3" thru_hole circle (at 0 48.26) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp ab93c249-614f-4756-8205-775844995b38))
|
||||
(pad "5V" thru_hole circle (at 0 43.18) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 9d2d5d11-17ad-498b-b650-ef6577a9e2e4))
|
||||
(pad "G" thru_hole circle (at 15.24 2.54) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 5769ca6c-3a60-4d6a-b8b1-c7432d89c83e))
|
||||
(pad "G" thru_hole circle (at 0 45.72) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 99122ab4-05b4-425f-afa6-c53cd70cfd8a))
|
||||
(pad "G" thru_hole circle (at 15.24 0) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp a53e144c-ae51-4f49-839a-b31e423f0b9d))
|
||||
(pad "NRST" thru_hole circle (at 15.24 7.62) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 89adf5f0-766a-45e3-af45-a3faf584a058))
|
||||
(pad "PA0" thru_hole circle (at 15.24 38.1) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp e7e7fbd7-4b54-4338-b1d2-29f53f7b660c))
|
||||
(pad "PA1" thru_hole circle (at 15.24 35.56) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp c14f5110-1d19-4caa-9122-5ac098ce414a))
|
||||
(pad "PA2" thru_hole circle (at 15.24 33.02) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 3991cdf7-8300-4efb-bb38-01580a5689c5))
|
||||
(pad "PA3" thru_hole circle (at 15.24 30.48) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 78e39cfa-07bc-4f7a-b896-73828b677fe1))
|
||||
(pad "PA4" thru_hole circle (at 15.24 27.94) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 56bca0f5-d3d4-461e-b2b6-fc223cd81593))
|
||||
(pad "PA5" thru_hole circle (at 15.24 25.4) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp f5742966-ec76-4f1f-88df-f64b9d56d458))
|
||||
(pad "PA6" thru_hole circle (at 15.24 22.86) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp d5e75f75-0d2d-44be-ae3e-080c6022f848))
|
||||
(pad "PA7" thru_hole circle (at 15.24 20.32) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp feef1a5d-b0e4-47c5-bf36-03b69c53c26e))
|
||||
(pad "PA8" thru_hole circle (at 0 10.16) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp d1d00f7c-ba70-407d-8a05-6b69162b6688))
|
||||
(pad "PA9" thru_hole circle (at 0 12.7) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 7efb9b93-c827-4b3b-a5d9-b36f9ef25816))
|
||||
(pad "PA10" thru_hole circle (at 0 15.24) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 71175409-5161-4e7f-870a-7220bae2c840))
|
||||
(pad "PA11" thru_hole circle (at 0 17.78) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 83d3b4b0-830f-4b2c-a2ad-25662b5585f5))
|
||||
(pad "PA12" thru_hole circle (at 0 20.32) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 2c9a54f8-1020-4c9b-88be-de55d79c9941))
|
||||
(pad "PA15" thru_hole circle (at 0 22.86) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp e6ecce2c-676a-4740-82a3-1cf281e0b525))
|
||||
(pad "PB0" thru_hole circle (at 15.24 17.78) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 6531a13d-ba14-42d0-a09c-ec44f2278da1))
|
||||
(pad "PB1" thru_hole circle (at 15.24 15.24) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 5f8423d6-a368-46fb-a863-e202201145ce))
|
||||
(pad "PB3" thru_hole circle (at 0 25.4) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 41fc3f0d-22fa-48a7-9930-c2029b9b969a))
|
||||
(pad "PB4" thru_hole circle (at 0 27.94) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp ba716453-7f84-4787-b000-a2ee3220be04))
|
||||
(pad "PB5" thru_hole circle (at 0 30.48) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp ddb6da8f-716c-4060-b5a4-c4f35c7c375f))
|
||||
(pad "PB6" thru_hole circle (at 0 33.02) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 0de60cee-8896-437b-a77d-cd13d6795028))
|
||||
(pad "PB7" thru_hole circle (at 0 35.56) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 4033c1c8-aeee-45cd-a4cf-4f861de46bdb))
|
||||
(pad "PB8" thru_hole circle (at 0 38.1) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 3f2a3830-7912-4fc3-8059-eef54d216ee3))
|
||||
(pad "PB9" thru_hole circle (at 0 40.64) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp f555b93a-c2fc-4e0d-b244-9eb4c2e6b819))
|
||||
(pad "PB10" thru_hole circle (at 15.24 12.7) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 90b36a28-d7c6-48d8-9dcb-2871978e5364))
|
||||
(pad "PB11" thru_hole circle (at 15.24 10.16) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp a1908b8e-0825-48b3-8135-e1cc6c5b0526))
|
||||
(pad "PB12" thru_hole circle (at 0 0) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 8a540c29-89ce-44a9-acf2-abe44ea3381b))
|
||||
(pad "PB13" thru_hole circle (at 0 2.54) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 3ab34b92-d783-4739-b3ee-5ec0badcacc5))
|
||||
(pad "PB14" thru_hole circle (at 0 5.08) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 7bdc6b61-1f4e-405d-addb-1f53ec9c409c))
|
||||
(pad "PB15" thru_hole circle (at 0 7.62) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 781733b4-d333-437b-af9a-88f7d844e98c))
|
||||
(pad "PC13" thru_hole circle (at 15.24 45.72) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp f5325825-1d7c-45fb-b4e1-4316fcafd9d2))
|
||||
(pad "PC14" thru_hole circle (at 15.24 43.18) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 02fd0541-1fc4-49c6-9718-ed72e55c2174))
|
||||
(pad "PC15" thru_hole circle (at 15.24 40.64) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 9111aca0-9ec0-4dd6-a8d4-54f6887adc07))
|
||||
(pad "VBAT" thru_hole circle (at 15.24 48.26) (size 1.524 1.524) (drill 0.9) (layers *.Cu *.Mask) (tstamp 02d8ba94-59de-429f-94fd-4bb380c66404))
|
||||
)
|
||||
3
cad/fan_monitor/fp-lib-table
Normal file
3
cad/fan_monitor/fp-lib-table
Normal file
@ -0,0 +1,3 @@
|
||||
(fp_lib_table
|
||||
(lib (name "fan_monitor")(type "KiCad")(uri "${KIPRJMOD}/fan_monitor.pretty")(options "")(descr ""))
|
||||
)
|
||||
3
cad/fan_monitor/sym-lib-table
Normal file
3
cad/fan_monitor/sym-lib-table
Normal file
@ -0,0 +1,3 @@
|
||||
(sym_lib_table
|
||||
(lib (name "fan_monitor")(type "KiCad")(uri "${KIPRJMOD}/fan_monitor.kicad_sym")(options "")(descr ""))
|
||||
)
|
||||
BIN
docs/Graphs.ods
BIN
docs/Graphs.ods
Binary file not shown.
15
docs/encoder_accel.py
Normal file
15
docs/encoder_accel.py
Normal file
@ -0,0 +1,15 @@
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
import seaborn as sns
|
||||
|
||||
sns.set_theme(style="whitegrid")
|
||||
|
||||
a = 0.85
|
||||
b = 0.2
|
||||
|
||||
x = np.arange(-5, 6)
|
||||
y = np.copysign(a*abs(x) * 10**(b*abs(x)) * 0.1, x)
|
||||
|
||||
sns.lineplot(x=x, y=y, palette="tab10", linewidth=2.5)
|
||||
plt.show()
|
||||
|
||||
306
src/config.rs
306
src/config.rs
@ -1,23 +1,52 @@
|
||||
pub enum ConfigError {
|
||||
LoadError,
|
||||
}
|
||||
use core::fmt;
|
||||
|
||||
use crate::lcd_gui::LCDScreen;
|
||||
|
||||
//---Config struct----------------------------------------------------------------------------------
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum FanOutput {
|
||||
P1,
|
||||
P2,
|
||||
}
|
||||
|
||||
pub enum FanState {
|
||||
ON,
|
||||
OFF,
|
||||
impl FanOutput {
|
||||
|
||||
pub fn from_bits(bits: u16) -> FanOutput {
|
||||
if bits == 0 { return Self::P1 }
|
||||
return Self::P2;
|
||||
}
|
||||
|
||||
pub fn to_bits(&self) -> u16 {
|
||||
match self {
|
||||
Self::P1 => 0,
|
||||
Self::P2 => 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct CalData {
|
||||
pub offset: f32,
|
||||
pub raw_value: Option<f32>,
|
||||
}
|
||||
|
||||
impl CalData {
|
||||
pub fn new(offset: f32) -> CalData {
|
||||
CalData {
|
||||
offset,
|
||||
raw_value: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct SystemConfig {
|
||||
pub max_temp_diff: f32,
|
||||
pub min_temp_diff: f32,
|
||||
pub ext_offset: f32,
|
||||
pub p1_offset: f32,
|
||||
pub p2_offset: f32,
|
||||
pub ext_offset: CalData,
|
||||
pub p1_offset: CalData,
|
||||
pub p2_offset: CalData,
|
||||
pub fan_output: FanOutput,
|
||||
}
|
||||
|
||||
@ -27,18 +56,263 @@ impl SystemConfig {
|
||||
SystemConfig {
|
||||
max_temp_diff: 8.0,
|
||||
min_temp_diff: 4.0,
|
||||
ext_offset: 0.0,
|
||||
p1_offset: 0.0,
|
||||
p2_offset: 0.0,
|
||||
ext_offset: CalData::new(0.0),
|
||||
p1_offset: CalData::new(0.0),
|
||||
p2_offset: CalData::new(0.0),
|
||||
fan_output: FanOutput::P1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load() -> Result<ConfigError, SystemConfig> {
|
||||
unimplemented!();
|
||||
//---Menu struct------------------------------------------------------------------------------------
|
||||
const MENU_ENTRY_NB: usize = 6;
|
||||
|
||||
pub enum MenuState {
|
||||
Scroll,
|
||||
Entry,
|
||||
}
|
||||
|
||||
pub struct Menu {
|
||||
entries: [Entry; MENU_ENTRY_NB],
|
||||
state: MenuState,
|
||||
should_refresh: bool,
|
||||
entry_index: usize,
|
||||
}
|
||||
|
||||
impl Menu {
|
||||
|
||||
pub fn new(config: &SystemConfig) -> Menu {
|
||||
|
||||
Menu {
|
||||
entries: [
|
||||
Entry::new("fan out", EntryValue::FanOut (FanOutput::P1), config),
|
||||
Entry::new("max diff", EntryValue::MaxTempDiff (0.0), config),
|
||||
Entry::new("min diff", EntryValue::MinTempDiff (0.0), config),
|
||||
Entry::new("ex", EntryValue::ExtOffset (CalData::new(0.0)), config),
|
||||
Entry::new("s1", EntryValue::P1Offset (CalData::new(0.0)), config),
|
||||
Entry::new("s2", EntryValue::P2Offset (CalData::new(0.0)), config),
|
||||
],
|
||||
state: MenuState::Scroll,
|
||||
should_refresh: true,
|
||||
entry_index: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn store() -> SystemConfig {
|
||||
unimplemented!();
|
||||
pub fn button_update(&mut self, config: &mut SystemConfig) -> bool {
|
||||
|
||||
self.should_refresh = true;
|
||||
|
||||
// update state machine
|
||||
match self.state {
|
||||
MenuState::Scroll => {
|
||||
if self.entry_index == 0 { return true }
|
||||
// read desired value from config
|
||||
self.state = MenuState::Entry;
|
||||
self.entries[self.entry_index - 1].select(config);
|
||||
},
|
||||
MenuState::Entry => {
|
||||
// write modified value to config
|
||||
self.state = MenuState::Scroll;
|
||||
self.entries[self.entry_index - 1].deselect(config);
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
pub fn movement_update(&mut self, movement: i32) {
|
||||
|
||||
if movement != 0 {
|
||||
match self.state {
|
||||
MenuState::Scroll => {
|
||||
|
||||
// convert movement to entry index
|
||||
let mut index = self.entry_index as i32 + movement;
|
||||
if index > MENU_ENTRY_NB as i32 {
|
||||
index = MENU_ENTRY_NB as i32;
|
||||
} else if index < 0 {
|
||||
index = 0;
|
||||
}
|
||||
self.entry_index = index as usize;
|
||||
},
|
||||
MenuState::Entry => {
|
||||
|
||||
// update entry
|
||||
self.entries[self.entry_index - 1].update(-movement);
|
||||
//note : "-" sign is just to revert encoder direction, feels better when using
|
||||
//the interface
|
||||
},
|
||||
}
|
||||
|
||||
self.should_refresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
|
||||
match self.state {
|
||||
MenuState::Entry => {
|
||||
// if an entry is selected, disguard all modifications
|
||||
self.entries[self.entry_index - 1].disgard();
|
||||
self.state = MenuState::Scroll;
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
|
||||
self.entry_index = 0;
|
||||
}
|
||||
|
||||
pub fn display<L: LCDScreen>(&mut self, screen: &mut L) {
|
||||
|
||||
if self.should_refresh {
|
||||
|
||||
// first line
|
||||
screen.clear();
|
||||
screen.set_cursor_pos(0);
|
||||
let _ = write!(screen, "\u{007e}");
|
||||
if self.entry_index == 0 {
|
||||
let _ = write!(screen, "retour");
|
||||
} else {
|
||||
self.entries[self.entry_index - 1].display(screen);
|
||||
}
|
||||
|
||||
// second line (if any)
|
||||
if self.entry_index < MENU_ENTRY_NB {
|
||||
screen.set_cursor_pos(0x40);
|
||||
let _ = write!(screen, " ");
|
||||
self.entries[self.entry_index].display(screen);
|
||||
}
|
||||
|
||||
self.should_refresh = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum EntryValue {
|
||||
MaxTempDiff (f32),
|
||||
MinTempDiff (f32),
|
||||
ExtOffset (CalData),
|
||||
P1Offset (CalData),
|
||||
P2Offset (CalData),
|
||||
FanOut (FanOutput),
|
||||
}
|
||||
|
||||
impl EntryValue {
|
||||
|
||||
fn modify(&mut self, n: i32) {
|
||||
use libm::{powf, copysignf, fabsf};
|
||||
|
||||
use crate::utils::TEMP_RANGE;
|
||||
|
||||
match self {
|
||||
Self::MaxTempDiff (val) | Self::MinTempDiff (val) => {
|
||||
*val += copysignf(fabsf(n as f32) * 0.85 * powf(10.0, 0.15 * fabsf(n as f32))
|
||||
* 0.1, n as f32);
|
||||
// avoid display issues by limiting value range
|
||||
if *val > 99.9 { *val = 99.9; }
|
||||
else if *val < -99.9 { *val = -99.9; }
|
||||
},
|
||||
Self::ExtOffset (data) | Self::P1Offset (data) | Self::P2Offset (data) => {
|
||||
data.offset += copysignf(fabsf(n as f32) * 0.85
|
||||
* powf(10.0, 0.15 * fabsf(n as f32)) * 0.1, n as f32);
|
||||
// avoid limiting issues like before, taking probe bounds into account
|
||||
if data.offset + TEMP_RANGE.end > 99.9 {
|
||||
data.offset = 99.9 - TEMP_RANGE.end;
|
||||
}
|
||||
else if data.offset + TEMP_RANGE.start < -99.9 {
|
||||
data.offset = -99.9 - TEMP_RANGE.start;
|
||||
}
|
||||
},
|
||||
Self::FanOut (output) => {
|
||||
if n%2 != 0 {
|
||||
match output {
|
||||
FanOutput::P1 => *output = FanOutput::P2,
|
||||
FanOutput::P2 => *output = FanOutput::P1,
|
||||
}}}}
|
||||
}
|
||||
|
||||
fn load(&mut self, config: &SystemConfig) {
|
||||
match self {
|
||||
Self::MaxTempDiff (val) => *val = config.max_temp_diff,
|
||||
Self::MinTempDiff (val) => *val = config.min_temp_diff,
|
||||
Self::ExtOffset (data) => *data = config.ext_offset,
|
||||
Self::P1Offset (data) => *data = config.p1_offset,
|
||||
Self::P2Offset (data) => *data = config.p2_offset,
|
||||
Self::FanOut (val) => *val = config.fan_output,
|
||||
};
|
||||
}
|
||||
|
||||
fn store(&mut self, config: &mut SystemConfig) {
|
||||
match self {
|
||||
Self::MaxTempDiff (val) => config.max_temp_diff = *val,
|
||||
Self::MinTempDiff (val) => config.min_temp_diff = *val,
|
||||
Self::ExtOffset (data) => config.ext_offset = *data,
|
||||
Self::P1Offset (data) => config.p1_offset = *data,
|
||||
Self::P2Offset (data) => config.p2_offset = *data,
|
||||
Self::FanOut (val) => config.fan_output = *val,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for EntryValue {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
use crate::lcd_gui::Temp;
|
||||
|
||||
match self {
|
||||
Self::MaxTempDiff (val) | Self::MinTempDiff (val) =>
|
||||
formatter.write_fmt(format_args!("{:.1}", val)),
|
||||
Self::ExtOffset (data) | Self::P1Offset (data) | Self::P2Offset (data) => {
|
||||
let temp: Temp = data.raw_value.map(|val| val + data.offset).into();
|
||||
formatter.write_fmt(format_args!("{:.1}({:.1})", data.offset, temp))
|
||||
},
|
||||
Self::FanOut (output) => {
|
||||
match output {
|
||||
FanOutput::P1 => formatter.write_fmt(format_args!("1")),
|
||||
FanOutput::P2 => formatter.write_fmt(format_args!("2")),
|
||||
}}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct Entry {
|
||||
text: &'static str,
|
||||
value: EntryValue,
|
||||
is_selected: bool,
|
||||
}
|
||||
|
||||
impl Entry {
|
||||
|
||||
pub fn new(text: &'static str, mut value: EntryValue, config: &SystemConfig) -> Entry {
|
||||
|
||||
value.load(config);
|
||||
Entry {
|
||||
text,
|
||||
value,
|
||||
is_selected: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn display<B: core::fmt::Write>(&self, buffer: &mut B) {
|
||||
let _ = match self.is_selected {
|
||||
true => write!(buffer, "{}:{}", self.text, self.value),
|
||||
false => write!(buffer, "{} {}", self.text, self.value),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn select(&mut self, config: &SystemConfig) {
|
||||
self.is_selected = true;
|
||||
self.value.load(config);
|
||||
}
|
||||
pub fn deselect(&mut self, config: &mut SystemConfig) {
|
||||
self.is_selected = false;
|
||||
self.value.store(config);
|
||||
}
|
||||
|
||||
pub fn disgard(&mut self) {
|
||||
self.is_selected = false;
|
||||
}
|
||||
|
||||
pub fn update(&mut self, n: i32) {
|
||||
self.value.modify(n);
|
||||
}
|
||||
}
|
||||
|
||||
234
src/lcd_gui.rs
234
src/lcd_gui.rs
@ -17,10 +17,16 @@ use hd44780_driver::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
config::SystemConfig,
|
||||
state::SystemState,
|
||||
config::{Menu, SystemConfig, FanOutput},
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* GUI config */
|
||||
|
||||
pub const GUI_TICK_SEC: f32 = 0.2;
|
||||
const GUI_ERROR_SEC: f32 = 0.8;
|
||||
|
||||
//---Temp Enum--------------------------------------------------------------------------------------
|
||||
/// A simple enum to handle displaying temps on the GUI. Temperatures can be valid or not. An
|
||||
/// invalid temperature is displayed as "inval°C" whereas a valid temperature is displayed as
|
||||
@ -33,16 +39,54 @@ pub enum Temp {
|
||||
impl fmt::Display for Temp {
|
||||
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Temp::Valid (deg) => formatter.write_fmt(format_args!("{:.2}", deg)),
|
||||
Temp::Valid (deg) => formatter.write_fmt(format_args!("{:.1}", deg)),
|
||||
Temp::Invalid => formatter.write_str("inval"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::convert::From<Option<f32>> for Temp {
|
||||
fn from(val: Option<f32>) -> Self {
|
||||
match val {
|
||||
Some(deg) => Temp::Valid(deg),
|
||||
None => Temp::Invalid,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl core::convert::From<f32> for Temp {
|
||||
fn from(val: f32) -> Self {
|
||||
Temp::Valid(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl core::cmp::PartialEq<Temp> for Temp {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match self {
|
||||
Self::Valid (val) => match other {
|
||||
Self::Invalid => false,
|
||||
Self::Valid (other_val) => val == other_val,
|
||||
},
|
||||
Self::Invalid => match other {
|
||||
Self::Invalid => true,
|
||||
_ => false,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---LCDGui Struct----------------------------------------------------------------------------------
|
||||
|
||||
pub enum GUIState {
|
||||
Off,
|
||||
Idle,
|
||||
Menu,
|
||||
Error (&'static str),
|
||||
}
|
||||
|
||||
/// Manages the lcd screen and inputs (encoder + button) and display relevant information. Can also
|
||||
/// be used to configure the system. The update() function should be called frequently to refresh
|
||||
/// the GUI (every 0.2s is enough)
|
||||
/// the GUI (every 0.2s is enough).
|
||||
pub struct LCDGui<L, Q, B>
|
||||
where
|
||||
L: LCDScreen,
|
||||
@ -53,9 +97,14 @@ where
|
||||
qei: Q,
|
||||
button: &'static AtomicBool,
|
||||
backlight: Option<B>,
|
||||
count: u16,
|
||||
count: i32,
|
||||
state: GUIState,
|
||||
menu: Menu,
|
||||
ext_deg: Temp,
|
||||
p1_deg: Temp,
|
||||
p2_deg: Temp,
|
||||
should_refresh: bool,
|
||||
blink_counter: i32,
|
||||
}
|
||||
|
||||
impl<L, Q, B> LCDGui<L, Q, B>
|
||||
@ -65,19 +114,27 @@ where
|
||||
B: OutputPin,
|
||||
{
|
||||
|
||||
pub fn new(lcd: L, qei: Q, button: &'static AtomicBool, backlight: Option<B>)
|
||||
/// Create and configure a new GUI. By default the screen will display the idle screen.
|
||||
pub fn new(lcd: L, qei: Q, button: &'static AtomicBool, backlight: Option<B>,
|
||||
config: &SystemConfig)
|
||||
-> LCDGui<L, Q, B> {
|
||||
|
||||
use hd44780_driver::{Cursor, CursorBlink, Display};
|
||||
|
||||
let count = qei.count();
|
||||
let count = qei.count() as i32;
|
||||
let mut gui = LCDGui {
|
||||
lcd,
|
||||
qei,
|
||||
button,
|
||||
backlight,
|
||||
count,
|
||||
state: GUIState::Idle,
|
||||
menu: Menu::new(config),
|
||||
ext_deg: Temp::Invalid,
|
||||
p1_deg: Temp::Invalid,
|
||||
p2_deg: Temp::Invalid,
|
||||
should_refresh: true,
|
||||
blink_counter: 0,
|
||||
};
|
||||
|
||||
if let Some(bl) = &mut gui.backlight { let _ = bl.set_high(); };
|
||||
@ -87,52 +144,157 @@ where
|
||||
gui.lcd.set_display_mode(
|
||||
DisplayMode {
|
||||
display: Display::On,
|
||||
cursor_visibility: Cursor::Visible,
|
||||
cursor_blink: CursorBlink::On,
|
||||
}
|
||||
);
|
||||
let _ = gui.lcd.write_str("Hello world!");
|
||||
cursor_visibility: Cursor::Invisible,
|
||||
cursor_blink: CursorBlink::Off,
|
||||
});
|
||||
|
||||
gui
|
||||
}
|
||||
|
||||
pub fn update<O: OutputPin>(&mut self, state: &mut SystemState<O>) {
|
||||
/// Perform the necessary operations after an action on the button or the encoder. This
|
||||
/// function should be called frequently (every 0.2s is enough) to keep track of the state of
|
||||
/// the encoder. For added reactivness, it can also be called on a button press. The function
|
||||
/// can modifify the system's config through the system state and will take care of updating
|
||||
/// the latter. Return true when something has been updated during the function call, usefull
|
||||
/// for implementing powersaving features.
|
||||
pub fn update<O: OutputPin>(&mut self, state: &mut SystemState<O>) -> bool {
|
||||
|
||||
self.ext_deg = match state.ext_temp() {
|
||||
Some(deg) => Temp::Valid(deg),
|
||||
None => Temp::Invalid,
|
||||
};
|
||||
let mut input_update = false;
|
||||
|
||||
self.p1_deg = match state.p1_temp() {
|
||||
Some(deg) => Temp::Valid(deg),
|
||||
None => Temp::Invalid,
|
||||
};
|
||||
|
||||
//TODO deduplicate button detection
|
||||
// manage button press
|
||||
if self.button.swap(false, Ordering::AcqRel) {
|
||||
self.lcd.write_str("paf").unwrap();
|
||||
input_update = true;
|
||||
|
||||
// update state machine
|
||||
match self.state {
|
||||
GUIState::Off => {
|
||||
self.state = GUIState::Idle;
|
||||
self.lcd.clear();
|
||||
if let Some(bl) = &mut self.backlight { let _ = bl.set_high(); };
|
||||
self.should_refresh = true;
|
||||
},
|
||||
GUIState::Idle => {
|
||||
self.state = GUIState::Menu;
|
||||
self.menu.display(&mut self.lcd);
|
||||
},
|
||||
GUIState::Menu => {
|
||||
|
||||
//TODO improve that
|
||||
let mut config: SystemConfig = *state.config();
|
||||
if self.menu.button_update(&mut config) {
|
||||
self.state = GUIState::Idle;
|
||||
self.update_temps(state);
|
||||
} else {
|
||||
state.update_config(config);
|
||||
self.menu.display(&mut self.lcd);
|
||||
}
|
||||
},
|
||||
GUIState::Error (_) => {
|
||||
self.state = GUIState::Idle;
|
||||
self.lcd.clear();
|
||||
self.should_refresh = true;
|
||||
}}}
|
||||
|
||||
// manage encoder movement
|
||||
let count = self.qei.count() as i32 / 2;
|
||||
let diff1 = count - self.count;
|
||||
let diff2 = 511 - i32::abs(diff1);
|
||||
let diff = if i32::abs(diff1) < diff2 {
|
||||
diff1
|
||||
} else {
|
||||
diff2 * -i32::signum(diff1)
|
||||
};
|
||||
|
||||
if diff != 0 {
|
||||
input_update = true;
|
||||
self.count = count;
|
||||
}
|
||||
|
||||
if self.count != self.qei.count() {
|
||||
self.count = self.qei.count();
|
||||
// display relevant screen
|
||||
match self.state {
|
||||
GUIState::Off => {},
|
||||
GUIState::Idle => {
|
||||
if self.should_refresh {
|
||||
display_idle_screen(&mut self.lcd, &self.ext_deg, &self.p1_deg, &self.p2_deg,
|
||||
&state.config().fan_output);
|
||||
self.should_refresh = false;
|
||||
}
|
||||
},
|
||||
GUIState::Menu => {
|
||||
if diff != 0 {
|
||||
self.menu.movement_update(diff);
|
||||
self.menu.display(&mut self.lcd);
|
||||
}
|
||||
},
|
||||
GUIState::Error (err)=> {
|
||||
self.blink_counter += 1;
|
||||
|
||||
if self.blink_counter as f32 * GUI_TICK_SEC >= 2.0*GUI_ERROR_SEC {
|
||||
let _ = write!(self.lcd, "Erreur: ");
|
||||
self.lcd.set_cursor_pos(0x40);
|
||||
self.lcd.write_str(" ").unwrap();
|
||||
self.lcd.set_cursor_pos(0x40);
|
||||
write!(self.lcd, "{}", self.qei.count()/2).unwrap();
|
||||
let _ = write!(self.lcd, "{}", err);
|
||||
self.blink_counter = 0;
|
||||
} else if self.blink_counter as f32 * GUI_TICK_SEC >= GUI_ERROR_SEC {
|
||||
self.lcd.clear();
|
||||
}
|
||||
}}
|
||||
|
||||
input_update
|
||||
}
|
||||
|
||||
self.lcd.set_cursor_pos(0);
|
||||
self.lcd.write_str(" ").unwrap();
|
||||
self.lcd.set_cursor_pos(0);
|
||||
let _ = write!(self.lcd, "{}\u{00df}C", self.ext_deg);
|
||||
/// Update the temperatures to display on the idle screen. Should be called whenever the
|
||||
/// temperatures are modified.
|
||||
pub fn update_temps<O: OutputPin>(&mut self, state: &SystemState<O>) {
|
||||
|
||||
self.lcd.set_cursor_pos(0x40);
|
||||
self.lcd.write_str(" ").unwrap();
|
||||
self.lcd.set_cursor_pos(0x40);
|
||||
let _ = write!(self.lcd, "{}\u{00df}C", self.p1_deg);
|
||||
self.ext_deg = state.ext_temp().into();
|
||||
self.p1_deg = state.p1_temp().into();
|
||||
self.p2_deg = state.p2_temp().into();
|
||||
|
||||
self.should_refresh = true;
|
||||
}
|
||||
|
||||
pub fn sleep(&mut self) {
|
||||
|
||||
self.state = GUIState::Off;
|
||||
|
||||
// reset menu in case the user was in-menu
|
||||
self.menu.reset();
|
||||
|
||||
// manage lcd
|
||||
self.lcd.clear();
|
||||
//TODO set display off ?
|
||||
if let Some(bl) = &mut self.backlight { let _ = bl.set_low(); };
|
||||
}
|
||||
|
||||
pub fn display_error(&mut self, error: &'static str) {
|
||||
self.state = GUIState::Error (error);
|
||||
self.blink_counter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fn display_idle_screen<L: LCDScreen>(screen: &mut L, ext_deg: &Temp, p1_deg: &Temp, p2_deg: &Temp,
|
||||
fan_output: &FanOutput) {
|
||||
|
||||
// display temperatures
|
||||
screen.clear();
|
||||
screen.set_cursor_pos(0);
|
||||
let _ = write!(screen, "Ext:{}", ext_deg);
|
||||
screen.set_cursor_pos(0x41);
|
||||
let _ = write!(screen, "1:{}", p1_deg);
|
||||
screen.set_cursor_pos(0x49);
|
||||
let _ = write!(screen, "2:{}", p2_deg);
|
||||
|
||||
// display probe selection
|
||||
match fan_output {
|
||||
FanOutput::P1 => screen.set_cursor_pos(0x40),
|
||||
FanOutput::P2 => screen.set_cursor_pos(0x48),
|
||||
}
|
||||
let _ = write!(screen, "*");
|
||||
}
|
||||
|
||||
//---LCDScreen trait--------------------------------------------------------------------------------
|
||||
/// A wrapper trait to complement the write trait by adding the extra functions provided by a lcd
|
||||
/// screen, such as cursor position.
|
||||
pub trait LCDScreen: core::fmt::Write {
|
||||
|
||||
fn reset(&mut self);
|
||||
|
||||
142
src/main.rs
142
src/main.rs
@ -12,7 +12,6 @@ use cortex_m::interrupt::Mutex;
|
||||
use cortex_m_rt::entry;
|
||||
|
||||
use embedded_hal::digital::{
|
||||
v2::OutputPin,
|
||||
v1_compat::OldOutputPin,
|
||||
};
|
||||
|
||||
@ -24,15 +23,16 @@ use stm32f1xx_hal::{
|
||||
prelude::*,
|
||||
timer::{Timer, CountDownTimer, Event},
|
||||
qei::{QeiOptions, SlaveMode},
|
||||
rtc::Rtc,
|
||||
rtc::{Rtc, RtcClkLsi},
|
||||
};
|
||||
|
||||
mod lcd_gui;
|
||||
use lcd_gui::LCDGui;
|
||||
use lcd_gui::{LCDGui, GUI_TICK_SEC};
|
||||
|
||||
mod utils;
|
||||
use utils::{
|
||||
TemperatureProbe,
|
||||
ConfigStorage,
|
||||
};
|
||||
|
||||
mod config;
|
||||
@ -44,10 +44,10 @@ use state::SystemState;
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* system config */
|
||||
|
||||
const GUI_TICK_SEC: f32 = 0.2;
|
||||
const AWAKE_TIMEOUT_SEC: f32 = 20.0;
|
||||
const HEARTBEAT_SEC: f32 = 1.0;
|
||||
|
||||
const TEMPS_TICK_SEC: u32 = 2;
|
||||
const TEMPS_TICK_SEC: u32 = 30;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* interrupt variables */
|
||||
@ -59,15 +59,30 @@ static TICK_TIMER: Mutex<RefCell<Option<CountDownTimer<pac::TIM2>>>>
|
||||
= Mutex::new(RefCell::new(None));
|
||||
|
||||
// button interrupt
|
||||
static BUTTON_PIN: Mutex<RefCell<Option<gpiob::PB8<Input<PullUp>>>>>
|
||||
static BUTTON_PIN: Mutex<RefCell<Option<gpiob::PB8<Input<Floating>>>>>
|
||||
= Mutex::new(RefCell::new(None));
|
||||
static BUTTON_FLAG: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
// temps interrupt
|
||||
static RTC: Mutex<RefCell<Option<Rtc>>> = Mutex::new(RefCell::new(None));
|
||||
static RTC: Mutex<RefCell<Option<Rtc::<RtcClkLsi>>>> = Mutex::new(RefCell::new(None));
|
||||
static G_EXTI: Mutex<RefCell<Option<EXTI>>> = Mutex::new(RefCell::new(None));
|
||||
static TEMP_FLAG: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* power management */
|
||||
enum PowerState {
|
||||
Awake,
|
||||
Sleeping,
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* error management */
|
||||
enum ErrorState {
|
||||
NoError,
|
||||
NewError (&'static str),
|
||||
HandlingError,
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* interrupt service routines */
|
||||
#[interrupt]
|
||||
@ -126,16 +141,16 @@ fn main() -> ! {
|
||||
let mut dp = pac::Peripherals::take().unwrap();
|
||||
|
||||
// clocks config
|
||||
let mut rcc = dp.RCC.constrain();
|
||||
let rcc = dp.RCC.constrain();
|
||||
let mut flash = dp.FLASH.constrain();
|
||||
let clocks = rcc.cfgr
|
||||
.use_hse(8.mhz())
|
||||
.freeze(&mut flash.acr);
|
||||
|
||||
// GPIOs
|
||||
let mut gpioa = dp.GPIOA.split(&mut rcc.apb2);
|
||||
let mut gpiob = dp.GPIOB.split(&mut rcc.apb2);
|
||||
let mut gpioc = dp.GPIOC.split(&mut rcc.apb2);
|
||||
let mut gpioa = dp.GPIOA.split();
|
||||
let mut gpiob = dp.GPIOB.split();
|
||||
let mut gpioc = dp.GPIOC.split();
|
||||
|
||||
// setup LED
|
||||
let mut led = gpioc.pc13.into_push_pull_output(&mut gpioc.crh);
|
||||
@ -146,7 +161,7 @@ fn main() -> ! {
|
||||
});
|
||||
|
||||
// Configure the timer 2 as tick timer
|
||||
let mut timer = Timer::tim2(dp.TIM2, &clocks, &mut rcc.apb1)
|
||||
let mut timer = Timer::tim2(dp.TIM2, &clocks)
|
||||
.start_count_down(((1.0/GUI_TICK_SEC) as u32).hz());
|
||||
timer.listen(Event::Update);
|
||||
|
||||
@ -159,8 +174,8 @@ fn main() -> ! {
|
||||
dp.EXTI.imr.write(|w| w.mr17().set_bit());
|
||||
|
||||
// setup RTC
|
||||
let mut backup_domain = rcc.bkp.constrain(dp.BKP, &mut rcc.apb1, &mut dp.PWR);
|
||||
let mut rtc = Rtc::rtc(dp.RTC, &mut backup_domain);
|
||||
let mut backup_domain = rcc.bkp.constrain(dp.BKP, &mut dp.PWR);
|
||||
let mut rtc = Rtc::<RtcClkLsi>::rtc(dp.RTC, &mut backup_domain);
|
||||
rtc.set_alarm(rtc.current_time() + TEMPS_TICK_SEC);
|
||||
rtc.listen_alarm();
|
||||
|
||||
@ -168,7 +183,21 @@ fn main() -> ! {
|
||||
RTC.borrow(cs).borrow_mut().replace(rtc)
|
||||
});
|
||||
|
||||
let mut afio = dp.AFIO.constrain(&mut rcc.apb2);
|
||||
let mut afio = dp.AFIO.constrain();
|
||||
|
||||
// initialize system state
|
||||
let mut config_storage = ConfigStorage::new(backup_domain, dp.CRC.new());
|
||||
let mut error_state = ErrorState::NoError;
|
||||
let config = match config_storage.load_config() {
|
||||
Ok(conf) => conf,
|
||||
Err(_) => {
|
||||
error_state = ErrorState::NewError("config invalide");
|
||||
let conf = SystemConfig::new();
|
||||
config_storage.save_config(&conf);
|
||||
conf
|
||||
}};
|
||||
let mut state = SystemState::new(config, config_storage,
|
||||
gpiob.pb12.into_push_pull_output(&mut gpiob.crh));
|
||||
|
||||
// Setup display
|
||||
let mut gui = {
|
||||
@ -193,7 +222,7 @@ fn main() -> ! {
|
||||
|
||||
// Force write mode
|
||||
let mut rw_pin = gpioa.pa9.into_push_pull_output(&mut gpioa.crh);
|
||||
rw_pin.set_low().unwrap();
|
||||
rw_pin.set_low();
|
||||
|
||||
let lcd = HD44780::new_8bit(
|
||||
OldOutputPin::new(rs_pin),
|
||||
@ -210,9 +239,9 @@ fn main() -> ! {
|
||||
);
|
||||
|
||||
// setup button (interrupt)
|
||||
let mut but_pin = gpiob.pb8.into_pull_up_input(&mut gpiob.crh);
|
||||
let mut but_pin = gpiob.pb8.into_floating_input(&mut gpiob.crh);
|
||||
but_pin.make_interrupt_source(&mut afio);
|
||||
but_pin.trigger_on_edge(&dp.EXTI, Edge::RISING);
|
||||
but_pin.trigger_on_edge(&dp.EXTI, Edge::Rising);
|
||||
but_pin.enable_interrupt(&dp.EXTI);
|
||||
|
||||
cortex_m::interrupt::free(|cs| {
|
||||
@ -223,14 +252,14 @@ fn main() -> ! {
|
||||
let backlight_pin = gpiob.pb9.into_push_pull_output(&mut gpiob.crh);
|
||||
|
||||
// setup encoder
|
||||
let enc = Timer::tim4(dp.TIM4, &clocks, &mut rcc.apb1)
|
||||
let enc = Timer::tim4(dp.TIM4, &clocks)
|
||||
.qei((gpiob.pb6, gpiob.pb7), &mut afio.mapr,
|
||||
QeiOptions {
|
||||
slave_mode:SlaveMode::EncoderMode2,
|
||||
auto_reload_value: 200
|
||||
slave_mode:SlaveMode::EncoderMode1,
|
||||
auto_reload_value: 1022,
|
||||
});
|
||||
|
||||
LCDGui::new(lcd, enc, &BUTTON_FLAG, Some(backlight_pin))
|
||||
LCDGui::new(lcd, enc, &BUTTON_FLAG, Some(backlight_pin), state.config())
|
||||
};
|
||||
|
||||
let exti = dp.EXTI;
|
||||
@ -254,42 +283,89 @@ fn main() -> ! {
|
||||
// configure stop mode (not working yet, probably due to fake chip)
|
||||
//dp.PWR.cr.write(|w| w.pdds().stop_mode());
|
||||
//dp.PWR.cr.write(|w| w.lpds().set_bit());
|
||||
cp.SCB.set_sleepdeep();
|
||||
|
||||
// setup adc
|
||||
let mut adc = Adc::adc1(dp.ADC1, &mut rcc.apb2, clocks);
|
||||
let mut adc = Adc::adc1(dp.ADC1, clocks);
|
||||
adc.set_sample_time(SampleTime::T_71);
|
||||
let adc = RefCell::new(adc);
|
||||
let ext1 = gpioa.pa4.into_analog(&mut gpioa.crl);
|
||||
let ext2 = gpioa.pa5.into_analog(&mut gpioa.crl);
|
||||
let p1_1 = gpioa.pa2.into_analog(&mut gpioa.crl);
|
||||
let p1_2 = gpioa.pa3.into_analog(&mut gpioa.crl);
|
||||
let p2_1 = gpioa.pa2.into_analog(&mut gpioa.crl);
|
||||
let p2_2 = gpioa.pa3.into_analog(&mut gpioa.crl);
|
||||
let p1_1 = gpioa.pa0.into_analog(&mut gpioa.crl);
|
||||
let p1_2 = gpioa.pa1.into_analog(&mut gpioa.crl);
|
||||
|
||||
let mut ext_probe = TemperatureProbe::new(&adc, ext1, ext2).unwrap();
|
||||
let mut p1_probe = TemperatureProbe::new(&adc, p1_1, p1_2).unwrap();
|
||||
let mut p2_probe = TemperatureProbe::new(&adc, p2_1, p2_2).unwrap();
|
||||
|
||||
// initialize system state
|
||||
let config = SystemConfig::new();
|
||||
let mut state = SystemState::new(config, gpiob.pb12.into_push_pull_output(&mut gpiob.crh));
|
||||
let mut power_state = PowerState::Awake;
|
||||
let mut timeout = 0;
|
||||
|
||||
/* run */
|
||||
let _ = TEMP_FLAG.swap(true, Ordering::Release);
|
||||
|
||||
// fix some weird bug caused by the debouncing capacitor of the button
|
||||
for _ in 0..10 {
|
||||
cortex_m::asm::wfi();
|
||||
}
|
||||
BUTTON_FLAG.store(false, Ordering::Release);
|
||||
|
||||
loop {
|
||||
|
||||
//compute temps
|
||||
match error_state {
|
||||
ErrorState::NoError => {
|
||||
if TEMP_FLAG.swap(false, Ordering::AcqRel) {
|
||||
|
||||
// compute temps
|
||||
let ext_temp = ext_probe.read().ok();
|
||||
let p1_temp = p1_probe.read().ok();
|
||||
let p2_temp = p2_probe.read().ok();
|
||||
|
||||
state.update(ext_temp, p1_temp, None);
|
||||
state.update(ext_temp, p1_temp, p2_temp);
|
||||
gui.update_temps(&mut state);
|
||||
|
||||
} else {
|
||||
|
||||
match gui.update(&mut state) {
|
||||
true => timeout = 0,
|
||||
false => timeout += 1,
|
||||
}
|
||||
|
||||
gui.update(&mut state);
|
||||
// manage power state
|
||||
match power_state {
|
||||
PowerState::Awake => { // normal gui update
|
||||
if timeout as f32 * GUI_TICK_SEC >= AWAKE_TIMEOUT_SEC {
|
||||
// go to sleep
|
||||
power_state = PowerState::Sleeping;
|
||||
gui.sleep();
|
||||
cp.SCB.set_sleepdeep();
|
||||
}
|
||||
},
|
||||
PowerState::Sleeping => { // button was pressed during sleep
|
||||
// wake up
|
||||
power_state = PowerState::Awake;
|
||||
cp.SCB.clear_sleepdeep();
|
||||
}}}
|
||||
},
|
||||
ErrorState::NewError (err) => {
|
||||
gui.display_error(err);
|
||||
state.stop();
|
||||
error_state = ErrorState::HandlingError;
|
||||
},
|
||||
ErrorState::HandlingError => {
|
||||
if gui.update(&mut state) {
|
||||
error_state = ErrorState::NoError;
|
||||
state.reset();
|
||||
ext_probe.reset().unwrap();
|
||||
p1_probe.reset().unwrap();
|
||||
p2_probe.reset().unwrap();
|
||||
timeout = 0;
|
||||
}
|
||||
}}
|
||||
|
||||
// put device in sleep mode until next interrupt (button or timer)
|
||||
cortex_m::asm::wfi();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
51
src/state.rs
51
src/state.rs
@ -6,9 +6,11 @@ use crate::config::{
|
||||
FanOutput,
|
||||
};
|
||||
|
||||
use crate::utils::ConfigStorage;
|
||||
|
||||
pub enum FanState {
|
||||
ON,
|
||||
OFF,
|
||||
On,
|
||||
Off,
|
||||
}
|
||||
|
||||
pub struct Fan<O: OutputPin> {
|
||||
@ -23,19 +25,19 @@ impl<O: OutputPin> Fan<O> {
|
||||
// erroring here means the pin is wrongly configured, there is nothing else to do...
|
||||
pin.set_low().map_err(|_| "fan pin configuration").unwrap();
|
||||
Fan {
|
||||
state: FanState::OFF,
|
||||
state: FanState::Off,
|
||||
pin,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn on(&mut self) {
|
||||
self.pin.set_high().map_err(|_| "fan pin configuration").unwrap();
|
||||
self.state = FanState::ON;
|
||||
self.state = FanState::On;
|
||||
}
|
||||
|
||||
pub fn off(&mut self) {
|
||||
self.pin.set_low().map_err(|_| "fan pin configuration").unwrap();
|
||||
self.state = FanState::OFF;
|
||||
self.state = FanState::Off;
|
||||
}
|
||||
|
||||
pub fn state(&self) -> &FanState { &self.state }
|
||||
@ -43,6 +45,7 @@ impl<O: OutputPin> Fan<O> {
|
||||
|
||||
pub struct SystemState<O: OutputPin> {
|
||||
config: SystemConfig,
|
||||
config_storage: ConfigStorage,
|
||||
ext_temp: Option<f32>,
|
||||
p1_temp: Option<f32>,
|
||||
p2_temp: Option<f32>,
|
||||
@ -51,10 +54,12 @@ pub struct SystemState<O: OutputPin> {
|
||||
|
||||
impl<O: OutputPin> SystemState<O> {
|
||||
|
||||
pub fn new(config: SystemConfig, fan_control_pin: O) -> SystemState<O> {
|
||||
pub fn new(config: SystemConfig, config_storage: ConfigStorage, fan_control_pin: O)
|
||||
-> SystemState<O> {
|
||||
|
||||
SystemState {
|
||||
config,
|
||||
config_storage,
|
||||
ext_temp: None,
|
||||
p1_temp: None,
|
||||
p2_temp: None,
|
||||
@ -70,12 +75,13 @@ impl<O: OutputPin> SystemState<O> {
|
||||
pub fn update_config(&mut self, config: SystemConfig) {
|
||||
|
||||
// remove offsets
|
||||
let ext_temp = self.ext_temp.map(|temp| temp - self.config.ext_offset);
|
||||
let p1_temp = self.p1_temp.map(|temp| temp - self.config.p1_offset);
|
||||
let p2_temp = self.p2_temp.map(|temp| temp - self.config.p2_offset);
|
||||
let ext_temp = self.ext_temp.map(|temp| temp - self.config.ext_offset.offset);
|
||||
let p1_temp = self.p1_temp.map(|temp| temp - self.config.p1_offset.offset);
|
||||
let p2_temp = self.p2_temp.map(|temp| temp - self.config.p2_offset.offset);
|
||||
|
||||
// replace config
|
||||
self.config = config;
|
||||
self.config_storage.save_config(&self.config);
|
||||
|
||||
// reset fan state before recomputing fan state
|
||||
self.fan.off();
|
||||
@ -87,9 +93,14 @@ impl<O: OutputPin> SystemState<O> {
|
||||
pub fn update(&mut self, ext_temp: Option<f32>, p1_temp: Option<f32>, p2_temp: Option<f32>) {
|
||||
|
||||
// apply offsets
|
||||
self.ext_temp = ext_temp.map(|temp| temp + self.config.ext_offset);
|
||||
self.p1_temp = p1_temp.map(|temp| temp + self.config.p1_offset);
|
||||
self.p2_temp = p2_temp.map(|temp| temp + self.config.p2_offset);
|
||||
self.ext_temp = ext_temp.map(|temp| temp + self.config.ext_offset.offset);
|
||||
self.p1_temp = p1_temp.map(|temp| temp + self.config.p1_offset.offset);
|
||||
self.p2_temp = p2_temp.map(|temp| temp + self.config.p2_offset.offset);
|
||||
|
||||
// update cal values
|
||||
self.config.ext_offset.raw_value = ext_temp;
|
||||
self.config.p1_offset.raw_value = p1_temp;
|
||||
self.config.p2_offset.raw_value = p2_temp;
|
||||
|
||||
// select right probe and check if data is available
|
||||
let p = match match self.config.fan_output {
|
||||
@ -112,16 +123,26 @@ impl<O: OutputPin> SystemState<O> {
|
||||
|
||||
// compute fan state
|
||||
match self.fan.state() {
|
||||
FanState::ON => {
|
||||
FanState::On => {
|
||||
if (p - ext) < self.config.min_temp_diff {
|
||||
self.fan.off();
|
||||
}
|
||||
},
|
||||
FanState::OFF => {
|
||||
FanState::Off => {
|
||||
if (p - ext) > self.config.max_temp_diff {
|
||||
self.fan.on();
|
||||
}
|
||||
},
|
||||
}}
|
||||
}
|
||||
|
||||
pub fn stop(&mut self) {
|
||||
self.fan.off();
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) {
|
||||
self.ext_temp = None;
|
||||
self.p1_temp = None;
|
||||
self.p2_temp = None;
|
||||
self.fan.off();
|
||||
}
|
||||
}
|
||||
|
||||
120
src/utils.rs
120
src/utils.rs
@ -1,24 +1,39 @@
|
||||
use core::{
|
||||
marker::PhantomData,
|
||||
cell::RefCell,
|
||||
ops::Range,
|
||||
};
|
||||
|
||||
use embedded_hal::adc::*;
|
||||
|
||||
use stm32f1xx_hal::{
|
||||
backup_domain::BackupDomain,
|
||||
crc::Crc,
|
||||
};
|
||||
|
||||
use libm::*;
|
||||
|
||||
use half::f16;
|
||||
|
||||
use crate::config::SystemConfig;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* 2nd order linearisation factor for the temperature probe */
|
||||
const A: f32 = -0.00058;
|
||||
const B: f32 = 0.0677;
|
||||
const A: f32 = -0.000574;
|
||||
const B: f32 = 0.0676;
|
||||
const C: f32 = -0.07;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* valid temperature range */
|
||||
pub const TEMP_RANGE: Range<f32> = -10.0..45.0;
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* error management */
|
||||
#[derive(Debug)]
|
||||
pub enum ProbeError {
|
||||
ReadError,
|
||||
Initializing,
|
||||
OutOfRange,
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
@ -76,9 +91,9 @@ where
|
||||
// compute first temp approximation to speed up stabilization
|
||||
let mut temp = 0.0;
|
||||
for _ in 0..10 {
|
||||
temp += read_temp(&adc, &mut pos_pin, &mut neg_pin)?;
|
||||
temp += read_temp(adc, &mut pos_pin, &mut neg_pin)?;
|
||||
}
|
||||
temp = temp/10.0;
|
||||
temp /= 10.0;
|
||||
|
||||
Ok(TemperatureProbe {
|
||||
adc,
|
||||
@ -97,7 +112,10 @@ where
|
||||
match self.stabilized {
|
||||
true => {
|
||||
self.filtered_temp += (temp - self.filtered_temp)/FILTER_TIME_CONSTANT;
|
||||
Ok(self.filtered_temp)
|
||||
match TEMP_RANGE.contains(&self.filtered_temp) {
|
||||
true => Ok(self.filtered_temp),
|
||||
false => Err(ProbeError::OutOfRange),
|
||||
}
|
||||
},
|
||||
false => { // filter is not yet stabilized
|
||||
let old_temp = self.filtered_temp;
|
||||
@ -112,5 +130,97 @@ where
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) -> Result<(), ProbeError>{
|
||||
|
||||
// re-compute first temp approximation to speed up stabilization
|
||||
let mut temp = 0.0;
|
||||
for _ in 0..10 {
|
||||
temp += read_temp(self.adc, &mut self.pos_pin, &mut self.neg_pin)?;
|
||||
}
|
||||
temp /= 10.0;
|
||||
|
||||
self.filtered_temp = temp;
|
||||
self.stabilized = false;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------
|
||||
/* ConfigStorage */
|
||||
|
||||
pub struct ConfigStorage {
|
||||
backup_domain: BackupDomain,
|
||||
crc: Crc,
|
||||
}
|
||||
|
||||
impl ConfigStorage {
|
||||
|
||||
pub fn new(backup_domain: BackupDomain, crc: Crc) -> ConfigStorage {
|
||||
|
||||
ConfigStorage {
|
||||
backup_domain,
|
||||
crc,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_config(&mut self) -> Result<SystemConfig, ()> {
|
||||
use crate::config::{CalData, FanOutput};
|
||||
|
||||
// read from persistent memory
|
||||
let mut values: [u16; 10] = [0; 10];
|
||||
for (i, val) in values.iter_mut().enumerate() {
|
||||
*val = self.backup_domain.read_data_register_low(i);
|
||||
}
|
||||
|
||||
// compute CRC
|
||||
self.crc.reset();
|
||||
for i in (2..8).step_by(2) {
|
||||
self.crc.write((values[i] as u32) << 16 | values[i+1] as u32);
|
||||
}
|
||||
let crc = (values[0] as u32) << 16 | values[1] as u32;
|
||||
|
||||
// parse config if CRC is valid
|
||||
match crc != 0 && crc == self.crc.read() {
|
||||
true => {
|
||||
Ok(SystemConfig {
|
||||
max_temp_diff: f16::from_bits(values[2]).to_f32(),
|
||||
min_temp_diff: f16::from_bits(values[3]).to_f32(),
|
||||
ext_offset: CalData::new(f16::from_bits(values[4]).to_f32()),
|
||||
p1_offset: CalData::new(f16::from_bits(values[5]).to_f32()),
|
||||
p2_offset: CalData::new(f16::from_bits(values[6]).to_f32()),
|
||||
fan_output: FanOutput::from_bits(values[7]),
|
||||
})
|
||||
},
|
||||
false => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_config(&mut self, config: &SystemConfig) {
|
||||
|
||||
// prepare buffer for later storage
|
||||
let mut values: [u16; 10] = [0; 10];
|
||||
values[2] = f16::from_f32(config.max_temp_diff).to_bits();
|
||||
values[3] = f16::from_f32(config.min_temp_diff).to_bits();
|
||||
values[4] = f16::from_f32(config.ext_offset.offset).to_bits();
|
||||
values[5] = f16::from_f32(config.p1_offset.offset).to_bits();
|
||||
values[6] = f16::from_f32(config.p2_offset.offset).to_bits();
|
||||
values[7] = config.fan_output.to_bits();
|
||||
|
||||
// compute CRC
|
||||
self.crc.reset();
|
||||
for i in (2..8).step_by(2) {
|
||||
self.crc.write((values[i] as u32) << 16 | values[i+1] as u32);
|
||||
}
|
||||
let crc = self.crc.read();
|
||||
values[0] = ((crc >> 16) & 0xFFFF) as u16;
|
||||
values[1] = (crc & 0xFFFF) as u16;
|
||||
|
||||
// write to persistent memory
|
||||
for (i, val) in values.iter().enumerate() {
|
||||
self.backup_domain.write_data_register_low(i, *val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user