Showing posts with label GPIO. Show all posts
Showing posts with label GPIO. Show all posts

Saturday, September 23, 2017

Raspberry Pi and Alexa Mobile Robot (Part 1)

The story so far...




In previous posts we have described building a Raspberry Pi based telepresence robot. At the moment, the robot can be remotely controlled via a web site to which it also streams video from the Pi camera. We have also added an ultrasonic sensor on a PTZ mount to allow it to roam autonomously. The next step in the robots evolution is to add voice recognition and speech using Amazon Alexa.

pi-top PULSE




The Raspberry Pi doesn't come with a microphone or speaker. There are lots of ways that you can add this capability but we decided to use the pi-top PULSE. The PULSE includes:

  • RGB LED's - 7x7 grid, illuminated speaker, underside ambient HAT and pi-top Accessory compatible;
  • SPEAKER - 2W with I2S amplifier; and a 
  • MICROPHONE - 200Hz to 11KHz response Automatic Gain Control (ACG).

Not only can we use the speaker and microphone for interfacing with Alexa but we can show some emotional/behaviour state changes via the LED's.

Wearing Multiple HATs - The 1st Problem


Even though HATs (Hardware Attached on Top) are not intended to be stacked, you can stack up to 62 HATs and not have an address collision. This assumes you don't have conflicting pin usage and you have compatible stackable headers.

The best way to check HAT / stackable board compatibility is to map out what every pin is being used for.


The image above illustrates the pin usage for the robot. The key is as follows:

  • Orange Pins - Are general I/O pins used for the PTZ servo's and ultrasonic sensor.
  • Blue Pins - Motor Driver Board pin usage.
  • Yellow Pins - Pi Top PULSE HAT pin usage.
Thus we don't have any electrical conflicts and can move on to the mechanical interfacing issues.




To call something a HAT it must meet the HAT requirements. We are using the Seeed Motor Driver Board (shown above) which can't be called a HAT because it doesn't have a full size 40W GPIO connector or an ID EEPROM. This presents us with two problems:

  1. We need access to 6 of the 14 pins which are not extended through the Motor Board.
  2. Even if all 40 pins were extended, placing the PULSE on top of the Motor Board wouldn't allow access to the power and GPIO pins used for the servo PTZ control and ultrasonic sensor. 
To solve this issue, we need a GPIO expansion shield which provides 3 x 40 pin connections in parallel. We can then use a couple of male to female cables to connect our "HAT's". We will conclude this build in the next post (once the expansion shield has arrived).




Wednesday, February 15, 2017

Raspberry Pi and "better" PWM for Servo Control?

RPIO and DMA PWM


Our current method of using software PWM to control servos is ok, but it does use CPU cycles and there is some jitter when the servos are in one position for any length of time. It turns out that there is an alternative (although it is currently in beta) in the RPIO module. From the documentation:

RPIO.PWM provides PWM via DMA for the Raspberry Pi, using the onboard PWM module for semi-hardware pulse width modulation, with a precision of up to 1µs.

With RPIO.PWM you can use any of the 15 DMA channels and any number of GPIOs per channel. Since the PWM is done via DMA, RPIO.PWM uses almost zero CPU resources and can generate stable pulses with a very high resolution. RPIO.PWM is implemented in C (source); you can use it in Python via the provided wrapper, as well as directly from your C source.

An important point to note is that you can use any number of GPIO's per channel, so you don't instantiate a new channel for each servo but use the one channel for as many servos as you have connected. An example of using RPIO.PWM is shown below.

from RPIO import PWM

servo = PWM.Servo()

# Set servo on GPIO17 to 1200µs (1.2ms)
servo.set_servo(17, 1200)

# Set servo on GPIO17 to 2000µs (2.0ms)
servo.set_servo(17, 2000)

# Clear servo on GPIO17
servo.stop_servo(17)

This example shows the high level application of RPIO.PWM. There are also a number of low level methods which you can review via the documentation link above. Two that we would like to briefly cover are:

  1. Subcycles - Each DMA channel is setup with a specific subcycle, within which pulses are added, and which will be repeated endlessly. Servos, for instance, typically use a subcycle of 20ms, which will be repeated 50 times a second. You can add pulses for multiple GPIOs, as well as multiple pulses for one GPIO. Subcycles cannot be lower than 2ms. This default works for us since the SG90 likes a frequency of 50 Hz (i.e. a period of 20 ms).
  2. Pulse-width increment granularity - (10µs by default) is used for all DMA channels (since its passed to the PWM timing hardware). Pulses are added to a subcycle by specifying a start and a width parameter, both in multiples of the granularity. For instance to set 500µs pulses with a granularity setting of 10µs, you’ll need to set the pulse-width as 50 (50 * 10µs = 500µs). The pulse-width granularity is a system-wide setting used by the PWM hardware, therefore you cannot use different granularities at the same time, even in different processes. So unless you change the default, increase your pulse width by 10µs increments.

Installing RPIO


RPIO is an advanced GPIO module for the Raspberry Pi. It includes the following:

  • PWM via DMA (up to 1µs resolution)
  • GPIO input and output (drop-in replacement for RPi.GPIO)
  • GPIO interrupts (callbacks when events occur on input gpios)
  • TCP socket interrupts (callbacks when tcp socket clients send data)
  • Command-line tools rpio and rpio-curses
  • Well documented, fast source code with minimal CPU usage
  • Open source (LGPLv3+)

RPIO is not installed by default on the Raspberry Pi. Depending on what model you are using you may come across some issues. As a first step try:
sudo apt-get update
sudo apt-get install python3-setuptools
sudo easy_install3 -U RPIO
Note that there are different versions for Python 3 and Python 2. This is for Python version 3. If you see this error:
fatal error: Python.h: No such file or directory
compilation terminated.
error: Setup script exited with error: command 'gcc' failed with exit status 1`
The fix is to install the python development headers. Again there are different versions for Python 2 and 3. To install for Python 3 use:
sudo apt-get install python3-dev
Lastly, if when you try and import the module you get the following:
SystemError: This module can only be run on a Raspberry Pi!
Try:
cd ~
git clone https://github.com/metachris/RPIO.git --branch v2 --single-branch
cd RPIO
sudo python setup.py install

Results


We got it working but the results seem a bit flaky. When it works it is good but every couple of runs we get the following error:
Traceback (most recent call last):
  File "/home/pi/python_code/RPIO_test.py", line 11, in <module>
    servo = PWM.Servo()
  File "/usr/local/lib/python3.4/dist-packages/RPIO-2.0.0_beta1-py3.4-linux-armv7l.egg/RPIO/PWM/__init__.py", line 188, in __init__
    setup(pulse_incr_us=pulse_incr_us)
  File "/usr/local/lib/python3.4/dist-packages/RPIO-2.0.0_beta1-py3.4-linux-armv7l.egg/RPIO/PWM/__init__.py", line 87, in setup
    return _PWM.setup(pulse_incr_us, delay_hw)
RuntimeError: Failed to create mailbox device

Started trying to track this error down but then decided life was too short! We will work with the RPi.GPIO PWM and see if we can't work around the jitter. At least it works consistently.