Adding RPi GPIO switch functionality to MAVProxy

Hello,

I´m new to Python and programming in general, but I´m learning.

Currently I´m working on a project with a standalone GCS unit based on two Raspberry Pi´s in a Peli case together with two 7" Raspberry touchscreens. One for the telemetry and one for a video downlink. (I´m using a RPi with Navio2 as flightcontroller).

I´ve successfully got the “telemetry” RPi with a custom USB joystick interface up and running with MavProxy and communicating with my Navio2. Now I´m studying the MavProxy code to find a way to issue some predefined terminal commands like “arm throttle” “rtl” etc with switches connected to the RPi GPIO or with my USB joystick interface by mapping the buttons to trigger a standalone script to do the tasks I want.

Basically I want to trigger the mavproxy_arm.py and mavproxy_mode.py with switches connected to the RPi.

I´m stuck. Can anyone point me in the right direction?

Best regards
Alex from Norway

I assume you’re talking about the second Pi, because the GPIO on the Pi you’re using with NAVIO are already being used.

You can make your Pi run a script when a button is pressed using interrupts. There’s an article about it here.

http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio

If you need some help, let me know. I’ve built other devices with the Pi that do the same thing. I can also make the SEEK Thermal Camera run on the Pi.

Bill from Connecticut USA

Hi Bill!

Thanks for your reply!

Yes I’m talking about the Pi that is running MAVProxy in my GCS. I’m currently studying the mavproxy_arm module. I’m trying to get my button to run self.master.arducopter_arm() from pymavlink with something like this:

GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)

while True:
    input_state = GPIO.input(18)
    if input_state == False:
        self.master.arducopter_arm()
        time.sleep(0.2)

This doesn’t work.

I’m interested in your Seek stuff if you want to share =) I’ve got a Seek module on my desk.

I don’t see where you are importing the GPIO module. Try adding:

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)

and then

GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)

I have some python scripts I can email you for the SEEK. The full compiled C++ version works as a ROS Topic.

Thanks! I’l PM you my email =)

I have that in my code as well, the button works when I try a simple “button pressed” program

I’d previously written a script that triggers and arm and takeoff on an APM, 60 seconds after the user presses a button on a Raspberry Pi:
https://github.com/stephendade/MAVProxy/blob/RemoteTakeoff/MAVProxy/modules/mavproxy_remtakeoff.py

Thanks for your reply @stephendade!

I will have a look at your code tonight and I will post back the results of my own code.

I’m starting to understand the basics of Python now, thanks for all feedback =)

Alex

Hello again!

I keep stumbling into this problem:

unexpected indent line 38.

This is the code I’m trying:

#!/usr/bin/env python
'''
Example Module
Peter barker, September 2016

This module simply serves as a starting point for your own MAVProxy module.

1. copy this module sidewise (e.g. "cp mavproxy_example.py mavproxy_coolfeature.py"
2. replace all instances of "example" with whatever your module should be called
(e.g. "coolfeature")

3. trim (or comment) out any functionality you do not need
'''

import time, os

from MAVProxy.modules.lib import mp_module
from pymavlink import mavutil

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)

arming_masks = {
    "all"     : 0x0001,
    "baro"    : 0x0002,
    "compass" : 0x0004,
    "gps"     : 0x0008,
    "ins"     : 0x0010,
    "params"  : 0x0020,
    "rc"      : 0x0040,
    "voltage" : 0x0080,
    "battery" : 0x0100
    }

class RpiModule(mp_module.MPModule):
    def __init__(self, mpstate):
        super(RpiModule, self).__init__(mpstate, "rpi", "arm/disarm handling")
		self.add_command('arm', self.cmd_arm2, 	'arm motors')
		self.add_command('disarm', self.cmd_disarm,   'disarm motors')
		self.was_armed = False

	def switch_18(channel):
		self.cmd_arm2()
	
	GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)	
	GPIO.add_event_detect(18, GPIO.RISING, callback=switch_18, bouncetime=200)

	def cmd_arm2(self, args):
		self.master.arducopter_arm()

	while True:
		pass
	
	def cmd_disarm(self, args):
        '''disarm motors'''
        p2 = 0
        if len(args) == 1 and args[0] == 'force':
            p2 = 21196
        self.master.mav.command_long_send(
            self.target_system,  # target_system
            0,
            mavutil.mavlink.MAV_CMD_COMPONENT_ARM_DISARM, # command
            0, # confirmation
            0, # param1 (0 to indicate disarm)
            p2, # param2 (all other params meaningless)
            0, # param3
            0, # param4
            0, # param5
            0, # param6
            0) # param7
	
	def mavlink_packet(self, m):
		mtype = m.get_type()
		if mtype == 'HEARTBEAT' and m.type != mavutil.mavlink.MAV_TYPE_GCS:
			armed = self.master.motors_armed()
			if armed != self.was_armed:
				self.was_armed = armed
				if armed and not self.all_checks_enabled():
					self.say("Arming checks disabled")
				   
      
