6 Replies Latest reply on Dec 17, 2014 9:06 PM by KurtE

    How to read binary data via Serial1?

    widret

      I'm using a sensor that outputs binary data on UART.

      I connected it to Edison's Serial1 port and tried to read data, but faced several problems.

       

      1)Until LF(0x0A) is sent, Serial1 doesn't work.

      My sensor doesn't send LF(0x0A) at the end of message.

      When I try to read data (by "read(int fd,char *readbuf,int size);" function), it stops there until 0x0A happens to be sent.

      Is there any way to force read before LF(0x0A) is sent ?

       

      2)Can't read following bytes:

      0x03

      0x04

      0x0A

      0x0B

      0x0C

      0x0D

      0x0E

      0x0F

      0x11

      0x12

      0x13

      0x15

      0x16

      0x17

      0x1C

      0x7F

      I suspect these might work as ASCII control code, but I want to prevent it and read as data.

       

      3)Loop back

      How to stop loop back of Serial1?

      It is not required for most sensors.

       

      I switched pin mode by this

      stty -F /dev/ttyMFD1 115200
      echo -n "214" > /sys/class/gpio/export
      echo -n "130" > /sys/class/gpio/export
      echo -n "248" > /sys/class/gpio/export
      echo -n "216" > /sys/class/gpio/export
      echo -n "131" > /sys/class/gpio/export
      echo -n "249" > /sys/class/gpio/export
      echo -n "217" > /sys/class/gpio/export
      echo low > /sys/class/gpio/gpio214/direction
      echo low > /sys/class/gpio/gpio248/direction
      echo in > /sys/class/gpio/gpio216/direction
      echo mode1 > /sys/kernel/debug/gpio_debug/gpio130/current_pinmux
      echo in > /sys/class/gpio/gpio130/direction
      echo high > /sys/class/gpio/gpio249/direction
      echo in > /sys/class/gpio/gpio217/direction
      echo mode1 > /sys/kernel/debug/gpio_debug/gpio131/current_pinmux
      echo out > /sys/class/gpio/gpio131/direction
      echo high > /sys/class/gpio/gpio214/direction
      

       

      and tried to read data as followed:

       

      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      #include <fcntl.h>
      
      void PrintHex(char *test,int size){
        int i;
        for(i = 0; i < size; i++){
        printf("0x%02X ", test[i] & 0x000000FF);
        }
          printf("\n");
      }
      
      int main(void) {
        printf("Serial1 test program starts\n");
        int fd;
        unsigned int readsize;
        char data[4] = { 0x41, 0x47, 0x42, 0x0A };
        if((fd = open("/dev/ttyMFD1",O_RDWR)) < 0){
        printf("Device File Open Error\n");
        exit(1);
        }
        printf("Device File Opened\n");
        write(fd,data,4);
        printf("Tx via /dev/ttyMFD1\n");
      
        while(1){
             char readbuf[1024]={0};
             readsize = read(fd,readbuf,1024);
             printf("Rx via /dev/ttyMFD1\n");
             PrintHex(readbuf,1024);
        }
      
        close(fd);
        return 0;
      }
      

      It works fine for charactor data (a,b,c...), but not for binary data.

        • 1. Re: How to read binary data via Serial1?
          KurtE

          There may be other ways to do this, but I use the stuff in

          #include <termios.h>

           

          For example for my code that reads data from the Arbotix Commander (XBee), some of the Init code looks like:

           

           

          bool Commander::begin(char *pszDevice,  speed_t baud)
          {
              int err;
              // Create our lock to make sure we can do stuff safely
              if (pthread_mutex_init(&lock, NULL) != 0)
                  return false;
          
              _fCancel = false;    // Flag to let our thread(s) know to abort.
          #ifdef CMDR_USE_XBEE
              _pszDevice = pszDevice;
              _baud = baud;
              
              // Lets do our init of the xbee here.
              // We will do all of the stuff to intialize the serial port plus we will spawn off our thread.
              struct termios tc, tcNew;
          
              if ((fdXBee = open(_pszDevice, O_RDWR | O_NONBLOCK)) == -1) 
              {
                  printf("Open Failed\n");
                  return 0;
              }
          
          
              if (tcgetattr(fdXBee, &tc))
              {
                  perror("tcgetattr()");
                  return 0;
              }
          
              // build new version
                 bzero(&tcNew, sizeof(tcNew));
          
              //newtios.c_cflag |= _dwBaudRate | CRTSCTS | CS8 | CLOCAL | CREAD;
              tcNew.c_cflag = tc.c_cflag;
              tcNew.c_cflag &= ~CBAUD;
              tcNew.c_cflag |= _baud;
              tcNew.c_iflag = IGNPAR;
              tcNew.c_oflag = 0;
          
              /* set input mode (non-canonical, no echo,...) */
              tcNew.c_lflag = 0;
          
              tcNew.c_cc[VTIME]    = 0;   /* inter-character timer unused */
              tcNew.c_cc[VMIN]     = 1;   /* blocking read until 1 chars received */
          
              tcflush(fdXBee, TCIFLUSH);
              tcsetattr(fdXBee, TCSANOW, &tcNew);
          
          
              // Now we need to create our thread for doing the reading from the Xbee
              pthread_barrier_init(&_barrier, 0, 2);
              err = pthread_create(&tidXBee, NULL, &XBeeThreadProc, this);
              if (err != 0)
                  return false;
          
                // sync startup
              pthread_barrier_wait(&_barrier);
              
          
          

           

          I have another version of similar code in my WrapperSerial file, but the above is modeled to be very much like how the Arduino IDE does it. this code creates a second thread to read in the data...

          If you wish to look at the full code of these files, they are up in my (KurtE) Raspberry_Pi project up on github in the library directory.

           

          Hope that helps

          Kurt

          • 2. Re: How to read binary data via Serial1?
            widret

            That's exactly what I want to do.

            I completely received the sensor data. Thank you!

            • 3. Re: How to read binary data via Serial1?
              hk101

              Hi All,

              Went through many posts of serial IO on this forum. I still have some questions.

              I am attempting to use the mini-break out board where there are the two USB connectors, described in the hardware ref manual

              (reproduced here for quick reference:

              J3 is a micro USB FTDI serial-to-USB converter.

              • J16 is a fully USB compatible, micro AB, OTG (power “on the go”) port.)

               

              When I connect a "standard" USB micro B (to J16)  to USB A (to PC) cable,

                  I can read/write using "C" serial IO code (posted elsewhere in these forum) via puTTY terminal on PC.

               

              Then I use a cable => OTG usb B micro to USB A female as below, but I am unable to read/write via "C" code.

              mini J13 <-> OTG USB micro B ==cable== USB A female[ <= USB A male === cable <-> USB (OTG capable) freescale microcontroler MK20DX256 


              When I use the standard USB micro B to USB A (to PC), with the microcontroler MK20DX256 I can read/write using puTTy.

               

              In short, I can talk to both microcontroler MK20DX256, and Edison via same cable to PC using puTTY.

               

              When I try to talk to microcontroler MK20DX256 via Edison J16 ( C code setup as /dev/ttyMFD2) the same programs do not work.

               

              I suspect there is a hardware component to this whole setup I am missing. Not sure if I need micro USB "A" on the Edison side? per

              Edison hardware manual for mini break out board:

              "J16 is a fully USB compatible, micro AB, OTG (power “on the go”) port. If you plug a micro A cable into this port, the Intel® Edison module will connect to a PC as the host; if you plug a micro B cable into this port, the Intel® Edison module will connect to the PC as a device. (See the USB A female to micro A male cable, Digikey P/N 10-00649 839-1105-ND in Figure 7.)"

               

              Anyone tried to use the J16 USB port on Edison for USB to USB (two devices both capable of OTG) communications?

               

              Thanks in advance

              • 4. Re: How to read binary data via Serial1?
                KurtE

                This sounds like a completely separate question and also many others can probably answer this better than I can.

                For now I will make several assumptions.  That is you are plugging an OTG like cable into Edison and then connecting a standard USB cable into it, which plugs into the the other controller who at that point is acting as a USB client. And that this client is acting like a USB to serial converter.... (Something like a UNO32?)

                 

                If this is the case, it would not use the /dev/ttyMFD2.  Since you are in USB server mode, you could for example plug in a hub and end up with multiple objects, But depending on what the Serial chip on the other side, will dictate which driver is needed and as which object is created.

                 

                For example if you plug in an Board that uses an FTDI chipset and the FTDI driver is installed, the device may show up with a device name something like:

                /dev/ttyUSB0 (Note the 0 may change depending on if you have other ftdi devices, so it may be /dev/ttyUSB1...)

                 

                Some other chip sets, example if I plug in an Atmega 32u2 (example USB2AX device), again assuming the correct driver is installed and operational, the device may show up like /dev/ttyACM0

                 

                Not sure about others.

                 

                With it plugged in, what does the command: lsusb

                show you?

                 

                If you boot up and then install the adapter what shows up when you do something like: dmesg | tail -20

                 

                Kurt

                 

                P.S - maybe I should drag out one of my old Pic32 boards.

                • 5. Re: How to read binary data via Serial1?
                  hk101

                  Hi KurtE,

                  Yes your assumptions are close.

                  I have listed more info below.

                  Any insights appreciated,

                  Thank you

                   

                   

                  Excerpts of C code on Edison:

                  static const char *PORT_NAME = "/dev/ttyMFD2";

                  serial_port = open(PORT_NAME, O_RDWR | O_NONBLOCK );

                  if (serial_port != -1)

                    {

                     printf("Serial Port open\n");

                     tcgetattr(serial_port,&options_original);

                     tcgetattr(serial_port, &options);

                     cfsetispeed(&options, B115200);

                     cfsetospeed(&options, B115200);

                     options.c_cflag |= ( CLOCAL | CREAD );

                     options.c_lflag |= ICANON;

                     tcsetattr(serial_port, TCSANOW, &options);

                    }

                  ...

                  ...

                  main() {

                  .....

                  int chars_read;

                  while (1) {

                  chars_read = read(serial_port, read_buffer, max_chars_to_read);

                   

                  if (chars_read > 0){
                  for(int i=0;i<chars_read;i++) {
                    printf("%c",read_buffer[i]);
                  }
                  printf("\n");
                  }

                  } // while


                  } // main

                  When I connect the Edison J16 to PC via micro B to USB A cable, and run puTTy, I can see what I type on puTTy printed out, indicating

                  the Edison is reading and printing chars.


                  Then on microcontroler MK20DX256, it is similar C code. This C code is doing : println("Hello World..\n"); which I can see on puTTy.

                  -------


                  The command lsusb did not show any USB attached to J16: Maybe this is main issue, no USB or serial link detected on J16

                   

                  lsusb

                  unable to initialize libusb: -99

                   

                  ---------dmesg output:

                   

                  dmesg | tail -20

                  [   36.983467] link down if wlan0 may call cfg80211_disconnected. event : 6, reason=15 from 00:14

                  :bf:39:71:1b

                  [   36.988928] CFG80211-ERROR) wl_is_linkdown : Link down Reason : WLC_E_LINK

                  [   36.993093] cfg80211: Calling CRDA to update world regulatory domain

                  [   41.459945] CFG80211-ERROR) wl_cfg80211_connect : Connectting with00:14:bf:39:71:1b channel (6

                  ) ssid "hkclients", len (9)

                  [   41.459945]

                  [   41.538052] wl_bss_connect_done succeeded with 00:14:bf:39:71:1b

                  [   41.638302] wl_bss_connect_done succeeded with 00:14:bf:39:71:1b

                  [   45.612291] CFG80211-ERROR) wl_is_linkdown : Link down Reason : WLC_E_DEAUTH_IND

                  [   45.612332] link down if wlan0 may call cfg80211_disconnected. event : 6, reason=15 from 00:14

                  :bf:39:71:1b

                  [   45.616244] CFG80211-ERROR) wl_is_linkdown : Link down Reason : WLC_E_LINK

                  [   45.619456] cfg80211: Calling CRDA to update world regulatory domain

                  [   50.108241] CFG80211-ERROR) wl_cfg80211_connect : Connectting with00:14:bf:39:71:1b channel (6

                  ) ssid "hkclients", len (9)

                  [   50.108241]

                  [   50.197275] wl_bss_connect_done succeeded with 00:14:bf:39:71:1b

                  [   50.222885] wl_bss_connect_done succeeded with 00:14:bf:39:71:1b

                  [   51.611228] ip (280) used greatest stack depth: 5216 bytes left

                  [   89.377248] EXT4-fs (mmcblk0p10): mounted filesystem with ordered data mode. Opts: discard,bar

                  rier=1,data=ordered,noauto_da_alloc

                   



                  • 6. Re: How to read binary data via Serial1?
                    KurtE

                    DMesg showing -1 is a clue. 

                     

                    as reported in a couple threads you can either have stuff plugged into usb when you power on, or not have devices connected when you boot and then plug it in to work.  What does not work is to reboot while devices plugged in.  Why??? Not sure but that is what I have run into.

                     

                    try powering up without any thing in that usb connector and after boot is up,  and see what shows up in lsusb and dmesg