Skip to content

Instantly share code, notes, and snippets.

@errkk
Last active December 26, 2016 19:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save errkk/7eed849017298a82de2a248e249356a6 to your computer and use it in GitHub Desktop.
Save errkk/7eed849017298a82de2a248e249356a6 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
#
require 'rmodbus'
status_labels = [
['Drive not ready', 'Ready for operation (READY)'],
['Stop', 'Running operation message (RUN)'],
['Clockwise rotating field (FWD)', 'Anticlockwise rotating field (REV)'],
['No fault', 'Fault detected (FAULT)'],
['No warning', 'Warning active (ALARM)'],
['Acceleration ramp', 'Frequency actual value equals setpoint value definition'],
[nil, 'Zero speed'],
['Speed control deactivated', 'Speed control activated'],
]
control_states = [
[:stop, :operation],
[:clockwise, :anticlockwise],
[nil, :reset_error],
[:per_setting, :free_coasting],
[:per_setting, :ramp],
[nil, 'Overwrite acceleration/deceleration ramps to 0.1 s'],
[nil, 'Block setpoint (speed not variable)'],
[nil, 'Overwrite setpoint with 0'],
[nil, 'Control level = Fieldbus'],
[nil, 'Setpoint input = Fieldbus'],
]
CONTROL_WORD = 2000
STATUS_WORD = 2100
MOTOR_STATUS_REGISTERS = 2102..2110
SPEED_REGISTER = 2002
BIT_NUMBER_POWER = 0
BIT_NUMBER_DIRECTION = 1
class Garage < ModBus::TCPClient
def initialize
super '192.168.0.7', 502
puts temp?
end
def temp?
with_thermometer do |slave|
slave.input_registers[1].first / 10.0
end
end
def status?
with_inverter do |slave|
status_word = slave.holding_registers[STATUS_WORD].first
map_labels_to_word status_word, status_labels
end
end
def motor?
with_inverter do |slave|
keys = [:actual_speed, :frequency, :speed, :current, :torque, :power, :voltage, :dc_link]
speed = slave.holding_registers[MOTOR_STATUS_REGISTERS]
Hash[keys.zip speed]
end
end
def on!
set! 1, BIT_NUMBER_POWER
end
def off!
set! 0, BIT_NUMBER_POWER
end
def fwd
set! 0, BIT_NUMBER_DIRECTION
end
def rev
set! 1, BIT_NUMBER_DIRECTION
end
def speed!(percent)
value = percent * 100
with_inverter do |slave|
slave.holding_registers[SPEED_REGISTER] = value
end
end
def speed?
with_inverter do |slave|
slave.holding_registers[SPEED_REGISTER]
end
end
private
def with_inverter
with_slave 3 do |slave|
yield(slave)
end
rescue ModBus::Errors::ModBusTimeout
puts "Soz, Contacting inverter timeed out"
end
def with_thermometer
with_slave 49 do |slave|
yield(slave)
end
rescue ModBus::Errors::ModBusTimeout
puts "Soz, Contacting thermometer timeed out"
end
def wordsmash
# Connect to slave, get status word, yield it to the block
# and then take back the return value and set it to the register
with_inverter do |slave|
# Get current word by reading register
word = slave.holding_registers[CONTROL_WORD]
# Do the block
# Set the result to the register
slave.holding_registers[CONTROL_WORD] = yield(word)
end
end
def toggle!(bit_number)
# Shift a 1 across to the bit we want to operate on
mask = 1 << bit_number
wordsmash do |word|
# Exclusive or, so swap only the bit forwhich this mask lines up
# Manipulates only the bit that we're doing stuff for
word ^= mask
end
end
def set!(value, bit_number)
# Set a single bit of the control word to on or off
# Shift a 1 across to the bit we want to operate on
mask = 1 << bit_number
wordsmash do |word|
# Manipulates only the bit that we're doing stuff for
if value > 0
# And or for on
word |= mask
else
# And not for off
word = word &~ mask
end
end
end
end
g = Garage.new
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment