Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d49c06e2ad | |||
| e512cac398 | |||
| 13aee50b80 | |||
| fdf4876a2b |
Binary file not shown.
|
After Width: | Height: | Size: 320 KiB |
Binary file not shown.
|
After 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.
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.
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"board": {
|
"board": {
|
||||||
"active_layer": 0,
|
"active_layer": 33,
|
||||||
"active_layer_preset": "All Layers",
|
"active_layer_preset": "All Layers",
|
||||||
"auto_track_width": true,
|
"auto_track_width": true,
|
||||||
"hidden_netclasses": [],
|
"hidden_netclasses": [],
|
||||||
|
|||||||
@ -58,7 +58,12 @@
|
|||||||
"width": 0.0
|
"width": 0.0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"drc_exclusions": [],
|
"drc_exclusions": [
|
||||||
|
"courtyards_overlap|116847500|113255000|4b518c68-cacc-4ba0-bdd7-4ed203d87dd8|c5b5c5e2-5bf5-406f-bc2c-791c87e4bd5a",
|
||||||
|
"courtyards_overlap|116847500|116747500|4b518c68-cacc-4ba0-bdd7-4ed203d87dd8|ce87971b-d681-44d7-9fb7-23a15933148a",
|
||||||
|
"courtyards_overlap|126372500|116747500|1094a2e1-479d-4870-8b87-1411fc6da792|4b518c68-cacc-4ba0-bdd7-4ed203d87dd8",
|
||||||
|
"courtyards_overlap|130322874|113255000|4b518c68-cacc-4ba0-bdd7-4ed203d87dd8|ee659d06-72c1-451a-8938-35a721a086e2"
|
||||||
|
],
|
||||||
"meta": {
|
"meta": {
|
||||||
"version": 2
|
"version": 2
|
||||||
},
|
},
|
||||||
@ -96,7 +101,7 @@
|
|||||||
"padstack": "warning",
|
"padstack": "warning",
|
||||||
"pth_inside_courtyard": "ignore",
|
"pth_inside_courtyard": "ignore",
|
||||||
"shorting_items": "error",
|
"shorting_items": "error",
|
||||||
"silk_edge_clearance": "warning",
|
"silk_edge_clearance": "ignore",
|
||||||
"silk_over_copper": "warning",
|
"silk_over_copper": "warning",
|
||||||
"silk_overlap": "warning",
|
"silk_overlap": "warning",
|
||||||
"skew_out_of_range": "error",
|
"skew_out_of_range": "error",
|
||||||
@ -178,7 +183,9 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"track_widths": [
|
"track_widths": [
|
||||||
0.0
|
0.0,
|
||||||
|
0.508,
|
||||||
|
1.27
|
||||||
],
|
],
|
||||||
"tuning_pattern_settings": {
|
"tuning_pattern_settings": {
|
||||||
"diff_pair_defaults": {
|
"diff_pair_defaults": {
|
||||||
@ -489,7 +496,7 @@
|
|||||||
"gencad": "",
|
"gencad": "",
|
||||||
"idf": "",
|
"idf": "",
|
||||||
"netlist": "../../../../../../",
|
"netlist": "../../../../../../",
|
||||||
"plot": "",
|
"plot": "/home/tgohle/Desktop/git/ToGo-Lab/0004-DenshaBekutoru/KiCad/0004-DenshaBekutoru_PCB_v0.2/",
|
||||||
"pos_files": "",
|
"pos_files": "",
|
||||||
"specctra_dsn": "",
|
"specctra_dsn": "",
|
||||||
"step": "",
|
"step": "",
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 66 KiB |
BIN
KiCad/0004-DenshaBekutoru_v0.2/2026-02-24_20-37-06_NUC2.png
Normal file
BIN
KiCad/0004-DenshaBekutoru_v0.2/2026-02-24_20-37-06_NUC2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 263 KiB |
File diff suppressed because it is too large
Load Diff
@ -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