Skip to content

Instantly share code, notes, and snippets.

@kyoma-takahashi
Created October 3, 2015 00:32
Show Gist options
  • Select an option

  • Save kyoma-takahashi/d04902f4a1a0f692bed0 to your computer and use it in GitHub Desktop.

Select an option

Save kyoma-takahashi/d04902f4a1a0f692bed0 to your computer and use it in GitHub Desktop.
#!/usr/bin/ruby
SERIAL_DEVICE = '/dev/tty.usbserial-FTXYGGG9'
# On Windows, like SERIAL_DEVICE = 'COM5'
require 'rubygems'
require 'rmodbus'
require 'serialport'
# To prepare,
# $ gem environment
# $ gem install -V rmodbus serialport
# To clean-up,
# $ gem uninstall gserver rmodbus serialport
# Serial constants according to the master configuration
BAUD_RATE = 19_200
SERVER_ADDRESS = 50
SERIAL_OPTS = {
:data_bit => 8,
:stop_bits => 1,
:parity => SerialPort::EVEN}
# FYI, default :read_timeout is 100 in SerialPort lib
# Modbus constants
HOLDING_REGISTER_OFFSET = 40001
IDX_WATCHDOG_COUNTER_M2S = 40501 - HOLDING_REGISTER_OFFSET
IDX_WATCHDOG_COUNTER_S2M = 40001 - HOLDING_REGISTER_OFFSET
WATCHDOG_COUNTER_MAX = 2 ** 8
IDX_DATA = 40510 - HOLDING_REGISTER_OFFSET
DATA_COUNTS = 28
INVALID_LENGTH_M2S = -1
LENGTH_S2M = 0x64
# Constants for this implementation
DUMMY_BYTE = 0x00
ModBus::RTUClient.connect(SERIAL_DEVICE, BAUD_RATE, SERIAL_OPTS) do |client|
client.debug = true
client.read_retries = Float::INFINITY
client.with_slave(SERVER_ADDRESS) do |slave|
time_before = nil
master_watchdog_counter = -1
slave_watchdog_counter = nil
loop do
time_now = Time.now.utc
if time_before && time_before.strftime('%s') == time_now.strftime('%s')
sleep(0.001)
next
end
time_before = time_now
master_watchdog_counter = (master_watchdog_counter + 1) % WATCHDOG_COUNTER_MAX
slave.write_multiple_registers(IDX_WATCHDOG_COUNTER_M2S,
[master_watchdog_counter,
Array.new(IDX_DATA - IDX_WATCHDOG_COUNTER_M2S - 1, DUMMY_BYTE),
[time_now.to_a.slice(0, 8),
Array.new(DATA_COUNTS - 8, -1.23456789)].
flatten.collect{|i| [i.to_f].from_32f.reverse}.
flatten[0, DATA_COUNTS * 2 + [INVALID_LENGTH_M2S, 0].sort.first],
if INVALID_LENGTH_M2S > 0
Array.new(INVALID_LENGTH_M2S, DUMMY_BYTE)
else
[]
end
].flatten)
# Sending s, min, h, day of month, month, year, day of week, day of year and 0
# for test
c = slave.read_holding_registers(IDX_WATCHDOG_COUNTER_S2M, LENGTH_S2M).first
if c == slave_watchdog_counter
warn "#{time_now.to_s} Received the same watchdog counter: #{slave_watchdog_counter}"
end
slave_watchdog_counter = c
$stderr.puts [time_now.to_s, slave_watchdog_counter].join(',')
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment