Mbot Joy
4409c53 (Mon Feb 4 17:15:40 2019 -0500)
|
Control your mbot with a joystick. More...
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
Macros | |
#define | MAX_SPEED 200 |
Normal forward speed. | |
#define | MED_SPEED 127 |
Slow speed when approaching an obstacle. | |
#define | STOP_DISTANCE 150 |
Stop when <= this distance from an obstacle. | |
#define | SLOW_DISTANCE 500 |
Slow down when <= this distance from an obstacle. | |
#define | LEDDDR (DDRB) |
DDR register for LED pin. | |
#define | LEDPORTREG (PORTB) |
PORT register for LED pin. | |
#define | LEDPINREG (PINB) |
PIN register for LED pin. | |
#define | LEDPIN (_BV(PORTB5)) |
LED pin number. | |
#define | USDDR (DDRC) |
DDR register for ultrasonic sensor. | |
#define | USPORTREG (PORTC) |
PORT register for ultrasonic sensor. | |
#define | USPINREG (PINC) |
PIN register for ultrasonic sensor. | |
#define | USPIN (_BV(PORTC1)) |
Data pin for ultrasonic sensor. | |
#define | MOTORDDR (DDRD) |
DDR register for motors. | |
#define | MOTORPORT (PORTD) |
PORT register for motors. | |
#define | MLEFTDIR (_BV(PORTD4)) |
Left motor direction pin. | |
#define | MLEFTPWM (_BV(PORTD5)) |
Left motor speed control. | |
#define | MRIGHTDIR (_BV(PORTD7)) |
Right motor direction pin. | |
#define | MRIGHTPWM (_BV(PORTD6)) |
Right motor speed control. | |
#define | MLEFTOCR (OCR0A) |
Left motor OCR register. | |
#define | MRIGHTOCR (OCR0B) |
Right motor OCR register. | |
#define | JOYDDR (DDRB) |
DDR register for joystick. | |
#define | JOYPORT (PORTB) |
PORT register for joystick. | |
#define | JOYPIN (PINB) |
PIN register for joystick. | |
#define | PIN_LEFT (_BV(PORTB1)) |
Joystick left pin. | |
#define | PIN_RIGHT (_BV(PORTB2)) |
Joystick right pin. | |
#define | PIN_DOWN (_BV(PORTB3)) |
Joystick down (reverse) pin. | |
#define | PIN_UP (_BV(PORTB4)) |
Joystick up (forward) pin. | |
Typedefs | |
typedef enum DIRECTION | DIRECTION |
Describe motor direction. | |
typedef enum TURN | TURN |
Describe current turning state. | |
typedef enum DISTANCE_STATE | DISTANCE_STATE |
States in ultrasonic measurement state machine. | |
Enumerations | |
enum | DIRECTION { STOPPED, FORWARD, REVERSE } |
Describe motor direction. More... | |
enum | TURN { NONE, LEFT, RIGHT } |
Describe current turning state. More... | |
enum | DISTANCE_STATE { PING, WAIT_PULSE_START, WAIT_PULSE_END, INTERVAL } |
States in ultrasonic measurement state machine. | |
Functions | |
void | setup () |
Configure pins and pwm. More... | |
uint8_t | measure_distance (uint16_t *distance) |
Handle distance measurements with the ultrasonic sensor. More... | |
int | main () |
Control your mbot with a joystick.
Connect a standard 5-pin arcade joystick to your mbot (pins GND, 9, 10, 11, 12) and control its movements. This code makes use of the ultrasonic sensor to avoid bumping into obstacles.
enum DIRECTION |
enum TURN |
int main | ( | ) |
We call measure_distance
every loop iteration. When there is a valid measurement available:
STOP_DISTANCE
, stop the mbot and set the obstacle
flag.SLOW_DISTANCE
, reduce mbot speed to MED_SPEED
and clear the obstacle flag.MAX_SPEED
and clear the obstacle flag.If the obstacle flag is set, turn on the built-in LED.
Set dir
and turn
based on the current joystick inputs.
Override dir
to STOPPED
if the obstacle flag is set.
If mbot state is STOPPED
, set motor speed to 0. Otherwise, set motor speed and direction based on the current value of dir
.
Next, handle turns. If the mbot is in motion, we want both motors to continue to run in the same direction, so reduce the speed on the turning side by 1/2. If the mbot is stopped, run the turning side motor in reverse and the opposite side forward.
Apply current l_speed
and r_speed
values to OCR*
registers.
uint8_t measure_distance | ( | uint16_t * | distance | ) |
Handle distance measurements with the ultrasonic sensor.
The ultrasonic sensor on the mbot is a three-pin sensor: GND
, 5V
, and a data pin that is used as both an input and an output. We send a 10us high pulse to the sensor to trigger a measurement. The sensor then sends out a series of ultrasonic pulses, and then reports the measurement by bringing the data line high. The duration of the high pulse corresponds to the distance.
In order to time the high pulse, we simply count loop iterations. This means that as you make changes to the code, you may need to adjust the STOP_DISTANCE
and SLOW_DISTANCE
settings.
void setup | ( | ) |
Configure pins and pwm.
Set up fast PWM mode with OCR output enabled on for the motor speed control pins, OC0A (PORTD6) and OC0B (PORTD5). The motor PWM frequency is 967Hz. At 16Mhz with a prescaler of clk/64, this gets us 976.5625Hz, which is apparenlty "close enough" (that's 16000000 / 64 / 255
, where the final /255
is because we are using 8-bit timers). Setting OCR0A
and OCR0B
controls the duty cycle of the PWM output.
We need to use TIMER0
for PWM output, since this is connected to OC0A and OC0B, which are in turn connected to the motor pins.
Select clk/64 prescaler (CS = 0b011)
Configure motor pins as outputs.
An arcade joystick has a five-pin connection (ground and one pin for each direction). When you move the joystick in a given direction, it connects the appopriate pin to ground. This means we need to enable the internall pull-ups on the joystick pins.