Giter Site home page Giter Site logo

pymultiwii's Introduction

Altax

pyMultiWii

Handles the MultiWii Serial Protocol to send/receive data from boards.

This is a text based / console, no GUI, it works reading data from the multicopter and/or sending commands from a computer via a serial modem. I use this module for doing different request to my multicopters in order to control them wirelessly via a raspberry pie.

Installation

To install with pip run the following command from this directory,

pip install .

How?

Just create a MultiWii object that receives the serial port address as parameter and then you can ask for a MSP command by using the function getData, an explicit example looks like this:

from pymultiwii import MultiWii

serialPort = "/dev/tty.usbserial-A101CCVF"
board = MultiWii(serialPort)
    while True:
		print board.getData(MultiWii.ATTITUDE)

With the example above, you will see a stream of data on your terminal.

ScreenShot

MultiWii Serial Protocol

MSP is a protocol designed by the MultiWii community, with the idea to be light, generic, bit wire efficient, secure. The MSP data frames are structured as:

$<header>,<direction>,<size>,<command>,<crc>$

where:

  • header: the ASCII characters $\$M$
  • direction: the ASCII character $<$ if the message goes to the MultiWii board or $>$ if the message is coming from the board
  • size: number of data bytes, binary. Can be zero as in the case of a data request to the board
  • command: message id of MSP
  • data: values to be sent. UINT16 values are LSB first
  • crc: (cyclic redundancy check) checksum, XOR of $<size>,<command>$ and each data byte into a zero sum

Data Flow

There is basically three types of messages to interact with a MultiWii board. Those are command, request and response. Command is an incoming message without implicit outgoing response from the board, request is an incoming message with implicit outgoing response while response is the outgoing message resulting from an incoming request.

If, e.g., the orientation of the board is needed, then a message with type request and ID = 108 must be created and then sent to the board, after being sent, the board will reply with a response.

Performance

The entire implementation of this module does not include a sleep function, which means that is very fast and efficient, the rate of communication would then depend on the computer and the board capabilities.

The module is also designed to be extremely simple to use, the next code will request and print (to the host computer) the orientation of the a MultiWii board connected to a USB port:

from pyMultiwii import MultiWii
from sys import stdout

if __name__ == "__main__":
    board = MultiWii("/dev/ttyUSB0")
    try:
        while True:
            board.getData(MultiWii.ATTITUDE)
            print board.attitude 
    except Exception,error:
        print "Error on Main: "+str(error)

This module can achieve communication back and forth of 300hz, this was achieved using a Naze32 (32bits micro-controller) board and a Odroid U3. And around 62.5hz when using a MultiWii AIO 2.0 (8bits micro-controller) board and a Raspberry Pi.

Boards update

8bit boards

When using an 8bit MultiWii board, please change the wakeup time on the main file at line 84. The old boards need more than 10 seconds to boot up in order to be ready to start asking for data. A safe time would be:

"""Time to wait until the board becomes operational"""
wakeup = 14

32bit boards

If you're using something similar to a naze32 using either baseflight or cleanflight you will be able to ask for attitude and some other commands, but by default you will not be able to use the MSP_SET_RAW_RC to write pilot commands to the multiwii. In order to do that you need to activate (via the baseflight/cleanflight GUI) the SerialRX with the specific type for MSP (MultiWii Serial Protocol). The instructions for doing that on baseflight are:

  • Open the CLI (while on the baseflight configurator) and type:
feature SERIALRX

and then type the following lines:

set serialrx_type=4

