Haskell: Serial received data not printed correctly

I'm trying to receive data from my Arduino Serial.println("No Format");. When I open arduino-serial-monitor I can see the output how I wanted it.

No Format
No Format
...

I use serialport package. But the output printed on ghci is:

*Main> main
"\r\nNo Forma"
"t\r\nNo Form"
"at\r\nNo For"
"mat\r\nNo Fo"
"rmat\r\nNo F"
"ormat\r\nNo "
"Format\r\nNo"
" Format\r\nN"
"o Format\r\n"
...
...
"\nNo"
" For"
"mat\r"
"\nNo "
"Form"
"at\r\n"
....

Haskell:

import qualified Data.ByteString.Char8 as B
import System.Hardware.Serialport
import System.IO
import Control.Monad

main :: IO ()
main = forever $ do
  let port = "/dev/ttyACM0"
  s <- openSerial port SerialPortSettings { commSpeed = CS9600,
                                            bitsPerWord = 8,
                                            stopb = One,
                                            parity = NoParity,
                                            flowControl = NoFlowControl,
                                            timeout = 10 }
  recv s 10 >>= print
  closeSerial s

Arduino:

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println("No Format");
}

Any help would be awesome. Thanks.

Upvotes: 0

Views: 167

Answers (2)

Using B.putStr instead of print fixed the problem. Thanks to @pat.

Upvotes: 0

Elie G&#233;nard
Elie G&#233;nard

Reputation: 1683

You could just receive characters until you receive a "\n" character. Maybe something like this:

import Control.Monad (forever)
import Control.Applicative ((<$>))
import Data.ByteString.Char8 (unpack)
import System.Hardware.Serialport (SerialPort, openSerial, recv)

-- Read a character from the serial port.
receive :: SerialPort -> IO String
receive sp = fmap unpack (recv sp 1)

-- Read a line, ending with '\n'.
readLine :: SerialPort -> IO String
readLine sp = readLineRec sp [] 

-- Recursive function to read a line from the serial port.
readLineRec :: SerialPort -> String -> IO String
readLineRec sp [] = receive sp >>= readLineRec sp 
readLineRec sp chars
    | last chars == '\n' = return chars
    | otherwise = (chars ++) <$> receive sp >>= readLineRec sp

main = do
    let port = "/dev/ttyACM0"
    s <- openSerial port SerialPortSettings { commSpeed = CS9600,
                                        bitsPerWord = 8,
                                        stopb = One,
                                        parity = NoParity,
                                        flowControl = NoFlowControl,
                                        timeout = 10 }
    forever $ do
        line <- readLine s
        print line

There is room for improvement, but it works!

Upvotes: 2

Related Questions