c++serial-portbaud-rate

How do I change the baud rate for a LoRa device?


I have a LoRa device that uses a default baud rate of 57600 on a USB port of a raspberry pi. I'd like to experiment with faster serial baud rates. The instructions to change the baud rate after returning from a device sleep state are as follows from the datasheet:

enter image description here

I have one major problem in that I don't know what a 'break' code is in serial port communications. I've tried various things, including the following (where usb_port is the file descriptor of the opened port):

ioctl(usb_port, TCSBRK, 0);

and

std::string msg;
msg="0X00";
write(usb_port, msg.c_str(), msg.size());

All with no luck. Can anyone take a look at this c++ function and tell me where I may be going wrong?

From elsewhere in the documentation, it is indicated that writing "0x55" triggers an auto-baud detection setup when returning from sleep.

Note: radiodevice file descriptor of "/dev/ttyUSBPort1" is a reference to /dev/ttyUSB0 that is set up using a udev serial rule.

const char* radiodevice = "/dev/ttyUSBPort1";
int openPort(void) {
    struct termios tty;
    memset(&tty, 0, sizeof tty);
    if ((usb_port = open(radiodevice, O_RDWR | O_NOCTTY | O_SYNC))>=0) {// | O_NOCTTY | O_SYNC
        std::cout << "DEVICE OPENED: " << radiodevice << " handle number: " << usb_port << std::endl;
    } else {
        fprintf(stderr, "unable to open serial radiodevice");
        return -1;
    }
    if(tcgetattr(usb_port, &tty) != 0) {
        printf("Error %i \n", errno);
    }
    cfsetispeed(&tty, B57600);
    cfsetospeed(&tty, B57600);
    tty.c_cflag     &=  ~PARENB;            // Make 8n1
    tty.c_cflag     &=  ~CSTOPB;
    tty.c_cflag     &=  ~CSIZE;
    tty.c_cflag     |=  CS8;
    tty.c_cflag     &=  ~CRTSCTS;           // no flow control
    tty.c_cc[VMIN]   =  0;                  // read doesn't block
    tty.c_cc[VTIME]  =  5;                  // 0.5 seconds read timeout
    tty.c_iflag &= ~ISTRIP;
    tty.c_iflag &= ~INLCR;
    tty.c_iflag &= ~IGNCR;
    tty.c_iflag &= ~ICRNL;
    tty.c_oflag &= OPOST;
    tty.c_lflag &= ICANON;
    tcflush(usb_port,TCIOFLUSH);
    usleep(10000);
    if (tcsetattr(usb_port, TCSANOW, &tty) != 0) {
        printf("Error %i\n", errno);
    }

    //FLASH UNIT LED LIGHTS TO CONFIRM INITIAL CONNECTION
    std::string msg="sys set pindig GPIO11 1\r\n";
    write(usb_port, msg.c_str(), msg.size());
    usleep(1000000);
    msg="sys set pindig GPIO11 0\r\n";
    write(usb_port, msg.c_str(), msg.size());
    usleep(10000);

    //WRITE SLEEP COMMAND TO DEVICE FOR 0.5 SECONDS
    std::cout << "WRITING SLEEP COMMAND" << std::endl;
    msg="sys sleep 5000\r\n";//
    write(usb_port, msg.c_str(), msg.size());
    usleep(100000);

    //ATTEMPT TO SEND BREAK COMMAND
    ioctl(usb_port, TCSBRK, 0);
    usleep(500000);

    //RESET SERIAL BAUD RATE
    cfsetispeed(&tty, B115200);
    cfsetospeed(&tty, B115200);

    //SET DEVICE TO AUTO-BAUD RATE DETECTION
    std::cout << "SENDING 0x55" << std::endl;
    msg="0x55";
    write(usb_port, msg.c_str(), msg.size());
    usleep(2000000);

    //FLASH UNIT LED LIGHTS TO CONFIRM FINAL CONNECTION AT NEW BAUD RATE
    std::cout << "BLINKING LIGHTS" << std::endl;
    msg="sys set pindig GPIO11 1\r\n";
    write(usb_port, msg.c_str(), msg.size());
    usleep(1000000);
    msg="sys set pindig GPIO11 0\r\n";
    write(usb_port, msg.c_str(), msg.size());

    return usb_port;
}

