0
votes

I want to send some serial output through the pins of my raspberrypi for serial communication with a drone flight controller. The controller only operates at a strange 100000 baudrate.

  1. My code does not always set the baudrate correctly. Sometimes I have to reboot and restart the code 5 times to get the right baudrate.

  2. The code does not send the requested data. It sends much more. The serial output of the console is disabled (by raspi-config).

I tried writing it in python, but the code is running too slow (I need image processing with OpenCV too) so I switched to C++. The python code was working fine. I already tried the serial library by wjwood : http://wjwwood.github.com/serial/ but it is also not working correctly whit the strange baudrate. Setting the baudrate with the stty command failed too. I tried setting the baudrate with the setispeed functions and the old termios structure. This didn't work too.

This is my code:

#include <fcntl.h>
#include <unistd.h>
#include <stropts.h>
#include <asm/termios.h>

#include <iostream>

int main()
{
   int fd_ = ::open("/dev/ttyAMA0", O_RDWR);

   struct termios2 options;

   ioctl(fd_, TCGETS2, &options);
   options.c_cflag |= PARENB;
   options.c_cflag &= ~CBAUD;
   options.c_cflag |= BOTHER;
   options.c_ispeed = 100000;
   options.c_ospeed = 100000;
   options.c_cc[VTIME] = 10;
   options.c_cc[VMIN] = 0;

   unsigned char buf[25];
   for (int i = 0; i != 25; i++)
   {
      buf[i] = 2 * i;
   }
   ioctl(fd_, TCSETS2, &options);

   for (int i = 0; i != 25; i++)
   {
      std::cout << static_cast<int>(buf[i]) << " ";
   }
   std::cout << std::endl;

   ::write(fd_, &buf, 25);
   ::close(fd_);
}

Expected is a serial output like: 0x00 0x02 0x04 ... 0x30. But I get: 0x5E 0x4F 0x5E 0x40 ... 0x00 0x02 0x04 ... 0x30.

The more I send the more additional useless bytes are blocking the bus and confusing the flight controller.

1
The controller only operates at a strange 100000 baudrate this makes things hard. You need to provide a valid speed_t value, and 100000 probably isn't valid. Is How to set baud rate to 307200 on Linux? any help?user4581301
I saw that post earlier and used the code to set the baurate. If it worked to set the baudrate, it stayed so until a reboot. But the strange additional bytes are the bigger problem.NurZumTest
This shouldn't help (and if it somehow does, I'm going to have to read more deeply into what the Standard says about the relationship between arrays and pointers) but I'm always leery of stuff like ::write(fd_, &buf, 25);. buf is an array. It automatically decays to a pointer. Remove a potential point of confusion from the code with ::write(fd_, buf, 25);.user4581301
A serial link requires the same configuration of baud rate, character size, parity, and number of stop bits at both ends. You neglect to mention how the serial port on this "drone flight controller" is configured. Your program only configures two parameters, and leaves the other two parameters to chance. IOW your termios configuration is incomplete. Do not expect reliable serial communications. BTW how are you determining what the "wrong" serial output is?sawdust
The controller uses 100000 baud, 8 bits per byte (which is set by default), even parity (like it's set), an one stopbit (default). I measured the serial communication with a logic analyzer. The only problem is the baud rate, the rest is properly set. The right output is determined by the first loop (0 to 48 with a stepsize of to, which should get 0x00, 0x02 etc. in hex on the serial bus. But there is more on the bus, like I wrote.NurZumTest

1 Answers

0
votes

Thanks to sawdust, I know, that the problem was relying on the flags which are "set by default". Because they weren't. To fix my code, I added those flags, with the help of this guide about Linux serial programming:

options.c_cflag &= ~CRTSCTS;
options.c_cflag |= CREAD | CLOCAL;
options.c_lflag &= ~ICANON;
options.c_lflag &= ~ECHO;
options.c_lflag &= ~ECHOE;
options.c_lflag &= ~ECHONL;
options.c_lflag &= ~ISIG;
options.c_iflag &= ~(IXON | IXOFF | IXANY);
options.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL);
options.c_oflag &= ~OPOST; 
options.c_oflag &= ~ONLCR;