Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Using fstream with USB Serial Port

Using fstream with USB Serial Port

Scheduled Pinned Locked Moved C / C++ / MFC
c++linuxhelpquestion
31 Posts 4 Posters 2 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • O OscardelaGrouch

    speedbump99 wrote:

    For what it's worth, are you sure your serial port parameters match?

    Yes. I can send data back and forth with a terminal program. I have modified the programs like this ..

    void APP_Wixel_IO_Test_Tasks(void)
    {
    APP_ESUART_Tasks();
    if (CmdReady == 1)
    {
    CmdReady = 0; // reset flag
    RXBufCnt = 0; // reset RX Buffer count
    utoa(TXBuf, Cnt, 10); // convert cnt into a string
    strcat(TXBuf, "\n"); // add NULL to end of string
    WriteESUARTDataMsg(TXBuf, strlen(TXBuf)); // send command back to ESUART
    Cnt++; // increment cnt
    }
    }

    and this ..

    int main(int argc, char** argv)
    {
    fstream COMPORT;
    int number;
    int x = 0;
    char c;

    while(1)    // only works for first input. run again and missed one reply
    {
        COMPORT.open("/dev/ttyACM0");
        if (COMPORT.is\_open())
        {
            cout << "Hit  to send command,  to Stop .." << endl;
            cin.get(c);
            if ((c == 's' || c == 'S')) 
            {
                COMPORT.close();
                return 0;
            }
            COMPORT << "UPLOAD NEW MAP\\n";
            COMPORT >> number;
            cout << "number = " << number;
            cout << endl;
        }
        COMPORT.close();
    }
    return 0;
    

    }

    I get this response ..

    Hit to send command, to Stop ..

    number = 0
    Hit to send command, to Stop ..

    number = 2
    Hit to send command, to Stop ..

    number = 4
    Hit to send command, to Stop ..

    number = 6
    Hit to send command, to Stop ..

    number = 8
    Hit to send command, to Stop ..
    s

    I cannot figure why the cnt goes to two times instead of one. I would like to not be limited to just sending numbers back from the PIC. I think I am doing things "pretty' much correctly, but?? Any thoughts? OdlG

    M Offline
    M Offline
    mo1492
    wrote on last edited by
    #9

    If it works in a terminal program I really don't have any help for you except this. I don't know if it is this issue but these lines could be a potential problem depending on how COMPORT functions: COMPORT << "UPLOAD NEW MAP\n"; COMPORT >> number; There might be a timing issue if all data has not been received from the pic when COMPORT >> number; is called. As a test you might want to put a delay in to give it time. COMPORT << "UPLOAD NEW MAP\n"; delay? COMPORT >> number;

    O 1 Reply Last reply
    0
    • M mo1492

      If it works in a terminal program I really don't have any help for you except this. I don't know if it is this issue but these lines could be a potential problem depending on how COMPORT functions: COMPORT << "UPLOAD NEW MAP\n"; COMPORT >> number; There might be a timing issue if all data has not been received from the pic when COMPORT >> number; is called. As a test you might want to put a delay in to give it time. COMPORT << "UPLOAD NEW MAP\n"; delay? COMPORT >> number;

      O Offline
      O Offline
      OscardelaGrouch
      wrote on last edited by
      #10

      Thanks for the reply and suggestion. I think that a delay might help if I am trying to get a string from the PIC to the PC app. I would HOPE that the Getline function would do the waiting, but ??

      speedbump99 wrote:

      As a test you might want to put a delay in to give it time.

      I've thought about trying that, I don't see a delay function in C++ though. Is there one? In PIC C there is a __delay_us(10); function that would delay, in this case 10 microseconds based on the current clock speed. Seems that C++ ought to have one. Maybe have to just do a loop? OdlG

      M 1 Reply Last reply
      0
      • O OscardelaGrouch

        Thanks for the reply and suggestion. I think that a delay might help if I am trying to get a string from the PIC to the PC app. I would HOPE that the Getline function would do the waiting, but ??

        speedbump99 wrote:

        As a test you might want to put a delay in to give it time.

        I've thought about trying that, I don't see a delay function in C++ though. Is there one? In PIC C there is a __delay_us(10); function that would delay, in this case 10 microseconds based on the current clock speed. Seems that C++ ought to have one. Maybe have to just do a loop? OdlG

        M Offline
        M Offline
        mo1492
        wrote on last edited by
        #11

        I kind of doubt that getline will wait for data as it has no way of knowing how much data to expect. A quick search for Linux and Delay turned up a sleep() command that may be what you need. Also a search of "Linux synchronous serial port PIC" showed several of examples where they went through the process of setting the parameters for the serial port and running a loop to retrieve data. Something like (pseudo code): while (1) { read(1 char); if char == "\n" break; } You would probably read the text and convert back to integer. You might try that search. Hope this helps.

        O 1 Reply Last reply
        0
        • M mo1492

          I kind of doubt that getline will wait for data as it has no way of knowing how much data to expect. A quick search for Linux and Delay turned up a sleep() command that may be what you need. Also a search of "Linux synchronous serial port PIC" showed several of examples where they went through the process of setting the parameters for the serial port and running a loop to retrieve data. Something like (pseudo code): while (1) { read(1 char); if char == "\n" break; } You would probably read the text and convert back to integer. You might try that search. Hope this helps.

          O Offline
          O Offline
          OscardelaGrouch
          wrote on last edited by
          #12

          Thanks for the reply,

          speedbump99 wrote:

          I kind of doubt that getline will wait for data as it has no way of knowing how much data to expect.

          I think it will. In fact there are several versions of the getline function. In one you can specify a char array, max number of chars and a delimiter char. The default delim is '\n'. I have tried doing it char by char and didn't have any better results. I may try that again as it seems the operator >> only inputs numbers (of various types) and not strings. I think getline must be used for that. For right now I'm going to get my scope out and see why my reply jumps by two's instead of one with each command sent to the PIC. I will keep this thread updated. Thanks all, OdlG

          M 2 Replies Last reply
          0
          • O OscardelaGrouch

            Hello everyone, I'm kinda new to writing application programs for a PC, a Linux one at that, so I hope this isn't a stupid question. ;) I am rather experienced at writing C programs for Microchip PICs. I need a PC application to interface with a PIC project, it will up load information to the PIC from the PC using a pair of Wixel modules. They are basically a USB to RF or RF to Serial bridge. I have them working (one connected to the PC, one connected to the PIC) using a terminal program. I can send data back and forth just fine. I am now trying to send and receive data using a C++ application. The sending from the PC to the PIC works just fine also. The problem I am having is getting data from the PIC to the PC Application. This is the application code ..

            #include #include #include #include using namespace std;

            /*
            *
            */
            int main(int argc, char** argv)
            {
            fstream COMPORT;

            char line\[256\];
            streamsize lim = 256;
            char c;
            
            COMPORT.open("/dev/ttyACM0");
            
            while(1)    // only works for first input. run again and missed one reply
            {
                if (COMPORT.is\_open())
                {
                    cout << "Hit to send command, to Stop .." << endl;
                    cin.get(c);
                    if ((c == 's' || c == 'S')) 
                    {
                        COMPORT.close();
                        return 0;
                    }
                    COMPORT << "UPLOAD NEW MAP\\n";
                    COMPORT.getline(line, lim);
                    cout << "Line =" << line;
                    cout << "Response=" << c;
                    cout << endl;
                }
            }
            COMPORT.close();
            return 0;
            

            }

            The PIC code, if that helps ..

            void APP_Wixel_IO_Test_Tasks(void)
            {
            APP_ESUART_Tasks();
            if (CmdReady == 1)
            {
            CmdReady = 0; // reset flag
            RXBufCnt = 0; // reset RX Buffer count command
            utoa(TXBuf, Cnt, 10);
            strcat(TXBuf, "\n");
            WriteESUARTDataMsg(TXBuf, strlen(RXBuf)); // send command back to ESUART
            Cnt++; // increment cnt
            }
            }

            Basically all the PIC code does is send back the 'cnt' variable when it gets data from the PC. The

            COMPORT.getline(line, lim);

            doesn't work right. The first time I run it, it kinda works, but resending the data back to the PIC gets no response ..

            Hit to send command, to Stop ..

            Response=4
            Hit to send command, to Stop

            O Offline
            O Offline
            OscardelaGrouch
            wrote on last edited by
            #13

            Just an update on things I found using my oscilloscope and looking at what is being sent back and forth between the PC and PIC. I wish I could upload a screen shot from the scope. The PC is sending out three (sometimes two) data bursts. The first is obviously the "UPLOAD NEW MAP\n" command to the PIC. What the other two data burst are, I don't know yet. The PIC is replying twice, as would be expected if the data bursts contain the '\n' char. So looks like my first objective is to find out why

            COMPORT << "UPLOAD NEW MAP" << endl;

            is sending data out more than once. Any ideas would be appreciated. OdlG

            O 1 Reply Last reply
            0
            • O OscardelaGrouch

              Thanks for the reply,

              speedbump99 wrote:

              I kind of doubt that getline will wait for data as it has no way of knowing how much data to expect.

              I think it will. In fact there are several versions of the getline function. In one you can specify a char array, max number of chars and a delimiter char. The default delim is '\n'. I have tried doing it char by char and didn't have any better results. I may try that again as it seems the operator >> only inputs numbers (of various types) and not strings. I think getline must be used for that. For right now I'm going to get my scope out and see why my reply jumps by two's instead of one with each command sent to the PIC. I will keep this thread updated. Thanks all, OdlG

              M Offline
              M Offline
              mo1492
              wrote on last edited by
              #14

              Last suggestion. If you have another pc with a com port, connect the two pc's together and run the terminal program you have on one and your application on the other. Then you can see exactly what your application is sending out. I have also done this on a single computer with two com ports. Good Luck

              1 Reply Last reply
              0
              • O OscardelaGrouch

                Thanks for the reply,

                speedbump99 wrote:

                I kind of doubt that getline will wait for data as it has no way of knowing how much data to expect.

                I think it will. In fact there are several versions of the getline function. In one you can specify a char array, max number of chars and a delimiter char. The default delim is '\n'. I have tried doing it char by char and didn't have any better results. I may try that again as it seems the operator >> only inputs numbers (of various types) and not strings. I think getline must be used for that. For right now I'm going to get my scope out and see why my reply jumps by two's instead of one with each command sent to the PIC. I will keep this thread updated. Thanks all, OdlG

                M Offline
                M Offline
                mo1492
                wrote on last edited by
                #15

                Last suggestion. If you have another pc with a com port, connect the two pc's together with a loopback cable, run your terminal program on one and your test application on the other. Then you can see what your test app is sending. I have also done this on a single computer with two com ports. Good Luck

                1 Reply Last reply
                0
                • L Lost User

                  I have never tried to read a serial port via a stream class. Serial ports tend to be slow, and are really character oriented. You could try just using a basic file handle and reading as many characters as you can, gradually filling a buffer until you see a newline character. I know the ifstream should work that way but ...

                  O Offline
                  O Offline
                  OscardelaGrouch
                  wrote on last edited by
                  #16

                  Did a little debugging and it seems that the PC app is echoing the data from the PIC back to the PIC. I wonder why and how to stop that. OdlG

                  1 Reply Last reply
                  0
                  • O OscardelaGrouch

                    Just an update on things I found using my oscilloscope and looking at what is being sent back and forth between the PC and PIC. I wish I could upload a screen shot from the scope. The PC is sending out three (sometimes two) data bursts. The first is obviously the "UPLOAD NEW MAP\n" command to the PIC. What the other two data burst are, I don't know yet. The PIC is replying twice, as would be expected if the data bursts contain the '\n' char. So looks like my first objective is to find out why

                    COMPORT << "UPLOAD NEW MAP" << endl;

                    is sending data out more than once. Any ideas would be appreciated. OdlG

                    O Offline
                    O Offline
                    OscardelaGrouch
                    wrote on last edited by
                    #17

                    I did a little debugging on the PIC side and see that the PC app is echoing back the data it gets from the PIC. Any ideas why and how to stop that? Thanks? OdlG

                    J 1 Reply Last reply
                    0
                    • O OscardelaGrouch

                      I did a little debugging on the PIC side and see that the PC app is echoing back the data it gets from the PIC. Any ideas why and how to stop that? Thanks? OdlG

                      J Offline
                      J Offline
                      Jochen Arndt
                      wrote on last edited by
                      #18

                      That is probably because the serial device has echoing enabled. Such is used with serial terminals. When a character is received, it is send back to be displayed in the terminal (which usually does not display the character locally before sending it but waits for the echoed character to display that). To avoid that you have to disable echoing by configuring the serial device initially:

                      stty -F /dev/ttyACM0 raw pass8 -echo -hup -clocal 9600

                      Note that it might be necessary to specify also other settings, remove some used above, and change the baud rate. See stty(1): change/print terminal line settings - Linux man page[^] for the available options. Before changing the options I suggest to execute

                      stty -F /dev/ttyACM0

                      to check the current settings. As already mentioned by others it is rather uncommon to use C++ streams with serial ports. The common method is using termios and the IO functions from the standard C library, or a library like Serial Ports - 1.65.0[^] from Boost.Asio - 1.66.0[^] . Related reads: Serial HOWTO[^] Serial Programming/Serial Linux - Wikibooks, open books for an open world[^]

                      O 2 Replies Last reply
                      0
                      • J Jochen Arndt

                        That is probably because the serial device has echoing enabled. Such is used with serial terminals. When a character is received, it is send back to be displayed in the terminal (which usually does not display the character locally before sending it but waits for the echoed character to display that). To avoid that you have to disable echoing by configuring the serial device initially:

                        stty -F /dev/ttyACM0 raw pass8 -echo -hup -clocal 9600

                        Note that it might be necessary to specify also other settings, remove some used above, and change the baud rate. See stty(1): change/print terminal line settings - Linux man page[^] for the available options. Before changing the options I suggest to execute

                        stty -F /dev/ttyACM0

                        to check the current settings. As already mentioned by others it is rather uncommon to use C++ streams with serial ports. The common method is using termios and the IO functions from the standard C library, or a library like Serial Ports - 1.65.0[^] from Boost.Asio - 1.66.0[^] . Related reads: Serial HOWTO[^] Serial Programming/Serial Linux - Wikibooks, open books for an open world[^]

                        O Offline
                        O Offline
                        OscardelaGrouch
                        wrote on last edited by
                        #19

                        Jochen Arndt wrote:

                        The common method is using termios and the IO functions from the standard C library

                        Thank you for the reply. It is ironic that I ran across this yesterday and was able to write something that used this successfully. I will use this in my final code I am sure. My issue now is the write command, it seems to be char based, so I'm working on sending a char buffer. Once again, thanks to you and the forum, I really appreciate it. OdlG

                        1 Reply Last reply
                        0
                        • J Jochen Arndt

                          That is probably because the serial device has echoing enabled. Such is used with serial terminals. When a character is received, it is send back to be displayed in the terminal (which usually does not display the character locally before sending it but waits for the echoed character to display that). To avoid that you have to disable echoing by configuring the serial device initially:

                          stty -F /dev/ttyACM0 raw pass8 -echo -hup -clocal 9600

                          Note that it might be necessary to specify also other settings, remove some used above, and change the baud rate. See stty(1): change/print terminal line settings - Linux man page[^] for the available options. Before changing the options I suggest to execute

                          stty -F /dev/ttyACM0

                          to check the current settings. As already mentioned by others it is rather uncommon to use C++ streams with serial ports. The common method is using termios and the IO functions from the standard C library, or a library like Serial Ports - 1.65.0[^] from Boost.Asio - 1.66.0[^] . Related reads: Serial HOWTO[^] Serial Programming/Serial Linux - Wikibooks, open books for an open world[^]

                          O Offline
                          O Offline
                          OscardelaGrouch
                          wrote on last edited by
                          #20

                          Thanks for the help so far. I have written a small PC App program to try termios out. I am having two issues. First is the first time I send data to the PIC, the return response is junk. Second is the response is out of sync with the sent command, it takes sending the command a second time for the response string to be correct. Would appreciate a second pair of eyes to see what is the problem. PC app code ..

                          int main(int argc, char** argv)
                          {
                          ComPort MyComPort;
                          char TXBuf[255];
                          char RXBuf[255];
                          char c;

                          while(1)
                          {
                              cout << "(U)load New Map, (N)ext Map, (Q)uit .." << endl;
                              cin >> c;
                              c = (char)toupper(c);
                              if (c == 'Q') return 0;
                              if (c == 'U')
                              {
                                  strcpy(TXBuf, "UPLOAD NEW MAP\\n");
                                  MyComPort.WriteComPortDataMsg(TXBuf, strlen(TXBuf));
                                  MyComPort.ReadComPortDataMsg(RXBuf);
                                  cout << "RXBuf = " << RXBuf << endl;
                              }
                              else if (c == 'N')
                              {
                                  strcpy(TXBuf, "NEXT MAP\\n");
                                  MyComPort.WriteComPortDataMsg(TXBuf, strlen(TXBuf));
                                  MyComPort.ReadComPortDataMsg(RXBuf);
                                  cout << "RXBuf = " << RXBuf << endl;
                              }
                              cout << endl;
                          }
                          return 0;
                          

                          }

                          class defs ..

                          /***** Class Declaration ******************************************************/
                          class ComPort
                          {
                          public:
                          ComPort();
                          ~ComPort();
                          void WriteComPortDataMsg(char *data, char num);
                          void ReadComPortDataMsg(char *data, char dlimc);
                          void ReadComPortDataMsg(char *data);
                          void SetDlimiter(char dlimc);
                          private:
                          char dlim;
                          struct termios config;
                          int hComPort;
                          bool Error;
                          };

                          void ComPort::WriteComPortDataMsg(char *data, char num)
                          {
                          for (int cnt = 0; cnt < num; cnt++)
                          {
                          write(hComPort, &data[cnt], 1); // write char to Com Port
                          }
                          tcdrain(hComPort);
                          }

                          void ComPort::ReadComPortDataMsg(char *data)
                          {
                          int cnt = 0;
                          char c;

                          data\[0\] = 0x00;
                          do
                          {
                              read(hComPort, &c, 1);
                              if ((c >= 0x20) && (c <= 0x7E)) data\[cnt++\] = c;
                          } while ((c != dlim) && (cnt < 255));
                          data\[cnt++\] = '\\0';
                          

                          }

                          responses ..

                          (U)load New Map, (N)ext Map, (Q)uit ..
                          u
                          RXBuf = MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM

                          J 1 Reply Last reply
                          0
                          • O OscardelaGrouch

                            Thanks for the help so far. I have written a small PC App program to try termios out. I am having two issues. First is the first time I send data to the PIC, the return response is junk. Second is the response is out of sync with the sent command, it takes sending the command a second time for the response string to be correct. Would appreciate a second pair of eyes to see what is the problem. PC app code ..

                            int main(int argc, char** argv)
                            {
                            ComPort MyComPort;
                            char TXBuf[255];
                            char RXBuf[255];
                            char c;

                            while(1)
                            {
                                cout << "(U)load New Map, (N)ext Map, (Q)uit .." << endl;
                                cin >> c;
                                c = (char)toupper(c);
                                if (c == 'Q') return 0;
                                if (c == 'U')
                                {
                                    strcpy(TXBuf, "UPLOAD NEW MAP\\n");
                                    MyComPort.WriteComPortDataMsg(TXBuf, strlen(TXBuf));
                                    MyComPort.ReadComPortDataMsg(RXBuf);
                                    cout << "RXBuf = " << RXBuf << endl;
                                }
                                else if (c == 'N')
                                {
                                    strcpy(TXBuf, "NEXT MAP\\n");
                                    MyComPort.WriteComPortDataMsg(TXBuf, strlen(TXBuf));
                                    MyComPort.ReadComPortDataMsg(RXBuf);
                                    cout << "RXBuf = " << RXBuf << endl;
                                }
                                cout << endl;
                            }
                            return 0;
                            

                            }

                            class defs ..

                            /***** Class Declaration ******************************************************/
                            class ComPort
                            {
                            public:
                            ComPort();
                            ~ComPort();
                            void WriteComPortDataMsg(char *data, char num);
                            void ReadComPortDataMsg(char *data, char dlimc);
                            void ReadComPortDataMsg(char *data);
                            void SetDlimiter(char dlimc);
                            private:
                            char dlim;
                            struct termios config;
                            int hComPort;
                            bool Error;
                            };

                            void ComPort::WriteComPortDataMsg(char *data, char num)
                            {
                            for (int cnt = 0; cnt < num; cnt++)
                            {
                            write(hComPort, &data[cnt], 1); // write char to Com Port
                            }
                            tcdrain(hComPort);
                            }

                            void ComPort::ReadComPortDataMsg(char *data)
                            {
                            int cnt = 0;
                            char c;

                            data\[0\] = 0x00;
                            do
                            {
                                read(hComPort, &c, 1);
                                if ((c >= 0x20) && (c <= 0x7E)) data\[cnt++\] = c;
                            } while ((c != dlim) && (cnt < 255));
                            data\[cnt++\] = '\\0';
                            

                            }

                            responses ..

                            (U)load New Map, (N)ext Map, (Q)uit ..
                            u
                            RXBuf = MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM

                            J Offline
                            J Offline
                            Jochen Arndt
                            wrote on last edited by
                            #21

                            I did not see any code that initialises the serial port. So it will still use the current settings as shown by the stty command line tool. You have to use tcsetattr to select the same basic settings as on the PIC (probably 8N1; baud rate seems to mach already), disable all kinds of flow control (software and hardware), and all additional features like echoing. Example:

                            memset(&config, 0, sizeof(config));
                            config.c_cflag = CS8 | CREAD | CLOCAL; // 8N1, enable receiver, ignore ctrl lines
                            cfsetospeed(&config, B9600); // baud rate used by the PIC
                            cfsetispeed(&config, B9600);
                            tcsetattr(hComPort, TCSANOW, &config);

                            With new line terminated data transfers, you may also use the canonical mode (ICANON).

                            O 1 Reply Last reply
                            0
                            • J Jochen Arndt

                              I did not see any code that initialises the serial port. So it will still use the current settings as shown by the stty command line tool. You have to use tcsetattr to select the same basic settings as on the PIC (probably 8N1; baud rate seems to mach already), disable all kinds of flow control (software and hardware), and all additional features like echoing. Example:

                              memset(&config, 0, sizeof(config));
                              config.c_cflag = CS8 | CREAD | CLOCAL; // 8N1, enable receiver, ignore ctrl lines
                              cfsetospeed(&config, B9600); // baud rate used by the PIC
                              cfsetispeed(&config, B9600);
                              tcsetattr(hComPort, TCSANOW, &config);

                              With new line terminated data transfers, you may also use the canonical mode (ICANON).

                              O Offline
                              O Offline
                              OscardelaGrouch
                              wrote on last edited by
                              #22

                              Jochen Arndt wrote:

                              I did not see any code that initialises the serial port.

                              There is, I was having trouble with the forum editor, thought maybe my code was too long. The first part is here ..

                              /***** Class Declaration ******************************************************/
                              class ComPort
                              {
                              public:
                              ComPort();
                              ~ComPort();
                              void WriteComPortDataMsg(char *data, char num);
                              void ReadComPortDataMsg(char *data, char dlimc);
                              void ReadComPortDataMsg(char *data);
                              void SetDlimiter(char dlimc);
                              private:
                              char dlim;
                              struct termios config;
                              int hComPort;
                              bool Error;
                              };

                              ComPort::ComPort()
                              {
                              dlim = '\n';
                              char c;

                              Error = false;
                              hComPort = open("/dev/ttyACM0", O\_RDWR | O\_NOCTTY | O\_NDELAY);
                              if (hComPort == -1)
                              {
                                  cout << "failed to open port\\n" << endl;
                                  cout << "Hit  to Stop .." << endl;
                                  cin >> c;
                                  c = (char)toupper(c);
                                  if (c == 'S') Error = true;
                              }
                              
                              if(!isatty(hComPort))
                              {
                                  cout << "file descriptor is  not pointing to a TTY device\\n" << endl;
                                  cout << "Hit  to Stop .." << endl;
                                  cin.get(c);
                                  if ((c == 's' || c == 'S')) Error = true;
                              }
                              
                              if(tcgetattr(hComPort, &config) < 0)
                              {
                                  cout << "configuration of the serial interface not found\\n" << endl;
                                  cout << "Hit  to Stop .." << endl;
                                  cin >> c;
                                  c = (char)toupper(c);
                                  if (c == 'S') Error = true;
                              }
                              
                              //
                              // Input flags - Turn off input processing
                              //
                              // convert break to null byte, no CR to NL translation,
                              // no NL to CR translation, don't mark parity errors or breaks
                              // no input parity check, don't strip high bit off,
                              // no XON/XOFF software flow control
                              //
                              config.c\_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON);
                              
                              // Output flags - Turn off output processing
                              //
                              // no CR to NL translation, no NL to CR-NL translation,
                              // no NL to CR translation, no column 0 CR suppression,
                              // no Ctrl-D suppression, no fill characters, no case mapping,
                              // no local output processing
                              //
                              // config.c\_oflag &= ~(OCRNL | ONLCR | ONLRET |
                              //                     ONOCR | ONOEOT| OFILL | OLCUC | OPOST);
                              config.c\_oflag = 0;
                              
                              //
                              // No line processing
                              //
                              // echo off, echo newline off, canonical mode off, 
                              // extended input processing off, signal ch
                              
                              J 1 Reply Last reply
                              0
                              • O OscardelaGrouch

                                Jochen Arndt wrote:

                                I did not see any code that initialises the serial port.

                                There is, I was having trouble with the forum editor, thought maybe my code was too long. The first part is here ..

                                /***** Class Declaration ******************************************************/
                                class ComPort
                                {
                                public:
                                ComPort();
                                ~ComPort();
                                void WriteComPortDataMsg(char *data, char num);
                                void ReadComPortDataMsg(char *data, char dlimc);
                                void ReadComPortDataMsg(char *data);
                                void SetDlimiter(char dlimc);
                                private:
                                char dlim;
                                struct termios config;
                                int hComPort;
                                bool Error;
                                };

                                ComPort::ComPort()
                                {
                                dlim = '\n';
                                char c;

                                Error = false;
                                hComPort = open("/dev/ttyACM0", O\_RDWR | O\_NOCTTY | O\_NDELAY);
                                if (hComPort == -1)
                                {
                                    cout << "failed to open port\\n" << endl;
                                    cout << "Hit  to Stop .." << endl;
                                    cin >> c;
                                    c = (char)toupper(c);
                                    if (c == 'S') Error = true;
                                }
                                
                                if(!isatty(hComPort))
                                {
                                    cout << "file descriptor is  not pointing to a TTY device\\n" << endl;
                                    cout << "Hit  to Stop .." << endl;
                                    cin.get(c);
                                    if ((c == 's' || c == 'S')) Error = true;
                                }
                                
                                if(tcgetattr(hComPort, &config) < 0)
                                {
                                    cout << "configuration of the serial interface not found\\n" << endl;
                                    cout << "Hit  to Stop .." << endl;
                                    cin >> c;
                                    c = (char)toupper(c);
                                    if (c == 'S') Error = true;
                                }
                                
                                //
                                // Input flags - Turn off input processing
                                //
                                // convert break to null byte, no CR to NL translation,
                                // no NL to CR translation, don't mark parity errors or breaks
                                // no input parity check, don't strip high bit off,
                                // no XON/XOFF software flow control
                                //
                                config.c\_iflag &= ~(IGNBRK | BRKINT | ICRNL | INLCR | PARMRK | INPCK | ISTRIP | IXON);
                                
                                // Output flags - Turn off output processing
                                //
                                // no CR to NL translation, no NL to CR-NL translation,
                                // no NL to CR translation, no column 0 CR suppression,
                                // no Ctrl-D suppression, no fill characters, no case mapping,
                                // no local output processing
                                //
                                // config.c\_oflag &= ~(OCRNL | ONLCR | ONLRET |
                                //                     ONOCR | ONOEOT| OFILL | OLCUC | OPOST);
                                config.c\_oflag = 0;
                                
                                //
                                // No line processing
                                //
                                // echo off, echo newline off, canonical mode off, 
                                // extended input processing off, signal ch
                                
                                J Offline
                                J Offline
                                Jochen Arndt
                                wrote on last edited by
                                #23

                                Use the code from my post. It sets all while you are modifying the existing where something might be still set / cleared. CREAD is probably set but what about CLOCAL?

                                O 1 Reply Last reply
                                0
                                • J Jochen Arndt

                                  Use the code from my post. It sets all while you are modifying the existing where something might be still set / cleared. CREAD is probably set but what about CLOCAL?

                                  O Offline
                                  O Offline
                                  OscardelaGrouch
                                  wrote on last edited by
                                  #24

                                  Jochen Arndt wrote:

                                  CREAD is probably set but what about CLOCAL?

                                  I had the same code except .. memset

                                  if(tcgetattr(hComPort, &config) < 0)
                                  {
                                  cout << "configuration of the serial interface not found\n" << endl;
                                  cout << "Hit to Stop .." << endl;
                                  cin >> c;
                                  c = (char)toupper(c);
                                  if (c == 'S') Error = true;
                                  }
                                  memset(&config, 0, sizeof(config));

                                  this is baudrate code ..

                                  config.c_cflag = CS8 | CREAD | CLOCAL; // 8N1, enable receiver, ignore ctrl lines

                                  if(cfsetispeed(&config, B9600) < 0 || cfsetospeed(&config, B9600) < 0)
                                  {
                                      cout << "Baud Rate did not set correctly\\n" << endl;
                                      cout << "Hit  to Stop .." << endl;
                                      cin >> c;
                                      c = (char)toupper(c);
                                      if (c == 'S') Error = true;
                                  }
                                  

                                  I get the same result as before. OdlG

                                  J 1 Reply Last reply
                                  0
                                  • O OscardelaGrouch

                                    Jochen Arndt wrote:

                                    CREAD is probably set but what about CLOCAL?

                                    I had the same code except .. memset

                                    if(tcgetattr(hComPort, &config) < 0)
                                    {
                                    cout << "configuration of the serial interface not found\n" << endl;
                                    cout << "Hit to Stop .." << endl;
                                    cin >> c;
                                    c = (char)toupper(c);
                                    if (c == 'S') Error = true;
                                    }
                                    memset(&config, 0, sizeof(config));

                                    this is baudrate code ..

                                    config.c_cflag = CS8 | CREAD | CLOCAL; // 8N1, enable receiver, ignore ctrl lines

                                    if(cfsetispeed(&config, B9600) < 0 || cfsetospeed(&config, B9600) < 0)
                                    {
                                        cout << "Baud Rate did not set correctly\\n" << endl;
                                        cout << "Hit  to Stop .." << endl;
                                        cin >> c;
                                        c = (char)toupper(c);
                                        if (c == 'S') Error = true;
                                    }
                                    

                                    I get the same result as before. OdlG

                                    J Offline
                                    J Offline
                                    Jochen Arndt
                                    wrote on last edited by
                                    #25

                                    The source is probably here:

                                    read(hComPort, &c, 1);
                                    if ((c >= 0x20) && (c <= 0x7E)) data[cnt++] = c;

                                    See read(2): read from file descriptor - Linux man page[^]:

                                    Quote:

                                    Return Value On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal. On error, -1 is returned, and errno is set appropriately. In this case it is left unspecified whether the file position (if any) changes.

                                    read() will return zero when there are no data available. So you have either to clear your c variable before, or - better - check the return value:

                                    int received = read(hComPort, &c, 1);
                                    if (received == 1 && c >= 0x20 && c <= 0x7E)
                                    data[cnt++] = c;
                                    else if (received < 0)
                                    // handle error here

                                    Another option is setting blocking mode (attributes c_cc[VMIN] to non zero and c_cc[VTIME] to the timeout value). Then you will not get zero return values but still have to check for negative return values indicating timeout or other errors.

                                    O 2 Replies Last reply
                                    0
                                    • J Jochen Arndt

                                      The source is probably here:

                                      read(hComPort, &c, 1);
                                      if ((c >= 0x20) && (c <= 0x7E)) data[cnt++] = c;

                                      See read(2): read from file descriptor - Linux man page[^]:

                                      Quote:

                                      Return Value On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal. On error, -1 is returned, and errno is set appropriately. In this case it is left unspecified whether the file position (if any) changes.

                                      read() will return zero when there are no data available. So you have either to clear your c variable before, or - better - check the return value:

                                      int received = read(hComPort, &c, 1);
                                      if (received == 1 && c >= 0x20 && c <= 0x7E)
                                      data[cnt++] = c;
                                      else if (received < 0)
                                      // handle error here

                                      Another option is setting blocking mode (attributes c_cc[VMIN] to non zero and c_cc[VTIME] to the timeout value). Then you will not get zero return values but still have to check for negative return values indicating timeout or other errors.

                                      O Offline
                                      O Offline
                                      OscardelaGrouch
                                      wrote on last edited by
                                      #26

                                      I was beginning to think I needed some way to wait on the USB/Com Port, but wasn't sure how to do that. This works great. My code change ..

                                      void ComPort::ReadComPortDataMsg(char *data)
                                      {
                                      int cnt = 0;
                                      int received;
                                      char c;

                                      data\[0\] = 0x00;
                                      do
                                      {
                                          received = read(hComPort, &c, 1);
                                          if ((received == 1) && (c >= 0x20) && (c <= 0x7E))
                                          {
                                              data\[cnt++\] = c;
                                          }
                                          else if (received < 0)
                                          {
                                              
                                          }
                                      } while ((c != dlim) && (cnt < 255));
                                      data\[cnt++\] = '\\0';
                                      

                                      }

                                      Not sure how to deal with received < 0. Do you know where can I read up on

                                      struct termios

                                      and

                                      global errno variable

                                      ? Thanks!!! OdlG

                                      J 1 Reply Last reply
                                      0
                                      • O OscardelaGrouch

                                        I was beginning to think I needed some way to wait on the USB/Com Port, but wasn't sure how to do that. This works great. My code change ..

                                        void ComPort::ReadComPortDataMsg(char *data)
                                        {
                                        int cnt = 0;
                                        int received;
                                        char c;

                                        data\[0\] = 0x00;
                                        do
                                        {
                                            received = read(hComPort, &c, 1);
                                            if ((received == 1) && (c >= 0x20) && (c <= 0x7E))
                                            {
                                                data\[cnt++\] = c;
                                            }
                                            else if (received < 0)
                                            {
                                                
                                            }
                                        } while ((c != dlim) && (cnt < 255));
                                        data\[cnt++\] = '\\0';
                                        

                                        }

                                        Not sure how to deal with received < 0. Do you know where can I read up on

                                        struct termios

                                        and

                                        global errno variable

                                        ? Thanks!!! OdlG

                                        J Offline
                                        J Offline
                                        Jochen Arndt
                                        wrote on last edited by
                                        #27

                                        For all standard C library features you can get the description from the shell command prompt as man page:

                                        man errno

                                        will shown the content of the errno(3) - Linux manual page[^]. Similar for termios which is covered by a single man page: termios(3) - Linux man page[^]. If you want to get the above links, just use the same "man " with your favorite search engine. Other good sources for the standard C and C++ libraries are cplusplus.com - The C++ Resources Network[^] and cppreference.com[^].

                                        1 Reply Last reply
                                        0
                                        • J Jochen Arndt

                                          The source is probably here:

                                          read(hComPort, &c, 1);
                                          if ((c >= 0x20) && (c <= 0x7E)) data[cnt++] = c;

                                          See read(2): read from file descriptor - Linux man page[^]:

                                          Quote:

                                          Return Value On success, the number of bytes read is returned (zero indicates end of file), and the file position is advanced by this number. It is not an error if this number is smaller than the number of bytes requested; this may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal. On error, -1 is returned, and errno is set appropriately. In this case it is left unspecified whether the file position (if any) changes.

                                          read() will return zero when there are no data available. So you have either to clear your c variable before, or - better - check the return value:

                                          int received = read(hComPort, &c, 1);
                                          if (received == 1 && c >= 0x20 && c <= 0x7E)
                                          data[cnt++] = c;
                                          else if (received < 0)
                                          // handle error here

                                          Another option is setting blocking mode (attributes c_cc[VMIN] to non zero and c_cc[VTIME] to the timeout value). Then you will not get zero return values but still have to check for negative return values indicating timeout or other errors.

                                          O Offline
                                          O Offline
                                          OscardelaGrouch
                                          wrote on last edited by
                                          #28

                                          Question on how to error handle. I am falling into the received < 0 but if I just ignore it and keep looking for chars, I get a complete, correct message. Is it safe to do that or should I clear the error? And How? Thanks in advance ;) OdlG

                                          J 1 Reply Last reply
                                          0
                                          Reply
                                          • Reply as topic
                                          Log in to reply
                                          • Oldest to Newest
                                          • Newest to Oldest
                                          • Most Votes


                                          • Login

                                          • Don't have an account? Register

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • World
                                          • Users
                                          • Groups