Mysterious Serial Port Behavior
I am trying to write a command line utility in Haskell (the first serious program in Haskell) to request a sensor connected to an arduino via a serial port. The relevant part of the code looks like this:
-- Read a single reading from the serial port
recursiveread :: SerialPort -> B.ByteString -> IO B.ByteString
recursiveread s acc sent = do
recd <- recv s 1000
if ((B.pack "Done\r\n") `B.isSuffixOf` acc)
then return acc
else recursiveread s $ B.append acc recd
-- Read a single reading from the serial port
getSingleRead :: FilePath -> IO [String]
getSingleRead path = do
s <- openSerial path defaultSerialSettings
send s $ B.pack "1"
acc <- recursiveread s B.empty
closeSerial s
return $ (lines . B.unpack) acc
-- Checks if the filepath exists, and prints a single reading
readspr :: [FilePath] -> IO ()
readspr [path] = do
exists <- doesFileExist path
case exists of
False -> putStrLn "No device found"
True -> getSingleRead path >>= (mapM_ putStrLn)
A send function (not shown) calls readspr
and uses a parameter "/dev/cu.modem1421"
as a parameter. The problem I suspect is related to the order of evaluation. The expected behavior is to get a dataframe like this, which I check for "Done" as a terminator:
T: 33697
Data
0:3.2967772483
1:3.2967772483
2:3.2967772483
...
126:3.2967772483
127:3.2967772483
Done
Here's the problem:
1) When I run this code myself after compilation, from Bash - the program calculates the second and hangs - no output. 2) However, when I go to ghci
and open the serial port with a command openSerial :: FilePath -> SerialPort
and then run the program in Bash , I see the expected output. (Shouldn't I be downloading a resource here or something? If I open a connection using screen
, I get this error)
This behavior is repeated - I can closeSerial
in ghci
and back to output without output to Bash.
Previous research / additional information:
I am using the library System.Hardware.SerialPort
(serialport-0.4.7: cross-platform serial port library in cabal) on an OS X machine. There is an issue related to the blocking / non-blocking nature of the serial port on OS X which is contrary to the UNIX standard - Issue 13 in Github for serialport -0.4.7 . However, I cannot figure it out. Any help in understanding this issue is highly appreciated. Is this a problem with my misunderstanding of Haskell lies, or am I missing something in the order of evaluation when the port is closed before I can read it in full or with the library? (in which case should I post it to the Github page?)
Further research: (the issue is being resolved)
Here's the problem - Arduino resets when opening serial connection (can be disconnected). When I opened a connection to the program, it will receive a message from the host before it loads. I noticed this while watching the LEDs on the Arduino on two separate occasions - opening (and holding) the port in ghc
allowed enough time to elapse between the second opening and reading.
The solution was to add a couple of seconds delay after opening the port - now "it just works"!
source to share
Answer updated for posterity: Further research: (resolved)
Here's the problem - Arduino resets when opening serial connection (can be disconnected). When I opened a connection to the program, it will receive a message from the host before it loads. I noticed this when observing the LEDs on the Arduino on two separate occasions - opening (and holding) the port in the ghc allowed enough time to elapse between the second open and read.
The solution was to add a couple of seconds delay after opening the port - now "it just works"!
source to share