Solution

  • For those that may be searching for this solution down the road, here's the way I accomplished the task of setting the LoRa device into auto baud mode and opening the port at the new baud rate:

        int openPort(void) {
            struct termios tty;
            memset(&tty, 0, sizeof tty);
            //OPEN PORT WITH DEFAULT BAUD RATE 57600
            if ((usb_port = open(radiodevice, O_RDWR | O_NOCTTY | O_SYNC))>=0) {// | O_NOCTTY | O_SYNC
                std::cout << "DEVICE OPENED: " << radiodevice << " handle number: " << usb_port << std::endl;
            } else {
                fprintf(stderr, "unable to open serial radiodevice");
                return -1;
            }
            if(tcgetattr(usb_port, &tty) != 0) {
                printf("Error %i \n", errno);
            }
            cfsetispeed(&tty, B57600);
            cfsetospeed(&tty, B57600);
            tty.c_cflag     &=  ~PARENB;            // Make 8n1
            tty.c_cflag     &=  ~CSTOPB;
            tty.c_cflag     &=  ~CSIZE;
            tty.c_cflag     |=  CS8;
            tty.c_cflag     &=  ~CRTSCTS;           // no flow control
            tty.c_cc[VMIN]   =  0;                  // read doesn't block
            tty.c_cc[VTIME]  =  5;                  // 0.5 seconds read timeout
            tty.c_iflag &= ~ISTRIP;
            tty.c_iflag &= ~INLCR;
            tty.c_iflag &= ~IGNCR;
            tty.c_iflag &= ~ICRNL;
            tty.c_oflag &= OPOST;
            tty.c_lflag &= ICANON;
            tcflush(usb_port,TCIOFLUSH);
            //usleep(10000);
            if (tcsetattr(usb_port, TCSANOW, &tty) != 0) {
                printf("Error %i\n", errno);
            }
    
            //FLASH UNIT LED LIGHTS TO CONFIRM INITIAL CONNECTION
            std::string msg="sys set pindig GPIO11 1\r\n";
            write(usb_port, msg.c_str(), msg.size());
            usleep(1000000);
            msg="sys set pindig GPIO11 0\r\n";
            write(usb_port, msg.c_str(), msg.size());
            usleep(10000);
    
            //WRITE SLEEP COMMAND TO DEVICE FOR 0.5 SECONDS
            std::cout << "WRITING SLEEP COMMAND" << std::endl;
            msg="sys sleep 5000\r\n";
            write(usb_port, msg.c_str(), msg.size());
            usleep(100000);
    
            close(usb_port);
    
            //OPEN PORT AT NEW BAUD RATE
            if ((usb_port = open(radiodevice, O_RDWR | O_NOCTTY | O_SYNC))>=0) {// | O_NOCTTY | O_SYNC
                std::cout << "DEVICE OPENED: " << radiodevice << " handle number: " << usb_port << std::endl;
            } else {
                fprintf(stderr, "unable to open serial radiodevice");
                return -1;
            }
            if(tcgetattr(usb_port, &tty) != 0) {
                printf("Error %i \n", errno);
            }
    
            //RESET SERIAL BAUD RATE
            cfsetispeed(&tty, B230400);<---SET NEW BAUD RATE VALUE
            cfsetospeed(&tty, B230400);<---SET NEW BAUD RATE VALUE
            tty.c_cflag     &=  ~PARENB;            // Make 8n1
            tty.c_cflag     &=  ~CSTOPB;
            tty.c_cflag     &=  ~CSIZE;
            tty.c_cflag     |=  CS8;
            tty.c_cflag     &=  ~CRTSCTS;           // no flow control
            tty.c_cc[VMIN]   =  0;                  // read doesn't block
            tty.c_cc[VTIME]  =  5;                  // 0.5 seconds read timeout
            tty.c_iflag &= ~ISTRIP;
            tty.c_iflag &= ~INLCR;
            tty.c_iflag &= ~IGNCR;
            tty.c_iflag &= ~ICRNL;
            tty.c_oflag &= OPOST;
            tty.c_lflag &= ICANON;
            tcflush(usb_port,TCIOFLUSH);
            usleep(10000);
            if (tcsetattr(usb_port, TCSANOW, &tty) != 0) {
                printf("Error %i\n", errno);
            }
    
            //SEND BREAK COMMAND
            std::cout << "SENDING BREAK COMMAND" << std::endl;
            tcsendbreak(usb_port, 0);
            usleep(10000);
    
            //SET DEVICE TO AUTO-BAUD RATE DETECTION
            msg = "U";//CORRESPONDS TO DOCUMENTED CHARACTER 0x55
            write(usb_port, msg.c_str(), msg.size());
    
            //FLASH UNIT LED LIGHTS TO CONFIRM FINAL CONNECTION AT NEW BAUD RATE
            std::cout << "BLINKING LIGHTS" << std::endl;
            msg="sys set pindig GPIO11 1\r\n";
            write(usb_port, msg.c_str(), msg.size());
            usleep(1000000);
            msg="sys set pindig GPIO11 0\r\n";
            write(usb_port, msg.c_str(), msg.size());
    
            return usb_port;
        }