12 Commits

48 changed files with 139785 additions and 0 deletions

View File

@ -0,0 +1,39 @@
*
.subckt 0004-DenshaBekutoru
.model __D2 D
.model __D1 D
R3 Net-_D10-A_ VCC 220
D10 __D10
C5 VCC GND 100n
U4 __U4
C4 VCC GND 4.7u
U3 __U3
R4 Net-_D11-A_ VCC 220
D11 __D11
R5 Net-_U3-_RESET/PB5_ VCC 10k
R6 Net-_D4-A_ Net-_D6-K_ 220
D6 __D6
D5 __D5
R7 Net-_D6-A_ Net-_D4-K_ 220
D4 __D4
C3 Net-_D3-K_ GND 100n
U1 __U1
C2 Net-_D3-K_ GND 47u
D3 __D3
U2 __U2
D2 Net-_D2-A_ Net-_D2-K_ __D2
C1 Net-_U3-_RESET/PB5_ GND 100n
SW1 __SW1
R8 Net-_D8-A_ Net-_D5-K_ 220
D7 __D7
D8 __D8
D9 __D9
R1 Net-_D2-A_ Net-_D1-K_ 1.8k
R2 Net-_D1-A_ Net-_D2-K_ 1.8k
D1 Net-_D1-A_ Net-_D1-K_ __D1
J1 __J1
.ends

View File

