Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read from a serial port in lua

I'm new to lua and I'm trying to receive data from the port, ttyACM0, I can write to the port by:

wserial = io.open("/dev/ttyACM0","w")
wserial:write("hellloooo")
wserial:flush()

I thought since I can write to it in the same way as I would write to a file that I could read it in the same way as I would read a file. But when I try to read it (using the code below) I just end up in an infinite loop.

rserial=io.open("/dev/ttyACM0","r")
while chaine==nil do
  chaine=rserial:read()
  rserial:flush()
end
print(chaine)

So my question is what am I doing wrong, how do I read from the port, ttyACM0?

like image 511
lana Avatar asked Aug 08 '14 13:08

lana


1 Answers

There are two kinds of line buffering going on here: one in the C library, which you can avoid using :read(1) like @Advert mentioned in the comments, and another one in the terminal driver itself. You can disable input line buffering in the terminal driver using the stty command line utility (stty -F /dev/ttyACM0 -icanon) or e.g. using luaposix (untested code):

local p = require( "posix" )
local rserial = assert( io.open( "/dev/ttyACM0", "r" ) )
local fd = assert( p.fileno( rserial ) )

local function table_copy( t )
  local copy = {}
  for k,v in pairs( t ) do
    if type( v ) == "table" then
      copy[ k ] = table_copy( v )
    else
      copy[ k ] = v
    end
  end
  return copy
end

-- get current settings
local saved_tcattr = assert( p.tcgetattr( fd ) )
local raw_tcattr = table_copy( saved_tcattr )
-- clear ICANON bits from local flags using Lua 5.2 bit32 module
raw_tcattr.lflag = bit32.band( raw_tcattr.lflag, bit32.bnot( p.ICANON ) )

-- apply modified settings
assert( p.tcsetattr( fd, p.TCSANOW, raw_tcattr ) )
local c = rserial:read( 1 )
print( c )
-- restore default settings afterwards
p.tcsetattr( fd, p.TCSANOW, saved_tcattr )
rserial:close()

There is also a specialized C module for handling serial ports in Lua, and the latest unreleased version of LuaSocket has code for handling serial ports (but it's disabled in default builds).

like image 184
siffiejoe Avatar answered Sep 28 '22 05:09

siffiejoe