神秘的串口行为

时间:2014-11-08 02:40:05

标签: haskell io serial-port operator-precedence

我试图在Haskell(Haskell中的第一个严重程序)中编写命令行实用程序来查询通过串行端口连接到arduino的传感器。代码的相关部分如下:

-- 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) 

调度功能(未显示)调用readspr并使用"/dev/cu.modem1421"作为参数。 我怀疑的问题与评估顺序有关。预期的行为是接收这样的数据帧,我检查&#34;完成&#34;作为终结者:

T: 33697
Data
0:3.2967772483
1:3.2967772483
2:3.2967772483
...
126:3.2967772483
127:3.2967772483
Done

问题在于:

1)当我在编译后自行运行此代码时,从Bash开始 - 程序计算一秒并挂起 - 没有输出。 2)然而,当我进入ghci并使用openSerial :: FilePath -> SerialPort命令打开一个串口,然后在Bash 中运行程序时,我确实看到了预期的输出。 (难道我没有资源在这里或者其他什么东西?如果我使用screen打开连接我会收到错误)

这种行为是可重复的 - 我可以在closeSerialghci并在Bash中返回无输出。

之前的研究/其他背景:

我在OS X计算机上使用System.Hardware.SerialPort库(serialport-0.4.7:cabal中的跨平台串行端口库)。 OS X上串行端口的阻塞/非阻塞特性与UNIX标准Issue 13 on Github for serialport-0.4.7不一致。但是,我无法理解它。任何有助于理解这个问题的帮助都非常感谢。这是我对Haskell懒惰的误读,还是我在评估顺序上丢失了一些问题,在我完全阅读或者使用库之前端口是关闭的? (在这种情况下,我应该在Github页面上发布它?)

进一步研究:(案例解决)

问题在于 - 当打开串行连接时,Arduino会重置(可以禁用)。当我打开与程序的连接时 - 它会在启动之前从主机接收通信。在两个独立的情况下观察Arduino上的LED时我注意到了这一点 - 打开(并保持)ghc中的端口,允许在第二次打开和读取之间经过足够的时间。

解决方案是在打开端口后添加几秒钟的延迟 - 现在&#34;它只是工作&#34;!

1 个答案:

答案 0 :(得分:1)

为子孙后代更新的答案: 进一步研究:(案例解决)

问题在于 - 当打开串行连接时可以重置Arduino(可以禁用)。当我打开与程序的连接时 - 它会在启动之前从主机接收通信。在两个独立的情况下观察Arduino上的LED时我注意到了这一点 - 在ghc中打开(并保持)端口,允许在第二次打开和读取之间经过足够的时间。

解决方案是在打开端口后添加几秒钟的延迟 - 现在“它只是工作”!