@ -0,0 +1,83 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "",
"auto_track_width": true,
"hidden_netclasses": [],
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"images": 0.6,
"pads": 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": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
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": "fffffff_ffffffff",
"zone_display_mode": 0
},
"git": {
"repo_password": "",
"repo_type": "",
"repo_username": "",
"ssh_key": ""
},
"meta": {
"filename": "0004-DenshaBekutoru_v0.1.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View File

@ -0,0 +1,392 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {},
"diff_pair_dimensions": [],
"drc_exclusions": [],
"rules": {},
"track_widths": [],
"via_dimensions": []
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"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",
"conflicting_netclasses": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "warning",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "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": "error",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"simulation_model_issue": "ignore",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "0004-DenshaBekutoru_v0.1.kicad_pro",
"version": 1
},
"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)",
"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": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "",
"pos_files": "",
"specctra_dsn": "",
"step": "",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"bom_export_filename": "",
"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": false,
"label": "Datasheet",
"name": "Datasheet",
"show": true
},
{
"group_by": false,
"label": "Footprint",
"name": "Footprint",
"show": true
},
{
"group_by": false,
"label": "Qty",
"name": "${QUANTITY}",
"show": true
},
{
"group_by": true,
"label": "DNP",
"name": "${DNP}",
"show": true
}
],
"filter_string": "",
"group_symbols": true,
"name": "Grouped By Value",
"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": "Spice Model",
"page_layout_descr_file": "",
"plot_directory": "/home/tgohle/Desktop/git/ToGo-Lab/0004-DenshaBekutoru/KiCad/0004-DenshaBekutoru_v0.1/",
"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": [
[
"f227a2cd-5cbd-41a5-87f8-a5c1515170aa",
"Root"
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,39 @@
*
.subckt 0004-DenshaBekutoru
.model __D2 D
.model __D1 D
R3 Net-_D10-A_ VCC 220
D10 __D10
C5 VCC GND 100n
U4 __U4
C4 VCC GND 4.7u
U3 __U3
R4 Net-_D11-A_ VCC 220
D11 __D11
R5 Net-_U3-_RESET/PB5_ VCC 10k
R6 Net-_D4-A_ Net-_D6-K_ 220
D6 __D6
D5 __D5
R7 Net-_D6-A_ Net-_D4-K_ 220
D4 __D4
C3 Net-_D3-K_ GND 100n
U1 __U1
C2 Net-_D3-K_ GND 47u
D3 __D3
U2 __U2
D2 Net-_D2-A_ Net-_D2-K_ __D2
C1 Net-_U3-_RESET/PB5_ GND 100n
SW1 __SW1
R8 Net-_D8-A_ Net-_D5-K_ 220
D7 __D7
D8 __D8
D9 __D9
R1 Net-_D2-A_ Net-_D1-K_ 1.8k
R2 Net-_D1-A_ Net-_D2-K_ 1.8k
D1 Net-_D1-A_ Net-_D1-K_ __D1
J1 __J1
.ends

View File

@ -0,0 +1,32 @@
ERC report (2026-01-25T14:36:13+0100, Encoding UTF8)
***** Sheet /
[pin_not_connected]: Pin not connected
; error (excluded)
@(10000.00 mils, 3950.00 mils): Symbol D7 Pin 1 [K, Passive, Line]
[pin_not_connected]: Pin not connected
; error (excluded)
@(10000.00 mils, 3650.00 mils): Symbol D7 Pin 2 [A, Passive, Line]
[pin_not_connected]: Pin not connected
; error (excluded)
@(9500.00 mils, 3950.00 mils): Symbol D6 Pin 1 [K, Passive, Line]
[pin_not_connected]: Pin not connected
; error (excluded)
@(9500.00 mils, 3650.00 mils): Symbol D6 Pin 2 [A, Passive, Line]
[power_pin_not_driven]: Input Power pin not driven by any Output Power pins
; error (excluded)
@(5650.00 mils, 3350.00 mils): Symbol A1 Pin Vcc1 [Vcc, Power input, Line]
[pin_not_connected]: Pin not connected
; error (excluded)
@(8500.00 mils, 3950.00 mils): Symbol D4 Pin 1 [K, Passive, Line]
[pin_not_connected]: Pin not connected
; error (excluded)
@(8500.00 mils, 3650.00 mils): Symbol D4 Pin 2 [A, Passive, Line]
[pin_not_connected]: Pin not connected
; error (excluded)
@(9000.00 mils, 3950.00 mils): Symbol D5 Pin 1 [K, Passive, Line]
[pin_not_connected]: Pin not connected
; error (excluded)
@(9000.00 mils, 3650.00 mils): Symbol D5 Pin 2 [A, Passive, Line]
** ERC messages: 9 Errors 9 Warnings 0

View File

@ -0,0 +1,83 @@
{
"board": {
"active_layer": 0,
"active_layer_preset": "",
"auto_track_width": true,
"hidden_netclasses": [],
"hidden_nets": [],
"high_contrast_mode": 0,
"net_color_mode": 1,
"opacity": {
"images": 0.6,
"pads": 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": [
0,
1,
2,
3,
4,
5,
8,
9,
10,
11,
12,
13,
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": "fffffff_ffffffff",
"zone_display_mode": 0
},
"git": {
"repo_password": "",
"repo_type": "",
"repo_username": "",
"ssh_key": ""
},
"meta": {
"filename": "0004-DenshaBekutoru_v0.2.kicad_prl",
"version": 3
},
"project": {
"files": []
}
}

View File

@ -0,0 +1,402 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {},
"diff_pair_dimensions": [],
"drc_exclusions": [],
"rules": {},
"track_widths": [],
"via_dimensions": []
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [
"pin_not_connected|2159000|1003300|75d7e973-8e06-4017-adef-8a7540fd15a0|00000000-0000-0000-0000-000000000000|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|",
"pin_not_connected|2159000|927100|b8d4dc81-b5c9-4b93-9376-0a9b9fc45175|00000000-0000-0000-0000-000000000000|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|",
"pin_not_connected|2286000|1003300|708ddeaa-1814-44d3-ae53-df03e7136210|00000000-0000-0000-0000-000000000000|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|",
"pin_not_connected|2286000|927100|e0f17062-911b-4fb8-9627-be8ce017775c|00000000-0000-0000-0000-000000000000|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|",
"pin_not_connected|2413000|1003300|c87497e0-f1a5-4cac-8154-452d26879be6|00000000-0000-0000-0000-000000000000|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|",
"pin_not_connected|2413000|927100|8209804a-7539-4743-bfca-aff943649ca9|00000000-0000-0000-0000-000000000000|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|",
"pin_not_connected|2540000|1003300|6d0ce029-b541-49e3-83e1-74431b2de240|00000000-0000-0000-0000-000000000000|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|",
"pin_not_connected|2540000|927100|252bd632-84ad-409c-ab54-696d48f55782|00000000-0000-0000-0000-000000000000|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|",
"power_pin_not_driven|1435100|850900|c21116e5-546b-4c55-ac12-ee16de044258|00000000-0000-0000-0000-000000000000|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|/f227a2cd-5cbd-41a5-87f8-a5c1515170aa|"
],
"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",
"conflicting_netclasses": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "warning",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "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": "error",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"simulation_model_issue": "ignore",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "0004-DenshaBekutoru_v0.2.kicad_pro",
"version": 1
},
"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)",
"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": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "",
"pos_files": "",
"specctra_dsn": "",
"step": "",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"bom_export_filename": "",
"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": false,
"label": "Datasheet",
"name": "Datasheet",
"show": true
},
{
"group_by": false,
"label": "Footprint",
"name": "Footprint",
"show": true
},
{
"group_by": false,
"label": "Qty",
"name": "${QUANTITY}",
"show": true
},
{
"group_by": true,
"label": "DNP",
"name": "${DNP}",
"show": true
}
],
"filter_string": "",
"group_symbols": true,
"name": "Grouped By Value",
"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": "Spice Model",
"page_layout_descr_file": "",
"plot_directory": "/home/tgohle/Desktop/git/ToGo-Lab/0004-DenshaBekutoru/KiCad/0004-DenshaBekutoru_v0.2/",
"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": [
[
"f227a2cd-5cbd-41a5-87f8-a5c1515170aa",
"Root"
]
],
"text_variables": {}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

