Compare commits
1 Commits
f0d89417b6
...
can
| Author | SHA1 | Date | |
|---|---|---|---|
| 50b2e994ca |
BIN
board/Body1.3mf
BIN
board/Body1.3mf
Binary file not shown.
@@ -18281,7 +18281,7 @@
|
|||||||
(type default)
|
(type default)
|
||||||
)
|
)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
(uuid "8f2e3343-7116-4222-96d1-499b037987be")
|
(uuid "46d24a82-3182-48c8-8e4a-4cd27dd2c4e0")
|
||||||
)
|
)
|
||||||
(fp_line
|
(fp_line
|
||||||
(start -45 24)
|
(start -45 24)
|
||||||
@@ -18291,7 +18291,7 @@
|
|||||||
(type default)
|
(type default)
|
||||||
)
|
)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
(uuid "7489b13e-5da9-4523-bc2a-3a1ad2df161b")
|
(uuid "1acd392a-edf0-453a-b4ea-80c286d57f01")
|
||||||
)
|
)
|
||||||
(fp_line
|
(fp_line
|
||||||
(start -44 24)
|
(start -44 24)
|
||||||
@@ -18301,7 +18301,7 @@
|
|||||||
(type default)
|
(type default)
|
||||||
)
|
)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
(uuid "439d930d-0e01-47c0-af2d-b20c62721628")
|
(uuid "b21db6c0-4242-449b-87d0-a7705aa786df")
|
||||||
)
|
)
|
||||||
(fp_line
|
(fp_line
|
||||||
(start 41 -18)
|
(start 41 -18)
|
||||||
@@ -18311,7 +18311,7 @@
|
|||||||
(type default)
|
(type default)
|
||||||
)
|
)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
(uuid "0547dba4-b6fc-4f82-945c-757ac7fe080a")
|
(uuid "227b10d5-7b48-413f-84d8-72e74d474200")
|
||||||
)
|
)
|
||||||
(fp_line
|
(fp_line
|
||||||
(start 41 24)
|
(start 41 24)
|
||||||
@@ -18321,7 +18321,7 @@
|
|||||||
(type default)
|
(type default)
|
||||||
)
|
)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
(uuid "68186df5-7ea3-4562-a430-befab9581145")
|
(uuid "cbc4f5c3-2761-4d98-86ed-5202a0b3f2e9")
|
||||||
)
|
)
|
||||||
(fp_text user "${REFERENCE}"
|
(fp_text user "${REFERENCE}"
|
||||||
(at -43 -16 90)
|
(at -43 -16 90)
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.1 KiB |
@@ -1,6 +0,0 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-battery-charging" viewBox="0 0 16 16">
|
|
||||||
<path d="M9.585 2.568a.5.5 0 0 1 .226.58L8.677 6.832h1.99a.5.5 0 0 1 .364.843l-5.334 5.667a.5.5 0 0 1-.842-.49L5.99 9.167H4a.5.5 0 0 1-.364-.843l5.333-5.667a.5.5 0 0 1 .616-.09z"/>
|
|
||||||
<path d="M2 4h4.332l-.94 1H2a1 1 0 0 0-1 1v4a1 1 0 0 0 1 1h2.38l-.308 1H2a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2"/>
|
|
||||||
<path d="M2 6h2.45L2.908 7.639A1.5 1.5 0 0 0 3.313 10H2zm8.595-2-.308 1H12a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1H9.276l-.942 1H12a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2z"/>
|
|
||||||
<path d="M12 10h-1.783l1.542-1.639q.146-.156.241-.34zm0-3.354V6h-.646a1.5 1.5 0 0 1 .646.646M16 8a1.5 1.5 0 0 1-1.5 1.5v-3A1.5 1.5 0 0 1 16 8"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 738 B |
@@ -182,40 +182,40 @@
|
|||||||
)
|
)
|
||||||
(pad "9" thru_hole rect
|
(pad "9" thru_hole rect
|
||||||
(at 39.5 22.5)
|
(at 39.5 22.5)
|
||||||
(size 1.7 1.7)
|
(size 0.85 0.85)
|
||||||
(drill 1)
|
(drill 0.5)
|
||||||
(layers "*.Cu" "*.Mask")
|
(layers "*.Cu" "*.Mask")
|
||||||
(remove_unused_layers no)
|
(remove_unused_layers no)
|
||||||
(uuid "f01565c2-eadd-4451-9dea-2ebe28d872f0")
|
(uuid "f01565c2-eadd-4451-9dea-2ebe28d872f0")
|
||||||
)
|
)
|
||||||
(pad "10" thru_hole rect
|
(pad "10" thru_hole rect
|
||||||
(at -0.5 15)
|
(at -0.5 15)
|
||||||
(size 1.7 1.7)
|
(size 0.85 0.85)
|
||||||
(drill 1)
|
(drill 0.5)
|
||||||
(layers "*.Cu" "*.Mask")
|
(layers "*.Cu" "*.Mask")
|
||||||
(remove_unused_layers no)
|
(remove_unused_layers no)
|
||||||
(uuid "56ec7c50-069f-4f46-9b83-ac18e4928930")
|
(uuid "56ec7c50-069f-4f46-9b83-ac18e4928930")
|
||||||
)
|
)
|
||||||
(pad "11" thru_hole rect
|
(pad "11" thru_hole rect
|
||||||
(at -43 22.5)
|
(at -43 22.5)
|
||||||
(size 1.7 1.7)
|
(size 0.85 0.85)
|
||||||
(drill 1)
|
(drill 0.5)
|
||||||
(layers "*.Cu" "*.Mask")
|
(layers "*.Cu" "*.Mask")
|
||||||
(remove_unused_layers no)
|
(remove_unused_layers no)
|
||||||
(uuid "f423be21-13b8-46de-8e19-e48325411a29")
|
(uuid "f423be21-13b8-46de-8e19-e48325411a29")
|
||||||
)
|
)
|
||||||
(pad "12" thru_hole rect
|
(pad "12" thru_hole rect
|
||||||
(at -0.5 -12)
|
(at -0.5 -12)
|
||||||
(size 1.7 1.7)
|
(size 0.85 0.85)
|
||||||
(drill 1)
|
(drill 0.5)
|
||||||
(layers "*.Cu" "*.Mask")
|
(layers "*.Cu" "*.Mask")
|
||||||
(remove_unused_layers no)
|
(remove_unused_layers no)
|
||||||
(uuid "536f0038-06c5-45e5-b1c8-898a364f6ec4")
|
(uuid "536f0038-06c5-45e5-b1c8-898a364f6ec4")
|
||||||
)
|
)
|
||||||
(pad "13" thru_hole rect
|
(pad "13" thru_hole rect
|
||||||
(at 39.5 -16)
|
(at 39.5 -16)
|
||||||
(size 1.7 1.7)
|
(size 0.85 0.85)
|
||||||
(drill 1)
|
(drill 0.5)
|
||||||
(layers "*.Cu" "*.Mask")
|
(layers "*.Cu" "*.Mask")
|
||||||
(remove_unused_layers no)
|
(remove_unused_layers no)
|
||||||
(uuid "3e0cdbaa-8219-48c4-bb0a-fd4f0e78a390")
|
(uuid "3e0cdbaa-8219-48c4-bb0a-fd4f0e78a390")
|
||||||
|
|||||||
@@ -1,208 +0,0 @@
|
|||||||
(footprint "Sensor"
|
|
||||||
(version 20241229)
|
|
||||||
(generator "pcbnew")
|
|
||||||
(generator_version "9.0")
|
|
||||||
(layer "F.Cu")
|
|
||||||
(property "Reference" "REF**"
|
|
||||||
(at 0 -0.5 0)
|
|
||||||
(unlocked yes)
|
|
||||||
(layer "F.SilkS")
|
|
||||||
(uuid "f71e9c26-7923-4e5c-828e-153927862740")
|
|
||||||
(effects
|
|
||||||
(font
|
|
||||||
(size 1 1)
|
|
||||||
(thickness 0.1)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(property "Value" "Sensor"
|
|
||||||
(at 0 1 0)
|
|
||||||
(unlocked yes)
|
|
||||||
(layer "F.Fab")
|
|
||||||
(uuid "d40c7203-0c06-49e1-8672-dbd216694fc8")
|
|
||||||
(effects
|
|
||||||
(font
|
|
||||||
(size 1 1)
|
|
||||||
(thickness 0.15)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(property "Datasheet" ""
|
|
||||||
(at 0 0 0)
|
|
||||||
(unlocked yes)
|
|
||||||
(layer "F.Fab")
|
|
||||||
(hide yes)
|
|
||||||
(uuid "6720cb18-0687-4d55-a6ad-3ccf0819eac2")
|
|
||||||
(effects
|
|
||||||
(font
|
|
||||||
(size 1 1)
|
|
||||||
(thickness 0.15)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(property "Description" ""
|
|
||||||
(at 0 0 0)
|
|
||||||
(unlocked yes)
|
|
||||||
(layer "F.Fab")
|
|
||||||
(hide yes)
|
|
||||||
(uuid "43905e6e-773d-4d5e-8d72-57c092c3495a")
|
|
||||||
(effects
|
|
||||||
(font
|
|
||||||
(size 1 1)
|
|
||||||
(thickness 0.15)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(attr smd)
|
|
||||||
(fp_line
|
|
||||||
(start -45 -18)
|
|
||||||
(end 41 -18)
|
|
||||||
(stroke
|
|
||||||
(width 0.1)
|
|
||||||
(type default)
|
|
||||||
)
|
|
||||||
(layer "F.SilkS")
|
|
||||||
(uuid "e63ec799-95c4-407e-acc9-9c7e6d3e330c")
|
|
||||||
)
|
|
||||||
(fp_line
|
|
||||||
(start -45 24)
|
|
||||||
(end -45 -18)
|
|
||||||
(stroke
|
|
||||||
(width 0.1)
|
|
||||||
(type default)
|
|
||||||
)
|
|
||||||
(layer "F.SilkS")
|
|
||||||
(uuid "a66c286b-432b-493d-9619-2dd4fbfdb21c")
|
|
||||||
)
|
|
||||||
(fp_line
|
|
||||||
(start -44 24)
|
|
||||||
(end -45 24)
|
|
||||||
(stroke
|
|
||||||
(width 0.1)
|
|
||||||
(type default)
|
|
||||||
)
|
|
||||||
(layer "F.SilkS")
|
|
||||||
(uuid "71526e68-71d4-4b13-ab74-482657a06849")
|
|
||||||
)
|
|
||||||
(fp_line
|
|
||||||
(start 41 -18)
|
|
||||||
(end 41 24)
|
|
||||||
(stroke
|
|
||||||
(width 0.1)
|
|
||||||
(type default)
|
|
||||||
)
|
|
||||||
(layer "F.SilkS")
|
|
||||||
(uuid "55554342-bbff-4d1b-b931-67fb7eaa5895")
|
|
||||||
)
|
|
||||||
(fp_line
|
|
||||||
(start 41 24)
|
|
||||||
(end -44 24)
|
|
||||||
(stroke
|
|
||||||
(width 0.1)
|
|
||||||
(type default)
|
|
||||||
)
|
|
||||||
(layer "F.SilkS")
|
|
||||||
(uuid "2dc0ee59-36f6-407e-821a-c6acfe3ea887")
|
|
||||||
)
|
|
||||||
(fp_text user "${REFERENCE}"
|
|
||||||
(at 0 2.5 0)
|
|
||||||
(unlocked yes)
|
|
||||||
(layer "F.Fab")
|
|
||||||
(uuid "befc0725-b201-4f81-b0dc-b327becad9ba")
|
|
||||||
(effects
|
|
||||||
(font
|
|
||||||
(size 1 1)
|
|
||||||
(thickness 0.15)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
(pad "1" thru_hole rect
|
|
||||||
(at -42.4 -15.3)
|
|
||||||
(size 1.7 1.7)
|
|
||||||
(drill 1)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "5538ac99-6e48-4111-a3df-8ff33be72ff3")
|
|
||||||
)
|
|
||||||
(pad "2" thru_hole circle
|
|
||||||
(at -42.4 -12.76)
|
|
||||||
(size 1.7 1.7)
|
|
||||||
(drill 1)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "0c1d4a6c-7871-46ae-a262-a8223571975e")
|
|
||||||
)
|
|
||||||
(pad "3" thru_hole circle
|
|
||||||
(at -42.4 -10.22)
|
|
||||||
(size 1.7 1.7)
|
|
||||||
(drill 1)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "70df4148-0415-45a2-8365-0977fcda45a1")
|
|
||||||
)
|
|
||||||
(pad "4" thru_hole circle
|
|
||||||
(at -42.4 -7.68)
|
|
||||||
(size 1.7 1.7)
|
|
||||||
(drill 1)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "179dd332-2ab2-4917-91ec-35f232b45ce3")
|
|
||||||
)
|
|
||||||
(pad "5" thru_hole circle
|
|
||||||
(at -42.4 -5.14)
|
|
||||||
(size 1.7 1.7)
|
|
||||||
(drill 1)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "17bc8f3a-4727-4e31-90f4-8252dff5ad1c")
|
|
||||||
)
|
|
||||||
(pad "6" thru_hole circle
|
|
||||||
(at -42.4 -2.6)
|
|
||||||
(size 1.7 1.7)
|
|
||||||
(drill 1)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "eee06414-e977-45a8-a5e0-618644284d45")
|
|
||||||
)
|
|
||||||
(pad "7" thru_hole rect
|
|
||||||
(at -0.5 -12)
|
|
||||||
(size 1.7 1.7)
|
|
||||||
(drill 1)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "536f0038-06c5-45e5-b1c8-898a364f6ec4")
|
|
||||||
)
|
|
||||||
(pad "8" thru_hole rect
|
|
||||||
(at 39.5 -16)
|
|
||||||
(size 1.7 1.7)
|
|
||||||
(drill 1)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "3e0cdbaa-8219-48c4-bb0a-fd4f0e78a390")
|
|
||||||
)
|
|
||||||
(pad "9" thru_hole rect
|
|
||||||
(at 39.5 22.5)
|
|
||||||
(size 1.7 1.7)
|
|
||||||
(drill 1)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "f01565c2-eadd-4451-9dea-2ebe28d872f0")
|
|
||||||
)
|
|
||||||
(pad "10" thru_hole rect
|
|
||||||
(at -0.5 15)
|
|
||||||
(size 1.7 1.7)
|
|
||||||
(drill 1)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "56ec7c50-069f-4f46-9b83-ac18e4928930")
|
|
||||||
)
|
|
||||||
(pad "11" thru_hole rect
|
|
||||||
(at -43 22.5)
|
|
||||||
(size 1.7 1.7)
|
|
||||||
(drill 1)
|
|
||||||
(layers "*.Cu" "*.Mask")
|
|
||||||
(remove_unused_layers no)
|
|
||||||
(uuid "f423be21-13b8-46de-8e19-e48325411a29")
|
|
||||||
)
|
|
||||||
(embedded_fonts no)
|
|
||||||
)
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,136 +0,0 @@
|
|||||||
{
|
|
||||||
"board": {
|
|
||||||
"active_layer": 6,
|
|
||||||
"active_layer_preset": "All Layers",
|
|
||||||
"auto_track_width": false,
|
|
||||||
"hidden_netclasses": [],
|
|
||||||
"hidden_nets": [],
|
|
||||||
"high_contrast_mode": 0,
|
|
||||||
"net_color_mode": 1,
|
|
||||||
"opacity": {
|
|
||||||
"images": 0.6,
|
|
||||||
"pads": 1.0,
|
|
||||||
"shapes": 1.0,
|
|
||||||
"tracks": 1.0,
|
|
||||||
"vias": 1.0,
|
|
||||||
"zones": 0.6
|
|
||||||
},
|
|
||||||
"selection_filter": {
|
|
||||||
"dimensions": true,
|
|
||||||
"footprints": true,
|
|
||||||
"graphics": true,
|
|
||||||
"keepouts": true,
|
|
||||||
"lockedItems": false,
|
|
||||||
"otherItems": true,
|
|
||||||
"pads": true,
|
|
||||||
"text": true,
|
|
||||||
"tracks": true,
|
|
||||||
"vias": true,
|
|
||||||
"zones": true
|
|
||||||
},
|
|
||||||
"visible_items": [
|
|
||||||
"vias",
|
|
||||||
"footprint_text",
|
|
||||||
"footprint_anchors",
|
|
||||||
"ratsnest",
|
|
||||||
"grid",
|
|
||||||
"footprints_front",
|
|
||||||
"footprints_back",
|
|
||||||
"footprint_values",
|
|
||||||
"footprint_references",
|
|
||||||
"tracks",
|
|
||||||
"drc_errors",
|
|
||||||
"drawing_sheet",
|
|
||||||
"bitmaps",
|
|
||||||
"pads",
|
|
||||||
"zones",
|
|
||||||
"drc_warnings",
|
|
||||||
"locked_item_shadows",
|
|
||||||
"conflict_shadows",
|
|
||||||
"shapes"
|
|
||||||
],
|
|
||||||
"visible_layers": "ffffffff_ffffffff_ffffffff_ffffffff",
|
|
||||||
"zone_display_mode": 1
|
|
||||||
},
|
|
||||||
"git": {
|
|
||||||
"repo_type": "",
|
|
||||||
"repo_username": "",
|
|
||||||
"ssh_key": ""
|
|
||||||
},
|
|
||||||
"meta": {
|
|
||||||
"filename": "Sensors.kicad_prl",
|
|
||||||
"version": 5
|
|
||||||
},
|
|
||||||
"net_inspector_panel": {
|
|
||||||
"col_hidden": [
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false
|
|
||||||
],
|
|
||||||
"col_order": [
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
4,
|
|
||||||
5,
|
|
||||||
6,
|
|
||||||
7,
|
|
||||||
8,
|
|
||||||
9,
|
|
||||||
10,
|
|
||||||
11
|
|
||||||
],
|
|
||||||
"col_widths": [
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
],
|
|
||||||
"custom_group_rules": [],
|
|
||||||
"expanded_rows": [],
|
|
||||||
"filter_by_net_name": true,
|
|
||||||
"filter_by_netclass": true,
|
|
||||||
"filter_text": "",
|
|
||||||
"group_by_constraint": false,
|
|
||||||
"group_by_netclass": false,
|
|
||||||
"show_unconnected_nets": false,
|
|
||||||
"show_zero_pad_nets": false,
|
|
||||||
"sort_ascending": true,
|
|
||||||
"sorting_column": 0
|
|
||||||
},
|
|
||||||
"open_jobsets": [],
|
|
||||||
"project": {
|
|
||||||
"files": []
|
|
||||||
},
|
|
||||||
"schematic": {
|
|
||||||
"selection_filter": {
|
|
||||||
"graphics": true,
|
|
||||||
"images": true,
|
|
||||||
"labels": true,
|
|
||||||
"lockedItems": false,
|
|
||||||
"otherItems": true,
|
|
||||||
"pins": true,
|
|
||||||
"symbols": true,
|
|
||||||
"text": true,
|
|
||||||
"wires": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,674 +0,0 @@
|
|||||||
{
|
|
||||||
"board": {
|
|
||||||
"3dviewports": [],
|
|
||||||
"design_settings": {
|
|
||||||
"defaults": {
|
|
||||||
"apply_defaults_to_fp_fields": false,
|
|
||||||
"apply_defaults_to_fp_shapes": false,
|
|
||||||
"apply_defaults_to_fp_text": false,
|
|
||||||
"board_outline_line_width": 0.05,
|
|
||||||
"copper_line_width": 0.2,
|
|
||||||
"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.05,
|
|
||||||
"dimension_precision": 4,
|
|
||||||
"dimension_units": 3,
|
|
||||||
"dimensions": {
|
|
||||||
"arrow_length": 1270000,
|
|
||||||
"extension_offset": 500000,
|
|
||||||
"keep_text_aligned": true,
|
|
||||||
"suppress_zeroes": true,
|
|
||||||
"text_position": 0,
|
|
||||||
"units_format": 0
|
|
||||||
},
|
|
||||||
"fab_line_width": 0.1,
|
|
||||||
"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.1,
|
|
||||||
"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": 0.8,
|
|
||||||
"height": 1.27,
|
|
||||||
"width": 2.54
|
|
||||||
},
|
|
||||||
"silk_line_width": 0.1,
|
|
||||||
"silk_text_italic": false,
|
|
||||||
"silk_text_size_h": 1.0,
|
|
||||||
"silk_text_size_v": 1.0,
|
|
||||||
"silk_text_thickness": 0.1,
|
|
||||||
"silk_text_upright": false,
|
|
||||||
"zones": {
|
|
||||||
"min_clearance": 0.5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"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",
|
|
||||||
"connection_width": "warning",
|
|
||||||
"copper_edge_clearance": "error",
|
|
||||||
"copper_sliver": "warning",
|
|
||||||
"courtyards_overlap": "error",
|
|
||||||
"creepage": "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": "error",
|
|
||||||
"footprint_filters_mismatch": "ignore",
|
|
||||||
"footprint_symbol_mismatch": "warning",
|
|
||||||
"footprint_type_mismatch": "ignore",
|
|
||||||
"hole_clearance": "error",
|
|
||||||
"hole_to_hole": "warning",
|
|
||||||
"holes_co_located": "warning",
|
|
||||||
"invalid_outline": "error",
|
|
||||||
"isolated_copper": "warning",
|
|
||||||
"item_on_disabled_layer": "error",
|
|
||||||
"items_not_allowed": "error",
|
|
||||||
"length_out_of_range": "error",
|
|
||||||
"lib_footprint_issues": "warning",
|
|
||||||
"lib_footprint_mismatch": "warning",
|
|
||||||
"malformed_courtyard": "ignore",
|
|
||||||
"microvia_drill_out_of_range": "error",
|
|
||||||
"mirrored_text_on_front_layer": "warning",
|
|
||||||
"missing_courtyard": "ignore",
|
|
||||||
"missing_footprint": "warning",
|
|
||||||
"net_conflict": "warning",
|
|
||||||
"nonmirrored_text_on_back_layer": "warning",
|
|
||||||
"npth_inside_courtyard": "ignore",
|
|
||||||
"padstack": "warning",
|
|
||||||
"pth_inside_courtyard": "ignore",
|
|
||||||
"shorting_items": "error",
|
|
||||||
"silk_edge_clearance": "ignore",
|
|
||||||
"silk_over_copper": "warning",
|
|
||||||
"silk_overlap": "warning",
|
|
||||||
"skew_out_of_range": "error",
|
|
||||||
"solder_mask_bridge": "error",
|
|
||||||
"starved_thermal": "warning",
|
|
||||||
"text_height": "warning",
|
|
||||||
"text_on_edge_cuts": "error",
|
|
||||||
"text_thickness": "warning",
|
|
||||||
"through_hole_pad_without_hole": "error",
|
|
||||||
"too_many_vias": "error",
|
|
||||||
"track_angle": "error",
|
|
||||||
"track_dangling": "warning",
|
|
||||||
"track_segment_length": "error",
|
|
||||||
"track_width": "error",
|
|
||||||
"tracks_crossing": "error",
|
|
||||||
"unconnected_items": "error",
|
|
||||||
"unresolved_variable": "error",
|
|
||||||
"via_dangling": "warning",
|
|
||||||
"zones_intersect": "error"
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"max_error": 0.005,
|
|
||||||
"min_clearance": 0.0,
|
|
||||||
"min_connection": 0.0,
|
|
||||||
"min_copper_edge_clearance": 0.5,
|
|
||||||
"min_groove_width": 0.0,
|
|
||||||
"min_hole_clearance": 0.15,
|
|
||||||
"min_hole_to_hole": 0.25,
|
|
||||||
"min_microvia_diameter": 0.2,
|
|
||||||
"min_microvia_drill": 0.1,
|
|
||||||
"min_resolved_spokes": 2,
|
|
||||||
"min_silk_clearance": 0.0,
|
|
||||||
"min_text_height": 0.8,
|
|
||||||
"min_text_thickness": 0.08,
|
|
||||||
"min_through_hole_diameter": 0.25,
|
|
||||||
"min_track_width": 0.0,
|
|
||||||
"min_via_annular_width": 0.05,
|
|
||||||
"min_via_diameter": 0.25,
|
|
||||||
"solder_mask_to_copper_clearance": 0.005,
|
|
||||||
"use_height_for_length_calcs": true
|
|
||||||
},
|
|
||||||
"teardrop_options": [
|
|
||||||
{
|
|
||||||
"td_onpthpad": true,
|
|
||||||
"td_onroundshapesonly": false,
|
|
||||||
"td_onsmdpad": true,
|
|
||||||
"td_ontrackend": false,
|
|
||||||
"td_onvia": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"teardrop_parameters": [
|
|
||||||
{
|
|
||||||
"td_allow_use_two_tracks": true,
|
|
||||||
"td_curve_segcount": 0,
|
|
||||||
"td_height_ratio": 1.0,
|
|
||||||
"td_length_ratio": 0.5,
|
|
||||||
"td_maxheight": 2.0,
|
|
||||||
"td_maxlen": 1.0,
|
|
||||||
"td_on_pad_in_zone": false,
|
|
||||||
"td_target_name": "td_round_shape",
|
|
||||||
"td_width_to_size_filter_ratio": 0.9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"td_allow_use_two_tracks": true,
|
|
||||||
"td_curve_segcount": 0,
|
|
||||||
"td_height_ratio": 1.0,
|
|
||||||
"td_length_ratio": 0.5,
|
|
||||||
"td_maxheight": 2.0,
|
|
||||||
"td_maxlen": 1.0,
|
|
||||||
"td_on_pad_in_zone": false,
|
|
||||||
"td_target_name": "td_rect_shape",
|
|
||||||
"td_width_to_size_filter_ratio": 0.9
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"td_allow_use_two_tracks": true,
|
|
||||||
"td_curve_segcount": 0,
|
|
||||||
"td_height_ratio": 1.0,
|
|
||||||
"td_length_ratio": 0.5,
|
|
||||||
"td_maxheight": 2.0,
|
|
||||||
"td_maxlen": 1.0,
|
|
||||||
"td_on_pad_in_zone": false,
|
|
||||||
"td_target_name": "td_track_end",
|
|
||||||
"td_width_to_size_filter_ratio": 0.9
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"track_widths": [
|
|
||||||
0.0,
|
|
||||||
0.1,
|
|
||||||
0.2,
|
|
||||||
0.5
|
|
||||||
],
|
|
||||||
"tuning_pattern_settings": {
|
|
||||||
"diff_pair_defaults": {
|
|
||||||
"corner_radius_percentage": 80,
|
|
||||||
"corner_style": 1,
|
|
||||||
"max_amplitude": 1.0,
|
|
||||||
"min_amplitude": 0.2,
|
|
||||||
"single_sided": false,
|
|
||||||
"spacing": 1.0
|
|
||||||
},
|
|
||||||
"diff_pair_skew_defaults": {
|
|
||||||
"corner_radius_percentage": 80,
|
|
||||||
"corner_style": 1,
|
|
||||||
"max_amplitude": 1.0,
|
|
||||||
"min_amplitude": 0.2,
|
|
||||||
"single_sided": false,
|
|
||||||
"spacing": 0.6
|
|
||||||
},
|
|
||||||
"single_track_defaults": {
|
|
||||||
"corner_radius_percentage": 80,
|
|
||||||
"corner_style": 1,
|
|
||||||
"max_amplitude": 1.0,
|
|
||||||
"min_amplitude": 0.2,
|
|
||||||
"single_sided": false,
|
|
||||||
"spacing": 0.6
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"via_dimensions": [
|
|
||||||
{
|
|
||||||
"diameter": 0.0,
|
|
||||||
"drill": 0.0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"diameter": 0.3,
|
|
||||||
"drill": 0.25
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"zones_allow_external_fillets": false
|
|
||||||
},
|
|
||||||
"ipc2581": {
|
|
||||||
"dist": "",
|
|
||||||
"distpn": "",
|
|
||||||
"internal_id": "",
|
|
||||||
"mfg": "",
|
|
||||||
"mpn": ""
|
|
||||||
},
|
|
||||||
"layer_pairs": [],
|
|
||||||
"layer_presets": [],
|
|
||||||
"viewports": []
|
|
||||||
},
|
|
||||||
"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_to_bus_conflict": "error",
|
|
||||||
"bus_to_net_conflict": "error",
|
|
||||||
"different_unit_footprint": "error",
|
|
||||||
"different_unit_net": "error",
|
|
||||||
"duplicate_reference": "error",
|
|
||||||
"duplicate_sheet_names": "error",
|
|
||||||
"endpoint_off_grid": "warning",
|
|
||||||
"extra_units": "error",
|
|
||||||
"footprint_filter": "ignore",
|
|
||||||
"footprint_link_issues": "warning",
|
|
||||||
"four_way_junction": "ignore",
|
|
||||||
"global_label_dangling": "warning",
|
|
||||||
"hier_label_mismatch": "error",
|
|
||||||
"label_dangling": "error",
|
|
||||||
"label_multiple_wires": "warning",
|
|
||||||
"lib_symbol_issues": "warning",
|
|
||||||
"lib_symbol_mismatch": "warning",
|
|
||||||
"missing_bidi_pin": "warning",
|
|
||||||
"missing_input_pin": "warning",
|
|
||||||
"missing_power_pin": "error",
|
|
||||||
"missing_unit": "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": "ignore",
|
|
||||||
"power_pin_not_driven": "ignore",
|
|
||||||
"same_local_global_label": "warning",
|
|
||||||
"similar_label_and_power": "warning",
|
|
||||||
"similar_labels": "warning",
|
|
||||||
"similar_power": "warning",
|
|
||||||
"simulation_model_issue": "ignore",
|
|
||||||
"single_global_label": "ignore",
|
|
||||||
"unannotated": "error",
|
|
||||||
"unconnected_wire_endpoint": "warning",
|
|
||||||
"unit_value_mismatch": "error",
|
|
||||||
"unresolved_variable": "error",
|
|
||||||
"wire_dangling": "error"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"libraries": {
|
|
||||||
"pinned_footprint_libs": [],
|
|
||||||
"pinned_symbol_libs": []
|
|
||||||
},
|
|
||||||
"meta": {
|
|
||||||
"filename": "Sensors.kicad_pro",
|
|
||||||
"version": 3
|
|
||||||
},
|
|
||||||
"net_settings": {
|
|
||||||
"classes": [
|
|
||||||
{
|
|
||||||
"bus_width": 12,
|
|
||||||
"clearance": 0.15,
|
|
||||||
"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)",
|
|
||||||
"priority": 2147483647,
|
|
||||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
|
||||||
"track_width": 0.2,
|
|
||||||
"via_diameter": 0.6,
|
|
||||||
"via_drill": 0.3,
|
|
||||||
"wire_width": 6
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"meta": {
|
|
||||||
"version": 4
|
|
||||||
},
|
|
||||||
"net_colors": null,
|
|
||||||
"netclass_assignments": null,
|
|
||||||
"netclass_patterns": []
|
|
||||||
},
|
|
||||||
"pcbnew": {
|
|
||||||
"last_paths": {
|
|
||||||
"gencad": "",
|
|
||||||
"idf": "",
|
|
||||||
"netlist": "",
|
|
||||||
"plot": "",
|
|
||||||
"pos_files": "",
|
|
||||||
"specctra_dsn": "",
|
|
||||||
"step": "Sensors.step",
|
|
||||||
"svg": "",
|
|
||||||
"vrml": ""
|
|
||||||
},
|
|
||||||
"page_layout_descr_file": ""
|
|
||||||
},
|
|
||||||
"schematic": {
|
|
||||||
"annotate_start_num": 0,
|
|
||||||
"bom_export_filename": "${PROJECTNAME}.csv",
|
|
||||||
"bom_fmt_presets": [],
|
|
||||||
"bom_fmt_settings": {
|
|
||||||
"field_delimiter": ",",
|
|
||||||
"keep_line_breaks": false,
|
|
||||||
"keep_tabs": false,
|
|
||||||
"name": "CSV",
|
|
||||||
"ref_delimiter": ",",
|
|
||||||
"ref_range_delimiter": "",
|
|
||||||
"string_delimiter": "\""
|
|
||||||
},
|
|
||||||
"bom_presets": [],
|
|
||||||
"bom_settings": {
|
|
||||||
"exclude_dnp": false,
|
|
||||||
"fields_ordered": [
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "Reference",
|
|
||||||
"name": "Reference",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": true,
|
|
||||||
"label": "Value",
|
|
||||||
"name": "Value",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": true,
|
|
||||||
"label": "Footprint",
|
|
||||||
"name": "Footprint",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "Datasheet",
|
|
||||||
"name": "Datasheet",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "Description",
|
|
||||||
"name": "Description",
|
|
||||||
"show": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "Qty",
|
|
||||||
"name": "${QUANTITY}",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "#",
|
|
||||||
"name": "${ITEM_NUMBER}",
|
|
||||||
"show": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "LCSC_PART_NUMBER",
|
|
||||||
"name": "LCSC_PART_NUMBER",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "Sim.Device",
|
|
||||||
"name": "Sim.Device",
|
|
||||||
"show": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "Sim.Pins",
|
|
||||||
"name": "Sim.Pins",
|
|
||||||
"show": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": false,
|
|
||||||
"label": "Sim.Type",
|
|
||||||
"name": "Sim.Type",
|
|
||||||
"show": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": true,
|
|
||||||
"label": "DNP",
|
|
||||||
"name": "${DNP}",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": true,
|
|
||||||
"label": "Exclude from BOM",
|
|
||||||
"name": "${EXCLUDE_FROM_BOM}",
|
|
||||||
"show": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"group_by": true,
|
|
||||||
"label": "Exclude from Board",
|
|
||||||
"name": "${EXCLUDE_FROM_BOARD}",
|
|
||||||
"show": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"filter_string": "",
|
|
||||||
"group_symbols": true,
|
|
||||||
"include_excluded_from_bom": true,
|
|
||||||
"name": "",
|
|
||||||
"sort_asc": true,
|
|
||||||
"sort_field": "Reference"
|
|
||||||
},
|
|
||||||
"connection_grid_size": 50.0,
|
|
||||||
"drawing": {
|
|
||||||
"dashed_lines_dash_length_ratio": 12.0,
|
|
||||||
"dashed_lines_gap_length_ratio": 3.0,
|
|
||||||
"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,
|
|
||||||
"operating_point_overlay_i_precision": 3,
|
|
||||||
"operating_point_overlay_i_range": "~A",
|
|
||||||
"operating_point_overlay_v_precision": 3,
|
|
||||||
"operating_point_overlay_v_range": "~V",
|
|
||||||
"overbar_offset_ratio": 1.23,
|
|
||||||
"pin_symbol_size": 25.0,
|
|
||||||
"text_offset_ratio": 0.15
|
|
||||||
},
|
|
||||||
"legacy_lib_dir": "",
|
|
||||||
"legacy_lib_list": [],
|
|
||||||
"meta": {
|
|
||||||
"version": 1
|
|
||||||
},
|
|
||||||
"net_format_name": "",
|
|
||||||
"page_layout_descr_file": "",
|
|
||||||
"plot_directory": "",
|
|
||||||
"space_save_all_events": true,
|
|
||||||
"spice_current_sheet_as_root": false,
|
|
||||||
"spice_external_command": "spice \"%I\"",
|
|
||||||
"spice_model_current_sheet_as_root": true,
|
|
||||||
"spice_save_all_currents": false,
|
|
||||||
"spice_save_all_dissipations": false,
|
|
||||||
"spice_save_all_voltages": false,
|
|
||||||
"subpart_first_id": 65,
|
|
||||||
"subpart_id_separator": 0
|
|
||||||
},
|
|
||||||
"sheets": [
|
|
||||||
[
|
|
||||||
"46346c04-8bed-48b4-837b-9342dd403232",
|
|
||||||
"Root"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"text_variables": {}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
|||||||
(sym_lib_table
|
|
||||||
(version 7)
|
|
||||||
(lib (name "Modules")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board/modules/Modules.kicad_sym")(options "")(descr ""))
|
|
||||||
)
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
[build]
|
|
||||||
target = "riscv32imc-unknown-none-elf"
|
|
||||||
|
|
||||||
[target."riscv32imc-unknown-none-elf"]
|
|
||||||
rustflags = [
|
|
||||||
# "-C", "link-arg=-Tlink.x",
|
|
||||||
]
|
|
||||||
# runner = "riscv64-unknown-elf-gdb -q -x openocd.gdb"
|
|
||||||
# runner = "riscv-none-embed-gdb -q -x openocd.gdb"
|
|
||||||
# runner = "gdb -q -x openocd.gdb"
|
|
||||||
# runner = "wlink -v flash"
|
|
||||||
|
|
||||||
runner = "wlink -v flash --enable-sdi-print --watch-serial --erase"
|
|
||||||
# runner = "wlink -v flash"
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
target extended-remote :3333
|
|
||||||
set remotetimeout 2000
|
|
||||||
|
|
||||||
#symbol-file target/riscv32imc-unknown-none-elf/release/ch32v203-examples
|
|
||||||
file target/riscv32imc-unknown-none-elf/release/bms
|
|
||||||
|
|
||||||
monitor reset halt
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
target
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
[package]
|
|
||||||
name = "bms"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
ch32-hal = { git = "https://github.com/ch32-rs/ch32-hal", features = [
|
|
||||||
"ch32v203c8t6",
|
|
||||||
"memory-x",
|
|
||||||
"embassy",
|
|
||||||
"rt",
|
|
||||||
"time-driver-tim2",
|
|
||||||
], default-features = false }
|
|
||||||
|
|
||||||
embassy-executor = { version = "0.7.0", features = [
|
|
||||||
"arch-riscv32",
|
|
||||||
"executor-thread",
|
|
||||||
] }
|
|
||||||
|
|
||||||
embassy-time = { version = "0.4.0" }
|
|
||||||
embassy-usb = { version = "0.3.0" }
|
|
||||||
embassy-futures = { version = "0.1.0" }
|
|
||||||
|
|
||||||
# This is okay because we should automatically use whatever ch32-hal uses
|
|
||||||
qingke-rt = "*"
|
|
||||||
qingke = "*"
|
|
||||||
|
|
||||||
panic-halt = "1.0"
|
|
||||||
|
|
||||||
embedded-hal = "1.0.0"
|
|
||||||
heapless = "0.8.0"
|
|
||||||
micromath = { version = "2.1.0", features = ["num-traits"] }
|
|
||||||
embedded-can = "0.4.1"
|
|
||||||
|
|
||||||
[profile.dev]
|
|
||||||
#lto = true
|
|
||||||
opt-level = 1
|
|
||||||
|
|
||||||
[profile.release]
|
|
||||||
strip = false # symbols are not flashed to the microcontroller, so don't strip them.
|
|
||||||
#lto = true
|
|
||||||
debug = true
|
|
||||||
opt-level = "z" # Optimize for size.
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
|
|
||||||
# ch32v203-bms
|
|
||||||
|
|
||||||
A simple battery management controller software.
|
|
||||||
|
|
||||||
## CAN bus and hardware address
|
|
||||||
|
|
||||||
This firmware exposes a CAN interface on the CH32V203 and uses 4 hardware address pins to allow up to 16 sensors on the same bus.
|
|
||||||
|
|
||||||
- CAN pins (default mapping):
|
|
||||||
- CAN RX: PA11
|
|
||||||
- CAN TX: PA12
|
|
||||||
- Address select pins (with internal pull-ups):
|
|
||||||
- A0: PA0
|
|
||||||
- A1: PA1
|
|
||||||
- A2: PA2
|
|
||||||
- A3: PA3
|
|
||||||
|
|
||||||
Wire each address pin to GND to set its corresponding bit to 1. The 4-bit address range is 0..15. The node’s CAN Standard ID is `0x100 | addr`, i.e. 0x100..0x10F. The CAN acceptance filter is configured to only accept frames with the node’s own ID.
|
|
||||||
|
|
||||||
Adjust the pins above if your PCB routes CAN or address lines to different pads.
|
|
||||||
|
|
||||||
## 555 timer (software) emulation mode
|
|
||||||
|
|
||||||
To save the BOM cost of a classic NE555 in simple oscillator applications, this firmware implements a minimal 555-like Schmitt trigger using the MCU’s ADC and a GPIO, approximating the behavior when the capacitor is charged/discharged via Q through a resistor, and the combined Trigger/Threshold senses the capacitor node.
|
|
||||||
|
|
||||||
- Pins used:
|
|
||||||
- Q output: PB2
|
|
||||||
- Combined Trigger/Threshold (ADC input): PA0
|
|
||||||
- Wiring:
|
|
||||||
- PB2 (Q) -> series resistor R -> capacitor node
|
|
||||||
- Capacitor node -> capacitor to GND
|
|
||||||
- Capacitor node -> PA0 (ADC input)
|
|
||||||
- Behavior:
|
|
||||||
- When ADC(PA0) <= ~1/3 Vref, PB2 is driven High.
|
|
||||||
- When ADC(PA0) >= ~2/3 Vref, PB2 is driven Low.
|
|
||||||
- Hysteresis avoids chatter; the actual charge/discharge dynamics follow your chosen R and C.
|
|
||||||
- Notes:
|
|
||||||
- Use an appropriate resistor from PB2 to the capacitor to set oscillation frequency. Start with 10k..100k and adjust with C.
|
|
||||||
- Ensure PA0 is routed to the capacitor node and left high impedance (no strong pull-ups/downs) so the ADC can sense the analog voltage.
|
|
||||||
- PB2 drives the on-board LED (if present), so the LED might blink at the oscillation frequency.
|
|
||||||
|
|
||||||
This mode is implemented in `src/main.rs` using `hal::adc::Adc::convert(&mut pin, SampleTime::...)` to take periodic samples and a simple state machine to toggle the Q output based on ~1/3 and ~2/3 Vref thresholds.
|
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
``` sh
|
|
||||||
cargo build --release
|
|
||||||
```
|
|
||||||
|
|
||||||
## Flash
|
|
||||||
|
|
||||||
``` sh
|
|
||||||
wchisp config reset
|
|
||||||
wchip wchisp flash target/riscv32imc-unknown-none-elf/release/bms
|
|
||||||
```
|
|
||||||
|
|
||||||
## Debugging
|
|
||||||
|
|
||||||
For debugging purposes a container file is provided together with wrapper scripts to start the containerized `openocd` and `riscv-gdb` transparently. The wrapper scripts assume that `podman` is setup.
|
|
||||||
|
|
||||||
Starting Debug server
|
|
||||||
|
|
||||||
```
|
|
||||||
./bin/openocd
|
|
||||||
```
|
|
||||||
|
|
||||||
Connecting with gdb for interactive debugging
|
|
||||||
|
|
||||||
```
|
|
||||||
./bin/gdb -f target/riscv32imc-unknown-none-elf/release/bms
|
|
||||||
```
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
CONTAINER_NAME="localhost/wch-dev-tools:latest"
|
|
||||||
CONTAINER_TOOLS_BASEDIR="$(dirname "$(readlink -f "$0")")"
|
|
||||||
|
|
||||||
pushd "$CONTAINER_TOOLS_BASEDIR"
|
|
||||||
podman build -t "$CONTAINER_NAME" -f "../wch-tools.Containerfile" .
|
|
||||||
popd
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
CONTAINER_IMAGE="localhost/wch-dev-tools:latest"
|
|
||||||
CONTAINER_TOOLS_BASEDIR="$(dirname "$(readlink -f "$0")")"
|
|
||||||
|
|
||||||
function _fatal {
|
|
||||||
echo -e "\e[31mERROR\e[0m $(</dev/stdin)$*" 1>&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
declare -a PODMAN_ARGS=(
|
|
||||||
"--rm" "-i" "--log-driver=none"
|
|
||||||
"--network=host"
|
|
||||||
"--pid=host"
|
|
||||||
"-v" "$PWD:$PWD:rw"
|
|
||||||
"-w" "$PWD"
|
|
||||||
)
|
|
||||||
|
|
||||||
[[ -t 1 ]] && PODMAN_ARGS+=("-t")
|
|
||||||
|
|
||||||
if ! podman image exists "$CONTAINER_IMAGE"; then
|
|
||||||
#attempt to build container
|
|
||||||
"$CONTAINER_TOOLS_BASEDIR/build-wch-tools-container.sh" 1>&2 ||
|
|
||||||
_fatal "faild to build local image, cannot continue! … please ensure you have an internet connection"
|
|
||||||
fi
|
|
||||||
|
|
||||||
podman run "${PODMAN_ARGS[@]}" --entrypoint riscv-none-elf-gdb-py3 "$CONTAINER_IMAGE" "$@"
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
CONTAINER_IMAGE="localhost/wch-dev-tools:latest"
|
|
||||||
CONTAINER_TOOLS_BASEDIR="$(dirname "$(readlink -f "$0")")"
|
|
||||||
|
|
||||||
function _fatal {
|
|
||||||
echo -e "\e[31mERROR\e[0m $(</dev/stdin)$*" 1>&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
declare -a PODMAN_ARGS=(
|
|
||||||
"--rm" "-i" "--log-driver=none"
|
|
||||||
"--network=host"
|
|
||||||
"-v" "$PWD:$PWD:rw"
|
|
||||||
"-w" "$PWD"
|
|
||||||
)
|
|
||||||
|
|
||||||
for device in /dev/bus/usb/*/*; do
|
|
||||||
if udevadm info "$device" | grep -q "ID_VENDOR=wch.cn" && \
|
|
||||||
udevadm info "$device" | grep -q "ID_MODEL=WCH-Link"; then
|
|
||||||
DEBUGGER_DEV_PATH="$device"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ -z "${DEBUGGER_DEV_PATH:-}" ]]; then
|
|
||||||
echo "Could not find hardware debugger … Exiting!" 1>&2
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
# add jlink to podman device
|
|
||||||
PODMAN_ARGS+=("--device=$DEBUGGER_DEV_PATH")
|
|
||||||
fi
|
|
||||||
|
|
||||||
[[ -t 1 ]] && PODMAN_ARGS+=("-t")
|
|
||||||
|
|
||||||
if ! podman image exists "$CONTAINER_IMAGE"; then
|
|
||||||
#attempt to build container
|
|
||||||
"$CONTAINER_TOOLS_BASEDIR/build-wch-tools-container.sh" 1>&2 ||
|
|
||||||
_fatal "faild to build local image, cannot continue! … please ensure you have an internet connection"
|
|
||||||
fi
|
|
||||||
|
|
||||||
podman run "${PODMAN_ARGS[@]}" --entrypoint openocd "$CONTAINER_IMAGE" "$@"
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
fn main() {
|
|
||||||
// println!("cargo:rustc-link-arg-bins=--nmagic");
|
|
||||||
println!("cargo:rustc-link-arg-bins=-Tlink.x");
|
|
||||||
// println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
|
|
||||||
|
|
||||||
let out_dir = std::env::var("OUT_DIR").unwrap();
|
|
||||||
let out_dir = std::path::PathBuf::from(out_dir);
|
|
||||||
std::fs::write(out_dir.join("memory.x"), include_bytes!("memory.x")).unwrap();
|
|
||||||
println!("cargo:rustc-link-search={}", out_dir.display());
|
|
||||||
println!("cargo:rerun-if-changed=memory.x");
|
|
||||||
}
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
/* CH32V203c8t6 */
|
|
||||||
MEMORY
|
|
||||||
{
|
|
||||||
FLASH : ORIGIN = 0x00000000, LENGTH = 64K /* BANK_1 */
|
|
||||||
RAM : ORIGIN = 0x20000000, LENGTH = 20K
|
|
||||||
}
|
|
||||||
REGION_ALIAS("REGION_TEXT", FLASH);
|
|
||||||
REGION_ALIAS("REGION_RODATA", FLASH);
|
|
||||||
REGION_ALIAS("REGION_DATA", RAM);
|
|
||||||
REGION_ALIAS("REGION_BSS", RAM);
|
|
||||||
REGION_ALIAS("REGION_HEAP", RAM);
|
|
||||||
REGION_ALIAS("REGION_STACK", RAM);
|
|
||||||
|
|
||||||
/* fault handlers */
|
|
||||||
|
|
||||||
PROVIDE(InstructionMisaligned = ExceptionHandler);
|
|
||||||
PROVIDE(InstructionFault = ExceptionHandler);
|
|
||||||
PROVIDE(IllegalInstruction = ExceptionHandler);
|
|
||||||
PROVIDE(Breakpoint = ExceptionHandler);
|
|
||||||
PROVIDE(LoadMisaligned = ExceptionHandler);
|
|
||||||
PROVIDE(LoadFault = ExceptionHandler);
|
|
||||||
PROVIDE(StoreMisaligned = ExceptionHandler);
|
|
||||||
PROVIDE(StoreFault = ExceptionHandler);;
|
|
||||||
PROVIDE(UserEnvCall = ExceptionHandler);
|
|
||||||
PROVIDE(SupervisorEnvCall = ExceptionHandler);
|
|
||||||
PROVIDE(MachineEnvCall = ExceptionHandler);
|
|
||||||
PROVIDE(InstructionPageFault = ExceptionHandler);
|
|
||||||
PROVIDE(LoadPageFault = ExceptionHandler);
|
|
||||||
PROVIDE(StorePageFault = ExceptionHandler);
|
|
||||||
|
|
||||||
/* core interrupt handlers */
|
|
||||||
|
|
||||||
PROVIDE(NonMaskableInt = DefaultHandler);
|
|
||||||
PROVIDE(Software = DefaultHandler);
|
|
||||||
|
|
||||||
/* external interrupt handlers */
|
|
||||||
|
|
||||||
PROVIDE(WWDG = DefaultHandler);
|
|
||||||
PROVIDE(PVD = DefaultHandler);
|
|
||||||
PROVIDE(TAMPER = DefaultHandler);
|
|
||||||
PROVIDE(RTC = DefaultHandler);
|
|
||||||
PROVIDE(FLASH = DefaultHandler);
|
|
||||||
PROVIDE(RCC = DefaultHandler);
|
|
||||||
PROVIDE(EXTI0 = DefaultHandler);
|
|
||||||
PROVIDE(EXTI1 = DefaultHandler);
|
|
||||||
PROVIDE(EXTI2 = DefaultHandler);
|
|
||||||
PROVIDE(EXTI3 = DefaultHandler);
|
|
||||||
PROVIDE(EXTI4 = DefaultHandler);
|
|
||||||
PROVIDE(DMA1_CHANNEL1 = DefaultHandler);
|
|
||||||
PROVIDE(DMA1_CHANNEL2 = DefaultHandler);
|
|
||||||
PROVIDE(DMA1_CHANNEL3 = DefaultHandler);
|
|
||||||
PROVIDE(DMA1_CHANNEL4 = DefaultHandler);
|
|
||||||
PROVIDE(DMA1_CHANNEL5 = DefaultHandler);
|
|
||||||
PROVIDE(DMA1_CHANNEL6 = DefaultHandler);
|
|
||||||
PROVIDE(DMA1_CHANNEL7 = DefaultHandler);
|
|
||||||
PROVIDE(ADC = DefaultHandler);
|
|
||||||
PROVIDE(USB_HP_CAN1_TX = DefaultHandler);
|
|
||||||
/*PROVIDE(USB_LP_CAN1_RX0 = DefaultHandler);*/
|
|
||||||
PROVIDE(CAN1_RX1 = DefaultHandler);
|
|
||||||
PROVIDE(CAN1_SCE = DefaultHandler);
|
|
||||||
PROVIDE(EXTI9_5 = DefaultHandler);
|
|
||||||
PROVIDE(TIM1_BRK = DefaultHandler);
|
|
||||||
PROVIDE(TIM1_UP_ = DefaultHandler);
|
|
||||||
PROVIDE(TIM1_TRG_COM = DefaultHandler);
|
|
||||||
PROVIDE(TIM1_CC = DefaultHandler);
|
|
||||||
PROVIDE(TIM2 = DefaultHandler);
|
|
||||||
PROVIDE(TIM3 = DefaultHandler);
|
|
||||||
PROVIDE(TIM4 = DefaultHandler);
|
|
||||||
PROVIDE(I2C1_EV = DefaultHandler);
|
|
||||||
PROVIDE(I2C1_ER = DefaultHandler);
|
|
||||||
PROVIDE(I2C2_EV = DefaultHandler);
|
|
||||||
PROVIDE(I2C2_ER = DefaultHandler);
|
|
||||||
PROVIDE(SPI1 = DefaultHandler);
|
|
||||||
PROVIDE(SPI2 = DefaultHandler);
|
|
||||||
PROVIDE(USART1 = DefaultHandler);
|
|
||||||
PROVIDE(USART2 = DefaultHandler);
|
|
||||||
PROVIDE(USART3 = DefaultHandler);
|
|
||||||
PROVIDE(EXTI15_10 = DefaultHandler);
|
|
||||||
PROVIDE(RTCALARM = DefaultHandler);
|
|
||||||
PROVIDE(USBWAKE_UP = DefaultHandler);
|
|
||||||
PROVIDE(TIM8_BRK = DefaultHandler);
|
|
||||||
PROVIDE(TIM8_UP_ = DefaultHandler);
|
|
||||||
PROVIDE(TIM8_TRG_COM = DefaultHandler);
|
|
||||||
PROVIDE(TIM8_CC = DefaultHandler);
|
|
||||||
PROVIDE(RNG = DefaultHandler);
|
|
||||||
PROVIDE(FSMC = DefaultHandler);
|
|
||||||
PROVIDE(SDIO = DefaultHandler);
|
|
||||||
PROVIDE(TIM5 = DefaultHandler);
|
|
||||||
PROVIDE(SPI3 = DefaultHandler);
|
|
||||||
PROVIDE(UART4 = DefaultHandler);
|
|
||||||
PROVIDE(UART5 = DefaultHandler);
|
|
||||||
PROVIDE(TIM6 = DefaultHandler);
|
|
||||||
PROVIDE(TIM7 = DefaultHandler);
|
|
||||||
PROVIDE(DMA2_CHANNEL1 = DefaultHandler);
|
|
||||||
PROVIDE(DMA2_CHANNEL2 = DefaultHandler);
|
|
||||||
PROVIDE(DMA2_CHANNEL3 = DefaultHandler);
|
|
||||||
PROVIDE(DMA2_CHANNEL4 = DefaultHandler);
|
|
||||||
PROVIDE(DMA2_CHANNEL5 = DefaultHandler);
|
|
||||||
PROVIDE(ETH = DefaultHandler);
|
|
||||||
PROVIDE(ETH_WKUP = DefaultHandler);
|
|
||||||
PROVIDE(CAN2_TX = DefaultHandler);
|
|
||||||
PROVIDE(CAN2_RX0 = DefaultHandler);
|
|
||||||
PROVIDE(CAN2_RX1 = DefaultHandler);
|
|
||||||
PROVIDE(CAN2_SCE = DefaultHandler);
|
|
||||||
PROVIDE(OTG_FS = DefaultHandler);
|
|
||||||
PROVIDE(USBHSWAKEUP = DefaultHandler);
|
|
||||||
PROVIDE(USBHS = DefaultHandler);
|
|
||||||
PROVIDE(DVP = DefaultHandler);
|
|
||||||
PROVIDE(UART6 = DefaultHandler);
|
|
||||||
PROVIDE(UART7 = DefaultHandler);
|
|
||||||
PROVIDE(UART8 = DefaultHandler);
|
|
||||||
PROVIDE(TIM9_BRK = DefaultHandler);
|
|
||||||
PROVIDE(TIM9_UP_ = DefaultHandler);
|
|
||||||
PROVIDE(TIM9_TRG_COM = DefaultHandler);
|
|
||||||
PROVIDE(TIM9_CC = DefaultHandler);
|
|
||||||
PROVIDE(TIM10_BRK = DefaultHandler);
|
|
||||||
PROVIDE(TIM10_UP_ = DefaultHandler);
|
|
||||||
PROVIDE(TIM10_TRG_COM = DefaultHandler);
|
|
||||||
PROVIDE(TIM10_CC = DefaultHandler);
|
|
||||||
PROVIDE(DMA2_CHANNEL6 = DefaultHandler);
|
|
||||||
PROVIDE(DMA2_CHANNEL7 = DefaultHandler);
|
|
||||||
PROVIDE(DMA2_CHANNEL8 = DefaultHandler);
|
|
||||||
PROVIDE(DMA2_CHANNEL9 = DefaultHandler);
|
|
||||||
PROVIDE(DMA2_CHANNEL10 = DefaultHandler);
|
|
||||||
PROVIDE(DMA2_CHANNEL11 = DefaultHandler);
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
set _CHIPNAME ch32v203
|
|
||||||
set _TARGETNAME $_CHIPNAME.cpu
|
|
||||||
|
|
||||||
#bindto 0.0.0.0
|
|
||||||
|
|
||||||
adapter driver wlinke
|
|
||||||
adapter speed 6000
|
|
||||||
transport select sdi
|
|
||||||
|
|
||||||
sdi newtap $_CHIPNAME cpu -irlen 5 --expected-id 0x00001
|
|
||||||
target create $_TARGETNAME.0 wch_riscv -chain-position $_TARGETNAME
|
|
||||||
$_TARGETNAME.0 configure -work-area-phys 0x20000000 -work-area-size 10000 -work-area-backup 1
|
|
||||||
set _FLASHNAME $_CHIPNAME.flash
|
|
||||||
|
|
||||||
flash bank $_FLASHNAME wch_rsicv 0x00000000 0 0 0 $_TARGETNAME.0
|
|
||||||
|
|
||||||
init
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
[toolchain]
|
|
||||||
channel = "nightly"
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
#![no_std]
|
|
||||||
#![no_main]
|
|
||||||
#![feature(type_alias_impl_trait)]
|
|
||||||
#![feature(impl_trait_in_assoc_type)]
|
|
||||||
|
|
||||||
// Simple 555-like oscillator implemented in firmware.
|
|
||||||
// - Q output: PB2 (also drives the on-board LED if present)
|
|
||||||
// - Combined Trigger/Threshold analog input: PA0 (capacitor node)
|
|
||||||
// Wiring suggestion:
|
|
||||||
// Q (PB2) --[R]--+-- C -- GND
|
|
||||||
// |
|
|
||||||
// PA0 (ADC input)
|
|
||||||
// The firmware toggles Q high when PA0 <= 1/3 Vref and low when PA0 >= 2/3 Vref.
|
|
||||||
|
|
||||||
use embassy_executor::Spawner;
|
|
||||||
use embassy_time::Timer;
|
|
||||||
use hal::gpio::{Level, Output};
|
|
||||||
use {ch32_hal as hal, panic_halt as _};
|
|
||||||
|
|
||||||
use hal::adc::{Adc, SampleTime};
|
|
||||||
|
|
||||||
#[embassy_executor::main(entry = "qingke_rt::entry")]
|
|
||||||
async fn main(_spawner: Spawner) -> ! {
|
|
||||||
let p = hal::init(Default::default());
|
|
||||||
|
|
||||||
// Q output on PB2
|
|
||||||
let mut q = Output::new(p.PB2, Level::Low, Default::default());
|
|
||||||
|
|
||||||
// ADC on PA0 for combined Trigger/Threshold input
|
|
||||||
let mut adc = Adc::new(p.ADC1, Default::default());
|
|
||||||
let mut trig_thres = p.PA0; // analog-capable pin used as ADC channel
|
|
||||||
|
|
||||||
// ADC characteristics: assume 12-bit if HAL doesn't expose it.
|
|
||||||
// If the HAL provides a method to query resolution, prefer that.
|
|
||||||
let full_scale: u16 = 4095; // 12-bit default
|
|
||||||
let thr_low: u16 = (full_scale as u32 / 3) as u16; // ~1/3 Vref
|
|
||||||
let thr_high: u16 = ((full_scale as u32 * 2) / 3) as u16; // ~2/3 Vref
|
|
||||||
|
|
||||||
// Start with Q low. State variable to avoid redundant toggles.
|
|
||||||
let mut q_high = false;
|
|
||||||
q.set_low();
|
|
||||||
|
|
||||||
loop {
|
|
||||||
// Read capacitor node voltage via ADC
|
|
||||||
let sample: u16 = adc.convert(&mut trig_thres, SampleTime::CYCLES239_5);
|
|
||||||
|
|
||||||
// Implement Schmitt trigger behavior like NE555 using thresholds
|
|
||||||
if !q_high && sample <= thr_low {
|
|
||||||
// Trigger: voltage fell below 1/3 Vref -> set output high
|
|
||||||
q.set_high();
|
|
||||||
q_high = true;
|
|
||||||
} else if q_high && sample >= thr_high {
|
|
||||||
// Threshold: voltage rose above 2/3 Vref -> set output low
|
|
||||||
q.set_low();
|
|
||||||
q_high = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Small delay to reduce CPU usage; adjust for responsiveness/noise
|
|
||||||
Timer::after_micros(200).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
FROM debian:bookworm
|
|
||||||
|
|
||||||
RUN apt update -y && apt upgrade -y && apt install git libjaylink-dev libusb-1.0-0 unzip curl libhidapi-hidraw0 xz-utils -y
|
|
||||||
|
|
||||||
RUN cd /root && \
|
|
||||||
curl -L -o mrs-toolchain.tar.xz "https://github.com/ch32-riscv-ug/MounRiver_Studio_Community_miror/releases/download/1.92-toolchain/MRS_Toolchain_Linux_x64_V1.92.tar.xz" && \
|
|
||||||
mkdir mrs-toolchain && \
|
|
||||||
tar -xvf mrs-toolchain.tar.xz -C mrs-toolchain --strip-components=1 && \
|
|
||||||
mv mrs-toolchain/OpenOCD/bin/openocd /usr/local/bin && \
|
|
||||||
mv mrs-toolchain/OpenOCD/share/openocd /usr/local/share && \
|
|
||||||
# mv mrs-toolchain/RISC-V_Embedded_GCC12/bin/riscv-none-elf-gdb /usr/local/bin && \ # both toolchains in MRS are to old to work with emacs dape
|
|
||||||
# mv mrs-toolchain/RISC-V_Embedded_GCC12/libexec /usr/local && \ # both toolchains in MRS are to old to work with emacs dape
|
|
||||||
rm -rf mrs-toolchain mrs-toolchain.tar.xz && \
|
|
||||||
# Use up to date xpack toolchains for gdb
|
|
||||||
curl -L -o xpack-riscv-toolchain.tar.gz "https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases/download/v14.2.0-3/xpack-riscv-none-elf-gcc-14.2.0-3-linux-x64.tar.gz" && \
|
|
||||||
mkdir xpack-toolchain && \
|
|
||||||
tar -xvf xpack-riscv-toolchain.tar.gz -C xpack-toolchain --strip-components=1 && \
|
|
||||||
mv xpack-toolchain/bin/* /usr/local/bin && \
|
|
||||||
mv xpack-toolchain/lib/ /usr/local && \
|
|
||||||
mv xpack-toolchain/lib64/ /usr/local && \
|
|
||||||
mv xpack-toolchain/libexec /usr/local && \
|
|
||||||
mv xpack-toolchain/riscv-none-elf /usr/local && \
|
|
||||||
rm -rf xpack-toolchain xpack-riscv-toolchain.tar.gz
|
|
||||||
|
|
||||||
RUN mkdir -p /root/.config/gdb && echo "set auto-load safe-path /" >> /root/.config/gdb/gdbinit
|
|
||||||
|
|
||||||
ENTRYPOINT [ "/usr/bin/bash" ]
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
(fp_lib_table
|
|
||||||
(version 7)
|
|
||||||
(lib (name "Sensor")(type "KiCad")(uri "${KIPRJMOD}/Sensor.pretty")(options "")(descr ""))
|
|
||||||
)
|
|
||||||
Binary file not shown.
@@ -86,6 +86,7 @@ pca9535 = { version = "2.0.0", features = ["std"] }
|
|||||||
ina219 = { version = "0.2.0", features = ["std"] }
|
ina219 = { version = "0.2.0", features = ["std"] }
|
||||||
embedded-storage = "=0.3.1"
|
embedded-storage = "=0.3.1"
|
||||||
ekv = "1.0.0"
|
ekv = "1.0.0"
|
||||||
|
embedded-can = "0.4.1"
|
||||||
|
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ pub struct TankConfig {
|
|||||||
pub tank_warn_percent: u8,
|
pub tank_warn_percent: u8,
|
||||||
pub tank_empty_percent: u8,
|
pub tank_empty_percent: u8,
|
||||||
pub tank_full_percent: u8,
|
pub tank_full_percent: u8,
|
||||||
pub ml_per_pulse: f32,
|
pub ml_per_pulse: f32
|
||||||
}
|
}
|
||||||
impl Default for TankConfig {
|
impl Default for TankConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@@ -111,7 +111,6 @@ pub struct PlantControllerConfig {
|
|||||||
pub struct PlantConfig {
|
pub struct PlantConfig {
|
||||||
pub mode: PlantWateringMode,
|
pub mode: PlantWateringMode,
|
||||||
pub target_moisture: f32,
|
pub target_moisture: f32,
|
||||||
pub min_moisture: f32,
|
|
||||||
pub pump_time_s: u16,
|
pub pump_time_s: u16,
|
||||||
pub pump_limit_ml: u16,
|
pub pump_limit_ml: u16,
|
||||||
pub pump_cooldown_min: u16,
|
pub pump_cooldown_min: u16,
|
||||||
@@ -132,7 +131,6 @@ impl Default for PlantConfig {
|
|||||||
Self {
|
Self {
|
||||||
mode: PlantWateringMode::OFF,
|
mode: PlantWateringMode::OFF,
|
||||||
target_moisture: 40.,
|
target_moisture: 40.,
|
||||||
min_moisture: 30.,
|
|
||||||
pump_time_s: 30,
|
pump_time_s: 30,
|
||||||
pump_limit_ml: 5000,
|
pump_limit_ml: 5000,
|
||||||
pump_cooldown_min: 60,
|
pump_cooldown_min: 60,
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ pub(crate) fn create_initial_board(
|
|||||||
config: PlantControllerConfig,
|
config: PlantControllerConfig,
|
||||||
esp: Esp<'static>,
|
esp: Esp<'static>,
|
||||||
) -> Result<Box<dyn BoardInteraction<'static> + Send>> {
|
) -> Result<Box<dyn BoardInteraction<'static> + Send>> {
|
||||||
|
println!("Start initial");
|
||||||
let mut general_fault = PinDriver::input_output(free_pins.gpio6.downgrade())?;
|
let mut general_fault = PinDriver::input_output(free_pins.gpio6.downgrade())?;
|
||||||
general_fault.set_pull(Pull::Floating)?;
|
general_fault.set_pull(Pull::Floating)?;
|
||||||
general_fault.set_low()?;
|
general_fault.set_low()?;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ mod rtc;
|
|||||||
mod v3_hal;
|
mod v3_hal;
|
||||||
mod v4_hal;
|
mod v4_hal;
|
||||||
mod water;
|
mod water;
|
||||||
|
mod v4_sensor;
|
||||||
|
|
||||||
use crate::hal::rtc::{DS3231Module, RTCModuleInteraction};
|
use crate::hal::rtc::{DS3231Module, RTCModuleInteraction};
|
||||||
use crate::hal::water::TankSensor;
|
use crate::hal::water::TankSensor;
|
||||||
@@ -22,7 +23,6 @@ use bq34z100::Bq34z100g1Driver;
|
|||||||
use ds323x::{DateTimeAccess, Ds323x};
|
use ds323x::{DateTimeAccess, Ds323x};
|
||||||
use eeprom24x::{Eeprom24x, SlaveAddr, Storage};
|
use eeprom24x::{Eeprom24x, SlaveAddr, Storage};
|
||||||
use embedded_hal_bus::i2c::MutexDevice;
|
use embedded_hal_bus::i2c::MutexDevice;
|
||||||
use esp_idf_hal::pcnt::PCNT1;
|
|
||||||
use esp_idf_hal::{
|
use esp_idf_hal::{
|
||||||
adc::ADC1,
|
adc::ADC1,
|
||||||
delay::Delay,
|
delay::Delay,
|
||||||
@@ -48,10 +48,12 @@ use once_cell::sync::Lazy;
|
|||||||
use std::result::Result::Ok as OkStd;
|
use std::result::Result::Ok as OkStd;
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
use esp_idf_hal::can::CAN;
|
||||||
|
use esp_idf_hal::pcnt::PCNT1;
|
||||||
|
|
||||||
//Only support for 8 right now!
|
//Only support for 8 right now!
|
||||||
pub const PLANT_COUNT: usize = 8;
|
pub const PLANT_COUNT: usize = 8;
|
||||||
const REPEAT_MOIST_MEASURE: usize = 1;
|
|
||||||
|
|
||||||
const TANK_MULTI_SAMPLE: usize = 11;
|
const TANK_MULTI_SAMPLE: usize = 11;
|
||||||
|
|
||||||
@@ -157,6 +159,7 @@ pub struct FreePeripherals {
|
|||||||
pub pcnt0: PCNT0,
|
pub pcnt0: PCNT0,
|
||||||
pub pcnt1: PCNT1,
|
pub pcnt1: PCNT1,
|
||||||
pub adc1: ADC1,
|
pub adc1: ADC1,
|
||||||
|
pub can: CAN,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PlantHal {
|
impl PlantHal {
|
||||||
@@ -186,6 +189,7 @@ impl PlantHal {
|
|||||||
boot_button.set_pull(Pull::Floating)?;
|
boot_button.set_pull(Pull::Floating)?;
|
||||||
|
|
||||||
let free_pins = FreePeripherals {
|
let free_pins = FreePeripherals {
|
||||||
|
can: peripherals.can,
|
||||||
adc1: peripherals.adc1,
|
adc1: peripherals.adc1,
|
||||||
pcnt0: peripherals.pcnt0,
|
pcnt0: peripherals.pcnt0,
|
||||||
pcnt1: peripherals.pcnt1,
|
pcnt1: peripherals.pcnt1,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::hal::rtc::RTCModuleInteraction;
|
use crate::hal::rtc::RTCModuleInteraction;
|
||||||
use crate::hal::water::TankSensor;
|
use crate::hal::water::TankSensor;
|
||||||
use crate::hal::{
|
use crate::hal::{
|
||||||
deep_sleep, BoardInteraction, FreePeripherals, Sensor, PLANT_COUNT, REPEAT_MOIST_MEASURE,
|
deep_sleep, BoardInteraction, FreePeripherals, Sensor, PLANT_COUNT,
|
||||||
};
|
};
|
||||||
use crate::log::{log, LogMessage};
|
use crate::log::{log, LogMessage};
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -64,6 +64,9 @@ const FAULT_4: usize = 21;
|
|||||||
const FAULT_1: usize = 22;
|
const FAULT_1: usize = 22;
|
||||||
const FAULT_2: usize = 23;
|
const FAULT_2: usize = 23;
|
||||||
|
|
||||||
|
const REPEAT_MOIST_MEASURE: usize = 1;
|
||||||
|
|
||||||
|
|
||||||
pub struct V3<'a> {
|
pub struct V3<'a> {
|
||||||
config: PlantControllerConfig,
|
config: PlantControllerConfig,
|
||||||
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
||||||
@@ -91,6 +94,7 @@ pub(crate) fn create_v3(
|
|||||||
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
||||||
rtc_module: Box<dyn RTCModuleInteraction + Send>,
|
rtc_module: Box<dyn RTCModuleInteraction + Send>,
|
||||||
) -> Result<Box<dyn BoardInteraction<'static> + Send>> {
|
) -> Result<Box<dyn BoardInteraction<'static> + Send>> {
|
||||||
|
println!("Start v3");
|
||||||
let mut clock = PinDriver::input_output(peripherals.gpio15.downgrade())?;
|
let mut clock = PinDriver::input_output(peripherals.gpio15.downgrade())?;
|
||||||
clock.set_pull(Pull::Floating)?;
|
clock.set_pull(Pull::Floating)?;
|
||||||
let mut latch = PinDriver::input_output(peripherals.gpio3.downgrade())?;
|
let mut latch = PinDriver::input_output(peripherals.gpio3.downgrade())?;
|
||||||
@@ -132,7 +136,7 @@ pub(crate) fn create_v3(
|
|||||||
peripherals.gpio5,
|
peripherals.gpio5,
|
||||||
tank_power_pin,
|
tank_power_pin,
|
||||||
flow_sensor_pin,
|
flow_sensor_pin,
|
||||||
peripherals.pcnt1,
|
peripherals.pcnt1
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut signal_counter = PcntDriver::new(
|
let mut signal_counter = PcntDriver::new(
|
||||||
|
|||||||
@@ -2,18 +2,18 @@ use crate::config::PlantControllerConfig;
|
|||||||
use crate::hal::battery::BatteryInteraction;
|
use crate::hal::battery::BatteryInteraction;
|
||||||
use crate::hal::esp::Esp;
|
use crate::hal::esp::Esp;
|
||||||
use crate::hal::rtc::RTCModuleInteraction;
|
use crate::hal::rtc::RTCModuleInteraction;
|
||||||
|
use crate::hal::v4_sensor::SensorImpl;
|
||||||
|
use crate::hal::v4_sensor::SensorInteraction;
|
||||||
use crate::hal::water::TankSensor;
|
use crate::hal::water::TankSensor;
|
||||||
use crate::hal::{
|
use crate::hal::{
|
||||||
deep_sleep, BoardInteraction, FreePeripherals, Sensor, I2C_DRIVER, PLANT_COUNT,
|
deep_sleep, BoardInteraction, FreePeripherals, Sensor, I2C_DRIVER, PLANT_COUNT
|
||||||
REPEAT_MOIST_MEASURE,
|
|
||||||
};
|
};
|
||||||
use crate::log::{log, LogMessage};
|
use crate::log::{log, LogMessage};
|
||||||
use anyhow::bail;
|
use anyhow::bail;
|
||||||
use embedded_hal::digital::OutputPin;
|
use embedded_hal::digital::OutputPin;
|
||||||
use embedded_hal_bus::i2c::MutexDevice;
|
use embedded_hal_bus::i2c::MutexDevice;
|
||||||
use esp_idf_hal::delay::Delay;
|
|
||||||
use esp_idf_hal::gpio::{AnyInputPin, IOPin, InputOutput, Output, PinDriver, Pull};
|
use esp_idf_hal::gpio::{AnyInputPin, IOPin, InputOutput, Output, PinDriver, Pull};
|
||||||
use esp_idf_hal::i2c::I2cDriver;
|
use esp_idf_hal::i2c::{I2cDriver, I2cError};
|
||||||
use esp_idf_hal::pcnt::{
|
use esp_idf_hal::pcnt::{
|
||||||
PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex,
|
PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex,
|
||||||
};
|
};
|
||||||
@@ -23,15 +23,13 @@ use ina219::calibration::UnCalibrated;
|
|||||||
use ina219::configuration::{Configuration, OperatingMode};
|
use ina219::configuration::{Configuration, OperatingMode};
|
||||||
use ina219::SyncIna219;
|
use ina219::SyncIna219;
|
||||||
use measurements::{Current, Resistance, Voltage};
|
use measurements::{Current, Resistance, Voltage};
|
||||||
use pca9535::{GPIOBank, Pca9535Immediate, StandardExpanderInterface};
|
use pca9535::{ExpanderError, GPIOBank, Pca9535Immediate, StandardExpanderInterface};
|
||||||
use std::result::Result::Ok as OkStd;
|
use std::result::Result::Ok as OkStd;
|
||||||
|
use embedded_can::nb::Can;
|
||||||
const MS0: u8 = 1_u8;
|
use embedded_can::Frame;
|
||||||
const MS1: u8 = 0_u8;
|
use embedded_can::StandardId;
|
||||||
const MS2: u8 = 3_u8;
|
use esp_idf_hal::prelude::*;
|
||||||
const MS3: u8 = 4_u8;
|
use esp_idf_hal::can;
|
||||||
const MS4: u8 = 2_u8;
|
|
||||||
const SENSOR_ON: u8 = 5_u8;
|
|
||||||
|
|
||||||
pub enum Charger<'a> {
|
pub enum Charger<'a> {
|
||||||
SolarMpptV1 {
|
SolarMpptV1 {
|
||||||
@@ -119,13 +117,13 @@ pub struct V4<'a> {
|
|||||||
rtc_module: Box<dyn RTCModuleInteraction + Send>,
|
rtc_module: Box<dyn RTCModuleInteraction + Send>,
|
||||||
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
||||||
config: PlantControllerConfig,
|
config: PlantControllerConfig,
|
||||||
signal_counter: PcntDriver<'a>,
|
|
||||||
awake: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, Output>,
|
awake: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, Output>,
|
||||||
light: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
light: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
general_fault: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
general_fault: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
pump_expander: Pca9535Immediate<MutexDevice<'a, I2cDriver<'a>>>,
|
pump_expander: Pca9535Immediate<MutexDevice<'a, I2cDriver<'a>>>,
|
||||||
pump_ina: Option<SyncIna219<MutexDevice<'a, I2cDriver<'a>>, UnCalibrated>>,
|
pump_ina: Option<SyncIna219<MutexDevice<'a, I2cDriver<'a>>, UnCalibrated>>,
|
||||||
sensor_expander: Pca9535Immediate<MutexDevice<'a, I2cDriver<'a>>>,
|
sensor: SensorImpl<'a>,
|
||||||
extra1: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, Output>,
|
extra1: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, Output>,
|
||||||
extra2: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, Output>,
|
extra2: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, Output>,
|
||||||
}
|
}
|
||||||
@@ -137,6 +135,7 @@ pub(crate) fn create_v4(
|
|||||||
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
||||||
rtc_module: Box<dyn RTCModuleInteraction + Send>,
|
rtc_module: Box<dyn RTCModuleInteraction + Send>,
|
||||||
) -> anyhow::Result<Box<dyn BoardInteraction<'static> + Send + 'static>> {
|
) -> anyhow::Result<Box<dyn BoardInteraction<'static> + Send + 'static>> {
|
||||||
|
println!("Start v4");
|
||||||
let mut awake = PinDriver::output(peripherals.gpio21.downgrade())?;
|
let mut awake = PinDriver::output(peripherals.gpio21.downgrade())?;
|
||||||
awake.set_high()?;
|
awake.set_high()?;
|
||||||
|
|
||||||
@@ -160,30 +159,71 @@ pub(crate) fn create_v4(
|
|||||||
peripherals.gpio5,
|
peripherals.gpio5,
|
||||||
tank_power_pin,
|
tank_power_pin,
|
||||||
flow_sensor_pin,
|
flow_sensor_pin,
|
||||||
peripherals.pcnt1,
|
peripherals.pcnt1
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let mut signal_counter = PcntDriver::new(
|
let mut sensor_expander = Pca9535Immediate::new(MutexDevice::new(&I2C_DRIVER), 34);
|
||||||
peripherals.pcnt0,
|
let sensor = match sensor_expander.pin_into_output(GPIOBank::Bank0, 0) {
|
||||||
Some(peripherals.gpio22),
|
Ok(_) => {
|
||||||
Option::<AnyInputPin>::None,
|
println!("SensorExpander answered");
|
||||||
Option::<AnyInputPin>::None,
|
//pulse counter version
|
||||||
Option::<AnyInputPin>::None,
|
let mut signal_counter = PcntDriver::new(
|
||||||
)?;
|
peripherals.pcnt0,
|
||||||
|
Some(peripherals.gpio22),
|
||||||
|
Option::<AnyInputPin>::None,
|
||||||
|
Option::<AnyInputPin>::None,
|
||||||
|
Option::<AnyInputPin>::None,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
signal_counter.channel_config(
|
||||||
|
PcntChannel::Channel0,
|
||||||
|
PinIndex::Pin0,
|
||||||
|
PinIndex::Pin1,
|
||||||
|
&PcntChannelConfig {
|
||||||
|
lctrl_mode: PcntControlMode::Keep,
|
||||||
|
hctrl_mode: PcntControlMode::Keep,
|
||||||
|
pos_mode: PcntCountMode::Increment,
|
||||||
|
neg_mode: PcntCountMode::Hold,
|
||||||
|
counter_h_lim: i16::MAX,
|
||||||
|
counter_l_lim: 0,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
for pin in 0..8 {
|
||||||
|
let _ = sensor_expander.pin_into_output(GPIOBank::Bank0, pin);
|
||||||
|
let _ = sensor_expander.pin_into_output(GPIOBank::Bank1, pin);
|
||||||
|
let _ = sensor_expander.pin_set_low(GPIOBank::Bank0, pin);
|
||||||
|
let _ = sensor_expander.pin_set_low(GPIOBank::Bank1, pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
SensorImpl::PulseCounter {
|
||||||
|
signal_counter,
|
||||||
|
sensor_expander,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
println!("Can bus mode ");
|
||||||
|
let timing = can::config::Timing::B25K;
|
||||||
|
let config = can::config::Config::new().timing(timing);
|
||||||
|
let mut can = can::CanDriver::new(peripherals.can, peripherals.gpio0, peripherals.gpio2, &config).unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
let frame = StandardId::new(0x042).unwrap();
|
||||||
|
let tx_frame = Frame::new(frame, &[0, 1, 2, 3, 4, 5, 6, 7]).unwrap();
|
||||||
|
can.transmit(&tx_frame, 1000).unwrap();
|
||||||
|
|
||||||
|
if let Ok(rx_frame) = can.receive(1000) {
|
||||||
|
println!("rx {:}:", rx_frame);
|
||||||
|
}
|
||||||
|
//can bus version
|
||||||
|
SensorImpl::CanBus {
|
||||||
|
can
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
signal_counter.channel_config(
|
|
||||||
PcntChannel::Channel0,
|
|
||||||
PinIndex::Pin0,
|
|
||||||
PinIndex::Pin1,
|
|
||||||
&PcntChannelConfig {
|
|
||||||
lctrl_mode: PcntControlMode::Keep,
|
|
||||||
hctrl_mode: PcntControlMode::Keep,
|
|
||||||
pos_mode: PcntCountMode::Increment,
|
|
||||||
neg_mode: PcntCountMode::Hold,
|
|
||||||
counter_h_lim: i16::MAX,
|
|
||||||
counter_l_lim: 0,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let mut solar_is_day = PinDriver::input(peripherals.gpio7.downgrade())?;
|
let mut solar_is_day = PinDriver::input(peripherals.gpio7.downgrade())?;
|
||||||
solar_is_day.set_pull(Pull::Floating)?;
|
solar_is_day.set_pull(Pull::Floating)?;
|
||||||
@@ -203,13 +243,7 @@ pub(crate) fn create_v4(
|
|||||||
let _ = pump_expander.pin_set_low(GPIOBank::Bank1, pin);
|
let _ = pump_expander.pin_set_low(GPIOBank::Bank1, pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut sensor_expander = Pca9535Immediate::new(MutexDevice::new(&I2C_DRIVER), 34);
|
|
||||||
for pin in 0..8 {
|
|
||||||
let _ = sensor_expander.pin_into_output(GPIOBank::Bank0, pin);
|
|
||||||
let _ = sensor_expander.pin_into_output(GPIOBank::Bank1, pin);
|
|
||||||
let _ = sensor_expander.pin_set_low(GPIOBank::Bank0, pin);
|
|
||||||
let _ = sensor_expander.pin_set_low(GPIOBank::Bank1, pin);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mppt_ina = SyncIna219::new(
|
let mppt_ina = SyncIna219::new(
|
||||||
MutexDevice::new(&I2C_DRIVER),
|
MutexDevice::new(&I2C_DRIVER),
|
||||||
@@ -252,17 +286,16 @@ pub(crate) fn create_v4(
|
|||||||
esp,
|
esp,
|
||||||
awake,
|
awake,
|
||||||
tank_sensor,
|
tank_sensor,
|
||||||
signal_counter,
|
|
||||||
light,
|
light,
|
||||||
general_fault,
|
general_fault,
|
||||||
pump_ina,
|
pump_ina,
|
||||||
pump_expander,
|
pump_expander,
|
||||||
sensor_expander,
|
|
||||||
config,
|
config,
|
||||||
battery_monitor,
|
battery_monitor,
|
||||||
charger,
|
charger,
|
||||||
extra1,
|
extra1,
|
||||||
extra2,
|
extra2,
|
||||||
|
sensor,
|
||||||
};
|
};
|
||||||
Ok(Box::new(v))
|
Ok(Box::new(v))
|
||||||
}
|
}
|
||||||
@@ -350,78 +383,7 @@ impl<'a> BoardInteraction<'a> for V4<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> anyhow::Result<f32> {
|
fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> anyhow::Result<f32> {
|
||||||
let mut results = [0_f32; REPEAT_MOIST_MEASURE];
|
self.sensor.measure_moisture_hz(plant, sensor)
|
||||||
for repeat in 0..REPEAT_MOIST_MEASURE {
|
|
||||||
self.signal_counter.counter_pause()?;
|
|
||||||
self.signal_counter.counter_clear()?;
|
|
||||||
|
|
||||||
//Disable all
|
|
||||||
self.sensor_expander.pin_set_high(GPIOBank::Bank0, MS4)?;
|
|
||||||
|
|
||||||
let sensor_channel = match sensor {
|
|
||||||
Sensor::A => plant as u32,
|
|
||||||
Sensor::B => (15 - plant) as u32,
|
|
||||||
};
|
|
||||||
|
|
||||||
let is_bit_set = |b: u8| -> bool { sensor_channel & (1 << b) != 0 };
|
|
||||||
if is_bit_set(0) {
|
|
||||||
self.sensor_expander.pin_set_high(GPIOBank::Bank0, MS0)?;
|
|
||||||
} else {
|
|
||||||
self.sensor_expander.pin_set_low(GPIOBank::Bank0, MS0)?;
|
|
||||||
}
|
|
||||||
if is_bit_set(1) {
|
|
||||||
self.sensor_expander.pin_set_high(GPIOBank::Bank0, MS1)?;
|
|
||||||
} else {
|
|
||||||
self.sensor_expander.pin_set_low(GPIOBank::Bank0, MS1)?;
|
|
||||||
}
|
|
||||||
if is_bit_set(2) {
|
|
||||||
self.sensor_expander.pin_set_high(GPIOBank::Bank0, MS2)?;
|
|
||||||
} else {
|
|
||||||
self.sensor_expander.pin_set_low(GPIOBank::Bank0, MS2)?;
|
|
||||||
}
|
|
||||||
if is_bit_set(3) {
|
|
||||||
self.sensor_expander.pin_set_high(GPIOBank::Bank0, MS3)?;
|
|
||||||
} else {
|
|
||||||
self.sensor_expander.pin_set_low(GPIOBank::Bank0, MS3)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.sensor_expander.pin_set_low(GPIOBank::Bank0, MS4)?;
|
|
||||||
self.sensor_expander
|
|
||||||
.pin_set_high(GPIOBank::Bank0, SENSOR_ON)?;
|
|
||||||
|
|
||||||
let delay = Delay::new_default();
|
|
||||||
let measurement = 100; // TODO what is this scaling factor? what is its purpose?
|
|
||||||
let factor = 1000f32 / measurement as f32;
|
|
||||||
|
|
||||||
//give some time to stabilize
|
|
||||||
delay.delay_ms(10);
|
|
||||||
self.signal_counter.counter_resume()?;
|
|
||||||
delay.delay_ms(measurement);
|
|
||||||
self.signal_counter.counter_pause()?;
|
|
||||||
self.sensor_expander.pin_set_high(GPIOBank::Bank0, MS4)?;
|
|
||||||
self.sensor_expander
|
|
||||||
.pin_set_low(GPIOBank::Bank0, SENSOR_ON)?;
|
|
||||||
self.sensor_expander.pin_set_low(GPIOBank::Bank0, MS0)?;
|
|
||||||
self.sensor_expander.pin_set_low(GPIOBank::Bank0, MS1)?;
|
|
||||||
self.sensor_expander.pin_set_low(GPIOBank::Bank0, MS2)?;
|
|
||||||
self.sensor_expander.pin_set_low(GPIOBank::Bank0, MS3)?;
|
|
||||||
delay.delay_ms(10);
|
|
||||||
let unscaled = self.signal_counter.get_counter_value()? as i32;
|
|
||||||
let hz = unscaled as f32 * factor;
|
|
||||||
log(
|
|
||||||
LogMessage::RawMeasure,
|
|
||||||
unscaled as u32,
|
|
||||||
hz as u32,
|
|
||||||
&plant.to_string(),
|
|
||||||
&format!("{sensor:?}"),
|
|
||||||
);
|
|
||||||
results[repeat] = hz;
|
|
||||||
}
|
|
||||||
results.sort_by(|a, b| a.partial_cmp(b).unwrap()); // floats don't seem to implement total_ord
|
|
||||||
|
|
||||||
let mid = results.len() / 2;
|
|
||||||
let median = results[mid];
|
|
||||||
anyhow::Ok(median)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn general_fault(&mut self, enable: bool) {
|
fn general_fault(&mut self, enable: bool) {
|
||||||
|
|||||||
115
rust/src/hal/v4_sensor.rs
Normal file
115
rust/src/hal/v4_sensor.rs
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
use embedded_hal_bus::i2c::MutexDevice;
|
||||||
|
use esp_idf_hal::can::CanDriver;
|
||||||
|
use esp_idf_hal::delay::Delay;
|
||||||
|
use esp_idf_hal::i2c::I2cDriver;
|
||||||
|
use esp_idf_hal::pcnt::PcntDriver;
|
||||||
|
use pca9535::{GPIOBank, Pca9535Immediate, StandardExpanderInterface};
|
||||||
|
use crate::hal::Sensor;
|
||||||
|
use crate::log::{log, LogMessage};
|
||||||
|
|
||||||
|
const REPEAT_MOIST_MEASURE: usize = 10;
|
||||||
|
|
||||||
|
pub trait SensorInteraction {
|
||||||
|
fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> anyhow::Result<f32>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MS0: u8 = 1_u8;
|
||||||
|
const MS1: u8 = 0_u8;
|
||||||
|
const MS2: u8 = 3_u8;
|
||||||
|
const MS3: u8 = 4_u8;
|
||||||
|
const MS4: u8 = 2_u8;
|
||||||
|
const SENSOR_ON: u8 = 5_u8;
|
||||||
|
|
||||||
|
pub enum SensorImpl<'a> {
|
||||||
|
PulseCounter{
|
||||||
|
signal_counter: PcntDriver<'a>,
|
||||||
|
sensor_expander: Pca9535Immediate<MutexDevice<'a, I2cDriver<'a>>>,
|
||||||
|
},
|
||||||
|
CanBus{
|
||||||
|
can: CanDriver<'a>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SensorInteraction for SensorImpl<'_> {
|
||||||
|
fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> anyhow::Result<f32> {
|
||||||
|
match self {
|
||||||
|
SensorImpl::PulseCounter { signal_counter, sensor_expander, .. } => {
|
||||||
|
let mut results = [0_f32; REPEAT_MOIST_MEASURE];
|
||||||
|
for repeat in 0..REPEAT_MOIST_MEASURE {
|
||||||
|
signal_counter.counter_pause()?;
|
||||||
|
signal_counter.counter_clear()?;
|
||||||
|
|
||||||
|
//Disable all
|
||||||
|
sensor_expander.pin_set_high(GPIOBank::Bank0, MS4)?;
|
||||||
|
|
||||||
|
let sensor_channel = match sensor {
|
||||||
|
Sensor::A => plant as u32,
|
||||||
|
Sensor::B => (15 - plant) as u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
let is_bit_set = |b: u8| -> bool { sensor_channel & (1 << b) != 0 };
|
||||||
|
if is_bit_set(0) {
|
||||||
|
sensor_expander.pin_set_high(GPIOBank::Bank0, MS0)?;
|
||||||
|
} else {
|
||||||
|
sensor_expander.pin_set_low(GPIOBank::Bank0, MS0)?;
|
||||||
|
}
|
||||||
|
if is_bit_set(1) {
|
||||||
|
sensor_expander.pin_set_high(GPIOBank::Bank0, MS1)?;
|
||||||
|
} else {
|
||||||
|
sensor_expander.pin_set_low(GPIOBank::Bank0, MS1)?;
|
||||||
|
}
|
||||||
|
if is_bit_set(2) {
|
||||||
|
sensor_expander.pin_set_high(GPIOBank::Bank0, MS2)?;
|
||||||
|
} else {
|
||||||
|
sensor_expander.pin_set_low(GPIOBank::Bank0, MS2)?;
|
||||||
|
}
|
||||||
|
if is_bit_set(3) {
|
||||||
|
sensor_expander.pin_set_high(GPIOBank::Bank0, MS3)?;
|
||||||
|
} else {
|
||||||
|
sensor_expander.pin_set_low(GPIOBank::Bank0, MS3)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
sensor_expander.pin_set_low(GPIOBank::Bank0, MS4)?;
|
||||||
|
sensor_expander
|
||||||
|
.pin_set_high(GPIOBank::Bank0, SENSOR_ON)?;
|
||||||
|
|
||||||
|
let delay = Delay::new_default();
|
||||||
|
let measurement = 100; // TODO what is this scaling factor? what is its purpose?
|
||||||
|
let factor = 1000f32 / measurement as f32;
|
||||||
|
|
||||||
|
//give some time to stabilize
|
||||||
|
delay.delay_ms(10);
|
||||||
|
signal_counter.counter_resume()?;
|
||||||
|
delay.delay_ms(measurement);
|
||||||
|
signal_counter.counter_pause()?;
|
||||||
|
sensor_expander.pin_set_high(GPIOBank::Bank0, MS4)?;
|
||||||
|
sensor_expander
|
||||||
|
.pin_set_low(GPIOBank::Bank0, SENSOR_ON)?;
|
||||||
|
sensor_expander.pin_set_low(GPIOBank::Bank0, MS0)?;
|
||||||
|
sensor_expander.pin_set_low(GPIOBank::Bank0, MS1)?;
|
||||||
|
sensor_expander.pin_set_low(GPIOBank::Bank0, MS2)?;
|
||||||
|
sensor_expander.pin_set_low(GPIOBank::Bank0, MS3)?;
|
||||||
|
delay.delay_ms(10);
|
||||||
|
let unscaled = signal_counter.get_counter_value()? as i32;
|
||||||
|
let hz = unscaled as f32 * factor;
|
||||||
|
log(
|
||||||
|
LogMessage::RawMeasure,
|
||||||
|
unscaled as u32,
|
||||||
|
hz as u32,
|
||||||
|
&plant.to_string(),
|
||||||
|
&format!("{sensor:?}"),
|
||||||
|
);
|
||||||
|
results[repeat] = hz;
|
||||||
|
}
|
||||||
|
results.sort_by(|a, b| a.partial_cmp(b).unwrap()); // floats don't seem to implement total_ord
|
||||||
|
|
||||||
|
let mid = results.len() / 2;
|
||||||
|
let median = results[mid];
|
||||||
|
anyhow::Ok(median)
|
||||||
|
}
|
||||||
|
SensorImpl::CanBus { .. } => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,9 +6,7 @@ use esp_idf_hal::adc::oneshot::{AdcChannelDriver, AdcDriver};
|
|||||||
use esp_idf_hal::adc::{attenuation, Resolution, ADC1};
|
use esp_idf_hal::adc::{attenuation, Resolution, ADC1};
|
||||||
use esp_idf_hal::delay::Delay;
|
use esp_idf_hal::delay::Delay;
|
||||||
use esp_idf_hal::gpio::{AnyIOPin, AnyInputPin, Gpio5, InputOutput, PinDriver, Pull};
|
use esp_idf_hal::gpio::{AnyIOPin, AnyInputPin, Gpio5, InputOutput, PinDriver, Pull};
|
||||||
use esp_idf_hal::pcnt::{
|
use esp_idf_hal::pcnt::{PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex, PCNT1};
|
||||||
PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex, PCNT1,
|
|
||||||
};
|
|
||||||
use esp_idf_sys::EspError;
|
use esp_idf_sys::EspError;
|
||||||
use one_wire_bus::OneWire;
|
use one_wire_bus::OneWire;
|
||||||
|
|
||||||
@@ -27,7 +25,7 @@ impl<'a> TankSensor<'a> {
|
|||||||
gpio5: Gpio5,
|
gpio5: Gpio5,
|
||||||
tank_power_pin: AnyIOPin,
|
tank_power_pin: AnyIOPin,
|
||||||
flow_sensor_pin: AnyIOPin,
|
flow_sensor_pin: AnyIOPin,
|
||||||
pcnt1: PCNT1,
|
pcnt1: PCNT1
|
||||||
) -> anyhow::Result<TankSensor<'a>> {
|
) -> anyhow::Result<TankSensor<'a>> {
|
||||||
let mut one_wire_pin =
|
let mut one_wire_pin =
|
||||||
PinDriver::input_output_od(one_wire_pin).expect("Failed to configure pin");
|
PinDriver::input_output_od(one_wire_pin).expect("Failed to configure pin");
|
||||||
@@ -75,6 +73,7 @@ impl<'a> TankSensor<'a> {
|
|||||||
},
|
},
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
||||||
Ok(TankSensor {
|
Ok(TankSensor {
|
||||||
one_wire_bus,
|
one_wire_bus,
|
||||||
tank_channel,
|
tank_channel,
|
||||||
|
|||||||
@@ -591,31 +591,16 @@ pub fn do_secure_pump(
|
|||||||
let mut first_error = true;
|
let mut first_error = true;
|
||||||
let mut pump_time_s = 0;
|
let mut pump_time_s = 0;
|
||||||
if !dry_run {
|
if !dry_run {
|
||||||
board
|
board.board_hal.get_tank_sensor().unwrap().reset_flow_meter();
|
||||||
.board_hal
|
board.board_hal.get_tank_sensor().unwrap().start_flow_meter();
|
||||||
.get_tank_sensor()
|
|
||||||
.unwrap()
|
|
||||||
.reset_flow_meter();
|
|
||||||
board
|
|
||||||
.board_hal
|
|
||||||
.get_tank_sensor()
|
|
||||||
.unwrap()
|
|
||||||
.start_flow_meter();
|
|
||||||
board.board_hal.pump(plant_id, true)?;
|
board.board_hal.pump(plant_id, true)?;
|
||||||
Delay::new_default().delay_ms(10);
|
Delay::new_default().delay_ms(10);
|
||||||
for step in 0..plant_config.pump_time_s as usize {
|
for step in 0..plant_config.pump_time_s as usize {
|
||||||
let flow_value = board
|
let flow_value = board.board_hal.get_tank_sensor().unwrap().get_flow_meter_value();
|
||||||
.board_hal
|
|
||||||
.get_tank_sensor()
|
|
||||||
.unwrap()
|
|
||||||
.get_flow_meter_value();
|
|
||||||
flow_collector[step] = flow_value;
|
flow_collector[step] = flow_value;
|
||||||
let flow_value_ml = flow_value as f32 * board.board_hal.get_config().tank.ml_per_pulse;
|
let flow_value_ml = flow_value as f32 * board.board_hal.get_config().tank.ml_per_pulse;
|
||||||
|
|
||||||
println!(
|
println!("Flow value is {} ml, limit is {} ml raw sensor {}", flow_value_ml, plant_config.pump_limit_ml, flow_value);
|
||||||
"Flow value is {} ml, limit is {} ml raw sensor {}",
|
|
||||||
flow_value_ml, plant_config.pump_limit_ml, flow_value
|
|
||||||
);
|
|
||||||
if flow_value_ml > plant_config.pump_limit_ml as f32 {
|
if flow_value_ml > plant_config.pump_limit_ml as f32 {
|
||||||
println!("Flow value is reached, stopping");
|
println!("Flow value is reached, stopping");
|
||||||
break;
|
break;
|
||||||
@@ -687,16 +672,9 @@ pub fn do_secure_pump(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
board.board_hal.get_tank_sensor().unwrap().stop_flow_meter();
|
board.board_hal.get_tank_sensor().unwrap().stop_flow_meter();
|
||||||
let final_flow_value = board
|
let final_flow_value = board.board_hal.get_tank_sensor().unwrap().get_flow_meter_value();
|
||||||
.board_hal
|
|
||||||
.get_tank_sensor()
|
|
||||||
.unwrap()
|
|
||||||
.get_flow_meter_value();
|
|
||||||
let flow_value_ml = final_flow_value as f32 * board.board_hal.get_config().tank.ml_per_pulse;
|
let flow_value_ml = final_flow_value as f32 * board.board_hal.get_config().tank.ml_per_pulse;
|
||||||
println!(
|
println!("Final flow value is {} with {} ml", final_flow_value, flow_value_ml);
|
||||||
"Final flow value is {} with {} ml",
|
|
||||||
final_flow_value, flow_value_ml
|
|
||||||
);
|
|
||||||
current_collector.sort();
|
current_collector.sort();
|
||||||
Ok(PumpResult {
|
Ok(PumpResult {
|
||||||
median_current_ma: current_collector[current_collector.len() / 2],
|
median_current_ma: current_collector[current_collector.len() / 2],
|
||||||
|
|||||||
@@ -78,7 +78,6 @@ impl PumpState {
|
|||||||
pub enum PlantWateringMode {
|
pub enum PlantWateringMode {
|
||||||
OFF,
|
OFF,
|
||||||
TargetMoisture,
|
TargetMoisture,
|
||||||
MinMoisture,
|
|
||||||
TimerOnly,
|
TimerOnly,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,30 +235,6 @@ impl PlantState {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PlantWateringMode::MinMoisture => {
|
|
||||||
let (moisture_percent, _) = self.plant_moisture();
|
|
||||||
if let Some(moisture_percent) = moisture_percent {
|
|
||||||
if self.pump_in_timeout(plant_conf, current_time) {
|
|
||||||
false
|
|
||||||
} else if !in_time_range(
|
|
||||||
current_time,
|
|
||||||
plant_conf.pump_hour_start,
|
|
||||||
plant_conf.pump_hour_end,
|
|
||||||
) {
|
|
||||||
false
|
|
||||||
} else if (true) {
|
|
||||||
//if not cooldown min and below max
|
|
||||||
true
|
|
||||||
} else if (true) {
|
|
||||||
//if below min disable cooldown min
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PlantWateringMode::TimerOnly => !self.pump_in_timeout(plant_conf, current_time),
|
PlantWateringMode::TimerOnly => !self.pump_in_timeout(plant_conf, current_time),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,9 +268,7 @@ impl PlantState {
|
|||||||
.map(|t| t.with_timezone(¤t_time.timezone())),
|
.map(|t| t.with_timezone(¤t_time.timezone())),
|
||||||
next_pump: if matches!(
|
next_pump: if matches!(
|
||||||
plant_conf.mode,
|
plant_conf.mode,
|
||||||
PlantWateringMode::TimerOnly
|
PlantWateringMode::TimerOnly | PlantWateringMode::TargetMoisture
|
||||||
| PlantWateringMode::TargetMoisture
|
|
||||||
| PlantWateringMode::MinMoisture
|
|
||||||
) {
|
) {
|
||||||
self.pump.previous_pump.and_then(|last_pump| {
|
self.pump.previous_pump.and_then(|last_pump| {
|
||||||
last_pump
|
last_pump
|
||||||
|
|||||||
@@ -105,7 +105,6 @@ export interface PlantControllerConfig {
|
|||||||
export interface PlantConfig {
|
export interface PlantConfig {
|
||||||
mode: string,
|
mode: string,
|
||||||
target_moisture: number,
|
target_moisture: number,
|
||||||
min_moisture: number,
|
|
||||||
pump_time_s: number,
|
pump_time_s: number,
|
||||||
pump_cooldown_min: number,
|
pump_cooldown_min: number,
|
||||||
pump_hour_start: number,
|
pump_hour_start: number,
|
||||||
|
|||||||
@@ -55,7 +55,6 @@
|
|||||||
<select class="plantvalue" id="plant_${plantId}_mode">
|
<select class="plantvalue" id="plant_${plantId}_mode">
|
||||||
<option value="OFF">Off</option>
|
<option value="OFF">Off</option>
|
||||||
<option value="TargetMoisture">Target</option>
|
<option value="TargetMoisture">Target</option>
|
||||||
<option value="MinMoisture">Min Moisture</option>
|
|
||||||
<option value="TimerOnly">Timer</option>
|
<option value="TimerOnly">Timer</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
@@ -64,10 +63,6 @@
|
|||||||
<div class="plantkey">Target Moisture:</div>
|
<div class="plantkey">Target Moisture:</div>
|
||||||
<input class="plantvalue" id="plant_${plantId}_target_moisture" type="number" min="0" max="100" placeholder="0">
|
<input class="plantvalue" id="plant_${plantId}_target_moisture" type="number" min="0" max="100" placeholder="0">
|
||||||
</div>
|
</div>
|
||||||
<div class="flexcontainer plantMinEnabledOnly_${plantId}">
|
|
||||||
<div class="plantkey">Minimum Moisture:</div>
|
|
||||||
<input class="plantvalue" id="plant_${plantId}_min_moisture" type="number" min="0" max="100" placeholder="0">
|
|
||||||
</div>
|
|
||||||
<div class="flexcontainer plantPumpEnabledOnly_${plantId}">
|
<div class="flexcontainer plantPumpEnabledOnly_${plantId}">
|
||||||
<div class="plantkey">Pump Time (s):</div>
|
<div class="plantkey">Pump Time (s):</div>
|
||||||
<input class="plantvalue" id="plant_${plantId}_pump_time_s" type="number" min="0" max="600" placeholder="30">
|
<input class="plantvalue" id="plant_${plantId}_pump_time_s" type="number" min="0" max="600" placeholder="30">
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ export class PlantView {
|
|||||||
private readonly header: HTMLElement;
|
private readonly header: HTMLElement;
|
||||||
private readonly testButton: HTMLButtonElement;
|
private readonly testButton: HTMLButtonElement;
|
||||||
private readonly targetMoisture: HTMLInputElement;
|
private readonly targetMoisture: HTMLInputElement;
|
||||||
private readonly minMoisture: HTMLInputElement;
|
|
||||||
private readonly pumpTimeS: HTMLInputElement;
|
private readonly pumpTimeS: HTMLInputElement;
|
||||||
private readonly pumpCooldown: HTMLInputElement;
|
private readonly pumpCooldown: HTMLInputElement;
|
||||||
private readonly pumpHourStart: HTMLSelectElement;
|
private readonly pumpHourStart: HTMLSelectElement;
|
||||||
@@ -119,11 +118,6 @@ export class PlantView {
|
|||||||
controller.configChanged()
|
controller.configChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.minMoisture = document.getElementById("plant_" + plantId + "_min_moisture")! as HTMLInputElement;
|
|
||||||
this.minMoisture.onchange = function () {
|
|
||||||
controller.configChanged()
|
|
||||||
}
|
|
||||||
|
|
||||||
this.pumpTimeS = document.getElementById("plant_" + plantId + "_pump_time_s") as HTMLInputElement;
|
this.pumpTimeS = document.getElementById("plant_" + plantId + "_pump_time_s") as HTMLInputElement;
|
||||||
this.pumpTimeS.onchange = function () {
|
this.pumpTimeS.onchange = function () {
|
||||||
controller.configChanged()
|
controller.configChanged()
|
||||||
@@ -209,15 +203,13 @@ export class PlantView {
|
|||||||
let sensorOnly = document.getElementsByClassName("plantSensorEnabledOnly_"+ this.plantId)
|
let sensorOnly = document.getElementsByClassName("plantSensorEnabledOnly_"+ this.plantId)
|
||||||
let pumpOnly = document.getElementsByClassName("plantPumpEnabledOnly_"+ this.plantId)
|
let pumpOnly = document.getElementsByClassName("plantPumpEnabledOnly_"+ this.plantId)
|
||||||
let targetOnly = document.getElementsByClassName("plantTargetEnabledOnly_"+ this.plantId)
|
let targetOnly = document.getElementsByClassName("plantTargetEnabledOnly_"+ this.plantId)
|
||||||
let minOnly = document.getElementsByClassName("plantMinEnabledOnly_"+ this.plantId)
|
|
||||||
|
|
||||||
console.log("updateVisibility plantConfig: " + plantConfig.mode)
|
console.log("updateVisibility plantConfig: " + plantConfig.mode)
|
||||||
let showSensor = plantConfig.sensor_a || plantConfig.sensor_b
|
let showSensor = plantConfig.sensor_a || plantConfig.sensor_b
|
||||||
let showPump = plantConfig.mode !== "OFF"
|
let showPump = plantConfig.mode !== "OFF"
|
||||||
let showTarget = plantConfig.mode === "TargetMoisture"
|
let showTarget = plantConfig.mode === "TargetMoisture"
|
||||||
let showMin = plantConfig.mode === "MinMoisture"
|
|
||||||
|
|
||||||
console.log("updateVisibility showsensor: " + showSensor + " pump " + showPump + " target " +showTarget + " min " + showMin)
|
console.log("updateVisibility showsensor: " + showSensor + " pump " + showPump + " target " +showTarget)
|
||||||
|
|
||||||
for (const element of Array.from(sensorOnly)) {
|
for (const element of Array.from(sensorOnly)) {
|
||||||
if (showSensor) {
|
if (showSensor) {
|
||||||
@@ -242,14 +234,6 @@ export class PlantView {
|
|||||||
element.classList.add("plantHidden_" + this.plantId)
|
element.classList.add("plantHidden_" + this.plantId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const element of Array.from(minOnly)) {
|
|
||||||
if (showMin) {
|
|
||||||
element.classList.remove("plantHidden_" + this.plantId)
|
|
||||||
} else {
|
|
||||||
element.classList.add("plantHidden_" + this.plantId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setTestResult(result: PumpTestResult) {
|
setTestResult(result: PumpTestResult) {
|
||||||
@@ -271,7 +255,6 @@ export class PlantView {
|
|||||||
setConfig(plantConfig: PlantConfig) {
|
setConfig(plantConfig: PlantConfig) {
|
||||||
this.mode.value = plantConfig.mode;
|
this.mode.value = plantConfig.mode;
|
||||||
this.targetMoisture.value = plantConfig.target_moisture.toString();
|
this.targetMoisture.value = plantConfig.target_moisture.toString();
|
||||||
this.minMoisture.value = plantConfig.min_moisture?.toString() || "";
|
|
||||||
this.pumpTimeS.value = plantConfig.pump_time_s.toString();
|
this.pumpTimeS.value = plantConfig.pump_time_s.toString();
|
||||||
this.pumpCooldown.value = plantConfig.pump_cooldown_min.toString();
|
this.pumpCooldown.value = plantConfig.pump_cooldown_min.toString();
|
||||||
this.pumpHourStart.value = plantConfig.pump_hour_start.toString();
|
this.pumpHourStart.value = plantConfig.pump_hour_start.toString();
|
||||||
@@ -297,7 +280,6 @@ export class PlantView {
|
|||||||
let conv: PlantConfig = {
|
let conv: PlantConfig = {
|
||||||
mode: this.mode.value,
|
mode: this.mode.value,
|
||||||
target_moisture: this.targetMoisture.valueAsNumber,
|
target_moisture: this.targetMoisture.valueAsNumber,
|
||||||
min_moisture: this.minMoisture.valueAsNumber,
|
|
||||||
pump_time_s: this.pumpTimeS.valueAsNumber,
|
pump_time_s: this.pumpTimeS.valueAsNumber,
|
||||||
pump_cooldown_min: this.pumpCooldown.valueAsNumber,
|
pump_cooldown_min: this.pumpCooldown.valueAsNumber,
|
||||||
pump_hour_start: +this.pumpHourStart.value,
|
pump_hour_start: +this.pumpHourStart.value,
|
||||||
|
|||||||
Reference in New Issue
Block a user