8-channel PWM with the MSP430G2553

Last week, I spent a bit of time working out how to generate PWM for servo control using the MSP430G2553. It took me a couple of hours to work it out, but worked well once I got it going. Today, I’ve been experimenting with a small robot manipulator that we’re exhibiting in our open day tomorrow in DIT Kevin St. This manipulator has a total of seven servo motors, but only 6 degrees of freedom because two of the servos are doubled up on the shoulder joint and are controlled by the same PWM signal. I wanted to control this manipulator with an MSP430G2553, but it doesn’t provide that many dedicated PWM outputs, so I needed to investigate an alternative way of doing it. The code below is my ad hoc solution.

//
// 8-channel PWM example for MSP430G2553
//
// Written by Ted Burke - last updated 4-4-2014
//

#include <msp430.h>

// PWM channels duty cycle array
int pw[] = {1000,1000,1000,1000,1000,1000,1000,1000};

int main( void )
{
    WDTCTL = WDTPW + WDTHOLD; // Disable watchdog timer

    P1DIR = 0b00111111; // Make P1.0-5 outputs

    // Configure Timer A0 Compare interrupts
    TA0CTL = TASSEL_2 + MC_1 + ID_0; // "up" mode, input divider = 1
    TA0CCR0 = 2500;                  // set timer period to 2.5ms
    TA0CCTL0 = CCIE;                 // enable CC0 interrupt
    TA0CCR1 = 1500;                  // set pulse width to 1.5ms
    TA0CCTL1 = CCIE;                 // enable CC1 interrupt
    _BIS_SR(GIE);                    // global interrupt enable

    // From this point on, we only need to write values
    // into the pw[] array to set the duty cycle on all
    // eight PWM channels (P1.0-7), or to be precise,
    // whichever channels are actually enabled as digital
    // outputs (six in this case).

    //
    // A quick example to test: Do a different number of
    // angle steps on each of the six PWM outputs. 1 step
    // on channel 0, 2 steps on channel 1, 3 steps on
    // channel 2, and so on.
    //
    int channel, counter = 0;
    while(1)
    {
        counter++;
        for (channel=0 ; channel<6 ; ++channel)
        {
            pw[channel] = 1000 + (counter%(channel+1))*100;
        }
        __delay_cycles(500000);
    }

    return 0;
}

//
// Timer A0 CC0 interrupt service routine.
// This ISR is triggered when Timer A0 reaches
// its maximum value TA0CCR0 and resets to zero.
// This ISR starts a pulse on one PWM channel
// every 2.5ms. It cycles through all eight channels
// in turn. After starting the pulse, it sets
// the TA0CCR1 register to the pulse width of
// the current pin so that the pulse will be
// ended by the partner ISR after the appropriate
// time delay (for this channel's duty cycle).
//
#pragma vector=TIMER0_A0_VECTOR
__interrupt void Timer_A0_CC0(void)
{
    static n=0;         // PWM channel index

    P1OUT = 1 << n;     // Set P1.n high
    TA0CCR1 = pw[n];    // Set timer for current pin's pulse width

    n = (n+1)%8;        // Move on to next PWM channel
    TA0CCTL0 &= ~CCIFG; // Reset CC interrupt flag
}

//
// Timer A0 CC1 interrupt service routine.
// This ISR is responsible for ending each PWM
// pulse on all channels. It is triggered when
// Timer A0 matches TA0CCR1, which is at a
// different time for each PWM channel.
//
#pragma vector=TIMER0_A1_VECTOR
__interrupt void Timer_A1_CC1(void)
{
    P1OUT = 0;
    TA0CCTL1 &= ~CCIFG;
}

The following video shows what the above program does. In the video you can see me switching the signal controlling the servo motor from one PWM output to the next in the following sequence: P1.0, P1.1, P1.2, P1.3, P1.4, P1.5.

This method involves cooperation between two Timer A0 interrupt service routines (ISRs), one which is responsible for starting pulses on every channel (TA0 CC0) and one which is responsible for ending pulses on every channels (TA1 CC1). The pulses for the six channels are interleaved, in the sense that the channels take it in turns to output one pulse. There is never more than one PWM channel outputting a pulse at any time. Even at its longest pulse width, the servo control PWM has a relatively low duty cycle (approximately 10%), so there is no difficulty interleaving 8 channels in this fashion, as illustrated below:

8-channel_pwm

Download Editable SVG version of above image

