Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 53bbb1c55c | |||
| b66ee7f50e | |||
| d49c06e2ad |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 320 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 418 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
25
KiCad/0004-DenshaBekutoru_v0.2/0004-DenshaBekutoru_v0.2.csv
Normal file
25
KiCad/0004-DenshaBekutoru_v0.2/0004-DenshaBekutoru_v0.2.csv
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
"Reference","Value","Datasheet","Footprint","Qty","DNP"
|
||||||
|
"A1","Arduino_Pro_Mini_Socket_NoSPH_V2","https://docs.arduino.cc/retired/boards/arduino-pro-mini","arduino-library:Arduino_Pro_Mini_Socket_NoSPH_V2","1",""
|
||||||
|
"C4","4.7µF","~","Capacitor_THT:CP_Axial_L10.0mm_D6.0mm_P15.00mm_Horizontal","1",""
|
||||||
|
"C5","100nF","~","Capacitor_THT:C_Disc_D3.0mm_W1.6mm_P2.50mm","1",""
|
||||||
|
"D1,D2","1N4148","https://assets.nexperia.com/documents/data-sheet/1N4148_1N4448.pdf","Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal","2",""
|
||||||
|
"D3","1N5819","http://www.vishay.com/docs/88525/1n5817.pdf","Diode_THT:D_DO-41_SOD81_P10.16mm_Horizontal","1",""
|
||||||
|
"D4","LED Green","~","LED_THT:LED_D3.0mm","1",""
|
||||||
|
"D5","LED Yellow","~","LED_THT:LED_D3.0mm","1",""
|
||||||
|
"D10","LED: HL_A.1","","LED_THT:LED_D5.0mm_Clear","1",""
|
||||||
|
"D11","LED: HL_A.2","","LED_THT:LED_D5.0mm_Clear","1",""
|
||||||
|
"D12","LED: HL_B.1","","LED_THT:LED_D5.0mm_Clear","1",""
|
||||||
|
"D13","LED: HL_B.2","","LED_THT:LED_D5.0mm_Clear","1",""
|
||||||
|
"J1","from Lego","~","Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Vertical","1",""
|
||||||
|
"J2","Headlight GND","~","Connector_PinSocket_2.54mm:PinSocket_1x04_P2.54mm_Vertical","1",""
|
||||||
|
"J3","Headlight GND; A1,2/B1,2","~","Connector_PinSocket_2.54mm:PinSocket_1x05_P2.54mm_Vertical","1",""
|
||||||
|
"J4","Headlight Test","~","Connector_PinHeader_2.54mm:PinHeader_1x05_P2.54mm_Horizontal","1",""
|
||||||
|
"J5","I2C","~","Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical","1",""
|
||||||
|
"J6","TX/RX","~","Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical","1",""
|
||||||
|
"J7","Add. Lights","~","Connector_PinSocket_2.54mm:PinSocket_1x04_P2.54mm_Vertical","1",""
|
||||||
|
"J8","LDR (~1MOhm) Option","~","Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical","1",""
|
||||||
|
"R1,R2","1.5k","~","Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P5.08mm_Horizontal","2",""
|
||||||
|
"R3,R4,R5,R6,R7,R8","220","~","Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P5.08mm_Horizontal","6",""
|
||||||
|
"R9","10k","~","Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P5.08mm_Horizontal","1",""
|
||||||
|
"RV1","1MOhm","~","Potentiometer_THT:Potentiometer_Piher_PT-10-V10_Vertical","1",""
|
||||||
|
"U1,U2","PC817","http://www.soselectronic.cz/a_info/resource/d/pc817.pdf","Package_DIP:DIP-4_W7.62mm","2",""
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
(paper "A4")
|
(paper "A4")
|
||||||
(title_block
|
(title_block
|
||||||
(title "DenshaBekutoru 電車ベクトル (Train Vector)")
|
(title "DenshaBekutoru 電車ベクトル (Train Vector)")
|
||||||
(date "2026-02-24")
|
(date "2026-03-08")
|
||||||
(rev "2")
|
(rev "3")
|
||||||
(company "ToGo-Lab")
|
(company "ToGo-Lab")
|
||||||
(comment 1 "- https://togo-lab.io/")
|
(comment 1 "- https://togo-lab.io/")
|
||||||
(comment 2 "- Email: tgohle@togo-lab.io")
|
(comment 2 "- Email: tgohle@togo-lab.io")
|
||||||
@ -3004,7 +3004,7 @@
|
|||||||
(at 130.4925 113.3475 90)
|
(at 130.4925 113.3475 90)
|
||||||
(descr "https://docs.arduino.cc/retired/boards/arduino-pro-mini")
|
(descr "https://docs.arduino.cc/retired/boards/arduino-pro-mini")
|
||||||
(property "Reference" "A1"
|
(property "Reference" "A1"
|
||||||
(at 3.81 -13.335 180)
|
(at 5.3975 -12.7 180)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
(uuid "0befe7a5-9602-4846-aa08-d4bc64dae7e1")
|
(uuid "0befe7a5-9602-4846-aa08-d4bc64dae7e1")
|
||||||
(effects
|
(effects
|
||||||
@ -3015,7 +3015,7 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Value" "Arduino_Pro_Mini_NoSPH_V2"
|
(property "Value" "Arduino_Pro_Mini_NoSPH_V2"
|
||||||
(at 2.2225 -3.81 180)
|
(at 2.8575 -3.4925 180)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
(uuid "2049cef5-6275-4255-ac56-b304d432463d")
|
(uuid "2049cef5-6275-4255-ac56-b304d432463d")
|
||||||
(effects
|
(effects
|
||||||
@ -4398,7 +4398,7 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Value" "Test Adapter"
|
(property "Value" "Test Adapter"
|
||||||
(at -1.27 -7.3025 0)
|
(at -9.2075 17.78 0)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
(uuid "18cffcf1-af66-444d-affe-79487dc09495")
|
(uuid "18cffcf1-af66-444d-affe-79487dc09495")
|
||||||
(effects
|
(effects
|
||||||
@ -7362,7 +7362,7 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Value" "1.8k"
|
(property "Value" "1.5k"
|
||||||
(at 2.54 0 0)
|
(at 2.54 0 0)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
(uuid "ee02cf63-7b31-43a1-82ae-44160db1979a")
|
(uuid "ee02cf63-7b31-43a1-82ae-44160db1979a")
|
||||||
@ -9818,7 +9818,7 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Value" "1.8k"
|
(property "Value" "1.5k"
|
||||||
(at 2.54 0 0)
|
(at 2.54 0 0)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
(uuid "ba12106b-c82c-4288-b78a-a458b5c67f48")
|
(uuid "ba12106b-c82c-4288-b78a-a458b5c67f48")
|
||||||
@ -10035,6 +10035,26 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
(gr_line
|
||||||
|
(start 105.2068 109.8804)
|
||||||
|
(end 102.4382 109.8804)
|
||||||
|
(stroke
|
||||||
|
(width 0.25)
|
||||||
|
(type default)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "a27b89ca-9346-42e2-be30-337456045f6d")
|
||||||
|
)
|
||||||
|
(gr_line
|
||||||
|
(start 105.2576 103.5812)
|
||||||
|
(end 102.489 103.5812)
|
||||||
|
(stroke
|
||||||
|
(width 0.25)
|
||||||
|
(type default)
|
||||||
|
)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "f3f41b38-c983-4582-a366-c9d6a3f3fd9e")
|
||||||
|
)
|
||||||
(gr_line
|
(gr_line
|
||||||
(start 208.915 123.19)
|
(start 208.915 123.19)
|
||||||
(end 182.88 123.19)
|
(end 182.88 123.19)
|
||||||
@ -11068,7 +11088,7 @@
|
|||||||
(layer "User.1")
|
(layer "User.1")
|
||||||
(uuid "f9057d61-3846-4a87-94cf-218abb7358cc")
|
(uuid "f9057d61-3846-4a87-94cf-218abb7358cc")
|
||||||
)
|
)
|
||||||
(gr_text "Part #0004_v2\nRev 2026/02\ntogo-lab.io\ntgohle@togo-lab.io\n"
|
(gr_text "Part #0004_v2\nRev 2026/03\ntogo-lab.io\ntgohle@togo-lab.io\n"
|
||||||
(at 105.0925 122.2375 0)
|
(at 105.0925 122.2375 0)
|
||||||
(layer "B.SilkS")
|
(layer "B.SilkS")
|
||||||
(uuid "05969e3e-86ff-4cc3-99fa-1a05d36faca3")
|
(uuid "05969e3e-86ff-4cc3-99fa-1a05d36faca3")
|
||||||
@ -11087,7 +11107,8 @@
|
|||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1 1)
|
(size 1 1)
|
||||||
(thickness 0.1)
|
(thickness 0.2)
|
||||||
|
(bold yes)
|
||||||
)
|
)
|
||||||
(justify left bottom mirror)
|
(justify left bottom mirror)
|
||||||
)
|
)
|
||||||
@ -11104,7 +11125,7 @@
|
|||||||
(justify mirror)
|
(justify mirror)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(gr_text "from Lego\nconnector"
|
(gr_text "from Lego\nor BlueBrix\n"
|
||||||
(at 99.06 113.03 270)
|
(at 99.06 113.03 270)
|
||||||
(layer "B.SilkS")
|
(layer "B.SilkS")
|
||||||
(uuid "6851b0c0-457b-4620-afd0-3f5a0bb10f50")
|
(uuid "6851b0c0-457b-4620-afd0-3f5a0bb10f50")
|
||||||
@ -11279,7 +11300,8 @@
|
|||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1 1)
|
(size 1 1)
|
||||||
(thickness 0.1)
|
(thickness 0.2)
|
||||||
|
(bold yes)
|
||||||
)
|
)
|
||||||
(justify bottom)
|
(justify bottom)
|
||||||
)
|
)
|
||||||
@ -11296,6 +11318,18 @@
|
|||||||
(justify left bottom)
|
(justify left bottom)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
(gr_text "A"
|
||||||
|
(at 105.0925 114.935 0)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "78080d62-92dd-4e93-aee5-6f3cb7f83d9f")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.1)
|
||||||
|
)
|
||||||
|
(justify left bottom)
|
||||||
|
)
|
||||||
|
)
|
||||||
(gr_text "GND\n(L1)"
|
(gr_text "GND\n(L1)"
|
||||||
(at 100.33 114.6175 0)
|
(at 100.33 114.6175 0)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
@ -11303,11 +11337,24 @@
|
|||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1 1)
|
(size 1 1)
|
||||||
(thickness 0.1)
|
(thickness 0.2)
|
||||||
|
(bold yes)
|
||||||
)
|
)
|
||||||
(justify bottom)
|
(justify bottom)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
(gr_text "K"
|
||||||
|
(at 105.0925 111.125 0)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "8593805b-f433-42d6-9789-6f22b613312d")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.1)
|
||||||
|
)
|
||||||
|
(justify left bottom)
|
||||||
|
)
|
||||||
|
)
|
||||||
(gr_text "GND"
|
(gr_text "GND"
|
||||||
(at 164.465 102.5525 90)
|
(at 164.465 102.5525 90)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
@ -11356,6 +11403,18 @@
|
|||||||
(justify left bottom)
|
(justify left bottom)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
(gr_text "<-- Prog. Connector"
|
||||||
|
(at 116.5225 112.7125 0)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "ae66e616-f48b-4958-ada3-e607bb17fc01")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.1)
|
||||||
|
)
|
||||||
|
(justify left bottom)
|
||||||
|
)
|
||||||
|
)
|
||||||
(gr_text "L3"
|
(gr_text "L3"
|
||||||
(at 99.3775 108.585 0)
|
(at 99.3775 108.585 0)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
@ -11381,8 +11440,33 @@
|
|||||||
(justify left bottom)
|
(justify left bottom)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(gr_text "LDR ~1MOhm\n(Option)"
|
(gr_text "K"
|
||||||
(at 161.29 121.6025 0)
|
(at 105.0925 104.775 0)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "c6269c73-2ab4-4cf6-b71d-e007ca1f9d6d")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.1)
|
||||||
|
)
|
||||||
|
(justify left bottom)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(gr_text "Option Board"
|
||||||
|
(at 163.5125 122.555 0)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "c7b274f2-61f2-470d-b434-e87e301cfa43")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.2)
|
||||||
|
(bold yes)
|
||||||
|
)
|
||||||
|
(justify left bottom)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
(gr_text "LDR ~1MOhm"
|
||||||
|
(at 157.7975 118.745 0)
|
||||||
(layer "F.SilkS")
|
(layer "F.SilkS")
|
||||||
(uuid "cae645b2-6fe1-4073-9efc-58388b6a68f6")
|
(uuid "cae645b2-6fe1-4073-9efc-58388b6a68f6")
|
||||||
(effects
|
(effects
|
||||||
@ -11465,6 +11549,18 @@
|
|||||||
(justify left bottom)
|
(justify left bottom)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
(gr_text "A"
|
||||||
|
(at 105.0925 108.585 0)
|
||||||
|
(layer "F.SilkS")
|
||||||
|
(uuid "ff7c7853-2377-4b59-a6d6-fc23e62dbb21")
|
||||||
|
(effects
|
||||||
|
(font
|
||||||
|
(size 1 1)
|
||||||
|
(thickness 0.1)
|
||||||
|
)
|
||||||
|
(justify left bottom)
|
||||||
|
)
|
||||||
|
)
|
||||||
(gr_text "PCB Dimension Note:\nNeeds to fit in Lego Raster (8mm x 8mm / 64x32)\n& 3D printed case with wall thickness > 1mm.\n\n\n X (mm) Y (mm) Notes\nPractical max 28.86 60.86 With 0.3 mm clearance\nAdjusted to grid) **27.94** **58.42** **Best choice**\n"
|
(gr_text "PCB Dimension Note:\nNeeds to fit in Lego Raster (8mm x 8mm / 64x32)\n& 3D printed case with wall thickness > 1mm.\n\n\n X (mm) Y (mm) Notes\nPractical max 28.86 60.86 With 0.3 mm clearance\nAdjusted to grid) **27.94** **58.42** **Best choice**\n"
|
||||||
(at 94.615 82.2325 0)
|
(at 94.615 82.2325 0)
|
||||||
(layer "User.1")
|
(layer "User.1")
|
||||||
@ -17490,14 +17586,6 @@
|
|||||||
(net 28)
|
(net 28)
|
||||||
(uuid "11883106-b98d-45fa-8770-f791ec08e266")
|
(uuid "11883106-b98d-45fa-8770-f791ec08e266")
|
||||||
)
|
)
|
||||||
(segment
|
|
||||||
(start 118.999 103.124)
|
|
||||||
(end 118.999 102.362)
|
|
||||||
(width 0.25)
|
|
||||||
(layer "F.Cu")
|
|
||||||
(net 28)
|
|
||||||
(uuid "16b27e74-bc4e-4cd5-91fd-fcb0430a7b56")
|
|
||||||
)
|
|
||||||
(segment
|
(segment
|
||||||
(start 103.886 103.124)
|
(start 103.886 103.124)
|
||||||
(end 118.999 103.124)
|
(end 118.999 103.124)
|
||||||
@ -17507,12 +17595,20 @@
|
|||||||
(uuid "297201a0-b4e1-4701-a6a0-437f93a90073")
|
(uuid "297201a0-b4e1-4701-a6a0-437f93a90073")
|
||||||
)
|
)
|
||||||
(segment
|
(segment
|
||||||
(start 118.999 102.362)
|
(start 122.428 103.124)
|
||||||
(end 122.428 102.362)
|
(end 132.969 103.124)
|
||||||
(width 0.25)
|
(width 0.25)
|
||||||
(layer "F.Cu")
|
(layer "F.Cu")
|
||||||
(net 28)
|
(net 28)
|
||||||
(uuid "39782305-3b85-46f7-8a18-450f173e1715")
|
(uuid "4b6a95e0-dece-4b23-a69b-84d8db6b9c27")
|
||||||
|
)
|
||||||
|
(segment
|
||||||
|
(start 122.428 102.362)
|
||||||
|
(end 122.428 103.124)
|
||||||
|
(width 0.25)
|
||||||
|
(layer "F.Cu")
|
||||||
|
(net 28)
|
||||||
|
(uuid "5a718368-6d0b-497e-8c07-d1a38574afa8")
|
||||||
)
|
)
|
||||||
(segment
|
(segment
|
||||||
(start 132.969 105.664)
|
(start 132.969 105.664)
|
||||||
@ -17522,6 +17618,14 @@
|
|||||||
(net 28)
|
(net 28)
|
||||||
(uuid "90e988ff-6419-4a22-9ecb-f6c86412067d")
|
(uuid "90e988ff-6419-4a22-9ecb-f6c86412067d")
|
||||||
)
|
)
|
||||||
|
(segment
|
||||||
|
(start 118.999 103.124)
|
||||||
|
(end 122.428 103.124)
|
||||||
|
(width 0.25)
|
||||||
|
(layer "F.Cu")
|
||||||
|
(net 28)
|
||||||
|
(uuid "92ff86ca-3f4e-472d-85a0-bc795724ed2f")
|
||||||
|
)
|
||||||
(segment
|
(segment
|
||||||
(start 127.9475 97.79)
|
(start 127.9475 97.79)
|
||||||
(end 122.428 97.79)
|
(end 122.428 97.79)
|
||||||
@ -17530,14 +17634,6 @@
|
|||||||
(net 28)
|
(net 28)
|
||||||
(uuid "94771de6-f506-474d-83c7-5c2cea7b0856")
|
(uuid "94771de6-f506-474d-83c7-5c2cea7b0856")
|
||||||
)
|
)
|
||||||
(segment
|
|
||||||
(start 132.969 102.362)
|
|
||||||
(end 122.428 102.362)
|
|
||||||
(width 0.25)
|
|
||||||
(layer "F.Cu")
|
|
||||||
(net 28)
|
|
||||||
(uuid "99c30f69-9aa9-424f-9ee0-7c341a491e2e")
|
|
||||||
)
|
|
||||||
(segment
|
(segment
|
||||||
(start 128.016 97.7215)
|
(start 128.016 97.7215)
|
||||||
(end 127.9525 97.785)
|
(end 127.9525 97.785)
|
||||||
@ -17571,12 +17667,12 @@
|
|||||||
(uuid "e7e6f896-d67f-42d8-8b1a-1337fbf2c40c")
|
(uuid "e7e6f896-d67f-42d8-8b1a-1337fbf2c40c")
|
||||||
)
|
)
|
||||||
(segment
|
(segment
|
||||||
(start 132.969 102.362)
|
(start 132.969 103.124)
|
||||||
(end 132.969 105.664)
|
(end 132.969 105.664)
|
||||||
(width 0.25)
|
(width 0.25)
|
||||||
(layer "F.Cu")
|
(layer "F.Cu")
|
||||||
(net 28)
|
(net 28)
|
||||||
(uuid "eb625b4c-1b5e-4764-bfdd-1795cca3f3fb")
|
(uuid "ef095471-86a3-42b7-9452-58b94748cb2f")
|
||||||
)
|
)
|
||||||
(segment
|
(segment
|
||||||
(start 122.428 102.362)
|
(start 122.428 102.362)
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"board": {
|
"board": {
|
||||||
"active_layer": 33,
|
"active_layer": 0,
|
||||||
"active_layer_preset": "All Layers",
|
"active_layer_preset": "All Layers",
|
||||||
"auto_track_width": true,
|
"auto_track_width": true,
|
||||||
"hidden_netclasses": [],
|
"hidden_netclasses": [],
|
||||||
|
|||||||
@ -507,7 +507,7 @@
|
|||||||
},
|
},
|
||||||
"schematic": {
|
"schematic": {
|
||||||
"annotate_start_num": 0,
|
"annotate_start_num": 0,
|
||||||
"bom_export_filename": "",
|
"bom_export_filename": "0004-DenshaBekutoru_v0.2.csv",
|
||||||
"bom_fmt_presets": [],
|
"bom_fmt_presets": [],
|
||||||
"bom_fmt_settings": {
|
"bom_fmt_settings": {
|
||||||
"field_delimiter": ",",
|
"field_delimiter": ",",
|
||||||
@ -557,11 +557,35 @@
|
|||||||
"label": "DNP",
|
"label": "DNP",
|
||||||
"name": "${DNP}",
|
"name": "${DNP}",
|
||||||
"show": true
|
"show": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group_by": false,
|
||||||
|
"label": "#",
|
||||||
|
"name": "${ITEM_NUMBER}",
|
||||||
|
"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": "Description",
|
||||||
|
"name": "Description",
|
||||||
|
"show": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"filter_string": "",
|
"filter_string": "",
|
||||||
"group_symbols": true,
|
"group_symbols": true,
|
||||||
"name": "Grouped By Value",
|
"name": "",
|
||||||
"sort_asc": true,
|
"sort_asc": true,
|
||||||
"sort_field": "Reference"
|
"sort_field": "Reference"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -6,8 +6,8 @@
|
|||||||
(paper "A4")
|
(paper "A4")
|
||||||
(title_block
|
(title_block
|
||||||
(title "DenshaBekutoru 電車ベクトル (Train Vector)")
|
(title "DenshaBekutoru 電車ベクトル (Train Vector)")
|
||||||
(date "2026-02-24")
|
(date "2026-03-08")
|
||||||
(rev "#004")
|
(rev "#005 1st bld.")
|
||||||
(company "ToGo-Lab")
|
(company "ToGo-Lab")
|
||||||
(comment 1 "- https://togo-lab.io/")
|
(comment 1 "- https://togo-lab.io/")
|
||||||
(comment 2 "- Email: tgohle@togo-lab.io")
|
(comment 2 "- Email: tgohle@togo-lab.io")
|
||||||
@ -5902,9 +5902,9 @@
|
|||||||
)
|
)
|
||||||
(uuid "0f47aaa2-d5fd-479c-9cd8-bfe8a8174c43")
|
(uuid "0f47aaa2-d5fd-479c-9cd8-bfe8a8174c43")
|
||||||
)
|
)
|
||||||
(text "Detachable part of PCB (I),\nOption. If communication\nis needed.\n"
|
(text "Detachable part of PCB (I),\nOption. If communication\nis needed.\n\n! not tested\n"
|
||||||
(exclude_from_sim no)
|
(exclude_from_sim no)
|
||||||
(at 93.218 80.518 0)
|
(at 93.472 82.042 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
@ -5913,9 +5913,9 @@
|
|||||||
)
|
)
|
||||||
(uuid "13419e56-d967-466e-bc8e-26537e73dd52")
|
(uuid "13419e56-d967-466e-bc8e-26537e73dd52")
|
||||||
)
|
)
|
||||||
(text "Detachable part of PCB, Option\nIf used, control PWM (Light) by \n- LDR (dark ~ 1Mohm) or\n- Potentiometer 1Mohm (manually aqdjusted)"
|
(text "Detachable part of PCB, Option\nIf used, control PWM (Light) by \n- LDR (dark ~ 1Mohm) or\n- Potentiometer 1Mohm (manually aqdjusted)\n\n! Not tested"
|
||||||
(exclude_from_sim no)
|
(exclude_from_sim no)
|
||||||
(at 78.486 171.958 0)
|
(at 78.232 170.18 0)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
(size 1.27 1.27)
|
(size 1.27 1.27)
|
||||||
@ -5935,7 +5935,7 @@
|
|||||||
)
|
)
|
||||||
(uuid "2f37a28e-8a64-4672-a892-5431464a2db8")
|
(uuid "2f37a28e-8a64-4672-a892-5431464a2db8")
|
||||||
)
|
)
|
||||||
(text "PWM LED drive – Arduino Pro Mini (ATmega328P)\n- PWM pins used: D3 (Timer2, 8-bit) and D9 (Timer1, 16-bit)\n- Control via analogWrite() → 0–255 on both timers (no practical difference for LEDs)\n- Each PWM pin drives 2× white LEDs in parallel, each LED with its own 220 Ω resistor\n- Approx. current per LED ≈ 7–8 mA, per pin ≈ 15 mA → safe for MCU\n- D0/D1 (TX/RX) free for later communication\n- Timer0 untouched → millis()/delay() unaffected\n- No Servo / tone / IR usage planned → no timer conflicts expected\n- Remember, Unsused D/A Connectors: Unconnected (no Pullup), but:\n Digital ones: \"pinMode(pin, INPUT_PULLUP);\" and Ax: nothing."
|
(text "PWM LED drive – Arduino Pro Mini (ATmega328P)\n- PWM pins used: D3 (Timer2, 8-bit) and D9 (Timer1, 16-bit)\n- Control via analogWrite() → 0–255 on both timers (no practical difference for LEDs)\n- Each PWM pin drives 2× white LEDs in parallel, each LED with its own 220 Ω resistor\n- Approx. current per LED ≈ 7–8 mA, per pin ≈ 15 mA → safe for MCU\n- D0/D1 (TX/RX) free for later communication\n- Timer0 untouched → millis()/delay() unaffected\n- No Servo / tone / IR usage planned → no timer conflicts expected\n- Remember, Unsused D/A Connectors: Unconnected (no Pullup), but:\n Digital ones: \"pinMode(pin, INPUT_PULLUP);\" and Ax: nothing.\n- all R smallest type (1/4W), due small footprint"
|
||||||
(exclude_from_sim no)
|
(exclude_from_sim no)
|
||||||
(at 128.778 49.53 0)
|
(at 128.778 49.53 0)
|
||||||
(effects
|
(effects
|
||||||
@ -5967,7 +5967,7 @@
|
|||||||
)
|
)
|
||||||
(uuid "9433f522-95dc-40eb-b260-abe7c4605d43")
|
(uuid "9433f522-95dc-40eb-b260-abe7c4605d43")
|
||||||
)
|
)
|
||||||
(text "Detachable part of PCB (I)\nAdditional PWM Lights\n- Timer1, (D9): D10\n- Timer2, (D3): D11\n! Don't forget Resistors"
|
(text "Detachable part of PCB (I)\nAdditional PWM Lights\n- Timer1, (D9): D10\n- Timer2, (D3): D11\n! Don't forget Resistors\n\n! Not tested"
|
||||||
(exclude_from_sim no)
|
(exclude_from_sim no)
|
||||||
(at 246.38 66.04 0)
|
(at 246.38 66.04 0)
|
||||||
(effects
|
(effects
|
||||||
@ -7071,7 +7071,7 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Value" "1.8k"
|
(property "Value" "1.5k"
|
||||||
(at 58.42 118.11 90)
|
(at 58.42 118.11 90)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
@ -7204,7 +7204,7 @@
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
(property "Value" "1.8k"
|
(property "Value" "1.5k"
|
||||||
(at 58.42 106.68 90)
|
(at 58.42 106.68 90)
|
||||||
(effects
|
(effects
|
||||||
(font
|
(font
|
||||||
|
|||||||
Binary file not shown.
1108
KiCad/0004-DenshaBekutoru_v0.2/0004-DenshaBekutoru_v0.2.xml
Normal file
1108
KiCad/0004-DenshaBekutoru_v0.2/0004-DenshaBekutoru_v0.2.xml
Normal file
File diff suppressed because it is too large
Load Diff
BIN
KiCad/0004-DenshaBekutoru_v0.2/0004-DenshaBekutoru_v0.2_PCB.pdf
Normal file
BIN
KiCad/0004-DenshaBekutoru_v0.2/0004-DenshaBekutoru_v0.2_PCB.pdf
Normal file
Binary file not shown.
BIN
KiCad/0004-DenshaBekutoru_v0.2/0004-DenshaBekutoru_v0.2_PCB.png
Normal file
BIN
KiCad/0004-DenshaBekutoru_v0.2/0004-DenshaBekutoru_v0.2_PCB.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 292 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 263 KiB |
@ -1,31 +0,0 @@
|
|||||||
Info: Processing symbol 'J7:Connector_PinSocket_2.54mm:PinSocket_1x04_P2.54mm_Vertical'.
|
|
||||||
Info: Processing symbol 'U2:Package_DIP:DIP-4_W7.62mm'.
|
|
||||||
Info: Processing symbol 'U1:Package_DIP:DIP-4_W7.62mm'.
|
|
||||||
Info: Processing symbol 'RV1:Potentiometer_THT:Potentiometer_Piher_PT-10-V10_Vertical'.
|
|
||||||
Info: Processing symbol 'R9:Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P1.90mm_Vertical'.
|
|
||||||
Info: Processing symbol 'R8:Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P1.90mm_Vertical'.
|
|
||||||
Info: Processing symbol 'R7:Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P1.90mm_Vertical'.
|
|
||||||
Info: Processing symbol 'R6:Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P1.90mm_Vertical'.
|
|
||||||
Info: Processing symbol 'R5:Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P1.90mm_Vertical'.
|
|
||||||
Info: Processing symbol 'R4:Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P5.08mm_Horizontal'.
|
|
||||||
Info: Processing symbol 'R3:Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P5.08mm_Horizontal'.
|
|
||||||
Info: Processing symbol 'R2:Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P5.08mm_Horizontal'.
|
|
||||||
Info: Processing symbol 'R1:Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P5.08mm_Horizontal'.
|
|
||||||
Info: Processing symbol 'J8:Connector_PinHeader_2.54mm:PinHeader_1x02_P2.54mm_Vertical'.
|
|
||||||
Info: Processing symbol 'A1:arduino-library:Arduino_Pro_Mini_Socket_NoSPH_V2'.
|
|
||||||
Info: Processing symbol 'J6:Connector_JST:JST_PH_B3B-PH-K_1x03_P2.00mm_Vertical'.
|
|
||||||
Info: Processing symbol 'J5:Connector_JST:JST_PH_B3B-PH-K_1x03_P2.00mm_Vertical'.
|
|
||||||
Info: Processing symbol 'J4:Connector_PinSocket_2.54mm:PinSocket_1x05_P2.54mm_Vertical'.
|
|
||||||
Info: Processing symbol 'J3:Connector_PinSocket_2.54mm:PinSocket_1x05_P2.54mm_Horizontal'.
|
|
||||||
Info: Processing symbol 'J2:Connector_PinSocket_2.54mm:PinSocket_1x04_P2.54mm_Vertical'.
|
|
||||||
Info: Processing symbol 'J1:Connector_PinHeader_2.54mm:PinHeader_1x04_P2.54mm_Horizontal'.
|
|
||||||
Info: Processing symbol 'D5:LED_THT:LED_D1.8mm_W3.3mm_H2.4mm'.
|
|
||||||
Info: Processing symbol 'D4:LED_THT:LED_D1.8mm_W3.3mm_H2.4mm'.
|
|
||||||
Info: Processing symbol 'D3:Diode_THT:D_DO-41_SOD81_P10.16mm_Horizontal'.
|
|
||||||
Info: Processing symbol 'D2:Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal'.
|
|
||||||
Info: Processing symbol 'D1:Diode_THT:D_DO-35_SOD27_P7.62mm_Horizontal'.
|
|
||||||
Info: Processing symbol 'C5:Capacitor_THT:C_Disc_D3.0mm_W1.6mm_P2.50mm'.
|
|
||||||
Info: Processing symbol 'C4:Capacitor_THT:CP_Axial_L10.0mm_D6.0mm_P15.00mm_Horizontal'.
|
|
||||||
|
|
||||||
|
|
||||||
Info: Total warnings: 0, errors: 0.
|
|
||||||
96
README.md
96
README.md
@ -1,12 +1,90 @@
|
|||||||
# DenshaBekutoru - Model Train Direction Sensor
|
# 電車ベクトル (DenshaBekutoru)
|
||||||
|
|
||||||
Get **direction** and **speed** from motor power signals.
|
## Model Train Direction Sensor
|
||||||
Target use case: **model trains**.
|
|
||||||
|
|
||||||
- Detects polarity (+/–) to identify train direction
|
DenshaBekutoru is a small controller board for brick-built model locomotives.
|
||||||
- Measures pulse width to calculate speed (% of maximum)
|
|
||||||
- Implemented with optocouplers and a state machine
|
|
||||||
- As small as possible, but I hope no SMD (beginner friendly)
|
|
||||||
|
|
||||||
Project is in an early stage. Currently running tests on target hardware.
|
The target use case is: read the motor power signals, detect the current driving direction, and switch the headlights accordingly. The software is also prepared to derive speed information from the motor signal behaviour.
|
||||||
More information and documentation will follow.
|
|
||||||
|
This project is built around one practical problem: the motor is driven from an H-bridge, so the signal is noisy, polarity changes are not “clean logic”, and inductive spikes make direct evaluation difficult.
|
||||||
|
|
||||||
|
## What it does
|
||||||
|
|
||||||
|
- detects train direction from the motor power signal
|
||||||
|
- evaluates two processed motor-side signals via analogue inputs
|
||||||
|
- switches the front / rear lights according to direction
|
||||||
|
- keeps the last valid direction if the train stops or the signal becomes unclear
|
||||||
|
- is designed as small as possible for installation in brick-built locomotives
|
||||||
|
|
||||||
|
## Technical approach
|
||||||
|
|
||||||
|
The current version is built around:
|
||||||
|
|
||||||
|
- optocoupler-based input isolation and signal conditioning
|
||||||
|
- Arduino Pro Mini 5V as controller
|
||||||
|
- software averaging of analogue inputs
|
||||||
|
- startup calibration to adapt to different controllers and builds
|
||||||
|
- threshold + hysteresis logic
|
||||||
|
- simple state machine with direction memory
|
||||||
|
- PWM-capable output pins for possible later LED dimming
|
||||||
|
|
||||||
|
The main idea is not to read one raw signal and react immediately.
|
||||||
|
The idea is to turn a noisy motor signal into a stable direction decision.
|
||||||
|
|
||||||
|
## Current status
|
||||||
|
|
||||||
|
**Version 2 (beta) is built and working.**
|
||||||
|
|
||||||
|
Current state:
|
||||||
|
|
||||||
|
- [x] schematic finished
|
||||||
|
- [x] PCB finished
|
||||||
|
- [x] firmware finished for the current beta state
|
||||||
|
- [x] three PCBs built and tested
|
||||||
|
- [x] first boards handed over for real-life testing in a model railway club
|
||||||
|
- [ ] Feedback and what to improve
|
||||||
|
|
||||||
|
## Design goals
|
||||||
|
|
||||||
|
- as small as possible
|
||||||
|
- beginner-friendly where possible
|
||||||
|
- no SMD if it can reasonably be avoided
|
||||||
|
- easy to reproduce later as a DIY kit
|
||||||
|
- modular PCB concept with main section, future-option section, and test section
|
||||||
|
|
||||||
|
## Repository content
|
||||||
|
|
||||||
|
Typical content of this repository:
|
||||||
|
|
||||||
|
- `KiCad/` – schematic and PCB files
|
||||||
|
- `firmware/` – Arduino test and controller software
|
||||||
|
- documentation and pictures will be added step by step
|
||||||
|
|
||||||
|
## Project status note
|
||||||
|
|
||||||
|
This is still a beta project.
|
||||||
|
|
||||||
|
The current hardware and software already work, but testing on real locomotives is still ongoing.
|
||||||
|
The next version will depend on real-life feedback from actual use.
|
||||||
|
|
||||||
|
Possible next steps:
|
||||||
|
|
||||||
|
- verify behaviour with different motor controllers
|
||||||
|
- check robustness in real train builds
|
||||||
|
- improve wiring / connector handling
|
||||||
|
- finalise optional features like LED dimming
|
||||||
|
- prepare a first “official” DIY kit version
|
||||||
|
|
||||||
|
## Blog / documentation
|
||||||
|
|
||||||
|
- Project overview: https://togo-lab.io/?p=223
|
||||||
|
- Hardware description: https://togo-lab.io/?p=233
|
||||||
|
- Software description: https://togo-lab.io/?p=243
|
||||||
|
|
||||||
|
## Short summary
|
||||||
|
|
||||||
|
DenshaBekutoru is a small Arduino-based direction sensor for brick-built model trains.
|
||||||
|
|
||||||
|
It reads the noisy motor signal from an H-bridge-driven setup, isolates and evaluates it, and switches the headlights automatically.
|
||||||
|
|
||||||
|
The current beta version is working and now entering real-life testing.
|
||||||
@ -0,0 +1,287 @@
|
|||||||
|
/*
|
||||||
|
0004_DenshaBekutoru – 1st Version PCB
|
||||||
|
|
||||||
|
PCB Version : 2026/02 (Order F016895)
|
||||||
|
Target dev board : Arduino Pro Mini 5V / 16 MHz (ATmega328P)
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
State machine (direction memory) + Hysteresis (Version A)
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
We use two thresholds:
|
||||||
|
T_hold (smaller): below -> treat as neutral and HOLD state
|
||||||
|
T_enter (larger) : above -> allow direction change (set by sign)
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
If |diff| <= T_hold : hold direction
|
||||||
|
If |diff| >= T_enter : set direction by sign
|
||||||
|
Else (between) : hold direction
|
||||||
|
|
||||||
|
Presets (implemented as multipliers of the calibrated VdiffThreshold):
|
||||||
|
T_hold = 1.0 * VdiffThreshold
|
||||||
|
T_enter = 2.0 * VdiffThreshold
|
||||||
|
|
||||||
|
Inputs derived from v1, v2: diff = v1 - v2
|
||||||
|
*/
|
||||||
|
|
||||||
|
const unsigned long SAMPLE_WINDOW_MS = 100; // averaging window per measurement
|
||||||
|
const unsigned long SAMPLE_DELAY_US = 500; // delay between ADC samples (~2 kHz)
|
||||||
|
|
||||||
|
const uint8_t ADC_PIN_1 = A0; // Pro Mini A0 -> (PCB dependend!)
|
||||||
|
const uint8_t ADC_PIN_2 = A1; // Pro Mini A1 -> (PCB dependend")
|
||||||
|
|
||||||
|
// Direction LEDs (avoid D0/D1 because you may want RX/TX later)
|
||||||
|
const uint8_t LED_DIR1_PIN = 3; // D3
|
||||||
|
const uint8_t LED_DIR2_PIN = 9; // D9
|
||||||
|
|
||||||
|
const unsigned int LED_BLINK_ON_MS = 150;
|
||||||
|
const unsigned int LED_BLINK_OFF_MS = 150;
|
||||||
|
|
||||||
|
// Serial output control (0 = no output, 1 = output)
|
||||||
|
bool SerialOutputAllow = true;
|
||||||
|
|
||||||
|
// ---- Calibration parameters ----
|
||||||
|
const uint16_t AverageRepeat = 100; // number of init measurements
|
||||||
|
const float VdiffThresholdMargin = 1.50f; // multiplier (e.g., 1.5 = +50% margin)
|
||||||
|
const float VdiffThresholdMinVolts = 0.03f; // floor in volts
|
||||||
|
|
||||||
|
// ---- Hysteresis presets (multipliers of VdiffThreshold) ----
|
||||||
|
const float THOLD_MULT = 1.0f; // T_hold = THOLD_MULT * VdiffThreshold
|
||||||
|
const float TENTER_MULT = 2.0f; // T_enter = TENTER_MULT * VdiffThreshold
|
||||||
|
|
||||||
|
// Globals: latest measured averaged voltages
|
||||||
|
float v1 = 0.0f;
|
||||||
|
float v2 = 0.0f;
|
||||||
|
|
||||||
|
// Calibration globals
|
||||||
|
float VdiffBaseline = 0.0f; // median(|V1-V2|) measured at boot (no movement)
|
||||||
|
float VdiffThreshold = 0.0f; // calibrated base threshold (used to derive T_hold/T_enter)
|
||||||
|
|
||||||
|
// Hysteresis thresholds (derived once after calibration)
|
||||||
|
float T_hold = 0.0f;
|
||||||
|
float T_enter = 0.0f;
|
||||||
|
|
||||||
|
// Direction encoding:
|
||||||
|
// 0 = NONE, 2 = DIR1, 3 = DIR2
|
||||||
|
byte direction = 0;
|
||||||
|
|
||||||
|
static inline float absf(float x) { return (x >= 0.0f) ? x : -x; }
|
||||||
|
static inline float maxf(float a, float b) { return (a > b) ? a : b; }
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// LED helpers
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
static void blinkLED(uint8_t pin, uint8_t times)
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0; i < times; i++) {
|
||||||
|
digitalWrite(pin, HIGH);
|
||||||
|
delay(LED_BLINK_ON_MS);
|
||||||
|
digitalWrite(pin, LOW);
|
||||||
|
delay(LED_BLINK_OFF_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initBlinkSequence()
|
||||||
|
{
|
||||||
|
// LED at Output 2 blinks 2 times
|
||||||
|
blinkLED(LED_DIR1_PIN, 2);
|
||||||
|
|
||||||
|
// LED at Output 3 blinks 3 times
|
||||||
|
blinkLED(LED_DIR2_PIN, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void applyDirectionOutputs()
|
||||||
|
{
|
||||||
|
digitalWrite(LED_DIR1_PIN, LOW);
|
||||||
|
digitalWrite(LED_DIR2_PIN, LOW);
|
||||||
|
|
||||||
|
if (direction == 2) {
|
||||||
|
digitalWrite(LED_DIR1_PIN, HIGH);
|
||||||
|
} else if (direction == 3) {
|
||||||
|
digitalWrite(LED_DIR2_PIN, HIGH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Measurement
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
static void measureAveragedVoltages()
|
||||||
|
{
|
||||||
|
unsigned long startTime = millis();
|
||||||
|
|
||||||
|
unsigned long sum1 = 0;
|
||||||
|
unsigned long sum2 = 0;
|
||||||
|
unsigned long samples = 0;
|
||||||
|
|
||||||
|
while (millis() - startTime < SAMPLE_WINDOW_MS) {
|
||||||
|
sum1 += analogRead(ADC_PIN_1);
|
||||||
|
sum2 += analogRead(ADC_PIN_2);
|
||||||
|
samples++;
|
||||||
|
delayMicroseconds(SAMPLE_DELAY_US);
|
||||||
|
}
|
||||||
|
|
||||||
|
float avg1 = (float)sum1 / samples;
|
||||||
|
float avg2 = (float)sum2 / samples;
|
||||||
|
|
||||||
|
// Convert ADC value to voltage (default analog reference = Vcc ~ 5V)
|
||||||
|
v1 = avg1 * (5.0f / 1023.0f);
|
||||||
|
v2 = avg2 * (5.0f / 1023.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Median helpers (for calibration)
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
static void sortFloatArray(float *a, uint16_t n)
|
||||||
|
{
|
||||||
|
// Insertion sort (n=100 is small, OK)
|
||||||
|
for (uint16_t i = 1; i < n; i++) {
|
||||||
|
float key = a[i];
|
||||||
|
int16_t j = (int16_t)i - 1;
|
||||||
|
while (j >= 0 && a[j] > key) {
|
||||||
|
a[j + 1] = a[j];
|
||||||
|
j--;
|
||||||
|
}
|
||||||
|
a[j + 1] = key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static float medianOfSortedFloatArray(const float *a, uint16_t n)
|
||||||
|
{
|
||||||
|
if (n == 0) return 0.0f;
|
||||||
|
if (n & 1) {
|
||||||
|
return a[n / 2];
|
||||||
|
} else {
|
||||||
|
return (a[(n / 2) - 1] + a[n / 2]) * 0.5f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calibrate baseline + VdiffThreshold once at boot/reset
|
||||||
|
static void calibrateVdiffThreshold(uint16_t averageRepeat)
|
||||||
|
{
|
||||||
|
if (averageRepeat < 1) averageRepeat = 1;
|
||||||
|
if (averageRepeat > 200) averageRepeat = 200; // RAM safety cap
|
||||||
|
|
||||||
|
float diffs[200];
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < averageRepeat; i++) {
|
||||||
|
measureAveragedVoltages();
|
||||||
|
diffs[i] = absf(v1 - v2); // baseline mismatch sample
|
||||||
|
}
|
||||||
|
|
||||||
|
sortFloatArray(diffs, averageRepeat);
|
||||||
|
VdiffBaseline = medianOfSortedFloatArray(diffs, averageRepeat);
|
||||||
|
|
||||||
|
// Calibrated base threshold with margin + floor
|
||||||
|
VdiffThreshold = maxf(VdiffBaseline * VdiffThresholdMargin, VdiffThresholdMinVolts);
|
||||||
|
|
||||||
|
// Derive hysteresis thresholds (Version A)
|
||||||
|
T_hold = THOLD_MULT * VdiffThreshold;
|
||||||
|
T_enter = TENTER_MULT * VdiffThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// State machine with hysteresis (Version A)
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
static void updateDirectionFromVoltages()
|
||||||
|
{
|
||||||
|
const float diff = v1 - v2;
|
||||||
|
const float absDiff = absf(diff);
|
||||||
|
|
||||||
|
// 1) Neutral region: HOLD
|
||||||
|
if (absDiff <= T_hold) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Strong region: allow direction change
|
||||||
|
if (absDiff >= T_enter) {
|
||||||
|
direction = (diff > 0.0f) ? (byte)2 : (byte)3;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) Deadband between T_hold and T_enter: HOLD
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Serial output
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
static void serialPrintAll()
|
||||||
|
{
|
||||||
|
if (!SerialOutputAllow) return;
|
||||||
|
|
||||||
|
Serial.print("A2 for PB3 XTAL1, Pin2: ");
|
||||||
|
Serial.print(v1, 3);
|
||||||
|
Serial.print(" V | ");
|
||||||
|
|
||||||
|
Serial.print("A3 for PB4 XTAL2, Pin3: ");
|
||||||
|
Serial.print(v2, 3);
|
||||||
|
Serial.print(" V | ");
|
||||||
|
|
||||||
|
Serial.print("|V1-V2|: ");
|
||||||
|
Serial.print(absf(v1 - v2), 3);
|
||||||
|
Serial.print(" V | ");
|
||||||
|
|
||||||
|
Serial.print("VdiffBaseline: ");
|
||||||
|
Serial.print(VdiffBaseline, 3);
|
||||||
|
Serial.print(" V | ");
|
||||||
|
|
||||||
|
Serial.print("VdiffThreshold: ");
|
||||||
|
Serial.print(VdiffThreshold, 3);
|
||||||
|
Serial.print(" V | ");
|
||||||
|
|
||||||
|
Serial.print("T_hold: ");
|
||||||
|
Serial.print(T_hold, 3);
|
||||||
|
Serial.print(" V | ");
|
||||||
|
|
||||||
|
Serial.print("T_enter: ");
|
||||||
|
Serial.print(T_enter, 3);
|
||||||
|
Serial.print(" V | ");
|
||||||
|
|
||||||
|
Serial.print("direction: ");
|
||||||
|
Serial.println(direction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Arduino entry points
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
pinMode(ADC_PIN_1, INPUT);
|
||||||
|
pinMode(ADC_PIN_2, INPUT);
|
||||||
|
|
||||||
|
pinMode(LED_DIR1_PIN, OUTPUT);
|
||||||
|
pinMode(LED_DIR2_PIN, OUTPUT);
|
||||||
|
|
||||||
|
// Initial calibration (assumes no movement)
|
||||||
|
calibrateVdiffThreshold(AverageRepeat);
|
||||||
|
|
||||||
|
// Init blink sequence: 2x on D2, 3x on D3
|
||||||
|
initBlinkSequence();
|
||||||
|
|
||||||
|
// One measurement for initial display + initial direction
|
||||||
|
measureAveragedVoltages();
|
||||||
|
updateDirectionFromVoltages();
|
||||||
|
applyDirectionOutputs();
|
||||||
|
|
||||||
|
if (SerialOutputAllow) {
|
||||||
|
Serial.println("=== DenshaBekutoru Optocoupler Average Test (Arduino Pro Mini 5V/16MHz) ===");
|
||||||
|
Serial.print("AverageRepeat: ");
|
||||||
|
Serial.println(AverageRepeat);
|
||||||
|
Serial.print("THOLD_MULT: ");
|
||||||
|
Serial.print(THOLD_MULT, 2);
|
||||||
|
Serial.print(" TENTER_MULT: ");
|
||||||
|
Serial.println(TENTER_MULT, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
serialPrintAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
measureAveragedVoltages();
|
||||||
|
updateDirectionFromVoltages();
|
||||||
|
applyDirectionOutputs();
|
||||||
|
|
||||||
|
serialPrintAll();
|
||||||
|
|
||||||
|
delay(300);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user