View File

@ -0,0 +1,108 @@
# [DIY Kit Name] — Build Guide
**Version:** [v1.0]
**Date:** [YYYY-MM-DD]
**Author:** [Name / Contact]
---
## 1. Introduction
- What this kit does (short description).
- Skill level required (Beginner / Intermediate / Advanced).
- Estimated build time: [X hours].
- Tools required: [Soldering iron, multimeter, etc.].
---
## 2. Circuit Description
### 2.1 General Idea
- Short explanation of the concept.
- Example: *The kit demonstrates low-power control using an ATtiny85 microcontroller. It blinks an LED in Morse code and sleeps when ambient light is detected.*
### 2.2 Annotated Schematic
*(Insert schematic image exported from KiCad, e.g., as PNG or PDF)*
Use numbered blocks for explanation. Example:
**Figure 1: Schematic with annotation numbers**
| Block | Circuit Section | Description |
|:-----:|:------------------|:------------------------------------------------------------------------------------------------------|
| 1 | Power Supply | 2×AA batteries → DC/DC regulator (U1) → 5 V rail. Decoupling capacitors (C1, C2) smooth the voltage. |
| 2 | Controller | ATtiny85 (U2) running firmware. Pull-up resistors (R1, R2) ensure stable inputs. |
| 3 | LED Output | LED D1 driven by PB0. Current limited by R3 (330 Ω). |
| 4 | Light Sensor | LED D2 reverse biased → generates photocurrent. Read on PB2. |
| 5 | Programming Header| ISP 6-pin header for flashing firmware. |
| 6 | Test Points | Labeled pads J1J3 for debugging with a multimeter. |
*(Link to the KiCad schematic file in Git repo, e.g.: [GitHub/Gitea link])*
### 2.3 Functional Flow
- Add a block diagram showing logic signal flow (KiCad → export block diagram or draw in Mermaid).
- Example: *Battery → DC/DC → ATtiny85 → LED driver → LED.*
---
## 3. Mechanical Parts
### 3.1 2D CAD Files
- Mechanical drawings in DXF for front panel / housing.
- Dimensions, hole positions, and cut-outs for connectors.
### 3.2 3D Models
- STL/STEP files for 3D printing, if available.
- Assembly orientation, support recommendations.
*(Link to repo with mechanical CAD files.)*
---
## 4. Kit Contents
*(BOM table)*
---
## 5. Safety Notes
⚠️ Soldering involves heat. Work on a non-flammable surface.
⚠️ Observe polarity on diodes, electrolytic capacitors, and ICs.
---
## 6. Assembly Instructions
*(step-by-step with images/photos)*
---
## 7. First Power-Up
*(preconditions + test steps)*
---
## 8. Adjustments / Calibration
*(potentiometer trim, jumper setting, firmware config)*
---
## 9. Troubleshooting
*(table with symptoms and remedies)*
---
## 10. Next Steps / Modifications
*(extensions, software mods, hardware mods)*
---
## 11. Resources
- **Git Repository:** [link]
- **KiCad Project Files:** [link]
- **DXF Mechanical Files:** [link]
- **STL/3D Models:** [link]
- **Firmware Source Code:** [link]
- **Datasheets:** [links]
---
## 12. Document Control
| Version | Date | Author | Changes |
|:-------:|:----------:|:-----------|:------------------------------------------|
| 1.0 | YYYY-MM-DD | [Name] | Initial release |