Posted in Uncategorized | 2 Comments

Simple Phaser Framework example – Flappy Words

I spent some time this week playing Aoife Crowley’s Flappy Bod game (my top score = 8). I was really impressed by the simplicity of the Phaser Framework which it runs on, so I decided to try it out for myself. Phaser is an open source framework for 2-D web game development. It’s really easy to get started with and I was able to get a few sprites moving around on the screen and responding to user input within minutes.

Of course, I still have to decide exactly how my own Flappy Words game is going to work, but the basic idea is to facilitate text communication (i.e. spelling messages out) using a single switch (the space bar), in something like the style of Flappy Bird. I suppose I’m picturing a cross between Flappy Bird and Dasher. The exact details remain to be worked out, but I thought I might as well document my program as it currently stands, which is a very basic indeed – no spelling at all yet; just one flying teapot.

Click on the screenshot below to see what this example does so far (not a lot!):
Flappy Words Screenshot - 03222014 - 01:53:13 AM

The game basically consists of just a few files:

  1. index.html – This is the main HTML file that you actually point the browser at. It doesn’t contain much apart from a div with the same id (“flappy-words”) as that specified when the game object is created in the game.js JavaScript File. The contents of this file are shown below.
  2. game.js – This is the file that contains all my JavaScript code for the game so far. The contents of this file are shown below.
  3. background.png – This is the background wallpaper used in the game world.
  4. teapot.png – This is the PNG image used for the flapping teapot sprite.
  5. phaser.min.js – This file contains the entire Phaser Framework. This one is version 2.0 and it’s exactly as I downloaded it from the Phaser github repo.

While developing with Phaser, of course you need to be able to test the program repeatedly in a browser. For security reasons, browsers will not generally allow javascript code to access the local filesystem, so to test the game while you’re writing it you need to set up a web server and make the web browser access the files through it. The easiest way to do this is to use the built in web server in the Python interpreter. I only discovered this brilliant feature yesterday in an article from the Linux Journal. Is there nothing Python can’t do?!

I store all my game files in the same folder and then start Python in that folder using the following command:

python -m SimpleHTTPServer

By default, the Python web server accepts connections on port 8000 (although you can specify a different port if necessary). I therefore test my game by pointing Firefox at the following URL:


http://127.0.0.1:8000

By the way, this is the Inkscape SVG file that I created to make the PNGs for the teapot sprite and background:

  1. teapot.svg

This is the HTML code in “index.html”:

<!DOCTYPE html>

<!-- This is the main HTML file for Flappy Words -->
<!-- Written by Ted Burke, last updated 21-3-2014 -->

<html>

<head>
	<title>Flappy Words</title>
	
	<style>
		#flappy-words {
			width: 800px;
			margin: auto;
			margin-top: 10px;
		}
	</style>
	
	<script type="text/javascript" src="phaser.min.js"></script>
	<script type="text/javascript" src="game.js"></script>
	
</head>

<body>
	<h1 style="text-align: center;">Flappy Words</h1>
	<div id="flappy-words"></div>
</body>

</html>

This is the JavaScript code in “game.js”:

//
// game.js - Main JavaScript file for Flappy Words
// Written by Ted Burke - last updated 21-3-2014
//

var game = new Phaser.Game(800, 600, Phaser.AUTO, 'flappy-words', {preload: preload, create: create, update: update});

var teapot;
var text;
var counter = 0;

function preload () {
	game.load.image('teapot', 'teapot.png');
	game.load.image('background', 'background.png');
}

function create() {
	game.add.image(0, 0, 'background');
	
	teapot = game.add.sprite(game.world.centerX, game.world.centerY, 'teapot');
	teapot.inputEnabled = true;
	teapot.events.onInputDown.add(flap, this);
	teapot.scale.x = 0.4;
	teapot.scale.y = 0.4;
	game.physics.enable(teapot, Phaser.Physics.ARCADE);
	teapot.anchor.setTo(0.5,0.5);
	teapot.body.collideWorldBounds = true;
	teapot.body.gravity.y = 200;
	teapot.body.bounce.y = 0.4;
	teapot.body.maxAngular = 200;
	//teapot.body.angularDrag = 20;
	
	text = game.add.text(250, 16, 'Press SPACE to flap...', { fill: '#ffffff' });
	
	spaceKey = game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
	spaceKey.onDown.add(flap, this);
}

