0

I am trying to take the sensor data from Arduino & Raspberry Pi using RS232 serial communication. I have searched for this small thing and found something related on this below link but was unable get the full idea.

The os (kernel) has an internal buffer of 4096 bytes. If this buffer is full and a new character arrives on the serial port, the oldest character in the buffer will be overwritten and thus will be lost. After a successful call to RS232_OpenComport(), the os will start to buffer incoming characters.

The values are properly coming from Arduino to Raspberry Pi (output attached below) and it is storing in a pointer to unsigned char[] which is defined as unsigned char *buf[4096].

enter image description here

int main()
{
  int i, n,
      cport_nr=0,        /* /dev/ttyS0 (COM1 on windows) */
      bdrate=9600;       /* 9600 baud */

  unsigned char buf[4096];

  char mode[]={'8','N','1',0};

  while(1)
  {
    n = RS232_PollComport(cport_nr, buf, 4095);

    if(n > 0)
    {
      buf[n] = 0;

      for(i=0; i < n; i++)
      {
        if(buf[i] < 32)  /* replace unreadable control-codes by dots */
        {
          buf[i] = '.';
        }
      }

      printf("received %i bytes: %s\n", n, (char *)buf);
    }
}

Now I want to store these values in another float/double variable so that I can perform further operations on it. How to store a value suppose 0.01 to a float/double which is later used to create stuff.

uvan
  • 19
  • 9
  • 1
    Try looking up atof/atod/strtod on cppreference.com or cplusplus.com – David Dalcino May 07 '19 at 06:34
  • 1
    Answered here: https://stackoverflow.com/questions/1012571/stdstring-to-float-or-double You just need to separate your numbers first, if your data consists of more than one. – pptaszni May 07 '19 at 07:31
  • @Ptaq666 can you elaborate, I am not getting what is exactly. – uvan May 07 '19 at 07:40
  • Possible duplicate of [std::string to float or double](https://stackoverflow.com/questions/1012571/stdstring-to-float-or-double) – Clonk May 07 '19 at 07:47
  • @uvan , elaborated in the answer. Now it's understood? – pptaszni May 07 '19 at 11:53
  • @Ptaq666 Thanks for your answer. I will check and update you shortly – uvan May 07 '19 at 13:24
  • @uvan why don't you try with qserial? – Jerwin Prabu May 08 '19 at 07:35
  • @JerwinPrabu I have tried to use qserial for receiving data, but I didn't get the proper response. I don't know where is the problem exactly. I hope you can help me to get a solution.` QString str = serial -> readAll();` `int num = str.toInt();` – uvan May 08 '19 at 10:19

2 Answers2

2

From the output in the screenshot it looks like you are sending the string representation of the numbers rather than the actual numbers. You just need to detect those "unreadable control-codes" that you are just replacing with a . as they will probably tell you when a number ends and another begins. Just make QSerialPort * serial; a proper class member.

Also, check for errors on opening the port: serial->open(QIODevice::ReadWrite); Then, insert some qDebug() in serialreceived() to see if the slot is called at all and if the canReadLine() works. you should use QByteArray to read your data. If there's any char in the response, that is not String conform, the resulting QString will be prematurely terminated, use readLine() instead readAll() like this:

QByteArray data = serial -> readLine();
qDebug() < data.toHex(' '); // prints the hex representation of your char array
QString str(data);
qDebug() << str;
Jerwin Prabu
  • 336
  • 1
  • 3
  • 16
1

First, it will be better if you use some other ASCII character (e.g. space) to separate the numbers, because . dot is a part of floating point number. Then, you can construct std::string object from your raw unsigned char array, split it in a multiple strings and convert each string to float.

#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>

int main() {
    // imagine that this buff is already after read and preprocessing
    unsigned char buff[1024] = "13.60  13.60  -11.12  -0.3  and let's say that the rest is garbage";
    int n = 28;  // let's say that you received 28 bytes
    std::string strBuff(reinterpret_cast<char*>(buff), n); // construct a string from buff using just first 28 bytes
    std::vector<std::string> numbers;
    boost::split(numbers, strBuff, boost::is_any_of(" "), boost::token_compress_on);
    for (const auto& n : numbers) {
        try {
            std::cout << std::stof(n) << std::endl;
        } catch (const std::exception& e) {
            std::cout << n << " is not convertible to float: " << e.what() << std::endl;
        }
    }
    return 0;
}

I took the string splitting method from this answer but you can use anything that works for you.

I used reinterpret_cast because std::string accepts char instead of unsigned char as a CTor arg.

pptaszni
  • 5,591
  • 5
  • 27
  • 43
  • It is for unsigned char buff, but what I have taken ( Buf is a pointer to a buffer and size the size of the buffer in bytes). In this case, how can I convert? Returns the amount of received characters into the buffer. – uvan May 08 '19 at 10:23