def init(mpstate):
    '''initialise module'''
    return RpiModule(mpstate)

Any suggestions on what I’m doing wrong?

Alex

In lines 38-40 above, they should have the same indent as the line above. Python is very picky about having the correct line indents

Thanks for the help, seems like the problem was Notepad+, I edited the indents in the regular notepad and the error was solved. Now on to my next issue. The code looks like this now:

#!/usr/bin/env python
'''
Example Module
Peter barker, September 2016

This module simply serves as a starting point for your own MAVProxy module.

1. copy this module sidewise (e.g. "cp mavproxy_example.py mavproxy_coolfeature.py"
2. replace all instances of "example" with whatever your module should be called
(e.g. "coolfeature")

3. trim (or comment) out any functionality you do not need
'''

import time, os

from MAVProxy.modules.lib import mp_module
from pymavlink import mavutil

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)

arming_masks = {
    "all"     : 0x0001,
    "baro"    : 0x0002,
    "compass" : 0x0004,
    "gps"     : 0x0008,
    "ins"     : 0x0010,
    "params"  : 0x0020,
    "rc"      : 0x0040,
    "voltage" : 0x0080,
    "battery" : 0x0100
    }

class RpiModule(mp_module.MPModule):
	def __init__(self, mpstate):
		super(RpiModule, self).__init__(mpstate, "rpi", "arm/disarm handling")
		self.add_command('arm', self.cmd_arm, 	'arm motors')
		self.add_command('disarm', self.cmd_disarm,   'disarm motors')
		self.was_armed = False

	def switch_18(channel):
		self.cmd_arm()
	
	GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)	
	GPIO.add_event_detect(18, GPIO.RISING, callback=switch_18, bouncetime=200)

	def cmd_arm2(self):
		self.master.arducopter_arm()

	while True:
		pass
	
	
	
	def mavlink_packet(self, m):
		mtype = m.get_type()
		if mtype == 'HEARTBEAT' and m.type != mavutil.mavlink.MAV_TYPE_GCS:
			armed = self.master.motors_armed()
			if armed != self.was_armed:
				self.was_armed = armed
				if armed and not self.all_checks_enabled():
					self.say("Arming checks disabled")
				   
      
def init(mpstate):
    '''initialise module'''
    return RpiModule(mpstate)

Now I get this error when I push my button:

Traceback (most recent call last):
File “build/bdist.linux-armv7l/egg/MAVProxy/modules/mavproxy_rpi3.py”, line 43, in switch_18
NameError: global name ‘self’ is not defined

Sorry for all my questions, I really appreciate the help you guys are providing!

Alex

I managed to get my first MAVProxy module to WORK now. I have to cleanup my code before I post it.

Thanks for pointing me in the right directions @stephendade and @Bill_Piedra!

Edit: The problem was indents, I think the texteditor i used was the problem (Notepad+ in Windows). Now I have switched to Visual Studio Code with a Python plugin. Which editor do you guys use?

Next step is to make a new module for MODE selection.

Alex

I use Notepad++ for most things.

Python has big issues with indents. The all have to be spaces, or all tabs. Any mixing of the two in a single files will cause compilation error. Most people use spaces.

In Notepad++, go Settings -> Preferences -> Tab Settings -> Python -> tick “replace by space”. That should fix your problem.

Thanks!

Now I understand why the indents gave me such a hazzle!

A

I keep stumbling into this problem:

unexpected indent line 38.
.
.
.
.
Any suggestions on what I’m doing wrong?

Python is really pick about whitespace. It is a bit hard to tell after
the code’s been through the mail what the exact problem is, but look at
line 38 of the file and make sure that you are indenting with spaces, not
tabs.

If that’s not the problem - please upload the file somewhere so we can
look at it unmolested by the mail system.