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.
Legacy Assignments thus means either the pin is no longer actually used by current firmware logic (e.g. AR1's pump relays, D2/D3 - real pump control now goes to AR3 over RS485), or the firmware still actively drives it but it is no longer physically connected to any downstream peripheral (AR1's four peripheral relays D4-D7, and AR1's Direct Pump Start override D11 - the code still runs this logic on each pin, but nothing is currently wired to receive the output). Whilst it would be neat to cut out this legacy code running on AR1 it does no harm, and experience tells me that cutting it out would require a whole test period to make sure it then still worked correctly.

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>


Page last modified on August 21, 2026, at 04:48 am