# Property of PMA Electrical Solutions, LLC. # # AutomationDirect IronHorse ACM series AC drive (1-phase 120/230 VAC input, # 1/8-3 hp), BUILT-IN RS-485 Modbus RTU on the RJ-45 port. The same RJ-45 also # serves the ACM-KPD remote keypad and VFD Suite; only one master at a time. # # Source: IH ACM Series AC Drive User Manual, 1st Edition - 03/23/2026 # (cdn.automationdirect.com/static/manuals/acmdrives/acmmanual.pdf). # CM group comm parameters ............. ch.5 pp. 5-8 to 5-9 # Command + frequency source ........... ch.5 p. 5-9 # Command-loss behaviour (Pr.12/13) .... ch.5 p. 5-9 # Total memory map ..................... ch.5 p. 5-10 # Modbus-RTU example ................... ch.5 p. 5-14 # Compatible common area (0h0001-001E).. ch.5 pp. 5-14 to 5-17 # Parameter address tables ............. ch.5 pp. 5-18 onward # Trip mnemonics ....................... ch.6 pp. 6-7 to 6-9 # Pr.12 default (0) .................... ch.4 Pr group summary (0h190C) # # Claims ONLY the IronHorse ACM. Its register set is NOT the ACG's or ACN's: # the ACM has no drive expansion area (no 0h0300 monitoring, no 0h0380 control # — memory map p. 5-10), and its control word bits are one-shot command bits, # not the ACG's run/direction pair. Do not cross-apply either way. # # --------------------------------------------------------------------------- # ADDRESSING — the manual's hex "Comm. Address" is NOT the wire address. # # 0-based protocol address = (manual hex Comm. Address) - 1 # # From this manual: the p. 5-14 worked example writes Acc/Dec time (Comm. # Address 0x1103/0x1104) with Starting Address 0x1102, labelled "Starting # Address -1 (0x1103-1)". Corroborated by the parameter table (p. 5-18), whose # "ModbusRTU Decimal" column is the 1-based 4xxxx reference — dr.20 hex 1114 # is listed as 44372, i.e. wire = 44372-40001 = 0x1113 = hex-1 — and by the # common area table starting at 0h0001 with no 0h0000 row. # # The ACM has no Ethernet option, so there is only one address column and no # RTU/TCP divergence to confuse it with (unlike the ACG and ACN). # # FALSIFY IN ONE READ on the first bench unit: read 0x0009 (0h000A, output # frequency) and 0x000A. Under this profile 0x0009 tracks the display in # 0.01 Hz. If instead 0x000A tracks it, the whole map is off by one and every # address here must be raised by 1. # # vfd-core reads HOLDING REGISTERS (FC03) only; everything below is reachable # by FC03. # --------------------------------------------------------------------------- # # Drive-side setup, or the drive ACKs writes and ignores them: # CM.1 station ID (1-250), CM.2 = 0 Modbus-RTU, CM.3 baud (3 = 9600), # CM.4 = 0 (8N1), CM.5 response delay ms; # drv = 3 (RS-485 comm) -> command source is the RS-485 port # Frq = 9 (RS-485 comm) -> frequency source is the RS-485 port # NOTE the Frq value differs from the ACG/ACN, which use 6. # # Common-area writes do NOT survive a power cycle (p. 5-10); values written # into the individual parameter groups do. name = "AutomationDirect IronHorse ACM" vendor = "AutomationDirect" device_type = "vfd" verified = false probe_register = 0x0000 # 0h0001 Drive capacity, readable whenever the port is alive [connection] summary = "The ACM has one built-in Modbus RTU path on its RJ45; it has no Ethernet option." warnings = [] [[connection.methods]] id = "rj45_rs485" title = "Built-in RJ45 Modbus RTU" transport = "serial" hardware = "built_in" port = "ACM RJ45 communications connector" connector = "RJ45 wired as RS-485, not Ethernet" adapter = "Isolated USB-to-RS-485 adapter, 2-wire half-duplex" cable = "18 AWG shielded twisted-pair RS-485 cable; Belden 9842 or AutomationDirect L19954 equivalent" parts = ["Isolated two-wire RS-485 adapter", "18 AWG shielded twisted-pair RS-485 cable; Belden 9842 or AutomationDirect L19954 equivalent", "Field-terminated modular plug or documented breakout adapter"] steps = ["Lock out line and control power, wait the vendor-specified discharge time, and verify the DC bus is de-energized before opening a cover or landing conductors.", "Land the positive and negative data conductors exactly as shown; connect the cable shield or signal common only where the method identifies it.", "Route the communications cable away from motor and mains conductors. Terminate the two physical ends of a long multidrop trunk only.", "Restore control power with the motor area clear, configure the drive from its keypad, then verify identity and read-only monitor data before enabling remote control."] setup = ["Set CM.1=node, CM.2=0 Modbus, CM.3=3 for 9600, CM.4=0 for 8N1, drv=3, and Frq=9."] warnings = ["A modular communications jack is not automatically Ethernet. Never connect it to a LAN switch unless this guide explicitly identifies a Modbus TCP method.", "RS-485 A/B naming is not consistent between manufacturers. Follow the + and - mapping shown here.", "This RJ45 is shared with the remote keypad/software. Only one master may use it at a time.", "The manual also documents a fixed 19200 8N1 keypad/software mode; ensure the drive is in configurable Modbus mode before discovery."] source = "AutomationDirect IronHorse ACM User Manual, 1st Ed. 03/23/2026, chapter 5 pp. 5-2 to 5-6 (RJ45 pins 1/8/7, 18 AWG STP and setup)" [[connection.methods.wiring]] adapter = "Adapter D+ / +" device = "RJ45 pin 1 (S+)" signal = "RS-485 data positive" required = true [[connection.methods.wiring]] adapter = "Adapter D- / -" device = "RJ45 pin 8 (S-)" signal = "RS-485 data negative" required = true [[connection.methods.wiring]] adapter = "Adapter signal ground / shield" device = "RJ45 pin 7 (SG)" signal = "Signal reference or shield drain" required = false [serial] baudrate = 9600 # CM.3 default 3 parity = "N" # CM.4 default 0 = D8/PN/S1 stopbits = 1 [monitor] # 0h000E Operation status (p. 5-15). Genuine flags, unlike the ACG's 0h0305. status_word = { address = 0x000D, bits = { 0 = "STOPPED", 1 = "RUNNING_FWD", 2 = "RUNNING_REV", 3 = "FAULT_TRIP", 4 = "ACCELERATING", 5 = "DECELERATING", 6 = "SPEED_REACHED", 7 = "DC_BRAKING", 8 = "STOPPING", 10 = "BRAKE_RELEASE", 11 = "FWD_CMD", 12 = "REV_CMD" } } output_frequency = { address = 0x0009, scale = 0.01, unit = "Hz" } # 0h000A motor_current = { address = 0x0008, scale = 0.1, unit = "A" } # 0h0009 output_voltage = { address = 0x000A, unit = "V" } # 0h000B dc_voltage = { address = 0x000B, unit = "V" } # 0h000C output_power = { address = 0x000C, scale = 0.1, unit = "kW" } # 0h000D motor_rpm = { address = 0x0014, unit = "rpm" } # 0h0015 input_terminals = { address = 0x000F, bits = { 0 = "P1", 1 = "P2", 2 = "P3", 3 = "P4", 4 = "P5" } } # 0h0010 output_relays = { address = 0x0010, bits = { 4 = "3ABC" } } # 0h0011 # 0h001D "Fault trip information -B" (p. 5-16). The last row of that table # prints "COM" with no legible bit index in the source PDF, so it is omitted # rather than guessed at bit 0. fault_trip_b = { address = 0x001C, bits = { 2 = "NTC_OPEN", 3 = "REEP", 4 = "OCT_OVERCURRENT", 5 = "NBR_BRAKE", 9 = "ROT_RELAY_OPEN" } } # 0h0006 Operation command (p. 5-15). B0 Stop(S), B1 Forward(F), B2 Reverse(R), # B3 Fault Reset, B4 Emergency stop — one-shot COMMAND bits, not a level, so # each action is a single distinct value. Direction is a command bit, not the # sign of the reference, so run_rev is real and is included. # The reset value 0x0008 carries neither B1 nor B2: it cannot start a motor. # Reading this register back also returns the drive's command source in # B5-B15 (3 = Built-in 485), which is the cheapest fieldbus-enable check. [control] command_register = 0x0005 # 0h0006 Operation command speed_register = 0x0004 # 0h0005 Target frequency speed_scale = 0.01 # 0.01 Hz per count — fieldbus scale, p. 5-14 speed_unit = "Hz" max_ref = 400.0 # FrM Maximum frequency range is 40.00-400.00 Hz step_delay = 0.05 stop = [0x0001] run_fwd = [0x0002] run_rev = [0x0004] reset = [0x0008, 0x0001] # Pr.12 Lost Cmd Mode / Pr.13 Lost Cmd Time (p. 5-9). AT FACTORY DEFAULT THIS # DRIVE DOES NOT STOP ON COMM LOSS: Pr.12 defaults to 0, which ch.5 calls # "None — the speed command immediately becomes the operation frequency # without any protection function" (the ch.4 summary labels the same 0 as # "Hold Output"; the labels disagree, the behaviour does not — the motor keeps # running). A Lost Command WARNING is raised even at Pr.12 = 0 (p. 6-9). Set # Pr.12 = 1 (Free-Run) or 2 (Dec) on any bus where silence must stop the # motor. Pr.13 defaults to 1.0 s (range 0.1-120 s); if Pr.13 is shortened # below 1 s, shorten interval_ms with it. [control.watchdog] interval_ms = 500 fault = "Lost Command (Pr.12 Lost Cmd Mode, Pr.13 Lost Cmd Time)" # No [running_check]. 0h000E splits running across B1 (forward) and B2 # (reverse) and offers no combined bit; B0 is STOPPED, i.e. inverted, and the # schema has no invert. Asserting B1 alone would report STOPPED while the # motor runs in reverse, which would let a parameter restore through on a # turning motor. RunState::Unknown blocks that restore; a wrong bit would not. # On a site that never reverses, and only there, add: # [running_check] # register = 0x000D # bit = 1 # 0h000F Fault trip information (p. 5-16). A BITFIELD: several trips can be # live at once, so there is no code to look up. B0 and B9 are printed as # Reserved. Names expanded from the ch.6 trip tables (pp. 6-7 to 6-8) where # ch.6 lists the mnemonic; POT, EEP, COL and EST appear only in the bit table, # so they keep their bare mnemonics rather than an invented expansion. # NOT SOURCED: no register-mapped trip history — the ACM keeps its last five # trips at Pr.91-95, which the manual describes as keypad reads and does not # publish a common-area address for. [faults] register = 0x000E bitfield = true bits = { 1 = "OVT_OVERVOLTAGE", 2 = "EXT_A_EXTERNAL_TRIP", 3 = "EST", 4 = "COL", 5 = "GFT_GROUND_FAULT", 6 = "OHT_OVERHEAT", 7 = "ETH_E_THERMAL", 8 = "OLT_OVERLOAD", 10 = "EXT_B_EXTERNAL_TRIP", 11 = "EEP", 12 = "FAN_TRIP", 13 = "POT", 14 = "IOLT_DRIVE_OVERLOAD", 15 = "LVT_LOW_VOLTAGE" } # 0h0001 Drive capacity. A coded value whose meaning depends on the input # voltage class (p. 5-14: 230 V 0000 = 0.1 kW ... 0005 = 2.2 kW; 120 V 0001 = # 0.2 kW ... 0003 = 0.75 kW), not a scaled number — useful as an identity to # compare before a restore, which is all [rating] is for. Pair it with 0h0002 # (wire 0x0001, 0 = 230 V, 3 = 110 V) to disambiguate. [rating] register = 0x0000 label = "drive capacity code (0h0001)" # No [parameters]. The manual publishes a complete per-parameter address table # (pp. 5-18 onward), but the CM group (0h1700) sits inside it: a restore that # sweeps a whole group rewrites the station ID and baud rate and drops the bus # mid-restore. Transcribe the wanted groups deliberately, excluding CM, before # enabling clone/restore on this drive.