Appendix 11A: Arduino Pin Allocations
This appendix lists every physical pin allocated on each of the three ARMAC control Arduinos (AR1, AR2, AR3 - all Arduino UNO R4 WiFi boards), its functional purpose, and any wiring detail relevant to correct assembly or fault-finding. Compiled from the current firmware source (AR1.ino, AR2.ino, AR3.ino) initially set at 16 July 2026, and systematically updated as new allocations are made. It should be treated as the definitive guide to these connections.
Key wiring notes (read this first)
- TestSys/Production detection pins must be permanent GND straps, not momentary buttons. AR1's A3 and AR3's D11 are each sampled once, briefly, at boot to decide whether the board is running on TestSys or production (FireSys) hardware. If either pin is wired to a push-button rather than a solid, permanent wire-to-GND strap, the board will almost always boot into the wrong mode (since the button won't be held during that boot-time sample). On AR3 this was the confirmed root cause of a full day's RS485 instability on 15 July 2026: with D11 not reliably grounded, AR3 wrongly assumed production hardware with a real LCD attached, and its
tickLCD()function hung for 8-18 seconds on every call trying to talk over I2C to a display that was never there, starving the RS485 link. Fixed by physically strapping D11 permanently to GND. - PIN_TEST_BTN (A3 on AR3) is a genuine momentary push-button that triggers scenario testing (short press = start, long press = stop) - completely separate from the TestSys-detection pin above, despite sharing the same pin letter/number in places. Easy to conflate; don't. AR2 has no button of its own - it only receives scenario effects remotely via UDP (SIMCTRL:START/SPEED/STOP) sent from AR3 when that button is pressed.
- AR2 has no TestSys/Production detection pin at all - it doesn't distinguish hardware mode.
- The backup SoftwareSerial link between AR1 and AR3 is wired cross-connected: AR1's TX (A4) -> AR3's RX (A2), and AR3's TX (A1) -> AR1's RX (A5).
- AR1's table is split into Active Connections and Legacy Assignments. Legacy reflects an earlier design where the relays and sensors were all driven to, or sampled at the House over the underground multi-core cable. This led to a lot of potential for disrupted signals due to electrical noise and voltage degradation. So the system was redesigned with AR1 being the communication interface with the outside world, and the relay and sensor work moved to two Arduinos in the pump shed itself (close to sensors and the motorised valves), one (AR2) dealing with sensor input and the other (AR3) with control via relays. Whilst the code was ported from AR1 to AR2 and 3, it was only modified in AR1 to the extent necessary.
AR1 - Remote / Pump & Peripheral Controller
Active Connections
| Pin | Name | Direction | Purpose | Wiring / notes |
| A2 | waterPressureSwitchPin | INPUT | Local water pressure switch | - |
| A3 | JF_TESTSYS_PIN | INPUT_PULLUP | TestSys/Production hardware-mode detection | Must be a permanent strap to GND for TestSys, left floating for Production. Sampled once at boot. D13 was deliberately avoided for this (its onboard LED circuit loads it, giving ~1.9V not 3.3V on INPUT_PULLUP) - an old comment near the detection code still mistakenly referenced D13; fixed 15 July 2026. |
| A4 | PIN_SW_TX | OUTPUT (SoftwareSerial) | Backup RS485 path, transmit | Wired to AR3's RX (A2) |
| A5 | PIN_SW_RX | INPUT (SoftwareSerial) | Backup RS485 path, receive | Wired to AR3's TX (A1) |
| D0/D1 | Serial1 (RS485 primary) | HW UART | Primary RS485 link to AR3 | Board-fixed hardware UART pins (not user-selectable); transceiver is Gravity DFR0845 (USE_GRAVITY_RS485=1, no DE/RE pin needed)
|
Legacy Assignments
These pins are still defined and (mostly) actively driven by firmware, but are no longer connected to anything meaningful - see the key wiring notes above for the two different reasons why.
| Pin | Name | Direction | Purpose | Wiring / notes |
| A0 | TANK_SENSOR_PIN | INPUT (configured, unread) | Tank/water level - defined and pin-configured but never actually read in this firmware; live water level instead arrives via RS485 from AR3 (RX_WATER_LVL). Vestigial. | - |
| D2 | relayPumpOn | OUTPUT | Legacy local pump-ON relay | Defined but never actuated in current firmware - real pump control goes via RS485 to AR3 instead. Held permanently HIGH (off). |
| D3 | relayPumpOff | OUTPUT | Legacy local pump-OFF relay | Same as D2 - defined, never actuated, vestigial. |
| D4 | relayPeripheral1 | OUTPUT, active-low | Peripheral 1 - sprinkler/recirculation valve driver | LOW = pass-through, HIGH = recirc/safe. LOCK forces HIGH. Not physically connected to any downstream peripheral - legacy. |
| D5 | relayPeripheral2 | OUTPUT, active-low | Peripheral 2 - shed cooling disable | Inverted LOCK logic vs. P1/P3/P4: while locked, this relay is held ON (cooling disabled) and OFF commands are blocked, rather than being forced OFF like the others (T43, 12 July 2026). Not physically connected to any downstream peripheral - legacy. |
| D6 | relayPeripheral3 | OUTPUT, active-low | Peripheral 3 - generic relay | Specific downstream device not identified in code comments. LOCK forces OFF. Not physically connected to any downstream peripheral - legacy. |
| D7 | relayPeripheral4 | OUTPUT, active-low | Peripheral 4 - generic relay | Specific downstream device not identified in code comments. LOCK forces OFF. Not physically connected to any downstream peripheral - legacy. |
| D8 | heartbeatPin | dynamic OUTPUT / INPUT_PULLUP | AR1<->AR3 manual/autonomous handoff heartbeat | Switches direction depending on mode (OUTPUT while AR1 holds manual control, INPUT_PULLUP when relinquishing to AR3's autonomous mode), but AR1 never reads this pin back and AR3 has no corresponding input pin wired to it. The heartbeat value AR3 actually acts on travels entirely inside the RS485 STAT frame's HB: field (a software variable), not this physical pin. Superseded by the protocol-level heartbeat - legacy. |
| D9 | tempSensor1Pin | not a live pin | Logical ID only, routes to RX_INT_TEMP (RS485 telemetry) | No pinMode/read - not physically wired as an input on AR1. |
| D10 | tempSensor2Pin | not a live pin | Logical ID only, routes to RX_EXT_TEMP (RS485 telemetry) | No pinMode/read - not physically wired as an input on AR1. |
| D11 | directPumpPin | OUTPUT, pulsed | "Direct Pump Start" override | Pulses HIGH up to 3s (or until oil pressure confirmed) to directly energise the pump-start circuit, bypassing the normal AR3-mediated RS485 command path. Blocked while locked. Not physically connected to any downstream peripheral - legacy. |
| D12 | (DE/RE, unused) | - | MAX485-style transceiver direction control | Not wired in the current build - only relevant if switching away from the Gravity DFR0845 transceiver. |
AR2 - Sensor Aggregator
| Pin | Name | Direction | Purpose | Wiring / notes |
| A0 | TANK_SENSOR_PIN | INPUT (analog) | Tank/water level sensor | Actively read via analogRead() on this board (unlike the vestigial copy of the same pin name on AR1).
|
| A1 | WATER_PRESS_PIN_ANALOG | INPUT (analog) | Water pressure, 0-5V direct analog tap on the SFS node | Comment notes this was "moved from D11" at some point. |
| A2 | BATTERY_PIN | INPUT (analog) | System battery voltage sense | - |
| A3 | DIESEL_LEVEL_PIN | INPUT (analog) | Level of diesel fuel in pump tank | - |
| D2 | FLOW_OUT_PIN | INPUT_PULLUP, interrupt (FALLING) | DN50 turbine flow sensor on the pump discharge line (to sprinklers) | Blue wire. 8ms debounce. K_OUT_PPL = 10.33 pulses/L (calibrated 13 July 2026 against a 290 L/min reference, post timing-bug fix). |
| D3 | FLOW_IN_PIN | INPUT_PULLUP, interrupt (FALLING) | DN15 turbine flow sensor on the mains in-feed to tank | White wire. 8ms debounce. K_IN_PPL = 450.0 pulses/L. |
| D6 | TEMP_ONEWIRE_PIN | 1-Wire bus | Shared bus for three address-locked DS18B20 temperature sensors (internal, external, external-2) | Grey wire. |
| D10 | OIL_PRESS_PIN_DIGITAL | INPUT_PULLUP | Oil pressure switch, via PC817 optocoupler output | Active-LOW (LOW = pressure present / engine running). |
| D12 | EMBER_PIN | INPUT_PULLUP | Ember detector, digital | Yellow wire. Active-LOW assumed. |
AR2 has no RS485/SoftwareSerial pins - it communicates with AR3 over its own hosted WiFi access point via UDP (port 5000), not the RS485 bus used between AR1 and AR3. AR2 has no TestSys/Production detection pin.
AR3 - Autonomous Control Module ("TAR3")
| Pin | Name | Direction | Purpose | Wiring / notes |
| A1 | PIN_SW_TX | OUTPUT (SoftwareSerial) | Backup RS485 path, transmit | Wired to AR1's RX (A5) |
| A2 | PIN_SW_RX | INPUT (SoftwareSerial) | Backup RS485 path, receive | Wired to AR1's TX (A4). Documented hardware caveat: this pin's interrupt can conflict with the SPI bus used by the onboard WiFi module, so it is dynamically enabled only after the primary RS485 link has been silent for 10s, and disabled again once primary resumes. |
| A3 | PIN_TEST_BTN | INPUT_PULLUP | Momentary scenario-test push-button | Short press starts a test scenario, long press (>=1.2s) stops it. Not the same pin as JF_TESTSYS_PIN (D11) below - do not conflate. |
| D0/D1 | Serial1 (RS485 primary) | HW UART | Primary RS485 link to AR1 | Board-fixed hardware UART pins. |
| D2 | PIN_COIL_ON | OUTPUT, pulsed, active-low | Pump latch-relay "ON" coil (production) / pump-OFF-state LED indicator (TestSys, no relay hardware fitted) | Subject to FS_POLARITY_INVERT, which can swap which physical coil fires for a given logical pump request.
|
| D3 | PIN_COIL_OFF | OUTPUT, pulsed, active-low | Pump latch-relay "OFF" coil (production) / pump-ON-state LED indicator (TestSys) | Same polarity-invert caveat as D2. |
| D4 | PIN_P1 | OUTPUT, active-low | Peripheral 1 - recirculation valve/line | LOCK forces OFF. State read back for telemetry/LCD. |
| D5 | PIN_P2 | OUTPUT, active-low | Peripheral 2 - shed cooling | Exempt from LOCK (thermostat-controlled). State read back. |
| D6 | PIN_P3 | OUTPUT, active-low | Peripheral 3 - high-flow sprinkler select | LOCK forces OFF. State read back. |
| D7 | PIN_P4 | OUTPUT, active-low | Peripheral 4 - gel injection | LOCK forces OFF. State read back. |
| D11 | JF_TESTSYS_PIN | INPUT_PULLUP | TestSys/FireSys hardware-mode detection | Must be a permanent strap to GND for TestSys, left floating for Production (LCD present). Sampled once at boot. See the key wiring note at the top of this appendix - a marginal/non-permanent connection here caused a significant RS485 fault on 15 July 2026. |
| I2C (SDA/SCL) | LCD (0x27, 16x2) | I2C bus | Status display | Board-fixed hardware I2C pins, not user-configurable. Only actually initialised and driven when JF_isTestSys is false (production/FireSys) - deliberately skipped on TestSys, since no LCD is fitted there. |
<< | | >> |Table of Contents>
