Saturday, October 15, 2016

LinuxFlight connecting to CleanFlight Configurator

Just finished updating github LinuxFlight.  CleanFlight Configurator, is not able to connect and start sending MSP packets; but something is hanging up in getting data messages.  Work on that next week.

How to build LinuxFlight (Linux only):
  • Need to build boost C++ libraries and install them 
  • make
  • ./PC
  • open another terminal 
    •  socat -d -d pty,raw,echo=0 tcp:localhost:56000
    • This will create a pty, the output from socat show which pty to connect configurator
      • i.e /dev/pts/9

There is a lot to do to improve the IPC speed, i.e not to copy std::vector, but to use std::move, so there is no copy.  Also, move the IPC queue struct from std::queue to boost::lockfree::queue with a semaphore to wake up the FC thread.  

The heart of the IPC is a send-reply via std::function<void (void)> type function.  So, how can a void function be able to process arguments and do process callbacks?  
  • Use std::bind, this arguments.   For example, in  mspSerialTCPPort.h,  function: handle_read creates a std::function<void (void)> 
                  msgPost_t _msg;
                  mspCallback_t _callback = std::bind(&mspSerialTCPClient::postHandleWrite,                                                                                            shared_from_this(),                                                                                                                                std::placeholders::_1);
                      _msg.m_in = std::bind(&callToMSPFromTCP, _pkt, _callback);

    So, msgPost_t is created with a function callback.  The std::bind takes the packet and places it in one of the arguments.  Along with a call back function.  It is important to use shared_ptr, so the class does not disappear until all callbacks are completed. So, when the function is invoked the arguments are unpacked and the MSP function is call.

    This is a simple way, to keep a callback IPC API and allow any type of arguments.  Yes, it is confusing, but look at the code, run it and debug it. 

    So, the current design is to move most of the I/O from the flight controller main thread, this way I2C. serial, etc are processed out side of the thread.  All data will be posted to the FC thread, this way, this should minimize jitter.  

    Saturday, October 8, 2016

    LinuxFlight github

    After several rounds of code porting and trying to keep the code compatible with a micro-controller decided to just move to Linux only port.

    The goal is to keep the main Flight-Controller loop reads accelerometer, and gyro, and move the reset of the I/O to read threads.  This way keeps the main loop on time.

    Also, the Neo Air is out, so, that will be the FC board with I/O processor.

    • ARM Linux board
      • GPS (Serial)
      • MS5611  (I2C)
      • MPU9250 (SPI)
      • I/O processor (USB)
      • MSP via TCP/IP
      • RX (Need to validate and test serial Ports are able to handle iBUS, or sBUS)
    • I/O processor
      • RX (PWM or Serial)
      • Telemetry
      • PWM out (motor control)
    So, go, but making progress.. 

    Saturday, September 24, 2016

    OrangePI PC with 4.8.x using buildroot

    Finally got some time to get back to testing OrangePI-PC as a Flight Controller board.  The OrangePI-PC offers several advantages over the Pi Zero:
    • Multiple serial ports (3) 
    • Multiple USB ports (each have port has its own controller not a Hub)
    • Camera (Still working on that)
    • Cost is low around $12

    I'm using standard buildroot with the orangePI defconfig, but using a different Linux kernel which has several patches for Ethernet, USB (slave), and thermal control (Which is big).   Using orange-pi-4.8 branch.

    Also made a couple of code changes:
    • spidev 
    static const struct of_device_id spidev_dt_ids[] = {
        { .compatible = "rohm,dh2228fv" },
        { .compatible = "lineartechnology,ltc2488" },
            { .compatible = "spidev" },

    • device tree: 
      • sun8i-h3-orangepi-pc.dts:
            spi0_pins_a: spi0@0 {
                    allwinner,pins = "PC0", "PC1", "PC2";
                    allwinner,function = "spi0";
                    allwinner,drive = <SUN4I_PINCTRL_10_MA>;
                    allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;

        spi0_cs0_pins_a: spi0_cs0@0 {
                    allwinner,pins = "PC3";
                    allwinner,function = "spi0";
                    allwinner,drive = <SUN4I_PINCTRL_10_MA>;
                    allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
            i2c0_pins_a: i2c0@0 {
            allwinner,pins = "PA11", "PA12";
                allwinner,function = "i2c0";
                allwinner,drive = <SUN4I_PINCTRL_10_MA>;
                allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;

    &spi0 {
        pinctrl-names = "default";
        pinctrl-0 = <&spi0_pins_a>, <&spi0_cs0_pins_a>;
        status = "okay";
            spidev0: spidev@0 {
                    #address-cells = <1>;
                #size-cells = <0>;
                compatible = "spidev";
            reg = <0>;
            spi-max-frequency = <50000000>;

    &i2c0 {
        pinctrl-names = "default";
        pinctrl-0 = <&i2c0_pins_a>;
        status = "okay";

        • sun8i-h3.dtsi
            spi0: spi@01c68000 {
                compatible = "allwinner,sun6i-a31-spi";
                reg = <0x01c68000 0x1000>;
                interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
                clock-names= "ahb", "mod";
                resets = <&ccu RST_BUS_SPI0>;
                dmas = <&dma 23>, <&dma 23>;
                dma-names = "rx", "tx";
                status = "disabled";
                #address-cells = <1>;
                #size-cells = <0>;
            i2c0: i2c@01c2ac00 {
                compatible = "allwinner,sun6i-a31-i2c";
                reg = <0x01c2ac00 0x400>;
                interrupts = <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&ccu CLK_BUS_I2C0>;
                resets = <&ccu  RST_BUS_I2C0>;
                status = "disabled";
                #address-cells = <1>;
    #size-cells = <0>;
    So, this adds a SPI interface and another I2C.

    Next is to do some testing with SPI and I2C.

    Also, still adding code to CleanFlight port to Linux.   Please post if you have any questions. 

    Sunday, September 11, 2016

    Cleanflight Fork

    Finally had time to create a github project for CleanFlight fork.  Over the next few weeks will post changes to allow CleanFlight to compile on Linux . 

    There are a couple targets:
    • PC - Allows CleanFlight to run on a PC and connect to a I/O processor
      • Helps in debugging and test with CleanFlight configurator
    • PI Zero
      • Connected a powered USB hub to the PI
        • Connected WIFI dongle
        • Connect I/O processor
    • Orange PI
      • Still working/waiting for some fixes to mainline, but will push forward with the basic camera.
    Right now, working on creating a I/O processor board.  This will be a simple perf board wired up by hand.  The reason for doing this, simple and cheap.  The following sensors will be supported
    • GPS
    • Compass
    • PWM In for RC
    • PWM out to motors
    •  USB

    The board for the PI Zero will also be a perf board.  But, it will use machine pin headers to keep the profile low.  This board will have just two sensors:

    Wednesday, August 24, 2016

    Cleanflight Confgurator

    Finally got CleanFlight Configurator communicating to PI Zero with CleanFlight.  Basic setup:

    1. Chrome With CleanFlight Configurator
      1. socat to create a pty to TCP socket
      2. socat -d -d pty,raw,echo=0 tcp:
        1. socat will display which port it created, i.e /dev/pty/20 then take this device and use it for the serial port "URL" in cleanflight.
    2. PI Zero
      1. CleanFlight Port
        1. TCP server to accept MSP messages
        2. Pipe the MSP messages into Cleanflight

    Gyro information was displayed in the Configurator, need to figure out why compass and accelerometer was not working. 

    Also, need to connect I/O processor to Cleanflight to forward RX info and GPS status.

    Friday, August 19, 2016

    I/O processor status

    Completed PWM input decode and sending results via USB.  For the first pass I'm using a HK-T6A transmitter/receiver.

    Overall Status:

    • I/O processor:  GD32F103 (red pill board) 
      • Interprocess commuinication via USB complete
        • Receiver PWM decode
        • GPS decode
      • Next is to do PWM for motor control
        • Standard PWM out
        • Support one shot125
        • Need validate USB jitter and performance
          • Out should be less then a 1ms
          • In should be no more then 2ms
    • Cleanflight
      • Update IPC using USB
      • Add socat for CleanFlight Configuration Web Tool
        •  open a TCP/IP port in CleanFlight 
        • use socat on Linux to forward MSP packets.

    Friday, July 15, 2016

    CleanFlight port to PI Zero

    Finally have MPU-9255 and MS5611 sensors working and a simple CLI on the command line.  It is simlar to CLI via serial port or CleanFlight configurator.

    Here is the output:
    Task list          max/us  avg/us rate/hz maxload avgload     total/ms
     0 -       SYSTEM      29       0       9    0.5%    0.5%         0
     1 -     GYRO/PID     748     145     848   63.9%   12.7%       743
     3 -       SERIAL      71       1      93    1.1%    0.5%         1
     5 -           RX       0       0   2147483647    0.5%    0.5%         0
    Task list          max/us  avg/us rate/hz maxload avgload     total/ms
     0 -       SYSTEM      31       0       9    0.5%    0.5%         1
     1 -     GYRO/PID     886     176     801   71.4%   14.5%      5864
     3 -       SERIAL      73       1      88    1.1%    0.5%         9
     5 -           RX       0       0   2147483647    0.5%    0.5%         0

    I'm going to switch to linenoise for controlling line processing to allow up and down errors etc. 

    Need to fix how average is calculated, but making progress.  Need to reconnect the I/O processor to get GPS, pwm out, s.bus in, and S.Port.

    The goal is to use socat where configurator is running to expose a virtual serial port and forward the packets to "LinuxFlight".

    Still working on CPU performance and getting GPIO to trigger for gyro-sync.

    Here is top:

    Here is the CLI on the PI Zero:

    The command line is using boost ASIO.  Goal is to add the socat protocol so configurator can still access and configure "LinuxFlight" ;)

    Yes, I'm thinking of forking the code, due to the amount of changes to the core.  Right now, there are very minimal.