0
votes

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.

2
Try looking up atof/atod/strtod on cppreference.com or cplusplus.com - David Dalcino
Answered here: stackoverflow.com/questions/1012571/… You just need to separate your numbers first, if your data consists of more than one. - pptaszni
@Ptaq666 can you elaborate, I am not getting what is exactly. - uvan
Possible duplicate of std::string to float or double - Clonk
@uvan , elaborated in the answer. Now it's understood? - pptaszni

2 Answers

2
votes

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;
1
votes

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.