Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Reading data from serial port
QtWS25 Last Chance

Reading data from serial port

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 3 Posters 296 Views
  • 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.
  • S Offline
    S Offline
    serkan_tr
    wrote on 7 Jun 2023, 13:50 last edited by
    #1
    Serial::Serial(): _baudrate(BAUDRATE){
        _serial_port = new QSerialPort;
        if(portDetect()){
            while(_serial_port->open(QIODevice::ReadOnly)){
                qDebug() << "ReadOnly";
            }
                QObject::connect(this->_serial_port, &QSerialPort::readyRead, this, &Serial::readBytes);
            }
    }
    
    Serial::~Serial(){
        _serial_port->close();
        delete _serial_port;
    }
    
    bool Serial::portDetect(){
        for(const QSerialPortInfo port_list : QSerialPortInfo::availablePorts()){
            if(port_list.description() == "Arduino Mega 2560" ){
                _serial_port->setPortName(port_list.portName());
                _serial_port->setBaudRate(_baudrate);
                _serial_port->setDataBits(QSerialPort::Data8);
                #ifdef DEBUG
                qDebug() << "-----------------------------------------------------";
                qDebug() << "portName:          " << port_list.portName();
                qDebug() << "systemLocation:    " << port_list.systemLocation();
                qDebug() << "description:       " << port_list.description();
                qDebug() << "manufacturer:      " << port_list.manufacturer();
                qDebug() << "serialNumber:      " << port_list.serialNumber();
                qDebug() << "vendorIdentifier:  " << port_list.vendorIdentifier();
                qDebug() << "productIdentifier: " << port_list.productIdentifier();
                #endif
                return true;
            }
        }   
        return false;
    }
    
    void Serial::readBytes(){
        while(_serial_port->bytesAvailable()){
            uint8_t cur_byte;
            _serial_port->read((char*)&cur_byte, 1);
            qDebug() << cur_byte;
        }
    }
    
    

    I am reading data from serial port. I constantly detect where the card I will read is inserted and read that port. it does port scan and reads only the card I mentioned. but when I remove and insert the card, it does not read again because the port is not closed. My aim is to not delete the serial object when I remove the port, just close it with close and when it is reconnected, it will open and read from the wheel. Can this be done?

    S B 2 Replies Last reply 7 Jun 2023, 18:51
    0
    • S Offline
      S Offline
      serkan_tr
      wrote 30 days ago last edited by
      #6

      I made the necessary modifications. In this part, I monitor the port at specific intervals and close the port if there is a change in the list of connected cards. This ensures that the port automatically connects and closes when the card is removed. My code is as follows, and you can access it on this GitHub page.

      1 Reply Last reply
      0
      • S serkan_tr
        7 Jun 2023, 13:50
        Serial::Serial(): _baudrate(BAUDRATE){
            _serial_port = new QSerialPort;
            if(portDetect()){
                while(_serial_port->open(QIODevice::ReadOnly)){
                    qDebug() << "ReadOnly";
                }
                    QObject::connect(this->_serial_port, &QSerialPort::readyRead, this, &Serial::readBytes);
                }
        }
        
        Serial::~Serial(){
            _serial_port->close();
            delete _serial_port;
        }
        
        bool Serial::portDetect(){
            for(const QSerialPortInfo port_list : QSerialPortInfo::availablePorts()){
                if(port_list.description() == "Arduino Mega 2560" ){
                    _serial_port->setPortName(port_list.portName());
                    _serial_port->setBaudRate(_baudrate);
                    _serial_port->setDataBits(QSerialPort::Data8);
                    #ifdef DEBUG
                    qDebug() << "-----------------------------------------------------";
                    qDebug() << "portName:          " << port_list.portName();
                    qDebug() << "systemLocation:    " << port_list.systemLocation();
                    qDebug() << "description:       " << port_list.description();
                    qDebug() << "manufacturer:      " << port_list.manufacturer();
                    qDebug() << "serialNumber:      " << port_list.serialNumber();
                    qDebug() << "vendorIdentifier:  " << port_list.vendorIdentifier();
                    qDebug() << "productIdentifier: " << port_list.productIdentifier();
                    #endif
                    return true;
                }
            }   
            return false;
        }
        
        void Serial::readBytes(){
            while(_serial_port->bytesAvailable()){
                uint8_t cur_byte;
                _serial_port->read((char*)&cur_byte, 1);
                qDebug() << cur_byte;
            }
        }
        
        

        I am reading data from serial port. I constantly detect where the card I will read is inserted and read that port. it does port scan and reads only the card I mentioned. but when I remove and insert the card, it does not read again because the port is not closed. My aim is to not delete the serial object when I remove the port, just close it with close and when it is reconnected, it will open and read from the wheel. Can this be done?

        S Offline
        S Offline
        SGaist
        Lifetime Qt Champion
        wrote on 7 Jun 2023, 18:51 last edited by
        #2

        Hi,

        You might want to use something like KDE's Solid framework for the hardware management part.

        Or maybe QtUsb to detect the hardware change and act on it.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        S 1 Reply Last reply 13 Jun 2023, 05:46
        2
        • S SGaist
          7 Jun 2023, 18:51

          Hi,

          You might want to use something like KDE's Solid framework for the hardware management part.

          Or maybe QtUsb to detect the hardware change and act on it.

          S Offline
          S Offline
          serkan_tr
          wrote on 13 Jun 2023, 05:46 last edited by
          #3

          @SGaist Is there any way to do it other than these two methods? I'm currently solving this problem with the following code, but it seems not very safe

          #include "SerialComm.hpp"
          #include <QSerialPortInfo>
          #define VOLTAGE_DEBUG
          // #define DEBUG
          
          Serial::Serial(): state(0), count(0), voltage(0), cam_value(0){
              port_ = new QSerialPort;
          
              connectionTimer = new QTimer(this);
              connectionTimer->setInterval(100);
              connectionTimer->start();
          
              raw_data.resize(V_SIZE);
              stable_data.resize(V_SIZE);
              joy_offset.resize(JOY_ALL);
              initializationData(RESET_ALL);
          
              checkDeviceConnection();
          
              connect(port_, &QSerialPort::readyRead, this, &Serial::readBytes);
              connect(port_, &QSerialPort::errorOccurred, this, [this]() { connectionTimer->start(); });
              connect(connectionTimer, &QTimer::timeout, this, &Serial::checkDeviceConnection);
          }
          
          Serial::~Serial(){
              port_->close();
              connectionTimer->stop();
              delete connectionTimer;
              delete port_;
          }
          
          void Serial::checkDeviceConnection(){
              if(port_->isOpen()) {  port_->close();  }
          
              for(const QSerialPortInfo port_list : QSerialPortInfo::availablePorts()){
                  if((port_list.manufacturer() == "FTDI") || (port_list.description() == "Arduino Mega 2560") ){
                      port_->setPortName(port_list.portName());
                      port_->setBaudRate(BAUDRATE);
                      port_->setDataBits(QSerialPort::Data8);
                      start_com = true;
                      while(port_->open(QIODevice::ReadOnly)){  qDebug() << "ReadOnly";   }
                      connectionTimer->stop();
                  }
          #ifdef DEBUG
                  qDebug() << "-----------------------------------------------------";
                  qDebug() << "portName:          " << port_list.portName();
                  qDebug() << "systemLocation:    " << port_list.systemLocation();
                  qDebug() << "description:       " << port_list.description();
                  qDebug() << "manufacturer:      " << port_list.manufacturer();
                  qDebug() << "serialNumber:      " << port_list.serialNumber();
                  qDebug() << "vendorIdentifier:  " << port_list.vendorIdentifier();
                  qDebug() << "productIdentifier: " << port_list.productIdentifier();
          #endif
              }
          }
          
          void Serial::readBytes(){
              while(port_->bytesAvailable()){
                  uint8_t cur_byte;
                  port_->read((char*)&cur_byte, 1);
                  if(state == 0){
                      if((cur_byte == HEADER) && (prev_byte == FOOTHER)){ rx_buffer[state++] = cur_byte; }
                      else { state = 0; }
                  }else if( state < HEADER_LEN + PAYLOAD_LEN){
                      rx_buffer[state++] = cur_byte;
                  }else if(state < HEADER_LEN + FOOTHER_LEN + PAYLOAD_LEN){
                      state = 0;
                      prev_byte = cur_byte;
                      if(cur_byte == FOOTHER){
                          raw_data[0] = (static_cast<int16_t>(rx_buffer[1] & 0x01));
                          raw_data[1] = (static_cast<int16_t>((rx_buffer[1]>>1) & 0x01));
                          raw_data[2] = (static_cast<int16_t>((rx_buffer[1]>>2) & 0x01));
                          raw_data[3] = (static_cast<int16_t>((rx_buffer[1]>>3) & 0x01));
                          raw_data[4] = (static_cast<int16_t>((rx_buffer[1] >> 4) | ((rx_buffer[2] << 4) & 0x03FF)));
                          raw_data[5] = (static_cast<int16_t>((rx_buffer[2] >> 6) | ((rx_buffer[3] << 2) & 0x03FF)));
                          raw_data[6] = (static_cast<int16_t>((rx_buffer[4])      | ((rx_buffer[5] << 8) & 0x03FF)));
                          raw_data[7] = (static_cast<int16_t>((rx_buffer[5] >> 2) | ((rx_buffer[6] << 6) & 0x03FF)));
                          raw_data[8] = (static_cast<int16_t>((rx_buffer[6] >> 4) | ((rx_buffer[7] << 4) & 0x03FF)));
                          raw_data[9] = (static_cast<int16_t>((rx_buffer[7] >> 6) | ((rx_buffer[8] << 2) & 0x03FF)));
                      }else{ state = 0;  }
                  }else    { state = 0;  }
                  prev_byte = cur_byte;
              }
          }
          
          void Serial::bufferCopy(QVector<int>& data){
              std::copy(raw_data.begin(), raw_data.end(), stable_data.begin());
          
              stable_data[QGC_VOL] = voltageFilter((float)raw_data[QGC_VOL]);
              stable_data[QGC_CAM] = camSliderFilter(raw_data[QGC_CAM]);
              stable_data[QGC_RX] = joyDataFilter(raw_data[4], JOY_RX);
              stable_data[QGC_RY] = joyDataFilter(raw_data[5], JOY_RY);
              stable_data[QGC_LX] = joyDataFilter(raw_data[8], JOY_LX);
              stable_data[QGC_LY] = joyDataFilter(raw_data[6], JOY_LY);
              std::copy(stable_data.begin(), stable_data.end(), data.begin());
          
          #ifdef DEBUG
              qDebug() << "Genel:" <<  raw_data[4] << raw_data[5] << raw_data[6] << raw_data[8];
              qDebug() << "Data: " << stable_data[QGC_RX] << stable_data[QGC_RY] << stable_data[QGC_LX] << stable_data[QGC_LY];
          #endif
          }
          
          int Serial::voltageFilter(float new_data){
          #ifdef VOLTAGE_DEBUG
              qDebug() << "voltage raw_data: " << new_data;
          #endif 
              new_data = filter[5].kalman(new_data);
              if(new_data < 610.0 || new_data > 860.0) { return -1; }
              new_data = map(new_data, 610.0, 860.0, 0.0, 100.0);
              if(filter[6].getKalmanDataOld() == 0){ filter[6].setKalmanDataOld(new_data);  }
              filter[6].setQR(0.005, 0.995);
              return (int)filter[6].kalman(new_data);  
          }
          
          int Serial::camSliderFilter(float new_data){
          #ifdef CAM_SLIDER_DEBUG
              qDebug() << "Cam slider raw_data: " << new_data;
          #endif 
              new_data = filter[4].kalman(new_data);
              if(new_data > (512 + OFFSET_CAM) ) { return cam_value += 5; }
              else if(new_data < (512 - OFFSET_CAM)) { return cam_value -= 5; }
              new_data  = constrain(new_data, 0.0, 1023.0);
              return (int)cam_value;
          }
          
          void Serial::calibrateJoy(){
              if(count == CALIBRATE_COUNT){
                  joy_offset[JOY_RX] /= CALIBRATE_COUNT;  
                  joy_offset[JOY_RY] /= CALIBRATE_COUNT;  
                  joy_offset[JOY_LX] /= CALIBRATE_COUNT;  
                  joy_offset[JOY_LY] /= CALIBRATE_COUNT;  
                  calibrated = false;
              }else if(calibrated){
                  joy_offset[JOY_RX] +=  filter[JOY_RX].kalman(constrain(raw_data[4], 0.0, 1023.0));
                  joy_offset[JOY_RY] +=  filter[JOY_RY].kalman(constrain(raw_data[5], 0.0, 1023.0));
                  joy_offset[JOY_LX] +=  filter[JOY_LX].kalman(constrain(raw_data[8], 0.0, 1023.0));
                  joy_offset[JOY_LY] +=  filter[JOY_LY].kalman(constrain(raw_data[6], 0.0, 1023.0));
              }
              count++;
          }
          
          int Serial::joyDataFilter(float new_data, JoyData_e joy_num){
              new_data = constrain(new_data, JOY_MIN_OFFSET, JOY_MAX_OFFSET);
              new_data = filter[joy_num].kalman(new_data);
              if((new_data > (joy_offset[joy_num] - JOY_OFFSET)) && (new_data < (joy_offset[joy_num] + JOY_OFFSET))){
                  new_data = 512;
              }else if(new_data <= (joy_offset[joy_num] - JOY_OFFSET)){
                  new_data = map(new_data, JOY_MIN_OFFSET, joy_offset[joy_num] - JOY_OFFSET, 0.0, 511.0);        
              }else{
                  new_data = map(new_data, joy_offset[joy_num] + JOY_OFFSET, JOY_MAX_OFFSET, 513.0, 1023.0);
              }
              new_data = map(new_data, 0, 1023, 0.0, 150.0);
              return (int)new_data;
          }
          
          void Serial::initializationData(DataReset_e n_data){
              switch (n_data){
                  case RAW_DATA_R:
                      std::fill(raw_data.begin(), raw_data.end(), 0);
                      break;
                  case STABLE_DATA_R:
                      std::fill(stable_data.begin(), stable_data.end(), 0); 
                      break;
                  case JOY_OFFSET_R:
                      std::fill(joy_offset.begin(), joy_offset.end(), 512);
                      break;
                  case JOY_OFFSET_Z:
                      std::fill(joy_offset.begin(), joy_offset.end(), 0);
                      calibrated = true; 
                      count = 0;
                      break;
                  case RESET_ALL:
                      std::fill(raw_data.begin(), raw_data.end(), 0);
                      std::fill(stable_data.begin(), stable_data.end(), 0); 
                      std::fill(joy_offset.begin(), joy_offset.end(), 512);
                      break;
                  default:
                      break;
              }
          }
          
          1 Reply Last reply
          0
          • S serkan_tr
            7 Jun 2023, 13:50
            Serial::Serial(): _baudrate(BAUDRATE){
                _serial_port = new QSerialPort;
                if(portDetect()){
                    while(_serial_port->open(QIODevice::ReadOnly)){
                        qDebug() << "ReadOnly";
                    }
                        QObject::connect(this->_serial_port, &QSerialPort::readyRead, this, &Serial::readBytes);
                    }
            }
            
            Serial::~Serial(){
                _serial_port->close();
                delete _serial_port;
            }
            
            bool Serial::portDetect(){
                for(const QSerialPortInfo port_list : QSerialPortInfo::availablePorts()){
                    if(port_list.description() == "Arduino Mega 2560" ){
                        _serial_port->setPortName(port_list.portName());
                        _serial_port->setBaudRate(_baudrate);
                        _serial_port->setDataBits(QSerialPort::Data8);
                        #ifdef DEBUG
                        qDebug() << "-----------------------------------------------------";
                        qDebug() << "portName:          " << port_list.portName();
                        qDebug() << "systemLocation:    " << port_list.systemLocation();
                        qDebug() << "description:       " << port_list.description();
                        qDebug() << "manufacturer:      " << port_list.manufacturer();
                        qDebug() << "serialNumber:      " << port_list.serialNumber();
                        qDebug() << "vendorIdentifier:  " << port_list.vendorIdentifier();
                        qDebug() << "productIdentifier: " << port_list.productIdentifier();
                        #endif
                        return true;
                    }
                }   
                return false;
            }
            
            void Serial::readBytes(){
                while(_serial_port->bytesAvailable()){
                    uint8_t cur_byte;
                    _serial_port->read((char*)&cur_byte, 1);
                    qDebug() << cur_byte;
                }
            }
            
            

            I am reading data from serial port. I constantly detect where the card I will read is inserted and read that port. it does port scan and reads only the card I mentioned. but when I remove and insert the card, it does not read again because the port is not closed. My aim is to not delete the serial object when I remove the port, just close it with close and when it is reconnected, it will open and read from the wheel. Can this be done?

            B Offline
            B Offline
            BosGemiler
            wrote on 13 Jun 2023, 07:44 last edited by
            #4

            ...but when I remove and insert the card, it does not read again because the port is not closed....

            Hi @serkan_tr ,
            Do you need to be notified when serialport is inserted or removed ?
            I don't know which platform you use. But for linux platform, you can take a look at using DBus with libdbus-glib.

            https://packages.debian.org/sid/libdbus-1-3

            https://stackoverflow.com/questions/14144781/receiving-notification-event-signal-of-usb-device-insertion-in-c

            http://www.matthew.ath.cx/articles/dbus

            S 1 Reply Last reply 13 Jun 2023, 11:11
            0
            • B BosGemiler
              13 Jun 2023, 07:44

              ...but when I remove and insert the card, it does not read again because the port is not closed....

              Hi @serkan_tr ,
              Do you need to be notified when serialport is inserted or removed ?
              I don't know which platform you use. But for linux platform, you can take a look at using DBus with libdbus-glib.

              https://packages.debian.org/sid/libdbus-1-3

              https://stackoverflow.com/questions/14144781/receiving-notification-event-signal-of-usb-device-insertion-in-c

              http://www.matthew.ath.cx/articles/dbus

              S Offline
              S Offline
              serkan_tr
              wrote on 13 Jun 2023, 11:11 last edited by
              #5

              @BosGemiler
              I am currently working on windows operating system. My goal is to prevent the screen from freezing when the connection is lost in unusual situations such as contactlessness, etc. I want the data stream to continue to flow the same as when the connection is restored.

              1 Reply Last reply
              0
              • S Offline
                S Offline
                serkan_tr
                wrote 30 days ago last edited by
                #6

                I made the necessary modifications. In this part, I monitor the port at specific intervals and close the port if there is a change in the list of connected cards. This ensures that the port automatically connects and closes when the card is removed. My code is as follows, and you can access it on this GitHub page.

                1 Reply Last reply
                0
                • S serkan_tr has marked this topic as solved 30 days ago

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved