First, we will see an example of a program that controls the state of the output ports directly by giving commands to the output ports through the output port device register at address 0xf000.
Second, we use a more refined control method called Puls Width Modulation (PWM): patterns of time-driven output commands are given to the output ports. This can be used to drive the actuators on the output ports with different output energy levels: Light can shine with varying lux, motors can run at different speeds.
Finally, we will use the ideas in Fred Martins chapter 5 on Control: Simple Feedback Control and Proportional-Derivative Control to obtain a car that can follow a wall and a car that can follow a line.
This program shows how the different output commands Float,OnPos,OnNeg and Brake can be given to the output ports through the output port device register OutputPorts. Try to connect lamps or motors to see the effect that this program has on such actuators.#include "RCX_String.h" #include "RCX_Control.h" #include "H8.h" #include "Time.h" #include "LCD.h" #include "Battery.h" #include "Buttons.h" #include "OutputPorts.h" void _start(void) { ButtonsInit(); while ( ! Running ){ lcd_show_int16(BatteryLevel()); BusyPauseMS(300); } lcd_show_int16(OutputPorts); lcd_show_digit(0); BusyPauseMS(3000); while ( Running){ PortA(OnPos); lcd_show_int16(OutputPorts); lcd_show_digit(1); BusyPauseMS(3000); PortA(Brake); PortB(OnNeg); PortC(Brake); lcd_show_int16(OutputPorts); lcd_show_digit(2); BusyPauseMS(3000); OutputPortsFloat(); lcd_show_int16(OutputPorts); lcd_show_digit(3); BusyPauseMS(3000); PortB(OnNeg); lcd_show_int16(OutputPorts); lcd_show_digit(4); BusyPauseMS(3000); PortB(Float); lcd_show_int16(OutputPorts); lcd_show_digit(5); BusyPauseMS(3000); } PortA(OnPos); PortC(OnPos); lcd_show_int16(OutputPorts); lcd_show_digit(6); while( ! Running ); RCX_Reset(); }
A simple program that shows how the motors on e.g. a car-like robot can be driven by means of the commands from RobotBehaviours.h is the following ( TestRobotBehaviours.c ):
/* Test of RobotBehaviours.h Last updated 19.2.01. */ #include "RCX_String.h" #include "RCX_Control.h" #include "H8.h" #include "Time.h" #include "LCD.h" #include "Battery.h" #include "Buttons.h" #include "RobotRTS.h" #include "RobotBehaviours.h" void _start(void) { byte power; ButtonsInit(); lcd_show_int16(BatteryLevel()); while ( ! Running ); RTSInit(); RobotBehavioursInit(); RobotGoForward(8);lcd_show_int16(8); BusyPauseMS(3000); RobotRest(); BusyPauseMS(3000); RobotGoBackward(7);lcd_show_int16(7); BusyPauseMS(3000); RobotTurnClockwise(6);lcd_show_int16(6); BusyPauseMS(3000); RobotTurnCounterClockwise(5);lcd_show_int16(5); BusyPauseMS(3000); power = 0; while ( power < 17 ) { RobotGoForward(power); lcd_show_int16(power); power++; BusyPauseMS(1000); } power = 0; while ( power < 17) { RobotGoBackward(power); lcd_show_int16(power); power++; BusyPauseMS(1000); } RobotGoForwardAndTurn(16,8); lcd_show_int16(16); lcd_show_digit(8); BusyPauseMS(3000); RobotGoForwardAndTurn(13,2); lcd_show_int16(13); lcd_show_digit(2); BusyPauseMS(3000); RobotGoForwardAndTurn(2,8); lcd_show_int16(2); lcd_show_digit(8); BusyPauseMS(3000); RobotGoForwardAndTurn(8,2); lcd_show_int16(8); lcd_show_digit(2); BusyPauseMS(3000); RobotGoForwardAndTurn(2,8); lcd_show_int16(2); lcd_show_digit(8); BusyPauseMS(3000); RobotGoForwardAndTurn(8,2); lcd_show_int16(8); lcd_show_digit(2); BusyPauseMS(3000); RobotGoForwardAndTurn(2,8); lcd_show_int16(2); lcd_show_digit(8); BusyPauseMS(3000); RobotGoForwardAndTurn(3,7); lcd_show_int16(3); lcd_show_digit(7); BusyPauseMS(3000); RobotGoForwardAndTurn(7,3); lcd_show_int16(7); lcd_show_digit(3); BusyPauseMS(3000); RobotGoForwardAndTurn(4,6); lcd_show_int16(4); lcd_show_digit(6); BusyPauseMS(3000); RobotGoForwardAndTurn(6,4); lcd_show_int16(6); lcd_show_digit(4); BusyPauseMS(3000); RobotGoForwardAndTurn(5,5); lcd_show_int16(5); lcd_show_digit(5); BusyPauseMS(3000); RobotGoBackwardAndTurn(5,5); lcd_show_int16(5); lcd_show_digit(5); BusyPauseMS(3000); RobotGoBackwardAndTurn(4,6); lcd_show_int16(4); lcd_show_digit(6); BusyPauseMS(3000); RobotGoBackwardAndTurn(6,4); lcd_show_int16(6); lcd_show_digit(4); BusyPauseMS(3000); RobotGoBackwardAndTurn(3,7); lcd_show_int16(3); lcd_show_digit(7); BusyPauseMS(3000); RobotGoBackwardAndTurn(7,3); lcd_show_int16(7); lcd_show_digit(3); BusyPauseMS(3000); RobotGoBackwardAndTurn(2,8); lcd_show_int16(2); lcd_show_digit(8); BusyPauseMS(3000); RobotGoBackwardAndTurn(8,2); lcd_show_int16(8); lcd_show_digit(2); BusyPauseMS(3000); RobotRest(); lcd_show_int16(0); lcd_show_digit(0); BusyPauseMS(3000); RobotGoForward(8); lcd_show_int16(8); lcd_show_digit(8); BusyPauseMS(3000); RobotBehavioursClose(); BusyPauseMS(3000); RTSClose(); RCX_Reset(); }
First, we consider to follow a coloured wall build out of LEGO bricks. A light sensor can be used to measure the distance to the wall. Build a car with a light sensor on the side to measure the distance to the wall. Use this distance measure to make a program that follows the wall by means of a program similar to the c program of Fred Martins Figure 5.3. Also try to use the gentle turning algorithm proposed in section 5.1.2. Furthermore, try out the ideas of Exercises 5.1.3, 1, 2, and 3.
Now make a car that can follow a line by means of one or two light sensors pointing to the floor. Building instructions for such a car can be found on Jonathan B. Knudsen, The Unofficial Guide to LEGOŽ MINDSTORMS[tm] Robots. Try similar approaches as in the wall following program.
The development of more refined control can start by implementing Exercise 5.1.3, 4 for both control problems. Then try to implement a propertional control and afterwards add a derivative term.