# Property of PMA Electrical Solutions, LLC. # # Danfoss VLT AQUA Drive FC 202 — the most common drive in East Coast municipal # water and wastewater. # # Corrected against Danfoss MG92B102 (Modbus RTU), MG20OB02 (FC202 programming # guide, pp. 152, 266-268, 286-288) and MG20N622. An earlier revision claimed # every FC parameter is 32-bit; that is false, and the wrong widths broke the # running-state interlock by testing a bit against the wrong half of a spliced # 32-bit read. # # Wiring: terminal 68 (+P), 69 (-N). Terminal 61 is an RC-filtered screen point, # connect only if you have EMC trouble. # # Drive-side setup: 8-30 Protocol = Modbus RTU, 8-31 Address, 8-32 Baud Rate, # 8-33 Parity. For bus control also set 8-01 Control Site and 8-02 Control Word # Source = the FC port. # # ADDRESSING: register = parameter_number * 10 - 1, where par 16-12 is the # integer 1612, so 1612 * 10 - 1 = 16119. Confirmed as the true 0-based wire # address by the MG92B102 worked example (par 3-03 -> 0x0BD5 = 3029). # # WIDTH IS PER PARAMETER — see the `words` key on each point below. Reading a # 16-bit parameter as 2 registers splices in the neighbouring parameter. name = "Danfoss VLT AQUA FC 202" vendor = "Danfoss" device_type = "vfd" verified = false probe_register = 16029 # 16-03 status word [connection] summary = "Connect to the built-in FC-port RS-485 terminals 68 and 69; no option card is required." warnings = ["Isolate the drive and verify the DC link is discharged before opening the control cover.", "Keep the serial cable away from motor and mains conductors."] [[connection.methods]] id = "built_in_rs485" title = "Built-in RS-485 (68/69)" transport = "serial" hardware = "built_in" port = "Control terminals 68 (+P), 69 (-N), optional 61 screen/reference" connector = "FC-port control terminal plug" adapter = "Isolated USB-to-RS-485 adapter" cable = "Shielded twisted-pair RS-485 cable" parts = ["Small insulated screwdriver", "120 ohm end termination when required"] wiring = [{ adapter = "D+ / B+", device = "68 (+P)", signal = "RS-485 positive" }, { adapter = "D- / A-", device = "69 (-N)", signal = "RS-485 negative" }, { adapter = "COM/GND", device = "61", signal = "Optional RC-filtered screen point", required = false }] steps = ["Isolate power and locate terminals 68, 69, and 61 on the control terminal strip.", "Land the shielded pair on 68/69 with the shown polarity.", "Use 61 only for the documented screen/reference need and terminate only at a bus end.", "Close the cover, restore power, and connect/select the USB-to-RS-485 adapter."] setup = ["Set 8-30 to Modbus RTU, then set 8-31 Address, 8-32 Baud Rate, and 8-33 Parity.", "For control, set 8-01 Control Site and 8-02 Control Word Source to the FC port."] warnings = ["The drive can communicate while ignoring control words if the control source remains local or terminal-based."] source = "Danfoss MG92B102, pp. 8-10 and 30; MG20OB02, p. 152 (existing profile citation)" [serial] baudrate = 9600 parity = "E" stopbits = 1 [monitor] # --- 16-bit parameters (words = 1) --- control_word = { address = 15999 } # 16-00 reference_pct = { address = 16019, signed = true, scale = 0.1, unit = "%" } # 16-02 # 16-03 status word. Bit 2 = 1 means ENABLED (0 = coasting); bit 10 = 1 means # WITHIN the frequency limits (0 = outside) — both were inverted previously. # # Bits 4 and 6 were also MISLABELLED. MG20N622 Table 3.46 (printed p. 94) for # this drive gives bit 4 = "Error (no trip)" and bit 6 = "Trip lock"; the file # had bit 4 = TripLock and bit 6 = TripLockRepeat, a name that appears in no # Danfoss table. That inverts the operator's information in the worst # direction: a trip lock clears only by power cycle, so "TripLock" shown on # bit 4 — a resettable non-tripping error — invites hammering the reset # sequence, while the real trip lock on bit 6 showed nothing at all. Bits # 13/14/15 now carry the book's own wording too. The FC 102, FC 103 and FC 302 # tables are identical to this one, verified separately in each book. status_word = { address = 16029, bits = { 0 = "CtrlReady", 1 = "DriveReady", 2 = "NotCoasting", 3 = "Trip", 4 = "ErrorNoTrip", 6 = "TripLock", 7 = "Warning", 8 = "SpeedEqRef", 9 = "BusControl", 10 = "WithinFreqLimits", 11 = "Running", 12 = "DriveOkStoppedAutoStart", 13 = "VoltageExceeded", 14 = "TorqueExceeded", 15 = "TimerExceeded" } } motor_voltage = { address = 16119, scale = 0.1, unit = "V" } # 16-12 output_frequency = { address = 16129, scale = 0.1, unit = "Hz" } # 16-13 motor_thermal = { address = 16179, unit = "%" } # 16-18 dc_link_voltage = { address = 16299, unit = "V" } # 16-30 heatsink_temp = { address = 16339, unit = "C" } # 16-34 # --- 32-bit parameters (words = 2) --- power_kw = { address = 16099, words = 2, scale = 0.01, unit = "kW" } # 16-10 motor_current = { address = 16139, words = 2, scale = 0.01, unit = "A" } # 16-14 # 16-16 is torque in Nm (0.1 Nm/count), NOT percent. Percent is 16-22. torque_nm = { address = 16159, words = 2, signed = true, scale = 0.1, unit = "Nm" } # 16-22 is Int16 — ONE register. It shipped as words = 2, which read holding # register 16220 as the high word plus 16221 (an unpopulated array slot) as the # low word, so torque read roughly 65536x high or the request NAKed. Confirmed # Int16, conversion index 0, in four separate books: MG20OB02 p. 267 (this # drive), MG11CE02 p. 236 and AU430028034214en-001901 p. 410 (FC 102), and # MG16H202 p. 208 (FC 103). 16-16 and 16-17 below really are Int32 and stay at # words = 2 — the width genuinely varies per parameter on this platform. torque_pct = { address = 16219, signed = true, unit = "%" } # 16-22, Int16 motor_speed = { address = 16169, words = 2, signed = true, unit = "rpm" } # 16-17 [control] command_register = 49999 speed_register = 50009 # Reference is % of max, NOT Hz. raw = value / scale, so 100% -> 16384. speed_scale = 0.006103515625 speed_unit = "%" max_ref = 100.0 step_delay = 0.05 stop = [1084] # 0x043C run_fwd = [1084, 1148] # 0x043C then 0x047C reset = [1212, 1084] # 0x04BC rising edge, then back to stop # run_rev is deliberately absent. Control word bit 15 reverses ONLY when 8-54 # Reversing Select is set to serial communication; the FC202 default is # [0] Digital input, so a "reverse" command silently runs the motor FORWARD. # Set 8-54 appropriately and add run_rev = [1084, 33916] if you need it. # Par 8-04 control word timeout defaults to Off on common firmware, so a run # command followed by silence leaves the motor running with no master attached. [control.watchdog] interval_ms = 500 fault = "control word timeout (8-04, if configured)" [running_check] register = 16029 # 16-03 status word, 16-bit bit = 11 # 16-90 Alarm Word is a 32-bit BITFIELD, not an enum: several bits can be set # at once, so there is no code table to look up. # # 16-92 Warning Word is NOT included as history: despite the similar name its # bit layout DIVERGES from the alarm word at bits 12, 13, 15, 17, 19-21, 25-29 # and 31 (bit 12 is "DC voltage low" warning vs "short circuit" alarm), so # decoding it with these names would mislabel every one of those. [faults] register = 16899 # 16-90 alarm word words = 2 bitfield = true bits = { 0 = "BrakeCheck", 1 = "HeatsinkTemp", 2 = "EarthFault", 3 = "CtrlCardOverTemp", 4 = "CtrlWordTimeout", 5 = "OverCurrent", 6 = "TorqueLimit", 7 = "MotorThermistor", 8 = "MotorETR_OverTemp", 9 = "InverterOverloaded", 10 = "DCUnderVoltage", 11 = "DCOverVoltage", 12 = "ShortCircuit", 13 = "InrushFault", 14 = "MainsPhaseLoss", 15 = "AMA_NotOK", 16 = "LiveZeroError", 17 = "InternalFault", 18 = "BrakeOverload", 19 = "U_PhaseLoss", 20 = "V_PhaseLoss", 21 = "W_PhaseLoss", 22 = "FieldbusFault", 23 = "Supply24V_Low", 24 = "MainsFailure", 25 = "Supply1V8_Low", 26 = "BrakeResistorShort", 27 = "BrakeChopperFault", 28 = "OptionChange", 29 = "DriveInitialized", 30 = "SafeStop", 31 = "MechBrakeLow" } # 16-36 Inv. Nom. Current, Uint32, conversion index -2 (MG20OB02 p. 268) — the # same register the FC 102/103/302 profiles use. Without this section the # restore frame-size guard returns Unverifiable and waves every clone through, # on the drive this file's own header calls the most common in East Coast # municipal water and wastewater. Uint32 means words = 2: read as one word it # returns the high half, which is 0 on any frame under 655.35 A and would then # compare equal to every saved source rating. [rating] register = 16359 words = 2 scale = 0.01 unit = "A" label = "Inverter nominal current"