Skip to content
/ baud Public
forked from samuelventura/baud

Elixir Serial Port with Modbus RTU support

License

Notifications You must be signed in to change notification settings

evnu/baud

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

89 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

baud

Elixir Serial Port with Modbus RTU.

Installation and Usage

  1. Add baud to your list of dependencies in mix.exs:
def deps do
  [{:baud, "~> 0.5.4"}]
end
  1. Enumerate your serial ports.
["COM1", "ttyUSB0", "cu.usbserial-FTVFV143"] = Baud.Enum.list()
  1. Interact with your serial port.
tty = case :os.type() do
  {:unix, :darwin} -> "cu.usbserial-FTYHQD9MA"
  {:unix, :linux} -> "ttyUSB0"
  {:win32, :nt} -> "COM5"
end

#Try this with a loopback
{:ok, pid} = Baud.start_link([device: tty])

Baud.write pid, "01234\n56789\n98765\n43210"
{:ok, "01234\n"} = Baud.readln pid
{:ok, "56789\n"} = Baud.readln pid
{:ok, "98765\n"} = Baud.readln pid
{:to, "43210"} = Baud.readln pid

Baud.write pid, "01234\r56789\r98765\r43210"
{:ok, "01234\r"} = Baud.readch pid, 0x0d
{:ok, "56789\r"} = Baud.readch pid, 0x0d
{:ok, "98765\r"} = Baud.readch pid, 0x0d
{:to, "43210"} = Baud.readch pid, 0x0d

Baud.write pid, "01234\n56789\n98765\n43210"
{:ok, "01234\n"} = Baud.readn pid, 6
{:ok, "56789\n"} = Baud.readn pid, 6
{:ok, "98765\n"} = Baud.readn pid, 6
{:to, "43210"} = Baud.readn pid, 6

Baud.write pid, "01234\n"
Baud.write pid, "56789\n"
Baud.write pid, "98765\n"
Baud.write pid, "43210"
:timer.sleep 100
{:ok, "01234\n56789\n98765\n43210"} = Baud.readall pid
  1. Interact with your RTU devices.
alias Modbus.Rtu.Master

tty = case :os.type() do
  {:unix, :darwin} -> "cu.usbserial-FTVFV143"
  {:unix, :linux} -> "ttyUSB0"
  {:win32, :nt} -> "COM5"
end

#rs485 usb adapter to modport
{:ok, pid} = Master.start_link([device: tty, speed: 57600])
#force 0 to coil at slave 1 address 3000
:ok = Master.exec pid, {:fc, 1, 3000, 0}
#read 0 from coil at slave 1 address 3000
{:ok, [0]} = Master.exec pid, {:rc, 1, 3000, 1}
#force 10 to coils at slave 1 address 3000 to 3001
:ok = Master.exec pid, {:fc, 1, 3000, [1, 0]}
#read 10 from coils at slave 1 address 3000 to 3001
{:ok, [1, 0]} = Master.exec pid, {:rc, 1, 3000, 2}
#preset 55AA to holding register at slave 1 address 3300
:ok = Master.exec pid, {:phr, 1, 3300, 0x55AA}
#read 55AA from holding register at slave 1 address 3300 to 3301
{:ok, [0x55AA]} = Master.exec pid, {:rhr, 1, 3300, 1}

Development

  • Testing requires two null modem serial ports configured in test/test_helper.exs

Windows

Install Visual C++ 2015 Build Tools by one of the following methods:

From the Windows run command launch cmd /K c:\Users\samuel\Documents\github\baud\setenv.bat adjusting your code location accordingly.

Ubuntu

Give yourself access to serial ports with sudo gpasswd -s samuel dialout. Follow the official Elixir installation instructions and install build-essential erlang-dev as well.

Roadmap

Future

  • Remote compile mix task to Linux & Windows
  • Pass test serial port thru environment variables

0.5.4

  • Updated to sniff 0.1.4

0.5.3

  • Updated to sniff 0.1.3
  • Document Windows/Ubuntu dependencies

0.5.2

  • Updated to sniff 0.1.2 need for ´iex -S mix´ to find native library in Elixir 1.5.1
  • Updated to modbus 0.3.7

0.5.1

  • Updated to sniff 0.1.1
  • Extract NIF to its own repo (sniff)

0.5.0

  • Posix NIF implementation
  • Win32 NIF implementation
  • Baud api simplification
  • Refactored to NIF for improved speed and test isolation
  • Removed sock/loop (will be implemented as part of forward)

0.4.3

  • Add wait4ch to handle non standard line/packet terminators

0.4.2

  • Port proxy added to ensure proper closing on exit status msg
  • Kill tests added for both baud and sock
  • Refactored from genserver to actor

0.4.1

  • Updated Makefile for Windows 10

0.4.0

  • Added sample script (1 y 2)
  • Improved documentation
  • Update to modbus 0.2.0 (refactoring required)

0.3.0

  • Integration test script for modport
  • Added test.sh to isolate tests run
  • RTU master, slave, and tcpgw loop modes
  • Serial port export to socket in raw, text, and modbus mode
  • RTU API matched to modbus package (1,2,3,4,5,6,15,16)
  • Improved timeout handling for shorter test times

0.2.0

  • Interactive RTU: read/write up to 8 coils at once

0.1.0

  • Cross platform native serial port (mac, win, linux)
  • Modbus (tcu-rtu), raw and text loop mode

Research

  • Support udoo neo
  • Support beaglebone black
  • Support raspberry pi 3 B
  • Assess rewriting the windows native code using the win32 api
  • Assess rewriting the windows native code using c#/.net
  • Split into a core package and OS dependant packages holding native code
  • loop* tests still show data corruption when run all at once
  • Implement Modbus ASCII support (no available device)
  • Implement DTR/RTS control and CTS/DSR monitoring
  • Implement separate discard for input and output buffers
  • Unit test 8N1 7E1 7O1 and baud rate setup against a confirmed gauge
  • Get port names required for unit testing from environment variables
  • Implement a clean exit to loop mode for a timely port close and to ensure test isolation
  • Improve debugging: stderr messages are interlaced in mix test output
  • Improve debugging: dev/test/prod conditional output
  • Move from polling to overlapped on Windows
  • Research why interchar timeout is applied when reading a single byte even having many already in the input buffer. Happens on MAC.
  • Research how to bypass the 0.1s minimum granularity on posix systems
  • Research higher baud rates support for posix and win32
  • Research Mix unit test isolation (OS resources cleanup)
  • Research printf to embed variable sized arrays as hex strings

About

Elixir Serial Port with Modbus RTU support

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Elixir 97.0%
  • Shell 2.0%
  • Batchfile 1.0%