View File

@ -0,0 +1,108 @@
# [Project Name] — Technical Manual
**Device:** [Device Name]
**Version:** [Document Version]
**Date:** [YYYY-MM-DD]
**Author:** [Name / Contact]
**Reviewed by:** [Reviewer]
---
## 1. Purpose and Scope
- **Purpose:** Short description of what the device does.
- **Scope:** Define the application area.
- **Target Audience:** Who should use this manual (e.g., service technicians, engineers).
- **Limitations:** What is not covered or not allowed.
---
## 2. Safety Information
⚠️ **Read before use!**
### 2.1 General Safety
- Only trained personnel may operate the device.
- Follow standard ESD and laboratory safety rules.
### 2.2 Electrical Safety
- Max. internal voltage: [X V].
- Use only insulated test leads and approved measurement devices.
### 2.3 Residual Risks
- [List possible hazards in failure scenarios.]
---
## 3. Device Overview
### 3.1 Description
Short text describing device and functionality.
### 3.2 Front Panel Elements
| ID | Name | Function |
|:-----:|:------------------|:--------------------------|
| SW1 | Channel Switch 1 | Activates channel 1 |
| LED1 | Status LED | Indicates request active |
| J1.1 | Connector | Test input/output |
### 3.3 Block Diagram
*(Insert diagram or schematic here)*
---
## 4. Intended Use
- The device is designed only for [specific purpose].
- Any other use is not permitted and voids responsibility of manufacturer.
---
## 5. Setup and Operation
### 5.1 Preconditions
- Batteries charged.
- All switches OFF.
### 5.2 Step-by-Step Procedure
| Step | Action | Expected Result | Remarks |
|:-----:|:----------------------------------|:----------------------|:--------------------------|
| 1 | Switch ON | LED lights green | — |
| 2 | Connect test cable J1.0 red/black | Channel LED active | — |
| 3 | Trigger tool GUI request | LED1 ON | Only one channel active |
*(Add additional steps as needed)*
---
## 6. Maintenance and Troubleshooting
### 6.1 Maintenance
- Replace fuse [specification].
- Replace batteries [specification].
### 6.2 Troubleshooting
| Symptom | Possible Cause | Remedy |
|:--------------------------|:------------------|:----------------------------------|
| No LED response | Battery empty | Replace batteries |
| Incorrect channel active | Miswiring | Check tool GUI configuration |
---
## 7. Technical Data
| Parameter | Value |
|:------------------|:------------------|
| Supply Voltage | [X V] |
| Fuse | [specification] |
| Battery | [type] |
| Max. current | [value] |
| Dimensions | [mm] |
| Weight | [g] |
---
## 8. References and Resources
- CAD files: [Link]
- Schematics: [Link]
- Git repository: [Link]
---
## 9. Document Control
| Version | Date | Author | Changes |
|:-------:|:----------:|:-----------|:------------------------------------------|
| 1.0 | YYYY-MM-DD | [Name] | Initial release |

View File

