Reading data from serial port
-
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?
-
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.
-
@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; } }
-
...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. -
@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.