Flipdot Matrix PCB Design Review
GPIO Mapping
| Function | GPIO | Connected To | Direction | Notes |
|---|---|---|---|---|
| ROW0_IN1 | 1 | U1 AIN1 | Output | ROW0 rail high/low control input 1 |
| ROW0_IN2 | 2 | U1 AIN2 | Output | ROW0 rail high/low control input 2 |
| ROW1_IN1 | 3 | U1 BIN1 | Output | ROW1 rail input 1 |
| ROW1_IN2 | 4 | U1 BIN2 | Output | ROW1 rail input 2 |
| ROW2_IN1 | 5 | U2 AIN1 | Output | ROW2 rail input 1 |
| ROW2_IN2 | 6 | U2 AIN2 | Output | ROW2 rail input 2 |
| ROW3_IN1 | 7 | U2 BIN1 | Output | ROW3 rail input 1 |
| ROW3_IN2 | 8 | U2 BIN2 | Output | ROW3 rail input 2 |
| ROW4_IN1 | 9 | U3 AIN1 | Output | ROW4 rail input 1 |
| ROW4_IN2 | 10 | U3 AIN2 | Output | ROW4 rail input 2 |
| ROW5_IN1 | 11 | U3 BIN1 | Output | ROW5 rail input 1 |
| ROW5_IN2 | 12 | U3 BIN2 | Output | ROW5 rail input 2 |
| ROW6_IN1 | 13 | U4 AIN1 | Output | ROW6 rail input 1 |
| ROW6_IN2 | 14 | U4 AIN2 | Output | ROW6 rail input 2 |
| ROW7_IN1 | 15 | U4 BIN1 | Output | ROW7 rail input 1 |
| ROW7_IN2 | 16 | U4 BIN2 | Output | ROW7 rail input 2 |
| COL0_IN1 | 17 | U5 AIN1 | Output | COL0 rail input 1 |
| COL0_IN2 | 18 | U5 AIN2 | Output | COL0 rail input 2 |
| USB_D_N | 19 | J1 D- through U11 | USB | Native USB D- |
| USB_D_P | 20 | J1 D+ through U11 | USB | Native USB D+ |
| COL1_IN1 | 21 | U5 BIN1 | Output | COL1 rail input 1 |
| COL1_IN2 | 33 | U5 BIN2 | Output | COL1 rail input 2 |
| COL2_IN1 | 34 | U6 AIN1 | Output | COL2 rail input 1 |
| COL2_IN2 | 35 | U6 AIN2 | Output | COL2 rail input 2 |
| COL3_IN1 | 36 | U6 BIN1 | Output | COL3 rail input 1 |
| COL3_IN2 | 37 | U6 BIN2 | Output | COL3 rail input 2 |
| COL4_IN1 | 38 | U7 AIN1 | Output | COL4 rail input 1 |
| COL4_IN2 | 39 | U7 AIN2 | Output | COL4 rail input 2 |
| COL5_IN1 | 40 | U7 BIN1 | Output | COL5 rail input 1 |
| COL5_IN2 | 41 | U7 BIN2 | Output | COL5 rail input 2 |
| STATUS_LED | 48 | R_LED -> LED1 | Output | Active-high status LED |
Ini
[env:esp32-s3-mini-1] platform = espressif32 board = esp32-s3-devkitc-1 framework = arduino monitor_speed = 115200 upload_speed = 921600 board_build.flash_size = 8MB board_build.arduino.memory_type = qio_opi build_flags = -D ARDUINO_USB_MODE=1 -D ARDUINO_USB_CDC_ON_BOOT=1
Cpp
#include <Arduino.h> // Matrix geometry constexpr uint8_t ROWS = 8; constexpr uint8_t COLS = 6; // Pulse timing defaults uint16_t PULSE_MS = 15; constexpr uint16_t SETTLE_MS = 3; constexpr uint16_t MAX_PULSE_MS = 50; // ROW rail control pins: each rail has IN1, IN2 to one DRV8833 half-bridge. const uint8_t ROW_IN1[ROWS] = {1, 3, 5, 7, 9, 11, 13, 15}; const uint8_t ROW_IN2[ROWS] = {2, 4, 6, 8, 10, 12, 14, 16}; // COL rail control pins. const uint8_t COL_IN1[COLS] = {17, 21, 34, 36, 38, 40}; const uint8_t COL_IN2[COLS] = {18, 33, 35, 37, 39, 41}; constexpr uint8_t STATUS_LED_PIN = 48; // DRV8833 single-ended rail states using OUT1 only: // IN1=0, IN2=0: high-Z / coast // IN1=1, IN2=0: OUT1 high // IN1=0, IN2=1: OUT1 low // IN1=1, IN2=1: brake, avoided void railHiZ(uint8_t in1, uint8_t in2) { digitalWrite(in1, LOW); digitalWrite(in2, LOW); } void railHigh(uint8_t in1, uint8_t in2) { digitalWrite(in1, HIGH); digitalWrite(in2, LOW); } void railLow(uint8_t in1, uint8_t in2) { digitalWrite(in1, LOW); digitalWrite(in2, HIGH); } void allRailsHiZ() { for (uint8_t r = 0; r < ROWS; r++) railHiZ(ROW_IN1[r], ROW_IN2[r]); for (uint8_t c = 0; c < COLS; c++) railHiZ(COL_IN1[c], COL_IN2[c]); } void initMatrixPins() { for (uint8_t r = 0; r < ROWS; r++) { pinMode(ROW_IN1[r], OUTPUT); pinMode(ROW_IN2[r], OUTPUT); } for (uint8_t c = 0; c < COLS; c++) { pinMode(COL_IN1[c], OUTPUT); pinMode(COL_IN2[c], OUTPUT); } allRailsHiZ(); } void flipCell(uint8_t row, uint8_t col, bool whiteFaceUp) { if (row >= ROWS || col >= COLS) return; allRailsHiZ(); delay(SETTLE_MS); if (whiteFaceUp) { // Forward current: ROW high, COL low. railHigh(ROW_IN1[row], ROW_IN2[row]); railLow(COL_IN1[col], COL_IN2[col]); } else { // Reverse current: ROW low, COL high. railLow(ROW_IN1[row], ROW_IN2[row]); railHigh(COL_IN1[col], COL_IN2[col]); } delay(PULSE_MS); allRailsHiZ(); delay(SETTLE_MS); } void setAll(bool whiteFaceUp) { for (uint8_t r = 0; r < ROWS; r++) { for (uint8_t c = 0; c < COLS; c++) { flipCell(r, c, whiteFaceUp); } } } void checkerboard(bool invert) { for (uint8_t r = 0; r < ROWS; r++) { for (uint8_t c = 0; c < COLS; c++) { flipCell(r, c, ((r + c) & 1) ^ invert); } } } void sweep() { for (uint8_t r = 0; r < ROWS; r++) { for (uint8_t c = 0; c < COLS; c++) { flipCell(r, c, true); } } for (uint8_t r = 0; r < ROWS; r++) { for (uint8_t c = 0; c < COLS; c++) { flipCell(r, c, false); } } } void halfSelectTest() { // Pulses one selected cell repeatedly; surrounding same-row/same-col cells should not move. for (uint8_t i = 0; i < 10; i++) { flipCell(0, 0, true); delay(100); flipCell(0, 0, false); delay(100); } } void printHelp() { Serial.println("Commands:"); Serial.println(" c clear all cells"); Serial.println(" s set all cells"); Serial.println(" k checkerboard"); Serial.println(" K inverse checkerboard"); Serial.println(" w sweep"); Serial.println(" h half-select test at R0 C0"); Serial.println(" f R C T flip row R col C to target T (0/1)"); Serial.println(" p N set pulse width in ms, clamped to MAX_PULSE_MS"); } void handleCommand(String line) { line.trim(); if (line.length() == 0) return; if (line == "c") setAll(false); else if (line == "s") setAll(true); else if (line == "k") checkerboard(false); else if (line == "K") checkerboard(true); else if (line == "w") sweep(); else if (line == "h") halfSelectTest(); else if (line[0] == 'p') { int n = line.substring(1).toInt(); if (n > 0) PULSE_MS = min<uint16_t>(n, MAX_PULSE_MS); Serial.printf("PULSE_MS=%u\n", PULSE_MS); } else if (line[0] == 'f') { int r = -1, c = -1, t = -1; if (sscanf(line.c_str(), "f %d %d %d", &r, &c, &t) == 3) { flipCell((uint8_t)r, (uint8_t)c, t != 0); } else { Serial.println("Usage: f R C T"); } } else { printHelp(); } } void setup() { pinMode(STATUS_LED_PIN, OUTPUT); digitalWrite(STATUS_LED_PIN, LOW); initMatrixPins(); Serial.begin(115200); unsigned long start = millis(); while (!Serial && (millis() - start < 1500)) { delay(10); } digitalWrite(STATUS_LED_PIN, HIGH); Serial.println("ESP32-S3-MINI-1 Flipdot 6x8 firmware ready."); printHelp(); } void loop() { if (Serial.available()) { String line = Serial.readStringUntil('\n'); handleCommand(line); } }
Bash
pio run pio run -t upload pio device monitor -b 115200
Welcome 👋
Flux helps you build PCBs faster with an AI teammate!
Create your account to collaborate, stay updated, fork your own version, and get instant answers from our AI agent.