@ -0,0 +1,217 @@
/*
0004_DenshaBekutoru Optocoupler Averaging Test
Target dev board (later): Arduino Pro Mini 5V / 16 MHz (ATmega328P)
Measures average voltage on:
- A2 -> later ATtiny85 PB3 (XTAL1, Pin 2)
- A3 -> later ATtiny85 PB4 (XTAL2, Pin 3)
Boot calibration:
- assumes "no movement" at startup
- measures V1/V2 AverageRepeat times
- computes di = |V1 - V2| each time
- VdiffBaseline = median(di)
- VdiffThreshold = max(VdiffBaseline * VdiffThresholdMargin, VdiffThresholdMinVolts)
*/
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 = A2; // Pro Mini A2 -> later ATtiny85 PB3 (XTAL1, Pin 2)
const uint8_t ADC_PIN_2 = A3; // Pro Mini A3 -> later ATtiny85 PB4 (XTAL2, Pin 3)
// LEDs for direction indication (avoid D0/D1)
const uint8_t LED_DIR1_PIN = 2; // D2
const uint8_t LED_DIR2_PIN = 3; // D3
// 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 (optional but practical)
// 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; // final threshold used for direction decision
// Direction encoding requirement:
// 0 = no direction
// 2 = direction 1 (maps to LED pin D2)
// 3 = direction 2 (maps to LED pin D3)
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; }
static void applyDirectionOutputs()
{
digitalWrite(LED_DIR1_PIN, LOW);
digitalWrite(LED_DIR2_PIN, LOW);
if (direction == LED_DIR1_PIN) {
digitalWrite(LED_DIR1_PIN, HIGH);
} else if (direction == LED_DIR2_PIN) {
digitalWrite(LED_DIR2_PIN, HIGH);
}
}
// Measure averaged voltages (updates globals v1/v2)
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);
}
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 + threshold once at boot/reset
// Parameter must be only AverageRepeat (per your requirement).
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);
// Final threshold with margin + floor
VdiffThreshold = maxf(VdiffBaseline * VdiffThresholdMargin, VdiffThresholdMinVolts);
}
static void updateDirectionFromVoltages()
{
float diff = v1 - v2;
float absDiff = absf(diff);
if (absDiff <= VdiffThreshold) {
direction = 0;
} else {
// Mapping choice:
// v1 lower than v2 -> direction 1 (D2)
// v2 lower than v1 -> direction 2 (D3)
direction = (diff < 0.0f) ? LED_DIR1_PIN : LED_DIR2_PIN;
}
}
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("VdiffThresholdMargin: ");
Serial.print(VdiffThresholdMargin, 2);
Serial.print(" x | ");
Serial.print("VdiffThresholdMinVolts: ");
Serial.print(VdiffThresholdMinVolts, 3);
Serial.print(" V | ");
Serial.print("VdiffThreshold: ");
Serial.print(VdiffThreshold, 3);
Serial.print(" V | ");
Serial.print("direction: ");
Serial.println(direction);
}
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);
calibrateVdiffThreshold(AverageRepeat);
// One measurement for initial output + outputs
measureAveragedVoltages();
updateDirectionFromVoltages();
applyDirectionOutputs();
if (SerialOutputAllow) {
Serial.println("=== DenshaBekutoru Optocoupler Average Test (Arduino Pro Mini 5V/16MHz) ===");
Serial.print("AverageRepeat: ");
Serial.println(AverageRepeat);
}
serialPrintAll();
}
void loop() {
measureAveragedVoltages();
updateDirectionFromVoltages();
applyDirectionOutputs();
serialPrintAll();
delay(300);
}

View File

@ -0,0 +1,58 @@
/*
0004_DenshaBekutoru ? Optocoupler Averaging Test (UNO)
Measures average voltage on:
- A2 -> later ATtiny85 PB3 (XTAL1, Pin 2)
- A3 -> later ATtiny85 PB4 (XTAL2, Pin 3)
Integration window is configurable via SAMPLE_WINDOW_MS.
by tgohle, last edit 20260111
*/
const unsigned long SAMPLE_WINDOW_MS = 100; // change here
const unsigned long SAMPLE_DELAY_US = 500; // delay between ADC samples
const uint8_t ADC_PIN_1 = A2; // UNO A2 -> later ATtiny85 PB3 (XTAL1, Pin 2)
const uint8_t ADC_PIN_2 = A3; // UNO A3 -> later ATtiny85 PB4 (XTAL2, Pin 3)
void setup() {
Serial.begin(115200);
pinMode(ADC_PIN_1, INPUT);
pinMode(ADC_PIN_2, INPUT);
Serial.println("=== DenshaBekutoru Optocoupler Average Test ===");
}
void loop() {
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;
float v1 = avg1 * (5.0 / 1023.0);
float v2 = avg2 * (5.0 / 1023.0);
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.println(" V");
delay(300);
}

View File