function update() {
	if (spaceKey.isDown)
	{
		text.fill = '#000000';
		teapot.body.angularVelocity = 100;
	}
	else
	{
		text.fill = '#ffffff';
		teapot.body.angularAcceleration = -50.0 * teapot.angle - 5.0 * teapot.body.angularVelocity;
	}
}

function flap() {
	teapot.body.velocity.y = -200;
	counter++;
	text.text = "You flapped " + counter + " times!";
}

These are the sprite and background PNG images:

Posted in Uncategorized | Leave a comment

Installing Microchip XC16 in CrunchBang Linux

XC16 is Microchip’s C compiler for the 16-bit dsPIC microcontrollers (PIC24, dsPIC30F, dsPIC33). I sometimes need to use it when I’m working in a live session in CrunchBang Linux.

First download the Linux installer for XC16

Then change directory into the downloads folder (/home/crunchbang/downloads/ in my case) and extract the installer from the tar archive:

cd downloads
tar xvf xc16-v1.21-linux-installer.run.tar

Now, log in as root, install some dependencies, and run the installer:

sudo su
apt-get update
apt-get install lib32z1
./xc16-v1.21-linux-installer.run

You will be asked to agree to a software license and to answer a few questions on installation options. The default options are mostly acceptable, but make sure you reject the pay options and time-limited premium license. The free time-unlimited version should be adequate for most purposes.

By default the compiler is installed in /opt/microchip/xc16/

To compile a program, here’s an example command line:

/opt/microchip/xc16/v1.21/bin/xc16-gcc main.c -mcpu=30F4011 -Wl,--script=p30F4011.gld

That produces a file called a.out. To convert the compiled program to hex format (i.e. “a.hex”), use the bin2hex tool, as follows:

/opt/microchip/xc16/v1.21/bin/xc16-bin2hex a.out
Posted in Uncategorized | Leave a comment

Low-cost motor control by displaying coloured shapes on a phone or PC screen

Smart phones pack a lot of features (battery, display, sensors, audio i/o, wireless internet connectivity, computing power, etc) into a tiny, convenient, inexpensive package. A smart phone therefore makes a great robot brain and I’ve become fascinated by the idea of creating an ultra low-cost robot that’s really just a vehicle for an Android phone running an app that analyses the robot’s environment and controls its behaviour.

Obviously, the phone could dispatch orders to actuators via an RF link (e.g. bluetooth) or a cable to control the robot’s movement. However, the idea I’m investigating here is to use ordinary LEDs as photodetectors to repond to colour changes on different regions of the phone screen. Using this technique, the phone app couldn control actuators just by displaying coloured shapes on the screen.

The following video demonstrates the principle, using alternating black and white squares on a screen to switch a motor on and off:

It works fine with the phone screen too, but since I was using my phone to do the filming you’ll have to take my word for it!

My aim is to build the whole robot using easy to find components for a cost of €10 or less. I don’t have a complete robot yet, but the cost is currently within budget. What I have implemented so far (as shown in the video above) is:

  • A pair of reverse-biased green LEDs act as photodetectors, providing a single binary signaling channel between the screen of the controlling device (laptop / phone) and an MSP430 microcontroller.
  • The MSP430 microcontroller controls a single geared DC motor. It uses one digital input to detect the control signal from the phone / laptop and one digital output to control the motor via an NPN transistor.

The code running on the MSP430 is dead simple – it basically just relays the binary control signal from a digital input (P1.1) to a digital output (P2.4):

//
// LED photodetector motor control example
// Written by Ted Burke - last updated 28-2-2014
// Code is for MSP430G2452 or MSP430G2553
//
 
#include <msp430.h>
 
int main( void )
{
    // Stop watchdog timer to prevent time out reset
    WDTCTL = WDTPW + WDTHOLD;
     
    // Set P2.4 as an output, other pins as inputs
    P2DIR = 0b00010000;
    P1DIR = 0b00000000;
     
    while(1)
    {
        if (P1IN & BIT1) P2OUT = 0b00010000;
        else P2OUT = 0b00000000;
    }
     
    return 0;
}

Here are some photos of my breadboard circuit (plus 4xAA battery pack and geared DC motor):

The circuit relies on a little-known property of ordinary LEDs: When reverse-biased, they act as (slightly inefficient) photodiodes and can therefore be used not only for display purposes, but also as photodetectors. I had completely forgotten about this phenomenon until I saw Frank Duignan using it for something ingenious a few months ago. What I like about this approach is that most electronics enthusiasts have at least a couple of LEDs lying around, so it makes photo sensing very accessible without needing to order components specially.

