Compare commits
106 Commits
e71351f135
...
can
| Author | SHA1 | Date | |
|---|---|---|---|
| 50b2e994ca | |||
| 7a7f000743 | |||
| d650358bab | |||
| 9f113adf7e | |||
| 735f836458 | |||
| f02d935f40 | |||
| cc4e9efffd | |||
| 5d91daf23d | |||
| 577c38d026 | |||
| 6b711e29fc | |||
| 5fb8705d9a | |||
| e57e87af3f | |||
| 450197c7cd | |||
| 736925f7de | |||
| 1fb9d2ab1b | |||
| ea60d804b3 | |||
| d059b7b1db | |||
| e7b6bda747 | |||
| 04849162cd | |||
|
5621f17e61
|
|||
|
d0e5627815
|
|||
|
7115809f2b
|
|||
|
c1d0ce542c
|
|||
|
b7b08d8747
|
|||
|
8d68f0ef14
|
|||
| 34b20b1f8f | |||
|
71973f8fe9
|
|||
|
506f0c36b5
|
|||
|
4b919b9613
|
|||
| 017078ef8e | |||
| c84e863d0f | |||
| de54afce52 | |||
|
a0e7f97887
|
|||
| 3a2e59874e | |||
|
69077239a5
|
|||
|
e2cbf9618e
|
|||
| fc1991523a | |||
|
c429c829b4
|
|||
| e2cce88390 | |||
| 751f07e6fd | |||
| 04bac4d0b6 | |||
| e24dc77fa9 | |||
| 05400c7c4a | |||
| 6499b18ada | |||
| a9d7936376 | |||
| 38f4ada433 | |||
| 3fe9aaeb6f | |||
| 4f4d15e4a4 | |||
| 9f48b46738 | |||
| 0614a0e1ef | |||
| 9e82d00a91 | |||
| 171b130a29 | |||
| bfc3fbc6e1 | |||
| 26da6b39cc | |||
| a401d4de7b | |||
| 5fe1dc8f40 | |||
| f8274ea7a8 | |||
| 1cae6c4aad | |||
| e3ed41a223 | |||
| 93b169f849 | |||
| ee5c67769b | |||
| 5d3abe0834 | |||
| d4ffa7d2f1 | |||
| 1b1b27e5c1 | |||
| 0e3549a755 | |||
| aec083bcef | |||
| 62d8a38e86 | |||
|
519c8d2c52
|
|||
|
e941a4973d
|
|||
|
2b5c1da484
|
|||
|
cf31ce8d43
|
|||
|
d9c3d4e13c
|
|||
| 3572b15564 | |||
| 49614a2f96 | |||
| c263ee4a2d | |||
| 04a4b52d9b | |||
| 55558ec53e | |||
| d19bd75e6e | |||
| 7f294548dd | |||
| 4a67b9fa2a | |||
| 6d0754e109 | |||
| 169a397fe7 | |||
| 285e7b66ed | |||
| 7b3b56200d | |||
| 4b1f2b9ca7 | |||
| db27de3073 | |||
| 110cb50098 | |||
|
9509be9527
|
|||
| 8ff2763580 | |||
| 67c653fa8b | |||
| 9bace8d8c5 | |||
| 16756aba94 | |||
|
53bd1f8cce
|
|||
|
55ba52b798
|
|||
|
038f74bca1
|
|||
|
fbf1a84e7d
|
|||
|
4a334ef2f2
|
|||
|
b993f2b037
|
|||
|
48b0777d94
|
|||
|
e878a774ff
|
|||
|
fb180630e4
|
|||
|
420f4f4ae5
|
|||
|
f340278236
|
|||
|
3cdaacabac
|
|||
|
9b144d234e
|
|||
| 9296cc8c80 |
@@ -1,82 +0,0 @@
|
|||||||
(kicad_symbol_lib (version 20220914) (generator kicad_symbol_editor)
|
|
||||||
(symbol "CN3306" (in_bom yes) (on_board yes)
|
|
||||||
(property "Reference" "U" (at 5.08 -5.08 0)
|
|
||||||
(effects (font (size 1.27 1.27)))
|
|
||||||
)
|
|
||||||
(property "Value" "" (at 0 0 0)
|
|
||||||
(effects (font (size 1.27 1.27)))
|
|
||||||
)
|
|
||||||
(property "Footprint" "" (at 0 0 0)
|
|
||||||
(effects (font (size 1.27 1.27)) hide)
|
|
||||||
)
|
|
||||||
(property "Datasheet" "" (at 0 0 0)
|
|
||||||
(effects (font (size 1.27 1.27)) hide)
|
|
||||||
)
|
|
||||||
(symbol "CN3306_1_1"
|
|
||||||
(rectangle (start -2.54 7.62) (end 12.7 -16.51)
|
|
||||||
(stroke (width 0) (type default))
|
|
||||||
(fill (type background))
|
|
||||||
)
|
|
||||||
(pin input line (at 15.24 -8.89 180) (length 2.54)
|
|
||||||
(name "FB" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "1" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at 5.08 10.16 270) (length 2.54)
|
|
||||||
(name "COME" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "10" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at 15.24 -13.97 180) (length 2.54)
|
|
||||||
(name "VCC" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "11" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at 15.24 -11.43 180) (length 2.54)
|
|
||||||
(name "VCC" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "12" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at 15.24 5.08 180) (length 2.54)
|
|
||||||
(name "DRV" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "13" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at 3.81 -19.05 90) (length 2.54)
|
|
||||||
(name "GND" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "14" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at 6.35 -19.05 90) (length 2.54)
|
|
||||||
(name "GND" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "15" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at 15.24 2.54 180) (length 2.54)
|
|
||||||
(name "ISW" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "16" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at -5.08 -10.16 0) (length 2.54)
|
|
||||||
(name "COMP" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "2" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at -5.08 -1.27 0) (length 2.54)
|
|
||||||
(name "MPPT" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "3" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at -5.08 -7.62 0) (length 2.54)
|
|
||||||
(name "SHDN" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "5" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at -5.08 3.81 0) (length 2.54)
|
|
||||||
(name "CHRG" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "6" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at -5.08 1.27 0) (length 2.54)
|
|
||||||
(name "DONE" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "7" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at 15.24 -3.81 180) (length 2.54)
|
|
||||||
(name "CSP" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "8" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
(pin input line (at 15.24 -6.35 180) (length 2.54)
|
|
||||||
(name "ONE" (effects (font (size 1.27 1.27))))
|
|
||||||
(number "9" (effects (font (size 1.27 1.27))))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
208
board/Modules.pretty/LightPower.kicad_mod
Normal file
208
board/Modules.pretty/LightPower.kicad_mod
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
(footprint "LightPower"
|
||||||
|
(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 "0d42c5f3-a9e7-44fb-91f8-62bbb8e8e7fb")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Value" "LightPower"
|
||||||
|
(at 0 1 0)
|
||||||
|
(unlocked yes)
|
||||||
|
(layer "F.Fab")
|
||||||
|
(uuid "56f97324-dbe4-43ff-a10c-cfc7875dabba")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.15)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Datasheet" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(unlocked yes)
|
||||||
|
(layer "F.Fab")
|
||||||
|
(hide yes)
|
||||||
|
(uuid "fffbc31d-2d05-4fe7-9786-5bc8d82bb48a")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.15)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Description" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(unlocked yes)
|
||||||
|
(layer "F.Fab")
|
||||||
|
(hide yes)
|
||||||
|
(uuid "7f894ad2-db32-4bd1-a0a8-dcb308562141")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.15)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(attr smd)
|
||||||
|
(fp_line
|
||||||
|
(start -19.1 -5.9)
|
||||||
|
(end 18.9 -5.9)
|
||||||
|
(stroke
|
||||||
|
(width 0.05)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "61ffbe7b-a4bf-4909-81b7-0e19518f145c")
|
||||||
|
)
|
||||||
|
(fp_line
|
||||||
|
(start -19.1 6.1)
|
||||||
|
(end -19.1 -5.9)
|
||||||
|
(stroke
|
||||||
|
(width 0.05)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "54f550a1-e6e1-4119-a49f-a9aebb4befbf")
|
||||||
|
)
|
||||||
|
(fp_line
|
||||||
|
(start 18.9 -5.9)
|
||||||
|
(end 18.9 -0.5)
|
||||||
|
(stroke
|
||||||
|
(width 0.05)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "d602ffa7-a7ff-4636-898f-1490ff61a015")
|
||||||
|
)
|
||||||
|
(fp_line
|
||||||
|
(start 18.9 -0.5)
|
||||||
|
(end 19.15 0.5)
|
||||||
|
(stroke
|
||||||
|
(width 0.05)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "92638711-2cf6-4115-80fb-f2f2d995f431")
|
||||||
|
)
|
||||||
|
(fp_line
|
||||||
|
(start 19.15 0.5)
|
||||||
|
(end 19.5 1.3)
|
||||||
|
(stroke
|
||||||
|
(width 0.05)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "72346884-b0d9-43b0-9826-8a279b34f109")
|
||||||
|
)
|
||||||
|
(fp_line
|
||||||
|
(start 19.5 1.3)
|
||||||
|
(end 19.9 2)
|
||||||
|
(stroke
|
||||||
|
(width 0.05)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "237fb7f5-440e-49c0-9e5f-57e450425975")
|
||||||
|
)
|
||||||
|
(fp_line
|
||||||
|
(start 19.9 2)
|
||||||
|
(end 21.1 2)
|
||||||
|
(stroke
|
||||||
|
(width 0.05)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "29de2776-0155-4990-9886-eaa6133e1e35")
|
||||||
|
)
|
||||||
|
(fp_line
|
||||||
|
(start 21.1 6.1)
|
||||||
|
(end -19.1 6.1)
|
||||||
|
(stroke
|
||||||
|
(width 0.05)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "86fbd866-c598-42d9-83d2-9f60637cd889")
|
||||||
|
)
|
||||||
|
(fp_line
|
||||||
|
(start 21.1 6.1)
|
||||||
|
(end 21.1 2)
|
||||||
|
(stroke
|
||||||
|
(width 0.05)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "e1bdee8f-0a26-4703-9a9a-41e4fae709ec")
|
||||||
|
)
|
||||||
|
(fp_text user "${REFERENCE}"
|
||||||
|
(at 0 2.5 0)
|
||||||
|
(unlocked yes)
|
||||||
|
(layer "F.Fab")
|
||||||
|
(uuid "10d8d783-d5cb-4308-95f2-9c79a6f90db2")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.15)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pad "1" thru_hole circle
|
||||||
|
(at 13.52 4.3 270)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "ef891d05-9b9f-48c3-bef3-9b4b56cb685e")
|
||||||
|
)
|
||||||
|
(pad "2" thru_hole circle
|
||||||
|
(at 16.06 4.3 270)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "124c24ec-7b0e-4868-9700-bc4e7c567885")
|
||||||
|
)
|
||||||
|
(pad "3" thru_hole rect
|
||||||
|
(at 18.6 4.3 270)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "92852bed-9f18-4995-a2a5-d26facacadd0")
|
||||||
|
)
|
||||||
|
(pad "4" thru_hole rect
|
||||||
|
(at 17.8 -4.8)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "142a18f8-cfac-497e-bb90-f927dc045155")
|
||||||
|
)
|
||||||
|
(pad "5" thru_hole rect
|
||||||
|
(at -18 -4.8)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "398d0534-3ff9-4028-9a52-9a410332884e")
|
||||||
|
)
|
||||||
|
(pad "6" thru_hole rect
|
||||||
|
(at -18 5)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "d7c32d07-2326-4bc1-8bda-aceb817d7a40")
|
||||||
|
)
|
||||||
|
(embedded_fonts no)
|
||||||
|
)
|
||||||
174
board/Modules.pretty/PumpModule.kicad_mod
Normal file
174
board/Modules.pretty/PumpModule.kicad_mod
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
(footprint "PumpModule"
|
||||||
|
(version 20241229)
|
||||||
|
(generator "pcbnew")
|
||||||
|
(generator_version "9.0")
|
||||||
|
(layer "F.Cu")
|
||||||
|
(property "Reference" "U1"
|
||||||
|
(at -0.1 -0.5 0)
|
||||||
|
(unlocked yes)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "0fac3daa-410a-424b-8b62-3653e0e39256")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Value" "~"
|
||||||
|
(at -0.1 1 0)
|
||||||
|
(unlocked yes)
|
||||||
|
(layer "F.Fab")
|
||||||
|
(uuid "490e1af0-9912-46a9-8419-a3c2a915a249")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.15)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Datasheet" ""
|
||||||
|
(at -13.3 -7.35 0)
|
||||||
|
(unlocked yes)
|
||||||
|
(layer "F.Fab")
|
||||||
|
(hide yes)
|
||||||
|
(uuid "46dc35be-63c1-46ff-8f93-dceb8fd53dc3")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.15)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Description" ""
|
||||||
|
(at -13.3 -7.35 0)
|
||||||
|
(unlocked yes)
|
||||||
|
(layer "F.Fab")
|
||||||
|
(hide yes)
|
||||||
|
(uuid "d96cf3f1-cf49-4af2-b935-e7df8b23c266")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.15)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(attr smd)
|
||||||
|
(fp_line
|
||||||
|
(start -40 4.9)
|
||||||
|
(end -40 28.4)
|
||||||
|
(stroke
|
||||||
|
(width 0.1)
|
||||||
|
(type default)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "5b0120eb-981a-40db-ad22-ef6fe81cbdcc")
|
||||||
|
)
|
||||||
|
(fp_line
|
||||||
|
(start -40 4.9)
|
||||||
|
(end 49.8 4.9)
|
||||||
|
(stroke
|
||||||
|
(width 0.05)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "c832bc6f-3a4d-41f7-ba87-e9cac399b8d7")
|
||||||
|
)
|
||||||
|
(fp_line
|
||||||
|
(start -40 28.4)
|
||||||
|
(end 49.8 28.4)
|
||||||
|
(stroke
|
||||||
|
(width 0.05)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "aea04064-7e14-41c3-adac-23e5ce64e65e")
|
||||||
|
)
|
||||||
|
(fp_line
|
||||||
|
(start 49.8 4.9)
|
||||||
|
(end 49.8 28.4)
|
||||||
|
(stroke
|
||||||
|
(width 0.05)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "7a9fdc40-f4c7-45e7-8b57-e7b2d37884c0")
|
||||||
|
)
|
||||||
|
(fp_text user "${REFERENCE}"
|
||||||
|
(at -0.1 2.5 0)
|
||||||
|
(unlocked yes)
|
||||||
|
(layer "F.Fab")
|
||||||
|
(uuid "8231e46b-5bec-4822-8561-bdd1fa9da1da")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.15)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pad "1" thru_hole rect
|
||||||
|
(at 48 6.7 270)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "95e5f681-61e1-4c06-8ff4-85f4013efdea")
|
||||||
|
)
|
||||||
|
(pad "2" thru_hole rect
|
||||||
|
(at 30 27)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "c521b1c9-f760-4dc6-879c-b94140d5624e")
|
||||||
|
)
|
||||||
|
(pad "3" thru_hole rect
|
||||||
|
(at -30 27)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "038ad619-2e4e-4056-a099-69de8ddd0df8")
|
||||||
|
)
|
||||||
|
(pad "4" thru_hole rect
|
||||||
|
(at -38.5 6.25)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "bb96f5cb-d9fa-4cd9-ac26-451919aa9518")
|
||||||
|
)
|
||||||
|
(pad "5" thru_hole oval
|
||||||
|
(at 45.46 6.7 270)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "def315f4-56be-4088-b826-eb2c89dfa8df")
|
||||||
|
)
|
||||||
|
(pad "6" thru_hole oval
|
||||||
|
(at 42.92 6.7 270)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "8fd26b79-013e-4286-8f18-adc764d1e894")
|
||||||
|
)
|
||||||
|
(pad "7" thru_hole oval
|
||||||
|
(at 40.38 6.7 270)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "58e24d78-f1d3-45df-867a-691db92a3ca2")
|
||||||
|
)
|
||||||
|
(pad "8" thru_hole oval
|
||||||
|
(at 37.84 6.7 270)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "7f75adc2-03d6-4d95-9e8a-b91e3d90198e")
|
||||||
|
)
|
||||||
|
(embedded_fonts no)
|
||||||
|
)
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"board": {
|
"board": {
|
||||||
"active_layer": 31,
|
"active_layer": 4,
|
||||||
"active_layer_preset": "",
|
"active_layer_preset": "All Layers",
|
||||||
"auto_track_width": false,
|
"auto_track_width": false,
|
||||||
"hidden_netclasses": [],
|
"hidden_netclasses": [],
|
||||||
"hidden_nets": [],
|
"hidden_nets": [],
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
"opacity": {
|
"opacity": {
|
||||||
"images": 0.4399999976158142,
|
"images": 0.4399999976158142,
|
||||||
"pads": 1.0,
|
"pads": 1.0,
|
||||||
|
"shapes": 1.0,
|
||||||
"tracks": 1.0,
|
"tracks": 1.0,
|
||||||
"vias": 1.0,
|
"vias": 1.0,
|
||||||
"zones": 0.6
|
"zones": 0.6
|
||||||
@@ -29,6 +30,55 @@
|
|||||||
"zones": true
|
"zones": true
|
||||||
},
|
},
|
||||||
"visible_items": [
|
"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_password": "",
|
||||||
|
"repo_type": "",
|
||||||
|
"repo_username": "",
|
||||||
|
"ssh_key": ""
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "PlantCtrlESP32.kicad_prl",
|
||||||
|
"version": 5
|
||||||
|
},
|
||||||
|
"net_inspector_panel": {
|
||||||
|
"col_hidden": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"col_order": [
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
@@ -40,48 +90,49 @@
|
|||||||
8,
|
8,
|
||||||
9,
|
9,
|
||||||
10,
|
10,
|
||||||
11,
|
11
|
||||||
12,
|
|
||||||
13,
|
|
||||||
14,
|
|
||||||
15,
|
|
||||||
16,
|
|
||||||
17,
|
|
||||||
18,
|
|
||||||
19,
|
|
||||||
20,
|
|
||||||
21,
|
|
||||||
22,
|
|
||||||
23,
|
|
||||||
24,
|
|
||||||
25,
|
|
||||||
26,
|
|
||||||
27,
|
|
||||||
28,
|
|
||||||
29,
|
|
||||||
30,
|
|
||||||
32,
|
|
||||||
33,
|
|
||||||
34,
|
|
||||||
35,
|
|
||||||
36,
|
|
||||||
39,
|
|
||||||
40
|
|
||||||
],
|
],
|
||||||
"visible_layers": "ffcffff_ffffffff",
|
"col_widths": [
|
||||||
"zone_display_mode": 1
|
0,
|
||||||
},
|
0,
|
||||||
"git": {
|
0,
|
||||||
"repo_password": "",
|
0,
|
||||||
"repo_type": "",
|
0,
|
||||||
"repo_username": "",
|
0,
|
||||||
"ssh_key": ""
|
0,
|
||||||
},
|
0,
|
||||||
"meta": {
|
0,
|
||||||
"filename": "PlantCtrlESP32.kicad_prl",
|
0,
|
||||||
"version": 3
|
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": {
|
"project": {
|
||||||
"files": []
|
"files": []
|
||||||
|
},
|
||||||
|
"schematic": {
|
||||||
|
"selection_filter": {
|
||||||
|
"graphics": true,
|
||||||
|
"images": true,
|
||||||
|
"labels": true,
|
||||||
|
"lockedItems": false,
|
||||||
|
"otherItems": true,
|
||||||
|
"pins": true,
|
||||||
|
"symbols": true,
|
||||||
|
"text": true,
|
||||||
|
"wires": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,9 +37,9 @@
|
|||||||
"other_text_thickness": 0.15,
|
"other_text_thickness": 0.15,
|
||||||
"other_text_upright": false,
|
"other_text_upright": false,
|
||||||
"pads": {
|
"pads": {
|
||||||
"drill": 0.25,
|
"drill": 1.0,
|
||||||
"height": 0.35,
|
"height": 1.7,
|
||||||
"width": 0.35
|
"width": 1.7
|
||||||
},
|
},
|
||||||
"silk_line_width": 0.12,
|
"silk_line_width": 0.12,
|
||||||
"silk_text_italic": false,
|
"silk_text_italic": false,
|
||||||
@@ -58,10 +58,7 @@
|
|||||||
"width": 0.0
|
"width": 0.0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"drc_exclusions": [
|
"drc_exclusions": [],
|
||||||
"footprint_symbol_mismatch|177050000|59025000|a624af3d-bffa-4ff7-9554-e16d3c677f69|00000000-0000-0000-0000-000000000000",
|
|
||||||
"footprint_symbol_mismatch|237580000|53970000|c9d8d35b-26b7-4992-9d25-be9130d57b1a|00000000-0000-0000-0000-000000000000"
|
|
||||||
],
|
|
||||||
"meta": {
|
"meta": {
|
||||||
"filename": "board_design_settings.json",
|
"filename": "board_design_settings.json",
|
||||||
"version": 2
|
"version": 2
|
||||||
@@ -73,16 +70,19 @@
|
|||||||
"copper_edge_clearance": "error",
|
"copper_edge_clearance": "error",
|
||||||
"copper_sliver": "warning",
|
"copper_sliver": "warning",
|
||||||
"courtyards_overlap": "error",
|
"courtyards_overlap": "error",
|
||||||
|
"creepage": "error",
|
||||||
"diff_pair_gap_out_of_range": "error",
|
"diff_pair_gap_out_of_range": "error",
|
||||||
"diff_pair_uncoupled_length_too_long": "error",
|
"diff_pair_uncoupled_length_too_long": "error",
|
||||||
"drill_out_of_range": "error",
|
"drill_out_of_range": "error",
|
||||||
"duplicate_footprints": "warning",
|
"duplicate_footprints": "warning",
|
||||||
"extra_footprint": "warning",
|
"extra_footprint": "warning",
|
||||||
"footprint": "error",
|
"footprint": "error",
|
||||||
|
"footprint_filters_mismatch": "ignore",
|
||||||
"footprint_symbol_mismatch": "warning",
|
"footprint_symbol_mismatch": "warning",
|
||||||
"footprint_type_mismatch": "ignore",
|
"footprint_type_mismatch": "ignore",
|
||||||
"hole_clearance": "error",
|
"hole_clearance": "error",
|
||||||
"hole_near_hole": "error",
|
"hole_near_hole": "error",
|
||||||
|
"hole_to_hole": "error",
|
||||||
"holes_co_located": "warning",
|
"holes_co_located": "warning",
|
||||||
"invalid_outline": "error",
|
"invalid_outline": "error",
|
||||||
"isolated_copper": "warning",
|
"isolated_copper": "warning",
|
||||||
@@ -91,11 +91,13 @@
|
|||||||
"length_out_of_range": "error",
|
"length_out_of_range": "error",
|
||||||
"lib_footprint_issues": "warning",
|
"lib_footprint_issues": "warning",
|
||||||
"lib_footprint_mismatch": "warning",
|
"lib_footprint_mismatch": "warning",
|
||||||
"malformed_courtyard": "error",
|
"malformed_courtyard": "ignore",
|
||||||
"microvia_drill_out_of_range": "error",
|
"microvia_drill_out_of_range": "error",
|
||||||
|
"mirrored_text_on_front_layer": "warning",
|
||||||
"missing_courtyard": "ignore",
|
"missing_courtyard": "ignore",
|
||||||
"missing_footprint": "warning",
|
"missing_footprint": "warning",
|
||||||
"net_conflict": "warning",
|
"net_conflict": "warning",
|
||||||
|
"nonmirrored_text_on_back_layer": "warning",
|
||||||
"npth_inside_courtyard": "ignore",
|
"npth_inside_courtyard": "ignore",
|
||||||
"padstack": "warning",
|
"padstack": "warning",
|
||||||
"pth_inside_courtyard": "ignore",
|
"pth_inside_courtyard": "ignore",
|
||||||
@@ -107,10 +109,13 @@
|
|||||||
"solder_mask_bridge": "error",
|
"solder_mask_bridge": "error",
|
||||||
"starved_thermal": "error",
|
"starved_thermal": "error",
|
||||||
"text_height": "warning",
|
"text_height": "warning",
|
||||||
|
"text_on_edge_cuts": "error",
|
||||||
"text_thickness": "warning",
|
"text_thickness": "warning",
|
||||||
"through_hole_pad_without_hole": "error",
|
"through_hole_pad_without_hole": "error",
|
||||||
"too_many_vias": "error",
|
"too_many_vias": "error",
|
||||||
|
"track_angle": "error",
|
||||||
"track_dangling": "warning",
|
"track_dangling": "warning",
|
||||||
|
"track_segment_length": "error",
|
||||||
"track_width": "error",
|
"track_width": "error",
|
||||||
"tracks_crossing": "error",
|
"tracks_crossing": "error",
|
||||||
"unconnected_items": "error",
|
"unconnected_items": "error",
|
||||||
@@ -125,6 +130,7 @@
|
|||||||
"min_clearance": 0.0,
|
"min_clearance": 0.0,
|
||||||
"min_connection": 0.0,
|
"min_connection": 0.0,
|
||||||
"min_copper_edge_clearance": 0.025,
|
"min_copper_edge_clearance": 0.025,
|
||||||
|
"min_groove_width": 0.0,
|
||||||
"min_hole_clearance": 0.25,
|
"min_hole_clearance": 0.25,
|
||||||
"min_hole_to_hole": 0.25,
|
"min_hole_to_hole": 0.25,
|
||||||
"min_microvia_diameter": 0.2,
|
"min_microvia_diameter": 0.2,
|
||||||
@@ -142,10 +148,11 @@
|
|||||||
},
|
},
|
||||||
"teardrop_options": [
|
"teardrop_options": [
|
||||||
{
|
{
|
||||||
"td_onpadsmd": true,
|
"td_onpthpad": true,
|
||||||
"td_onroundshapesonly": false,
|
"td_onroundshapesonly": false,
|
||||||
|
"td_onsmdpad": true,
|
||||||
"td_ontrackend": false,
|
"td_ontrackend": false,
|
||||||
"td_onviapad": true
|
"td_onvia": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"teardrop_parameters": [
|
"teardrop_parameters": [
|
||||||
@@ -241,6 +248,7 @@
|
|||||||
"mfg": "",
|
"mfg": "",
|
||||||
"mpn": ""
|
"mpn": ""
|
||||||
},
|
},
|
||||||
|
"layer_pairs": [],
|
||||||
"layer_presets": [],
|
"layer_presets": [],
|
||||||
"viewports": []
|
"viewports": []
|
||||||
},
|
},
|
||||||
@@ -435,10 +443,15 @@
|
|||||||
"duplicate_sheet_names": "error",
|
"duplicate_sheet_names": "error",
|
||||||
"endpoint_off_grid": "ignore",
|
"endpoint_off_grid": "ignore",
|
||||||
"extra_units": "error",
|
"extra_units": "error",
|
||||||
|
"footprint_filter": "ignore",
|
||||||
|
"footprint_link_issues": "warning",
|
||||||
|
"four_way_junction": "ignore",
|
||||||
"global_label_dangling": "warning",
|
"global_label_dangling": "warning",
|
||||||
"hier_label_mismatch": "error",
|
"hier_label_mismatch": "error",
|
||||||
"label_dangling": "error",
|
"label_dangling": "error",
|
||||||
|
"label_multiple_wires": "warning",
|
||||||
"lib_symbol_issues": "warning",
|
"lib_symbol_issues": "warning",
|
||||||
|
"lib_symbol_mismatch": "warning",
|
||||||
"missing_bidi_pin": "warning",
|
"missing_bidi_pin": "warning",
|
||||||
"missing_input_pin": "warning",
|
"missing_input_pin": "warning",
|
||||||
"missing_power_pin": "error",
|
"missing_power_pin": "error",
|
||||||
@@ -449,11 +462,16 @@
|
|||||||
"no_connect_dangling": "warning",
|
"no_connect_dangling": "warning",
|
||||||
"pin_not_connected": "error",
|
"pin_not_connected": "error",
|
||||||
"pin_not_driven": "error",
|
"pin_not_driven": "error",
|
||||||
"pin_to_pin": "error",
|
"pin_to_pin": "ignore",
|
||||||
"power_pin_not_driven": "error",
|
"power_pin_not_driven": "ignore",
|
||||||
|
"same_local_global_label": "warning",
|
||||||
|
"similar_label_and_power": "warning",
|
||||||
"similar_labels": "warning",
|
"similar_labels": "warning",
|
||||||
|
"similar_power": "warning",
|
||||||
"simulation_model_issue": "ignore",
|
"simulation_model_issue": "ignore",
|
||||||
|
"single_global_label": "ignore",
|
||||||
"unannotated": "error",
|
"unannotated": "error",
|
||||||
|
"unconnected_wire_endpoint": "warning",
|
||||||
"unit_value_mismatch": "error",
|
"unit_value_mismatch": "error",
|
||||||
"unresolved_variable": "error",
|
"unresolved_variable": "error",
|
||||||
"wire_dangling": "error"
|
"wire_dangling": "error"
|
||||||
@@ -465,7 +483,7 @@
|
|||||||
},
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"filename": "PlantCtrlESP32.kicad_pro",
|
"filename": "PlantCtrlESP32.kicad_pro",
|
||||||
"version": 1
|
"version": 3
|
||||||
},
|
},
|
||||||
"net_settings": {
|
"net_settings": {
|
||||||
"classes": [
|
"classes": [
|
||||||
@@ -480,6 +498,7 @@
|
|||||||
"microvia_drill": 0.1,
|
"microvia_drill": 0.1,
|
||||||
"name": "Default",
|
"name": "Default",
|
||||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"priority": 2147483647,
|
||||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||||
"track_width": 1.2,
|
"track_width": 1.2,
|
||||||
"via_diameter": 0.8,
|
"via_diameter": 0.8,
|
||||||
@@ -497,6 +516,7 @@
|
|||||||
"microvia_drill": 0.1,
|
"microvia_drill": 0.1,
|
||||||
"name": "12V",
|
"name": "12V",
|
||||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"priority": 0,
|
||||||
"schematic_color": "rgb(255, 4, 6)",
|
"schematic_color": "rgb(255, 4, 6)",
|
||||||
"track_width": 1.0,
|
"track_width": 1.0,
|
||||||
"via_diameter": 0.8,
|
"via_diameter": 0.8,
|
||||||
@@ -514,6 +534,7 @@
|
|||||||
"microvia_drill": 0.1,
|
"microvia_drill": 0.1,
|
||||||
"name": "3V",
|
"name": "3V",
|
||||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"priority": 1,
|
||||||
"schematic_color": "rgb(255, 153, 0)",
|
"schematic_color": "rgb(255, 153, 0)",
|
||||||
"track_width": 0.2,
|
"track_width": 0.2,
|
||||||
"via_diameter": 0.8,
|
"via_diameter": 0.8,
|
||||||
@@ -531,6 +552,7 @@
|
|||||||
"microvia_drill": 0.1,
|
"microvia_drill": 0.1,
|
||||||
"name": "BAT+",
|
"name": "BAT+",
|
||||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"priority": 2,
|
||||||
"schematic_color": "rgb(81, 255, 3)",
|
"schematic_color": "rgb(81, 255, 3)",
|
||||||
"track_width": 1.2,
|
"track_width": 1.2,
|
||||||
"via_diameter": 0.8,
|
"via_diameter": 0.8,
|
||||||
@@ -548,6 +570,7 @@
|
|||||||
"microvia_drill": 0.1,
|
"microvia_drill": 0.1,
|
||||||
"name": "BAT-",
|
"name": "BAT-",
|
||||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"priority": 3,
|
||||||
"schematic_color": "rgb(130, 130, 130)",
|
"schematic_color": "rgb(130, 130, 130)",
|
||||||
"track_width": 1.2,
|
"track_width": 1.2,
|
||||||
"via_diameter": 0.8,
|
"via_diameter": 0.8,
|
||||||
@@ -565,6 +588,7 @@
|
|||||||
"microvia_drill": 0.1,
|
"microvia_drill": 0.1,
|
||||||
"name": "GND",
|
"name": "GND",
|
||||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"priority": 4,
|
||||||
"schematic_color": "rgb(0, 0, 0)",
|
"schematic_color": "rgb(0, 0, 0)",
|
||||||
"track_width": 0.5,
|
"track_width": 0.5,
|
||||||
"via_diameter": 0.8,
|
"via_diameter": 0.8,
|
||||||
@@ -573,13 +597,10 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"meta": {
|
"meta": {
|
||||||
"version": 3
|
"version": 4
|
||||||
},
|
},
|
||||||
"net_colors": null,
|
"net_colors": null,
|
||||||
"netclass_assignments": {
|
"netclass_assignments": null,
|
||||||
"Net-(battery1-Pin_1)": "BAT-",
|
|
||||||
"VBAT": "BAT+"
|
|
||||||
},
|
|
||||||
"netclass_patterns": [
|
"netclass_patterns": [
|
||||||
{
|
{
|
||||||
"netclass": "3V",
|
"netclass": "3V",
|
||||||
@@ -1055,7 +1076,7 @@
|
|||||||
},
|
},
|
||||||
"schematic": {
|
"schematic": {
|
||||||
"annotate_start_num": 0,
|
"annotate_start_num": 0,
|
||||||
"bom_export_filename": "",
|
"bom_export_filename": "PlantCtrlESP32.csv",
|
||||||
"bom_fmt_presets": [],
|
"bom_fmt_presets": [],
|
||||||
"bom_fmt_settings": {
|
"bom_fmt_settings": {
|
||||||
"field_delimiter": ",",
|
"field_delimiter": ",",
|
||||||
@@ -1229,6 +1250,7 @@
|
|||||||
],
|
],
|
||||||
"filter_string": "",
|
"filter_string": "",
|
||||||
"group_symbols": true,
|
"group_symbols": true,
|
||||||
|
"include_excluded_from_bom": false,
|
||||||
"name": "",
|
"name": "",
|
||||||
"sort_asc": true,
|
"sort_asc": true,
|
||||||
"sort_field": "LCSC_PART_NUMBER"
|
"sort_field": "LCSC_PART_NUMBER"
|
||||||
@@ -1272,6 +1294,7 @@
|
|||||||
},
|
},
|
||||||
"page_layout_descr_file": "",
|
"page_layout_descr_file": "",
|
||||||
"plot_directory": "/tmp/",
|
"plot_directory": "/tmp/",
|
||||||
|
"space_save_all_events": true,
|
||||||
"spice_adjust_passive_values": false,
|
"spice_adjust_passive_values": false,
|
||||||
"spice_current_sheet_as_root": false,
|
"spice_current_sheet_as_root": false,
|
||||||
"spice_external_command": "spice \"%I\"",
|
"spice_external_command": "spice \"%I\"",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
1438595
board/PlantCtrlESP32_v3_3.step
Normal file
1438595
board/PlantCtrlESP32_v3_3.step
Normal file
File diff suppressed because it is too large
Load Diff
4669
board/bom/ibom.html
4669
board/bom/ibom.html
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
|||||||
{"EXTRA_LAYERS": "", "EXTEND_EDGE_CUT": false, "AUTO TRANSLATE": true, "AUTO FILL": true, "EXCLUDE DNP": true}
|
{"EXTRA_LAYERS": "", "ALL_ACTIVE_LAYERS": false, "EXTEND_EDGE_CUT": false, "ALTERNATIVE_EDGE_CUT": false, "AUTO TRANSLATE": true, "AUTO FILL": true, "EXCLUDE DNP": true}
|
||||||
@@ -6,4 +6,8 @@
|
|||||||
(lib (name "board")(type "KiCad")(uri "${KIPRJMOD}/")(options "")(descr ""))
|
(lib (name "board")(type "KiCad")(uri "${KIPRJMOD}/")(options "")(descr ""))
|
||||||
(lib (name "esp32c6")(type "KiCad")(uri "${KIPRJMOD}/esp32c6")(options "")(descr ""))
|
(lib (name "esp32c6")(type "KiCad")(uri "${KIPRJMOD}/esp32c6")(options "")(descr ""))
|
||||||
(lib (name "easyeda2kicad")(type "KiCad")(uri "${KIPRJMOD}/kicad-stuff/easyeda2kicad.pretty")(options "")(descr ""))
|
(lib (name "easyeda2kicad")(type "KiCad")(uri "${KIPRJMOD}/kicad-stuff/easyeda2kicad.pretty")(options "")(descr ""))
|
||||||
|
(lib (name "MPPT")(type "KiCad")(uri "${KIPRJMOD}/modules/MPPT/MPPT.pretty")(options "")(descr ""))
|
||||||
|
(lib (name "PumpOut")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board/Modules.pretty")(options "")(descr ""))
|
||||||
|
(lib (name "Modules")(type "KiCad")(uri "${KIPRJMOD}/Modules.pretty")(options "")(descr ""))
|
||||||
|
(lib (name "Sensor")(type "KiCad")(uri "${KIPRJMOD}/modules/Sensors/Sensors/Sensor.pretty")(options "")(descr ""))
|
||||||
)
|
)
|
||||||
|
|||||||
2782
board/modules/3v3/3v3.kicad_pcb
Normal file
2782
board/modules/3v3/3v3.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
130
board/modules/3v3/3v3.kicad_prl
Normal file
130
board/modules/3v3/3v3.kicad_prl
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"active_layer": 0,
|
||||||
|
"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": 0
|
||||||
|
},
|
||||||
|
"git": {
|
||||||
|
"repo_type": "",
|
||||||
|
"repo_username": "",
|
||||||
|
"ssh_key": ""
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "3v3.kicad_prl",
|
||||||
|
"version": 5
|
||||||
|
},
|
||||||
|
"net_inspector_panel": {
|
||||||
|
"col_hidden": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"col_order": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9
|
||||||
|
],
|
||||||
|
"col_widths": [
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
635
board/modules/3v3/3v3.kicad_pro
Normal file
635
board/modules/3v3/3v3.kicad_pro
Normal file
@@ -0,0 +1,635 @@
|
|||||||
|
{
|
||||||
|
"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": "error",
|
||||||
|
"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": "warning",
|
||||||
|
"silk_over_copper": "warning",
|
||||||
|
"silk_overlap": "warning",
|
||||||
|
"skew_out_of_range": "error",
|
||||||
|
"solder_mask_bridge": "error",
|
||||||
|
"starved_thermal": "error",
|
||||||
|
"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.25,
|
||||||
|
"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.3,
|
||||||
|
"min_track_width": 0.0,
|
||||||
|
"min_via_annular_width": 0.1,
|
||||||
|
"min_via_diameter": 0.5,
|
||||||
|
"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.5,
|
||||||
|
1.0,
|
||||||
|
1.5,
|
||||||
|
2.0
|
||||||
|
],
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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": "warning",
|
||||||
|
"power_pin_not_driven": "error",
|
||||||
|
"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": "3v3.kicad_pro",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"net_settings": {
|
||||||
|
"classes": [
|
||||||
|
{
|
||||||
|
"bus_width": 12,
|
||||||
|
"clearance": 0.2,
|
||||||
|
"diff_pair_gap": 0.25,
|
||||||
|
"diff_pair_via_gap": 0.25,
|
||||||
|
"diff_pair_width": 0.2,
|
||||||
|
"line_style": 0,
|
||||||
|
"microvia_diameter": 0.3,
|
||||||
|
"microvia_drill": 0.1,
|
||||||
|
"name": "Default",
|
||||||
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"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": "3v3.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": false,
|
||||||
|
"label": "Qty",
|
||||||
|
"name": "${QUANTITY}",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Value",
|
||||||
|
"name": "Value",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": true,
|
||||||
|
"label": "Footprint",
|
||||||
|
"name": "Footprint",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Datasheet",
|
||||||
|
"name": "Datasheet",
|
||||||
|
"show": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filter_string": "",
|
||||||
|
"group_symbols": true,
|
||||||
|
"include_excluded_from_bom": true,
|
||||||
|
"name": "Default Editing",
|
||||||
|
"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": [
|
||||||
|
[
|
||||||
|
"5d71a9a3-d83a-4a01-809f-1cb0d3006b10",
|
||||||
|
"Root"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"text_variables": {}
|
||||||
|
}
|
||||||
1941
board/modules/3v3/3v3.kicad_sch
Normal file
1941
board/modules/3v3/3v3.kicad_sch
Normal file
File diff suppressed because it is too large
Load Diff
34730
board/modules/3v3/3v3.step
Normal file
34730
board/modules/3v3/3v3.step
Normal file
File diff suppressed because it is too large
Load Diff
7136
board/modules/LightOut/LightOut.kicad_pcb
Normal file
7136
board/modules/LightOut/LightOut.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
130
board/modules/LightOut/LightOut.kicad_prl
Normal file
130
board/modules/LightOut/LightOut.kicad_prl
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"active_layer": 25,
|
||||||
|
"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": 0
|
||||||
|
},
|
||||||
|
"git": {
|
||||||
|
"repo_type": "",
|
||||||
|
"repo_username": "",
|
||||||
|
"ssh_key": ""
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "LightOut.kicad_prl",
|
||||||
|
"version": 5
|
||||||
|
},
|
||||||
|
"net_inspector_panel": {
|
||||||
|
"col_hidden": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"col_order": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9
|
||||||
|
],
|
||||||
|
"col_widths": [
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
669
board/modules/LightOut/LightOut.kicad_pro
Normal file
669
board/modules/LightOut/LightOut.kicad_pro
Normal file
@@ -0,0 +1,669 @@
|
|||||||
|
{
|
||||||
|
"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": 1.0,
|
||||||
|
"height": 1.7,
|
||||||
|
"width": 1.7
|
||||||
|
},
|
||||||
|
"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": [
|
||||||
|
[
|
||||||
|
"copper_edge_clearance|127050000|19750000|9699c74c-42f0-475d-905c-32f2bfc21b27|f47bb74a-cab1-4bf9-acd5-ef1613b09d02",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"starved_thermal|119050000|20500000|7ae79caf-9e0f-4e4d-8ab8-b020d8cfa707|e5f29b1c-951c-45bf-a2c4-47dcea02bfd5|F.Cu",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"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": "error",
|
||||||
|
"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": "warning",
|
||||||
|
"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.25,
|
||||||
|
"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.3,
|
||||||
|
"min_track_width": 0.0,
|
||||||
|
"min_via_annular_width": 0.1,
|
||||||
|
"min_via_diameter": 0.5,
|
||||||
|
"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.5,
|
||||||
|
1.0,
|
||||||
|
1.5,
|
||||||
|
2.0
|
||||||
|
],
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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": "warning",
|
||||||
|
"power_pin_not_driven": "error",
|
||||||
|
"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": "LightOut.kicad_pro",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"net_settings": {
|
||||||
|
"classes": [
|
||||||
|
{
|
||||||
|
"bus_width": 12,
|
||||||
|
"clearance": 0.2,
|
||||||
|
"diff_pair_gap": 0.25,
|
||||||
|
"diff_pair_via_gap": 0.25,
|
||||||
|
"diff_pair_width": 0.2,
|
||||||
|
"line_style": 0,
|
||||||
|
"microvia_diameter": 0.3,
|
||||||
|
"microvia_drill": 0.1,
|
||||||
|
"name": "Default",
|
||||||
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"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": "LightOut.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",
|
||||||
|
"name": "LCSC",
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "LCSC_PART_NUMBER",
|
||||||
|
"name": "LCSC_PART_NUMBER",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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": [
|
||||||
|
[
|
||||||
|
"2a8304c5-3c9a-4ae8-a3b2-19491060e8fb",
|
||||||
|
"Root"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"text_variables": {}
|
||||||
|
}
|
||||||
4454
board/modules/LightOut/LightOut.kicad_sch
Normal file
4454
board/modules/LightOut/LightOut.kicad_sch
Normal file
File diff suppressed because it is too large
Load Diff
98977
board/modules/LightOut/LightOut.step
Normal file
98977
board/modules/LightOut/LightOut.step
Normal file
File diff suppressed because it is too large
Load Diff
4
board/modules/LightOut/fp-lib-table
Normal file
4
board/modules/LightOut/fp-lib-table
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
(fp_lib_table
|
||||||
|
(version 7)
|
||||||
|
(lib (name "Modules")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board/Modules.pretty")(options "")(descr ""))
|
||||||
|
)
|
||||||
4
board/modules/LightOut/sym-lib-table
Normal file
4
board/modules/LightOut/sym-lib-table
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
(sym_lib_table
|
||||||
|
(version 7)
|
||||||
|
(lib (name "Modules")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board/modules/Modules.kicad_sym")(options "")(descr ""))
|
||||||
|
)
|
||||||
24479
board/modules/MPPT/MPPT.kicad_pcb
Normal file
24479
board/modules/MPPT/MPPT.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
130
board/modules/MPPT/MPPT.kicad_prl
Normal file
130
board/modules/MPPT/MPPT.kicad_prl
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"active_layer": 5,
|
||||||
|
"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": "MPPT.kicad_prl",
|
||||||
|
"version": 5
|
||||||
|
},
|
||||||
|
"net_inspector_panel": {
|
||||||
|
"col_hidden": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"col_order": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9
|
||||||
|
],
|
||||||
|
"col_widths": [
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
785
board/modules/MPPT/MPPT.kicad_pro
Normal file
785
board/modules/MPPT/MPPT.kicad_pro
Normal file
@@ -0,0 +1,785 @@
|
|||||||
|
{
|
||||||
|
"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": [
|
||||||
|
[
|
||||||
|
"courtyards_overlap|112084965|21032500|499f5fe7-5885-47c2-974b-f649b529c51e|6df87025-4003-41e5-8291-17fff766dac2",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"courtyards_overlap|113305000|20282500|19502f41-24bc-474e-a572-d11957ca9fa9|499f5fe7-5885-47c2-974b-f649b529c51e",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"silk_overlap|110300000|20977500|4acc8ffe-9ac8-4a84-956a-115a7d7b3e4c|57669fc8-8e26-4233-af7a-24a49cb88f5a",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"silk_overlap|112537500|21285000|897a7275-18f3-4da7-9aa2-dd2257c674f9|aef215d0-4617-401a-9e7b-04f4e00e75a8",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"silk_overlap|112537500|23950000|91e8dcc0-f8c0-4d84-aa8d-100828268b67|aef215d0-4617-401a-9e7b-04f4e00e75a8",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"silk_overlap|113440000|21550000|0c747b16-d7ce-4265-bf62-3ef103975f38|d32e574f-a2c5-4328-b36b-1bf733cc7a57",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"silk_overlap|113440000|22327500|0c747b16-d7ce-4265-bf62-3ef103975f38|edcef2ac-d633-4378-9e2e-d34d824f48da",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"silk_overlap|113440000|22327500|729846c7-71d4-40af-9ddc-5c4441b51013|edcef2ac-d633-4378-9e2e-d34d824f48da",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"silk_overlap|113440000|22550000|729846c7-71d4-40af-9ddc-5c4441b51013|d32e574f-a2c5-4328-b36b-1bf733cc7a57",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"starved_thermal|115000000|21190000|1c111c53-aa66-4ea7-a1fd-488f9eb7dc56|96d7d8f0-db01-449e-8fed-d03c5a7d0f39|F.Cu",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"starved_thermal|86675000|37750000|1c111c53-aa66-4ea7-a1fd-488f9eb7dc56|d0eae3f0-eb5a-480d-9ab2-1af2af11e319|F.Cu",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"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": "error",
|
||||||
|
"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": "warning",
|
||||||
|
"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.25,
|
||||||
|
"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.3,
|
||||||
|
"min_track_width": 0.0,
|
||||||
|
"min_via_annular_width": 0.1,
|
||||||
|
"min_via_diameter": 0.5,
|
||||||
|
"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,
|
||||||
|
1.0,
|
||||||
|
1.5,
|
||||||
|
2.0
|
||||||
|
],
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"zones_allow_external_fillets": false
|
||||||
|
},
|
||||||
|
"ipc2581": {
|
||||||
|
"dist": "",
|
||||||
|
"distpn": "",
|
||||||
|
"internal_id": "",
|
||||||
|
"mfg": "",
|
||||||
|
"mpn": ""
|
||||||
|
},
|
||||||
|
"layer_pairs": [],
|
||||||
|
"layer_presets": [],
|
||||||
|
"viewports": []
|
||||||
|
},
|
||||||
|
"boards": [],
|
||||||
|
"cvpcb": {
|
||||||
|
"equivalence_files": []
|
||||||
|
},
|
||||||
|
"erc": {
|
||||||
|
"erc_exclusions": [
|
||||||
|
[
|
||||||
|
"pin_to_pin|2222500|1549400|e3b55a99-d520-4e90-8de0-46127973153b|9077e07b-1f30-4868-845d-93f2d4a2c725|/7218b645-aff7-4fb9-9c17-5858b920ef23|/7218b645-aff7-4fb9-9c17-5858b920ef23|/7218b645-aff7-4fb9-9c17-5858b920ef23",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"pin_to_pin|2222500|1549400|e3b55a99-d520-4e90-8de0-46127973153b|c174cc28-f539-4d5e-b27b-cf983a713ffb|/7218b645-aff7-4fb9-9c17-5858b920ef23|/7218b645-aff7-4fb9-9c17-5858b920ef23|/7218b645-aff7-4fb9-9c17-5858b920ef23",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"power_pin_not_driven|3162300|1003300|fefaa914-52bb-4f31-b127-8901fa81a93d|00000000-0000-0000-0000-000000000000|/7218b645-aff7-4fb9-9c17-5858b920ef23|/7218b645-aff7-4fb9-9c17-5858b920ef23|",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"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": "error",
|
||||||
|
"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": "MPPT.kicad_pro",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"net_settings": {
|
||||||
|
"classes": [
|
||||||
|
{
|
||||||
|
"bus_width": 12,
|
||||||
|
"clearance": 0.2,
|
||||||
|
"diff_pair_gap": 0.25,
|
||||||
|
"diff_pair_via_gap": 0.25,
|
||||||
|
"diff_pair_width": 0.2,
|
||||||
|
"line_style": 0,
|
||||||
|
"microvia_diameter": 0.3,
|
||||||
|
"microvia_drill": 0.1,
|
||||||
|
"name": "Default",
|
||||||
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"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": "MPPT.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": "Availability",
|
||||||
|
"name": "Availability",
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Check_prices",
|
||||||
|
"name": "Check_prices",
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Description_1",
|
||||||
|
"name": "Description_1",
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Field5",
|
||||||
|
"name": "Field5",
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "LCSC_PART_NUMBER",
|
||||||
|
"name": "LCSC_PART_NUMBER",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "MF",
|
||||||
|
"name": "MF",
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "MP",
|
||||||
|
"name": "MP",
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Package",
|
||||||
|
"name": "Package",
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Price",
|
||||||
|
"name": "Price",
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"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": false,
|
||||||
|
"label": "SnapEDA_Link",
|
||||||
|
"name": "SnapEDA_Link",
|
||||||
|
"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": [
|
||||||
|
[
|
||||||
|
"7218b645-aff7-4fb9-9c17-5858b920ef23",
|
||||||
|
"Root"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"text_variables": {}
|
||||||
|
}
|
||||||
9744
board/modules/MPPT/MPPT.kicad_sch
Normal file
9744
board/modules/MPPT/MPPT.kicad_sch
Normal file
File diff suppressed because it is too large
Load Diff
265
board/modules/MPPT/MPPT.kicad_sym
Normal file
265
board/modules/MPPT/MPPT.kicad_sym
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
(kicad_symbol_lib
|
||||||
|
(version 20241209)
|
||||||
|
(generator "kicad_symbol_editor")
|
||||||
|
(generator_version "9.0")
|
||||||
|
(symbol "MPPT"
|
||||||
|
(exclude_from_sim no)
|
||||||
|
(in_bom yes)
|
||||||
|
(on_board yes)
|
||||||
|
(property "Reference" "U"
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Value" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Footprint" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Datasheet" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Description" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(symbol "MPPT_1_1"
|
||||||
|
(rectangle
|
||||||
|
(start -10.16 -1.27)
|
||||||
|
(end 8.89 -22.86)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type background)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at -12.7 -6.35 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "SDA"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "6"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at -12.7 -8.89 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "SCL"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "5"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_out line
|
||||||
|
(at -7.62 -25.4 90)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "8"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_out line
|
||||||
|
(at -5.08 -25.4 90)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "9"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_out line
|
||||||
|
(at -2.54 -25.4 90)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "10"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_out line
|
||||||
|
(at 0 -25.4 90)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "11"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_out line
|
||||||
|
(at 11.43 -3.81 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "7"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_out line
|
||||||
|
(at 11.43 -6.35 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "VBAT"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "1"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin output line
|
||||||
|
(at 11.43 -11.43 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "IsDay"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "2"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at 11.43 -13.97 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "Charge"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "3"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at 11.43 -20.32 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "3V3"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "4"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(embedded_fonts no)
|
||||||
|
)
|
||||||
|
)
|
||||||
4990
board/modules/MPPT/MPPT.pretty/MPPT.kicad_mod
Normal file
4990
board/modules/MPPT/MPPT.pretty/MPPT.kicad_mod
Normal file
File diff suppressed because it is too large
Load Diff
171909
board/modules/MPPT/MPPT.step
Normal file
171909
board/modules/MPPT/MPPT.step
Normal file
File diff suppressed because it is too large
Load Diff
7
board/modules/MPPT/fp-lib-table
Normal file
7
board/modules/MPPT/fp-lib-table
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
(fp_lib_table
|
||||||
|
(version 7)
|
||||||
|
(lib (name "esp32c6")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board/esp32c6")(options "")(descr ""))
|
||||||
|
(lib (name "board")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board")(options "")(descr ""))
|
||||||
|
(lib (name "MPPT")(type "KiCad")(uri "${KIPRJMOD}/MPPT.pretty")(options "")(descr ""))
|
||||||
|
(lib (name "kicad-stuff")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board/kicad-stuff")(options "")(descr ""))
|
||||||
|
)
|
||||||
6
board/modules/MPPT/sym-lib-table
Normal file
6
board/modules/MPPT/sym-lib-table
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
(sym_lib_table
|
||||||
|
(version 7)
|
||||||
|
(lib (name "CN3795")(type "KiCad")(uri "${KIPRJMOD}/symbols/CN3795.kicad_sym")(options "")(descr ""))
|
||||||
|
(lib (name "MPPT")(type "KiCad")(uri "${KIPRJMOD}/MPPT.kicad_sym")(options "")(descr ""))
|
||||||
|
(lib (name "SL2300")(type "KiCad")(uri "${KIPRJMOD}/symbols/SL2300.kicad_sym")(options "")(descr ""))
|
||||||
|
)
|
||||||
278
board/modules/MPPT/symbols/SL2300.kicad_sym
Normal file
278
board/modules/MPPT/symbols/SL2300.kicad_sym
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
(kicad_symbol_lib
|
||||||
|
(version 20241209)
|
||||||
|
(generator "kicad_symbol_editor")
|
||||||
|
(generator_version "9.0")
|
||||||
|
(symbol "SL2300"
|
||||||
|
(pin_names
|
||||||
|
(offset 1.016)
|
||||||
|
)
|
||||||
|
(exclude_from_sim no)
|
||||||
|
(in_bom yes)
|
||||||
|
(on_board yes)
|
||||||
|
(property "Reference" "Q"
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Value" "SL2300"
|
||||||
|
(at 7.62 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Footprint" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Datasheet" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Description" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(symbol "SL2300_1_1"
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy -1.016 1.905) (xy -1.016 -1.905)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0.254)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type none)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy -1.016 0) (xy -3.81 0)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type none)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy -0.508 2.286) (xy -0.508 1.27)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0.254)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type none)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy -0.508 0.508) (xy -0.508 -0.508)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0.254)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type none)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy -0.508 -1.27) (xy -0.508 -2.286)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0.254)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type none)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy -0.508 -1.778) (xy 2.032 -1.778) (xy 2.032 1.778) (xy -0.508 1.778)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type none)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy -0.254 0) (xy 0.762 0.381) (xy 0.762 -0.381) (xy -0.254 0)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type outline)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(circle
|
||||||
|
(center 0.381 0)
|
||||||
|
(radius 2.794)
|
||||||
|
(stroke
|
||||||
|
(width 0.254)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type none)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy 1.27 2.54) (xy 1.27 1.778)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type none)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(circle
|
||||||
|
(center 1.27 1.778)
|
||||||
|
(radius 0.254)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type outline)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(circle
|
||||||
|
(center 1.27 -1.778)
|
||||||
|
(radius 0.254)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type outline)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy 1.27 -2.54) (xy 1.27 0) (xy -0.508 0)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type none)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy 1.524 0.508) (xy 1.651 0.381) (xy 2.413 0.381) (xy 2.54 0.254)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type none)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(polyline
|
||||||
|
(pts
|
||||||
|
(xy 2.032 0.381) (xy 1.651 -0.254) (xy 2.413 -0.254) (xy 2.032 0.381)
|
||||||
|
)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type none)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at -6.35 0 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "G"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "1"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin passive line
|
||||||
|
(at 1.27 5.08 270)
|
||||||
|
(length 2.54)
|
||||||
|
(name "D"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "3"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin passive line
|
||||||
|
(at 1.27 -5.08 90)
|
||||||
|
(length 2.54)
|
||||||
|
(name "S"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "2"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(embedded_fonts no)
|
||||||
|
)
|
||||||
|
)
|
||||||
677
board/modules/Modules.kicad_sym
Normal file
677
board/modules/Modules.kicad_sym
Normal file
@@ -0,0 +1,677 @@
|
|||||||
|
(kicad_symbol_lib
|
||||||
|
(version 20241209)
|
||||||
|
(generator "kicad_symbol_editor")
|
||||||
|
(generator_version "9.0")
|
||||||
|
(symbol "LightPowerSupply"
|
||||||
|
(exclude_from_sim no)
|
||||||
|
(in_bom yes)
|
||||||
|
(on_board yes)
|
||||||
|
(property "Reference" "U"
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Value" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Footprint" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Datasheet" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Description" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(symbol "LightPowerSupply_1_1"
|
||||||
|
(rectangle
|
||||||
|
(start -6.35 -1.27)
|
||||||
|
(end 6.35 -19.05)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type background)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at -8.89 -2.54 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "LED_ENABLE"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "1"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_in line
|
||||||
|
(at -8.89 -5.08 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "VBAT"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "2"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at -8.89 -7.62 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "3"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at -8.89 -10.16 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "4"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at -8.89 -12.7 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "5"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at -8.89 -15.24 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "6"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(embedded_fonts no)
|
||||||
|
)
|
||||||
|
(symbol "Pump_Output"
|
||||||
|
(exclude_from_sim no)
|
||||||
|
(in_bom yes)
|
||||||
|
(on_board yes)
|
||||||
|
(property "Reference" "U"
|
||||||
|
(at -6.35 15.24 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Value" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Footprint" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Datasheet" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Description" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(symbol "Pump_Output_1_1"
|
||||||
|
(rectangle
|
||||||
|
(start -12.7 12.7)
|
||||||
|
(end 10.16 -15.24)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type background)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin bidirectional line
|
||||||
|
(at -15.24 1.27 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "SCL"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "5"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin bidirectional line
|
||||||
|
(at -15.24 -1.27 0)
|
||||||
|
(length 2.54)
|
||||||
|
(name "SDA"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "6"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_in line
|
||||||
|
(at -3.81 15.24 270)
|
||||||
|
(length 2.54)
|
||||||
|
(name "3V3"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "7"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_in line
|
||||||
|
(at -1.27 15.24 270)
|
||||||
|
(length 2.54)
|
||||||
|
(name "VCC"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "8"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_in line
|
||||||
|
(at -1.27 -17.78 90)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "1"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_in line
|
||||||
|
(at 1.27 -17.78 90)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "2"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_in line
|
||||||
|
(at 3.81 -17.78 90)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "3"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_in line
|
||||||
|
(at 6.35 -17.78 90)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "4"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(embedded_fonts no)
|
||||||
|
)
|
||||||
|
(symbol "Sensor"
|
||||||
|
(exclude_from_sim no)
|
||||||
|
(in_bom yes)
|
||||||
|
(on_board yes)
|
||||||
|
(property "Reference" "U"
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Value" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Footprint" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Datasheet" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(property "Description" ""
|
||||||
|
(at 0 0 0)
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
(hide yes)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(symbol "Sensor_1_1"
|
||||||
|
(rectangle
|
||||||
|
(start -5.08 -1.27)
|
||||||
|
(end 5.08 -34.29)
|
||||||
|
(stroke
|
||||||
|
(width 0)
|
||||||
|
(type solid)
|
||||||
|
)
|
||||||
|
(fill
|
||||||
|
(type background)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_in line
|
||||||
|
(at 7.62 -2.54 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "3V3"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "1"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_in line
|
||||||
|
(at 7.62 -5.08 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "VBAT"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "2"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_in line
|
||||||
|
(at 7.62 -7.62 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "SDA"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "3"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin power_in line
|
||||||
|
(at 7.62 -10.16 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "SCL"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "4"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin output line
|
||||||
|
(at 7.62 -12.7 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "Signal"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "5"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at 7.62 -15.24 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "CAN_H"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "6"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin input line
|
||||||
|
(at 7.62 -17.78 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "CAN_L"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "7"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin output line
|
||||||
|
(at 7.62 -20.32 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "8"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin output line
|
||||||
|
(at 7.62 -22.86 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "9"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin output line
|
||||||
|
(at 7.62 -25.4 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "10"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin output line
|
||||||
|
(at 7.62 -27.94 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "11"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin output line
|
||||||
|
(at 7.62 -30.48 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "12"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(pin output line
|
||||||
|
(at 7.62 -33.02 180)
|
||||||
|
(length 2.54)
|
||||||
|
(name "GND"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(number "13"
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1.27 1.27)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(embedded_fonts no)
|
||||||
|
)
|
||||||
|
)
|
||||||
24500
board/modules/PumpOutput/PumpOutput.kicad_pcb
Normal file
24500
board/modules/PumpOutput/PumpOutput.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
130
board/modules/PumpOutput/PumpOutput.kicad_prl
Normal file
130
board/modules/PumpOutput/PumpOutput.kicad_prl
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"active_layer": 5,
|
||||||
|
"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": 0
|
||||||
|
},
|
||||||
|
"git": {
|
||||||
|
"repo_type": "",
|
||||||
|
"repo_username": "",
|
||||||
|
"ssh_key": ""
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "PumpOutput.kicad_prl",
|
||||||
|
"version": 5
|
||||||
|
},
|
||||||
|
"net_inspector_panel": {
|
||||||
|
"col_hidden": [
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"col_order": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9
|
||||||
|
],
|
||||||
|
"col_widths": [
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
690
board/modules/PumpOutput/PumpOutput.kicad_pro
Normal file
690
board/modules/PumpOutput/PumpOutput.kicad_pro
Normal file
@@ -0,0 +1,690 @@
|
|||||||
|
{
|
||||||
|
"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": [
|
||||||
|
[
|
||||||
|
"footprint_type_mismatch|145100000|72500000|5ecd01c7-e707-43f2-ada2-bb695111d219|00000000-0000-0000-0000-000000000000",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"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": "warning",
|
||||||
|
"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": "error",
|
||||||
|
"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": "warning",
|
||||||
|
"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.25,
|
||||||
|
"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.3,
|
||||||
|
"min_track_width": 0.0,
|
||||||
|
"min_via_annular_width": 0.1,
|
||||||
|
"min_via_diameter": 0.5,
|
||||||
|
"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.3,
|
||||||
|
0.5,
|
||||||
|
1.0,
|
||||||
|
1.5,
|
||||||
|
2.0
|
||||||
|
],
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"zones_allow_external_fillets": false
|
||||||
|
},
|
||||||
|
"ipc2581": {
|
||||||
|
"dist": "",
|
||||||
|
"distpn": "",
|
||||||
|
"internal_id": "",
|
||||||
|
"mfg": "",
|
||||||
|
"mpn": ""
|
||||||
|
},
|
||||||
|
"layer_pairs": [],
|
||||||
|
"layer_presets": [],
|
||||||
|
"viewports": []
|
||||||
|
},
|
||||||
|
"boards": [],
|
||||||
|
"cvpcb": {
|
||||||
|
"equivalence_files": []
|
||||||
|
},
|
||||||
|
"erc": {
|
||||||
|
"erc_exclusions": [
|
||||||
|
[
|
||||||
|
"power_pin_not_driven|1130300|660400|e4ea27f9-c0eb-4f42-a53b-0c7fd9aa9f2d|00000000-0000-0000-0000-000000000000|/fa7c93d2-7670-4cd5-85ee-82ddfb7f2ba1|/fa7c93d2-7670-4cd5-85ee-82ddfb7f2ba1|",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"power_pin_not_driven|1384300|812800|1d894c27-ab0a-479f-ab88-cf53e2baa7e4|00000000-0000-0000-0000-000000000000|/fa7c93d2-7670-4cd5-85ee-82ddfb7f2ba1|/fa7c93d2-7670-4cd5-85ee-82ddfb7f2ba1|",
|
||||||
|
""
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"power_pin_not_driven|1943100|812800|e0cac361-8a98-43b1-965d-36aa882fb85b|00000000-0000-0000-0000-000000000000|/fa7c93d2-7670-4cd5-85ee-82ddfb7f2ba1|/fa7c93d2-7670-4cd5-85ee-82ddfb7f2ba1|",
|
||||||
|
""
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"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": "warning",
|
||||||
|
"power_pin_not_driven": "error",
|
||||||
|
"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": "PumpOutput.kicad_pro",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"net_settings": {
|
||||||
|
"classes": [
|
||||||
|
{
|
||||||
|
"bus_width": 12,
|
||||||
|
"clearance": 0.1,
|
||||||
|
"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": [
|
||||||
|
{
|
||||||
|
"netclass": "Default",
|
||||||
|
"pattern": "VCC"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"pcbnew": {
|
||||||
|
"last_paths": {
|
||||||
|
"gencad": "",
|
||||||
|
"idf": "",
|
||||||
|
"netlist": "",
|
||||||
|
"plot": "",
|
||||||
|
"pos_files": "",
|
||||||
|
"specctra_dsn": "",
|
||||||
|
"step": "PumpOutput.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": "Field5",
|
||||||
|
"name": "Field5",
|
||||||
|
"show": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "LCSC_PART_NUMBER",
|
||||||
|
"name": "LCSC_PART_NUMBER",
|
||||||
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "Sim.Pins",
|
||||||
|
"name": "Sim.Pins",
|
||||||
|
"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": [
|
||||||
|
[
|
||||||
|
"fa7c93d2-7670-4cd5-85ee-82ddfb7f2ba1",
|
||||||
|
"Root"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"text_variables": {}
|
||||||
|
}
|
||||||
10891
board/modules/PumpOutput/PumpOutput.kicad_sch
Normal file
10891
board/modules/PumpOutput/PumpOutput.kicad_sch
Normal file
File diff suppressed because it is too large
Load Diff
249823
board/modules/PumpOutput/PumpOutput.step
Normal file
249823
board/modules/PumpOutput/PumpOutput.step
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
|||||||
|
{"EXTRA_LAYERS": "", "ALL_ACTIVE_LAYERS": false, "EXTEND_EDGE_CUT": false, "ALTERNATIVE_EDGE_CUT": false, "AUTO TRANSLATE": true, "AUTO FILL": true, "EXCLUDE DNP": false}
|
||||||
6
board/modules/PumpOutput/fp-lib-table
Normal file
6
board/modules/PumpOutput/fp-lib-table
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
(fp_lib_table
|
||||||
|
(version 7)
|
||||||
|
(lib (name "Modules")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board/Modules.pretty")(options "")(descr ""))
|
||||||
|
(lib (name "board")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board")(options "")(descr ""))
|
||||||
|
(lib (name "Library")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board/modules/LightOut/Library.pretty")(options "")(descr ""))
|
||||||
|
)
|
||||||
259
board/modules/PumpOutput/production/netlist.ipc
Normal file
259
board/modules/PumpOutput/production/netlist.ipc
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
P CODE 00
|
||||||
|
P UNITS CUST 0
|
||||||
|
P arrayDim N
|
||||||
|
317VBAT VIA MD0118PA00X+070000Y-031653X0236Y0000R000S3
|
||||||
|
317VBAT VIA MD0118PA00X+068198Y-031624X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+044783Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+043012Y-034843X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+048720Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+056496Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+071949Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+057874Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+071453Y-034485X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+065669Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+050689Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+062598Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+068406Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+064469Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+042126Y-034843X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+046949Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+060433Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+046063Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+069587Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+058661Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+068113Y-033900X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+052677Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+054724Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+053937Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+050000Y-034803X0236Y0000R000S3
|
||||||
|
317GND VIA MD0118PA00X+061811Y-034803X0236Y0000R000S3
|
||||||
|
3175K_VBAT VIA MD0118PA00X+070866Y-031969X0236Y0000R000S3
|
||||||
|
3175K_VBAT VIA MD0118PA00X+062598Y-032087X0236Y0000R000S3
|
||||||
|
3175K_VBAT VIA MD0118PA00X+064055Y-032087X0236Y0000R000S3
|
||||||
|
3175K_VBAT VIA MD0118PA00X+066378Y-032087X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT1-K) VIA MD0118PA00X+063543Y-033504X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT1-K) VIA MD0118PA00X+067126Y-033583X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT1-K) VIA MD0118PA00X+071535Y-033622X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT1-A) VIA MD0118PA00X+074134Y-033169X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT1-A) VIA MD0118PA00X+044488Y-032599X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT2-A) VIA MD0118PA00X+048386Y-032796X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT2-A) VIA MD0118PA00X+073858Y-033150X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT3-A) VIA MD0118PA00X+073543Y-033150X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT3-A) VIA MD0118PA00X+052165Y-032875X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT4-A) VIA MD0118PA00X+056260Y-032954X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT4-A) VIA MD0118PA00X+073228Y-033150X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT5-A) VIA MD0118PA00X+074724Y-031850X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT5-A) VIA MD0118PA00X+060157Y-032441X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT6-A) VIA MD0118PA00X+074409Y-031850X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT6-A) VIA MD0118PA00X+064055Y-032362X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT7-A) VIA MD0118PA00X+067126Y-032165X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT7-A) VIA MD0118PA00X+074094Y-031850X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT8-A) VIA MD0118PA00X+073780Y-031850X0236Y0000R000S3
|
||||||
|
317T-(P_FAULT8-A) VIA MD0118PA00X+071417Y-031850X0236Y0000R000S3
|
||||||
|
317PUMP1 VIA MD0118PA00X+073425Y-034646X0236Y0000R000S3
|
||||||
|
317PUMP1 VIA MD0118PA00X+045374Y-036713X0236Y0000R000S3
|
||||||
|
317PUMP3 VIA MD0118PA00X+053248Y-036319X0236Y0000R000S3
|
||||||
|
317PUMP3 VIA MD0118PA00X+074370Y-034449X0236Y0000R000S3
|
||||||
|
317PUMP4 VIA MD0118PA00X+074764Y-034331X0236Y0000R000S3
|
||||||
|
317PUMP4 VIA MD0118PA00X+057185Y-036122X0236Y0000R000S3
|
||||||
|
317PUMP5 VIA MD0118PA00X+061024Y-036024X0236Y0000R000S3
|
||||||
|
317PUMP5 VIA MD0118PA00X+075079Y-034252X0236Y0000R000S3
|
||||||
|
317PUMP6 VIA MD0118PA00X+075354Y-034134X0236Y0000R000S3
|
||||||
|
317PUMP6 VIA MD0118PA00X+064654Y-035649X0236Y0000R000S3
|
||||||
|
317PUMP7 VIA MD0118PA00X+068898Y-035630X0236Y0000R000S3
|
||||||
|
317PUMP7 VIA MD0118PA00X+075551Y-033937X0236Y0000R000S3
|
||||||
|
317PUMP2 VIA MD0118PA00X+073858Y-034567X0236Y0000R000S3
|
||||||
|
317PUMP2 VIA MD0118PA00X+049311Y-036516X0236Y0000R000S3
|
||||||
|
3173_3V VIA MD0118PA00X+068287Y-033051X0236Y0000R000S3
|
||||||
|
3173_3V VIA MD0118PA00X+071929Y-033268X0236Y0000R000S3
|
||||||
|
317SDA VIA MD0118PA00X+069796Y-033232X0236Y0000R000S3
|
||||||
|
317SDA VIA MD0118PA00X+072677Y-033150X0236Y0000R000S3
|
||||||
|
317SCL VIA MD0118PA00X+070039Y-033103X0236Y0000R000S3
|
||||||
|
317SCL VIA MD0118PA00X+072953Y-033150X0236Y0000R000S3
|
||||||
|
327VCC R23 -1 A01X+069281Y-031654X0443Y0689R000S2
|
||||||
|
327VBAT R23 -2 A01X+070433Y-031654X0443Y0689R000S2
|
||||||
|
327VCC R22 -1 A01X+067416Y-031654X0443Y0689R000S2
|
||||||
|
327VBAT R22 -2 A01X+068568Y-031654X0443Y0689R000S2
|
||||||
|
327PUMP3 R16 -1 A01X+052195Y-033858X0315Y0374R180S2
|
||||||
|
327NET-(Q3-G) R16 -2 A01X+051545Y-033858X0315Y0374R180S2
|
||||||
|
327NET-(Q3-G) Q3 -1 A01X+052657Y-035984X0354Y0315R180S2
|
||||||
|
327GND Q3 -2 A01X+052657Y-035236X0354Y0315R180S2
|
||||||
|
327-(PUMP3-PIN_1) Q3 -3 A01X+051870Y-035610X0354Y0315R180S2
|
||||||
|
327NET-(Q5-G) Q5 -1 A01X+060443Y-035984X0354Y0315R180S2
|
||||||
|
327GND Q5 -2 A01X+060443Y-035236X0354Y0315R180S2
|
||||||
|
327-(PUMP5-PIN_1) Q5 -3 A01X+059656Y-035610X0354Y0315R180S2
|
||||||
|
327NET-(Q1-G) Q1 -1 A01X+044783Y-035984X0354Y0315R180S2
|
||||||
|
327GND Q1 -2 A01X+044783Y-035236X0354Y0315R180S2
|
||||||
|
327-(PUMP1-PIN_1) Q1 -3 A01X+043996Y-035610X0354Y0315R180S2
|
||||||
|
317-(PUMP8-PIN_1) PUMP8 -1 D0394PA00X+070551Y-037362X0669Y0787R000S0
|
||||||
|
317VCC PUMP8 -2 D0394PA00X+071535Y-037362X0669Y0787R000S0
|
||||||
|
317-(PUMP7-PIN_1) PUMP7 -1 D0394PA00X+066535Y-037382X0669Y0787R000S0
|
||||||
|
317VCC PUMP7 -2 D0394PA00X+067520Y-037382X0669Y0787R000S0
|
||||||
|
327NET-(Q6-G) Q6 -1 A01X+064469Y-035984X0354Y0315R180S2
|
||||||
|
327GND Q6 -2 A01X+064469Y-035236X0354Y0315R180S2
|
||||||
|
327-(PUMP6-PIN_1) Q6 -3 A01X+063681Y-035610X0354Y0315R180S2
|
||||||
|
327PUMP8 R19 -1 A01X+073199Y-036024X0315Y0374R180S2
|
||||||
|
327NET-(Q8-G) R19 -2 A01X+072549Y-036024X0315Y0374R180S2
|
||||||
|
327NET-(Q5-G) R10 -1 A01X+058661Y-033829X0315Y0374R090S2
|
||||||
|
327GND R10 -2 A01X+058661Y-034478X0315Y0374R090S2
|
||||||
|
327T-(P_FAULT1-K) P_FAUL-1 A01X+059646Y-033164X0384Y0551R270S2
|
||||||
|
327T-(P_FAULT5-A) P_FAUL-2 A01X+059646Y-032426X0384Y0551R270S2
|
||||||
|
327NET-(Q6-G) R11 -1 A01X+062598Y-033829X0315Y0374R090S2
|
||||||
|
327GND R11 -2 A01X+062598Y-034478X0315Y0374R090S2
|
||||||
|
327-(PUMP6-PIN_1) PUMP_D-1 A01X+062598Y-033164X0384Y0551R270S2
|
||||||
|
3275K_VBAT PUMP_D-2 A01X+062598Y-032426X0384Y0551R270S2
|
||||||
|
327PUMP6 R21 -1 A01X+064104Y-033858X0315Y0374R180S2
|
||||||
|
327NET-(Q6-G) R21 -2 A01X+063455Y-033858X0315Y0374R180S2
|
||||||
|
327-(PUMP2-PIN_1) PUMP_D-1 A01X+046949Y-033145X0384Y0551R270S2
|
||||||
|
3275K_VBAT PUMP_D-2 A01X+046949Y-032406X0384Y0551R270S2
|
||||||
|
327PUMP1 R14 -1 A01X+044488Y-033858X0315Y0374R180S2
|
||||||
|
327NET-(Q1-G) R14 -2 A01X+043839Y-033858X0315Y0374R180S2
|
||||||
|
327NET-(Q2-G) R7 -1 A01X+046949Y-033829X0315Y0374R090S2
|
||||||
|
327GND R7 -2 A01X+046949Y-034478X0315Y0374R090S2
|
||||||
|
327T-(P_FAULT1-K) P_FAUL-1 A01X+055709Y-033164X0384Y0551R270S2
|
||||||
|
327T-(P_FAULT4-A) P_FAUL-2 A01X+055709Y-032426X0384Y0551R270S2
|
||||||
|
327NET-(Q7-G) R12 -1 A01X+065945Y-033829X0315Y0374R090S2
|
||||||
|
327GND R12 -2 A01X+065945Y-034478X0315Y0374R090S2
|
||||||
|
327NET-(Q4-G) Q4 -1 A01X+056521Y-035984X0354Y0315R180S2
|
||||||
|
327GND Q4 -2 A01X+056521Y-035236X0354Y0315R180S2
|
||||||
|
327-(PUMP4-PIN_1) Q4 -3 A01X+055733Y-035610X0354Y0315R180S2
|
||||||
|
327-(PUMP5-PIN_1) PUMP_D-1 A01X+058661Y-033164X0384Y0551R270S2
|
||||||
|
3275K_VBAT PUMP_D-2 A01X+058661Y-032426X0384Y0551R270S2
|
||||||
|
327GND C3 -1 A01X+067913Y-034099X0423Y0374R270S2
|
||||||
|
3273_3V C3 -2 A01X+067913Y-033420X0423Y0374R270S2
|
||||||
|
327NET-(U2-IN+) U2 -1 A01X+069380Y-033159X0522Y0197R090S2
|
||||||
|
327NET-(U2-IN-) U2 -2 A01X+069124Y-033159X0522Y0197R090S2
|
||||||
|
327GND U2 -3 A01X+068868Y-033159X0522Y0197R090S2
|
||||||
|
3273_3V U2 -4 A01X+068612Y-033159X0522Y0197R090S2
|
||||||
|
327SCL U2 -5 A01X+068612Y-034055X0522Y0197R090S2
|
||||||
|
327SDA U2 -6 A01X+068868Y-034055X0522Y0197R090S2
|
||||||
|
327GND U2 -7 A01X+069124Y-034055X0522Y0197R090S2
|
||||||
|
327SDA U2 -8 A01X+069380Y-034055X0522Y0197R090S2
|
||||||
|
327-(PUMP8-PIN_1) PUMP_D-1 A01X+070472Y-033204X0384Y0551R270S2
|
||||||
|
3275K_VBAT PUMP_D-2 A01X+070472Y-032466X0384Y0551R270S2
|
||||||
|
327-(PUMP1-PIN_1) PUMP_D-1 A01X+043012Y-033169X0384Y0551R270S2
|
||||||
|
3275K_VBAT PUMP_D-2 A01X+043012Y-032431X0384Y0551R270S2
|
||||||
|
317GND U1 -1 D0394PA00X+076024Y-031181X0669Y0669R090S0
|
||||||
|
317GND U1 -2 D0394PA00X+068937Y-039173X0669Y0669R000S0
|
||||||
|
317GND U1 -3 D0394PA00X+045315Y-039173X0669Y0669R000S0
|
||||||
|
317GND U1 -4 D0394PA00X+041969Y-031004X0669Y0669R000S0
|
||||||
|
317SCL U1 -5 D0394PA00X+075024Y-031181X0669Y0669R090S0
|
||||||
|
317SDA U1 -6 D0394PA00X+074024Y-031181X0669Y0669R090S0
|
||||||
|
3173_3V U1 -7 D0394PA00X+073024Y-031181X0669Y0669R090S0
|
||||||
|
317VBAT U1 -8 D0394PA00X+072024Y-031181X0669Y0669R090S0
|
||||||
|
3273-~{INT}-PAD1) U3 -1 A01X+072726Y-035197X0689Y0177R270S2
|
||||||
|
327GND U3 -2 A01X+072982Y-035197X0689Y0177R270S2
|
||||||
|
327GND U3 -3 A01X+073238Y-035197X0689Y0177R270S2
|
||||||
|
327PUMP1 U3 -4 A01X+073494Y-035197X0689Y0177R270S2
|
||||||
|
327PUMP2 U3 -5 A01X+073750Y-035197X0689Y0177R270S2
|
||||||
|
327PUMP3 U3 -6 A01X+074006Y-035197X0689Y0177R270S2
|
||||||
|
327PUMP4 U3 -7 A01X+074262Y-035197X0689Y0177R270S2
|
||||||
|
327PUMP5 U3 -8 A01X+074518Y-035197X0689Y0177R270S2
|
||||||
|
327PUMP6 U3 -9 A01X+074774Y-035197X0689Y0177R270S2
|
||||||
|
327PUMP7 U3 -10 A01X+075030Y-035197X0689Y0177R270S2
|
||||||
|
327PUMP8 U3 -11 A01X+075285Y-035197X0689Y0177R270S2
|
||||||
|
327GND U3 -12 A01X+075541Y-035197X0689Y0177R270S2
|
||||||
|
327T-(P_FAULT1-A) U3 -13 A01X+075541Y-032362X0689Y0177R270S2
|
||||||
|
327T-(P_FAULT2-A) U3 -14 A01X+075285Y-032362X0689Y0177R270S2
|
||||||
|
327T-(P_FAULT3-A) U3 -15 A01X+075030Y-032362X0689Y0177R270S2
|
||||||
|
327T-(P_FAULT4-A) U3 -16 A01X+074774Y-032362X0689Y0177R270S2
|
||||||
|
327T-(P_FAULT5-A) U3 -17 A01X+074518Y-032362X0689Y0177R270S2
|
||||||
|
327T-(P_FAULT6-A) U3 -18 A01X+074262Y-032362X0689Y0177R270S2
|
||||||
|
327T-(P_FAULT7-A) U3 -19 A01X+074006Y-032362X0689Y0177R270S2
|
||||||
|
327T-(P_FAULT8-A) U3 -20 A01X+073750Y-032362X0689Y0177R270S2
|
||||||
|
327GND U3 -21 A01X+073494Y-032362X0689Y0177R270S2
|
||||||
|
327SCL U3 -22 A01X+073238Y-032362X0689Y0177R270S2
|
||||||
|
327SDA U3 -23 A01X+072982Y-032362X0689Y0177R270S2
|
||||||
|
3273_3V U3 -24 A01X+072726Y-032362X0689Y0177R270S2
|
||||||
|
317-(PUMP5-PIN_1) PUMP5 -1 D0394PA00X+058661Y-037382X0669Y0787R000S0
|
||||||
|
317VCC PUMP5 -2 D0394PA00X+059646Y-037382X0669Y0787R000S0
|
||||||
|
327-(PUMP3-PIN_1) PUMP_D-1 A01X+050689Y-033164X0384Y0551R270S2
|
||||||
|
3275K_VBAT PUMP_D-2 A01X+050689Y-032426X0384Y0551R270S2
|
||||||
|
327PUMP7 R20 -1 A01X+067254Y-033957X0315Y0374R180S2
|
||||||
|
327NET-(Q7-G) R20 -2 A01X+066604Y-033957X0315Y0374R180S2
|
||||||
|
327T-(P_FAULT1-K) P_FAUL-1 A01X+067141Y-033204X0384Y0551R270S2
|
||||||
|
327T-(P_FAULT7-A) P_FAUL-2 A01X+067141Y-032466X0384Y0551R270S2
|
||||||
|
317-(PUMP6-PIN_1) PUMP6 -1 D0394PA00X+062598Y-037382X0669Y0787R000S0
|
||||||
|
317VCC PUMP6 -2 D0394PA00X+063583Y-037382X0669Y0787R000S0
|
||||||
|
327VCC C2 -1 A01X+065251Y-033071X0463Y0571R180S2
|
||||||
|
327GND C2 -2 A01X+064434Y-033071X0463Y0571R180S2
|
||||||
|
327VBAT R3 -1 A01X+069783Y-032480X0315Y0374R180S2
|
||||||
|
327NET-(U2-IN+) R3 -2 A01X+069134Y-032480X0315Y0374R180S2
|
||||||
|
327NET-(U2-IN-) R2 -1 A01X+068533Y-032480X0315Y0374R180S2
|
||||||
|
327VCC R2 -2 A01X+067884Y-032480X0315Y0374R180S2
|
||||||
|
327-(PUMP7-PIN_1) PUMP_D-1 A01X+066156Y-033204X0384Y0551R270S2
|
||||||
|
3275K_VBAT PUMP_D-2 A01X+066156Y-032466X0384Y0551R270S2
|
||||||
|
327NET-(Q2-G) Q2 -1 A01X+048720Y-035984X0354Y0315R180S2
|
||||||
|
327GND Q2 -2 A01X+048720Y-035236X0354Y0315R180S2
|
||||||
|
327-(PUMP2-PIN_1) Q2 -3 A01X+047933Y-035610X0354Y0315R180S2
|
||||||
|
327T-(P_FAULT1-K) P_FAUL-1 A01X+047933Y-033145X0384Y0551R270S2
|
||||||
|
327T-(P_FAULT2-A) P_FAUL-2 A01X+047933Y-032406X0384Y0551R270S2
|
||||||
|
327GND D3 -1 A01X+050000Y-035236X0581Y0236R000S2
|
||||||
|
327VCC D3 -2 A01X+050000Y-035984X0581Y0236R000S2
|
||||||
|
327-(PUMP3-PIN_1) D3 -3 A01X+050738Y-035610X0581Y0236R000S2
|
||||||
|
327GND D6 -1 A01X+061811Y-035217X0581Y0236R000S2
|
||||||
|
327VCC D6 -2 A01X+061811Y-035965X0581Y0236R000S2
|
||||||
|
327-(PUMP6-PIN_1) D6 -3 A01X+062549Y-035591X0581Y0236R000S2
|
||||||
|
327T-(P_FAULT1-K) P_FAUL-1 A01X+051673Y-033164X0384Y0551R270S2
|
||||||
|
327T-(P_FAULT3-A) P_FAUL-2 A01X+051673Y-032426X0384Y0551R270S2
|
||||||
|
327T-(P_FAULT1-K) P_FAUL-1 A01X+063583Y-033164X0384Y0551R270S2
|
||||||
|
327T-(P_FAULT6-A) P_FAUL-2 A01X+063583Y-032426X0384Y0551R270S2
|
||||||
|
317-(PUMP3-PIN_1) PUMP3 -1 D0394PA00X+050787Y-037382X0669Y0787R000S0
|
||||||
|
317VCC PUMP3 -2 D0394PA00X+051772Y-037382X0669Y0787R000S0
|
||||||
|
327GND C1 -1 A01X+071255Y-033937X0423Y0374R000S2
|
||||||
|
3273_3V C1 -2 A01X+071934Y-033937X0423Y0374R000S2
|
||||||
|
327NET-(Q8-G) R13 -1 A01X+069951Y-033937X0315Y0374R000S2
|
||||||
|
327GND R13 -2 A01X+070600Y-033937X0315Y0374R000S2
|
||||||
|
327GND D2 -1 A01X+046088Y-035256X0581Y0236R000S2
|
||||||
|
327VCC D2 -2 A01X+046088Y-036004X0581Y0236R000S2
|
||||||
|
327-(PUMP2-PIN_1) D2 -3 A01X+046826Y-035630X0581Y0236R000S2
|
||||||
|
327VCC R5 -1 A01X+065089Y-032283X0315Y0374R180S2
|
||||||
|
3275K_VBAT R5 -2 A01X+064439Y-032283X0315Y0374R180S2
|
||||||
|
327GND D5 -1 A01X+057884Y-035236X0581Y0236R000S2
|
||||||
|
327VCC D5 -2 A01X+057884Y-035984X0581Y0236R000S2
|
||||||
|
327-(PUMP5-PIN_1) D5 -3 A01X+058622Y-035610X0581Y0236R000S2
|
||||||
|
327PUMP4 R17 -1 A01X+056230Y-033858X0315Y0374R180S2
|
||||||
|
327NET-(Q4-G) R17 -2 A01X+055581Y-033858X0315Y0374R180S2
|
||||||
|
317-(PUMP2-PIN_1) PUMP2 -1 D0394PA00X+046850Y-037382X0669Y0787R000S0
|
||||||
|
317VCC PUMP2 -2 D0394PA00X+047835Y-037382X0669Y0787R000S0
|
||||||
|
327T-(P_FAULT1-K) P_FAUL-1 A01X+043996Y-033145X0384Y0551R270S2
|
||||||
|
327T-(P_FAULT1-A) P_FAUL-2 A01X+043996Y-032406X0384Y0551R270S2
|
||||||
|
327PUMP5 R18 -1 A01X+060167Y-033858X0315Y0374R180S2
|
||||||
|
327NET-(Q5-G) R18 -2 A01X+059518Y-033858X0315Y0374R180S2
|
||||||
|
327GND D1 -1 A01X+042077Y-035256X0581Y0236R000S2
|
||||||
|
327VCC D1 -2 A01X+042077Y-036004X0581Y0236R000S2
|
||||||
|
327-(PUMP1-PIN_1) D1 -3 A01X+042815Y-035630X0581Y0236R000S2
|
||||||
|
327-(PUMP4-PIN_1) PUMP_D-1 A01X+054724Y-033164X0384Y0551R270S2
|
||||||
|
3275K_VBAT PUMP_D-2 A01X+054724Y-032426X0384Y0551R270S2
|
||||||
|
327NET-(Q8-G) Q8 -1 A01X+071949Y-035965X0354Y0315R180S2
|
||||||
|
327GND Q8 -2 A01X+071949Y-035217X0354Y0315R180S2
|
||||||
|
327-(PUMP8-PIN_1) Q8 -3 A01X+071161Y-035591X0354Y0315R180S2
|
||||||
|
327GND D4 -1 A01X+053962Y-035236X0581Y0236R000S2
|
||||||
|
327VCC D4 -2 A01X+053962Y-035984X0581Y0236R000S2
|
||||||
|
327-(PUMP4-PIN_1) D4 -3 A01X+054700Y-035610X0581Y0236R000S2
|
||||||
|
317-(PUMP1-PIN_1) PUMP1 -1 D0394PA00X+042913Y-037402X0669Y0787R000S0
|
||||||
|
317VCC PUMP1 -2 D0394PA00X+043898Y-037402X0669Y0787R000S0
|
||||||
|
327T-(P_FAULT1-K) P_FAUL-1 A01X+071417Y-033204X0384Y0551R270S2
|
||||||
|
327T-(P_FAULT8-A) P_FAUL-2 A01X+071417Y-032466X0384Y0551R270S2
|
||||||
|
327GND R4 -1 A01X+046260Y-034478X0315Y0374R270S2
|
||||||
|
327T-(P_FAULT1-K) R4 -2 A01X+046260Y-033829X0315Y0374R270S2
|
||||||
|
327PUMP2 R15 -1 A01X+048455Y-033858X0315Y0374R180S2
|
||||||
|
327NET-(Q2-G) R15 -2 A01X+047805Y-033858X0315Y0374R180S2
|
||||||
|
317-(PUMP4-PIN_1) PUMP4 -1 D0394PA00X+054724Y-037382X0669Y0787R000S0
|
||||||
|
317VCC PUMP4 -2 D0394PA00X+055709Y-037382X0669Y0787R000S0
|
||||||
|
327NET-(Q3-G) R8 -1 A01X+050689Y-033858X0315Y0374R090S2
|
||||||
|
327GND R8 -2 A01X+050689Y-034508X0315Y0374R090S2
|
||||||
|
327NET-(Q1-G) R6 -1 A01X+043012Y-033829X0315Y0374R090S2
|
||||||
|
327GND R6 -2 A01X+043012Y-034478X0315Y0374R090S2
|
||||||
|
327NET-(Q7-G) Q7 -1 A01X+068406Y-035984X0354Y0315R180S2
|
||||||
|
327GND Q7 -2 A01X+068406Y-035236X0354Y0315R180S2
|
||||||
|
327-(PUMP7-PIN_1) Q7 -3 A01X+067618Y-035610X0354Y0315R180S2
|
||||||
|
327GND D7 -1 A01X+065797Y-035236X0581Y0236R000S2
|
||||||
|
327VCC D7 -2 A01X+065797Y-035984X0581Y0236R000S2
|
||||||
|
327-(PUMP7-PIN_1) D7 -3 A01X+066535Y-035610X0581Y0236R000S2
|
||||||
|
327GND D8 -1 A01X+069636Y-035236X0581Y0236R000S2
|
||||||
|
327VCC D8 -2 A01X+069636Y-035984X0581Y0236R000S2
|
||||||
|
327-(PUMP8-PIN_1) D8 -3 A01X+070374Y-035610X0581Y0236R000S2
|
||||||
|
327NET-(Q4-G) R9 -1 A01X+054724Y-033829X0315Y0374R090S2
|
||||||
|
327GND R9 -2 A01X+054724Y-034478X0315Y0374R090S2
|
||||||
|
999
|
||||||
5
board/modules/PumpOutput/sym-lib-table
Normal file
5
board/modules/PumpOutput/sym-lib-table
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
(sym_lib_table
|
||||||
|
(version 7)
|
||||||
|
(lib (name "Modules")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board/modules/Modules.kicad_sym")(options "")(descr ""))
|
||||||
|
(lib (name "ESP32-C6-WROOM-1-N8")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board/esp32c6/ESP32-C6-WROOM-1-N8.kicad_sym")(options "")(descr ""))
|
||||||
|
)
|
||||||
224
board/modules/Sensors/Sensors/Sensor.pretty/Sensor.kicad_mod
Normal file
224
board/modules/Sensors/Sensors/Sensor.pretty/Sensor.kicad_mod
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
(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 circle
|
||||||
|
(at -42.4 -0.06)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "a794ee5a-cb4c-4bc2-9f30-7f38ae9862fc")
|
||||||
|
)
|
||||||
|
(pad "8" thru_hole circle
|
||||||
|
(at -42.4 2.48)
|
||||||
|
(size 1.7 1.7)
|
||||||
|
(drill 1)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "f9ed5486-c56c-4c91-b707-d09fae18d351")
|
||||||
|
)
|
||||||
|
(pad "9" thru_hole rect
|
||||||
|
(at 39.5 22.5)
|
||||||
|
(size 0.85 0.85)
|
||||||
|
(drill 0.5)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "f01565c2-eadd-4451-9dea-2ebe28d872f0")
|
||||||
|
)
|
||||||
|
(pad "10" thru_hole rect
|
||||||
|
(at -0.5 15)
|
||||||
|
(size 0.85 0.85)
|
||||||
|
(drill 0.5)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "56ec7c50-069f-4f46-9b83-ac18e4928930")
|
||||||
|
)
|
||||||
|
(pad "11" thru_hole rect
|
||||||
|
(at -43 22.5)
|
||||||
|
(size 0.85 0.85)
|
||||||
|
(drill 0.5)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "f423be21-13b8-46de-8e19-e48325411a29")
|
||||||
|
)
|
||||||
|
(pad "12" thru_hole rect
|
||||||
|
(at -0.5 -12)
|
||||||
|
(size 0.85 0.85)
|
||||||
|
(drill 0.5)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "536f0038-06c5-45e5-b1c8-898a364f6ec4")
|
||||||
|
)
|
||||||
|
(pad "13" thru_hole rect
|
||||||
|
(at 39.5 -16)
|
||||||
|
(size 0.85 0.85)
|
||||||
|
(drill 0.5)
|
||||||
|
(layers "*.Cu" "*.Mask")
|
||||||
|
(remove_unused_layers no)
|
||||||
|
(uuid "3e0cdbaa-8219-48c4-bb0a-fd4f0e78a390")
|
||||||
|
)
|
||||||
|
(embedded_fonts no)
|
||||||
|
)
|
||||||
59199
board/modules/Sensors/Sensors/Sensors.kicad_pcb
Normal file
59199
board/modules/Sensors/Sensors/Sensors.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
136
board/modules/Sensors/Sensors/Sensors.kicad_prl
Normal file
136
board/modules/Sensors/Sensors/Sensors.kicad_prl
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"active_layer": 0,
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
674
board/modules/Sensors/Sensors/Sensors.kicad_pro
Normal file
674
board/modules/Sensors/Sensors/Sensors.kicad_pro
Normal file
@@ -0,0 +1,674 @@
|
|||||||
|
{
|
||||||
|
"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": "warning",
|
||||||
|
"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": "warning",
|
||||||
|
"power_pin_not_driven": "error",
|
||||||
|
"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": {}
|
||||||
|
}
|
||||||
25063
board/modules/Sensors/Sensors/Sensors.kicad_sch
Normal file
25063
board/modules/Sensors/Sensors/Sensors.kicad_sch
Normal file
File diff suppressed because it is too large
Load Diff
35338
board/modules/Sensors/Sensors/Sensors.step
Normal file
35338
board/modules/Sensors/Sensors/Sensors.step
Normal file
File diff suppressed because it is too large
Load Diff
5
board/modules/Sensors/Sensors/fp-lib-table
Normal file
5
board/modules/Sensors/Sensors/fp-lib-table
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
(fp_lib_table
|
||||||
|
(version 7)
|
||||||
|
(lib (name "kicad-stuff")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board/kicad-stuff")(options "")(descr ""))
|
||||||
|
(lib (name "Sensor")(type "KiCad")(uri "${KIPRJMOD}/Sensor.pretty")(options "")(descr ""))
|
||||||
|
)
|
||||||
4
board/modules/Sensors/Sensors/sym-lib-table
Normal file
4
board/modules/Sensors/Sensors/sym-lib-table
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
(sym_lib_table
|
||||||
|
(version 7)
|
||||||
|
(lib (name "Modules")(type "KiCad")(uri "/home/empire/workspace/PlantCtrl/board/modules/Modules.kicad_sym")(options "")(descr ""))
|
||||||
|
)
|
||||||
@@ -0,0 +1,208 @@
|
|||||||
|
(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)
|
||||||
|
)
|
||||||
36510
board/modules/Sensors_simplified/Sensors/Sensors.kicad_pcb
Normal file
36510
board/modules/Sensors_simplified/Sensors/Sensors.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
136
board/modules/Sensors_simplified/Sensors/Sensors.kicad_prl
Normal file
136
board/modules/Sensors_simplified/Sensors/Sensors.kicad_prl
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"active_layer": 0,
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
674
board/modules/Sensors_simplified/Sensors/Sensors.kicad_pro
Normal file
674
board/modules/Sensors_simplified/Sensors/Sensors.kicad_pro
Normal file
@@ -0,0 +1,674 @@
|
|||||||
|
{
|
||||||
|
"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": "warning",
|
||||||
|
"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": {}
|
||||||
|
}
|
||||||
15385
board/modules/Sensors_simplified/Sensors/Sensors.kicad_sch
Normal file
15385
board/modules/Sensors_simplified/Sensors/Sensors.kicad_sch
Normal file
File diff suppressed because it is too large
Load Diff
35338
board/modules/Sensors_simplified/Sensors/Sensors.step
Normal file
35338
board/modules/Sensors_simplified/Sensors/Sensors.step
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1 @@
|
|||||||
|
{"EXTRA_LAYERS": "", "ALL_ACTIVE_LAYERS": false, "EXTEND_EDGE_CUT": false, "ALTERNATIVE_EDGE_CUT": false, "AUTO TRANSLATE": true, "AUTO FILL": true, "EXCLUDE DNP": false}
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -10,4 +10,6 @@
|
|||||||
(lib (name "BQ34Z100PWR-G1")(type "KiCad")(uri "${KIPRJMOD}/kicad-stuff/BQ34Z100PWR-G1.kicad_sym")(options "")(descr ""))
|
(lib (name "BQ34Z100PWR-G1")(type "KiCad")(uri "${KIPRJMOD}/kicad-stuff/BQ34Z100PWR-G1.kicad_sym")(options "")(descr ""))
|
||||||
(lib (name "ESP32-C6-WROOM-1-N8")(type "KiCad")(uri "${KIPRJMOD}/esp32c6/ESP32-C6-WROOM-1-N8.kicad_sym")(options "")(descr ""))
|
(lib (name "ESP32-C6-WROOM-1-N8")(type "KiCad")(uri "${KIPRJMOD}/esp32c6/ESP32-C6-WROOM-1-N8.kicad_sym")(options "")(descr ""))
|
||||||
(lib (name "easyeda2kicad")(type "KiCad")(uri "${KIPRJMOD}/kicad-stuff/easyeda2kicad.kicad_sym")(options "")(descr ""))
|
(lib (name "easyeda2kicad")(type "KiCad")(uri "${KIPRJMOD}/kicad-stuff/easyeda2kicad.kicad_sym")(options "")(descr ""))
|
||||||
|
(lib (name "Modules")(type "KiCad")(uri "${KIPRJMOD}/modules/Modules.kicad_sym")(options "")(descr ""))
|
||||||
|
(lib (name "MPPT")(type "KiCad")(uri "${KIPRJMOD}/modules/MPPT/MPPT.kicad_sym")(options "")(descr ""))
|
||||||
)
|
)
|
||||||
|
|||||||
BIN
case/case.3mf
BIN
case/case.3mf
Binary file not shown.
@@ -5,22 +5,22 @@ target = "riscv32imac-esp-espidf"
|
|||||||
[target.riscv32imac-esp-espidf]
|
[target.riscv32imac-esp-espidf]
|
||||||
linker = "ldproxy"
|
linker = "ldproxy"
|
||||||
#runner = "espflash flash --monitor --baud 921600 --partition-table partitions.csv -b no-reset" # Select this runner in case of usb ttl
|
#runner = "espflash flash --monitor --baud 921600 --partition-table partitions.csv -b no-reset" # Select this runner in case of usb ttl
|
||||||
#runner = "espflash flash --monitor --baud 921600 --flash-size 16mb --partition-table partitions.csv"
|
runner = "espflash flash --monitor"
|
||||||
runner = "cargo runner"
|
#runner = "cargo runner"
|
||||||
|
|
||||||
|
|
||||||
#runner = "espflash flash --monitor --partition-table partitions.csv -b no-reset" # create upgrade image file for webupload
|
#runner = "espflash flash --monitor --partition-table partitions.csv -b no-reset" # create upgrade image file for webupload
|
||||||
# runner = espflash erase-parts otadata //ensure flash is clean
|
# runner = espflash erase-parts otadata //ensure flash is clean
|
||||||
|
|
||||||
rustflags = [ "--cfg", "espidf_time64"] # Extending time_t for ESP IDF 5: https://github.com/esp-rs/rust/issues/110
|
rustflags = ["--cfg", "espidf_time64"] # Extending time_t for ESP IDF 5: https://github.com/esp-rs/rust/issues/110
|
||||||
|
|
||||||
[unstable]
|
[unstable]
|
||||||
build-std = ["std", "panic_abort"]
|
build-std = ["std", "panic_abort"]
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
MCU="esp32c6"
|
MCU = "esp32c6"
|
||||||
# Note: this variable is not used by the pio builder (`cargo build --features pio`)
|
# Note: this variable is not used by the pio builder (`cargo build --features pio`)
|
||||||
ESP_IDF_VERSION = "v5.2.1"
|
ESP_IDF_VERSION = "v5.2.1"
|
||||||
CHRONO_TZ_TIMEZONE_FILTER="UTC|Europe/Berlin"
|
CHRONO_TZ_TIMEZONE_FILTER = "UTC|America/New_York|America/Chicago|America/Los_Angeles|Europe/London|Europe/Berlin|Europe/Paris|Asia/Tokyo|Asia/Shanghai|Asia/Kolkata|Australia/Sydney|America/Sao_Paulo|Africa/Johannesburg|Asia/Dubai|Pacific/Auckland"
|
||||||
CARGO_WORKSPACE_DIR = { value = "", relative = true }
|
CARGO_WORKSPACE_DIR = { value = "", relative = true }
|
||||||
RUST_BACKTRACE = "full"
|
RUST_BACKTRACE = "full"
|
||||||
14
rust/.idea/dictionaries/project.xml
generated
Normal file
14
rust/.idea/dictionaries/project.xml
generated
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
<component name="ProjectDictionaryState">
|
||||||
|
<dictionary name="project">
|
||||||
|
<words>
|
||||||
|
<w>buildtime</w>
|
||||||
|
<w>deepsleep</w>
|
||||||
|
<w>githash</w>
|
||||||
|
<w>lightstate</w>
|
||||||
|
<w>mppt</w>
|
||||||
|
<w>plantstate</w>
|
||||||
|
<w>sntp</w>
|
||||||
|
<w>vergen</w>
|
||||||
|
</words>
|
||||||
|
</dictionary>
|
||||||
|
</component>
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
<component name="InspectionProjectProfileManager">
|
||||||
<profile version="1.0">
|
<profile version="1.0">
|
||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
|
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
||||||
|
<Languages>
|
||||||
|
<language minSize="102" name="Rust" />
|
||||||
|
</Languages>
|
||||||
|
</inspection_tool>
|
||||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
</profile>
|
</profile>
|
||||||
</component>
|
</component>
|
||||||
1
rust/.idea/vcs.xml
generated
1
rust/.idea/vcs.xml
generated
@@ -2,5 +2,6 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||||
|
<mapping directory="$PROJECT_DIR$/../website/themes/blowfish" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -10,15 +10,12 @@ resolver = "2"
|
|||||||
# Explicitly disable LTO which the Xtensa codegen backend has issues
|
# Explicitly disable LTO which the Xtensa codegen backend has issues
|
||||||
lto = false
|
lto = false
|
||||||
strip = false
|
strip = false
|
||||||
debug = true
|
debug = true
|
||||||
overflow-checks = true
|
overflow-checks = true
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
incremental = true
|
incremental = true
|
||||||
opt-level = "s"
|
opt-level = 2
|
||||||
|
|
||||||
[profile.dev.build-override]
|
|
||||||
opt-level = 1
|
|
||||||
incremental = true
|
|
||||||
|
|
||||||
[package.metadata.cargo_runner]
|
[package.metadata.cargo_runner]
|
||||||
# The string `$TARGET_FILE` will be replaced with the path from cargo.
|
# The string `$TARGET_FILE` will be replaced with the path from cargo.
|
||||||
@@ -38,13 +35,13 @@ command = [
|
|||||||
partition_table = "partitions.csv"
|
partition_table = "partitions.csv"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "embassy", "esp-idf-svc/native"]
|
default = ["std", "esp-idf-svc/native"]
|
||||||
pio = ["esp-idf-svc/pio"]
|
pio = ["esp-idf-svc/pio"]
|
||||||
std = ["alloc", "esp-idf-svc/binstart", "esp-idf-svc/std"]
|
std = ["alloc", "esp-idf-svc/binstart", "esp-idf-svc/std"]
|
||||||
alloc = ["esp-idf-svc/alloc"]
|
alloc = ["esp-idf-svc/alloc"]
|
||||||
nightly = ["esp-idf-svc/nightly"]
|
nightly = ["esp-idf-svc/nightly"]
|
||||||
experimental = ["esp-idf-svc/experimental"]
|
experimental = ["esp-idf-svc/experimental"]
|
||||||
embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf-svc/embassy-time-driver"]
|
#embassy = ["esp-idf-svc/embassy-sync", "esp-idf-svc/critical-section", "esp-idf-svc/embassy-time-driver"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
#ESP stuff
|
#ESP stuff
|
||||||
@@ -54,7 +51,7 @@ esp-idf-sys = { version = "0.36.1", features = ["binstart", "native"] }
|
|||||||
esp-idf-svc = { version = "0.51.0", default-features = false }
|
esp-idf-svc = { version = "0.51.0", default-features = false }
|
||||||
embedded-hal = "1.0.0"
|
embedded-hal = "1.0.0"
|
||||||
heapless = { version = "0.8", features = ["serde"] }
|
heapless = { version = "0.8", features = ["serde"] }
|
||||||
embedded-hal-bus = { version = "0.2.0", features = ["std"] }
|
embedded-hal-bus = { version = "0.3.0", features = ["std"] }
|
||||||
|
|
||||||
#Hardware additional driver
|
#Hardware additional driver
|
||||||
ds18b20 = "0.1.1"
|
ds18b20 = "0.1.1"
|
||||||
@@ -63,31 +60,33 @@ one-wire-bus = "0.1.1"
|
|||||||
ds323x = "0.6.0"
|
ds323x = "0.6.0"
|
||||||
|
|
||||||
#pure code dependencies
|
#pure code dependencies
|
||||||
log = { version = "0.4", default-features = false }
|
|
||||||
once_cell = "1.19.0"
|
once_cell = "1.19.0"
|
||||||
anyhow = { version = "1.0.75", features = ["std", "backtrace"] }
|
anyhow = { version = "1.0.75", features = ["std", "backtrace"] }
|
||||||
average = { version = "0.14.1" , features = ["std"] }
|
|
||||||
bit_field = "0.10.2"
|
|
||||||
strum = { version = "0.27.0", features = ["derive"] }
|
strum = { version = "0.27.0", features = ["derive"] }
|
||||||
measurements = "0.11.0"
|
measurements = "0.11.0"
|
||||||
schemars = "0.8.16"
|
|
||||||
|
|
||||||
#json
|
#json
|
||||||
serde = { version = "1.0.192", features = ["derive"] }
|
serde = { version = "1.0.192", features = ["derive"] }
|
||||||
serde_json = "1.0.108"
|
serde_json = "1.0.108"
|
||||||
|
|
||||||
#timezone
|
#timezone
|
||||||
chrono = { version = "0.4.23", default-features = false , features = ["iana-time-zone" , "alloc"] }
|
|
||||||
chrono-tz = {version="0.8.0", default-features = false , features = [ "filter-by-regex" ]}
|
chrono = { version = "0.4.23", default-features = false, features = ["iana-time-zone", "alloc", "serde"] }
|
||||||
|
chrono-tz = { version = "0.10.3", default-features = false, features = ["filter-by-regex"] }
|
||||||
eeprom24x = "0.7.2"
|
eeprom24x = "0.7.2"
|
||||||
url = "2.5.3"
|
url = "2.5.3"
|
||||||
crc = "3.2.1"
|
crc = "3.2.1"
|
||||||
bincode = "1.3.3"
|
bincode = "2.0.1"
|
||||||
ringbuffer = "0.15.0"
|
ringbuffer = "0.15.0"
|
||||||
text-template = "0.1.0"
|
text-template = "0.1.0"
|
||||||
strum_macros = "0.27.0"
|
strum_macros = "0.27.0"
|
||||||
esp-ota = { version = "0.2.2", features = ["log"] }
|
esp-ota = { version = "0.2.2", features = ["log"] }
|
||||||
unit-enum = "1.4.1"
|
unit-enum = "1.4.1"
|
||||||
|
pca9535 = { version = "2.0.0", features = ["std"] }
|
||||||
|
ina219 = { version = "0.2.0", features = ["std"] }
|
||||||
|
embedded-storage = "=0.3.1"
|
||||||
|
ekv = "1.0.0"
|
||||||
|
embedded-can = "0.4.1"
|
||||||
|
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
@@ -100,5 +99,5 @@ unit-enum = "1.4.1"
|
|||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cc = "=1.1.30"
|
cc = "=1.1.30"
|
||||||
embuild = { version= "0.32.0", features = ["espidf"]}
|
embuild = { version = "0.32.0", features = ["espidf"] }
|
||||||
vergen = { version = "8.2.6", features = ["build", "git", "gitcl"] }
|
vergen = { version = "8.2.6", features = ["build", "git", "gitcl"] }
|
||||||
|
|||||||
@@ -22,6 +22,22 @@ fn main() {
|
|||||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||||
assert!(output.status.success());
|
assert!(output.status.success());
|
||||||
|
|
||||||
|
// move webpack results to rust webserver src
|
||||||
|
let _ = Command::new("cmd")
|
||||||
|
.arg("/K")
|
||||||
|
.arg("move")
|
||||||
|
.arg("./src_webpack/bundle.js")
|
||||||
|
.arg("./src/webserver")
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
let _ = Command::new("cmd")
|
||||||
|
.arg("/K")
|
||||||
|
.arg("move")
|
||||||
|
.arg("./src_webpack/index.html")
|
||||||
|
.arg("./src/webserver")
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
println!("Assuming build on linux");
|
println!("Assuming build on linux");
|
||||||
@@ -34,6 +50,18 @@ fn main() {
|
|||||||
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
|
||||||
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
|
||||||
assert!(output.status.success());
|
assert!(output.status.success());
|
||||||
|
|
||||||
|
// move webpack results to rust webserver src
|
||||||
|
let _ = Command::new("mv")
|
||||||
|
.arg("./src_webpack/bundle.js")
|
||||||
|
.arg("./src/webserver")
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
let _ = Command::new("mv")
|
||||||
|
.arg("./src_webpack/index.html")
|
||||||
|
.arg("./src/webserver")
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
rust/espflash.toml
Normal file
5
rust/espflash.toml
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
partition_table = "partitions.csv"
|
||||||
|
[connection]
|
||||||
|
serial = "/dev/ttyACM0"
|
||||||
|
[flash]
|
||||||
|
size = "16MB"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
nvs, data, nvs, , 16k,
|
nvs, data, nvs, , 16k,
|
||||||
otadata, data, ota, , 8k,
|
otadata, data, ota, , 8k,
|
||||||
phy_init, data, phy, , 4k,
|
phy_init, data, phy, , 4k,
|
||||||
ota_0, app, ota_0, , 5632k,
|
ota_0, app, ota_0, , 3968k,
|
||||||
ota_1, app, ota_1, , 5632k,
|
ota_1, app, ota_1, , 3968k,
|
||||||
storage, data, spiffs, , 5000k,
|
storage, data, spiffs, , 8M,
|
||||||
|
|||||||
|
@@ -1,8 +1,7 @@
|
|||||||
use std::str::FromStr;
|
use crate::hal::PLANT_COUNT;
|
||||||
|
use crate::plant_state::PlantWateringMode;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::str::FromStr;
|
||||||
use crate::PLANT_COUNT;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -12,6 +11,7 @@ pub struct NetworkConfig {
|
|||||||
pub password: Option<heapless::String<64>>,
|
pub password: Option<heapless::String<64>>,
|
||||||
pub mqtt_url: Option<heapless::String<128>>,
|
pub mqtt_url: Option<heapless::String<128>>,
|
||||||
pub base_topic: Option<heapless::String<64>>,
|
pub base_topic: Option<heapless::String<64>>,
|
||||||
|
pub max_wait: u32,
|
||||||
}
|
}
|
||||||
impl Default for NetworkConfig {
|
impl Default for NetworkConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@@ -21,6 +21,7 @@ impl Default for NetworkConfig {
|
|||||||
password: None,
|
password: None,
|
||||||
mqtt_url: None,
|
mqtt_url: None,
|
||||||
base_topic: None,
|
base_topic: None,
|
||||||
|
max_wait: 10000,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +34,7 @@ pub struct NightLampConfig {
|
|||||||
pub night_lamp_hour_end: u8,
|
pub night_lamp_hour_end: u8,
|
||||||
pub night_lamp_only_when_dark: bool,
|
pub night_lamp_only_when_dark: bool,
|
||||||
pub low_soc_cutoff: u8,
|
pub low_soc_cutoff: u8,
|
||||||
pub low_soc_restore: u8
|
pub low_soc_restore: u8,
|
||||||
}
|
}
|
||||||
impl Default for NightLampConfig {
|
impl Default for NightLampConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@@ -43,7 +44,7 @@ impl Default for NightLampConfig {
|
|||||||
night_lamp_hour_end: 2,
|
night_lamp_hour_end: 2,
|
||||||
night_lamp_only_when_dark: true,
|
night_lamp_only_when_dark: true,
|
||||||
low_soc_cutoff: 30,
|
low_soc_cutoff: 30,
|
||||||
low_soc_restore: 50
|
low_soc_restore: 50,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,6 +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
|
||||||
}
|
}
|
||||||
impl Default for TankConfig {
|
impl Default for TankConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@@ -67,50 +69,81 @@ impl Default for TankConfig {
|
|||||||
tank_warn_percent: 40,
|
tank_warn_percent: 40,
|
||||||
tank_empty_percent: 5,
|
tank_empty_percent: 5,
|
||||||
tank_full_percent: 95,
|
tank_full_percent: 95,
|
||||||
|
ml_per_pulse: 0.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
|
||||||
|
pub enum BatteryBoardVersion {
|
||||||
|
#[default]
|
||||||
|
Disabled,
|
||||||
|
BQ34Z100G1,
|
||||||
|
WchI2cSlave,
|
||||||
|
}
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
|
||||||
|
pub enum BoardVersion {
|
||||||
|
#[default]
|
||||||
|
INITIAL,
|
||||||
|
V3,
|
||||||
|
V4,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
|
||||||
|
pub struct BoardHardware {
|
||||||
|
pub board: BoardVersion,
|
||||||
|
pub battery: BatteryBoardVersion,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct PlantControllerConfig {
|
pub struct PlantControllerConfig {
|
||||||
|
pub hardware: BoardHardware,
|
||||||
pub network: NetworkConfig,
|
pub network: NetworkConfig,
|
||||||
pub tank: TankConfig,
|
pub tank: TankConfig,
|
||||||
pub night_lamp: NightLampConfig,
|
pub night_lamp: NightLampConfig,
|
||||||
pub plants: [PlantConfig; PLANT_COUNT],
|
pub plants: [PlantConfig; PLANT_COUNT],
|
||||||
|
pub timezone: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub struct PlantConfig {
|
pub struct PlantConfig {
|
||||||
pub mode: Mode,
|
pub mode: PlantWateringMode,
|
||||||
pub target_moisture: u8,
|
pub target_moisture: f32,
|
||||||
pub pump_time_s: u16,
|
pub pump_time_s: u16,
|
||||||
|
pub pump_limit_ml: u16,
|
||||||
pub pump_cooldown_min: u16,
|
pub pump_cooldown_min: u16,
|
||||||
pub pump_hour_start: u8,
|
pub pump_hour_start: u8,
|
||||||
pub pump_hour_end: u8,
|
pub pump_hour_end: u8,
|
||||||
|
pub sensor_a: bool,
|
||||||
pub sensor_b: bool,
|
pub sensor_b: bool,
|
||||||
pub max_consecutive_pump_count: u8,
|
pub max_consecutive_pump_count: u8,
|
||||||
|
pub moisture_sensor_min_frequency: Option<f32>, // Optional min frequency
|
||||||
|
pub moisture_sensor_max_frequency: Option<f32>, // Optional max frequency
|
||||||
|
pub min_pump_current_ma: u16,
|
||||||
|
pub max_pump_current_ma: u16,
|
||||||
|
pub ignore_current_error: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PlantConfig {
|
impl Default for PlantConfig {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
mode: Mode::OFF,
|
mode: PlantWateringMode::OFF,
|
||||||
target_moisture: 40,
|
target_moisture: 40.,
|
||||||
pump_time_s: 30,
|
pump_time_s: 30,
|
||||||
|
pump_limit_ml: 5000,
|
||||||
pump_cooldown_min: 60,
|
pump_cooldown_min: 60,
|
||||||
pump_hour_start: 9,
|
pump_hour_start: 9,
|
||||||
pump_hour_end: 20,
|
pump_hour_end: 20,
|
||||||
|
sensor_a: true,
|
||||||
sensor_b: false,
|
sensor_b: false,
|
||||||
max_consecutive_pump_count: 10,
|
max_consecutive_pump_count: 10,
|
||||||
|
moisture_sensor_min_frequency: None, // No override by default
|
||||||
|
moisture_sensor_max_frequency: None, // No override by default
|
||||||
|
min_pump_current_ma: 10,
|
||||||
|
max_pump_current_ma: 3000,
|
||||||
|
ignore_current_error: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
|
|
||||||
pub enum Mode {
|
|
||||||
OFF,
|
|
||||||
TargetMoisture,
|
|
||||||
TimerOnly,
|
|
||||||
TimerAndDeadzone,
|
|
||||||
}
|
|
||||||
|
|||||||
214
rust/src/hal/battery.rs
Normal file
214
rust/src/hal/battery.rs
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
use anyhow::anyhow;
|
||||||
|
use bq34z100::{Bq34Z100Error, Bq34z100g1, Bq34z100g1Driver};
|
||||||
|
use embedded_hal_bus::i2c::MutexDevice;
|
||||||
|
use esp_idf_hal::delay::Delay;
|
||||||
|
use esp_idf_hal::i2c::{I2cDriver, I2cError};
|
||||||
|
use measurements::Temperature;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
pub trait BatteryInteraction {
|
||||||
|
fn state_charge_percent(&mut self) -> Result<f32, BatteryError>;
|
||||||
|
fn remaining_milli_ampere_hour(&mut self) -> Result<u16, BatteryError>;
|
||||||
|
fn max_milli_ampere_hour(&mut self) -> Result<u16, BatteryError>;
|
||||||
|
fn design_milli_ampere_hour(&mut self) -> Result<u16, BatteryError>;
|
||||||
|
fn voltage_milli_volt(&mut self) -> Result<u16, BatteryError>;
|
||||||
|
fn average_current_milli_ampere(&mut self) -> Result<i16, BatteryError>;
|
||||||
|
fn cycle_count(&mut self) -> Result<u16, BatteryError>;
|
||||||
|
fn state_health_percent(&mut self) -> Result<u16, BatteryError>;
|
||||||
|
fn bat_temperature(&mut self) -> Result<u16, BatteryError>;
|
||||||
|
fn get_battery_state(&mut self) -> Result<BatteryState, BatteryError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct BatteryInfo {
|
||||||
|
pub voltage_milli_volt: u16,
|
||||||
|
pub average_current_milli_ampere: i16,
|
||||||
|
pub cycle_count: u16,
|
||||||
|
pub design_milli_ampere_hour: u16,
|
||||||
|
pub remaining_milli_ampere_hour: u16,
|
||||||
|
pub state_of_charge: f32,
|
||||||
|
pub state_of_health: u16,
|
||||||
|
pub temperature: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub enum BatteryError {
|
||||||
|
NoBatteryMonitor,
|
||||||
|
CommunicationError(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Bq34Z100Error<esp_idf_hal::i2c::I2cError>> for BatteryError {
|
||||||
|
fn from(err: Bq34Z100Error<esp_idf_hal::i2c::I2cError>) -> Self {
|
||||||
|
BatteryError::CommunicationError(
|
||||||
|
anyhow!("failed to communicate with battery monitor: {:?}", err).to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub enum BatteryState {
|
||||||
|
Unknown,
|
||||||
|
Info(BatteryInfo),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If no battery monitor is installed this implementation will be used
|
||||||
|
pub struct NoBatteryMonitor {}
|
||||||
|
|
||||||
|
impl BatteryInteraction for NoBatteryMonitor {
|
||||||
|
fn state_charge_percent(&mut self) -> Result<f32, BatteryError> {
|
||||||
|
Err(BatteryError::NoBatteryMonitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remaining_milli_ampere_hour(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Err(BatteryError::NoBatteryMonitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_milli_ampere_hour(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Err(BatteryError::NoBatteryMonitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn design_milli_ampere_hour(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Err(BatteryError::NoBatteryMonitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn voltage_milli_volt(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Err(BatteryError::NoBatteryMonitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn average_current_milli_ampere(&mut self) -> Result<i16, BatteryError> {
|
||||||
|
Err(BatteryError::NoBatteryMonitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cycle_count(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Err(BatteryError::NoBatteryMonitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state_health_percent(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Err(BatteryError::NoBatteryMonitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bat_temperature(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Err(BatteryError::NoBatteryMonitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_battery_state(&mut self) -> Result<BatteryState, BatteryError> {
|
||||||
|
Ok(BatteryState::Unknown)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO implement this battery monitor kind once controller is complete
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct WchI2cSlave {}
|
||||||
|
|
||||||
|
pub struct BQ34Z100G1<'a> {
|
||||||
|
pub battery_driver: Bq34z100g1Driver<MutexDevice<'a, I2cDriver<'a>>, Delay>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BatteryInteraction for BQ34Z100G1<'_> {
|
||||||
|
fn state_charge_percent(&mut self) -> Result<f32, BatteryError> {
|
||||||
|
Ok(self.battery_driver.state_of_charge().map(f32::from)?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remaining_milli_ampere_hour(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Ok(self.battery_driver.remaining_capacity()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_milli_ampere_hour(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Ok(self.battery_driver.full_charge_capacity()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn design_milli_ampere_hour(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Ok(self.battery_driver.design_capacity()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn voltage_milli_volt(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Ok(self.battery_driver.voltage()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn average_current_milli_ampere(&mut self) -> Result<i16, BatteryError> {
|
||||||
|
Ok(self.battery_driver.average_current()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cycle_count(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Ok(self.battery_driver.cycle_count()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state_health_percent(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Ok(self.battery_driver.state_of_health()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bat_temperature(&mut self) -> Result<u16, BatteryError> {
|
||||||
|
Ok(self.battery_driver.temperature()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_battery_state(&mut self) -> Result<BatteryState, BatteryError> {
|
||||||
|
Ok(BatteryState::Info(BatteryInfo {
|
||||||
|
voltage_milli_volt: self.voltage_milli_volt()?,
|
||||||
|
average_current_milli_ampere: self.average_current_milli_ampere()?,
|
||||||
|
cycle_count: self.cycle_count()?,
|
||||||
|
design_milli_ampere_hour: self.design_milli_ampere_hour()?,
|
||||||
|
remaining_milli_ampere_hour: self.remaining_milli_ampere_hour()?,
|
||||||
|
state_of_charge: self.state_charge_percent()?,
|
||||||
|
state_of_health: self.state_health_percent()?,
|
||||||
|
temperature: self.bat_temperature()?,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_battery_bq34z100(
|
||||||
|
battery_driver: &mut Bq34z100g1Driver<MutexDevice<I2cDriver<'_>>, Delay>,
|
||||||
|
) -> anyhow::Result<(), Bq34Z100Error<I2cError>> {
|
||||||
|
println!("Try communicating with battery");
|
||||||
|
let fwversion = battery_driver.fw_version().unwrap_or_else(|e| {
|
||||||
|
println!("Firmware {:?}", e);
|
||||||
|
0
|
||||||
|
});
|
||||||
|
println!("fw version is {}", fwversion);
|
||||||
|
|
||||||
|
let design_capacity = battery_driver.design_capacity().unwrap_or_else(|e| {
|
||||||
|
println!("Design capacity {:?}", e);
|
||||||
|
0
|
||||||
|
});
|
||||||
|
println!("Design Capacity {}", design_capacity);
|
||||||
|
if design_capacity == 1000 {
|
||||||
|
println!("Still stock configuring battery, readouts are likely to be wrong!");
|
||||||
|
}
|
||||||
|
|
||||||
|
let flags = battery_driver.get_flags_decoded()?;
|
||||||
|
println!("Flags {:?}", flags);
|
||||||
|
|
||||||
|
let chem_id = battery_driver.chem_id().unwrap_or_else(|e| {
|
||||||
|
println!("Chemid {:?}", e);
|
||||||
|
0
|
||||||
|
});
|
||||||
|
|
||||||
|
let bat_temp = battery_driver.internal_temperature().unwrap_or_else(|e| {
|
||||||
|
println!("Bat Temp {:?}", e);
|
||||||
|
0
|
||||||
|
});
|
||||||
|
let temp_c = Temperature::from_kelvin(bat_temp as f64 / 10_f64).as_celsius();
|
||||||
|
let voltage = battery_driver.voltage().unwrap_or_else(|e| {
|
||||||
|
println!("Bat volt {:?}", e);
|
||||||
|
0
|
||||||
|
});
|
||||||
|
let current = battery_driver.current().unwrap_or_else(|e| {
|
||||||
|
println!("Bat current {:?}", e);
|
||||||
|
0
|
||||||
|
});
|
||||||
|
let state = battery_driver.state_of_charge().unwrap_or_else(|e| {
|
||||||
|
println!("Bat Soc {:?}", e);
|
||||||
|
0
|
||||||
|
});
|
||||||
|
let charge_voltage = battery_driver.charge_voltage().unwrap_or_else(|e| {
|
||||||
|
println!("Bat Charge Volt {:?}", e);
|
||||||
|
0
|
||||||
|
});
|
||||||
|
let charge_current = battery_driver.charge_current().unwrap_or_else(|e| {
|
||||||
|
println!("Bat Charge Current {:?}", e);
|
||||||
|
0
|
||||||
|
});
|
||||||
|
println!("ChemId: {} Current voltage {} and current {} with charge {}% and temp {} CVolt: {} CCur {}", chem_id, voltage, current, state, temp_c, charge_voltage, charge_current);
|
||||||
|
let _ = battery_driver.unsealed();
|
||||||
|
let _ = battery_driver.it_enable();
|
||||||
|
anyhow::Result::Ok(())
|
||||||
|
}
|
||||||
600
rust/src/hal/esp.rs
Normal file
600
rust/src/hal/esp.rs
Normal file
@@ -0,0 +1,600 @@
|
|||||||
|
use crate::config::{NetworkConfig, PlantControllerConfig};
|
||||||
|
use crate::hal::PLANT_COUNT;
|
||||||
|
use crate::log::{log, LogMessage};
|
||||||
|
use crate::STAY_ALIVE;
|
||||||
|
use anyhow::{anyhow, bail, Context};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use embedded_svc::ipv4::IpInfo;
|
||||||
|
use embedded_svc::mqtt::client::QoS::{AtLeastOnce, ExactlyOnce};
|
||||||
|
use embedded_svc::wifi::{
|
||||||
|
AccessPointConfiguration, AccessPointInfo, AuthMethod, ClientConfiguration, Configuration,
|
||||||
|
};
|
||||||
|
use esp_idf_hal::delay::Delay;
|
||||||
|
use esp_idf_hal::gpio::{Level, PinDriver};
|
||||||
|
use esp_idf_svc::mqtt::client::{EspMqttClient, LwtConfiguration, MqttClientConfiguration};
|
||||||
|
use esp_idf_svc::sntp;
|
||||||
|
use esp_idf_svc::sntp::SyncStatus;
|
||||||
|
use esp_idf_svc::systime::EspSystemTime;
|
||||||
|
use esp_idf_svc::wifi::config::{ScanConfig, ScanType};
|
||||||
|
use esp_idf_svc::wifi::EspWifi;
|
||||||
|
use esp_idf_sys::{esp_spiffs_info, vTaskDelay};
|
||||||
|
use serde::Serialize;
|
||||||
|
use std::ffi::CString;
|
||||||
|
use std::fs;
|
||||||
|
use std::fs::File;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::result::Result::Ok as OkStd;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
#[link_section = ".rtc.data"]
|
||||||
|
static mut LAST_WATERING_TIMESTAMP: [i64; PLANT_COUNT] = [0; PLANT_COUNT];
|
||||||
|
#[link_section = ".rtc.data"]
|
||||||
|
static mut CONSECUTIVE_WATERING_PLANT: [u32; PLANT_COUNT] = [0; PLANT_COUNT];
|
||||||
|
#[link_section = ".rtc.data"]
|
||||||
|
static mut LOW_VOLTAGE_DETECTED: bool = false;
|
||||||
|
#[link_section = ".rtc.data"]
|
||||||
|
static mut RESTART_TO_CONF: bool = false;
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug)]
|
||||||
|
pub struct FileInfo {
|
||||||
|
filename: String,
|
||||||
|
size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug)]
|
||||||
|
pub struct FileList {
|
||||||
|
total: usize,
|
||||||
|
used: usize,
|
||||||
|
files: Vec<FileInfo>,
|
||||||
|
file_system_corrupt: Option<String>,
|
||||||
|
iter_error: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FileSystemSizeInfo {
|
||||||
|
pub total_size: usize,
|
||||||
|
pub used_size: usize,
|
||||||
|
pub free_size: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MqttClient<'a> {
|
||||||
|
mqtt_client: EspMqttClient<'a>,
|
||||||
|
base_topic: heapless::String<64>,
|
||||||
|
}
|
||||||
|
pub struct Esp<'a> {
|
||||||
|
pub(crate) mqtt_client: Option<MqttClient<'a>>,
|
||||||
|
pub(crate) wifi_driver: EspWifi<'a>,
|
||||||
|
pub(crate) boot_button: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, esp_idf_hal::gpio::Input>,
|
||||||
|
pub(crate) delay: Delay,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Esp<'_> {
|
||||||
|
const SPIFFS_PARTITION_NAME: &'static str = "storage";
|
||||||
|
const CONFIG_FILE: &'static str = "/spiffs/config.cfg";
|
||||||
|
const BASE_PATH: &'static str = "/spiffs";
|
||||||
|
|
||||||
|
pub(crate) fn mode_override_pressed(&mut self) -> bool {
|
||||||
|
self.boot_button.get_level() == Level::Low
|
||||||
|
}
|
||||||
|
pub(crate) fn sntp(&mut self, max_wait_ms: u32) -> anyhow::Result<DateTime<Utc>> {
|
||||||
|
let sntp = sntp::EspSntp::new_default()?;
|
||||||
|
let mut counter = 0;
|
||||||
|
while sntp.get_sync_status() != SyncStatus::Completed {
|
||||||
|
self.delay.delay_ms(100);
|
||||||
|
counter += 100;
|
||||||
|
if counter > max_wait_ms {
|
||||||
|
bail!("Reached sntp timeout, aborting")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.time()
|
||||||
|
}
|
||||||
|
pub(crate) fn time(&mut self) -> anyhow::Result<DateTime<Utc>> {
|
||||||
|
let time = EspSystemTime {}.now().as_millis();
|
||||||
|
let smaller_time = time as i64;
|
||||||
|
let local_time = DateTime::from_timestamp_millis(smaller_time)
|
||||||
|
.ok_or(anyhow!("could not convert timestamp"))?;
|
||||||
|
anyhow::Ok(local_time)
|
||||||
|
}
|
||||||
|
pub(crate) fn wifi_scan(&mut self) -> anyhow::Result<Vec<AccessPointInfo>> {
|
||||||
|
self.wifi_driver.start_scan(
|
||||||
|
&ScanConfig {
|
||||||
|
scan_type: ScanType::Passive(Duration::from_secs(5)),
|
||||||
|
show_hidden: false,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
)?;
|
||||||
|
anyhow::Ok(self.wifi_driver.get_scan_result()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn last_pump_time(&self, plant: usize) -> Option<DateTime<Utc>> {
|
||||||
|
let ts = unsafe { LAST_WATERING_TIMESTAMP }[plant];
|
||||||
|
DateTime::from_timestamp_millis(ts)
|
||||||
|
}
|
||||||
|
pub(crate) fn store_last_pump_time(&mut self, plant: usize, time: DateTime<Utc>) {
|
||||||
|
unsafe {
|
||||||
|
LAST_WATERING_TIMESTAMP[plant] = time.timestamp_millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) fn set_low_voltage_in_cycle(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
LOW_VOLTAGE_DETECTED = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) fn clear_low_voltage_in_cycle(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
LOW_VOLTAGE_DETECTED = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn low_voltage_in_cycle(&mut self) -> bool {
|
||||||
|
unsafe { LOW_VOLTAGE_DETECTED }
|
||||||
|
}
|
||||||
|
pub(crate) fn store_consecutive_pump_count(&mut self, plant: usize, count: u32) {
|
||||||
|
unsafe {
|
||||||
|
CONSECUTIVE_WATERING_PLANT[plant] = count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) fn consecutive_pump_count(&mut self, plant: usize) -> u32 {
|
||||||
|
unsafe { CONSECUTIVE_WATERING_PLANT[plant] }
|
||||||
|
}
|
||||||
|
pub(crate) fn get_restart_to_conf(&mut self) -> bool {
|
||||||
|
unsafe { RESTART_TO_CONF }
|
||||||
|
}
|
||||||
|
pub(crate) fn set_restart_to_conf(&mut self, to_conf: bool) {
|
||||||
|
unsafe {
|
||||||
|
RESTART_TO_CONF = to_conf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn wifi_ap(&mut self) -> anyhow::Result<()> {
|
||||||
|
let ssid = match self.load_config() {
|
||||||
|
Ok(config) => config.network.ap_ssid.clone(),
|
||||||
|
Err(_) => heapless::String::from_str("PlantCtrl Emergency Mode").unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let apconfig = AccessPointConfiguration {
|
||||||
|
ssid,
|
||||||
|
auth_method: AuthMethod::None,
|
||||||
|
ssid_hidden: false,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
self.wifi_driver
|
||||||
|
.set_configuration(&Configuration::AccessPoint(apconfig))?;
|
||||||
|
self.wifi_driver.start()?;
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn wifi(&mut self, network_config: &NetworkConfig) -> anyhow::Result<IpInfo> {
|
||||||
|
let ssid = network_config
|
||||||
|
.ssid
|
||||||
|
.clone()
|
||||||
|
.ok_or(anyhow!("No ssid configured"))?;
|
||||||
|
let password = network_config.password.clone();
|
||||||
|
let max_wait = network_config.max_wait;
|
||||||
|
|
||||||
|
match password {
|
||||||
|
Some(pw) => {
|
||||||
|
//TODO expect error due to invalid pw or similar! //call this during configuration and check if works, revert to config mode if not
|
||||||
|
self.wifi_driver.set_configuration(&Configuration::Client(
|
||||||
|
ClientConfiguration {
|
||||||
|
ssid,
|
||||||
|
password: pw,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
))?;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
self.wifi_driver.set_configuration(&Configuration::Client(
|
||||||
|
ClientConfiguration {
|
||||||
|
ssid,
|
||||||
|
auth_method: AuthMethod::None,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.wifi_driver.start()?;
|
||||||
|
self.wifi_driver.connect()?;
|
||||||
|
|
||||||
|
let delay = Delay::new_default();
|
||||||
|
let mut counter = 0_u32;
|
||||||
|
while !self.wifi_driver.is_connected()? {
|
||||||
|
delay.delay_ms(250);
|
||||||
|
counter += 250;
|
||||||
|
if counter > max_wait {
|
||||||
|
//ignore these errors, Wi-Fi will not be used this
|
||||||
|
self.wifi_driver.disconnect().unwrap_or(());
|
||||||
|
self.wifi_driver.stop().unwrap_or(());
|
||||||
|
bail!("Did not manage wifi connection within timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("Should be connected now, waiting for link to be up");
|
||||||
|
|
||||||
|
while !self.wifi_driver.is_up()? {
|
||||||
|
delay.delay_ms(250);
|
||||||
|
counter += 250;
|
||||||
|
if counter > max_wait {
|
||||||
|
//ignore these errors, Wi-Fi will not be used this
|
||||||
|
self.wifi_driver.disconnect().unwrap_or(());
|
||||||
|
self.wifi_driver.stop().unwrap_or(());
|
||||||
|
bail!("Did not manage wifi connection within timeout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//update freertos registers ;)
|
||||||
|
let address = self.wifi_driver.sta_netif().get_ip_info()?;
|
||||||
|
log(LogMessage::WifiInfo, 0, 0, "", &format!("{address:?}"));
|
||||||
|
anyhow::Ok(address)
|
||||||
|
}
|
||||||
|
pub(crate) fn load_config(&mut self) -> anyhow::Result<PlantControllerConfig> {
|
||||||
|
let cfg = File::open(Self::CONFIG_FILE)?;
|
||||||
|
let config: PlantControllerConfig = serde_json::from_reader(cfg)?;
|
||||||
|
anyhow::Ok(config)
|
||||||
|
}
|
||||||
|
pub(crate) fn save_config(&mut self, config: &PlantControllerConfig) -> anyhow::Result<()> {
|
||||||
|
let mut cfg = File::create(Self::CONFIG_FILE)?;
|
||||||
|
serde_json::to_writer(&mut cfg, &config)?;
|
||||||
|
println!("Wrote config config {:?}", config);
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
pub(crate) fn mount_file_system(&mut self) -> anyhow::Result<()> {
|
||||||
|
log(LogMessage::MountingFilesystem, 0, 0, "", "");
|
||||||
|
let base_path = CString::new("/spiffs")?;
|
||||||
|
let storage = CString::new(Self::SPIFFS_PARTITION_NAME)?;
|
||||||
|
let conf = esp_idf_sys::esp_vfs_spiffs_conf_t {
|
||||||
|
base_path: base_path.as_ptr(),
|
||||||
|
partition_label: storage.as_ptr(),
|
||||||
|
max_files: 5,
|
||||||
|
format_if_mount_failed: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
esp_idf_sys::esp!(esp_idf_sys::esp_vfs_spiffs_register(&conf))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let free_space = self.file_system_size()?;
|
||||||
|
log(
|
||||||
|
LogMessage::FilesystemMount,
|
||||||
|
free_space.free_size as u32,
|
||||||
|
free_space.total_size as u32,
|
||||||
|
&free_space.used_size.to_string(),
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
fn file_system_size(&mut self) -> anyhow::Result<FileSystemSizeInfo> {
|
||||||
|
let storage = CString::new(Self::SPIFFS_PARTITION_NAME)?;
|
||||||
|
let mut total_size = 0;
|
||||||
|
let mut used_size = 0;
|
||||||
|
unsafe {
|
||||||
|
esp_idf_sys::esp!(esp_spiffs_info(
|
||||||
|
storage.as_ptr(),
|
||||||
|
&mut total_size,
|
||||||
|
&mut used_size
|
||||||
|
))?;
|
||||||
|
}
|
||||||
|
anyhow::Ok(FileSystemSizeInfo {
|
||||||
|
total_size,
|
||||||
|
used_size,
|
||||||
|
free_size: total_size - used_size,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn list_files(&self) -> FileList {
|
||||||
|
let storage = CString::new(Self::SPIFFS_PARTITION_NAME).unwrap();
|
||||||
|
|
||||||
|
let mut file_system_corrupt = None;
|
||||||
|
|
||||||
|
let mut iter_error = None;
|
||||||
|
let mut result = Vec::new();
|
||||||
|
|
||||||
|
let filepath = Path::new(Self::BASE_PATH);
|
||||||
|
let read_dir = fs::read_dir(filepath);
|
||||||
|
match read_dir {
|
||||||
|
OkStd(read_dir) => {
|
||||||
|
for item in read_dir {
|
||||||
|
match item {
|
||||||
|
OkStd(file) => {
|
||||||
|
let f = FileInfo {
|
||||||
|
filename: file.file_name().into_string().unwrap(),
|
||||||
|
size: file.metadata().map(|it| it.len()).unwrap_or_default()
|
||||||
|
as usize,
|
||||||
|
};
|
||||||
|
result.push(f);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
iter_error = Some(format!("{err:?}"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
file_system_corrupt = Some(format!("{err:?}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let mut total: usize = 0;
|
||||||
|
let mut used: usize = 0;
|
||||||
|
unsafe {
|
||||||
|
esp_spiffs_info(storage.as_ptr(), &mut total, &mut used);
|
||||||
|
}
|
||||||
|
|
||||||
|
FileList {
|
||||||
|
total,
|
||||||
|
used,
|
||||||
|
file_system_corrupt,
|
||||||
|
files: result,
|
||||||
|
iter_error,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) fn delete_file(&self, filename: &str) -> anyhow::Result<()> {
|
||||||
|
let filepath = Path::new(Self::BASE_PATH).join(Path::new(filename));
|
||||||
|
match fs::remove_file(filepath) {
|
||||||
|
OkStd(_) => anyhow::Ok(()),
|
||||||
|
Err(err) => {
|
||||||
|
bail!(format!("{err:?}"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) fn get_file_handle(&self, filename: &str, write: bool) -> anyhow::Result<File> {
|
||||||
|
let filepath = Path::new(Self::BASE_PATH).join(Path::new(filename));
|
||||||
|
anyhow::Ok(if write {
|
||||||
|
File::create(filepath)?
|
||||||
|
} else {
|
||||||
|
File::open(filepath)?
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn init_rtc_deepsleep_memory(&self, init_rtc_store: bool, to_config_mode: bool) {
|
||||||
|
if init_rtc_store {
|
||||||
|
unsafe {
|
||||||
|
LAST_WATERING_TIMESTAMP = [0; PLANT_COUNT];
|
||||||
|
CONSECUTIVE_WATERING_PLANT = [0; PLANT_COUNT];
|
||||||
|
LOW_VOLTAGE_DETECTED = false;
|
||||||
|
crate::log::init();
|
||||||
|
RESTART_TO_CONF = to_config_mode;
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
unsafe {
|
||||||
|
if to_config_mode {
|
||||||
|
RESTART_TO_CONF = true;
|
||||||
|
}
|
||||||
|
log(
|
||||||
|
LogMessage::RestartToConfig,
|
||||||
|
RESTART_TO_CONF as u32,
|
||||||
|
0,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
log(
|
||||||
|
LogMessage::LowVoltage,
|
||||||
|
LOW_VOLTAGE_DETECTED as u32,
|
||||||
|
0,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
for i in 0..PLANT_COUNT {
|
||||||
|
println!(
|
||||||
|
"LAST_WATERING_TIMESTAMP[{}] = UTC {}",
|
||||||
|
i, LAST_WATERING_TIMESTAMP[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
for i in 0..PLANT_COUNT {
|
||||||
|
println!(
|
||||||
|
"CONSECUTIVE_WATERING_PLANT[{}] = {}",
|
||||||
|
i, CONSECUTIVE_WATERING_PLANT[i]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn mqtt(&mut self, network_config: &NetworkConfig) -> anyhow::Result<()> {
|
||||||
|
let base_topic = network_config
|
||||||
|
.base_topic
|
||||||
|
.as_ref()
|
||||||
|
.context("missing base topic")?;
|
||||||
|
if base_topic.is_empty() {
|
||||||
|
bail!("Mqtt base_topic was empty")
|
||||||
|
}
|
||||||
|
let base_topic_copy = base_topic.clone();
|
||||||
|
let mqtt_url = network_config
|
||||||
|
.mqtt_url
|
||||||
|
.as_ref()
|
||||||
|
.context("missing mqtt url")?;
|
||||||
|
if mqtt_url.is_empty() {
|
||||||
|
bail!("Mqtt url was empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
let last_will_topic = format!("{}/state", base_topic);
|
||||||
|
let mqtt_client_config = MqttClientConfiguration {
|
||||||
|
lwt: Some(LwtConfiguration {
|
||||||
|
topic: &last_will_topic,
|
||||||
|
payload: "lost".as_bytes(),
|
||||||
|
qos: AtLeastOnce,
|
||||||
|
retain: true,
|
||||||
|
}),
|
||||||
|
client_id: Some("plantctrl"),
|
||||||
|
keep_alive_interval: Some(Duration::from_secs(60 * 60 * 2)),
|
||||||
|
//room for improvement
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mqtt_connected_event_received = Arc::new(AtomicBool::new(false));
|
||||||
|
let mqtt_connected_event_ok = Arc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
|
let round_trip_ok = Arc::new(AtomicBool::new(false));
|
||||||
|
let round_trip_topic = format!("{}/internal/roundtrip", base_topic);
|
||||||
|
let stay_alive_topic = format!("{}/stay_alive", base_topic);
|
||||||
|
log(LogMessage::StayAlive, 0, 0, "", &stay_alive_topic);
|
||||||
|
|
||||||
|
let mqtt_connected_event_received_copy = mqtt_connected_event_received.clone();
|
||||||
|
let mqtt_connected_event_ok_copy = mqtt_connected_event_ok.clone();
|
||||||
|
let stay_alive_topic_copy = stay_alive_topic.clone();
|
||||||
|
let round_trip_topic_copy = round_trip_topic.clone();
|
||||||
|
let round_trip_ok_copy = round_trip_ok.clone();
|
||||||
|
let client_id = mqtt_client_config.client_id.unwrap_or("not set");
|
||||||
|
log(LogMessage::MqttInfo, 0, 0, client_id, mqtt_url);
|
||||||
|
let mut client = EspMqttClient::new_cb(mqtt_url, &mqtt_client_config, move |event| {
|
||||||
|
let payload = event.payload();
|
||||||
|
match payload {
|
||||||
|
embedded_svc::mqtt::client::EventPayload::Received {
|
||||||
|
id: _,
|
||||||
|
topic,
|
||||||
|
data,
|
||||||
|
details: _,
|
||||||
|
} => {
|
||||||
|
let data = String::from_utf8_lossy(data);
|
||||||
|
if let Some(topic) = topic {
|
||||||
|
//todo use enums
|
||||||
|
if topic.eq(round_trip_topic_copy.as_str()) {
|
||||||
|
round_trip_ok_copy.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
} else if topic.eq(stay_alive_topic_copy.as_str()) {
|
||||||
|
let value =
|
||||||
|
data.eq_ignore_ascii_case("true") || data.eq_ignore_ascii_case("1");
|
||||||
|
log(LogMessage::MqttStayAliveRec, 0, 0, &data, "");
|
||||||
|
STAY_ALIVE.store(value, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
} else {
|
||||||
|
log(LogMessage::UnknownTopic, 0, 0, "", topic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
esp_idf_svc::mqtt::client::EventPayload::Connected(_) => {
|
||||||
|
mqtt_connected_event_received_copy
|
||||||
|
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
mqtt_connected_event_ok_copy.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
println!("Mqtt connected");
|
||||||
|
}
|
||||||
|
esp_idf_svc::mqtt::client::EventPayload::Disconnected => {
|
||||||
|
mqtt_connected_event_received_copy
|
||||||
|
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
mqtt_connected_event_ok_copy.store(false, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
println!("Mqtt disconnected");
|
||||||
|
}
|
||||||
|
esp_idf_svc::mqtt::client::EventPayload::Error(esp_error) => {
|
||||||
|
println!("EspMqttError reported {:?}", esp_error);
|
||||||
|
mqtt_connected_event_received_copy
|
||||||
|
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
mqtt_connected_event_ok_copy.store(false, std::sync::atomic::Ordering::Relaxed);
|
||||||
|
println!("Mqtt error");
|
||||||
|
}
|
||||||
|
esp_idf_svc::mqtt::client::EventPayload::BeforeConnect => {
|
||||||
|
println!("Mqtt before connect")
|
||||||
|
}
|
||||||
|
esp_idf_svc::mqtt::client::EventPayload::Subscribed(_) => {
|
||||||
|
println!("Mqtt subscribed")
|
||||||
|
}
|
||||||
|
esp_idf_svc::mqtt::client::EventPayload::Unsubscribed(_) => {
|
||||||
|
println!("Mqtt unsubscribed")
|
||||||
|
}
|
||||||
|
esp_idf_svc::mqtt::client::EventPayload::Published(_) => {
|
||||||
|
println!("Mqtt published")
|
||||||
|
}
|
||||||
|
esp_idf_svc::mqtt::client::EventPayload::Deleted(_) => {
|
||||||
|
println!("Mqtt deleted")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut wait_for_connections_event = 0;
|
||||||
|
while wait_for_connections_event < 100 {
|
||||||
|
wait_for_connections_event += 1;
|
||||||
|
match mqtt_connected_event_received.load(std::sync::atomic::Ordering::Relaxed) {
|
||||||
|
true => {
|
||||||
|
println!("Mqtt connection callback received, progressing");
|
||||||
|
match mqtt_connected_event_ok.load(std::sync::atomic::Ordering::Relaxed) {
|
||||||
|
true => {
|
||||||
|
println!("Mqtt did callback as connected, testing with roundtrip now");
|
||||||
|
//subscribe to roundtrip
|
||||||
|
client.subscribe(round_trip_topic.as_str(), ExactlyOnce)?;
|
||||||
|
client.subscribe(stay_alive_topic.as_str(), ExactlyOnce)?;
|
||||||
|
//publish to roundtrip
|
||||||
|
client.publish(
|
||||||
|
round_trip_topic.as_str(),
|
||||||
|
ExactlyOnce,
|
||||||
|
false,
|
||||||
|
"online_test".as_bytes(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut wait_for_roundtrip = 0;
|
||||||
|
while wait_for_roundtrip < 100 {
|
||||||
|
wait_for_roundtrip += 1;
|
||||||
|
match round_trip_ok.load(std::sync::atomic::Ordering::Relaxed) {
|
||||||
|
true => {
|
||||||
|
println!("Round trip registered, proceeding");
|
||||||
|
self.mqtt_client = Some(MqttClient {
|
||||||
|
mqtt_client: client,
|
||||||
|
base_topic: base_topic_copy,
|
||||||
|
});
|
||||||
|
return anyhow::Ok(());
|
||||||
|
}
|
||||||
|
false => {
|
||||||
|
unsafe { vTaskDelay(10) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bail!("Mqtt did not complete roundtrip in time");
|
||||||
|
}
|
||||||
|
false => {
|
||||||
|
bail!("Mqtt did respond but with failure")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false => {
|
||||||
|
unsafe { vTaskDelay(10) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bail!("Mqtt did not fire connection callback in time");
|
||||||
|
}
|
||||||
|
pub(crate) fn mqtt_publish(&mut self, subtopic: &str, message: &[u8]) -> anyhow::Result<()> {
|
||||||
|
if self.mqtt_client.is_none() {
|
||||||
|
return anyhow::Ok(());
|
||||||
|
}
|
||||||
|
if !subtopic.starts_with("/") {
|
||||||
|
println!("Subtopic without / at start {}", subtopic);
|
||||||
|
bail!("Subtopic without / at start {}", subtopic);
|
||||||
|
}
|
||||||
|
if subtopic.len() > 192 {
|
||||||
|
println!("Subtopic exceeds 192 chars {}", subtopic);
|
||||||
|
bail!("Subtopic exceeds 192 chars {}", subtopic);
|
||||||
|
}
|
||||||
|
let client = self.mqtt_client.as_mut().unwrap();
|
||||||
|
let mut full_topic: heapless::String<256> = heapless::String::new();
|
||||||
|
if full_topic.push_str(client.base_topic.as_str()).is_err() {
|
||||||
|
println!("Some error assembling full_topic 1");
|
||||||
|
bail!("Some error assembling full_topic 1")
|
||||||
|
};
|
||||||
|
if full_topic.push_str(subtopic).is_err() {
|
||||||
|
println!("Some error assembling full_topic 2");
|
||||||
|
bail!("Some error assembling full_topic 2")
|
||||||
|
};
|
||||||
|
let publish = client
|
||||||
|
.mqtt_client
|
||||||
|
.publish(&full_topic, ExactlyOnce, true, message);
|
||||||
|
Delay::new(10).delay_ms(50);
|
||||||
|
match publish {
|
||||||
|
OkStd(message_id) => {
|
||||||
|
println!(
|
||||||
|
"Published mqtt topic {} with message {:#?} msgid is {:?}",
|
||||||
|
full_topic,
|
||||||
|
String::from_utf8_lossy(message),
|
||||||
|
message_id
|
||||||
|
);
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
println!(
|
||||||
|
"Error during mqtt send on topic {} with message {:#?} error is {:?}",
|
||||||
|
full_topic,
|
||||||
|
String::from_utf8_lossy(message),
|
||||||
|
err
|
||||||
|
);
|
||||||
|
Err(err)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
144
rust/src/hal/initial_hal.rs
Normal file
144
rust/src/hal/initial_hal.rs
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
use crate::hal::esp::Esp;
|
||||||
|
use crate::hal::rtc::{BackupHeader, RTCModuleInteraction};
|
||||||
|
use crate::hal::water::TankSensor;
|
||||||
|
use crate::hal::{deep_sleep, BoardInteraction, FreePeripherals, Sensor};
|
||||||
|
use crate::{
|
||||||
|
config::PlantControllerConfig,
|
||||||
|
hal::battery::{BatteryInteraction, NoBatteryMonitor},
|
||||||
|
};
|
||||||
|
use anyhow::{bail, Result};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use embedded_hal::digital::OutputPin;
|
||||||
|
use esp_idf_hal::gpio::{IOPin, Pull};
|
||||||
|
use esp_idf_hal::gpio::{InputOutput, PinDriver};
|
||||||
|
use measurements::{Current, Voltage};
|
||||||
|
|
||||||
|
pub struct Initial<'a> {
|
||||||
|
pub(crate) general_fault: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
pub(crate) esp: Esp<'a>,
|
||||||
|
pub(crate) config: PlantControllerConfig,
|
||||||
|
pub(crate) battery: Box<dyn BatteryInteraction + Send>,
|
||||||
|
pub rtc: Box<dyn RTCModuleInteraction + Send>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NoRTC {}
|
||||||
|
|
||||||
|
impl RTCModuleInteraction for NoRTC {
|
||||||
|
fn get_backup_info(&mut self) -> Result<BackupHeader> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_backup_config(&mut self) -> Result<Vec<u8>> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn backup_config(&mut self, _bytes: &[u8]) -> Result<()> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_rtc_time(&mut self) -> Result<DateTime<Utc>> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_rtc_time(&mut self, _time: &DateTime<Utc>) -> Result<()> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn create_initial_board(
|
||||||
|
free_pins: FreePeripherals,
|
||||||
|
fs_mount_error: bool,
|
||||||
|
config: PlantControllerConfig,
|
||||||
|
esp: Esp<'static>,
|
||||||
|
) -> Result<Box<dyn BoardInteraction<'static> + Send>> {
|
||||||
|
println!("Start initial");
|
||||||
|
let mut general_fault = PinDriver::input_output(free_pins.gpio6.downgrade())?;
|
||||||
|
general_fault.set_pull(Pull::Floating)?;
|
||||||
|
general_fault.set_low()?;
|
||||||
|
|
||||||
|
if fs_mount_error {
|
||||||
|
general_fault.set_high()?
|
||||||
|
}
|
||||||
|
let v = Initial {
|
||||||
|
general_fault,
|
||||||
|
config,
|
||||||
|
esp,
|
||||||
|
battery: Box::new(NoBatteryMonitor {}),
|
||||||
|
rtc: Box::new(NoRTC {}),
|
||||||
|
};
|
||||||
|
Ok(Box::new(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BoardInteraction<'a> for Initial<'a> {
|
||||||
|
fn get_tank_sensor(&mut self) -> Option<&mut TankSensor<'a>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_esp(&mut self) -> &mut Esp<'a> {
|
||||||
|
&mut self.esp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_config(&mut self) -> &PlantControllerConfig {
|
||||||
|
&self.config
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_battery_monitor(&mut self) -> &mut Box<dyn BatteryInteraction + Send> {
|
||||||
|
&mut self.battery
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_rtc_module(&mut self) -> &mut Box<dyn RTCModuleInteraction + Send> {
|
||||||
|
&mut self.rtc
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_charge_indicator(&mut self, _charging: bool) -> Result<()> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deep_sleep(&mut self, duration_in_ms: u64) -> ! {
|
||||||
|
deep_sleep(duration_in_ms)
|
||||||
|
}
|
||||||
|
fn is_day(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
fn light(&mut self, _enable: bool) -> Result<()> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pump(&mut self, _plant: usize, _enable: bool) -> Result<()> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pump_current(&mut self, _plant: usize) -> Result<Current> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fault(&mut self, _plant: usize, _enable: bool) -> Result<()> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn measure_moisture_hz(&mut self, _plant: usize, _sensor: Sensor) -> Result<f32> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn general_fault(&mut self, enable: bool) {
|
||||||
|
let _ = self.general_fault.set_state(enable.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test(&mut self) -> Result<()> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_config(&mut self, config: PlantControllerConfig) -> anyhow::Result<()> {
|
||||||
|
self.config = config;
|
||||||
|
self.esp.save_config(&self.config)?;
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mptt_voltage(&mut self) -> Result<Voltage> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mptt_current(&mut self) -> Result<Current> {
|
||||||
|
bail!("Please configure board revision")
|
||||||
|
}
|
||||||
|
}
|
||||||
361
rust/src/hal/mod.rs
Normal file
361
rust/src/hal/mod.rs
Normal file
@@ -0,0 +1,361 @@
|
|||||||
|
pub(crate) mod battery;
|
||||||
|
mod esp;
|
||||||
|
mod initial_hal;
|
||||||
|
mod rtc;
|
||||||
|
mod v3_hal;
|
||||||
|
mod v4_hal;
|
||||||
|
mod water;
|
||||||
|
mod v4_sensor;
|
||||||
|
|
||||||
|
use crate::hal::rtc::{DS3231Module, RTCModuleInteraction};
|
||||||
|
use crate::hal::water::TankSensor;
|
||||||
|
use crate::{
|
||||||
|
config::{BatteryBoardVersion, BoardVersion, PlantControllerConfig},
|
||||||
|
hal::{
|
||||||
|
battery::{print_battery_bq34z100, BatteryInteraction, NoBatteryMonitor},
|
||||||
|
esp::Esp,
|
||||||
|
},
|
||||||
|
log::{log, LogMessage},
|
||||||
|
};
|
||||||
|
use anyhow::{Ok, Result};
|
||||||
|
use battery::BQ34Z100G1;
|
||||||
|
use bq34z100::Bq34z100g1Driver;
|
||||||
|
use ds323x::{DateTimeAccess, Ds323x};
|
||||||
|
use eeprom24x::{Eeprom24x, SlaveAddr, Storage};
|
||||||
|
use embedded_hal_bus::i2c::MutexDevice;
|
||||||
|
use esp_idf_hal::{
|
||||||
|
adc::ADC1,
|
||||||
|
delay::Delay,
|
||||||
|
gpio::{
|
||||||
|
Gpio0, Gpio1, Gpio10, Gpio11, Gpio12, Gpio13, Gpio14, Gpio15, Gpio16, Gpio17, Gpio18,
|
||||||
|
Gpio2, Gpio21, Gpio22, Gpio23, Gpio24, Gpio25, Gpio26, Gpio27, Gpio28, Gpio29, Gpio3,
|
||||||
|
Gpio30, Gpio4, Gpio5, Gpio6, Gpio7, Gpio8, IOPin, PinDriver, Pull,
|
||||||
|
},
|
||||||
|
i2c::{APBTickType, I2cConfig, I2cDriver},
|
||||||
|
pcnt::PCNT0,
|
||||||
|
prelude::Peripherals,
|
||||||
|
reset::ResetReason,
|
||||||
|
units::FromValueType,
|
||||||
|
};
|
||||||
|
use esp_idf_svc::{eventloop::EspSystemEventLoop, nvs::EspDefaultNvsPartition, wifi::EspWifi};
|
||||||
|
use esp_idf_sys::{
|
||||||
|
esp_deep_sleep, esp_restart, esp_sleep_enable_ext1_wakeup,
|
||||||
|
esp_sleep_ext1_wakeup_mode_t_ESP_EXT1_WAKEUP_ANY_LOW,
|
||||||
|
};
|
||||||
|
use esp_ota::mark_app_valid;
|
||||||
|
use measurements::{Current, Voltage};
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
use std::result::Result::Ok as OkStd;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
use std::time::Duration;
|
||||||
|
use esp_idf_hal::can::CAN;
|
||||||
|
use esp_idf_hal::pcnt::PCNT1;
|
||||||
|
|
||||||
|
//Only support for 8 right now!
|
||||||
|
pub const PLANT_COUNT: usize = 8;
|
||||||
|
|
||||||
|
|
||||||
|
const TANK_MULTI_SAMPLE: usize = 11;
|
||||||
|
|
||||||
|
pub static I2C_DRIVER: Lazy<Mutex<I2cDriver<'static>>> = Lazy::new(PlantHal::create_i2c);
|
||||||
|
|
||||||
|
fn deep_sleep(duration_in_ms: u64) -> ! {
|
||||||
|
unsafe {
|
||||||
|
//if we don't do this here, we might just revert newly flashed firmware
|
||||||
|
mark_app_valid();
|
||||||
|
//allow early wakeup by pressing the boot button
|
||||||
|
if duration_in_ms == 0 {
|
||||||
|
esp_restart();
|
||||||
|
} else {
|
||||||
|
//configure gpio 1 to wakeup on low, reused boot button for this
|
||||||
|
esp_sleep_enable_ext1_wakeup(
|
||||||
|
0b10u64,
|
||||||
|
esp_sleep_ext1_wakeup_mode_t_ESP_EXT1_WAKEUP_ANY_LOW,
|
||||||
|
);
|
||||||
|
esp_deep_sleep(duration_in_ms);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum Sensor {
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PlantHal {}
|
||||||
|
|
||||||
|
pub struct HAL<'a> {
|
||||||
|
pub board_hal: Box<dyn BoardInteraction<'a> + Send>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait BoardInteraction<'a> {
|
||||||
|
fn get_tank_sensor(&mut self) -> Option<&mut TankSensor<'a>>;
|
||||||
|
fn get_esp(&mut self) -> &mut Esp<'a>;
|
||||||
|
fn get_config(&mut self) -> &PlantControllerConfig;
|
||||||
|
fn get_battery_monitor(&mut self) -> &mut Box<dyn BatteryInteraction + Send>;
|
||||||
|
fn get_rtc_module(&mut self) -> &mut Box<dyn RTCModuleInteraction + Send>;
|
||||||
|
fn set_charge_indicator(&mut self, charging: bool) -> Result<()>;
|
||||||
|
fn deep_sleep(&mut self, duration_in_ms: u64) -> !;
|
||||||
|
|
||||||
|
fn is_day(&self) -> bool;
|
||||||
|
//should be multsampled
|
||||||
|
fn light(&mut self, enable: bool) -> Result<()>;
|
||||||
|
fn pump(&mut self, plant: usize, enable: bool) -> Result<()>;
|
||||||
|
fn pump_current(&mut self, plant: usize) -> Result<Current>;
|
||||||
|
fn fault(&mut self, plant: usize, enable: bool) -> Result<()>;
|
||||||
|
fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> Result<f32>;
|
||||||
|
fn general_fault(&mut self, enable: bool);
|
||||||
|
fn test(&mut self) -> Result<()>;
|
||||||
|
fn set_config(&mut self, config: PlantControllerConfig) -> Result<()>;
|
||||||
|
fn get_mptt_voltage(&mut self) -> anyhow::Result<Voltage>;
|
||||||
|
fn get_mptt_current(&mut self) -> anyhow::Result<Current>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl dyn BoardInteraction<'_> {
|
||||||
|
//the counter is just some arbitrary number that increases whenever some progress was made, try to keep the updates < 10 per second for ux reasons
|
||||||
|
fn progress(&mut self, counter: u32) {
|
||||||
|
let even = counter % 2 == 0;
|
||||||
|
let current = counter / (PLANT_COUNT as u32);
|
||||||
|
for led in 0..PLANT_COUNT {
|
||||||
|
self.fault(led, current == led as u32).unwrap();
|
||||||
|
}
|
||||||
|
let _ = self.general_fault(even.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct FreePeripherals {
|
||||||
|
pub gpio0: Gpio0,
|
||||||
|
pub gpio1: Gpio1,
|
||||||
|
pub gpio2: Gpio2,
|
||||||
|
pub gpio3: Gpio3,
|
||||||
|
pub gpio4: Gpio4,
|
||||||
|
pub gpio5: Gpio5,
|
||||||
|
pub gpio6: Gpio6,
|
||||||
|
pub gpio7: Gpio7,
|
||||||
|
pub gpio8: Gpio8,
|
||||||
|
//config button here
|
||||||
|
pub gpio10: Gpio10,
|
||||||
|
pub gpio11: Gpio11,
|
||||||
|
pub gpio12: Gpio12,
|
||||||
|
pub gpio13: Gpio13,
|
||||||
|
pub gpio14: Gpio14,
|
||||||
|
pub gpio15: Gpio15,
|
||||||
|
pub gpio16: Gpio16,
|
||||||
|
pub gpio17: Gpio17,
|
||||||
|
pub gpio18: Gpio18,
|
||||||
|
//i2c here
|
||||||
|
pub gpio21: Gpio21,
|
||||||
|
pub gpio22: Gpio22,
|
||||||
|
pub gpio23: Gpio23,
|
||||||
|
pub gpio24: Gpio24,
|
||||||
|
pub gpio25: Gpio25,
|
||||||
|
pub gpio26: Gpio26,
|
||||||
|
pub gpio27: Gpio27,
|
||||||
|
pub gpio28: Gpio28,
|
||||||
|
pub gpio29: Gpio29,
|
||||||
|
pub gpio30: Gpio30,
|
||||||
|
pub pcnt0: PCNT0,
|
||||||
|
pub pcnt1: PCNT1,
|
||||||
|
pub adc1: ADC1,
|
||||||
|
pub can: CAN,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlantHal {
|
||||||
|
fn create_i2c() -> Mutex<I2cDriver<'static>> {
|
||||||
|
let peripherals = unsafe { Peripherals::new() };
|
||||||
|
|
||||||
|
let config = I2cConfig::new()
|
||||||
|
.scl_enable_pullup(true)
|
||||||
|
.sda_enable_pullup(true)
|
||||||
|
.baudrate(100_u32.kHz().into())
|
||||||
|
.timeout(APBTickType::from(Duration::from_millis(100)));
|
||||||
|
|
||||||
|
let i2c = peripherals.i2c0;
|
||||||
|
let scl = peripherals.pins.gpio19.downgrade();
|
||||||
|
let sda = peripherals.pins.gpio20.downgrade();
|
||||||
|
|
||||||
|
Mutex::new(I2cDriver::new(i2c, sda, scl, &config).unwrap())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create() -> Result<Mutex<HAL<'static>>> {
|
||||||
|
let peripherals = Peripherals::take()?;
|
||||||
|
let sys_loop = EspSystemEventLoop::take()?;
|
||||||
|
let nvs = EspDefaultNvsPartition::take()?;
|
||||||
|
let wifi_driver = EspWifi::new(peripherals.modem, sys_loop, Some(nvs))?;
|
||||||
|
|
||||||
|
let mut boot_button = PinDriver::input(peripherals.pins.gpio9.downgrade())?;
|
||||||
|
boot_button.set_pull(Pull::Floating)?;
|
||||||
|
|
||||||
|
let free_pins = FreePeripherals {
|
||||||
|
can: peripherals.can,
|
||||||
|
adc1: peripherals.adc1,
|
||||||
|
pcnt0: peripherals.pcnt0,
|
||||||
|
pcnt1: peripherals.pcnt1,
|
||||||
|
gpio0: peripherals.pins.gpio0,
|
||||||
|
gpio1: peripherals.pins.gpio1,
|
||||||
|
gpio2: peripherals.pins.gpio2,
|
||||||
|
gpio3: peripherals.pins.gpio3,
|
||||||
|
gpio4: peripherals.pins.gpio4,
|
||||||
|
gpio5: peripherals.pins.gpio5,
|
||||||
|
gpio6: peripherals.pins.gpio6,
|
||||||
|
gpio7: peripherals.pins.gpio7,
|
||||||
|
gpio8: peripherals.pins.gpio8,
|
||||||
|
gpio10: peripherals.pins.gpio10,
|
||||||
|
gpio11: peripherals.pins.gpio11,
|
||||||
|
gpio12: peripherals.pins.gpio12,
|
||||||
|
gpio13: peripherals.pins.gpio13,
|
||||||
|
gpio14: peripherals.pins.gpio14,
|
||||||
|
gpio15: peripherals.pins.gpio15,
|
||||||
|
gpio16: peripherals.pins.gpio16,
|
||||||
|
gpio17: peripherals.pins.gpio17,
|
||||||
|
gpio18: peripherals.pins.gpio18,
|
||||||
|
gpio21: peripherals.pins.gpio21,
|
||||||
|
gpio22: peripherals.pins.gpio22,
|
||||||
|
gpio23: peripherals.pins.gpio23,
|
||||||
|
gpio24: peripherals.pins.gpio24,
|
||||||
|
gpio25: peripherals.pins.gpio25,
|
||||||
|
gpio26: peripherals.pins.gpio26,
|
||||||
|
gpio27: peripherals.pins.gpio27,
|
||||||
|
gpio28: peripherals.pins.gpio28,
|
||||||
|
gpio29: peripherals.pins.gpio29,
|
||||||
|
gpio30: peripherals.pins.gpio30,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut esp = Esp {
|
||||||
|
mqtt_client: None,
|
||||||
|
wifi_driver,
|
||||||
|
boot_button,
|
||||||
|
delay: Delay::new(1000),
|
||||||
|
};
|
||||||
|
|
||||||
|
//init,reset rtc memory depending on cause
|
||||||
|
let mut init_rtc_store: bool = false;
|
||||||
|
let mut to_config_mode: bool = false;
|
||||||
|
let reasons = ResetReason::get();
|
||||||
|
match reasons {
|
||||||
|
ResetReason::Software => {}
|
||||||
|
ResetReason::ExternalPin => {}
|
||||||
|
ResetReason::Watchdog => {
|
||||||
|
init_rtc_store = true;
|
||||||
|
}
|
||||||
|
ResetReason::Sdio => init_rtc_store = true,
|
||||||
|
ResetReason::Panic => init_rtc_store = true,
|
||||||
|
ResetReason::InterruptWatchdog => init_rtc_store = true,
|
||||||
|
ResetReason::PowerOn => init_rtc_store = true,
|
||||||
|
ResetReason::Unknown => init_rtc_store = true,
|
||||||
|
ResetReason::Brownout => init_rtc_store = true,
|
||||||
|
ResetReason::TaskWatchdog => init_rtc_store = true,
|
||||||
|
ResetReason::DeepSleep => {}
|
||||||
|
ResetReason::USBPeripheral => {
|
||||||
|
init_rtc_store = true;
|
||||||
|
to_config_mode = true;
|
||||||
|
}
|
||||||
|
ResetReason::JTAG => init_rtc_store = true,
|
||||||
|
};
|
||||||
|
log(
|
||||||
|
LogMessage::ResetReason,
|
||||||
|
init_rtc_store as u32,
|
||||||
|
to_config_mode as u32,
|
||||||
|
"",
|
||||||
|
&format!("{reasons:?}"),
|
||||||
|
);
|
||||||
|
|
||||||
|
esp.init_rtc_deepsleep_memory(init_rtc_store, to_config_mode);
|
||||||
|
let fs_mount_error = esp.mount_file_system().is_err();
|
||||||
|
|
||||||
|
let config = esp.load_config();
|
||||||
|
|
||||||
|
println!("Init rtc driver");
|
||||||
|
let mut rtc = Ds323x::new_ds3231(MutexDevice::new(&I2C_DRIVER));
|
||||||
|
|
||||||
|
println!("Init rtc eeprom driver");
|
||||||
|
let eeprom = {
|
||||||
|
Eeprom24x::new_24x32(
|
||||||
|
MutexDevice::new(&I2C_DRIVER),
|
||||||
|
SlaveAddr::Alternative(true, true, true),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
let rtc_time = rtc.datetime();
|
||||||
|
match rtc_time {
|
||||||
|
OkStd(tt) => {
|
||||||
|
println!("Rtc Module reports time at UTC {}", tt);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
println!("Rtc Module could not be read {:?}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let storage = Storage::new(eeprom, Delay::new(1000));
|
||||||
|
let rtc_module: Box<dyn RTCModuleInteraction + Send> =
|
||||||
|
Box::new(DS3231Module { rtc, storage }) as Box<dyn RTCModuleInteraction + Send>;
|
||||||
|
|
||||||
|
let hal = match config {
|
||||||
|
Result::Ok(config) => {
|
||||||
|
let battery_interaction: Box<dyn BatteryInteraction + Send> =
|
||||||
|
match config.hardware.battery {
|
||||||
|
BatteryBoardVersion::Disabled => Box::new(NoBatteryMonitor {}),
|
||||||
|
BatteryBoardVersion::BQ34Z100G1 => {
|
||||||
|
let mut battery_driver = Bq34z100g1Driver {
|
||||||
|
i2c: MutexDevice::new(&I2C_DRIVER),
|
||||||
|
delay: Delay::new(0),
|
||||||
|
flash_block_data: [0; 32],
|
||||||
|
};
|
||||||
|
let status = print_battery_bq34z100(&mut battery_driver);
|
||||||
|
match status {
|
||||||
|
OkStd(_) => {}
|
||||||
|
Err(err) => {
|
||||||
|
log(
|
||||||
|
LogMessage::BatteryCommunicationError,
|
||||||
|
0u32,
|
||||||
|
0,
|
||||||
|
"",
|
||||||
|
&format!("{err:?})"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Box::new(BQ34Z100G1 { battery_driver })
|
||||||
|
}
|
||||||
|
BatteryBoardVersion::WchI2cSlave => {
|
||||||
|
// TODO use correct implementation once availible
|
||||||
|
Box::new(NoBatteryMonitor {})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let board_hal: Box<dyn BoardInteraction + Send> = match config.hardware.board {
|
||||||
|
BoardVersion::INITIAL => {
|
||||||
|
initial_hal::create_initial_board(free_pins, fs_mount_error, config, esp)?
|
||||||
|
}
|
||||||
|
BoardVersion::V3 => {
|
||||||
|
v3_hal::create_v3(free_pins, esp, config, battery_interaction, rtc_module)?
|
||||||
|
}
|
||||||
|
BoardVersion::V4 => {
|
||||||
|
v4_hal::create_v4(free_pins, esp, config, battery_interaction, rtc_module)?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
HAL { board_hal }
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
log(
|
||||||
|
LogMessage::ConfigModeMissingConfig,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
"",
|
||||||
|
&err.to_string(),
|
||||||
|
);
|
||||||
|
HAL {
|
||||||
|
board_hal: initial_hal::create_initial_board(
|
||||||
|
free_pins,
|
||||||
|
fs_mount_error,
|
||||||
|
PlantControllerConfig::default(),
|
||||||
|
esp,
|
||||||
|
)?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Mutex::new(hal))
|
||||||
|
}
|
||||||
|
}
|
||||||
132
rust/src/hal/rtc.rs
Normal file
132
rust/src/hal/rtc.rs
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
use anyhow::{anyhow, bail};
|
||||||
|
use bincode::config::Configuration;
|
||||||
|
use bincode::{config, Decode, Encode};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use ds323x::{DateTimeAccess, Ds323x};
|
||||||
|
use eeprom24x::addr_size::TwoBytes;
|
||||||
|
use eeprom24x::page_size::B32;
|
||||||
|
use eeprom24x::unique_serial::No;
|
||||||
|
use eeprom24x::Storage;
|
||||||
|
use embedded_hal_bus::i2c::MutexDevice;
|
||||||
|
use embedded_storage::ReadStorage as embedded_storage_ReadStorage;
|
||||||
|
use embedded_storage::Storage as embedded_storage_Storage;
|
||||||
|
use esp_idf_hal::delay::Delay;
|
||||||
|
use esp_idf_hal::i2c::I2cDriver;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::result::Result::Ok as OkStd;
|
||||||
|
|
||||||
|
const X25: crc::Crc<u16> = crc::Crc::<u16>::new(&crc::CRC_16_IBM_SDLC);
|
||||||
|
const CONFIG: Configuration = config::standard();
|
||||||
|
|
||||||
|
pub trait RTCModuleInteraction {
|
||||||
|
fn get_backup_info(&mut self) -> anyhow::Result<BackupHeader>;
|
||||||
|
fn get_backup_config(&mut self) -> anyhow::Result<Vec<u8>>;
|
||||||
|
fn backup_config(&mut self, bytes: &[u8]) -> anyhow::Result<()>;
|
||||||
|
fn get_rtc_time(&mut self) -> anyhow::Result<DateTime<Utc>>;
|
||||||
|
fn set_rtc_time(&mut self, time: &DateTime<Utc>) -> anyhow::Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const BACKUP_HEADER_MAX_SIZE: usize = 64;
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Debug, Default, Encode, Decode)]
|
||||||
|
pub struct BackupHeader {
|
||||||
|
pub timestamp: i64,
|
||||||
|
crc16: u16,
|
||||||
|
pub size: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DS3231Module<'a> {
|
||||||
|
pub(crate) rtc:
|
||||||
|
Ds323x<ds323x::interface::I2cInterface<MutexDevice<'a, I2cDriver<'a>>>, ds323x::ic::DS3231>,
|
||||||
|
|
||||||
|
pub(crate) storage: Storage<MutexDevice<'a, I2cDriver<'a>>, B32, TwoBytes, No, Delay>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RTCModuleInteraction for DS3231Module<'_> {
|
||||||
|
fn get_backup_info(&mut self) -> anyhow::Result<BackupHeader> {
|
||||||
|
let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
|
||||||
|
|
||||||
|
self.storage
|
||||||
|
.read(0, &mut header_page_buffer)
|
||||||
|
.map_err(|err| anyhow!("Error reading eeprom header {:?}", err))?;
|
||||||
|
|
||||||
|
let (header, len): (BackupHeader, usize) =
|
||||||
|
bincode::decode_from_slice(&header_page_buffer[..], CONFIG)?;
|
||||||
|
|
||||||
|
println!("Raw header is {:?} with size {}", header_page_buffer, len);
|
||||||
|
anyhow::Ok(header)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_backup_config(&mut self) -> anyhow::Result<Vec<u8>> {
|
||||||
|
let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
|
||||||
|
|
||||||
|
self.storage
|
||||||
|
.read(0, &mut header_page_buffer)
|
||||||
|
.map_err(|err| anyhow!("Error reading eeprom header {:?}", err))?;
|
||||||
|
let (header, _header_size): (BackupHeader, usize) =
|
||||||
|
bincode::decode_from_slice(&header_page_buffer[..], CONFIG)?;
|
||||||
|
|
||||||
|
let mut data_buffer = vec![0_u8; header.size as usize];
|
||||||
|
//read the specified number of bytes after the header
|
||||||
|
self.storage
|
||||||
|
.read(BACKUP_HEADER_MAX_SIZE as u32, &mut data_buffer)
|
||||||
|
.map_err(|err| anyhow!("Error reading eeprom data {:?}", err))?;
|
||||||
|
|
||||||
|
let checksum = X25.checksum(&data_buffer);
|
||||||
|
if checksum != header.crc16 {
|
||||||
|
bail!(
|
||||||
|
"Invalid checksum, got {} but expected {}",
|
||||||
|
checksum,
|
||||||
|
header.crc16
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
anyhow::Ok(data_buffer)
|
||||||
|
}
|
||||||
|
fn backup_config(&mut self, bytes: &[u8]) -> anyhow::Result<()> {
|
||||||
|
let mut header_page_buffer = [0_u8; BACKUP_HEADER_MAX_SIZE];
|
||||||
|
|
||||||
|
let time = self.get_rtc_time()?.timestamp_millis();
|
||||||
|
let checksum = X25.checksum(bytes);
|
||||||
|
|
||||||
|
let header = BackupHeader {
|
||||||
|
crc16: checksum,
|
||||||
|
timestamp: time,
|
||||||
|
size: bytes.len() as u16,
|
||||||
|
};
|
||||||
|
let config = config::standard();
|
||||||
|
let encoded = bincode::encode_into_slice(&header, &mut header_page_buffer, config)?;
|
||||||
|
println!(
|
||||||
|
"Raw header is {:?} with size {}",
|
||||||
|
header_page_buffer, encoded
|
||||||
|
);
|
||||||
|
self.storage
|
||||||
|
.write(0, &header_page_buffer)
|
||||||
|
.map_err(|err| anyhow!("Error writing header {:?}", err))?;
|
||||||
|
|
||||||
|
//write rest after the header
|
||||||
|
self.storage
|
||||||
|
.write(BACKUP_HEADER_MAX_SIZE as u32, &bytes)
|
||||||
|
.map_err(|err| anyhow!("Error writing body {:?}", err))?;
|
||||||
|
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_rtc_time(&mut self) -> anyhow::Result<DateTime<Utc>> {
|
||||||
|
match self.rtc.datetime() {
|
||||||
|
OkStd(rtc_time) => anyhow::Ok(rtc_time.and_utc()),
|
||||||
|
Err(err) => {
|
||||||
|
bail!("Error getting rtc time {:?}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_rtc_time(&mut self, time: &DateTime<Utc>) -> anyhow::Result<()> {
|
||||||
|
let naive_time = time.naive_utc();
|
||||||
|
match self.rtc.set_datetime(&naive_time) {
|
||||||
|
OkStd(_) => anyhow::Ok(()),
|
||||||
|
Err(err) => {
|
||||||
|
bail!("Error getting rtc time {:?}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
436
rust/src/hal/v3_hal.rs
Normal file
436
rust/src/hal/v3_hal.rs
Normal file
@@ -0,0 +1,436 @@
|
|||||||
|
use crate::hal::rtc::RTCModuleInteraction;
|
||||||
|
use crate::hal::water::TankSensor;
|
||||||
|
use crate::hal::{
|
||||||
|
deep_sleep, BoardInteraction, FreePeripherals, Sensor, PLANT_COUNT,
|
||||||
|
};
|
||||||
|
use crate::log::{log, LogMessage};
|
||||||
|
use crate::{
|
||||||
|
config::PlantControllerConfig,
|
||||||
|
hal::{battery::BatteryInteraction, esp::Esp},
|
||||||
|
};
|
||||||
|
use anyhow::{bail, Ok, Result};
|
||||||
|
use embedded_hal::digital::OutputPin;
|
||||||
|
use esp_idf_hal::{
|
||||||
|
gpio::{AnyInputPin, IOPin, InputOutput, PinDriver, Pull},
|
||||||
|
pcnt::{PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex},
|
||||||
|
};
|
||||||
|
use esp_idf_sys::{gpio_hold_dis, gpio_hold_en};
|
||||||
|
use measurements::{Current, Voltage};
|
||||||
|
use plant_ctrl2::sipo::ShiftRegister40;
|
||||||
|
use std::result::Result::Ok as OkStd;
|
||||||
|
|
||||||
|
const PUMP8_BIT: usize = 0;
|
||||||
|
const PUMP1_BIT: usize = 1;
|
||||||
|
const PUMP2_BIT: usize = 2;
|
||||||
|
const PUMP3_BIT: usize = 3;
|
||||||
|
const PUMP4_BIT: usize = 4;
|
||||||
|
const PUMP5_BIT: usize = 5;
|
||||||
|
const PUMP6_BIT: usize = 6;
|
||||||
|
const PUMP7_BIT: usize = 7;
|
||||||
|
const MS_0: usize = 8;
|
||||||
|
const MS_4: usize = 9;
|
||||||
|
const MS_2: usize = 10;
|
||||||
|
const MS_3: usize = 11;
|
||||||
|
const MS_1: usize = 13;
|
||||||
|
const SENSOR_ON: usize = 12;
|
||||||
|
|
||||||
|
const SENSOR_A_1: u8 = 7;
|
||||||
|
const SENSOR_A_2: u8 = 6;
|
||||||
|
const SENSOR_A_3: u8 = 5;
|
||||||
|
const SENSOR_A_4: u8 = 4;
|
||||||
|
const SENSOR_A_5: u8 = 3;
|
||||||
|
const SENSOR_A_6: u8 = 2;
|
||||||
|
const SENSOR_A_7: u8 = 1;
|
||||||
|
const SENSOR_A_8: u8 = 0;
|
||||||
|
|
||||||
|
const SENSOR_B_1: u8 = 8;
|
||||||
|
const SENSOR_B_2: u8 = 9;
|
||||||
|
const SENSOR_B_3: u8 = 10;
|
||||||
|
const SENSOR_B_4: u8 = 11;
|
||||||
|
const SENSOR_B_5: u8 = 12;
|
||||||
|
const SENSOR_B_6: u8 = 13;
|
||||||
|
const SENSOR_B_7: u8 = 14;
|
||||||
|
const SENSOR_B_8: u8 = 15;
|
||||||
|
|
||||||
|
const CHARGING: usize = 14;
|
||||||
|
const AWAKE: usize = 15;
|
||||||
|
|
||||||
|
const FAULT_3: usize = 16;
|
||||||
|
const FAULT_8: usize = 17;
|
||||||
|
const FAULT_7: usize = 18;
|
||||||
|
const FAULT_6: usize = 19;
|
||||||
|
const FAULT_5: usize = 20;
|
||||||
|
const FAULT_4: usize = 21;
|
||||||
|
const FAULT_1: usize = 22;
|
||||||
|
const FAULT_2: usize = 23;
|
||||||
|
|
||||||
|
const REPEAT_MOIST_MEASURE: usize = 1;
|
||||||
|
|
||||||
|
|
||||||
|
pub struct V3<'a> {
|
||||||
|
config: PlantControllerConfig,
|
||||||
|
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
||||||
|
rtc_module: Box<dyn RTCModuleInteraction + Send>,
|
||||||
|
esp: Esp<'a>,
|
||||||
|
shift_register: ShiftRegister40<
|
||||||
|
PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
>,
|
||||||
|
_shift_register_enable_invert:
|
||||||
|
PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, esp_idf_hal::gpio::Output>,
|
||||||
|
tank_sensor: TankSensor<'a>,
|
||||||
|
solar_is_day: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, esp_idf_hal::gpio::Input>,
|
||||||
|
light: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
main_pump: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
general_fault: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
signal_counter: PcntDriver<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn create_v3(
|
||||||
|
peripherals: FreePeripherals,
|
||||||
|
esp: Esp<'static>,
|
||||||
|
config: PlantControllerConfig,
|
||||||
|
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
||||||
|
rtc_module: Box<dyn RTCModuleInteraction + Send>,
|
||||||
|
) -> Result<Box<dyn BoardInteraction<'static> + Send>> {
|
||||||
|
println!("Start v3");
|
||||||
|
let mut clock = PinDriver::input_output(peripherals.gpio15.downgrade())?;
|
||||||
|
clock.set_pull(Pull::Floating)?;
|
||||||
|
let mut latch = PinDriver::input_output(peripherals.gpio3.downgrade())?;
|
||||||
|
latch.set_pull(Pull::Floating)?;
|
||||||
|
let mut data = PinDriver::input_output(peripherals.gpio23.downgrade())?;
|
||||||
|
data.set_pull(Pull::Floating)?;
|
||||||
|
let shift_register = ShiftRegister40::new(clock, latch, data);
|
||||||
|
//disable all
|
||||||
|
for mut pin in shift_register.decompose() {
|
||||||
|
pin.set_low()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let awake = &mut shift_register.decompose()[AWAKE];
|
||||||
|
awake.set_high()?;
|
||||||
|
|
||||||
|
let charging = &mut shift_register.decompose()[CHARGING];
|
||||||
|
charging.set_high()?;
|
||||||
|
|
||||||
|
let ms0 = &mut shift_register.decompose()[MS_0];
|
||||||
|
ms0.set_low()?;
|
||||||
|
let ms1 = &mut shift_register.decompose()[MS_1];
|
||||||
|
ms1.set_low()?;
|
||||||
|
let ms2 = &mut shift_register.decompose()[MS_2];
|
||||||
|
ms2.set_low()?;
|
||||||
|
let ms3 = &mut shift_register.decompose()[MS_3];
|
||||||
|
ms3.set_low()?;
|
||||||
|
|
||||||
|
let ms4 = &mut shift_register.decompose()[MS_4];
|
||||||
|
ms4.set_high()?;
|
||||||
|
|
||||||
|
let one_wire_pin = peripherals.gpio18.downgrade();
|
||||||
|
let tank_power_pin = peripherals.gpio11.downgrade();
|
||||||
|
|
||||||
|
let flow_sensor_pin = peripherals.gpio4.downgrade();
|
||||||
|
|
||||||
|
let tank_sensor = TankSensor::create(
|
||||||
|
one_wire_pin,
|
||||||
|
peripherals.adc1,
|
||||||
|
peripherals.gpio5,
|
||||||
|
tank_power_pin,
|
||||||
|
flow_sensor_pin,
|
||||||
|
peripherals.pcnt1
|
||||||
|
)?;
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut solar_is_day = PinDriver::input(peripherals.gpio7.downgrade())?;
|
||||||
|
solar_is_day.set_pull(Pull::Floating)?;
|
||||||
|
|
||||||
|
let mut light = PinDriver::input_output(peripherals.gpio10.downgrade())?;
|
||||||
|
light.set_pull(Pull::Floating)?;
|
||||||
|
|
||||||
|
let mut main_pump = PinDriver::input_output(peripherals.gpio2.downgrade())?;
|
||||||
|
main_pump.set_pull(Pull::Floating)?;
|
||||||
|
main_pump.set_low()?;
|
||||||
|
|
||||||
|
let mut general_fault = PinDriver::input_output(peripherals.gpio6.downgrade())?;
|
||||||
|
general_fault.set_pull(Pull::Floating)?;
|
||||||
|
general_fault.set_low()?;
|
||||||
|
|
||||||
|
let mut shift_register_enable_invert = PinDriver::output(peripherals.gpio21.downgrade())?;
|
||||||
|
|
||||||
|
unsafe { gpio_hold_dis(shift_register_enable_invert.pin()) };
|
||||||
|
shift_register_enable_invert.set_low()?;
|
||||||
|
unsafe { gpio_hold_en(shift_register_enable_invert.pin()) };
|
||||||
|
|
||||||
|
Ok(Box::new(V3 {
|
||||||
|
config,
|
||||||
|
battery_monitor,
|
||||||
|
rtc_module,
|
||||||
|
esp,
|
||||||
|
shift_register,
|
||||||
|
_shift_register_enable_invert: shift_register_enable_invert,
|
||||||
|
tank_sensor,
|
||||||
|
solar_is_day,
|
||||||
|
light,
|
||||||
|
main_pump,
|
||||||
|
general_fault,
|
||||||
|
signal_counter,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BoardInteraction<'a> for V3<'a> {
|
||||||
|
fn get_tank_sensor(&mut self) -> Option<&mut TankSensor<'a>> {
|
||||||
|
Some(&mut self.tank_sensor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_esp(&mut self) -> &mut Esp<'a> {
|
||||||
|
&mut self.esp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_config(&mut self) -> &PlantControllerConfig {
|
||||||
|
&self.config
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_battery_monitor(&mut self) -> &mut Box<(dyn BatteryInteraction + Send + 'static)> {
|
||||||
|
&mut self.battery_monitor
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_rtc_module(&mut self) -> &mut Box<dyn RTCModuleInteraction + Send> {
|
||||||
|
&mut self.rtc_module
|
||||||
|
}
|
||||||
|
fn set_charge_indicator(&mut self, charging: bool) -> Result<()> {
|
||||||
|
Ok(self.shift_register.decompose()[CHARGING].set_state(charging.into())?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deep_sleep(&mut self, duration_in_ms: u64) -> ! {
|
||||||
|
let _ = self.shift_register.decompose()[AWAKE].set_low();
|
||||||
|
deep_sleep(duration_in_ms)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_day(&self) -> bool {
|
||||||
|
self.solar_is_day.get_level().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn light(&mut self, enable: bool) -> Result<()> {
|
||||||
|
unsafe { gpio_hold_dis(self.light.pin()) };
|
||||||
|
self.light.set_state(enable.into())?;
|
||||||
|
unsafe { gpio_hold_en(self.light.pin()) };
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn pump(&mut self, plant: usize, enable: bool) -> Result<()> {
|
||||||
|
if enable {
|
||||||
|
self.main_pump.set_high()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = match plant {
|
||||||
|
0 => PUMP1_BIT,
|
||||||
|
1 => PUMP2_BIT,
|
||||||
|
2 => PUMP3_BIT,
|
||||||
|
3 => PUMP4_BIT,
|
||||||
|
4 => PUMP5_BIT,
|
||||||
|
5 => PUMP6_BIT,
|
||||||
|
6 => PUMP7_BIT,
|
||||||
|
7 => PUMP8_BIT,
|
||||||
|
_ => bail!("Invalid pump {plant}",),
|
||||||
|
};
|
||||||
|
self.shift_register.decompose()[index].set_state(enable.into())?;
|
||||||
|
|
||||||
|
if !enable {
|
||||||
|
self.main_pump.set_low()?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pump_current(&mut self, _plant: usize) -> Result<Current> {
|
||||||
|
bail!("Not implemented in v3")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fault(&mut self, plant: usize, enable: bool) -> Result<()> {
|
||||||
|
let index = match plant {
|
||||||
|
0 => FAULT_1,
|
||||||
|
1 => FAULT_2,
|
||||||
|
2 => FAULT_3,
|
||||||
|
3 => FAULT_4,
|
||||||
|
4 => FAULT_5,
|
||||||
|
5 => FAULT_6,
|
||||||
|
6 => FAULT_7,
|
||||||
|
7 => FAULT_8,
|
||||||
|
_ => panic!("Invalid plant id {}", plant),
|
||||||
|
};
|
||||||
|
self.shift_register.decompose()[index].set_state(enable.into())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> Result<f32> {
|
||||||
|
let mut results = [0_f32; REPEAT_MOIST_MEASURE];
|
||||||
|
for repeat in 0..REPEAT_MOIST_MEASURE {
|
||||||
|
self.signal_counter.counter_pause()?;
|
||||||
|
self.signal_counter.counter_clear()?;
|
||||||
|
//Disable all
|
||||||
|
self.shift_register.decompose()[MS_4].set_high()?;
|
||||||
|
|
||||||
|
let sensor_channel = match sensor {
|
||||||
|
Sensor::A => match plant {
|
||||||
|
0 => SENSOR_A_1,
|
||||||
|
1 => SENSOR_A_2,
|
||||||
|
2 => SENSOR_A_3,
|
||||||
|
3 => SENSOR_A_4,
|
||||||
|
4 => SENSOR_A_5,
|
||||||
|
5 => SENSOR_A_6,
|
||||||
|
6 => SENSOR_A_7,
|
||||||
|
7 => SENSOR_A_8,
|
||||||
|
_ => bail!("Invalid plant id {}", plant),
|
||||||
|
},
|
||||||
|
Sensor::B => match plant {
|
||||||
|
0 => SENSOR_B_1,
|
||||||
|
1 => SENSOR_B_2,
|
||||||
|
2 => SENSOR_B_3,
|
||||||
|
3 => SENSOR_B_4,
|
||||||
|
4 => SENSOR_B_5,
|
||||||
|
5 => SENSOR_B_6,
|
||||||
|
6 => SENSOR_B_7,
|
||||||
|
7 => SENSOR_B_8,
|
||||||
|
_ => bail!("Invalid plant id {}", plant),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let is_bit_set = |b: u8| -> bool { sensor_channel & (1 << b) != 0 };
|
||||||
|
let pin_0 = &mut self.shift_register.decompose()[MS_0];
|
||||||
|
let pin_1 = &mut self.shift_register.decompose()[MS_1];
|
||||||
|
let pin_2 = &mut self.shift_register.decompose()[MS_2];
|
||||||
|
let pin_3 = &mut self.shift_register.decompose()[MS_3];
|
||||||
|
if is_bit_set(0) {
|
||||||
|
pin_0.set_high()?;
|
||||||
|
} else {
|
||||||
|
pin_0.set_low()?;
|
||||||
|
}
|
||||||
|
if is_bit_set(1) {
|
||||||
|
pin_1.set_high()?;
|
||||||
|
} else {
|
||||||
|
pin_1.set_low()?;
|
||||||
|
}
|
||||||
|
if is_bit_set(2) {
|
||||||
|
pin_2.set_high()?;
|
||||||
|
} else {
|
||||||
|
pin_2.set_low()?;
|
||||||
|
}
|
||||||
|
if is_bit_set(3) {
|
||||||
|
pin_3.set_high()?;
|
||||||
|
} else {
|
||||||
|
pin_3.set_low()?;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.shift_register.decompose()[MS_4].set_low()?;
|
||||||
|
self.shift_register.decompose()[SENSOR_ON].set_high()?;
|
||||||
|
|
||||||
|
let measurement = 100; //how long to measure and then extrapolate to hz
|
||||||
|
let factor = 1000f32 / measurement as f32; //scale raw cound by this number to get hz
|
||||||
|
|
||||||
|
//give some time to stabilize
|
||||||
|
self.esp.delay.delay_ms(10);
|
||||||
|
self.signal_counter.counter_resume()?;
|
||||||
|
self.esp.delay.delay_ms(measurement);
|
||||||
|
self.signal_counter.counter_pause()?;
|
||||||
|
self.shift_register.decompose()[MS_4].set_high()?;
|
||||||
|
self.shift_register.decompose()[SENSOR_ON].set_low()?;
|
||||||
|
self.esp.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];
|
||||||
|
Ok(median)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn general_fault(&mut self, enable: bool) {
|
||||||
|
unsafe { gpio_hold_dis(self.general_fault.pin()) };
|
||||||
|
self.general_fault.set_state(enable.into()).unwrap();
|
||||||
|
unsafe { gpio_hold_en(self.general_fault.pin()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test(&mut self) -> Result<()> {
|
||||||
|
self.general_fault(true);
|
||||||
|
self.esp.delay.delay_ms(100);
|
||||||
|
self.general_fault(false);
|
||||||
|
self.esp.delay.delay_ms(100);
|
||||||
|
self.light(true)?;
|
||||||
|
self.esp.delay.delay_ms(500);
|
||||||
|
self.light(false)?;
|
||||||
|
self.esp.delay.delay_ms(500);
|
||||||
|
for i in 0..PLANT_COUNT {
|
||||||
|
self.fault(i, true)?;
|
||||||
|
self.esp.delay.delay_ms(500);
|
||||||
|
self.fault(i, false)?;
|
||||||
|
self.esp.delay.delay_ms(500);
|
||||||
|
}
|
||||||
|
for i in 0..PLANT_COUNT {
|
||||||
|
self.pump(i, true)?;
|
||||||
|
self.esp.delay.delay_ms(100);
|
||||||
|
self.pump(i, false)?;
|
||||||
|
self.esp.delay.delay_ms(100);
|
||||||
|
}
|
||||||
|
for plant in 0..PLANT_COUNT {
|
||||||
|
let a = self.measure_moisture_hz(plant, Sensor::A);
|
||||||
|
let b = self.measure_moisture_hz(plant, Sensor::B);
|
||||||
|
let aa = match a {
|
||||||
|
OkStd(a) => a as u32,
|
||||||
|
Err(_) => u32::MAX,
|
||||||
|
};
|
||||||
|
let bb = match b {
|
||||||
|
OkStd(b) => b as u32,
|
||||||
|
Err(_) => u32::MAX,
|
||||||
|
};
|
||||||
|
log(LogMessage::TestSensor, aa, bb, &plant.to_string(), "");
|
||||||
|
}
|
||||||
|
self.esp.delay.delay_ms(10);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_config(&mut self, config: PlantControllerConfig) -> Result<()> {
|
||||||
|
self.config = config;
|
||||||
|
self.esp.save_config(&self.config)?;
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mptt_voltage(&mut self) -> Result<Voltage> {
|
||||||
|
//assuming module to work, these are the hardware set values
|
||||||
|
if self.is_day() {
|
||||||
|
Ok(Voltage::from_volts(15_f64))
|
||||||
|
} else {
|
||||||
|
Ok(Voltage::from_volts(0_f64))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mptt_current(&mut self) -> Result<Current> {
|
||||||
|
bail!("Board does not have current sensor")
|
||||||
|
}
|
||||||
|
}
|
||||||
446
rust/src/hal/v4_hal.rs
Normal file
446
rust/src/hal/v4_hal.rs
Normal file
@@ -0,0 +1,446 @@
|
|||||||
|
use crate::config::PlantControllerConfig;
|
||||||
|
use crate::hal::battery::BatteryInteraction;
|
||||||
|
use crate::hal::esp::Esp;
|
||||||
|
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::{
|
||||||
|
deep_sleep, BoardInteraction, FreePeripherals, Sensor, I2C_DRIVER, PLANT_COUNT
|
||||||
|
};
|
||||||
|
use crate::log::{log, LogMessage};
|
||||||
|
use anyhow::bail;
|
||||||
|
use embedded_hal::digital::OutputPin;
|
||||||
|
use embedded_hal_bus::i2c::MutexDevice;
|
||||||
|
use esp_idf_hal::gpio::{AnyInputPin, IOPin, InputOutput, Output, PinDriver, Pull};
|
||||||
|
use esp_idf_hal::i2c::{I2cDriver, I2cError};
|
||||||
|
use esp_idf_hal::pcnt::{
|
||||||
|
PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex,
|
||||||
|
};
|
||||||
|
use esp_idf_sys::{gpio_hold_dis, gpio_hold_en};
|
||||||
|
use ina219::address::{Address, Pin};
|
||||||
|
use ina219::calibration::UnCalibrated;
|
||||||
|
use ina219::configuration::{Configuration, OperatingMode};
|
||||||
|
use ina219::SyncIna219;
|
||||||
|
use measurements::{Current, Resistance, Voltage};
|
||||||
|
use pca9535::{ExpanderError, GPIOBank, Pca9535Immediate, StandardExpanderInterface};
|
||||||
|
use std::result::Result::Ok as OkStd;
|
||||||
|
use embedded_can::nb::Can;
|
||||||
|
use embedded_can::Frame;
|
||||||
|
use embedded_can::StandardId;
|
||||||
|
use esp_idf_hal::prelude::*;
|
||||||
|
use esp_idf_hal::can;
|
||||||
|
|
||||||
|
pub enum Charger<'a> {
|
||||||
|
SolarMpptV1 {
|
||||||
|
mppt_ina: SyncIna219<MutexDevice<'a, I2cDriver<'a>>, UnCalibrated>,
|
||||||
|
solar_is_day: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, esp_idf_hal::gpio::Input>,
|
||||||
|
charge_indicator: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, InputOutput>,
|
||||||
|
},
|
||||||
|
ErrorInit {},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Charger<'_> {
|
||||||
|
pub(crate) fn power_save(&mut self) {
|
||||||
|
match self {
|
||||||
|
Charger::SolarMpptV1 { mppt_ina, .. } => {
|
||||||
|
let _ = mppt_ina
|
||||||
|
.set_configuration(Configuration {
|
||||||
|
reset: Default::default(),
|
||||||
|
bus_voltage_range: Default::default(),
|
||||||
|
shunt_voltage_range: Default::default(),
|
||||||
|
bus_resolution: Default::default(),
|
||||||
|
shunt_resolution: Default::default(),
|
||||||
|
operating_mode: OperatingMode::PowerDown,
|
||||||
|
})
|
||||||
|
.map_err(|e| {
|
||||||
|
println!(
|
||||||
|
"Error setting ina mppt configuration during deep sleep preparation{:?}",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn set_charge_indicator(&mut self, charging: bool) -> anyhow::Result<()> {
|
||||||
|
match self {
|
||||||
|
Self::SolarMpptV1 {
|
||||||
|
charge_indicator, ..
|
||||||
|
} => {
|
||||||
|
charge_indicator.set_state(charging.into())?;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_day(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Charger::SolarMpptV1 { solar_is_day, .. } => solar_is_day.get_level().into(),
|
||||||
|
_ => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mptt_voltage(&mut self) -> anyhow::Result<Voltage> {
|
||||||
|
let voltage = match self {
|
||||||
|
Charger::SolarMpptV1 { mppt_ina, .. } => mppt_ina
|
||||||
|
.bus_voltage()
|
||||||
|
.map(|v| Voltage::from_millivolts(v.voltage_mv() as f64))?,
|
||||||
|
_ => {
|
||||||
|
bail!("hardware error during init")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(voltage)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mptt_current(&mut self) -> anyhow::Result<Current> {
|
||||||
|
let current = match self {
|
||||||
|
Charger::SolarMpptV1 { mppt_ina, .. } => mppt_ina.shunt_voltage().map(|v| {
|
||||||
|
let shunt_voltage = Voltage::from_microvolts(v.shunt_voltage_uv().abs() as f64);
|
||||||
|
let shut_value = Resistance::from_ohms(0.05_f64);
|
||||||
|
let current = shunt_voltage.as_volts() / shut_value.as_ohms();
|
||||||
|
Current::from_amperes(current)
|
||||||
|
})?,
|
||||||
|
_ => {
|
||||||
|
bail!("hardware error during init")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(current)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct V4<'a> {
|
||||||
|
esp: Esp<'a>,
|
||||||
|
tank_sensor: TankSensor<'a>,
|
||||||
|
charger: Charger<'a>,
|
||||||
|
rtc_module: Box<dyn RTCModuleInteraction + Send>,
|
||||||
|
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
||||||
|
config: PlantControllerConfig,
|
||||||
|
|
||||||
|
awake: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, Output>,
|
||||||
|
light: 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_ina: Option<SyncIna219<MutexDevice<'a, I2cDriver<'a>>, UnCalibrated>>,
|
||||||
|
sensor: SensorImpl<'a>,
|
||||||
|
extra1: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, Output>,
|
||||||
|
extra2: PinDriver<'a, esp_idf_hal::gpio::AnyIOPin, Output>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn create_v4(
|
||||||
|
peripherals: FreePeripherals,
|
||||||
|
esp: Esp<'static>,
|
||||||
|
config: PlantControllerConfig,
|
||||||
|
battery_monitor: Box<dyn BatteryInteraction + Send>,
|
||||||
|
rtc_module: Box<dyn RTCModuleInteraction + Send>,
|
||||||
|
) -> anyhow::Result<Box<dyn BoardInteraction<'static> + Send + 'static>> {
|
||||||
|
println!("Start v4");
|
||||||
|
let mut awake = PinDriver::output(peripherals.gpio21.downgrade())?;
|
||||||
|
awake.set_high()?;
|
||||||
|
|
||||||
|
let mut general_fault = PinDriver::input_output(peripherals.gpio23.downgrade())?;
|
||||||
|
general_fault.set_pull(Pull::Floating)?;
|
||||||
|
general_fault.set_low()?;
|
||||||
|
|
||||||
|
let mut extra1 = PinDriver::output(peripherals.gpio6.downgrade())?;
|
||||||
|
extra1.set_low()?;
|
||||||
|
|
||||||
|
let mut extra2 = PinDriver::output(peripherals.gpio15.downgrade())?;
|
||||||
|
extra2.set_low()?;
|
||||||
|
|
||||||
|
let one_wire_pin = peripherals.gpio18.downgrade();
|
||||||
|
let tank_power_pin = peripherals.gpio11.downgrade();
|
||||||
|
let flow_sensor_pin = peripherals.gpio4.downgrade();
|
||||||
|
|
||||||
|
let tank_sensor = TankSensor::create(
|
||||||
|
one_wire_pin,
|
||||||
|
peripherals.adc1,
|
||||||
|
peripherals.gpio5,
|
||||||
|
tank_power_pin,
|
||||||
|
flow_sensor_pin,
|
||||||
|
peripherals.pcnt1
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let mut sensor_expander = Pca9535Immediate::new(MutexDevice::new(&I2C_DRIVER), 34);
|
||||||
|
let sensor = match sensor_expander.pin_into_output(GPIOBank::Bank0, 0) {
|
||||||
|
Ok(_) => {
|
||||||
|
println!("SensorExpander answered");
|
||||||
|
//pulse counter version
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let mut solar_is_day = PinDriver::input(peripherals.gpio7.downgrade())?;
|
||||||
|
solar_is_day.set_pull(Pull::Floating)?;
|
||||||
|
|
||||||
|
let mut light = PinDriver::input_output(peripherals.gpio10.downgrade())?;
|
||||||
|
light.set_pull(Pull::Floating)?;
|
||||||
|
|
||||||
|
let mut charge_indicator = PinDriver::input_output(peripherals.gpio3.downgrade())?;
|
||||||
|
charge_indicator.set_pull(Pull::Floating)?;
|
||||||
|
charge_indicator.set_low()?;
|
||||||
|
|
||||||
|
let mut pump_expander = Pca9535Immediate::new(MutexDevice::new(&I2C_DRIVER), 32);
|
||||||
|
for pin in 0..8 {
|
||||||
|
let _ = pump_expander.pin_into_output(GPIOBank::Bank0, pin);
|
||||||
|
let _ = pump_expander.pin_into_output(GPIOBank::Bank1, pin);
|
||||||
|
let _ = pump_expander.pin_set_low(GPIOBank::Bank0, pin);
|
||||||
|
let _ = pump_expander.pin_set_low(GPIOBank::Bank1, pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let mppt_ina = SyncIna219::new(
|
||||||
|
MutexDevice::new(&I2C_DRIVER),
|
||||||
|
Address::from_pins(Pin::Vcc, Pin::Gnd),
|
||||||
|
);
|
||||||
|
|
||||||
|
let charger = match mppt_ina {
|
||||||
|
Ok(mut mppt_ina) => {
|
||||||
|
mppt_ina.set_configuration(Configuration {
|
||||||
|
reset: Default::default(),
|
||||||
|
bus_voltage_range: Default::default(),
|
||||||
|
shunt_voltage_range: Default::default(),
|
||||||
|
bus_resolution: Default::default(),
|
||||||
|
shunt_resolution: ina219::configuration::Resolution::Avg128,
|
||||||
|
operating_mode: Default::default(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Charger::SolarMpptV1 {
|
||||||
|
mppt_ina,
|
||||||
|
solar_is_day,
|
||||||
|
charge_indicator,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => Charger::ErrorInit {},
|
||||||
|
};
|
||||||
|
|
||||||
|
let pump_ina = match SyncIna219::new(
|
||||||
|
MutexDevice::new(&I2C_DRIVER),
|
||||||
|
Address::from_pins(Pin::Gnd, Pin::Sda),
|
||||||
|
) {
|
||||||
|
Ok(pump_ina) => Some(pump_ina),
|
||||||
|
Err(err) => {
|
||||||
|
println!("Error creating pump ina: {:?}", err);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let v = V4 {
|
||||||
|
rtc_module,
|
||||||
|
esp,
|
||||||
|
awake,
|
||||||
|
tank_sensor,
|
||||||
|
light,
|
||||||
|
general_fault,
|
||||||
|
pump_ina,
|
||||||
|
pump_expander,
|
||||||
|
config,
|
||||||
|
battery_monitor,
|
||||||
|
charger,
|
||||||
|
extra1,
|
||||||
|
extra2,
|
||||||
|
sensor,
|
||||||
|
};
|
||||||
|
Ok(Box::new(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> BoardInteraction<'a> for V4<'a> {
|
||||||
|
fn get_tank_sensor(&mut self) -> Option<&mut TankSensor<'a>> {
|
||||||
|
Some(&mut self.tank_sensor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_esp(&mut self) -> &mut Esp<'a> {
|
||||||
|
&mut self.esp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_config(&mut self) -> &PlantControllerConfig {
|
||||||
|
&self.config
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_battery_monitor(&mut self) -> &mut Box<dyn BatteryInteraction + Send> {
|
||||||
|
&mut self.battery_monitor
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_rtc_module(&mut self) -> &mut Box<dyn RTCModuleInteraction + Send> {
|
||||||
|
&mut self.rtc_module
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_charge_indicator(&mut self, charging: bool) -> anyhow::Result<()> {
|
||||||
|
self.charger.set_charge_indicator(charging)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deep_sleep(&mut self, duration_in_ms: u64) -> ! {
|
||||||
|
self.awake.set_low().unwrap();
|
||||||
|
self.charger.power_save();
|
||||||
|
deep_sleep(duration_in_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_day(&self) -> bool {
|
||||||
|
self.charger.is_day()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn light(&mut self, enable: bool) -> anyhow::Result<()> {
|
||||||
|
unsafe { gpio_hold_dis(self.light.pin()) };
|
||||||
|
self.light.set_state(enable.into())?;
|
||||||
|
unsafe { gpio_hold_en(self.light.pin()) };
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pump(&mut self, plant: usize, enable: bool) -> anyhow::Result<()> {
|
||||||
|
if enable {
|
||||||
|
self.pump_expander
|
||||||
|
.pin_set_high(GPIOBank::Bank0, plant.try_into()?)?;
|
||||||
|
} else {
|
||||||
|
self.pump_expander
|
||||||
|
.pin_set_low(GPIOBank::Bank0, plant.try_into()?)?;
|
||||||
|
}
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pump_current(&mut self, _plant: usize) -> anyhow::Result<Current> {
|
||||||
|
//sensore is shared for all pumps, ignore plant id
|
||||||
|
match self.pump_ina.as_mut() {
|
||||||
|
None => {
|
||||||
|
bail!("pump current sensor not available");
|
||||||
|
}
|
||||||
|
Some(pump_ina) => {
|
||||||
|
let v = pump_ina.shunt_voltage().map(|v| {
|
||||||
|
let shunt_voltage = Voltage::from_microvolts(v.shunt_voltage_uv().abs() as f64);
|
||||||
|
let shut_value = Resistance::from_ohms(0.05_f64);
|
||||||
|
let current = shunt_voltage.as_volts() / shut_value.as_ohms();
|
||||||
|
Current::from_amperes(current)
|
||||||
|
})?;
|
||||||
|
Ok(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fault(&mut self, plant: usize, enable: bool) -> anyhow::Result<()> {
|
||||||
|
if enable {
|
||||||
|
self.pump_expander
|
||||||
|
.pin_set_high(GPIOBank::Bank1, plant.try_into()?)?
|
||||||
|
} else {
|
||||||
|
self.pump_expander
|
||||||
|
.pin_set_low(GPIOBank::Bank1, plant.try_into()?)?
|
||||||
|
}
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn measure_moisture_hz(&mut self, plant: usize, sensor: Sensor) -> anyhow::Result<f32> {
|
||||||
|
self.sensor.measure_moisture_hz(plant, sensor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn general_fault(&mut self, enable: bool) {
|
||||||
|
unsafe { gpio_hold_dis(self.general_fault.pin()) };
|
||||||
|
self.general_fault.set_state(enable.into()).unwrap();
|
||||||
|
unsafe { gpio_hold_en(self.general_fault.pin()) };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test(&mut self) -> anyhow::Result<()> {
|
||||||
|
self.general_fault(true);
|
||||||
|
self.esp.delay.delay_ms(100);
|
||||||
|
self.general_fault(false);
|
||||||
|
self.esp.delay.delay_ms(500);
|
||||||
|
self.light(true)?;
|
||||||
|
self.esp.delay.delay_ms(500);
|
||||||
|
self.light(false)?;
|
||||||
|
self.esp.delay.delay_ms(500);
|
||||||
|
for i in 0..PLANT_COUNT {
|
||||||
|
self.fault(i, true)?;
|
||||||
|
self.esp.delay.delay_ms(500);
|
||||||
|
self.fault(i, false)?;
|
||||||
|
self.esp.delay.delay_ms(500);
|
||||||
|
}
|
||||||
|
for i in 0..PLANT_COUNT {
|
||||||
|
self.pump(i, true)?;
|
||||||
|
self.esp.delay.delay_ms(100);
|
||||||
|
self.pump(i, false)?;
|
||||||
|
self.esp.delay.delay_ms(100);
|
||||||
|
}
|
||||||
|
for plant in 0..PLANT_COUNT {
|
||||||
|
let a = self.measure_moisture_hz(plant, Sensor::A);
|
||||||
|
let b = self.measure_moisture_hz(plant, Sensor::B);
|
||||||
|
let aa = match a {
|
||||||
|
OkStd(a) => a as u32,
|
||||||
|
Err(_) => u32::MAX,
|
||||||
|
};
|
||||||
|
let bb = match b {
|
||||||
|
OkStd(b) => b as u32,
|
||||||
|
Err(_) => u32::MAX,
|
||||||
|
};
|
||||||
|
log(LogMessage::TestSensor, aa, bb, &plant.to_string(), "");
|
||||||
|
}
|
||||||
|
self.esp.delay.delay_ms(10);
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_config(&mut self, config: PlantControllerConfig) -> anyhow::Result<()> {
|
||||||
|
self.config = config;
|
||||||
|
self.esp.save_config(&self.config)?;
|
||||||
|
anyhow::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mptt_voltage(&mut self) -> anyhow::Result<Voltage> {
|
||||||
|
self.charger.get_mptt_voltage()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_mptt_current(&mut self) -> anyhow::Result<Current> {
|
||||||
|
self.charger.get_mptt_current()
|
||||||
|
}
|
||||||
|
}
|
||||||
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!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
170
rust/src/hal/water.rs
Normal file
170
rust/src/hal/water.rs
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
use crate::hal::TANK_MULTI_SAMPLE;
|
||||||
|
use anyhow::{anyhow, bail};
|
||||||
|
use ds18b20::Ds18b20;
|
||||||
|
use esp_idf_hal::adc::oneshot::config::AdcChannelConfig;
|
||||||
|
use esp_idf_hal::adc::oneshot::{AdcChannelDriver, AdcDriver};
|
||||||
|
use esp_idf_hal::adc::{attenuation, Resolution, ADC1};
|
||||||
|
use esp_idf_hal::delay::Delay;
|
||||||
|
use esp_idf_hal::gpio::{AnyIOPin, AnyInputPin, Gpio5, InputOutput, PinDriver, Pull};
|
||||||
|
use esp_idf_hal::pcnt::{PcntChannel, PcntChannelConfig, PcntControlMode, PcntCountMode, PcntDriver, PinIndex, PCNT1};
|
||||||
|
use esp_idf_sys::EspError;
|
||||||
|
use one_wire_bus::OneWire;
|
||||||
|
|
||||||
|
pub struct TankSensor<'a> {
|
||||||
|
one_wire_bus: OneWire<PinDriver<'a, AnyIOPin, InputOutput>>,
|
||||||
|
tank_channel: AdcChannelDriver<'a, Gpio5, AdcDriver<'a, ADC1>>,
|
||||||
|
tank_power: PinDriver<'a, AnyIOPin, InputOutput>,
|
||||||
|
flow_counter: PcntDriver<'a>,
|
||||||
|
delay: Delay,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TankSensor<'a> {
|
||||||
|
pub(crate) fn create(
|
||||||
|
one_wire_pin: AnyIOPin,
|
||||||
|
adc1: ADC1,
|
||||||
|
gpio5: Gpio5,
|
||||||
|
tank_power_pin: AnyIOPin,
|
||||||
|
flow_sensor_pin: AnyIOPin,
|
||||||
|
pcnt1: PCNT1
|
||||||
|
) -> anyhow::Result<TankSensor<'a>> {
|
||||||
|
let mut one_wire_pin =
|
||||||
|
PinDriver::input_output_od(one_wire_pin).expect("Failed to configure pin");
|
||||||
|
one_wire_pin
|
||||||
|
.set_pull(Pull::Floating)
|
||||||
|
.expect("Failed to set pull");
|
||||||
|
|
||||||
|
let adc_config = AdcChannelConfig {
|
||||||
|
attenuation: attenuation::DB_11,
|
||||||
|
resolution: Resolution::Resolution12Bit,
|
||||||
|
calibration: esp_idf_hal::adc::oneshot::config::Calibration::Curve,
|
||||||
|
};
|
||||||
|
let tank_driver = AdcDriver::new(adc1).expect("Failed to configure ADC");
|
||||||
|
let tank_channel = AdcChannelDriver::new(tank_driver, gpio5, &adc_config)
|
||||||
|
.expect("Failed to configure ADC channel");
|
||||||
|
|
||||||
|
let mut tank_power =
|
||||||
|
PinDriver::input_output(tank_power_pin).expect("Failed to configure pin");
|
||||||
|
tank_power
|
||||||
|
.set_pull(Pull::Floating)
|
||||||
|
.expect("Failed to set pull");
|
||||||
|
|
||||||
|
let one_wire_bus =
|
||||||
|
OneWire::new(one_wire_pin).expect("OneWire bus did not pull up after release");
|
||||||
|
|
||||||
|
let mut flow_counter = PcntDriver::new(
|
||||||
|
pcnt1,
|
||||||
|
Some(flow_sensor_pin),
|
||||||
|
Option::<AnyInputPin>::None,
|
||||||
|
Option::<AnyInputPin>::None,
|
||||||
|
Option::<AnyInputPin>::None,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
flow_counter.channel_config(
|
||||||
|
PcntChannel::Channel1,
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
|
||||||
|
Ok(TankSensor {
|
||||||
|
one_wire_bus,
|
||||||
|
tank_channel,
|
||||||
|
tank_power,
|
||||||
|
flow_counter,
|
||||||
|
delay: Default::default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn reset_flow_meter(&mut self) {
|
||||||
|
self.flow_counter.counter_pause().unwrap();
|
||||||
|
self.flow_counter.counter_clear().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_flow_meter(&mut self) {
|
||||||
|
self.flow_counter.counter_resume().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_flow_meter_value(&mut self) -> i16 {
|
||||||
|
self.flow_counter.get_counter_value().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stop_flow_meter(&mut self) -> i16 {
|
||||||
|
self.flow_counter.counter_pause().unwrap();
|
||||||
|
self.get_flow_meter_value()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn water_temperature_c(&mut self) -> anyhow::Result<f32> {
|
||||||
|
//multisample should be moved to water_temperature_c
|
||||||
|
let mut attempt = 1;
|
||||||
|
let water_temp: Result<f32, anyhow::Error> = loop {
|
||||||
|
let temp = self.single_temperature_c();
|
||||||
|
match &temp {
|
||||||
|
Ok(res) => {
|
||||||
|
println!("Water temp is {}", res);
|
||||||
|
break temp;
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
println!("Could not get water temp {} attempt {}", err, attempt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if attempt == 5 {
|
||||||
|
break temp;
|
||||||
|
}
|
||||||
|
attempt += 1;
|
||||||
|
};
|
||||||
|
water_temp
|
||||||
|
}
|
||||||
|
|
||||||
|
fn single_temperature_c(&mut self) -> anyhow::Result<f32> {
|
||||||
|
self.one_wire_bus
|
||||||
|
.reset(&mut self.delay)
|
||||||
|
.map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?;
|
||||||
|
let first = self.one_wire_bus.devices(false, &mut self.delay).next();
|
||||||
|
if first.is_none() {
|
||||||
|
bail!("Not found any one wire Ds18b20");
|
||||||
|
}
|
||||||
|
let device_address = first
|
||||||
|
.unwrap()
|
||||||
|
.map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?;
|
||||||
|
|
||||||
|
let water_temp_sensor = Ds18b20::new::<EspError>(device_address)
|
||||||
|
.map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?;
|
||||||
|
|
||||||
|
water_temp_sensor
|
||||||
|
.start_temp_measurement(&mut self.one_wire_bus, &mut self.delay)
|
||||||
|
.map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?;
|
||||||
|
ds18b20::Resolution::Bits12.delay_for_measurement_time(&mut self.delay);
|
||||||
|
let sensor_data = water_temp_sensor
|
||||||
|
.read_data(&mut self.one_wire_bus, &mut self.delay)
|
||||||
|
.map_err(|err| -> anyhow::Error { anyhow!("Missing attribute: {:?}", err) })?;
|
||||||
|
if sensor_data.temperature == 85_f32 {
|
||||||
|
bail!("Ds18b20 dummy temperature returned");
|
||||||
|
}
|
||||||
|
anyhow::Ok(sensor_data.temperature / 10_f32)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tank_sensor_voltage(&mut self) -> anyhow::Result<f32> {
|
||||||
|
self.tank_power.set_high()?;
|
||||||
|
//let stabilize
|
||||||
|
self.delay.delay_ms(100);
|
||||||
|
|
||||||
|
let mut store = [0_u16; TANK_MULTI_SAMPLE];
|
||||||
|
for multisample in 0..TANK_MULTI_SAMPLE {
|
||||||
|
let value = self.tank_channel.read()?;
|
||||||
|
store[multisample] = value;
|
||||||
|
}
|
||||||
|
self.tank_power.set_low()?;
|
||||||
|
|
||||||
|
store.sort();
|
||||||
|
let median_mv = store[6] as f32 / 1000_f32;
|
||||||
|
anyhow::Ok(median_mv)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::{collections::{BTreeMap, HashMap}, sync::Mutex};
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use strum::{EnumIter, IntoEnumIterator};
|
use std::{collections::HashMap, sync::Mutex};
|
||||||
use strum_macros::IntoStaticStr;
|
use strum::EnumIter;
|
||||||
|
use strum_macros::IntoStaticStr;
|
||||||
|
|
||||||
use esp_idf_svc::systime::EspSystemTime;
|
use esp_idf_svc::systime::EspSystemTime;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
@@ -9,16 +9,17 @@ use ringbuffer::{ConstGenericRingBuffer, RingBuffer};
|
|||||||
use text_template::Template;
|
use text_template::Template;
|
||||||
use unit_enum::UnitEnum;
|
use unit_enum::UnitEnum;
|
||||||
|
|
||||||
const TXT_SHORT_LENGTH:usize = 8;
|
const TXT_SHORT_LENGTH: usize = 8;
|
||||||
const TXT_LONG_LENGTH:usize = 32;
|
const TXT_LONG_LENGTH: usize = 32;
|
||||||
|
|
||||||
const BUFFER_SIZE:usize = 220;
|
const BUFFER_SIZE: usize = 220;
|
||||||
|
|
||||||
#[link_section = ".rtc.data"]
|
#[link_section = ".rtc.data"]
|
||||||
static mut BUFFER:ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE> = ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>::new();
|
static mut BUFFER: ConstGenericRingBuffer<LogEntry, BUFFER_SIZE> =
|
||||||
|
ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>::new();
|
||||||
#[allow(static_mut_refs)]
|
#[allow(static_mut_refs)]
|
||||||
static BUFFER_ACCESS: Lazy<Mutex<&mut ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>>> = Lazy::new(|| unsafe { Mutex::new(&mut BUFFER) });
|
static BUFFER_ACCESS: Lazy<Mutex<&mut ConstGenericRingBuffer<LogEntry, BUFFER_SIZE>>> =
|
||||||
|
Lazy::new(|| unsafe { Mutex::new(&mut BUFFER) });
|
||||||
|
|
||||||
#[derive(Serialize, Debug, Clone)]
|
#[derive(Serialize, Debug, Clone)]
|
||||||
pub struct LogEntry {
|
pub struct LogEntry {
|
||||||
@@ -27,36 +28,36 @@ pub struct LogEntry {
|
|||||||
pub a: u32,
|
pub a: u32,
|
||||||
pub b: u32,
|
pub b: u32,
|
||||||
pub txt_short: heapless::String<TXT_SHORT_LENGTH>,
|
pub txt_short: heapless::String<TXT_SHORT_LENGTH>,
|
||||||
pub txt_long: heapless::String<TXT_LONG_LENGTH>
|
pub txt_long: heapless::String<TXT_LONG_LENGTH>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(){
|
pub fn init() {
|
||||||
unsafe {
|
unsafe {
|
||||||
BUFFER = ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>::new();
|
BUFFER = ConstGenericRingBuffer::<LogEntry, BUFFER_SIZE>::new();
|
||||||
};
|
};
|
||||||
let mut access = BUFFER_ACCESS.lock().unwrap();
|
let mut access = BUFFER_ACCESS.lock().unwrap();
|
||||||
access.drain().for_each(|_| {});
|
access.drain().for_each(|_| {});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn limit_length <const LIMIT:usize> (input: &str, target: &mut heapless::String<LIMIT>){
|
fn limit_length<const LIMIT: usize>(input: &str, target: &mut heapless::String<LIMIT>) {
|
||||||
for char in input.chars() {
|
for char in input.chars() {
|
||||||
match target.push(char) {
|
match target.push(char) {
|
||||||
Ok(_) => {}, //continue adding chars
|
Ok(_) => {} //continue adding chars
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
//clear space for two asci chars
|
//clear space for two asci chars
|
||||||
while target.len()+2 >= LIMIT {
|
while target.len() + 2 >= LIMIT {
|
||||||
target.pop().unwrap();
|
target.pop().unwrap();
|
||||||
}
|
}
|
||||||
//add .. to shortened strings
|
//add .. to shortened strings
|
||||||
target.push('.').unwrap();
|
target.push('.').unwrap();
|
||||||
target.push('.').unwrap();
|
target.push('.').unwrap();
|
||||||
return;
|
return;
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_log() -> Vec<LogEntry>{
|
pub fn get_log() -> Vec<LogEntry> {
|
||||||
let buffer = BUFFER_ACCESS.lock().unwrap();
|
let buffer = BUFFER_ACCESS.lock().unwrap();
|
||||||
let mut read_copy = Vec::new();
|
let mut read_copy = Vec::new();
|
||||||
for entry in buffer.iter() {
|
for entry in buffer.iter() {
|
||||||
@@ -64,22 +65,20 @@ pub fn get_log() -> Vec<LogEntry>{
|
|||||||
read_copy.push(copy);
|
read_copy.push(copy);
|
||||||
}
|
}
|
||||||
drop(buffer);
|
drop(buffer);
|
||||||
return read_copy;
|
read_copy
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn log(message_key: LogMessage, number_a: u32, number_b: u32, txt_short:&str, txt_long:&str){
|
pub fn log(message_key: LogMessage, number_a: u32, number_b: u32, txt_short: &str, txt_long: &str) {
|
||||||
let mut txt_short_stack:heapless::String<TXT_SHORT_LENGTH> = heapless::String::new();
|
let mut txt_short_stack: heapless::String<TXT_SHORT_LENGTH> = heapless::String::new();
|
||||||
let mut txt_long_stack:heapless::String<TXT_LONG_LENGTH> = heapless::String::new();
|
let mut txt_long_stack: heapless::String<TXT_LONG_LENGTH> = heapless::String::new();
|
||||||
|
|
||||||
limit_length(txt_short, &mut txt_short_stack);
|
limit_length(txt_short, &mut txt_short_stack);
|
||||||
limit_length(txt_long, &mut txt_long_stack);
|
limit_length(txt_long, &mut txt_long_stack);
|
||||||
|
|
||||||
let time = EspSystemTime {}.now().as_millis() as u64;
|
let time = EspSystemTime {}.now().as_millis() as u64;
|
||||||
|
|
||||||
|
|
||||||
let ordinal = message_key.ordinal() as u16;
|
let ordinal = message_key.ordinal() as u16;
|
||||||
let template_string:&str = message_key.into();
|
let template_string: &str = message_key.into();
|
||||||
|
|
||||||
|
|
||||||
let mut values: HashMap<&str, &str> = HashMap::new();
|
let mut values: HashMap<&str, &str> = HashMap::new();
|
||||||
let number_a_str = number_a.to_string();
|
let number_a_str = number_a.to_string();
|
||||||
@@ -92,12 +91,11 @@ pub fn log(message_key: LogMessage, number_a: u32, number_b: u32, txt_short:&str
|
|||||||
|
|
||||||
let template = Template::from(template_string);
|
let template = Template::from(template_string);
|
||||||
let serial_entry = template.fill_in(&values);
|
let serial_entry = template.fill_in(&values);
|
||||||
|
|
||||||
println!("{serial_entry}");
|
println!("{serial_entry}");
|
||||||
|
//TODO push to mqtt?
|
||||||
|
|
||||||
|
let entry = LogEntry {
|
||||||
let entry = LogEntry{
|
|
||||||
timestamp: time,
|
timestamp: time,
|
||||||
message_id: ordinal,
|
message_id: ordinal,
|
||||||
a: number_a,
|
a: number_a,
|
||||||
@@ -106,14 +104,10 @@ pub fn log(message_key: LogMessage, number_a: u32, number_b: u32, txt_short:&str
|
|||||||
txt_long: txt_long_stack,
|
txt_long: txt_long_stack,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut buffer = BUFFER_ACCESS.lock().unwrap();
|
||||||
let mut buffer = BUFFER_ACCESS.lock().unwrap();
|
|
||||||
buffer.push(entry);
|
buffer.push(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -121,9 +115,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn within_limit() {
|
fn within_limit() {
|
||||||
let test = "12345678";
|
let test = "12345678";
|
||||||
|
|
||||||
let mut txt_short_stack:heapless::String<TXT_SHORT_LENGTH> = heapless::String::new();
|
let mut txt_short_stack: heapless::String<TXT_SHORT_LENGTH> = heapless::String::new();
|
||||||
let mut txt_long_stack:heapless::String<TXT_LONG_LENGTH> = heapless::String::new();
|
let mut txt_long_stack: heapless::String<TXT_LONG_LENGTH> = heapless::String::new();
|
||||||
limit_length(test, &mut txt_short_stack);
|
limit_length(test, &mut txt_short_stack);
|
||||||
limit_length(test, &mut txt_long_stack);
|
limit_length(test, &mut txt_long_stack);
|
||||||
|
|
||||||
@@ -132,39 +126,51 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(IntoStaticStr, EnumIter, Serialize, PartialEq, Eq, PartialOrd, Ord, Clone, UnitEnum)]
|
#[derive(IntoStaticStr, EnumIter, Serialize, PartialEq, Eq, PartialOrd, Ord, Clone, UnitEnum)]
|
||||||
pub enum LogMessage {
|
pub enum LogMessage {
|
||||||
#[strum(serialize = "Reset due to ${txt_long} requires rtc clear ${number_a} and force config mode ${number_b}")]
|
#[strum(
|
||||||
|
serialize = "Reset due to ${txt_long} requires rtc clear ${number_a} and force config mode ${number_b}"
|
||||||
|
)]
|
||||||
ResetReason,
|
ResetReason,
|
||||||
#[strum(serialize = "Current restart to conf mode ${number_a}")]
|
#[strum(serialize = "Current restart to conf mode ${number_a}")]
|
||||||
RestartToConfig,
|
RestartToConfig,
|
||||||
#[strum(serialize = "Current low voltage detection is ${number_a}")]
|
#[strum(serialize = "Current low voltage detection is ${number_a}")]
|
||||||
LowVoltage,
|
LowVoltage,
|
||||||
#[strum(serialize = "Error communicating with battery!! ${txt_long}")]
|
#[strum(serialize = "Error communicating with battery!! ${txt_long}")]
|
||||||
BatteryCommunicationError,
|
BatteryCommunicationError,
|
||||||
#[strum(serialize = "Tank sensor raw ${number_a} percent ${number_b}")]
|
#[strum(serialize = "Tank water level cricial! Refill tank!")]
|
||||||
SensorTankRaw,
|
TankWaterLevelLow,
|
||||||
#[strum(serialize = "raw measure unscaled ${number_a} hz ${number_b}, plant ${txt_short} sensor ${txt_long}")]
|
#[strum(serialize = "Tank sensor hardware error: ${txt_long}")]
|
||||||
|
TankSensorBoardError,
|
||||||
|
#[strum(serialize = "Tank sensor not present, raw voltage measured = ${number_a} mV")]
|
||||||
|
TankSensorMissing,
|
||||||
|
#[strum(
|
||||||
|
serialize = "Tank sensor value out of range, min = ${number_a}%, max = ${number_b}%, value = ${text_short}%"
|
||||||
|
)]
|
||||||
|
TankSensorValueRangeError,
|
||||||
|
#[strum(
|
||||||
|
serialize = "raw measure unscaled ${number_a} hz ${number_b}, plant ${txt_short} sensor ${txt_long}"
|
||||||
|
)]
|
||||||
RawMeasure,
|
RawMeasure,
|
||||||
#[strum(serialize = "IP info: ${txt_long}")]
|
#[strum(serialize = "IP info: ${txt_long}")]
|
||||||
WifiInfo,
|
WifiInfo,
|
||||||
#[strum(serialize = "Plant:${txt_short} a:${number_a} b:${number_b}")]
|
#[strum(serialize = "Plant:${txt_short} a:${number_a} b:${number_b}")]
|
||||||
TestSensor,
|
TestSensor,
|
||||||
#[strum(serialize = "Stay alive topic is ${txt_long}")]
|
#[strum(serialize = "Stay alive topic is ${txt_long}")]
|
||||||
StayAlive,
|
StayAlive,
|
||||||
#[strum(serialize = "Connecting mqtt ${txt_short} with id ${txt_long}")]
|
#[strum(serialize = "Connecting mqtt ${txt_short} with id ${txt_long}")]
|
||||||
MqttInfo,
|
MqttInfo,
|
||||||
#[strum(serialize = "Received stay alive with value ${txt_short}")]
|
#[strum(serialize = "Received stay alive with value ${txt_short}")]
|
||||||
MqttStayAliveRec,
|
MqttStayAliveRec,
|
||||||
#[strum(serialize = "Unknown topic recieved ${txt_long}")]
|
#[strum(serialize = "Unknown topic recieved ${txt_long}")]
|
||||||
UnknownTopic,
|
UnknownTopic,
|
||||||
#[strum(serialize = "Partition state is ${txt_long}")]
|
#[strum(serialize = "Partition state is ${txt_long}")]
|
||||||
PartitionState,
|
PartitionState,
|
||||||
#[strum(serialize = "Mounted Filesystem free ${number_a} total ${number_b} use ${txt_short}")]
|
#[strum(serialize = "Mounted Filesystem free ${number_a} total ${number_b} use ${txt_short}")]
|
||||||
FilesystemMount,
|
FilesystemMount,
|
||||||
#[strum(serialize = "Mounting Filesystem, this will format the first time and needs quite some time!")]
|
#[strum(
|
||||||
|
serialize = "Mounting Filesystem, this will format the first time and needs quite some time!"
|
||||||
|
)]
|
||||||
MountingFilesystem,
|
MountingFilesystem,
|
||||||
#[strum(serialize = "Year inplausible, force config mode")]
|
#[strum(serialize = "Year inplausible, force config mode")]
|
||||||
YearInplausibleForceConfig,
|
YearInplausibleForceConfig,
|
||||||
@@ -178,21 +184,48 @@ pub enum LogMessage {
|
|||||||
ConfigModeMissingConfig,
|
ConfigModeMissingConfig,
|
||||||
#[strum(serialize = "startup state wifi ${number_a} sntp ${number_b} mqtt ${txt_short}")]
|
#[strum(serialize = "startup state wifi ${number_a} sntp ${number_b} mqtt ${txt_short}")]
|
||||||
StartupInfo,
|
StartupInfo,
|
||||||
#[strum(serialize = "Trying to pump for ${number_b}s with pump ${number_a} now dryrun: ${txt_short}")]
|
#[strum(
|
||||||
|
serialize = "Trying to pump for ${number_b}s with pump ${number_a} now dryrun: ${txt_short}"
|
||||||
|
)]
|
||||||
PumpPlant,
|
PumpPlant,
|
||||||
#[strum(serialize = "Enable main power dryrun: ${number_a}")]
|
#[strum(serialize = "Enable main power dryrun: ${number_a}")]
|
||||||
EnableMain,
|
EnableMain,
|
||||||
#[strum(serialize = "Pumped multiple times, but plant is still to try attempt: ${number_a} limit :: ${number_b} plant: ${txt_short}")]
|
#[strum(
|
||||||
ConsecutivePumpCountLimit
|
serialize = "Pumped multiple times, but plant is still to try attempt: ${number_a} limit :: ${number_b} plant: ${txt_short}"
|
||||||
|
)]
|
||||||
|
ConsecutivePumpCountLimit,
|
||||||
|
#[strum(
|
||||||
|
serialize = "Pump Overcurrent error, pump: ${number_a} tripped overcurrent ${number_b} limit was ${txt_short} @s ${txt_long}"
|
||||||
|
)]
|
||||||
|
PumpOverCurrent,
|
||||||
|
#[strum(
|
||||||
|
serialize = "Pump Open loop error, pump: ${number_a} is low, ${number_b} limit was ${txt_short} @s ${txt_long}"
|
||||||
|
)]
|
||||||
|
PumpOpenLoopCurrent,
|
||||||
|
#[strum(serialize = "Pump Open current sensor required but did not work: ${number_a}")]
|
||||||
|
PumpMissingSensorCurrent,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
pub struct MessageTranslation {
|
||||||
|
msg_type: LogMessage,
|
||||||
|
message: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&LogMessage> for MessageTranslation {
|
||||||
|
fn from(value: &LogMessage) -> Self {
|
||||||
|
Self {
|
||||||
|
msg_type: value.clone(),
|
||||||
|
message: value.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LogMessage {
|
impl LogMessage {
|
||||||
pub fn to_log_localisation_config() -> BTreeMap<LogMessage,&'static str> {
|
pub fn to_log_localisation_config() -> Vec<MessageTranslation> {
|
||||||
let mut data = BTreeMap::new();
|
Vec::from_iter((0..LogMessage::len()).map(|i| {
|
||||||
for msg_type in LogMessage::iter() {
|
let msg_type = LogMessage::from_ordinal(i).unwrap();
|
||||||
let s: &'static str = msg_type.clone().into();
|
(&msg_type).into()
|
||||||
data.insert(msg_type, s);
|
}))
|
||||||
}
|
|
||||||
data
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
1517
rust/src/main.rs
1517
rust/src/main.rs
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
309
rust/src/plant_state.rs
Normal file
309
rust/src/plant_state.rs
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
use crate::{
|
||||||
|
config::PlantConfig,
|
||||||
|
hal::{Sensor, HAL},
|
||||||
|
in_time_range,
|
||||||
|
};
|
||||||
|
use chrono::{DateTime, TimeDelta, Utc};
|
||||||
|
use chrono_tz::Tz;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
const MOIST_SENSOR_MAX_FREQUENCY: f32 = 7500.; // 60kHz (500Hz margin)
|
||||||
|
const MOIST_SENSOR_MIN_FREQUENCY: f32 = 150.; // this is really, really dry, think like cactus levels
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize)]
|
||||||
|
pub enum MoistureSensorError {
|
||||||
|
ShortCircuit { hz: f32, max: f32 },
|
||||||
|
OpenLoop { hz: f32, min: f32 },
|
||||||
|
BoardError(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize)]
|
||||||
|
pub enum MoistureSensorState {
|
||||||
|
Disabled,
|
||||||
|
MoistureValue { raw_hz: f32, moisture_percent: f32 },
|
||||||
|
SensorError(MoistureSensorError),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MoistureSensorState {
|
||||||
|
pub fn is_err(&self) -> Option<&MoistureSensorError> {
|
||||||
|
match self {
|
||||||
|
MoistureSensorState::SensorError(moisture_sensor_error) => Some(moisture_sensor_error),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn moisture_percent(&self) -> Option<f32> {
|
||||||
|
if let MoistureSensorState::MoistureValue {
|
||||||
|
raw_hz: _,
|
||||||
|
moisture_percent,
|
||||||
|
} = self
|
||||||
|
{
|
||||||
|
Some(*moisture_percent)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MoistureSensorState {}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize)]
|
||||||
|
pub enum PumpError {
|
||||||
|
PumpNotWorking {
|
||||||
|
failed_attempts: usize,
|
||||||
|
max_allowed_failures: usize,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
pub struct PumpState {
|
||||||
|
consecutive_pump_count: u32,
|
||||||
|
previous_pump: Option<DateTime<Utc>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PumpState {
|
||||||
|
fn is_err(&self, plant_config: &PlantConfig) -> Option<PumpError> {
|
||||||
|
if self.consecutive_pump_count > plant_config.max_consecutive_pump_count as u32 {
|
||||||
|
Some(PumpError::PumpNotWorking {
|
||||||
|
failed_attempts: self.consecutive_pump_count as usize,
|
||||||
|
max_allowed_failures: plant_config.max_consecutive_pump_count as usize,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub enum PlantWateringMode {
|
||||||
|
OFF,
|
||||||
|
TargetMoisture,
|
||||||
|
TimerOnly,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PlantState {
|
||||||
|
pub sensor_a: MoistureSensorState,
|
||||||
|
pub sensor_b: MoistureSensorState,
|
||||||
|
pub pump: PumpState,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn map_range_moisture(
|
||||||
|
s: f32,
|
||||||
|
min_frequency: Option<f32>,
|
||||||
|
max_frequency: Option<f32>,
|
||||||
|
) -> Result<f32, MoistureSensorError> {
|
||||||
|
// Use overrides if provided, otherwise fallback to defaults
|
||||||
|
let min_freq = min_frequency.unwrap_or(MOIST_SENSOR_MIN_FREQUENCY);
|
||||||
|
let max_freq = max_frequency.unwrap_or(MOIST_SENSOR_MAX_FREQUENCY);
|
||||||
|
|
||||||
|
if s < min_freq {
|
||||||
|
return Err(MoistureSensorError::OpenLoop {
|
||||||
|
hz: s,
|
||||||
|
min: min_freq,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if s > max_freq {
|
||||||
|
return Err(MoistureSensorError::ShortCircuit {
|
||||||
|
hz: s,
|
||||||
|
max: max_freq,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let moisture_percent = (s - min_freq) * 100.0 / (max_freq - min_freq);
|
||||||
|
|
||||||
|
Ok(moisture_percent)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlantState {
|
||||||
|
pub fn read_hardware_state(plant_id: usize, board: &mut HAL) -> Self {
|
||||||
|
let sensor_a = if board.board_hal.get_config().plants[plant_id].sensor_a {
|
||||||
|
match board.board_hal.measure_moisture_hz(plant_id, Sensor::A) {
|
||||||
|
Ok(raw) => match map_range_moisture(
|
||||||
|
raw,
|
||||||
|
board.board_hal.get_config().plants[plant_id].moisture_sensor_min_frequency,
|
||||||
|
board.board_hal.get_config().plants[plant_id].moisture_sensor_max_frequency,
|
||||||
|
) {
|
||||||
|
Ok(moisture_percent) => MoistureSensorState::MoistureValue {
|
||||||
|
raw_hz: raw,
|
||||||
|
moisture_percent,
|
||||||
|
},
|
||||||
|
Err(err) => MoistureSensorState::SensorError(err),
|
||||||
|
},
|
||||||
|
Err(err) => MoistureSensorState::SensorError(MoistureSensorError::BoardError(
|
||||||
|
err.to_string(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MoistureSensorState::Disabled
|
||||||
|
};
|
||||||
|
|
||||||
|
let sensor_b = if board.board_hal.get_config().plants[plant_id].sensor_b {
|
||||||
|
match board.board_hal.measure_moisture_hz(plant_id, Sensor::B) {
|
||||||
|
Ok(raw) => match map_range_moisture(
|
||||||
|
raw,
|
||||||
|
board.board_hal.get_config().plants[plant_id].moisture_sensor_min_frequency,
|
||||||
|
board.board_hal.get_config().plants[plant_id].moisture_sensor_max_frequency,
|
||||||
|
) {
|
||||||
|
Ok(moisture_percent) => MoistureSensorState::MoistureValue {
|
||||||
|
raw_hz: raw,
|
||||||
|
moisture_percent,
|
||||||
|
},
|
||||||
|
Err(err) => MoistureSensorState::SensorError(err),
|
||||||
|
},
|
||||||
|
Err(err) => MoistureSensorState::SensorError(MoistureSensorError::BoardError(
|
||||||
|
err.to_string(),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MoistureSensorState::Disabled
|
||||||
|
};
|
||||||
|
|
||||||
|
let previous_pump = board.board_hal.get_esp().last_pump_time(plant_id);
|
||||||
|
let consecutive_pump_count = board.board_hal.get_esp().consecutive_pump_count(plant_id);
|
||||||
|
let state = Self {
|
||||||
|
sensor_a,
|
||||||
|
sensor_b,
|
||||||
|
pump: PumpState {
|
||||||
|
consecutive_pump_count,
|
||||||
|
previous_pump,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
if state.is_err() {
|
||||||
|
let _ = board.board_hal.fault(plant_id, true);
|
||||||
|
}
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pump_in_timeout(&self, plant_conf: &PlantConfig, current_time: &DateTime<Tz>) -> bool {
|
||||||
|
if matches!(plant_conf.mode, PlantWateringMode::OFF) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
self.pump.previous_pump.is_some_and(|last_pump| {
|
||||||
|
last_pump
|
||||||
|
.checked_add_signed(TimeDelta::minutes(plant_conf.pump_cooldown_min.into()))
|
||||||
|
.is_some_and(|earliest_next_allowed_pump| {
|
||||||
|
earliest_next_allowed_pump > *current_time
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_err(&self) -> bool {
|
||||||
|
self.sensor_a.is_err().is_some() || self.sensor_b.is_err().is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn plant_moisture(
|
||||||
|
&self,
|
||||||
|
) -> (
|
||||||
|
Option<f32>,
|
||||||
|
(Option<&MoistureSensorError>, Option<&MoistureSensorError>),
|
||||||
|
) {
|
||||||
|
match (
|
||||||
|
self.sensor_a.moisture_percent(),
|
||||||
|
self.sensor_b.moisture_percent(),
|
||||||
|
) {
|
||||||
|
(Some(moisture_a), Some(moisture_b)) => {
|
||||||
|
(Some((moisture_a + moisture_b) / 2.), (None, None))
|
||||||
|
}
|
||||||
|
(Some(moisture_percent), _) => (Some(moisture_percent), (None, self.sensor_b.is_err())),
|
||||||
|
(_, Some(moisture_percent)) => (Some(moisture_percent), (self.sensor_a.is_err(), None)),
|
||||||
|
_ => (None, (self.sensor_a.is_err(), self.sensor_b.is_err())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn needs_to_be_watered(
|
||||||
|
&self,
|
||||||
|
plant_conf: &PlantConfig,
|
||||||
|
current_time: &DateTime<Tz>,
|
||||||
|
) -> bool {
|
||||||
|
match plant_conf.mode {
|
||||||
|
PlantWateringMode::OFF => false,
|
||||||
|
PlantWateringMode::TargetMoisture => {
|
||||||
|
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 moisture_percent < plant_conf.target_moisture {
|
||||||
|
in_time_range(
|
||||||
|
current_time,
|
||||||
|
plant_conf.pump_hour_start,
|
||||||
|
plant_conf.pump_hour_end,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// in case no moisture can be determined, do not water the plant
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PlantWateringMode::TimerOnly => !self.pump_in_timeout(plant_conf, current_time),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_mqtt_info(
|
||||||
|
&self,
|
||||||
|
plant_conf: &PlantConfig,
|
||||||
|
current_time: &DateTime<Tz>,
|
||||||
|
) -> PlantInfo<'_> {
|
||||||
|
PlantInfo {
|
||||||
|
sensor_a: &self.sensor_a,
|
||||||
|
sensor_b: &self.sensor_b,
|
||||||
|
mode: plant_conf.mode,
|
||||||
|
do_water: self.needs_to_be_watered(plant_conf, current_time),
|
||||||
|
dry: if let Some(moisture_percent) = self.plant_moisture().0 {
|
||||||
|
moisture_percent < plant_conf.target_moisture
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
},
|
||||||
|
cooldown: self.pump_in_timeout(plant_conf, current_time),
|
||||||
|
out_of_work_hour: in_time_range(
|
||||||
|
current_time,
|
||||||
|
plant_conf.pump_hour_start,
|
||||||
|
plant_conf.pump_hour_end,
|
||||||
|
),
|
||||||
|
consecutive_pump_count: self.pump.consecutive_pump_count,
|
||||||
|
pump_error: self.pump.is_err(plant_conf),
|
||||||
|
last_pump: self
|
||||||
|
.pump
|
||||||
|
.previous_pump
|
||||||
|
.map(|t| t.with_timezone(¤t_time.timezone())),
|
||||||
|
next_pump: if matches!(
|
||||||
|
plant_conf.mode,
|
||||||
|
PlantWateringMode::TimerOnly | PlantWateringMode::TargetMoisture
|
||||||
|
) {
|
||||||
|
self.pump.previous_pump.and_then(|last_pump| {
|
||||||
|
last_pump
|
||||||
|
.checked_add_signed(TimeDelta::minutes(plant_conf.pump_cooldown_min.into()))
|
||||||
|
.map(|t| t.with_timezone(¤t_time.timezone()))
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Serialize)]
|
||||||
|
/// State of a single plant to be tracked
|
||||||
|
pub struct PlantInfo<'a> {
|
||||||
|
/// state of humidity sensor on bank a
|
||||||
|
sensor_a: &'a MoistureSensorState,
|
||||||
|
/// state of humidity sensor on bank b
|
||||||
|
sensor_b: &'a MoistureSensorState,
|
||||||
|
/// configured plant watering mode
|
||||||
|
mode: PlantWateringMode,
|
||||||
|
/// the plant needs to be watered
|
||||||
|
do_water: bool,
|
||||||
|
/// plant is considered to be dry according to settings
|
||||||
|
dry: bool,
|
||||||
|
/// plant irrigation cooldown is active
|
||||||
|
cooldown: bool,
|
||||||
|
/// plant should not be watered at this time of day TODO: does this really belong here? Isn't this a global setting?
|
||||||
|
out_of_work_hour: bool,
|
||||||
|
/// how often has the pump been watered without reaching target moisture
|
||||||
|
consecutive_pump_count: u32,
|
||||||
|
pump_error: Option<PumpError>,
|
||||||
|
/// last time when the pump was active
|
||||||
|
last_pump: Option<DateTime<Tz>>,
|
||||||
|
/// next time when pump should activate
|
||||||
|
next_pump: Option<DateTime<Tz>>,
|
||||||
|
}
|
||||||
@@ -100,7 +100,7 @@ macro_rules! ShiftRegisterBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get embedded-hal output pins to control the shift register outputs
|
/// Get embedded-hal output pins to control the shift register outputs
|
||||||
pub fn decompose(&self) -> [ShiftRegisterPin; $size] {
|
pub fn decompose(&self) -> [ShiftRegisterPin<'_>; $size] {
|
||||||
// Create an uninitialized array of `MaybeUninit`. The `assume_init` is
|
// Create an uninitialized array of `MaybeUninit`. The `assume_init` is
|
||||||
// safe because the type we are claiming to have initialized here is a
|
// safe because the type we are claiming to have initialized here is a
|
||||||
// bunch of `MaybeUninit`s, which do not require initialization.
|
// bunch of `MaybeUninit`s, which do not require initialization.
|
||||||
|
|||||||
189
rust/src/tank.rs
Normal file
189
rust/src/tank.rs
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
use crate::{config::TankConfig, hal::HAL};
|
||||||
|
use anyhow::Context;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
const OPEN_TANK_VOLTAGE: f32 = 3.0;
|
||||||
|
pub const WATER_FROZEN_THRESH: f32 = 4.0;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize)]
|
||||||
|
pub enum TankError {
|
||||||
|
SensorDisabled,
|
||||||
|
SensorMissing(f32),
|
||||||
|
SensorValueError { value: f32, min: f32, max: f32 },
|
||||||
|
BoardError(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum TankState {
|
||||||
|
Present(f32),
|
||||||
|
Error(TankError),
|
||||||
|
Disabled,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn raw_voltage_to_divider_percent(raw_value_mv: f32) -> Result<f32, TankError> {
|
||||||
|
if raw_value_mv > OPEN_TANK_VOLTAGE {
|
||||||
|
return Err(TankError::SensorMissing(raw_value_mv));
|
||||||
|
}
|
||||||
|
|
||||||
|
let r2 = raw_value_mv * 50.0 / (3.3 - raw_value_mv);
|
||||||
|
let mut percent = r2 / 190_f32 * 100_f32;
|
||||||
|
percent = percent.clamp(0.0, 100.0);
|
||||||
|
Ok(percent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn raw_voltage_to_tank_fill_percent(
|
||||||
|
raw_value_mv: f32,
|
||||||
|
config: &TankConfig,
|
||||||
|
) -> Result<f32, TankError> {
|
||||||
|
let divider_percent = raw_voltage_to_divider_percent(raw_value_mv)?;
|
||||||
|
if divider_percent < config.tank_empty_percent.into()
|
||||||
|
|| divider_percent > config.tank_full_percent.into()
|
||||||
|
{
|
||||||
|
return Err(TankError::SensorValueError {
|
||||||
|
value: divider_percent,
|
||||||
|
min: config.tank_empty_percent.into(),
|
||||||
|
max: config.tank_full_percent.into(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(
|
||||||
|
(divider_percent - f32::from(config.tank_empty_percent)) * 100.
|
||||||
|
/ f32::from(config.tank_full_percent - config.tank_empty_percent),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TankState {
|
||||||
|
pub fn left_ml(&self, config: &TankConfig) -> Result<f32, TankError> {
|
||||||
|
match self {
|
||||||
|
TankState::Disabled => Err(TankError::SensorDisabled),
|
||||||
|
TankState::Error(err) => Err(err.clone()),
|
||||||
|
TankState::Present(raw_value_mv) => {
|
||||||
|
let tank_fill_percent = raw_voltage_to_tank_fill_percent(*raw_value_mv, config)?;
|
||||||
|
Ok(config.tank_useable_ml as f32 * tank_fill_percent / 100.)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn enough_water(&self, config: &TankConfig) -> Result<bool, TankError> {
|
||||||
|
match self {
|
||||||
|
TankState::Disabled => Err(TankError::SensorDisabled),
|
||||||
|
TankState::Error(err) => Err(err.clone()),
|
||||||
|
TankState::Present(raw_value_mv) => {
|
||||||
|
let tank_fill_percent = raw_voltage_to_tank_fill_percent(*raw_value_mv, config)?;
|
||||||
|
if tank_fill_percent > config.tank_empty_percent.into() {
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_enabled(&self) -> bool {
|
||||||
|
!matches!(self, TankState::Disabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn warn_level(&self, config: &TankConfig) -> Result<bool, TankError> {
|
||||||
|
match self {
|
||||||
|
TankState::Disabled => Err(TankError::SensorDisabled),
|
||||||
|
TankState::Error(err) => Err(err.clone()),
|
||||||
|
TankState::Present(raw_value_mv) => {
|
||||||
|
let tank_fill_percent = raw_voltage_to_tank_fill_percent(*raw_value_mv, config);
|
||||||
|
match tank_fill_percent {
|
||||||
|
Ok(value) => {
|
||||||
|
if value < config.tank_warn_percent.into() {
|
||||||
|
Ok(true)
|
||||||
|
} else {
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => match err {
|
||||||
|
TankError::SensorValueError { value, min, max: _ } => Ok(value < min),
|
||||||
|
_ => Err(err),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn got_error(&self, config: &TankConfig) -> Option<TankError> {
|
||||||
|
match self {
|
||||||
|
TankState::Present(raw_value_mv) => {
|
||||||
|
raw_voltage_to_tank_fill_percent(*raw_value_mv, config).err()
|
||||||
|
}
|
||||||
|
TankState::Error(err) => Some(err.clone()),
|
||||||
|
TankState::Disabled => Some(TankError::SensorDisabled),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_mqtt_info(&self, config: &TankConfig, water_temp: &anyhow::Result<f32>) -> TankInfo {
|
||||||
|
let mut tank_err: Option<TankError> = None;
|
||||||
|
let left_ml = match self.left_ml(config) {
|
||||||
|
Err(err) => {
|
||||||
|
tank_err = Some(err);
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Ok(left_ml) => Some(left_ml),
|
||||||
|
};
|
||||||
|
let enough_water = self.enough_water(config).unwrap_or(false); //NOTE: is this correct if there is an error assume not enough water?
|
||||||
|
let warn_level = self.warn_level(config).unwrap_or(false); //NOTE: should warn level be triggered if there is an error?
|
||||||
|
let raw = match self {
|
||||||
|
TankState::Disabled | TankState::Error(_) => None,
|
||||||
|
TankState::Present(raw_value_mv) => Some(*raw_value_mv),
|
||||||
|
};
|
||||||
|
|
||||||
|
let percent = match raw {
|
||||||
|
Some(r) => raw_voltage_to_tank_fill_percent(r, config).ok(),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
TankInfo {
|
||||||
|
enough_water,
|
||||||
|
warn_level,
|
||||||
|
left_ml,
|
||||||
|
sensor_error: tank_err,
|
||||||
|
raw,
|
||||||
|
water_frozen: water_temp
|
||||||
|
.as_ref()
|
||||||
|
.is_ok_and(|temp| *temp < WATER_FROZEN_THRESH),
|
||||||
|
water_temp: water_temp.as_ref().copied().ok(),
|
||||||
|
temp_sensor_error: water_temp.as_ref().err().map(|err| err.to_string()),
|
||||||
|
percent,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn determine_tank_state(board: &mut std::sync::MutexGuard<'_, HAL<'_>>) -> TankState {
|
||||||
|
if board.board_hal.get_config().tank.tank_sensor_enabled {
|
||||||
|
match board
|
||||||
|
.board_hal
|
||||||
|
.get_tank_sensor()
|
||||||
|
.context("no sensor")
|
||||||
|
.and_then(|f| f.tank_sensor_voltage())
|
||||||
|
{
|
||||||
|
Ok(raw_sensor_value_mv) => TankState::Present(raw_sensor_value_mv),
|
||||||
|
Err(err) => TankState::Error(TankError::BoardError(err.to_string())),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TankState::Disabled
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize)]
|
||||||
|
/// Information structure send to mqtt for monitoring purposes
|
||||||
|
pub struct TankInfo {
|
||||||
|
/// there is enough water in the tank
|
||||||
|
enough_water: bool,
|
||||||
|
/// warning that water needs to be refilled soon
|
||||||
|
warn_level: bool,
|
||||||
|
/// estimation how many ml are still in the tank
|
||||||
|
left_ml: Option<f32>,
|
||||||
|
/// if there is an issue with the water level sensor
|
||||||
|
sensor_error: Option<TankError>,
|
||||||
|
/// raw water sensor value
|
||||||
|
raw: Option<f32>,
|
||||||
|
/// percent value
|
||||||
|
percent: Option<f32>,
|
||||||
|
/// water in the tank might be frozen
|
||||||
|
water_frozen: bool,
|
||||||
|
/// water temperature
|
||||||
|
water_temp: Option<f32>,
|
||||||
|
temp_sensor_error: Option<String>,
|
||||||
|
}
|
||||||
@@ -1,26 +1,28 @@
|
|||||||
//offer ota and config mode
|
//offer ota and config mode
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
config::PlantControllerConfig,
|
||||||
|
determine_tank_state, do_secure_pump, get_version,
|
||||||
|
hal::PLANT_COUNT,
|
||||||
|
log::LogMessage,
|
||||||
|
plant_state::{MoistureSensorState, PlantState},
|
||||||
|
BOARD_ACCESS,
|
||||||
|
};
|
||||||
|
use anyhow::{bail, Context};
|
||||||
|
use chrono::DateTime;
|
||||||
|
use core::result::Result::Ok;
|
||||||
|
use embedded_svc::http::Method;
|
||||||
|
use esp_idf_svc::http::server::{Configuration, EspHttpConnection, EspHttpServer, Request};
|
||||||
|
use esp_idf_sys::{settimeofday, timeval, vTaskDelay};
|
||||||
|
use esp_ota::OtaUpdate;
|
||||||
|
use heapless::String;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
str::from_utf8,
|
str::from_utf8,
|
||||||
sync::{atomic::AtomicBool, Arc},
|
sync::{atomic::AtomicBool, Arc},
|
||||||
};
|
};
|
||||||
use crate::{
|
|
||||||
get_version, log::LogMessage, map_range_moisture, plant_hal::PLANT_COUNT, BOARD_ACCESS
|
|
||||||
};
|
|
||||||
use anyhow::bail;
|
|
||||||
use chrono::DateTime;
|
|
||||||
use esp_idf_sys::{settimeofday, timeval, vTaskDelay};
|
|
||||||
use esp_ota::OtaUpdate;
|
|
||||||
use core::result::Result::Ok;
|
|
||||||
use embedded_svc::http::Method;
|
|
||||||
use esp_idf_hal::delay::Delay;
|
|
||||||
use esp_idf_svc::http::server::{Configuration, EspHttpConnection, EspHttpServer, Request};
|
|
||||||
use heapless::String;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::config::PlantControllerConfig;
|
|
||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
struct SSIDList<'a> {
|
struct SSIDList<'a> {
|
||||||
ssids: Vec<&'a String<32>>,
|
ssids: Vec<&'a String<32>>,
|
||||||
@@ -34,8 +36,15 @@ struct LoadData<'a> {
|
|||||||
|
|
||||||
#[derive(Serialize, Debug)]
|
#[derive(Serialize, Debug)]
|
||||||
struct Moistures {
|
struct Moistures {
|
||||||
moisture_a: Vec<u8>,
|
moisture_a: Vec<std::string::String>,
|
||||||
moisture_b: Vec<u8>,
|
moisture_b: Vec<std::string::String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Debug)]
|
||||||
|
struct SolarState {
|
||||||
|
mppt_voltage: f32,
|
||||||
|
mppt_current: f32,
|
||||||
|
is_day: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
@@ -49,14 +58,14 @@ pub struct TestPump {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
pub struct WebBackupHeader{
|
pub struct WebBackupHeader {
|
||||||
timestamp: std::string::String,
|
timestamp: std::string::String,
|
||||||
size: usize
|
size: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct NightLampCommand {
|
pub struct NightLampCommand {
|
||||||
active: bool
|
active: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_time(
|
fn write_time(
|
||||||
@@ -65,69 +74,35 @@ fn write_time(
|
|||||||
let actual_data = read_up_to_bytes_from_request(request, None)?;
|
let actual_data = read_up_to_bytes_from_request(request, None)?;
|
||||||
let time: SetTime = serde_json::from_slice(&actual_data)?;
|
let time: SetTime = serde_json::from_slice(&actual_data)?;
|
||||||
let parsed = DateTime::parse_from_rfc3339(time.time).map_err(|err| anyhow::anyhow!(err))?;
|
let parsed = DateTime::parse_from_rfc3339(time.time).map_err(|err| anyhow::anyhow!(err))?;
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().expect("board access");
|
||||||
|
|
||||||
let now = timeval {
|
let now = timeval {
|
||||||
tv_sec: parsed.to_utc().timestamp(),
|
tv_sec: parsed.to_utc().timestamp(),
|
||||||
tv_usec: 0
|
tv_usec: 0,
|
||||||
};
|
};
|
||||||
unsafe { settimeofday(&now, core::ptr::null_mut()) };
|
unsafe { settimeofday(&now, core::ptr::null_mut()) };
|
||||||
board.set_rtc_time(&parsed.to_utc())?;
|
board
|
||||||
|
.board_hal
|
||||||
|
.get_rtc_module()
|
||||||
|
.set_rtc_time(&parsed.to_utc())?;
|
||||||
anyhow::Ok(None)
|
anyhow::Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_live_moisture(
|
fn get_time(
|
||||||
_request: &mut Request<&mut EspHttpConnection>,
|
_request: &mut Request<&mut EspHttpConnection>,
|
||||||
) -> Result<Option<std::string::String>, anyhow::Error> {
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().expect("board access");
|
||||||
|
|
||||||
let mut a: Vec<u8> = Vec::new();
|
|
||||||
let mut b: Vec<u8> = Vec::new();
|
|
||||||
for plant in 0..8 {
|
|
||||||
let a_hz = board.measure_moisture_hz(plant, crate::plant_hal::Sensor::A)?;
|
|
||||||
let b_hz = board.measure_moisture_hz(plant, crate::plant_hal::Sensor::B)?;
|
|
||||||
let a_pct = map_range_moisture(a_hz as f32);
|
|
||||||
|
|
||||||
match a_pct {
|
|
||||||
Ok(result) => {
|
|
||||||
a.push(result);
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
a.push(200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let b_pct = map_range_moisture(b_hz as f32);
|
|
||||||
match b_pct {
|
|
||||||
Ok(result) => {
|
|
||||||
b.push(result);
|
|
||||||
}
|
|
||||||
Err(_) => {
|
|
||||||
b.push(200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = Moistures {
|
|
||||||
moisture_a: a,
|
|
||||||
moisture_b: b,
|
|
||||||
};
|
|
||||||
let json = serde_json::to_string(&data)?;
|
|
||||||
|
|
||||||
anyhow::Ok(Some(json))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_data(
|
|
||||||
_request: &mut Request<&mut EspHttpConnection>,
|
|
||||||
) -> Result<Option<std::string::String>, anyhow::Error> {
|
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
|
||||||
let native = board
|
let native = board
|
||||||
|
.board_hal
|
||||||
|
.get_esp()
|
||||||
.time()
|
.time()
|
||||||
.and_then(|t| Ok(t.to_rfc3339()))
|
.map(|t| t.to_rfc3339())
|
||||||
.unwrap_or("error".to_string());
|
.unwrap_or("error".to_string());
|
||||||
let rtc = board
|
let rtc = board
|
||||||
|
.board_hal
|
||||||
|
.get_rtc_module()
|
||||||
.get_rtc_time()
|
.get_rtc_time()
|
||||||
.and_then(|t| Ok(t.to_rfc3339()))
|
.map(|t| t.to_rfc3339())
|
||||||
.unwrap_or("error".to_string());
|
.unwrap_or("error".to_string());
|
||||||
|
|
||||||
let data = LoadData {
|
let data = LoadData {
|
||||||
@@ -139,14 +114,58 @@ fn get_data(
|
|||||||
anyhow::Ok(Some(json))
|
anyhow::Ok(Some(json))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_timezones(
|
||||||
|
_request: &mut Request<&mut EspHttpConnection>,
|
||||||
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
|
// Get all timezones using chrono-tz
|
||||||
|
let timezones: Vec<&'static str> = chrono_tz::TZ_VARIANTS.iter().map(|tz| tz.name()).collect();
|
||||||
|
|
||||||
|
// Convert to JSON
|
||||||
|
let json = serde_json::to_string(&timezones)?;
|
||||||
|
anyhow::Ok(Some(json))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_live_moisture(
|
||||||
|
_request: &mut Request<&mut EspHttpConnection>,
|
||||||
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
|
let mut board = BOARD_ACCESS.lock().expect("Should never fail");
|
||||||
|
let plant_state =
|
||||||
|
Vec::from_iter((0..PLANT_COUNT).map(|i| PlantState::read_hardware_state(i, &mut board)));
|
||||||
|
let a = Vec::from_iter(plant_state.iter().map(|s| match &s.sensor_a {
|
||||||
|
MoistureSensorState::Disabled => "disabled".to_string(),
|
||||||
|
MoistureSensorState::MoistureValue {
|
||||||
|
raw_hz,
|
||||||
|
moisture_percent,
|
||||||
|
} => {
|
||||||
|
format!("{moisture_percent:.2}% {raw_hz}hz",)
|
||||||
|
}
|
||||||
|
MoistureSensorState::SensorError(err) => format!("{err:?}"),
|
||||||
|
}));
|
||||||
|
let b = Vec::from_iter(plant_state.iter().map(|s| match &s.sensor_b {
|
||||||
|
MoistureSensorState::Disabled => "disabled".to_string(),
|
||||||
|
MoistureSensorState::MoistureValue {
|
||||||
|
raw_hz,
|
||||||
|
moisture_percent,
|
||||||
|
} => {
|
||||||
|
format!("{moisture_percent:.2}% {raw_hz}hz",)
|
||||||
|
}
|
||||||
|
MoistureSensorState::SensorError(err) => format!("{err:?}"),
|
||||||
|
}));
|
||||||
|
|
||||||
|
let data = Moistures {
|
||||||
|
moisture_a: a,
|
||||||
|
moisture_b: b,
|
||||||
|
};
|
||||||
|
let json = serde_json::to_string(&data)?;
|
||||||
|
|
||||||
|
anyhow::Ok(Some(json))
|
||||||
|
}
|
||||||
|
|
||||||
fn get_config(
|
fn get_config(
|
||||||
_request: &mut Request<&mut EspHttpConnection>,
|
_request: &mut Request<&mut EspHttpConnection>,
|
||||||
) -> Result<Option<std::string::String>, anyhow::Error> {
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().expect("Should never fail");
|
||||||
let json = match board.get_config() {
|
let json = serde_json::to_string(&board.board_hal.get_config())?;
|
||||||
Ok(config) => serde_json::to_string(&config)?,
|
|
||||||
Err(_) => serde_json::to_string(&PlantControllerConfig::default())?,
|
|
||||||
};
|
|
||||||
anyhow::Ok(Some(json))
|
anyhow::Ok(Some(json))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,17 +173,19 @@ fn backup_config(
|
|||||||
request: &mut Request<&mut EspHttpConnection>,
|
request: &mut Request<&mut EspHttpConnection>,
|
||||||
) -> Result<Option<std::string::String>, anyhow::Error> {
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
let all = read_up_to_bytes_from_request(request, Some(3072))?;
|
let all = read_up_to_bytes_from_request(request, Some(3072))?;
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().expect("board access");
|
||||||
board.backup_config(&all)?;
|
|
||||||
|
//TODO how to handle progress here? prior versions animated the fault leds while running
|
||||||
|
board.board_hal.get_rtc_module().backup_config(&all)?;
|
||||||
anyhow::Ok(Some("saved".to_owned()))
|
anyhow::Ok(Some("saved".to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_backup_config(
|
fn get_backup_config(
|
||||||
_request: &mut Request<&mut EspHttpConnection>,
|
_request: &mut Request<&mut EspHttpConnection>,
|
||||||
) -> Result<Option<std::string::String>, anyhow::Error> {
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().expect("board access");
|
||||||
let json = match board.get_backup_config() {
|
let json = match board.board_hal.get_rtc_module().get_backup_config() {
|
||||||
Ok(config) => std::str::from_utf8(&config)?.to_owned(),
|
Ok(config) => from_utf8(&config)?.to_owned(),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
println!("Error get backup config {:?}", err);
|
println!("Error get backup config {:?}", err);
|
||||||
err.to_string()
|
err.to_string()
|
||||||
@@ -173,22 +194,27 @@ fn get_backup_config(
|
|||||||
anyhow::Ok(Some(json))
|
anyhow::Ok(Some(json))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn backup_info(
|
fn backup_info(
|
||||||
_request: &mut Request<&mut EspHttpConnection>,
|
_request: &mut Request<&mut EspHttpConnection>,
|
||||||
) -> Result<Option<std::string::String>, anyhow::Error> {
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().expect("Should never fail");
|
||||||
let header = board.get_backup_info();
|
let header = board.board_hal.get_rtc_module().get_backup_info();
|
||||||
let json = match header {
|
let json = match header {
|
||||||
Ok(h) => {
|
Ok(h) => {
|
||||||
let timestamp = DateTime::from_timestamp_millis(h.timestamp).unwrap();
|
let timestamp = DateTime::from_timestamp_millis(h.timestamp).unwrap();
|
||||||
let wbh = WebBackupHeader{
|
let wbh = WebBackupHeader {
|
||||||
timestamp: timestamp.to_rfc3339(),
|
timestamp: timestamp.to_rfc3339(),
|
||||||
size: h.size,
|
size: h.size,
|
||||||
};
|
};
|
||||||
serde_json::to_string(&wbh)?
|
serde_json::to_string(&wbh)?
|
||||||
},
|
}
|
||||||
Err(_) => "{\"error\":\"Header could not be parsed\"".to_owned()
|
Err(err) => {
|
||||||
|
let wbh = WebBackupHeader {
|
||||||
|
timestamp: err.to_string(),
|
||||||
|
size: 0,
|
||||||
|
};
|
||||||
|
serde_json::to_string(&wbh)?
|
||||||
|
}
|
||||||
};
|
};
|
||||||
anyhow::Ok(Some(json))
|
anyhow::Ok(Some(json))
|
||||||
}
|
}
|
||||||
@@ -196,21 +222,32 @@ fn backup_info(
|
|||||||
fn set_config(
|
fn set_config(
|
||||||
request: &mut Request<&mut EspHttpConnection>,
|
request: &mut Request<&mut EspHttpConnection>,
|
||||||
) -> Result<Option<std::string::String>, anyhow::Error> {
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
let all = read_up_to_bytes_from_request(request, Some(3072))?;
|
let all = read_up_to_bytes_from_request(request, Some(4096))?;
|
||||||
let config: PlantControllerConfig = serde_json::from_slice(&all)?;
|
let config: PlantControllerConfig = serde_json::from_slice(&all)?;
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
|
||||||
board.set_config(&config)?;
|
let mut board = BOARD_ACCESS.lock().expect("board access");
|
||||||
|
board.board_hal.set_config(config)?;
|
||||||
anyhow::Ok(Some("saved".to_owned()))
|
anyhow::Ok(Some("saved".to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_solar_state(
|
||||||
|
_request: &mut Request<&mut EspHttpConnection>,
|
||||||
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
|
let mut board = BOARD_ACCESS.lock().expect("board access");
|
||||||
|
let state = SolarState {
|
||||||
|
mppt_voltage: board.board_hal.get_mptt_voltage()?.as_millivolts() as f32,
|
||||||
|
mppt_current: board.board_hal.get_mptt_current()?.as_milliamperes() as f32,
|
||||||
|
is_day: board.board_hal.is_day(),
|
||||||
|
};
|
||||||
|
anyhow::Ok(Some(serde_json::to_string(&state)?))
|
||||||
|
}
|
||||||
|
|
||||||
fn get_battery_state(
|
fn get_battery_state(
|
||||||
_request: &mut Request<&mut EspHttpConnection>,
|
_request: &mut Request<&mut EspHttpConnection>,
|
||||||
) -> Result<Option<std::string::String>, anyhow::Error> {
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().expect("board access");
|
||||||
let battery_state = board.get_battery_state();
|
let battery_state = board.board_hal.get_battery_monitor().get_battery_state();
|
||||||
let battery_json = serde_json::to_string(&battery_state)?;
|
anyhow::Ok(Some(serde_json::to_string(&battery_state)?))
|
||||||
anyhow::Ok(Some(battery_json))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_log(
|
fn get_log(
|
||||||
@@ -221,13 +258,14 @@ fn get_log(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_log_localization_config() -> Result<std::string::String, anyhow::Error> {
|
fn get_log_localization_config() -> Result<std::string::String, anyhow::Error> {
|
||||||
anyhow::Ok(serde_json::to_string(&LogMessage::to_log_localisation_config())?)
|
anyhow::Ok(serde_json::to_string(
|
||||||
|
&LogMessage::to_log_localisation_config(),
|
||||||
|
)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_version_web(
|
fn get_version_web(
|
||||||
_request: &mut Request<&mut EspHttpConnection>,
|
_request: &mut Request<&mut EspHttpConnection>,
|
||||||
) -> Result<Option<std::string::String>, anyhow::Error> {
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
|
|
||||||
anyhow::Ok(Some(serde_json::to_string(&get_version())?))
|
anyhow::Ok(Some(serde_json::to_string(&get_version())?))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,8 +275,29 @@ fn pump_test(
|
|||||||
let actual_data = read_up_to_bytes_from_request(request, None)?;
|
let actual_data = read_up_to_bytes_from_request(request, None)?;
|
||||||
let pump_test: TestPump = serde_json::from_slice(&actual_data)?;
|
let pump_test: TestPump = serde_json::from_slice(&actual_data)?;
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().unwrap();
|
||||||
board.test_pump(pump_test.pump)?;
|
|
||||||
anyhow::Ok(None)
|
let config = &board.board_hal.get_config().plants[pump_test.pump].clone();
|
||||||
|
let pump_result = do_secure_pump(&mut board, pump_test.pump, config, false)?;
|
||||||
|
board.board_hal.pump(pump_test.pump, false)?;
|
||||||
|
anyhow::Ok(Some(serde_json::to_string(&pump_result)?))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tank_info(
|
||||||
|
_request: &mut Request<&mut EspHttpConnection>,
|
||||||
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
|
let mut board = BOARD_ACCESS.lock().unwrap();
|
||||||
|
let tank_info = determine_tank_state(&mut board);
|
||||||
|
//should be multsampled
|
||||||
|
|
||||||
|
let water_temp = board
|
||||||
|
.board_hal
|
||||||
|
.get_tank_sensor()
|
||||||
|
.context("no sensor")
|
||||||
|
.and_then(|f| f.water_temperature_c());
|
||||||
|
Ok(Some(serde_json::to_string(&tank_info.as_mqtt_info(
|
||||||
|
&board.board_hal.get_config().tank,
|
||||||
|
&water_temp,
|
||||||
|
))?))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn night_lamp_test(
|
fn night_lamp_test(
|
||||||
@@ -247,7 +306,7 @@ fn night_lamp_test(
|
|||||||
let actual_data = read_up_to_bytes_from_request(request, None)?;
|
let actual_data = read_up_to_bytes_from_request(request, None)?;
|
||||||
let light_command: NightLampCommand = serde_json::from_slice(&actual_data)?;
|
let light_command: NightLampCommand = serde_json::from_slice(&actual_data)?;
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().unwrap();
|
||||||
board.light(light_command.active)?;
|
board.board_hal.light(light_command.active)?;
|
||||||
anyhow::Ok(None)
|
anyhow::Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,7 +314,7 @@ fn wifi_scan(
|
|||||||
_request: &mut Request<&mut EspHttpConnection>,
|
_request: &mut Request<&mut EspHttpConnection>,
|
||||||
) -> Result<Option<std::string::String>, anyhow::Error> {
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().unwrap();
|
||||||
let scan_result = board.wifi_scan()?;
|
let scan_result = board.board_hal.get_esp().wifi_scan()?;
|
||||||
let mut ssids: Vec<&String<32>> = Vec::new();
|
let mut ssids: Vec<&String<32>> = Vec::new();
|
||||||
scan_result.iter().for_each(|s| ssids.push(&s.ssid));
|
scan_result.iter().for_each(|s| ssids.push(&s.ssid));
|
||||||
let ssid_json = serde_json::to_string(&SSIDList { ssids })?;
|
let ssid_json = serde_json::to_string(&SSIDList { ssids })?;
|
||||||
@@ -266,10 +325,12 @@ fn wifi_scan(
|
|||||||
fn list_files(
|
fn list_files(
|
||||||
_request: &mut Request<&mut EspHttpConnection>,
|
_request: &mut Request<&mut EspHttpConnection>,
|
||||||
) -> Result<Option<std::string::String>, anyhow::Error> {
|
) -> Result<Option<std::string::String>, anyhow::Error> {
|
||||||
let board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS
|
||||||
let result = board.list_files();
|
.lock()
|
||||||
|
.expect("It should be possible to lock the board for exclusive fs access");
|
||||||
|
let result = board.board_hal.get_esp().list_files();
|
||||||
let file_list_json = serde_json::to_string(&result)?;
|
let file_list_json = serde_json::to_string(&result)?;
|
||||||
return anyhow::Ok(Some(file_list_json));
|
anyhow::Ok(Some(file_list_json))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ota(
|
fn ota(
|
||||||
@@ -278,7 +339,7 @@ fn ota(
|
|||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().unwrap();
|
||||||
let mut ota = OtaUpdate::begin()?;
|
let mut ota = OtaUpdate::begin()?;
|
||||||
println!("start ota");
|
println!("start ota");
|
||||||
|
|
||||||
//having a larger buffer is not really faster, requires more stack and prevents the progress bar from working ;)
|
//having a larger buffer is not really faster, requires more stack and prevents the progress bar from working ;)
|
||||||
const BUFFER_SIZE: usize = 512;
|
const BUFFER_SIZE: usize = 512;
|
||||||
let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
|
let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
|
||||||
@@ -288,15 +349,17 @@ fn ota(
|
|||||||
let read = request.read(&mut buffer)?;
|
let read = request.read(&mut buffer)?;
|
||||||
total_read += read;
|
total_read += read;
|
||||||
let to_write = &buffer[0..read];
|
let to_write = &buffer[0..read];
|
||||||
|
//delay for watchdog and wifi stuff
|
||||||
|
board.board_hal.get_esp().delay.delay_ms(1);
|
||||||
|
|
||||||
let iter = (total_read/1024)%8;
|
let iter = (total_read / 1024) % 8;
|
||||||
if iter != lastiter {
|
if iter != lastiter {
|
||||||
|
board.board_hal.general_fault(iter % 5 == 0);
|
||||||
for i in 0..PLANT_COUNT {
|
for i in 0..PLANT_COUNT {
|
||||||
board.fault(i, iter==i);
|
let _ = board.board_hal.fault(i, iter == i);
|
||||||
|
|
||||||
}
|
}
|
||||||
lastiter = iter;
|
lastiter = iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
ota.write(to_write)?;
|
ota.write(to_write)?;
|
||||||
if read == 0 {
|
if read == 0 {
|
||||||
@@ -310,60 +373,19 @@ fn ota(
|
|||||||
|
|
||||||
let mut finalizer = ota.finalize()?;
|
let mut finalizer = ota.finalize()?;
|
||||||
println!("changing boot partition");
|
println!("changing boot partition");
|
||||||
board.set_restart_to_conf(true);
|
board.board_hal.get_esp().set_restart_to_conf(true);
|
||||||
drop(board);
|
drop(board);
|
||||||
finalizer.set_as_boot_partition()?;
|
finalizer.set_as_boot_partition()?;
|
||||||
return anyhow::Ok(None);
|
anyhow::Ok(None)
|
||||||
}
|
|
||||||
|
|
||||||
fn flash_bq(filename: &str, dryrun: bool) -> anyhow::Result<()> {
|
|
||||||
let mut board = BOARD_ACCESS.lock().unwrap();
|
|
||||||
|
|
||||||
let mut toggle = true;
|
|
||||||
let delay = Delay::new(1);
|
|
||||||
|
|
||||||
let file_handle = board.get_file_handle(filename, false)?;
|
|
||||||
|
|
||||||
let mut reader = std::io::BufRead::lines(std::io::BufReader::with_capacity(512, file_handle));
|
|
||||||
let mut line = 0;
|
|
||||||
loop {
|
|
||||||
board.general_fault(toggle);
|
|
||||||
toggle = !toggle;
|
|
||||||
|
|
||||||
delay.delay_us(2);
|
|
||||||
line += 1;
|
|
||||||
match reader.next() {
|
|
||||||
Some(next) => {
|
|
||||||
let input = next?;
|
|
||||||
println!("flashing bq34z100 dryrun:{dryrun} line {line} payload: {input}");
|
|
||||||
match board.flash_bq34_z100(&input, dryrun) {
|
|
||||||
Ok(_) => {
|
|
||||||
println!("ok")
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
bail!(
|
|
||||||
"Error flashing bq34z100 in dryrun: {dryrun} line: {line} error: {err}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => break,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("Finished flashing file {line} lines processed");
|
|
||||||
board.general_fault(false);
|
|
||||||
return anyhow::Ok(());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn query_param(uri: &str, param_name: &str) -> Option<std::string::String> {
|
fn query_param(uri: &str, param_name: &str) -> Option<std::string::String> {
|
||||||
println!("{uri} get {param_name}");
|
println!("{uri} get {param_name}");
|
||||||
let parsed = Url::parse(&format!("http://127.0.0.1/{uri}")).unwrap();
|
let parsed = Url::parse(&format!("http://127.0.0.1/{uri}")).unwrap();
|
||||||
let value = parsed.query_pairs().filter(|it| it.0 == param_name).next();
|
let value = parsed.query_pairs().find(|it| it.0 == param_name);
|
||||||
match value {
|
match value {
|
||||||
Some(found) => {
|
Some(found) => Some(found.1.into_owned()),
|
||||||
return Some(found.1.into_owned());
|
None => None,
|
||||||
}
|
|
||||||
None => return None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,23 +402,28 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server
|
server
|
||||||
.fn_handler("/log", Method::Get, |request| {
|
.fn_handler("/log", Method::Get, |request| {
|
||||||
handle_error_to500(request, get_log)
|
handle_error_to500(request, get_log)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server.fn_handler("/log_localization", Method::Get, |request| {
|
server
|
||||||
cors_response(request, 200, &get_log_localization_config().unwrap())
|
.fn_handler("/log_localization", Method::Get, |request| {
|
||||||
|
cors_response(request, 200, &get_log_localization_config().unwrap())
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server
|
server
|
||||||
.fn_handler("/battery", Method::Get, |request| {
|
.fn_handler("/battery", Method::Get, |request| {
|
||||||
handle_error_to500(request, get_battery_state)
|
handle_error_to500(request, get_battery_state)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
server
|
||||||
|
.fn_handler("/solar", Method::Get, |request| {
|
||||||
|
handle_error_to500(request, get_solar_state)
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
server
|
server
|
||||||
.fn_handler("/time", Method::Get, |request| {
|
.fn_handler("/time", Method::Get, |request| {
|
||||||
handle_error_to500(request, get_data)
|
handle_error_to500(request, get_time)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server
|
server
|
||||||
@@ -409,19 +436,24 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
|
|||||||
handle_error_to500(request, write_time)
|
handle_error_to500(request, write_time)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
server
|
||||||
|
.fn_handler("/tank", Method::Get, |request| {
|
||||||
|
handle_error_to500(request, tank_info)
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
server
|
server
|
||||||
.fn_handler("/pumptest", Method::Post, |request| {
|
.fn_handler("/pumptest", Method::Post, |request| {
|
||||||
handle_error_to500(request, pump_test)
|
handle_error_to500(request, pump_test)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server
|
server
|
||||||
.fn_handler("/lamptest", Method::Post, |request| {
|
.fn_handler("/lamptest", Method::Post, |request| {
|
||||||
handle_error_to500(request, night_lamp_test)
|
handle_error_to500(request, night_lamp_test)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server
|
server
|
||||||
.fn_handler("/boardtest", Method::Post, move |_| {
|
.fn_handler("/boardtest", Method::Post, move |_| {
|
||||||
BOARD_ACCESS.lock().unwrap().test()
|
BOARD_ACCESS.lock().unwrap().board_hal.test()
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server
|
server
|
||||||
@@ -456,15 +488,15 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server
|
server
|
||||||
.fn_handler("/backup_config", Method::Post, move |request| {
|
.fn_handler("/backup_config", Method::Post, move |request| {
|
||||||
handle_error_to500(request, backup_config)
|
handle_error_to500(request, backup_config)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server
|
server
|
||||||
.fn_handler("/backup_info", Method::Get, move |request| {
|
.fn_handler("/backup_info", Method::Get, move |request| {
|
||||||
handle_error_to500(request, backup_info)
|
handle_error_to500(request, backup_info)
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server
|
server
|
||||||
.fn_handler("/files", Method::Get, move |request| {
|
.fn_handler("/files", Method::Get, move |request| {
|
||||||
handle_error_to500(request, list_files)
|
handle_error_to500(request, list_files)
|
||||||
@@ -472,31 +504,35 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let reboot_now_for_reboot = reboot_now.clone();
|
let reboot_now_for_reboot = reboot_now.clone();
|
||||||
server
|
server
|
||||||
.fn_handler("/reboot", Method::Post, move |_| {
|
.fn_handler("/reboot", Method::Post, move |_| {
|
||||||
BOARD_ACCESS
|
BOARD_ACCESS
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_restart_to_conf(true);
|
.board_hal
|
||||||
reboot_now_for_reboot.store(true, std::sync::atomic::Ordering::Relaxed);
|
.get_esp()
|
||||||
anyhow::Ok(())
|
.set_restart_to_conf(true);
|
||||||
})
|
reboot_now_for_reboot.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
.unwrap();
|
anyhow::Ok(())
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
unsafe { vTaskDelay(1) };
|
unsafe { vTaskDelay(1) };
|
||||||
|
|
||||||
let reboot_now_for_exit = reboot_now.clone();
|
let reboot_now_for_exit = reboot_now.clone();
|
||||||
server
|
server
|
||||||
.fn_handler("/exit", Method::Post, move |_| {
|
.fn_handler("/exit", Method::Post, move |_| {
|
||||||
reboot_now_for_exit.store(true, std::sync::atomic::Ordering::Relaxed);
|
reboot_now_for_exit.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||||
anyhow::Ok(())
|
anyhow::Ok(())
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server
|
server
|
||||||
.fn_handler("/file", Method::Get, move |request| {
|
.fn_handler("/file", Method::Get, move |request| {
|
||||||
let filename = query_param(request.uri(), "filename").unwrap();
|
let filename = query_param(request.uri(), "filename").unwrap();
|
||||||
let file_handle = BOARD_ACCESS
|
let file_handle = BOARD_ACCESS
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.board_hal
|
||||||
|
.get_esp()
|
||||||
.get_file_handle(&filename, false);
|
.get_file_handle(&filename, false);
|
||||||
match file_handle {
|
match file_handle {
|
||||||
Ok(mut file_handle) => {
|
Ok(mut file_handle) => {
|
||||||
@@ -532,28 +568,23 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
|
|||||||
server
|
server
|
||||||
.fn_handler("/file", Method::Post, move |mut request| {
|
.fn_handler("/file", Method::Post, move |mut request| {
|
||||||
let filename = query_param(request.uri(), "filename").unwrap();
|
let filename = query_param(request.uri(), "filename").unwrap();
|
||||||
let lock = BOARD_ACCESS
|
let mut board = BOARD_ACCESS.lock().unwrap();
|
||||||
.lock()
|
let file_handle = board.board_hal.get_esp().get_file_handle(&filename, true);
|
||||||
.unwrap();
|
|
||||||
let file_handle =
|
|
||||||
lock.get_file_handle(&filename, true);
|
|
||||||
match file_handle {
|
match file_handle {
|
||||||
//TODO get free filesystem size, check against during write if not to large
|
//TODO get free filesystem size, check against during write if not to large
|
||||||
|
|
||||||
Ok(mut file_handle) => {
|
Ok(mut file_handle) => {
|
||||||
const BUFFER_SIZE: usize = 512;
|
const BUFFER_SIZE: usize = 512;
|
||||||
let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
|
let mut buffer: [u8; BUFFER_SIZE] = [0; BUFFER_SIZE];
|
||||||
let mut total_read: usize = 0;
|
let mut total_read: usize = 0;
|
||||||
let mut lastiter = 0;
|
let mut lastiter = 0;
|
||||||
loop {
|
loop {
|
||||||
|
let iter = (total_read / 1024) % 8;
|
||||||
let iter = (total_read/1024)%8;
|
|
||||||
if iter != lastiter {
|
if iter != lastiter {
|
||||||
for i in 0..PLANT_COUNT {
|
for i in 0..PLANT_COUNT {
|
||||||
lock.fault(i, iter==i);
|
let _ = board.board_hal.fault(i, iter == i);
|
||||||
}
|
}
|
||||||
lastiter = iter;
|
lastiter = iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
let read = request.read(&mut buffer)?;
|
let read = request.read(&mut buffer)?;
|
||||||
total_read += read;
|
total_read += read;
|
||||||
@@ -572,7 +603,7 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
|
|||||||
cors_response(request, 500, &error_text)?;
|
cors_response(request, 500, &error_text)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
drop(lock);
|
drop(board);
|
||||||
anyhow::Ok(())
|
anyhow::Ok(())
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -581,8 +612,8 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
|
|||||||
.fn_handler("/file", Method::Delete, move |request| {
|
.fn_handler("/file", Method::Delete, move |request| {
|
||||||
let filename = query_param(request.uri(), "filename").unwrap();
|
let filename = query_param(request.uri(), "filename").unwrap();
|
||||||
let copy = filename.clone();
|
let copy = filename.clone();
|
||||||
let board = BOARD_ACCESS.lock().unwrap();
|
let mut board = BOARD_ACCESS.lock().unwrap();
|
||||||
match board.delete_file(&filename) {
|
match board.board_hal.get_esp().delete_file(&filename) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
let info = format!("Deleted file {copy}");
|
let info = format!("Deleted file {copy}");
|
||||||
cors_response(request, 200, &info)?;
|
cors_response(request, 200, &info)?;
|
||||||
@@ -600,35 +631,6 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
|
|||||||
cors_response(request, 200, "")
|
cors_response(request, 200, "")
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
server
|
|
||||||
.fn_handler("/flashbattery", Method::Post, move |request| {
|
|
||||||
let filename = query_param(request.uri(),"filename").unwrap();
|
|
||||||
let dryrun = true;
|
|
||||||
match flash_bq(&filename, false) {
|
|
||||||
Ok(_) => {
|
|
||||||
if !dryrun {
|
|
||||||
match flash_bq(&filename, true) {
|
|
||||||
Ok(_) => {
|
|
||||||
cors_response(request, 200, "Sucessfully flashed bq34z100")?;
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
let info = format!("Could not flash bq34z100, could be bricked now! {filename} {err:?}");
|
|
||||||
cors_response(request, 500, &info)?;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cors_response(request, 200, "Sucessfully processed bq34z100")?;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
let info = format!("Could not process firmware file for, bq34z100, refusing to flash! {filename} {err:?}");
|
|
||||||
cors_response(request, 500, &info)?;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
anyhow::Ok(())
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
unsafe { vTaskDelay(1) };
|
unsafe { vTaskDelay(1) };
|
||||||
server
|
server
|
||||||
.fn_handler("/", Method::Get, move |request| {
|
.fn_handler("/", Method::Get, move |request| {
|
||||||
@@ -654,6 +656,11 @@ pub fn httpd(reboot_now: Arc<AtomicBool>) -> Box<EspHttpServer<'static>> {
|
|||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
server
|
server
|
||||||
|
.fn_handler("/timezones", Method::Get, move |request| {
|
||||||
|
handle_error_to500(request, get_timezones)
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
server
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cors_response(
|
fn cors_response(
|
||||||
@@ -669,7 +676,7 @@ fn cors_response(
|
|||||||
let mut response = request.into_response(status, None, &headers)?;
|
let mut response = request.into_response(status, None, &headers)?;
|
||||||
response.write(body.as_bytes())?;
|
response.write(body.as_bytes())?;
|
||||||
response.flush()?;
|
response.flush()?;
|
||||||
return anyhow::Ok(());
|
anyhow::Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
type AnyhowHandler =
|
type AnyhowHandler =
|
||||||
@@ -694,14 +701,17 @@ fn handle_error_to500(
|
|||||||
cors_response(request, 500, &error_text)?;
|
cors_response(request, 500, &error_text)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return anyhow::Ok(());
|
anyhow::Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_up_to_bytes_from_request(request: &mut Request<&mut EspHttpConnection<'_>>, limit: Option<usize>) -> Result<Vec<u8>, anyhow::Error> {
|
fn read_up_to_bytes_from_request(
|
||||||
|
request: &mut Request<&mut EspHttpConnection<'_>>,
|
||||||
|
limit: Option<usize>,
|
||||||
|
) -> Result<Vec<u8>, anyhow::Error> {
|
||||||
let max_read = limit.unwrap_or(1024);
|
let max_read = limit.unwrap_or(1024);
|
||||||
let mut data_store = Vec::new();
|
let mut data_store = Vec::new();
|
||||||
let mut total_read = 0;
|
let mut total_read = 0;
|
||||||
loop{
|
loop {
|
||||||
let mut buf = [0_u8; 64];
|
let mut buf = [0_u8; 64];
|
||||||
let read = request.read(&mut buf)?;
|
let read = request.read(&mut buf)?;
|
||||||
if read == 0 {
|
if read == 0 {
|
||||||
@@ -709,7 +719,7 @@ fn read_up_to_bytes_from_request(request: &mut Request<&mut EspHttpConnection<'_
|
|||||||
}
|
}
|
||||||
let actual_data = &buf[0..read];
|
let actual_data = &buf[0..read];
|
||||||
total_read += read;
|
total_read += read;
|
||||||
if total_read > max_read{
|
if total_read > max_read {
|
||||||
bail!("Request too large {total_read} > {max_read}");
|
bail!("Request too large {total_read} > {max_read}");
|
||||||
}
|
}
|
||||||
data_store.push(actual_data.to_owned());
|
data_store.push(actual_data.to_owned());
|
||||||
@@ -1,105 +1,189 @@
|
|||||||
interface BackupHeader {
|
export interface LogArray extends Array<LogEntry> {
|
||||||
timestamp: string,
|
|
||||||
size: number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NetworkConfig {
|
export interface LogEntry {
|
||||||
ap_ssid: string,
|
timestamp: string,
|
||||||
ssid: string,
|
message_id: number,
|
||||||
password: string,
|
a: number,
|
||||||
mqtt_url: string,
|
b: number,
|
||||||
base_topic: string
|
txt_short: string,
|
||||||
|
txt_long: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FileList {
|
export interface LogLocalisation extends Array<LogLocalisationEntry> {
|
||||||
total: number,
|
|
||||||
used: number,
|
|
||||||
files: FileInfo[],
|
|
||||||
file_system_corrupt: string,
|
|
||||||
iter_error: string,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FileInfo{
|
export interface LogLocalisationEntry {
|
||||||
filename: string,
|
msg_type: string,
|
||||||
size: number,
|
message: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NightLampConfig {
|
export interface BackupHeader {
|
||||||
enabled: boolean,
|
timestamp: string,
|
||||||
night_lamp_hour_start: number,
|
size: number
|
||||||
night_lamp_hour_end: number,
|
|
||||||
night_lamp_only_when_dark: boolean,
|
|
||||||
low_soc_cutoff: number,
|
|
||||||
low_soc_restore: number
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface NightLampCommand {
|
export interface NetworkConfig {
|
||||||
active: boolean
|
ap_ssid: string,
|
||||||
|
ssid: string,
|
||||||
|
password: string,
|
||||||
|
mqtt_url: string,
|
||||||
|
base_topic: string,
|
||||||
|
max_wait: number
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TankConfig {
|
export interface FileList {
|
||||||
tank_sensor_enabled: boolean,
|
total: number,
|
||||||
tank_allow_pumping_if_sensor_error: boolean,
|
used: number,
|
||||||
tank_useable_ml: number,
|
files: FileInfo[],
|
||||||
tank_warn_percent: number,
|
file_system_corrupt: string,
|
||||||
tank_empty_percent: number,
|
iter_error: string,
|
||||||
tank_full_percent: number,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PlantControllerConfig {
|
export interface SolarState {
|
||||||
network: NetworkConfig,
|
mppt_voltage: number,
|
||||||
tank: TankConfig,
|
mppt_current: number,
|
||||||
night_lamp: NightLampConfig,
|
is_day: boolean
|
||||||
plants: PlantConfig[]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PlantConfig {
|
export interface FileInfo {
|
||||||
mode: string,
|
filename: string,
|
||||||
target_moisture: number,
|
size: number,
|
||||||
pump_time_s: number,
|
}
|
||||||
pump_cooldown_min: number,
|
|
||||||
pump_hour_start: number,
|
export interface NightLampConfig {
|
||||||
pump_hour_end: number,
|
enabled: boolean,
|
||||||
sensor_b: boolean,
|
night_lamp_hour_start: number,
|
||||||
max_consecutive_pump_count: number,
|
night_lamp_hour_end: number,
|
||||||
|
night_lamp_only_when_dark: boolean,
|
||||||
|
low_soc_cutoff: number,
|
||||||
|
low_soc_restore: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NightLampCommand {
|
||||||
|
active: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TankConfig {
|
||||||
|
tank_sensor_enabled: boolean,
|
||||||
|
tank_allow_pumping_if_sensor_error: boolean,
|
||||||
|
tank_useable_ml: number,
|
||||||
|
tank_warn_percent: number,
|
||||||
|
tank_empty_percent: number,
|
||||||
|
tank_full_percent: number,
|
||||||
|
ml_per_pulse: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface SSIDList {
|
export enum BatteryBoardVersion {
|
||||||
ssids: [string]
|
Disabled = "Disabled",
|
||||||
|
BQ34Z100G1 = "BQ34Z100G1",
|
||||||
|
WchI2cSlave = "WchI2cSlave"
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TestPump {
|
export enum BoardVersion {
|
||||||
pump: number
|
INITIAL = "INITIAL",
|
||||||
|
V3 = "V3",
|
||||||
|
V4 = "V4"
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SetTime {
|
export interface BoardHardware {
|
||||||
time: string
|
board: BoardVersion,
|
||||||
|
battery: BatteryBoardVersion,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface GetTime {
|
export interface PlantControllerConfig {
|
||||||
rtc: string,
|
hardware: BoardHardware,
|
||||||
native: string
|
|
||||||
|
network: NetworkConfig,
|
||||||
|
tank: TankConfig,
|
||||||
|
night_lamp: NightLampConfig,
|
||||||
|
plants: PlantConfig[]
|
||||||
|
timezone?: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Moistures {
|
export interface PlantConfig {
|
||||||
moisture_a: [number],
|
mode: string,
|
||||||
moisture_b: [number],
|
target_moisture: number,
|
||||||
|
pump_time_s: number,
|
||||||
|
pump_cooldown_min: number,
|
||||||
|
pump_hour_start: number,
|
||||||
|
pump_hour_end: number,
|
||||||
|
sensor_a: boolean,
|
||||||
|
sensor_b: boolean,
|
||||||
|
max_consecutive_pump_count: number,
|
||||||
|
moisture_sensor_min_frequency: number | null;
|
||||||
|
moisture_sensor_max_frequency: number | null;
|
||||||
|
min_pump_current_ma: number,
|
||||||
|
max_pump_current_ma: number,
|
||||||
|
ignore_current_error: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface VersionInfo {
|
export interface PumpTestResult {
|
||||||
git_hash: string,
|
median_current_ma: number,
|
||||||
build_time: string,
|
max_current_ma: number,
|
||||||
partition: string
|
min_current_ma: number,
|
||||||
|
flow_value_ml: number,
|
||||||
|
flow_value_count: number,
|
||||||
|
pump_time_s: number,
|
||||||
|
error: boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BatteryState {
|
export interface SSIDList {
|
||||||
temperature: string
|
ssids: [string]
|
||||||
voltage_milli_volt: string,
|
}
|
||||||
current_milli_ampere: string,
|
|
||||||
cycle_count: string,
|
export interface TestPump {
|
||||||
design_milli_ampere: string,
|
pump: number
|
||||||
remaining_milli_ampere: string,
|
}
|
||||||
state_of_charge: string,
|
|
||||||
state_of_health: string
|
export interface SetTime {
|
||||||
|
time: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GetTime {
|
||||||
|
rtc: string,
|
||||||
|
native: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Moistures {
|
||||||
|
moisture_a: [string],
|
||||||
|
moisture_b: [string],
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface VersionInfo {
|
||||||
|
git_hash: string,
|
||||||
|
build_time: string,
|
||||||
|
partition: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BatteryState {
|
||||||
|
temperature: string
|
||||||
|
voltage_milli_volt: string,
|
||||||
|
current_milli_ampere: string,
|
||||||
|
cycle_count: string,
|
||||||
|
design_milli_ampere: string,
|
||||||
|
remaining_milli_ampere: string,
|
||||||
|
state_of_charge: string,
|
||||||
|
state_of_health: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TankInfo {
|
||||||
|
/// is there enough water in the tank
|
||||||
|
enough_water: boolean,
|
||||||
|
/// warning that water needs to be refilled soon
|
||||||
|
warn_level: boolean,
|
||||||
|
/// estimation how many ml are still in tank
|
||||||
|
left_ml: number | null,
|
||||||
|
/// if there is was an issue with the water level sensor
|
||||||
|
sensor_error: string | null,
|
||||||
|
/// raw water sensor value
|
||||||
|
raw: number | null,
|
||||||
|
/// percent value
|
||||||
|
percent: number | null,
|
||||||
|
/// water in tank might be frozen
|
||||||
|
water_frozen: boolean,
|
||||||
|
/// water temperature
|
||||||
|
water_temp: number | null,
|
||||||
|
temp_sensor_error: string | null
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Controller } from "./main";
|
import { Controller } from "./main";
|
||||||
|
import {BatteryState} from "./api";
|
||||||
|
|
||||||
export class BatteryView{
|
export class BatteryView{
|
||||||
voltage_milli_volt: HTMLSpanElement;
|
voltage_milli_volt: HTMLSpanElement;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Controller } from "./main";
|
import {Controller} from "./main";
|
||||||
|
import {FileInfo, FileList} from "./api";
|
||||||
const regex = /[^a-zA-Z0-9_.]/g;
|
const regex = /[^a-zA-Z0-9_.]/g;
|
||||||
|
|
||||||
function sanitize(str:string){
|
function sanitize(str:string){
|
||||||
@@ -24,7 +24,7 @@ export class FileView {
|
|||||||
let fileuploadname = document.getElementById("fileuploadname") as HTMLInputElement
|
let fileuploadname = document.getElementById("fileuploadname") as HTMLInputElement
|
||||||
let fileuploadbtn = document.getElementById("fileuploadbtn") as HTMLInputElement
|
let fileuploadbtn = document.getElementById("fileuploadbtn") as HTMLInputElement
|
||||||
fileuploadfile.onchange = () => {
|
fileuploadfile.onchange = () => {
|
||||||
var selectedFile = fileuploadfile.files?.[0];
|
const selectedFile = fileuploadfile.files?.[0];
|
||||||
if (selectedFile == null) {
|
if (selectedFile == null) {
|
||||||
//TODO error dialog here
|
//TODO error dialog here
|
||||||
return
|
return
|
||||||
@@ -42,7 +42,7 @@ export class FileView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fileuploadbtn.onclick = () => {
|
fileuploadbtn.onclick = () => {
|
||||||
var selectedFile = fileuploadfile.files?.[0];
|
const selectedFile = fileuploadfile.files?.[0];
|
||||||
if (selectedFile == null) {
|
if (selectedFile == null) {
|
||||||
//TODO error dialog here
|
//TODO error dialog here
|
||||||
return
|
return
|
||||||
@@ -77,8 +77,7 @@ class FileEntry {
|
|||||||
this.view.classList.add("fileentryouter")
|
this.view.classList.add("fileentryouter")
|
||||||
|
|
||||||
const template = require('./fileviewentry.html') as string;
|
const template = require('./fileviewentry.html') as string;
|
||||||
const fileRaw = template.replaceAll("${fileid}", String(fileid));
|
this.view.innerHTML = template.replaceAll("${fileid}", String(fileid))
|
||||||
this.view.innerHTML = fileRaw
|
|
||||||
|
|
||||||
let name = document.getElementById("file_" + fileid + "_name") as HTMLElement;
|
let name = document.getElementById("file_" + fileid + "_name") as HTMLElement;
|
||||||
let size = document.getElementById("file_" + fileid + "_size") as HTMLElement;
|
let size = document.getElementById("file_" + fileid + "_size") as HTMLElement;
|
||||||
|
|||||||
20
rust/src_webpack/src/hardware.html
Normal file
20
rust/src_webpack/src/hardware.html
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<style>
|
||||||
|
.boardkey{
|
||||||
|
min-width: 200px;
|
||||||
|
}
|
||||||
|
.boardvalue{
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class="subtitle">Hardware:</div>
|
||||||
|
<div class="flexcontainer">
|
||||||
|
<div class="boardkey">BoardRevision</div>
|
||||||
|
<select class="boardvalue" id="hardware_board_value">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="flexcontainer">
|
||||||
|
<div class="boardkey">BatteryMonitor</div>
|
||||||
|
<select class="boardvalue" id="hardware_battery_value">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
45
rust/src_webpack/src/hardware.ts
Normal file
45
rust/src_webpack/src/hardware.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { Controller } from "./main";
|
||||||
|
import {BatteryBoardVersion, BoardHardware, BoardVersion} from "./api";
|
||||||
|
|
||||||
|
export class HardwareConfigView {
|
||||||
|
private readonly hardware_board_value: HTMLSelectElement;
|
||||||
|
private readonly hardware_battery_value: HTMLSelectElement;
|
||||||
|
constructor(controller:Controller){
|
||||||
|
(document.getElementById("hardwareview") as HTMLElement).innerHTML = require('./hardware.html') as string;
|
||||||
|
|
||||||
|
this.hardware_board_value = document.getElementById("hardware_board_value") as HTMLSelectElement;
|
||||||
|
this.hardware_board_value.onchange = controller.configChanged
|
||||||
|
|
||||||
|
Object.keys(BoardVersion).forEach(version => {
|
||||||
|
let option = document.createElement("option");
|
||||||
|
if (version == BoardVersion.INITIAL.toString()){
|
||||||
|
option.selected = true
|
||||||
|
}
|
||||||
|
option.innerText = version.toString();
|
||||||
|
this.hardware_board_value.appendChild(option);
|
||||||
|
})
|
||||||
|
|
||||||
|
this.hardware_battery_value = document.getElementById("hardware_battery_value") as HTMLSelectElement;
|
||||||
|
this.hardware_battery_value.onchange = controller.configChanged
|
||||||
|
Object.keys(BatteryBoardVersion).forEach(version => {
|
||||||
|
let option = document.createElement("option");
|
||||||
|
if (version == BatteryBoardVersion.Disabled.toString()){
|
||||||
|
option.selected = true
|
||||||
|
}
|
||||||
|
option.innerText = version.toString();
|
||||||
|
this.hardware_battery_value.appendChild(option);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfig(hardware: BoardHardware) {
|
||||||
|
this.hardware_board_value.value = hardware.board.toString()
|
||||||
|
this.hardware_battery_value.value = hardware.battery.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
getConfig(): BoardHardware {
|
||||||
|
return {
|
||||||
|
board : BoardVersion[this.hardware_board_value.value as keyof typeof BoardVersion],
|
||||||
|
battery : BatteryBoardVersion[this.hardware_battery_value.value as keyof typeof BatteryBoardVersion],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
rust/src_webpack/src/log.html
Normal file
7
rust/src_webpack/src/log.html
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<button id="loadLog">Load Logs</button>
|
||||||
|
<div id="logpanel">
|
||||||
|
|
||||||
|
</div>
|
||||||
46
rust/src_webpack/src/log.ts
Normal file
46
rust/src_webpack/src/log.ts
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { Controller } from "./main";
|
||||||
|
import {LogArray, LogLocalisation} from "./api";
|
||||||
|
|
||||||
|
export class LogView {
|
||||||
|
private readonly logpanel: HTMLElement;
|
||||||
|
private readonly loadLog: HTMLButtonElement;
|
||||||
|
loglocale: LogLocalisation | undefined;
|
||||||
|
|
||||||
|
constructor(controller: Controller) {
|
||||||
|
(document.getElementById("logview") as HTMLElement).innerHTML = require('./log.html') as string;
|
||||||
|
this.logpanel = document.getElementById("logpanel") as HTMLElement
|
||||||
|
this.loadLog = document.getElementById("loadLog") as HTMLButtonElement
|
||||||
|
|
||||||
|
this.loadLog.onclick = () => {
|
||||||
|
controller.loadLog();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setLogLocalisation(loglocale: LogLocalisation) {
|
||||||
|
this.loglocale = loglocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
setLog(logs: LogArray) {
|
||||||
|
this.logpanel.textContent = ""
|
||||||
|
logs.forEach(entry => {
|
||||||
|
let message = this.loglocale!![entry.message_id];
|
||||||
|
let template = message.message
|
||||||
|
template = template.replace("${number_a}", entry.a.toString());
|
||||||
|
template = template.replace("${number_b}", entry.b.toString());
|
||||||
|
template = template.replace("${txt_short}", entry.txt_short.toString());
|
||||||
|
template = template.replace("${txt_long}", entry.txt_long.toString());
|
||||||
|
|
||||||
|
let ts = new Date(entry.timestamp);
|
||||||
|
|
||||||
|
let div = document.createElement("div")
|
||||||
|
let timestampDiv = document.createElement("div")
|
||||||
|
let messageDiv = document.createElement("div")
|
||||||
|
timestampDiv.innerText = ts.toISOString();
|
||||||
|
messageDiv.innerText = template;
|
||||||
|
div.appendChild(timestampDiv)
|
||||||
|
div.appendChild(messageDiv)
|
||||||
|
this.logpanel.appendChild(div)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.progress {
|
.progress {
|
||||||
height: 1.5em;
|
height: 2.5em;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #555;
|
background-color: #555;
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
top: 5px;
|
top: 10px;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
animation: indeterminateAnimation 1s infinite linear;
|
animation: indeterminateAnimation 1s infinite linear;
|
||||||
transform-origin: 0% 50%;
|
transform-origin: 0 50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -75,15 +75,15 @@
|
|||||||
.subcontainer {
|
.subcontainer {
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
max-width: 900px;
|
max-width: 900px;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
.subcontainercontainer{
|
.subcontainercontainer{
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.plantcontainer {
|
.plantcontainer {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
@@ -120,15 +120,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.plantlist {
|
.plantlist {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.subtitle {
|
.subtitle {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,6 +138,10 @@
|
|||||||
|
|
||||||
|
|
||||||
<div class="container-xl">
|
<div class="container-xl">
|
||||||
|
<div style="display:flex; flex-wrap: wrap;">
|
||||||
|
<div id="hardwareview" class="subcontainer"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div style="display:flex; flex-wrap: wrap;">
|
<div style="display:flex; flex-wrap: wrap;">
|
||||||
<div id="firmwareview" class="subcontainer">
|
<div id="firmwareview" class="subcontainer">
|
||||||
</div>
|
</div>
|
||||||
@@ -145,6 +149,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div id="batteryview" class="subcontainer">
|
<div id="batteryview" class="subcontainer">
|
||||||
</div>
|
</div>
|
||||||
|
<div id="solarview" class="subcontainer">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flexcontainer">
|
<div class="flexcontainer">
|
||||||
@@ -171,6 +177,10 @@
|
|||||||
<button id="exit">Exit</button>
|
<button id="exit">Exit</button>
|
||||||
<button id="reboot">Reboot</button>
|
<button id="reboot">Reboot</button>
|
||||||
|
|
||||||
|
<div class="flexcontainer">
|
||||||
|
<div id="logview" class="subcontainercontainer"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script src="bundle.js"></script>
|
<script src="bundle.js"></script>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
|
import {deepEqual} from 'fast-equals';
|
||||||
import { deepEqual } from 'fast-equals';
|
|
||||||
|
|
||||||
declare var PUBLIC_URL: string;
|
declare var PUBLIC_URL: string;
|
||||||
console.log("Url is " + PUBLIC_URL);
|
console.log("Url is " + PUBLIC_URL);
|
||||||
@@ -7,426 +6,572 @@ console.log("Url is " + PUBLIC_URL);
|
|||||||
document.body.innerHTML = require('./main.html') as string;
|
document.body.innerHTML = require('./main.html') as string;
|
||||||
|
|
||||||
|
|
||||||
import { TimeView } from "./timeview";
|
import {TimeView} from "./timeview";
|
||||||
import { PlantView, PlantViews } from "./plant";
|
import {PlantViews} from "./plant";
|
||||||
import { NetworkConfigView } from "./network";
|
import {NetworkConfigView} from "./network";
|
||||||
import { NightLampView } from "./nightlightview";
|
import {NightLampView} from "./nightlightview";
|
||||||
import { TankConfigView } from "./tankview";
|
import {TankConfigView} from "./tankview";
|
||||||
import { SubmitView } from "./submitView";
|
import {SubmitView} from "./submitView";
|
||||||
import { ProgressView } from "./progress";
|
import {ProgressView} from "./progress";
|
||||||
import { OTAView } from "./ota";
|
import {OTAView} from "./ota";
|
||||||
import { BatteryView } from "./batteryview";
|
import {BatteryView} from "./batteryview";
|
||||||
import { FileView } from './fileview';
|
import {FileView} from './fileview';
|
||||||
|
import {LogView} from './log';
|
||||||
|
import {HardwareConfigView} from "./hardware";
|
||||||
|
import {
|
||||||
|
BackupHeader,
|
||||||
|
BatteryState,
|
||||||
|
GetTime, LogArray, LogLocalisation,
|
||||||
|
Moistures,
|
||||||
|
NightLampCommand,
|
||||||
|
PlantControllerConfig,
|
||||||
|
SetTime, SSIDList, TankInfo,
|
||||||
|
TestPump,
|
||||||
|
VersionInfo,
|
||||||
|
FileList, SolarState, PumpTestResult
|
||||||
|
} from "./api";
|
||||||
|
import {SolarView} from "./solarview";
|
||||||
|
|
||||||
export class Controller {
|
export class Controller {
|
||||||
getBackupInfo() {
|
loadTankInfo(): Promise<void> {
|
||||||
fetch(PUBLIC_URL + "/backup_info")
|
return fetch(PUBLIC_URL + "/tank")
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(json => json as BackupHeader)
|
.then(json => json as TankInfo)
|
||||||
.then(header => {
|
.then(tankinfo => {
|
||||||
controller.submitView.setBackupInfo(header)
|
controller.tankView.setTankInfo(tankinfo)
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
updateFileList() {
|
|
||||||
fetch(PUBLIC_URL + "/files")
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(json => json as FileList)
|
|
||||||
.then(filelist => {
|
|
||||||
controller.fileview.setFileList(filelist, PUBLIC_URL)
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
uploadFile(file: File, name:string) {
|
|
||||||
var current = 0;
|
|
||||||
var max = 100;
|
|
||||||
controller.progressview.addProgress("file_upload", (current / max) * 100, "Uploading File " + name + "(" + current + "/" + max + ")")
|
|
||||||
var ajax = new XMLHttpRequest();
|
|
||||||
ajax.upload.addEventListener("progress", event => {
|
|
||||||
current = event.loaded / 1000;
|
|
||||||
max = event.total / 1000;
|
|
||||||
controller.progressview.addProgress("file_upload", (current / max) * 100, "Uploading File " + name + "(" + current + "/" + max + ")")
|
|
||||||
}, false);
|
|
||||||
ajax.addEventListener("load", () => {
|
|
||||||
controller.progressview.removeProgress("file_upload")
|
|
||||||
controller.updateFileList()
|
|
||||||
}, false);
|
|
||||||
ajax.addEventListener("error", () => {
|
|
||||||
alert("Error upload")
|
|
||||||
controller.progressview.removeProgress("file_upload")
|
|
||||||
controller.updateFileList()
|
|
||||||
}, false);
|
|
||||||
ajax.addEventListener("abort", () => {
|
|
||||||
alert("abort upload")
|
|
||||||
controller.progressview.removeProgress("file_upload")
|
|
||||||
controller.updateFileList()
|
|
||||||
}, false);
|
|
||||||
ajax.open("POST", PUBLIC_URL + "/file?filename="+name);
|
|
||||||
ajax.send(file);
|
|
||||||
}
|
|
||||||
deleteFile(name:string) {
|
|
||||||
controller.progressview.addIndeterminate("file_delete", "Deleting " + name);
|
|
||||||
var ajax = new XMLHttpRequest();
|
|
||||||
ajax.open("DELETE", PUBLIC_URL + "/file?filename="+name);
|
|
||||||
ajax.send();
|
|
||||||
ajax.addEventListener("error", () => {
|
|
||||||
controller.progressview.removeProgress("file_delete")
|
|
||||||
alert("Error delete")
|
|
||||||
controller.updateFileList()
|
|
||||||
}, false);
|
|
||||||
ajax.addEventListener("abort", () => {
|
|
||||||
controller.progressview.removeProgress("file_delete")
|
|
||||||
alert("Error upload")
|
|
||||||
controller.updateFileList()
|
|
||||||
}, false);
|
|
||||||
ajax.addEventListener("load", () => {
|
|
||||||
controller.progressview.removeProgress("file_delete")
|
|
||||||
controller.updateFileList()
|
|
||||||
}, false);
|
|
||||||
controller.updateFileList()
|
|
||||||
}
|
|
||||||
|
|
||||||
updateRTCData() {
|
loadLogLocaleConfig() {
|
||||||
fetch(PUBLIC_URL + "/time")
|
return fetch(PUBLIC_URL + "/log_localization")
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(json => json as GetTime)
|
.then(json => json as LogLocalisation)
|
||||||
.then(time => {
|
.then(loglocale => {
|
||||||
controller.timeView.update(time.native, time.rtc)
|
controller.logView.setLogLocalisation(loglocale)
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
controller.timeView.update("n/a", "n/a")
|
console.log(error);
|
||||||
console.log(error);
|
});
|
||||||
});
|
}
|
||||||
}
|
|
||||||
updateBatteryData() {
|
|
||||||
fetch(PUBLIC_URL + "/battery")
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(json => json as BatteryState)
|
|
||||||
.then(battery => {
|
|
||||||
controller.batteryView.update(battery)
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
controller.batteryView.update(null)
|
|
||||||
console.log(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
uploadNewFirmware(file: File) {
|
|
||||||
var current = 0;
|
|
||||||
var max = 100;
|
|
||||||
controller.progressview.addProgress("ota_upload", (current / max) * 100, "Uploading firmeware (" + current + "/" + max + ")")
|
|
||||||
var ajax = new XMLHttpRequest();
|
|
||||||
ajax.upload.addEventListener("progress", event => {
|
|
||||||
current = event.loaded / 1000;
|
|
||||||
max = event.total / 1000;
|
|
||||||
controller.progressview.addProgress("ota_upload", (current / max) * 100, "Uploading firmeware (" + current + "/" + max + ")")
|
|
||||||
}, false);
|
|
||||||
ajax.addEventListener("load", () => {
|
|
||||||
controller.progressview.removeProgress("ota_upload")
|
|
||||||
controller.reboot();
|
|
||||||
}, false);
|
|
||||||
ajax.addEventListener("error", () => {
|
|
||||||
alert("Error ota")
|
|
||||||
controller.progressview.removeProgress("ota_upload")
|
|
||||||
}, false);
|
|
||||||
ajax.addEventListener("abort", () => {
|
|
||||||
alert("abort ota")
|
|
||||||
controller.progressview.removeProgress("ota_upload")
|
|
||||||
}, false);
|
|
||||||
ajax.open("POST", PUBLIC_URL + "/ota");
|
|
||||||
ajax.send(file);
|
|
||||||
}
|
|
||||||
version() {
|
|
||||||
controller.progressview.addIndeterminate("version", "Getting buildVersion")
|
|
||||||
fetch(PUBLIC_URL + "/version")
|
|
||||||
.then(response => response.json())
|
|
||||||
.then(json => json as VersionInfo)
|
|
||||||
.then(versionInfo => {
|
|
||||||
controller.progressview.removeProgress("version")
|
|
||||||
controller.firmWareView.setVersion(versionInfo);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
getBackupConfig() {
|
loadLog() {
|
||||||
controller.progressview.addIndeterminate("get_backup_config", "Downloading Backup")
|
return fetch(PUBLIC_URL + "/log")
|
||||||
fetch(PUBLIC_URL + "/get_backup_config")
|
.then(response => response.json())
|
||||||
.then(response => response.text())
|
.then(json => json as LogArray)
|
||||||
.then(loaded => {
|
.then(logs => {
|
||||||
controller.progressview.removeProgress("get_backup_config")
|
controller.logView.setLog(logs)
|
||||||
controller.submitView.setBackupJson(loaded);
|
})
|
||||||
})
|
.catch(error => {
|
||||||
}
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
downloadConfig() {
|
getBackupInfo(): Promise<void> {
|
||||||
controller.progressview.addIndeterminate("get_config", "Downloading Config")
|
return fetch(PUBLIC_URL + "/backup_info")
|
||||||
fetch(PUBLIC_URL + "/get_config")
|
.then(response => response.json())
|
||||||
.then(response => response.json())
|
.then(json => json as BackupHeader)
|
||||||
.then(loaded => {
|
.then(header => {
|
||||||
|
controller.submitView.setBackupInfo(header)
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
populateTimezones(): Promise<void> {
|
||||||
|
return fetch(PUBLIC_URL + '/timezones')
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(json => json as string[])
|
||||||
|
.then(timezones => {
|
||||||
|
controller.timeView.timezones(timezones)
|
||||||
|
})
|
||||||
|
.catch(error => console.error('Error fetching timezones:', error));
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFileList(): Promise<void> {
|
||||||
|
return fetch(PUBLIC_URL + "/files")
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(json => json as FileList)
|
||||||
|
.then(filelist => {
|
||||||
|
controller.fileview.setFileList(filelist, PUBLIC_URL)
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadFile(file: File, name: string) {
|
||||||
|
var current = 0;
|
||||||
|
var max = 100;
|
||||||
|
controller.progressview.addProgress("file_upload", (current / max) * 100, "Uploading File " + name + "(" + current + "/" + max + ")")
|
||||||
|
var ajax = new XMLHttpRequest();
|
||||||
|
ajax.upload.addEventListener("progress", event => {
|
||||||
|
current = event.loaded / 1000;
|
||||||
|
max = event.total / 1000;
|
||||||
|
controller.progressview.addProgress("file_upload", (current / max) * 100, "Uploading File " + name + "(" + current + "/" + max + ")")
|
||||||
|
}, false);
|
||||||
|
ajax.addEventListener("load", () => {
|
||||||
|
controller.progressview.removeProgress("file_upload")
|
||||||
|
controller.updateFileList()
|
||||||
|
}, false);
|
||||||
|
ajax.addEventListener("error", () => {
|
||||||
|
alert("Error upload")
|
||||||
|
controller.progressview.removeProgress("file_upload")
|
||||||
|
controller.updateFileList()
|
||||||
|
}, false);
|
||||||
|
ajax.addEventListener("abort", () => {
|
||||||
|
alert("abort upload")
|
||||||
|
controller.progressview.removeProgress("file_upload")
|
||||||
|
controller.updateFileList()
|
||||||
|
}, false);
|
||||||
|
ajax.open("POST", PUBLIC_URL + "/file?filename=" + name);
|
||||||
|
ajax.send(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteFile(name: string) {
|
||||||
|
controller.progressview.addIndeterminate("file_delete", "Deleting " + name);
|
||||||
|
var ajax = new XMLHttpRequest();
|
||||||
|
ajax.open("DELETE", PUBLIC_URL + "/file?filename=" + name);
|
||||||
|
ajax.send();
|
||||||
|
ajax.addEventListener("error", () => {
|
||||||
|
controller.progressview.removeProgress("file_delete")
|
||||||
|
alert("Error delete")
|
||||||
|
controller.updateFileList()
|
||||||
|
}, false);
|
||||||
|
ajax.addEventListener("abort", () => {
|
||||||
|
controller.progressview.removeProgress("file_delete")
|
||||||
|
alert("Error upload")
|
||||||
|
controller.updateFileList()
|
||||||
|
}, false);
|
||||||
|
ajax.addEventListener("load", () => {
|
||||||
|
controller.progressview.removeProgress("file_delete")
|
||||||
|
controller.updateFileList()
|
||||||
|
}, false);
|
||||||
|
controller.updateFileList()
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRTCData(): Promise<void> {
|
||||||
|
return fetch(PUBLIC_URL + "/time")
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(json => json as GetTime)
|
||||||
|
.then(time => {
|
||||||
|
controller.timeView.update(time.native, time.rtc)
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
controller.timeView.update("n/a", "n/a")
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBatteryData(): Promise<void> {
|
||||||
|
return fetch(PUBLIC_URL + "/battery")
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(json => json as BatteryState)
|
||||||
|
.then(battery => {
|
||||||
|
controller.batteryView.update(battery)
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
controller.batteryView.update(null)
|
||||||
|
console.log(error);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSolarData(): Promise<void> {
|
||||||
|
return fetch(PUBLIC_URL + "/solar")
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(json => json as SolarState)
|
||||||
|
.then(solar => {
|
||||||
|
controller.solarView.update(solar)
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
controller.solarView.update(null)
|
||||||
|
console.log(error);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
uploadNewFirmware(file: File) {
|
||||||
|
var current = 0;
|
||||||
|
var max = 100;
|
||||||
|
controller.progressview.addProgress("ota_upload", (current / max) * 100, "Uploading firmeware (" + current + "/" + max + ")")
|
||||||
|
var ajax = new XMLHttpRequest();
|
||||||
|
ajax.upload.addEventListener("progress", event => {
|
||||||
|
current = event.loaded / 1000;
|
||||||
|
max = event.total / 1000;
|
||||||
|
controller.progressview.addProgress("ota_upload", (current / max) * 100, "Uploading firmeware (" + current + "/" + max + ")")
|
||||||
|
}, false);
|
||||||
|
ajax.addEventListener("load", () => {
|
||||||
|
controller.progressview.removeProgress("ota_upload")
|
||||||
|
controller.reboot();
|
||||||
|
}, false);
|
||||||
|
ajax.addEventListener("error", () => {
|
||||||
|
alert("Error ota")
|
||||||
|
controller.progressview.removeProgress("ota_upload")
|
||||||
|
}, false);
|
||||||
|
ajax.addEventListener("abort", () => {
|
||||||
|
alert("abort ota")
|
||||||
|
controller.progressview.removeProgress("ota_upload")
|
||||||
|
}, false);
|
||||||
|
ajax.open("POST", PUBLIC_URL + "/ota");
|
||||||
|
ajax.send(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
version(): Promise<void> {
|
||||||
|
controller.progressview.addIndeterminate("version", "Getting buildVersion")
|
||||||
|
return fetch(PUBLIC_URL + "/version")
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(json => json as VersionInfo)
|
||||||
|
.then(versionInfo => {
|
||||||
|
controller.progressview.removeProgress("version")
|
||||||
|
controller.firmWareView.setVersion(versionInfo);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getBackupConfig() {
|
||||||
|
controller.progressview.addIndeterminate("get_backup_config", "Downloading Backup")
|
||||||
|
fetch(PUBLIC_URL + "/get_backup_config")
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(loaded => {
|
||||||
|
controller.progressview.removeProgress("get_backup_config")
|
||||||
|
controller.submitView.setBackupJson(loaded);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async downloadConfig(): Promise<void> {
|
||||||
|
controller.progressview.addIndeterminate("get_config", "Downloading Config")
|
||||||
|
const response = await fetch(PUBLIC_URL + "/get_config");
|
||||||
|
const loaded = await response.json();
|
||||||
var currentConfig = loaded as PlantControllerConfig;
|
var currentConfig = loaded as PlantControllerConfig;
|
||||||
controller.setInitialConfig(currentConfig);
|
controller.setInitialConfig(currentConfig);
|
||||||
controller.setConfig(currentConfig);
|
controller.setConfig(currentConfig);
|
||||||
//sync json view initially
|
//sync json view initially
|
||||||
this.configChanged();
|
controller.configChanged();
|
||||||
controller.progressview.removeProgress("get_config")
|
controller.progressview.removeProgress("get_config");
|
||||||
})
|
|
||||||
}
|
|
||||||
setInitialConfig(currentConfig: PlantControllerConfig) {
|
|
||||||
this.initialConfig = currentConfig
|
|
||||||
}
|
|
||||||
uploadConfig(json: string, statusCallback: (status: string) => void) {
|
|
||||||
controller.progressview.addIndeterminate("set_config", "Uploading Config")
|
|
||||||
fetch(PUBLIC_URL + "/set_config", {
|
|
||||||
method: "POST",
|
|
||||||
body: json,
|
|
||||||
})
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(text => statusCallback(text))
|
|
||||||
controller.progressview.removeProgress("set_config")
|
|
||||||
//load from remote to be clean
|
|
||||||
controller.downloadConfig()
|
|
||||||
}
|
|
||||||
backupConfig(json: string, statusCallback: (status: string) => void) {
|
|
||||||
controller.progressview.addIndeterminate("backup_config", "Backingup Config")
|
|
||||||
fetch(PUBLIC_URL + "/backup_config", {
|
|
||||||
method: "POST",
|
|
||||||
body: json,
|
|
||||||
})
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(text => statusCallback(text))
|
|
||||||
controller.progressview.removeProgress("backup_config")
|
|
||||||
}
|
|
||||||
syncRTCFromBrowser() {
|
|
||||||
controller.progressview.addIndeterminate("write_rtc", "Writing RTC")
|
|
||||||
var value: SetTime = {
|
|
||||||
time: new Date().toISOString()
|
|
||||||
}
|
}
|
||||||
var pretty = JSON.stringify(value, undefined, 1);
|
|
||||||
fetch(PUBLIC_URL + "/time", {
|
|
||||||
method: "POST",
|
|
||||||
body: pretty
|
|
||||||
}).then(
|
|
||||||
_ => controller.progressview.removeProgress("write_rtc")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
configChanged() {
|
setInitialConfig(currentConfig: PlantControllerConfig) {
|
||||||
const current = controller.getConfig();
|
this.initialConfig = currentConfig
|
||||||
var pretty = JSON.stringify(current, undefined, 0);
|
|
||||||
var initial = JSON.stringify(this.initialConfig, undefined, 0);
|
|
||||||
controller.submitView.setJson(pretty);
|
|
||||||
|
|
||||||
if (deepEqual(current, controller.initialConfig)) {
|
|
||||||
document.title = "PlantCtrl"
|
|
||||||
} else {
|
|
||||||
document.title = "*PlantCtrl"
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
testNightLamp(active: boolean){
|
uploadConfig(json: string, statusCallback: (status: string) => void) {
|
||||||
var body: NightLampCommand = {
|
controller.progressview.addIndeterminate("set_config", "Uploading Config")
|
||||||
active: active
|
fetch(PUBLIC_URL + "/set_config", {
|
||||||
|
method: "POST",
|
||||||
|
body: json,
|
||||||
|
})
|
||||||
|
.then(response => response.text())
|
||||||
|
.then(text => statusCallback(text))
|
||||||
|
controller.progressview.removeProgress("set_config")
|
||||||
|
//load from remote to be clean
|
||||||
|
controller.downloadConfig()
|
||||||
}
|
}
|
||||||
var pretty = JSON.stringify(body, undefined, 1);
|
|
||||||
fetch(PUBLIC_URL + "/lamptest", {
|
|
||||||
method: "POST",
|
|
||||||
body: pretty
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
testPlant(plantId: number) {
|
|
||||||
let counter = 0
|
|
||||||
let limit = 30
|
|
||||||
controller.progressview.addProgress("test_pump", counter / limit * 100, "Testing pump " + (plantId + 1) + " for " + (limit - counter) + "s")
|
|
||||||
|
|
||||||
let timerId: string | number | NodeJS.Timeout | undefined
|
|
||||||
function updateProgress() {
|
|
||||||
counter++;
|
|
||||||
controller.progressview.addProgress("test_pump", counter / limit * 100, "Testing pump " + (plantId + 1) + " for " + (limit - counter) + "s")
|
|
||||||
timerId = setTimeout(updateProgress, 1000);
|
|
||||||
|
|
||||||
|
backupConfig(json: string): Promise<string> {
|
||||||
|
return fetch(PUBLIC_URL + "/backup_config", {
|
||||||
|
method: "POST",
|
||||||
|
body: json,
|
||||||
|
})
|
||||||
|
.then(response => response.text());
|
||||||
}
|
}
|
||||||
timerId = setTimeout(updateProgress, 1000);
|
|
||||||
|
|
||||||
var body: TestPump = {
|
syncRTCFromBrowser() {
|
||||||
pump: plantId
|
controller.progressview.addIndeterminate("write_rtc", "Writing RTC")
|
||||||
|
const value: SetTime = {
|
||||||
|
time: new Date().toISOString()
|
||||||
|
};
|
||||||
|
const pretty = JSON.stringify(value, undefined, 1);
|
||||||
|
fetch(PUBLIC_URL + "/time", {
|
||||||
|
method: "POST",
|
||||||
|
body: pretty
|
||||||
|
}).then(
|
||||||
|
_ => controller.progressview.removeProgress("write_rtc")
|
||||||
|
)
|
||||||
}
|
}
|
||||||
var pretty = JSON.stringify(body, undefined, 1);
|
|
||||||
|
|
||||||
fetch(PUBLIC_URL + "/pumptest", {
|
configChanged() {
|
||||||
method: "POST",
|
const current = controller.getConfig();
|
||||||
body: pretty
|
var pretty = JSON.stringify(current, undefined, 0);
|
||||||
})
|
controller.submitView.setJson(pretty);
|
||||||
.then(response => response.text())
|
|
||||||
.then(
|
|
||||||
text => {
|
if (deepEqual(current, controller.initialConfig)) {
|
||||||
clearTimeout(timerId);
|
document.title = "PlantCtrl"
|
||||||
controller.progressview.removeProgress("test_pump");
|
} else {
|
||||||
|
document.title = "*PlantCtrl"
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
getConfig(): PlantControllerConfig {
|
|
||||||
return {
|
|
||||||
network: controller.networkView.getConfig(),
|
|
||||||
tank: controller.tankView.getConfig(),
|
|
||||||
night_lamp: controller.nightLampView.getConfig(),
|
|
||||||
plants: controller.plantViews.getConfig()
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
scanWifi() {
|
selfTest() {
|
||||||
let counter = 0
|
fetch(PUBLIC_URL + "/boardtest", {
|
||||||
let limit = 5
|
method: "POST"
|
||||||
controller.progressview.addProgress("scan_ssid", counter / limit * 100, "Scanning for SSIDs for " + (limit - counter) + "s")
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let timerId: string | number | NodeJS.Timeout | undefined
|
testNightLamp(active: boolean) {
|
||||||
function updateProgress() {
|
var body: NightLampCommand = {
|
||||||
counter++;
|
active: active
|
||||||
controller.progressview.addProgress("scan_ssid", counter / limit * 100, "Scanning for SSIDs for " + (limit - counter) + "s")
|
}
|
||||||
timerId = setTimeout(updateProgress, 1000);
|
var pretty = JSON.stringify(body, undefined, 1);
|
||||||
|
fetch(PUBLIC_URL + "/lamptest", {
|
||||||
|
method: "POST",
|
||||||
|
body: pretty
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
testPlant(plantId: number) {
|
||||||
|
let counter = 0
|
||||||
|
let limit = 30
|
||||||
|
controller.progressview.addProgress("test_pump", counter / limit * 100, "Testing pump " + (plantId + 1) + " for " + (limit - counter) + "s")
|
||||||
|
|
||||||
|
let timerId: string | number | NodeJS.Timeout | undefined
|
||||||
|
|
||||||
|
function updateProgress() {
|
||||||
|
counter++;
|
||||||
|
controller.progressview.addProgress("test_pump", counter / limit * 100, "Testing pump " + (plantId + 1) + " for " + (limit - counter) + "s")
|
||||||
|
timerId = setTimeout(updateProgress, 1000);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
timerId = setTimeout(updateProgress, 1000);
|
||||||
|
|
||||||
|
var body: TestPump = {
|
||||||
|
pump: plantId
|
||||||
|
}
|
||||||
|
var pretty = JSON.stringify(body, undefined, 1);
|
||||||
|
|
||||||
|
fetch(PUBLIC_URL + "/pumptest", {
|
||||||
|
method: "POST",
|
||||||
|
body: pretty
|
||||||
|
})
|
||||||
|
.then(response => response.json() as Promise<PumpTestResult>)
|
||||||
|
.then(
|
||||||
|
response => {
|
||||||
|
controller.plantViews.setPumpTestCurrent(plantId, response);
|
||||||
|
clearTimeout(timerId);
|
||||||
|
controller.progressview.removeProgress("test_pump");
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
getConfig(): PlantControllerConfig {
|
||||||
|
return {
|
||||||
|
hardware: controller.hardwareView.getConfig(),
|
||||||
|
network: controller.networkView.getConfig(),
|
||||||
|
tank: controller.tankView.getConfig(),
|
||||||
|
night_lamp: controller.nightLampView.getConfig(),
|
||||||
|
plants: controller.plantViews.getConfig(),
|
||||||
|
timezone: controller.timeView.getTimeZone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scanWifi() {
|
||||||
|
let counter = 0
|
||||||
|
let limit = 5
|
||||||
|
controller.progressview.addProgress("scan_ssid", counter / limit * 100, "Scanning for SSIDs for " + (limit - counter) + "s")
|
||||||
|
|
||||||
|
let timerId: string | number | NodeJS.Timeout | undefined
|
||||||
|
|
||||||
|
function updateProgress() {
|
||||||
|
counter++;
|
||||||
|
controller.progressview.addProgress("scan_ssid", counter / limit * 100, "Scanning for SSIDs for " + (limit - counter) + "s")
|
||||||
|
timerId = setTimeout(updateProgress, 1000);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
timerId = setTimeout(updateProgress, 1000);
|
||||||
|
|
||||||
|
|
||||||
|
var ajax = new XMLHttpRequest();
|
||||||
|
ajax.responseType = 'json';
|
||||||
|
ajax.onreadystatechange = () => {
|
||||||
|
if (ajax.readyState === 4) {
|
||||||
|
clearTimeout(timerId);
|
||||||
|
controller.progressview.removeProgress("scan_ssid");
|
||||||
|
this.networkView.setScanResult(ajax.response as SSIDList)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ajax.onerror = (evt) => {
|
||||||
|
clearTimeout(timerId);
|
||||||
|
controller.progressview.removeProgress("scan_ssid");
|
||||||
|
alert("Failed to start see console")
|
||||||
|
}
|
||||||
|
ajax.open("POST", PUBLIC_URL + "/wifiscan");
|
||||||
|
ajax.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
setConfig(current: PlantControllerConfig) {
|
||||||
|
this.tankView.setConfig(current.tank);
|
||||||
|
this.networkView.setConfig(current.network);
|
||||||
|
this.nightLampView.setConfig(current.night_lamp);
|
||||||
|
this.plantViews.setConfig(current.plants);
|
||||||
|
this.timeView.setTimeZone(current.timezone);
|
||||||
|
this.hardwareView.setConfig(current.hardware);
|
||||||
|
}
|
||||||
|
|
||||||
|
measure_moisture() {
|
||||||
|
let counter = 0
|
||||||
|
let limit = 2
|
||||||
|
controller.progressview.addProgress("measure_moisture", counter / limit * 100, "Measure Moisture " + (limit - counter) + "s")
|
||||||
|
|
||||||
|
let timerId: string | number | NodeJS.Timeout | undefined
|
||||||
|
|
||||||
|
function updateProgress() {
|
||||||
|
counter++;
|
||||||
|
controller.progressview.addProgress("measure_moisture", counter / limit * 100, "Measure Moisture " + (limit - counter) + "s")
|
||||||
|
timerId = setTimeout(updateProgress, 1000);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
timerId = setTimeout(updateProgress, 1000);
|
||||||
|
|
||||||
|
|
||||||
|
fetch(PUBLIC_URL + "/moisture")
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(json => json as Moistures)
|
||||||
|
.then(time => {
|
||||||
|
controller.plantViews.update(time.moisture_a, time.moisture_b)
|
||||||
|
clearTimeout(timerId);
|
||||||
|
controller.progressview.removeProgress("measure_moisture");
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
clearTimeout(timerId);
|
||||||
|
controller.progressview.removeProgress("measure_moisture");
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exit() {
|
||||||
|
fetch(PUBLIC_URL + "/exit", {
|
||||||
|
method: "POST",
|
||||||
|
})
|
||||||
|
controller.progressview.addIndeterminate("rebooting", "Returned to normal mode, you can close this site now")
|
||||||
|
|
||||||
}
|
}
|
||||||
timerId = setTimeout(updateProgress, 1000);
|
|
||||||
|
|
||||||
|
waitForReboot() {
|
||||||
var ajax = new XMLHttpRequest();
|
console.log("Check if controller online again")
|
||||||
ajax.responseType = 'json';
|
fetch(PUBLIC_URL + "/version", {
|
||||||
ajax.onreadystatechange = () => {
|
method: "GET",
|
||||||
if (ajax.readyState === 4) {
|
signal: AbortSignal.timeout(5000)
|
||||||
clearTimeout(timerId);
|
}).then(response => {
|
||||||
controller.progressview.removeProgress("scan_ssid");
|
if (response.status != 200) {
|
||||||
this.networkView.setScanResult(ajax.response as SSIDList)
|
console.log("Not reached yet, retrying")
|
||||||
}
|
setTimeout(controller.waitForReboot, 1000)
|
||||||
};
|
} else {
|
||||||
ajax.onerror = (evt) => {
|
console.log("Reached controller, reloading")
|
||||||
clearTimeout(timerId);
|
controller.progressview.addIndeterminate("rebooting", "Reached Controller, reloading")
|
||||||
controller.progressview.removeProgress("scan_ssid");
|
setTimeout(function () {
|
||||||
alert("Failed to start see console")
|
window.location.reload()
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log("Not reached yet, retrying")
|
||||||
|
setTimeout(controller.waitForReboot, 1000)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
ajax.open("POST", PUBLIC_URL + "/wifiscan");
|
|
||||||
ajax.send();
|
|
||||||
}
|
|
||||||
|
|
||||||
setConfig(current: PlantControllerConfig) {
|
|
||||||
this.tankView.setConfig(current.tank);
|
|
||||||
this.networkView.setConfig(current.network);
|
|
||||||
this.nightLampView.setConfig(current.night_lamp);
|
|
||||||
this.plantViews.setConfig(current.plants);
|
|
||||||
}
|
|
||||||
|
|
||||||
measure_moisture() {
|
|
||||||
let counter = 0
|
|
||||||
let limit = 2
|
|
||||||
controller.progressview.addProgress("measure_moisture", counter / limit * 100, "Measure Moisture " + (limit - counter) + "s")
|
|
||||||
|
|
||||||
let timerId: string | number | NodeJS.Timeout | undefined
|
|
||||||
function updateProgress() {
|
|
||||||
counter++;
|
|
||||||
controller.progressview.addProgress("measure_moisture", counter / limit * 100, "Measure Moisture " + (limit - counter) + "s")
|
|
||||||
timerId = setTimeout(updateProgress, 1000);
|
|
||||||
|
|
||||||
|
reboot() {
|
||||||
|
fetch(PUBLIC_URL + "/reboot", {
|
||||||
|
method: "POST",
|
||||||
|
})
|
||||||
|
controller.progressview.addIndeterminate("rebooting", "Rebooting")
|
||||||
|
setTimeout(this.waitForReboot, 1000)
|
||||||
}
|
}
|
||||||
timerId = setTimeout(updateProgress, 1000);
|
|
||||||
|
|
||||||
|
initialConfig: PlantControllerConfig | null = null
|
||||||
|
readonly rebootBtn: HTMLButtonElement
|
||||||
|
readonly exitBtn: HTMLButtonElement
|
||||||
|
readonly timeView: TimeView;
|
||||||
|
readonly plantViews: PlantViews;
|
||||||
|
readonly networkView: NetworkConfigView;
|
||||||
|
readonly hardwareView: HardwareConfigView;
|
||||||
|
readonly tankView: TankConfigView;
|
||||||
|
readonly nightLampView: NightLampView;
|
||||||
|
readonly submitView: SubmitView;
|
||||||
|
readonly firmWareView: OTAView;
|
||||||
|
readonly progressview: ProgressView;
|
||||||
|
readonly batteryView: BatteryView;
|
||||||
|
readonly solarView: SolarView;
|
||||||
|
readonly fileview: FileView;
|
||||||
|
readonly logView: LogView
|
||||||
|
|
||||||
fetch(PUBLIC_URL + "/moisture")
|
constructor() {
|
||||||
.then(response => response.json())
|
this.timeView = new TimeView(this)
|
||||||
.then(json => json as Moistures)
|
this.plantViews = new PlantViews(this)
|
||||||
.then(time => {
|
this.networkView = new NetworkConfigView(this, PUBLIC_URL)
|
||||||
controller.plantViews.update(time.moisture_a, time.moisture_b)
|
this.tankView = new TankConfigView(this)
|
||||||
clearTimeout(timerId);
|
this.batteryView = new BatteryView(this)
|
||||||
controller.progressview.removeProgress("measure_moisture");
|
this.solarView = new SolarView(this)
|
||||||
})
|
this.nightLampView = new NightLampView(this)
|
||||||
.catch(error => {
|
this.submitView = new SubmitView(this)
|
||||||
clearTimeout(timerId);
|
this.firmWareView = new OTAView(this)
|
||||||
controller.progressview.removeProgress("measure_moisture");
|
this.progressview = new ProgressView(this)
|
||||||
console.log(error);
|
this.fileview = new FileView(this)
|
||||||
});
|
this.logView = new LogView(this)
|
||||||
}
|
this.hardwareView = new HardwareConfigView(this)
|
||||||
|
this.rebootBtn = document.getElementById("reboot") as HTMLButtonElement
|
||||||
exit() {
|
this.rebootBtn.onclick = () => {
|
||||||
fetch(PUBLIC_URL + "/exit", {
|
controller.reboot();
|
||||||
method: "POST",
|
}
|
||||||
})
|
this.exitBtn = document.getElementById("exit") as HTMLButtonElement
|
||||||
controller.progressview.addIndeterminate("rebooting", "Returned to normal mode, you can close this site now")
|
this.exitBtn.onclick = () => {
|
||||||
|
controller.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForReboot() {
|
|
||||||
console.log("Check if controller online again")
|
|
||||||
fetch(PUBLIC_URL + "/version", {
|
|
||||||
method: "GET",
|
|
||||||
signal: AbortSignal.timeout(5000)
|
|
||||||
}).then(response => {
|
|
||||||
if (response.status != 200){
|
|
||||||
console.log("Not reached yet, retrying")
|
|
||||||
setTimeout(controller.waitForReboot, 1000)
|
|
||||||
} else {
|
|
||||||
console.log("Reached controller, reloading")
|
|
||||||
controller.progressview.addIndeterminate("rebooting", "Reached Controller, reloading")
|
|
||||||
setTimeout(function(){
|
|
||||||
window.location.reload()
|
|
||||||
}, 2000);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log("Not reached yet, retrying")
|
|
||||||
setTimeout(controller.waitForReboot, 1000)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
reboot() {
|
|
||||||
fetch(PUBLIC_URL + "/reboot", {
|
|
||||||
method: "POST",
|
|
||||||
})
|
|
||||||
controller.progressview.addIndeterminate("rebooting", "Rebooting")
|
|
||||||
setTimeout(this.waitForReboot, 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
initialConfig: PlantControllerConfig | null = null
|
|
||||||
readonly rebootBtn: HTMLButtonElement
|
|
||||||
readonly exitBtn: HTMLButtonElement
|
|
||||||
readonly timeView: TimeView;
|
|
||||||
readonly plantViews: PlantViews;
|
|
||||||
readonly networkView: NetworkConfigView;
|
|
||||||
readonly tankView: TankConfigView;
|
|
||||||
readonly nightLampView: NightLampView;
|
|
||||||
readonly submitView: SubmitView;
|
|
||||||
readonly firmWareView: OTAView;
|
|
||||||
readonly progressview: ProgressView;
|
|
||||||
readonly batteryView: BatteryView;
|
|
||||||
readonly fileview: FileView;
|
|
||||||
constructor() {
|
|
||||||
this.timeView = new TimeView(this)
|
|
||||||
this.plantViews = new PlantViews(this)
|
|
||||||
this.networkView = new NetworkConfigView(this, PUBLIC_URL)
|
|
||||||
this.tankView = new TankConfigView(this)
|
|
||||||
this.batteryView = new BatteryView(this)
|
|
||||||
this.nightLampView = new NightLampView(this)
|
|
||||||
this.submitView = new SubmitView(this)
|
|
||||||
this.firmWareView = new OTAView(this)
|
|
||||||
this.progressview = new ProgressView(this)
|
|
||||||
this.fileview = new FileView(this)
|
|
||||||
this.rebootBtn = document.getElementById("reboot") as HTMLButtonElement
|
|
||||||
this.rebootBtn.onclick = () => {
|
|
||||||
controller.reboot();
|
|
||||||
}
|
}
|
||||||
this.exitBtn = document.getElementById("exit") as HTMLButtonElement
|
|
||||||
this.exitBtn.onclick = () => {
|
|
||||||
controller.exit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const controller = new Controller();
|
const controller = new Controller();
|
||||||
controller.updateRTCData();
|
|
||||||
controller.updateBatteryData();
|
|
||||||
controller.downloadConfig();
|
|
||||||
//controller.measure_moisture();
|
|
||||||
controller.version();
|
|
||||||
controller.updateFileList();
|
|
||||||
controller.getBackupInfo();
|
|
||||||
controller.progressview.removeProgress("rebooting");
|
controller.progressview.removeProgress("rebooting");
|
||||||
|
|
||||||
|
|
||||||
|
const tasks = [
|
||||||
|
{task: controller.populateTimezones, displayString: "Populating Timezones"},
|
||||||
|
{task: controller.updateRTCData, displayString: "Updating RTC Data"},
|
||||||
|
{task: controller.updateBatteryData, displayString: "Updating Battery Data"},
|
||||||
|
{task: controller.updateSolarData, displayString: "Updating Solar Data"},
|
||||||
|
{task: controller.downloadConfig, displayString: "Downloading Configuration"},
|
||||||
|
{task: controller.version, displayString: "Fetching Version Information"},
|
||||||
|
{task: controller.updateFileList, displayString: "Updating File List"},
|
||||||
|
{task: controller.getBackupInfo, displayString: "Fetching Backup Information"},
|
||||||
|
{task: controller.loadLogLocaleConfig, displayString: "Loading Log Localization Config"},
|
||||||
|
{task: controller.loadTankInfo, displayString: "Loading Tank Information"},
|
||||||
|
];
|
||||||
|
|
||||||
|
async function executeTasksSequentially() {
|
||||||
|
let current = 0;
|
||||||
|
for (const {task, displayString} of tasks) {
|
||||||
|
current++;
|
||||||
|
let ratio = current / tasks.length;
|
||||||
|
controller.progressview.addProgress("initial", ratio * 100, displayString);
|
||||||
|
try {
|
||||||
|
await task();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error executing task '${displayString}':`, error);
|
||||||
|
// Optionally, you can decide whether to continue or break on errors
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
executeTasksSequentially().then(r => {
|
||||||
|
controller.progressview.removeProgress("initial")
|
||||||
|
});
|
||||||
|
|
||||||
|
controller.progressview.removeProgress("rebooting");
|
||||||
|
|
||||||
|
window.addEventListener("beforeunload", (event) => {
|
||||||
|
const currentConfig = controller.getConfig();
|
||||||
|
|
||||||
|
// Check if the current state differs from the initial configuration
|
||||||
|
if (!deepEqual(currentConfig, controller.initialConfig)) {
|
||||||
|
const confirmationMessage = "You have unsaved changes. Are you sure you want to leave this page?";
|
||||||
|
|
||||||
|
// Standard behavior for displaying the confirmation dialog
|
||||||
|
event.preventDefault();
|
||||||
|
event.returnValue = confirmationMessage; // This will trigger the browser's default dialog
|
||||||
|
return confirmationMessage;
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -42,6 +42,11 @@
|
|||||||
</datalist>
|
</datalist>
|
||||||
<input class="basicnetworkkeyssid2" type="button" id="scan" value="Scan">
|
<input class="basicnetworkkeyssid2" type="button" id="scan" value="Scan">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flexcontainer">
|
||||||
|
<label class="basicnetworkkey" for="max_wait">Max wait:</label>
|
||||||
|
<input class="basicnetworkvalue" type="number" id="max_wait">
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flexcontainer">
|
<div class="flexcontainer">
|
||||||
<label class="basicnetworkkey" for="ssid">Password:</label>
|
<label class="basicnetworkkey" for="ssid">Password:</label>
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import { Controller } from "./main";
|
import { Controller } from "./main";
|
||||||
|
import {NetworkConfig, SSIDList} from "./api";
|
||||||
|
|
||||||
export class NetworkConfigView {
|
export class NetworkConfigView {
|
||||||
setScanResult(ssidList: SSIDList) {
|
setScanResult(ssidList: SSIDList) {
|
||||||
this.ssidlist.innerHTML = ''
|
this.ssidlist.innerHTML = ''
|
||||||
for (var ssid of ssidList.ssids) {
|
for (const ssid of ssidList.ssids) {
|
||||||
var wi = document.createElement("option");
|
const wi = document.createElement("option");
|
||||||
wi.value = ssid;
|
wi.value = ssid;
|
||||||
this.ssidlist.appendChild(wi);
|
this.ssidlist.appendChild(wi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,6 +15,7 @@ export class NetworkConfigView {
|
|||||||
private readonly password: HTMLInputElement;
|
private readonly password: HTMLInputElement;
|
||||||
private readonly mqtt_url: HTMLInputElement;
|
private readonly mqtt_url: HTMLInputElement;
|
||||||
private readonly base_topic: HTMLInputElement;
|
private readonly base_topic: HTMLInputElement;
|
||||||
|
private readonly max_wait: HTMLInputElement;
|
||||||
private readonly ssidlist: HTMLElement;
|
private readonly ssidlist: HTMLElement;
|
||||||
|
|
||||||
constructor(controller: Controller, publicIp: string) {
|
constructor(controller: Controller, publicIp: string) {
|
||||||
@@ -28,6 +30,9 @@ export class NetworkConfigView {
|
|||||||
this.ssid.onchange = controller.configChanged
|
this.ssid.onchange = controller.configChanged
|
||||||
this.password = (document.getElementById("password") as HTMLInputElement);
|
this.password = (document.getElementById("password") as HTMLInputElement);
|
||||||
this.password.onchange = controller.configChanged
|
this.password.onchange = controller.configChanged
|
||||||
|
this.max_wait = (document.getElementById("max_wait") as HTMLInputElement);
|
||||||
|
this.max_wait.onchange = controller.configChanged
|
||||||
|
|
||||||
this.mqtt_url = document.getElementById("mqtt_url") as HTMLInputElement;
|
this.mqtt_url = document.getElementById("mqtt_url") as HTMLInputElement;
|
||||||
this.mqtt_url.onchange = controller.configChanged
|
this.mqtt_url.onchange = controller.configChanged
|
||||||
this.base_topic = document.getElementById("base_topic") as HTMLInputElement;
|
this.base_topic = document.getElementById("base_topic") as HTMLInputElement;
|
||||||
@@ -47,10 +52,12 @@ export class NetworkConfigView {
|
|||||||
this.password.value = network.password;
|
this.password.value = network.password;
|
||||||
this.mqtt_url.value = network.mqtt_url;
|
this.mqtt_url.value = network.mqtt_url;
|
||||||
this.base_topic.value = network.base_topic;
|
this.base_topic.value = network.base_topic;
|
||||||
|
this.max_wait.value = network.max_wait.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
getConfig(): NetworkConfig {
|
getConfig(): NetworkConfig {
|
||||||
return {
|
return {
|
||||||
|
max_wait: +this.max_wait.value,
|
||||||
ap_ssid: this.ap_ssid.value,
|
ap_ssid: this.ap_ssid.value,
|
||||||
ssid: this.ssid.value ?? null,
|
ssid: this.ssid.value ?? null,
|
||||||
password: this.password.value ?? null,
|
password: this.password.value ?? null,
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<div class="lightkey">Test Nightlight</div>
|
<div class="lightkey">Test Nightlight</div>
|
||||||
<input class="lightcheckbox" type="checkbox" id="night_lamp_test">
|
<input class="lightcheckbox" type="checkbox" id="night_lamp_test">
|
||||||
</div>
|
</div>
|
||||||
<div class="flexcontainer" style="text-decoration-line: line-through;">
|
<div class="flexcontainer">
|
||||||
<div class="lightkey">Enable Nightlight</div>
|
<div class="lightkey">Enable Nightlight</div>
|
||||||
<input class="lightcheckbox" type="checkbox" id="night_lamp_enabled">
|
<input class="lightcheckbox" type="checkbox" id="night_lamp_enabled">
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user