@ -0,0 +1,292 @@
/*
0004_DenshaBekutoru Version 0.1 Test
Target dev board (later): Arduino Pro Mini 5V / 16 MHz (ATmega328P)
----------------------------------------------------------------------------
State machine (direction memory)
----------------------------------------------------------------------------
Inputs derived from v1, v2, VdiffThreshold:
N (Neutral): |v1 - v2| <= VdiffThreshold
D1 (v1>>v2): (v1 - v2) > VdiffThreshold
D2 (v2>>v1): (v2 - v1) > VdiffThreshold
State encoding:
0 = NONE
2 = DIR1
3 = DIR2
Transition table:
Current \ Input | N (neutral) | D1 (v1>>v2) | D2 (v2>>v1)
-----------------------------------------------------------------
0 (NONE) | 0 | 2 | 3
2 (DIR1) | 2 | 2 | 3
3 (DIR2) | 3 | 2 | 3
Mermaid (documentation)
-----------------------
stateDiagram-v2
[*] --> NONE
state "0 : NONE" as NONE
state "2 : DIR1 (v1>>v2)" as DIR1
state "3 : DIR2 (v2>>v1)" as DIR2
NONE --> NONE : |v1 - v2| <= T
NONE --> DIR1 : v1 - v2 > T
NONE --> DIR2 : v2 - v1 > T
DIR1 --> DIR1 : |v1 - v2| <= T
DIR1 --> DIR1 : v1 - v2 > T
DIR1 --> DIR2 : v2 - v1 > T
DIR2 --> DIR2 : |v1 - v2| <= T
DIR2 --> DIR2 : v2 - v1 > T
DIR2 --> DIR1 : v1 - v2 > T
*/
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 = A2; // Pro Mini A2 -> later ATtiny85 PB3 (XTAL1, Pin 2)
const uint8_t ADC_PIN_2 = A3; // Pro Mini A3 -> later ATtiny85 PB4 (XTAL2, Pin 3)
// Direction LEDs (avoid D0/D1 because you may want RX/TX later)
const uint8_t LED_DIR1_PIN = 2; // D2
const uint8_t LED_DIR2_PIN = 3; // D3
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
// 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; // final threshold used for direction decision
// 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 + threshold once at boot/reset
// Parameter must be only AverageRepeat.
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);
// Final threshold with margin + floor
VdiffThreshold = maxf(VdiffBaseline * VdiffThresholdMargin, VdiffThresholdMinVolts);
}
// -----------------------------------------------------------------------------
// State machine
// -----------------------------------------------------------------------------
static void updateDirectionFromVoltages()
{
const float diff = v1 - v2;
const float absDiff = absf(diff);
// Neutral region: hold direction
if (absDiff <= VdiffThreshold) {
return;
}
// Clear dominance: set direction deterministically
// diff > 0 => v1 >> v2 => DIR1 (2)
// diff < 0 => v2 >> v1 => DIR2 (3)
direction = (diff > 0.0f) ? (byte)2 : (byte)3;
}
// -----------------------------------------------------------------------------
// 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("VdiffThresholdMargin: ");
Serial.print(VdiffThresholdMargin, 2);
Serial.print(" x | ");
Serial.print("VdiffThresholdMinVolts: ");
Serial.print(VdiffThresholdMinVolts, 3);
Serial.print(" V | ");
Serial.print("VdiffThreshold: ");
Serial.print(VdiffThreshold, 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 0004 Version 0.1 Test (Arduino Uno Test) ===");
Serial.println(" ~~~ InitStart ~~~");
Serial.print(" AverageRepeat: ");
Serial.println(AverageRepeat);
Serial.println(" ~~~ InitEnd ~~~");
}
serialPrintAll();
}
void loop() {
measureAveragedVoltages();
updateDirectionFromVoltages();
applyDirectionOutputs();
serialPrintAll();
delay(300);
}

View File

