Getting Started

Quick Start Guide

From blank boards to a working ball-in-play state. No prior pinball experience required — just ATmega2560 + ATmega328P hardware and the Micro PinOS sketches.

Est. 30–60 min · Beginner friendly
What you need
🧠
ATmega2560
Game brain board
🔲
ATmega328P Nano ×1–5
One per switch cluster
📡
MAX485 Modules
One per board — RS485 drivers
MOSFET Drivers
TIP120 or IRLZ44N per coil
🔧
1N4007 Diodes
Flyback protection per coil
🔌
Dual PSU
5V logic + 24–48V solenoid

Step-by-step guide
1
Download Micro PinOS and open in Arduino IDE
Install the framework and verify your board setup

Download the full bundle from the Download page and unzip. You'll find two folders: Mega/ and nano/. Open Mega/MainMega.ino in Arduino IDE 2.x, select ATmega2560 (or ATmega2560 (Mega 2560)) as the board, and the correct COM port.

Mega/ folder structure
// Mega/
//   MainMega.ino    ← open this file
//   attract.h       ← attract mode + wheel selector
//   GameStyleOne.h  ← traditional scoring (full)
//   GameStyleStubs.h← Styles 2–4 (stub, ready to fill)
//   commands.h      ← all TYPE:PAYLOAD strings
//   switches.h      ← all switch ID #defines

// nano/
//   nano_universal.ino  ← open this for each Nano
//   switch_ids.h        ← shared switch ID constants
2
Wire the RS485 bus
One MAX485 module per board, four wires shared

The RS485 bus uses four wires between all boards: A, B (the differential pair), GND, and +5V. All Nanos and the Mega share the same A and B lines — this is the multi-drop topology.

  • Mega: Serial1 (pins 18/19) → MAX485 → bus
  • Each Nano: Serial (pins 0/1) → MAX485 → same bus
  • DE/RE pins on all MAX485 modules tied together to D2 on each board
  • Add 120Ω termination resistors across A/B at each end of the bus
Pin definitions — MainMega.ino
// MainMega.ino — serial port assignments
//   Serial1 (pins 18/19) → RS485 bus → all Nanos
//   Serial2 (pins 16/17) → Sound board (DFPlayer etc.)
//   Serial3 (pins 14/15) → Display / lights board

#define RS485_DE_PIN  2    // MAX485 transmit enable

void setup() {
  Serial.begin(115200);   // USB debug
  Serial1.begin(115200);  // RS485 bus
  Serial2.begin(115200);  // Sound board
  Serial3.begin(115200);  // Display/lights board

  pinMode(RS485_DE_PIN, OUTPUT);
  digitalWrite(RS485_DE_PIN, LOW);  // start in receive

  // Init solenoid pins
  for (int i = 0; i < NUM_SOLENOIDS; i++) {
    pinMode(solenoids[i].pin, OUTPUT);
    digitalWrite(solenoids[i].pin, LOW);
  }
}
3
Configure your first Nano
Edit the switch table — nothing else needs changing

Open nano/nano_universal.ino. Set MY_ADDRESS to a unique number for this Nano (0–4). Then fill in the switch table at the top — each row is one switch: pin, ID, solenoid pin, hold pin, pulse duration, debounce time.

nano_universal.ino — Nano 0 (Type 2 Reaction)
#define MY_ADDRESS   0        // unique per Nano
#define DE_PIN       2        // MAX485 DE pin — always D2
#define BAUD_RATE    115200

// Type 1 Sensor:   solPin=-1, holdPin=-1
// Type 2 Reaction: solPin>=0, holdPin=-1  (fires local coil)
// Type 3 Flipper:  add #define DUAL_WOUND at top

// pin | switchID           | solPin | holdPin | pulseMs | debounceMs
static const SwEntry SW[] = {
  {  3, SW_SLINGSHOT_LEFT,       5,      -1,      25,           5 },
  {  4, SW_SLINGSHOT_RIGHT,      6,      -1,      25,           5 },
  {  7, SW_POP_BUMPER_TOP,       8,      -1,      20,           5 },
  {  9, SW_POP_BUMPER_LEFT,     10,      -1,      20,           5 },
  { 11, SW_POP_BUMPER_RIGHT,    12,      -1,      20,           5 },
};
// ── NOTHING BELOW THIS LINE NEEDS EDITING ──

For a Type 1 sensor Nano (rollover lanes, targets, cabinet switches), set solPin = -1 and holdPin = -1. The Nano just debounces and reports — no local solenoid fires.

Nano 1 — Rollover lanes (Type 1 Sensor)
#define MY_ADDRESS   1   // Nano 1

static const SwEntry SW[] = {
  {  3, SW_ROLLOVER_F,  -1, -1, 0, 10 },
  {  4, SW_ROLLOVER_I,  -1, -1, 0, 10 },
  {  7, SW_ROLLOVER_R,  -1, -1, 0, 10 },
  {  9, SW_ROLLOVER_E,  -1, -1, 0, 10 },
};
4
Wire solenoids on the Mega
MOSFET driver per coil — millis() pulse management

Each solenoid on the Mega side uses one N-channel MOSFET (IRLZ44N or TIP120). Gate → Mega digital pin, Drain → coil negative, Source → GND. A 1N4007 flyback diode goes across each coil (cathode to +V).

Solenoid pin definitions — MainMega.ino
// Mega solenoid pin assignments
#define PIN_TROUGH       22   // ball trough kicker
#define PIN_KNOCKER      23   // knocker (game over)
#define PIN_UPPER_L      24   // upper left flipper assist
#define PIN_UPPER_R      25   // upper right flipper assist
#define PIN_SLING_LEFT   26   // left slingshot (also Type 2)
#define PIN_SLING_RIGHT  27   // right slingshot
#define PIN_POP_LEFT     28   // left pop bumper
#define PIN_POP_RIGHT    29   // right pop bumper
#define PIN_POP_CENTER   30   // center pop bumper

#define SOL_PULSE_MS    30    // default coil pulse duration
#define TROUGH_PULSE_MS 60    // trough kicker needs longer

// Fire from game code:
fireSolenoid(IDX_TROUGH, TROUGH_PULSE_MS);
fireSolenoid(IDX_KNOCKER);   // uses SOL_PULSE_MS default
5
Flash both boards and verify the bus
Upload Mega first, then each Nano

Upload MainMega.ino to the Mega first. Open Serial Monitor at 115200 baud — you should see [ Micro PinOS ] Main Mega ready. and Styles loaded: 4.

Then upload nano_universal.ino to each Nano (change MY_ADDRESS each time). Trigger a switch manually — the Mega Serial Monitor should show the event being received.

Expected serial output on boot
// Mega Serial Monitor output:
[ Micro PinOS ] Main Mega ready.
Styles loaded: 4

// When a Nano switch fires (e.g. slingshot left):
// Mega receives frame "S0:1\n" on Serial1
// dispatchEvent(0, 1) called
// → currentGame->onShot(SW_SLINGSHOT_LEFT)
// → addScore(50), fireSolenoid(IDX_SLING_LEFT)
// → sendSound("SLING") on Serial2
Additional setup notes
Loading additional notes…

🎉 You're rolling!

Ball is in play. Now explore the deeper features.