This will activate "msp" in order to control the multiwii via that protocol. Important: when type=4 is active, standard radio will not work... (at least on the releases I'm using).

Then you can carefully test my example "test-arm-disarm.py"... You will see the motors spin for 3 seconds. ¡¡BE CAREFUL!!

Example:

This code has no time.sleep(), so, its very fast and efficient. The output looks like this when asking or ATTITUDE:

{'timestamp': 1417432436.878697, 'elapsed': 0.016, 'angx': -26.8, 'angy': -24.8, 'heading': -84.0}
{'timestamp': 1417432436.894663, 'elapsed': 0.016, 'angx': -26.8, 'angy': -24.7, 'heading': -84.0}
{'timestamp': 1417432436.910673, 'elapsed': 0.016, 'angx': -26.7, 'angy': -24.8, 'heading': -84.0}
{'timestamp': 1417432436.926812, 'elapsed': 0.016, 'angx': -26.7, 'angy': -24.7, 'heading': -84.0}
{'timestamp': 1417432436.942629, 'elapsed': 0.016, 'angx': -26.7, 'angy': -24.7, 'heading': -84.0}
{'timestamp': 1417432436.958657, 'elapsed': 0.016, 'angx': -26.7, 'angy': -24.6, 'heading': -84.0}
{'timestamp': 1417432436.974627, 'elapsed': 0.016, 'angx': -26.7, 'angy': -24.6, 'heading': -84.0}
{'timestamp': 1417432436.990591, 'elapsed': 0.016, 'angx': -26.7, 'angy': -24.5, 'heading': -84.0}
{'timestamp': 1417432437.006598, 'elapsed': 0.016, 'angx': -26.7, 'angy': -24.5, 'heading': -84.0}
{'timestamp': 1417432437.022676, 'elapsed': 0.016, 'angx': -26.6, 'angy': -24.5, 'heading': -84.0}
{'timestamp': 1417432437.038604, 'elapsed': 0.016, 'angx': -26.6, 'angy': -24.4, 'heading': -85.0}
{'timestamp': 1417432437.054619, 'elapsed': 0.016, 'angx': -26.7, 'angy': -24.4, 'heading': -85.0}
{'timestamp': 1417432437.070593, 'elapsed': 0.016, 'angx': -26.6, 'angy': -24.3, 'heading': -85.0}
{'timestamp': 1417432437.086576, 'elapsed': 0.016, 'angx': -26.6, 'angy': -24.3, 'heading': -85.0}
{'timestamp': 1417432437.102768, 'elapsed': 0.016, 'angx': -26.7, 'angy': -24.2, 'heading': -85.0}
{'timestamp': 1417432437.118586, 'elapsed': 0.016, 'angx': -26.6, 'angy': -24.2, 'heading': -85.0}
{'timestamp': 1417432437.134683, 'elapsed': 0.016, 'angx': -26.6, 'angy': -24.2, 'heading': -85.0}
{'timestamp': 1417432437.150524, 'elapsed': 0.016, 'angx': -26.6, 'angy': -24.1, 'heading': -85.0}
{'timestamp': 1417432437.166525, 'elapsed': 0.016, 'angx': -26.6, 'angy': -24.1, 'heading': -85.0}

Using different devices and newer boards you can achieve greater rates of communication, using an oDroid U3 and a naze32 I have achieved close to 300hz.

Video usages:

Multiwii joystick (naze32)

Drone Pilot - Position hold controller (raspberry pi + naze32)

Drone Pilot - Trajectory controller (raspberry pi + naze32)

Caution

This code is still somewhat under development, if you found a bug or a improvement, please let me know!!

Why?

I'm doing systems identification of multicopters being flown by me via a multiwii board. Why do I want to do this? I want to do very precise navigation algorithms using a motion capture system.

Systems identification is a statistical method to build mathematical models of the multicopters, to have excellent control we require a perfect mathematical model. In order to do a good sysid we require data, lots of data, data coming from the board as well as the pilot and the position in the space (motion capture), so, I require raw imu (accelerometers and gyroscopes), pilot commands (rc channels) and position (x,y,z).

So far, I have a position controller working with the multiwii board being flow by simulink using data from the motion capture system and just sending rc channels via a 3DR robotics radio (roll, pitch, yaw, throttle), you can see a video about that here TEGO indoor position control

I works nice... but I want it to work even nicer and better!!! so, we need all the mathematical models and parameters to be as precise as possible, ergo, systems identification required.

I knew that the 3DR radio was not good enough to send data in a fast way to the ground station... So, I put onboard a Raspberry Pie, this computer ask data to the multwii and also to the motion capture system, and saves it... thats it for now.

MultWii and Raspberry Pie on a quadcopter

pymultiwii's People

Contributors

alduxvm avatar ansgarschmidt avatar levansanadiradze avatar probhakarroy avatar wil3 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pymultiwii's Issues

Problems when trying to control via MSP

Hi

I've been running the tests and I only was able to run correctly the test-attitude.py. I enabled the feature SERIALRX and set SERIALRX_TYPE to 4 with CLI in BaseFlight but I'm not able to write pilot commands to the board and I don't know if I'm doing something wrong.

I have a naze32 with the last stable BaseFlight firmware.

Thanks

Controlling the copter with a joystick

Hello! We are a bunch of students building a quadcopter as a school-project. We have no previous experience with copters or python but your solution is exactly what we've been looking for.

We've managed to get it to arm through the arm-disarm test program but haven't gotten any further than that. It would be great if you could explain a bit more of how you controlled the copter with the joystick, since our ultimate goal is to control it with an xbox controller connected to the computer.

Any help would be appreciated, thanks!

Variable types in getData()

Hi first of all great work nice class you've made it saved me some time. However you have few issues, mainly in getData. You are not doing crc checking thats one. Second when you are unpacking string to temp you assume it's signed short which is correct however not for everything. For example RC Channels are send as UInt16 which is unsigned short.

Another thing is you can batch send like 5 requests and then recieve 5 of them processing whole buffer. The idea is to get liek 5 infos updated every loop rather than 5 infos updated every 5 loops.

Error in sendCMDreceiveATT. (tuple index out of range)

Hello!

I'm getting an error in the terminal:

Error in sendCMDreceiveATT.
(tuple index out of range)

I'm using a Jetson nano (Ubuntu 18.04 (Python 3.6.9) ) to control a Mamba F405 FC over serial port, with the example code:

data = [1500,1500,1000,1500,1000,1000,1000,1000]
board.sendCMDreceiveATT(16,MultiWii.SET_RAW_RC,data)

Everything else is working fine except sending channel data. The weird thing is that the flight controller is receiving every channel data from my script and I can actually control the FC, except that error.

Thank you in advance!

pymultiwii library issue with inav 1.6

Hello alduxvm, I tried using your pymultiwii library for controlling naze32 rev6 through raspberry pi. I can read board data like accelerometer value but not write commands like arm and disarm. I configured naze32
with rc type to msp serial rx. raspberry pi and naze32 are connected through usb cable.

Versioning + uploading to PyPI

Thanks for an excellent Python module. We're experimenting with wifi drone flying at our makerspace SparkCC and pyMultiWii saved us a lot of work!

It would be great if pyMultiWii was properly versioned and made available on PyPI so that it could be easily installed via pip and included as a dependency in other projects.

Happy to help out with this if you'd like me to.

Error when running the example(folder test)

Error:

Traceback (most recent call last):
File "C:\Pyton.PROJECTS\pythonProject1\MyFile.py", line 18, in
board = MultiWii("/dev/ttyUSB0")
File "C:\Pyton.PROJECTS\pythonProject1\venv\lib\site-packages\pymultiwii_init_.py", line 79, in init
self.ser = serial.Serial()
AttributeError: module 'serial' has no attribute 'Serial'

What am I doing wrong?

Latest Cleanflight version 1.12

Hi!

I can see in pyMultiWii.py that line:

Modification required on Multiwii firmware to Protocol.cpp in evaluateCommand:

Is the modification still necessary? The cleanflight code got changed over time and now that evaluateCommand is no longer there.

I'm trying the test-arm-disarm.py and nothing happens.

Also this part seems not updated. Cleanflight has rx_serial instead of serialrx.
and serialrx_type seems to be replaced with serialrx_provider?

but by default you will not be able to use the MSP_SET_RAW_RC to write pilot commands to the multiwii. In order to do that you need to activate (via the baseflight/cleanflight GUI) the SerialRX with the specific type for MSP (MultiWii Serial Protocol). The instructions for doing that on baseflight are:

Open the CLI (while on the baseflight configurator) and type:
feature SERIALRX
and then type the following lines:

set serialrx_type=4

feature SERIALRX Invalid name

I want to use the library to send commands to my naze32, but typing feature SERIALRX in the CLI gives invalid name error. Is this due to the version of cleanflight? If so do you know what the new command is, Many thanks.

Raw RC problems

I'm running multiwii on an arduino nano, and it won't let me input raw rc signals. I have success in requesting information, but raw rc commands seem not to be going through. Is there a setup procedure I have overlooked? I know that some boards need to be told what kind of rc input to receive.

Strange Connection Bug with CleanFlight 2.2.0-RC1

Hi guys,
I'm trying to get the ATTITUDE of my board with this python code:

from pymultiwii import MultiWii
serialPort = "/dev/tty.SLAB_USBtoUART"
board = MultiWii(serialPort)
while True:
    print board.getData(MultiWii.ATTITUDE)

I always get a series of "None" in my terminal.
When I open CF-Configurator and click on connect, on the terminal I start to see all the normal output like:
{'timestamp': '1514405918.46', 'elapsed': 0.052, 'angx': 0.0, 'angy': 0.1, 'heading': 181.0}
Has anyone faced this issue?
EDIT: issue fixed with my PR #18

combinación de radio y rpi

Hola Aldo, Muchas gracias por este aporte, quisiera saber si es posible el control del drone tanto por la raspberry como por el radiocontrol ppm, me gustaría controlarlo por radio y en momentos puntuales controlarlo por raspberry es posible??

Gracias!!

Running a Python 3 script

Hello @alduxvm, thanks for your work.
This is not entirely an issue, perhaps someone has never encountered such a problem.
I use WSL on Windows 10 to run Ubuntu.

py --version
Python 3.12.0

There I collect the firmware for betaflight from source code, and someone may use docker, but that’s not the point.
So, I needed to get attitude angle data from the flight controller F411 NOXE V3 via the UART2.
I got the code from here

https://github.com/alduxvm/pyMultiWii/blob/master/demo/show-attitude.py

But it didn’t want to work and gave an error.
I had to change the code a little:

#except Exception,error:
except Exception as error:

After that, I could not determine the COM port, the command line always showed the message
sendCMD...
The solution to the problem was simple, because... I'm on Linux on WSL, then my ports are designated like this:

`COM1:` - `/dev/ttyS1`
`COM2:` - `/dev/ttyS2`
`COM3:` - `/dev/ttyS3`
...
`COM30:` - `/dev/ttyS30`

Information from here.
As a result, the rewritten code for the COM15 port.

#!/usr/bin/env python

"""show-attitude.py: Script to ask the MultiWii Board attitude and print it."""

__author__ = "Aldo Vargas"
__copyright__ = "Copyright 2017 Altax.net"

__license__ = "GPL"
__version__ = "1.1"
__maintainer__ = "Aldo Vargas"
__email__ = "[email protected]"
__status__ = "Development"

from pymultiwii import MultiWii
from sys import stdout

if __name__ == "__main__":

    #board = MultiWii("/dev/ttyUSB0")
    #board = MultiWii("/dev/tty.SLAB_USBtoUART")
    #board = MultiWii("COM15")
    board = MultiWii("/dev/ttyS15")
    try:
        while True:
            board.getData(MultiWii.ATTITUDE)
            #print (board.attitude) #uncomment for regular printing

            # Fancy printing (might not work on windows...)
            message = "angx = {:+.2f} \t angy = {:+.2f} \t heading = {:+.2f} \t elapsed = {:+.4f} \t".format(float(board.attitude['angx']),float(board.attitude['angy']),float(board.attitude['heading']),float(board.attitude['elapsed']))
            stdout.write("\r%s" % message )
            stdout.flush()
            # End of fancy printing
    #except Exception,error:
    except Exception as error:
        print ("Error on Main: "+str(error))

I receive orientation angle data.

python3 show-attitude.py
Waking up board on /dev/ttyS15...
1
angx = +2.90     angy = +21.70   heading = +57.00        elapsed = +0.0100

show-attitude
It works well!

Can't read sensor data

Hey,

I am trying to get sensor data to my Py from my sp 3 racing board (using betaflight). Unfortunately i get the following error while doing so:

unpack requires a bytes object of length 1
'utf-8' codec can't decode byte 0xfc in position 0: invalid start byte
'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
'utf-8' codec can't decode byte 0xfc in position 0: invalid start byte
'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
unpack requires a bytes object of length 1
'utf-8' codec can't decode byte 0xfc in position 0: invalid start byte
'utf-8' codec can't decode byte 0xff in position 0: invalid start byte
'utf-8' codec can't decode byte 0xfc in position 0: invalid start byte
'utf-8' codec can't decode byte 0xff in position 0: invalid start byte

I think there is an issue with reading the header in the init.py file. Would you know the reason?

Kind regards,

Accelerometer data returns 0s

I have a working Naze32 that returns good acc/gyro data to the Cleanflight Configurator. On both a Macbook and a Raspberry Pi, the show-imu.py or any program in this project that reads accelerometer data returns only 0s. I have modified the files to include the right USB port address on both devices but I'm still not getting any valid data.

Rc controller is still available?

Hi and congrats for your work. I'm planning to build a drone with image detection utopilot with raspebbry pi 4. The idea is to use it to make it follow me during my mtb ride.
I was thinking to make something similar to your project. In this case, is it still possible to bypass rpi controll with classic rc controller? The idea is to let the drone follow me but take control again with rc controller if something goes wrong.

cant seem to get sendCMD to work

hi, i'm using a F4 flight controller, i set the necessary settings in betaflight, and can read the imu and attitude from the FC, however when i try using the sendCMD i get the following error:
Error on Main: pack expected 18 items for packing (got 26)
this is the code i'm trynig:

data = [1500,1500,1000,1500,2000,1000,1000,1000] #roll/pitch/throttle/yaw/Aux1/2/3/4
for i in range(len(data)):
  binary = '{0:016b}'.format(data[i])
  data.append(int(binary[8:], 2))
  data.append(int(binary[:8], 2))
  self.sendCMD(16,MultiWii.SET_RAW_RC,data,'16B')

using msp library in arduino

hello, I am just beguinner in programation ,I ask you if you can help me ,
I want to use your MSP library or others to show some paramteres (like altitude..... ) in MULTIWII GUI using an arduino nano ,so ,can you at least give me an exemple to test ?

.

Update to newer MultiWii Version

Hello alduxvm,
I noticed your pyMultiWii module is not working with MultiWii firmware > 2. Are you planing to update your module?
Thanks!

I cannot communicate between my Raspberry pi 4 and the omnibus with MSP.

Hello, I need to communicate between omnibus and raspberry pi 4 in my project. When I use the shared arm-disarm code, the screen show:

Board is armed now!
"In 3 seconds it will disarm..."
"Disarmed."

However, the motors do not rotate.

Also, when I run the send data file, all values are 0.

I am using Betaflight.

I guess I couldn't set the MSP settings for the omnibus. Am I doing wrong in the ports part in betaflight? I am not getting errors, but the motors do not turn.

SPracing F3 V1 flight controller

I am trying to read raw IMU data from a SPracing F3 V1 flight controller, but I can't seem to get any data on my Rasberry pi. Looping the getData function returns "None". Any advice? I made sure I have the correct drivers. Thanks.

getData type error

When trying to run either demo in python2, I am seeing a type error on line 110 where the pack.struct is supposed to be iterated over. Here's an example output:
angx = +0.00 angy = +0.00 heading = +0.00 elapsed = +0.0000 unsupported operand type(s) for ^: 'int' and 'str'

When debugging, it's apparent that a string is being output from iteration over the pack.struct object. Have you seen this issue before? It seems this is either something to do with the dependencies version or a a fundamental bug

Error with sendCMD

It seems like the ord() get a int instead of a character that’s what cause the error in my case any suggestions to fix this problem?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.