@ -0,0 +1,286 @@
/*
0004_DenshaBekutoru 1st working Example
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 = A2; // Pro Mini A2 -> later ATtiny85 PB3 (XTAL1, Pin 2)
const uint8_t ADC_PIN_2 = A3; // Pro Mini A3 -> later ATtiny85 PB4 (XTAL2, Pin 3)
// Direction LEDs (avoid D0/D1 because you may want RX/TX later)
const uint8_t LED_DIR1_PIN = 2; // D2
const uint8_t LED_DIR2_PIN = 3; // D3
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);
}

View File

@ -0,0 +1,231 @@
/*
0004_DenshaBekutoru State Machine implemented
Target dev board (later): Arduino Pro Mini 5V / 16 MHz (ATmega328P)
----------------------------------------------------------------------------
State machine (direction memory)
----------------------------------------------------------------------------
Inputs derived from v1, v2, VdiffThreshold:
N (Neutral): |v1 - v2| <= VdiffThreshold
D1 (v1>>v2): (v1 - v2) > VdiffThreshold
D2 (v2>>v1): (v2 - v1) > VdiffThreshold
State encoding (kept transfer-friendly, and compatible with earlier pin-mapping):
0 = NONE
2 = DIR1
3 = DIR2
Transition table:
Current \ Input | N (neutral) | D1 (v1>>v2) | D2 (v2>>v1)
-----------------------------------------------------------------
0 (NONE) | 0 | 2 | 3
2 (DIR1) | 2 | 2 | 3
3 (DIR2) | 3 | 2 | 3
Mermaid (documentation)
-----------------------
stateDiagram-v2
[*] --> NONE
state "0 : NONE" as NONE
state "2 : DIR1 (v1>>v2)" as DIR1
state "3 : DIR2 (v2>>v1)" as DIR2
NONE --> NONE : |v1 - v2| <= T
NONE --> DIR1 : v1 - v2 > T
NONE --> DIR2 : v2 - v1 > T
DIR1 --> DIR1 : |v1 - v2| <= T
DIR1 --> DIR1 : v1 - v2 > T
DIR1 --> DIR2 : v2 - v1 > T
DIR2 --> DIR2 : |v1 - v2| <= T
DIR2 --> DIR2 : v2 - v1 > T
DIR2 --> DIR1 : v1 - v2 > T
*/
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 = A2; // Pro Mini A2 -> later ATtiny85 PB3 (XTAL1, Pin 2)
const uint8_t ADC_PIN_2 = A3; // Pro Mini A3 -> later ATtiny85 PB4 (XTAL2, Pin 3)
// 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 (optional but practical)
// 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; // final threshold used for direction decision
// 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; }
// Measure averaged voltages (updates globals v1/v2)
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);
}
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 + threshold once at boot/reset
// Parameter must be only AverageRepeat (per your requirement).
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);
// Final threshold with margin + floor
VdiffThreshold = maxf(VdiffBaseline * VdiffThresholdMargin, VdiffThresholdMinVolts);
}
// Implements the state machine table above
static void updateDirectionFromVoltages()
{
const float diff = v1 - v2;
const float absDiff = absf(diff);
// Neutral region: hold direction (only NONE stays NONE)
if (absDiff <= VdiffThreshold) {
// direction remains unchanged (0 stays 0; 2 stays 2; 3 stays 3)
return;
}
// Clear dominance: set direction deterministically
// diff > 0 => v1 >> v2 => DIR1 (2)
// diff < 0 => v2 >> v1 => DIR2 (3)
direction = (diff > 0.0f) ? (byte)2 : (byte)3;
}
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("VdiffThresholdMargin: ");
Serial.print(VdiffThresholdMargin, 2);
Serial.print(" x | ");
Serial.print("VdiffThresholdMinVolts: ");
Serial.print(VdiffThresholdMinVolts, 3);
Serial.print(" V | ");
Serial.print("VdiffThreshold: ");
Serial.print(VdiffThreshold, 3);
Serial.print(" V | ");
Serial.print("direction: ");
Serial.println(direction);
}
void setup() {
Serial.begin(115200);
pinMode(ADC_PIN_1, INPUT);
pinMode(ADC_PIN_2, INPUT);
// Initial calibration: compute VdiffThreshold once after boot/reset
calibrateVdiffThreshold(AverageRepeat);
// One measurement for initial display
measureAveragedVoltages();
updateDirectionFromVoltages();
if (SerialOutputAllow) {
Serial.println("=== DenshaBekutoru State Machine and Variable Output (Arduino Pro Mini 5V/16MHz) ===");
Serial.println("~~~ Init ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
Serial.print("AverageRepeat: ");
Serial.println(AverageRepeat);
Serial.println("~~~ Init ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
}
serialPrintAll();
}
void loop() {
measureAveragedVoltages();
updateDirectionFromVoltages();
serialPrintAll();
delay(300);
}

File diff suppressed because it is too large Load Diff