merge panels
This commit is contained in:
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* Pin Discovery Tool for Toy PCB Brain Transplant
|
||||
*
|
||||
* Upload this to the XIAO nRF52840, then connect one breakout pin
|
||||
* at a time to the PROBE_PIN. Open Serial Monitor at 115200 baud.
|
||||
*
|
||||
* The tool will tell you:
|
||||
* - Resting voltage (VCC, GND, floating, pulled up/down)
|
||||
* - Whether it responds to button presses
|
||||
* - Whether it looks like an analog resistor ladder
|
||||
* - Suggested function (power, button, output, NC)
|
||||
*
|
||||
* Workflow:
|
||||
* 1. Desolder original MCU, solder SOP-16 breakout adapter
|
||||
* 2. Install batteries in toy
|
||||
* 3. Connect XIAO GND to toy GND (battery negative)
|
||||
* 4. For each breakout pin, connect it to PROBE_PIN with a jumper
|
||||
* 5. Type the pin number in Serial Monitor and press Enter
|
||||
* 6. Follow prompts (press buttons when asked, etc.)
|
||||
* 7. Tool builds a pin map as you go
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
#define PROBE_PIN A0 // Connect test jumper here
|
||||
#define NUM_MCU_PINS 16 // SOP-16
|
||||
|
||||
// Storage for discovered pin map
|
||||
struct PinInfo {
|
||||
char label[20];
|
||||
float voltage;
|
||||
bool discovered;
|
||||
};
|
||||
|
||||
PinInfo pinMap[NUM_MCU_PINS + 1]; // 1-indexed
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial) delay(10);
|
||||
|
||||
memset(pinMap, 0, sizeof(pinMap));
|
||||
|
||||
Serial.println("╔══════════════════════════════════════════╗");
|
||||
Serial.println("║ Toy PCB Pin Discovery Tool v1.0 ║");
|
||||
Serial.println("║ Connect XIAO GND to toy battery GND ║");
|
||||
Serial.println("║ Connect one SOP pin at a time to A0 ║");
|
||||
Serial.println("╚══════════════════════════════════════════╝");
|
||||
Serial.println();
|
||||
Serial.println("Commands:");
|
||||
Serial.println(" 1-16 = Probe that SOP pin number");
|
||||
Serial.println(" map = Show current pin map");
|
||||
Serial.println(" auto = Auto-detect VCC and GND pins");
|
||||
Serial.println(" btn = Button detection mode (tests all states)");
|
||||
Serial.println(" ladder = Resistor ladder detection");
|
||||
Serial.println();
|
||||
Serial.print("> ");
|
||||
}
|
||||
|
||||
// Read voltage on probe pin (0-3.3V range)
|
||||
float readVoltage() {
|
||||
analogReadResolution(12); // nRF52840 supports 12-bit ADC
|
||||
delay(10); // settle
|
||||
|
||||
// Average multiple readings
|
||||
uint32_t sum = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
sum += analogRead(PROBE_PIN);
|
||||
delayMicroseconds(500);
|
||||
}
|
||||
float raw = sum / 16.0;
|
||||
return (raw / 4095.0) * 3.3; // Convert to voltage
|
||||
}
|
||||
|
||||
// Check if pin is actively being driven or floating
|
||||
String classifyVoltage(float v) {
|
||||
if (v < 0.1) return "GND (hard low)";
|
||||
if (v < 0.4) return "Weak pulldown or low output";
|
||||
if (v > 3.1) return "VCC (hard high)";
|
||||
if (v > 2.5) return "Weak pullup (~3V)";
|
||||
if (v > 1.4 && v < 1.9) return "Floating (~mid-rail)";
|
||||
return "Unknown voltage";
|
||||
}
|
||||
|
||||
// Test if the pin changes state (button detection)
|
||||
void testButton(int sopPin) {
|
||||
Serial.println("\n--- Button Detection ---");
|
||||
Serial.println("Watch the voltage while pressing each toy button.");
|
||||
Serial.println("Monitoring for 10 seconds...");
|
||||
Serial.println();
|
||||
|
||||
float baseline = readVoltage();
|
||||
Serial.print("Baseline: ");
|
||||
Serial.print(baseline, 3);
|
||||
Serial.println("V");
|
||||
|
||||
float minV = baseline, maxV = baseline;
|
||||
unsigned long start = millis();
|
||||
int changes = 0;
|
||||
float lastV = baseline;
|
||||
|
||||
while (millis() - start < 10000) {
|
||||
float v = readVoltage();
|
||||
|
||||
if (v < minV) minV = v;
|
||||
if (v > maxV) maxV = v;
|
||||
|
||||
// Detect transitions
|
||||
if (abs(v - lastV) > 0.3) {
|
||||
changes++;
|
||||
Serial.print(" Change detected! ");
|
||||
Serial.print(lastV, 2);
|
||||
Serial.print("V → ");
|
||||
Serial.print(v, 2);
|
||||
Serial.print("V at t=");
|
||||
Serial.print((millis() - start) / 1000.0, 1);
|
||||
Serial.println("s");
|
||||
}
|
||||
lastV = v;
|
||||
delay(20);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
Serial.print("Range: ");
|
||||
Serial.print(minV, 3);
|
||||
Serial.print("V to ");
|
||||
Serial.print(maxV, 3);
|
||||
Serial.println("V");
|
||||
Serial.print("Transitions detected: ");
|
||||
Serial.println(changes);
|
||||
|
||||
if (changes > 0 && maxV - minV > 1.0) {
|
||||
Serial.println("→ LIKELY A BUTTON PIN (digital, active low)");
|
||||
if (sopPin > 0) {
|
||||
snprintf(pinMap[sopPin].label, sizeof(pinMap[sopPin].label), "Button");
|
||||
pinMap[sopPin].voltage = baseline;
|
||||
pinMap[sopPin].discovered = true;
|
||||
}
|
||||
} else if (changes > 0 && maxV - minV > 0.2) {
|
||||
Serial.println("→ POSSIBLE ANALOG INPUT or RESISTOR LADDER");
|
||||
} else {
|
||||
Serial.println("→ No button activity detected on this pin");
|
||||
}
|
||||
}
|
||||
|
||||
// Detect resistor ladder (multiple buttons on one analog pin)
|
||||
void testResistorLadder() {
|
||||
Serial.println("\n--- Resistor Ladder Detection ---");
|
||||
Serial.println("Press each button ONE AT A TIME when prompted.");
|
||||
Serial.println("Press Enter after pressing each button.");
|
||||
Serial.println("Type 'done' when finished.");
|
||||
Serial.println();
|
||||
|
||||
float voltages[10];
|
||||
String names[10];
|
||||
int count = 0;
|
||||
|
||||
float baseline = readVoltage();
|
||||
Serial.print("Baseline (no button): ");
|
||||
Serial.print(baseline, 3);
|
||||
Serial.println("V");
|
||||
|
||||
while (count < 10) {
|
||||
Serial.print("\nPress button #");
|
||||
Serial.print(count + 1);
|
||||
Serial.println(" and type its name (or 'done'):");
|
||||
Serial.print("> ");
|
||||
|
||||
while (!Serial.available()) delay(10);
|
||||
String input = Serial.readStringUntil('\n');
|
||||
input.trim();
|
||||
|
||||
if (input.equalsIgnoreCase("done")) break;
|
||||
|
||||
float v = readVoltage();
|
||||
voltages[count] = v;
|
||||
names[count] = input;
|
||||
|
||||
Serial.print(" ");
|
||||
Serial.print(input);
|
||||
Serial.print(": ");
|
||||
Serial.print(v, 3);
|
||||
Serial.println("V");
|
||||
|
||||
count++;
|
||||
|
||||
Serial.println(" Release button now.");
|
||||
delay(500);
|
||||
}
|
||||
|
||||
if (count > 1) {
|
||||
Serial.println("\n--- Ladder Summary ---");
|
||||
Serial.print("Baseline: ");
|
||||
Serial.print(baseline, 3);
|
||||
Serial.println("V");
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
Serial.print(" ");
|
||||
Serial.print(names[i]);
|
||||
Serial.print(": ");
|
||||
Serial.print(voltages[i], 3);
|
||||
Serial.print("V (ADC ~");
|
||||
Serial.print((int)(voltages[i] / 3.3 * 4095));
|
||||
Serial.println(")");
|
||||
}
|
||||
|
||||
// Check if voltages are distinct enough
|
||||
bool isLadder = true;
|
||||
for (int i = 0; i < count - 1; i++) {
|
||||
for (int j = i + 1; j < count; j++) {
|
||||
if (abs(voltages[i] - voltages[j]) < 0.15) {
|
||||
isLadder = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isLadder && count >= 2) {
|
||||
Serial.println("\n→ THIS IS A RESISTOR LADDER");
|
||||
Serial.println(" Use analogRead() with thresholds to detect buttons.");
|
||||
Serial.println(" Suggested thresholds (midpoints between readings):");
|
||||
|
||||
// Sort by voltage
|
||||
for (int i = 0; i < count - 1; i++) {
|
||||
for (int j = i + 1; j < count; j++) {
|
||||
if (voltages[j] < voltages[i]) {
|
||||
float tv = voltages[i]; voltages[i] = voltages[j]; voltages[j] = tv;
|
||||
String ts = names[i]; names[i] = names[j]; names[j] = ts;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
float lo = (i == 0) ? 0 : (voltages[i-1] + voltages[i]) / 2;
|
||||
float hi = (i == count-1) ? 3.3 : (voltages[i] + voltages[i+1]) / 2;
|
||||
Serial.print(" ");
|
||||
Serial.print(names[i]);
|
||||
Serial.print(": ");
|
||||
Serial.print(lo, 2);
|
||||
Serial.print("V - ");
|
||||
Serial.print(hi, 2);
|
||||
Serial.println("V");
|
||||
}
|
||||
} else {
|
||||
Serial.println("\n→ Doesn't look like a resistor ladder");
|
||||
Serial.println(" (Voltages too close together or too few buttons)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Full probe of one pin
|
||||
void probePin(int sopPin) {
|
||||
Serial.print("\n═══ Probing SOP-16 Pin ");
|
||||
Serial.print(sopPin);
|
||||
Serial.println(" ═══");
|
||||
|
||||
// First read as analog input (high impedance)
|
||||
pinMode(PROBE_PIN, INPUT);
|
||||
delay(50);
|
||||
float v_floating = readVoltage();
|
||||
|
||||
Serial.print("Floating voltage: ");
|
||||
Serial.print(v_floating, 3);
|
||||
Serial.print("V → ");
|
||||
Serial.println(classifyVoltage(v_floating));
|
||||
|
||||
// Classify
|
||||
if (v_floating < 0.1) {
|
||||
Serial.println("→ This is a GND pin");
|
||||
snprintf(pinMap[sopPin].label, sizeof(pinMap[sopPin].label), "GND");
|
||||
pinMap[sopPin].voltage = v_floating;
|
||||
pinMap[sopPin].discovered = true;
|
||||
}
|
||||
else if (v_floating > 2.8) {
|
||||
// Could be VCC or a pulled-up button pin
|
||||
// Try briefly enabling internal pulldown to see if it drops
|
||||
pinMode(PROBE_PIN, INPUT_PULLDOWN);
|
||||
delay(50);
|
||||
float v_pulldown = readVoltage();
|
||||
pinMode(PROBE_PIN, INPUT);
|
||||
|
||||
if (v_pulldown > 2.5) {
|
||||
Serial.print("With pulldown: ");
|
||||
Serial.print(v_pulldown, 3);
|
||||
Serial.println("V — Still high → VCC (power) pin");
|
||||
snprintf(pinMap[sopPin].label, sizeof(pinMap[sopPin].label), "VCC");
|
||||
pinMap[sopPin].voltage = v_floating;
|
||||
pinMap[sopPin].discovered = true;
|
||||
} else {
|
||||
Serial.print("With pulldown: ");
|
||||
Serial.print(v_pulldown, 3);
|
||||
Serial.println("V — Dropped → Weak pullup (likely button input)");
|
||||
Serial.println("→ Try pressing buttons to confirm. Running button test...");
|
||||
testButton(sopPin);
|
||||
}
|
||||
}
|
||||
else if (v_floating > 0.4 && v_floating < 2.5) {
|
||||
Serial.println("Mid-range voltage. Could be:");
|
||||
Serial.println(" - Floating (not connected)");
|
||||
Serial.println(" - Part of a resistor ladder");
|
||||
Serial.println(" - An analog output");
|
||||
Serial.println("→ Try pressing buttons to see if it changes...");
|
||||
testButton(sopPin);
|
||||
}
|
||||
else {
|
||||
Serial.println("Low but not GND. Could be pulled-down output.");
|
||||
testButton(sopPin);
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
// Print the current pin map
|
||||
void showMap() {
|
||||
Serial.println("\n╔════════════════════════════════════╗");
|
||||
Serial.println("║ Current Pin Map ║");
|
||||
Serial.println("╠════════════════════════════════════╣");
|
||||
|
||||
for (int i = 1; i <= NUM_MCU_PINS; i++) {
|
||||
Serial.print("║ Pin ");
|
||||
if (i < 10) Serial.print(" ");
|
||||
Serial.print(i);
|
||||
Serial.print(": ");
|
||||
|
||||
if (pinMap[i].discovered) {
|
||||
Serial.print(pinMap[i].label);
|
||||
// Pad to align
|
||||
for (int j = strlen(pinMap[i].label); j < 12; j++) Serial.print(" ");
|
||||
Serial.print("(");
|
||||
Serial.print(pinMap[i].voltage, 2);
|
||||
Serial.print("V)");
|
||||
} else {
|
||||
Serial.print("-- not probed -- ");
|
||||
}
|
||||
Serial.println(" ║");
|
||||
}
|
||||
|
||||
Serial.println("╚════════════════════════════════════╝");
|
||||
|
||||
// Count discovered
|
||||
int found = 0;
|
||||
for (int i = 1; i <= NUM_MCU_PINS; i++) {
|
||||
if (pinMap[i].discovered) found++;
|
||||
}
|
||||
Serial.print("Discovered: ");
|
||||
Serial.print(found);
|
||||
Serial.print("/");
|
||||
Serial.println(NUM_MCU_PINS);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (Serial.available()) {
|
||||
String input = Serial.readStringUntil('\n');
|
||||
input.trim();
|
||||
|
||||
if (input.equalsIgnoreCase("map")) {
|
||||
showMap();
|
||||
}
|
||||
else if (input.equalsIgnoreCase("btn")) {
|
||||
Serial.println("Connect the pin you want to test to A0, then:");
|
||||
testButton(0);
|
||||
}
|
||||
else if (input.equalsIgnoreCase("ladder")) {
|
||||
testResistorLadder();
|
||||
}
|
||||
else if (input.equalsIgnoreCase("auto")) {
|
||||
Serial.println("\n--- Auto-detect mode ---");
|
||||
Serial.println("Connect each pin to A0 one at a time.");
|
||||
Serial.println("Press Enter after connecting each pin.");
|
||||
for (int pin = 1; pin <= NUM_MCU_PINS; pin++) {
|
||||
Serial.print("\nConnect SOP pin ");
|
||||
Serial.print(pin);
|
||||
Serial.println(" to A0, then press Enter");
|
||||
Serial.print("> ");
|
||||
while (!Serial.available()) delay(10);
|
||||
Serial.readStringUntil('\n');
|
||||
probePin(pin);
|
||||
}
|
||||
showMap();
|
||||
}
|
||||
else {
|
||||
int pin = input.toInt();
|
||||
if (pin >= 1 && pin <= NUM_MCU_PINS) {
|
||||
probePin(pin);
|
||||
} else {
|
||||
Serial.println("Unknown command. Use 1-16, map, auto, btn, or ladder");
|
||||
}
|
||||
}
|
||||
|
||||
Serial.print("\n> ");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user