LED_photodetector_circuit

Click here to download editable SVG version of circuit diagram

In this case, I placed the two LEDs in series (both reverse-biased) between the supply rails, forming a voltage divider. The output of the voltage divider is connected to a high impedance digital input of the MSP430. The idea is to point each LED at a different region of the controlling device’s screen and turn one region white and the other black, causing the output of the voltage divider to be either high or low. Binary signaling is achieved by swapping the black and white regions back and forth.

  • When LED1 sees black and LED2 sees white, P1.1 is low.
  • When LED1 sees white and LED2 sees black, P1.1 is high.

I created the following animated GIF to test my circuit:

reverser

Posted in Uncategorized | Leave a comment

Phasor diagrams in GNU Octave

I’ve been experimenting with plotting phasor diagrams in GNU Octave. This approach may also work in MATLAB, but I haven’t tried that yet. I need to tidy this up a little more to make it convenient to reuse, but I’m capturing it as it is for the time being, so that I don’t lose it.

GNU octave phasor diagram

This is my M-file, “example.m”:

%
% GNU Octave phasor plot example
% Written by Ted Burke - 19-2-2014
%

% Create a few complex values
z1 = 3 + 3j;
z2 = 2 + 4j;
z3 = z1 * z2;

% Calculate a suitable axis limit based on phasors
m = 1.2 * max([real([z1 z2 z3]) imag([z1 z2 z3])]);

% Create a new figure window
figure
hold on

% Plot phasors one at a time
quiver(0,0,real(z1),imag(z1))
quiver(0,0,real(z2),imag(z2))
quiver(0,0,real(z3),imag(z3))

% Add horizontal and vertical axes
plot([-m m],[0 0])
plot([0 0],[-m m])

% Set axis limits and aspect ratio
axis([-m,m,-m,m], 'square')

To install octave in Linux (debian), just run the following command as root:

apt-get install octave

Then, to run the example:

octave_running_example

Posted in Uncategorized | Leave a comment

2D Room Mapping With a Laser and a Webcam

batchloaf:

Shane Ormonde, from DIT programme DT009, also recently featured on hackaday.com. His project is a lovely adaptation of a webcam laser range finder (originally by Todd Danko) to scan and map the shape of a room. It’s an ingenious piece of work – I hope to try this out myself soon!

Originally posted on Hackaday:

2014-01-29-21-02-40

[Shane Ormonde] recently learned how to measure distance using just a webcam, a laser, and everyone’s favorite math — trigonometry. Since then he’s thrown the device onto a stepper motor, and now has a clever 2D room mapping machine.

He learned how to create the webcam laser range finder from [Todd Danko], a project we featured 7 years ago! It’s a pretty simple concept. The camera and laser are placed parallel to each other at a known distance, axis-to-axis. On the computer, a python script (using the OpenCV library) searches the image for the brightest point (the laser). The closer the brightest point is to the center of the image, the farther the object. Counting pixels from the center of the image to the laser point allows you to calculate an angle, which can then be used to calculate the distance to the object — of course, this needs to…

View original 60 more words

Posted in Uncategorized | Leave a comment

Motion Tracking on the Cheap with a PIC

batchloaf:

Projects by Aron Horan from DIT programme DT009 have recently featured twice on hackaday.com. The first one to be featured was his Dodging Robot, which is pretty nifty, but this one here is an interesting combination of SHARP rangefinder and servo motor. Nice work Aron!

Originally posted on Hackaday:

motion tracking

Ever need a cheap motion tracker for very basic object following? Did you know you can throw one together with a few IR distance sensors and a PIC?

The setup is fairly simple. [Aron Horan] is using a dsPIC30F4011 PIC, a SHARP infrared distance sensor, an RC servo, and a PICkit2 for testing. It works by scanning left and right using the servo motor. When the edge of an object is detected, it will turn away from the object until it can no longer detect the edge — then it turns back. Unfortunately this does mean it will always be twitching, even when it’s tracking an object.

Like many of the other projects [Aron] has documented, he’s included everything you need to know to be able to recreate the project yourself. Flowcharts, wiring diagrams, and the code — written in C of course! The following video includes an excellent demonstration, but…

View original 37 more words

Posted in Uncategorized | Leave a comment