In this page there is all my study about a little robot driven
by
a pic
microcontroller.
I have a lot of experience on C language so my first idea has
been use this language instead of the complex assembler.
The C language is easier to learn also for the person without
programming experience.
a
Leading Provider of Microcontroller & Analog Semiconductors
The PIC FLASH used allow erasing and reprogramming of the MCU
program memory.
Reprogrammability offers a highly flexible solution to today's
ever-changing market demands and can substantially reduce time to
market.
Users can program their systems late in the manufacturing process or
update systems in the field. This allows easy code revisions, system
parameteriza-tion or customer-specific options with no scrappage.
Reprogrammability also reduces the design verification cycle. PROGRAMMER BOARD
The first step has been get a programmer board and my choice is gone on
PROGRAMMATORE DEMOBOARD PER PIC • 8220-VM111
This board could be used to program and to make simple test with many
PIC from 8 to 28 pins.
The board coming with a PIC 16F627 installed.
To transfert the program from the PC to the board it is necessary a
serial port.
My experienze with two different USB to serial converter has been
negative.
The samples programs are in assembler language and the
demo2.asm allow to test any button and led in the VM111 board.
To compile the code you just need to start the compiler MPASMWIN,
included in the CDROM in board package,
select the demo2.asm file and click on Assemble button without change
any options but checking in the listbox the processor 16F627.
A file with HEX estention will be generated in the same directory of
the source file.
Now we need to start the program PROGPIC2 with the icon
,open the file with HEX estension, select the rigth Controller in the
listbox to 16F627, move the switch on the board in the PROG. posistion
and click on Write button.
If all is gone fine an OK in the Activity box will be print.
Now move the switch on the board in the RUN position and you should
seen the LED game.
Tolking with other DIY I have ear that the best programmer are the
parallel version.
THE C COMPILER
To manage a more friendly code I have searched a C Compiler to
start the experiment.
A freeware version of the C compiler could be found at HI-TEC Software in the Download /
Demos & free software selectin PICC-LITE (Windows), also a Linux
version is available.
The develop environment HTLPIC include a simple editor with compile
integration.
You need just to open the source file with extension .C and select
Compile / Compile and Link or F3.
Remember to save the source after the modification with File / Save
because the compilation does not save the source.
A new windows ask for the microcontroller selection.
To compile with a faster method use a command line like the
following:
THE CODE PART 1 - SWITCH ON A LED
Now we can start with a simple code to switch on a LED.
Follows the schematic of parts the VM111 board relative to the
connection from the PIC with 16 pins to the LED and SW (button).
We can see that the
LED6 is connected to the RB5
pin of PIC.
This schematic
has been extract from the complete available in the manual of the K8048
board.
Usually in the PIC the pins are configurable to do more functions so
the same pin could be an input or an output or program input.
Finally the code:
#include
<pic.h>
__CONFIG(WDTDIS & XT &
UNPROTECT & LVPDIS);
void main() { TRISB =
0b11000000;
PORTB =
0b00100000; }
Only two lines of source code? yes
The first line assigne to the TRISB register the 0 value to the
bit 0 to 5 to set the RA0 - RA5 port to be outputs following the table
in the PIC16F627 datasheet:
This table show all the rgister that could change the use of the RB
ports.
The second line ofcourse switch on the led on the RB5 port (LED6).
The __CONFIG specify the PIC processor configuration fuses and I
have lost many time to search this because does not apper in many
samples on internet.
Without this line the PROGPIC2 program give the warning "No
Config-World in File!" and if you go on writing this program this will
not run.
The uinique node to program a PIC without specify a __CONFIG line is
deselect the checkbox Erase bef. Write and Write Config. Word to
preserve a previous configuration and update only the code.
The parameters used in my sample are:
WDTDIS
//
disable watchdog
XT // specify an XT crystal
UNPROTECT // leave the code space unprotected
LVPDIS // low voltage programmer disabled
The last parameter has been set to skip the problems found using
the RB4 port.
This port is a low voltage programming input pin when this is enable so
cannot be used like output.
THE CODE PART 2 - SEQUENTIAL LED LOOP
There is the posibility to set only one bit per time of PORTB
using RBx variables.
To create a sequential led loop I have used the DelayMs() function
given with the compiler like examples in the delay.c.
#include
<pic.h>
#include
"delay.c"
__CONFIG(WDTDIS
& XT & UNPROTECT & LVPDIS);
#define
XTAL
4000000 // crystal
frequency - 4MHz #define
DELAY 250
// delay time
To get button state is possble use the RAx variables and
the follwing table given in the PIC16F627 datasheet show the relative
registers.
Has been necessary disable the comparators on input pins RA0, RA1 and
RA2 setting to 1 the first bits of the register CMCON.
CMCON
= 0b00000111; // CM0, CM1 and CM2 set to 1
This code run but it have a little problem: the button
press cannot be
recognized until we are in the led sequential part of the code so to
check the buttons functions you need to keep pressed the button until
the
led sequence is end.
To skip the problem of this code you just need to change the
DelayMs function inserting the button test in the loop.
Follows the code of function modified:
To the left are visible the two different frequency source for the
timer: the clock divide by 4 or the pin T0CK.
Changing the value of the T0CS and PSA registers is possible
change the flow as show below.
Follows an easy example to switch on and switch off a led
every second.
#include
<pic.h>
__CONFIG(WDTDIS & XT & UNPROTECT & LVPDIS);
#define XTAL
4000000 // crystal
frequency - 4MHz
long tics = 0l;
int flag = 1;
void interrupt prv_int(void)
{
//****************************************************************
// To calculate when will enter here:
//
// Freq = clock cycle / 4 / 256 = 4000000Hz / 4 /
256 = 3906Hz
// Period = 1 / 3906Hz = 0.256msec
//****************************************************************
if (!T0IF)
return;
//****************************************************************
// T0IF is 1 when the counter TMR0 is arrived to the
// overflow = 0xFF = 256 so to calculate when will
enter here:
//
// Freq = (clock cycle / 4 / 256) / 256 = 3906Hz /
256 = 15Hz
// Period = 1 / 15Hz = 65msec
//****************************************************************
T0IF = 0;
tics++;
if (tics == 15l)
{
tics = 0l;
//***********************************************************
// To calculate when will
enter here:
// Freq = 15Hz / 15 = 1Hz
and periord is 1 second
//******************************+****************************
if (flag == 1)
{
RB5
= 1;
flag
= 0;
}
else
{
RB5
= 0;
flag
= 1;
}
}
}
TMR0 = 0; // Reset the TMR0 counter
T0CS = 0; // Enable timer to get
the input from internal counter XTAL/4
PSA = 0; // Enable prescaler
to divide the frequency
PS2 = 1; //
PS1 = 1; // 111 mean
prescaler set to 1:256
PS0 = 1; //
INTCON = 0; // reset all the flag bits for all
the interrupts
GIE = 1; // global interrupt
enable bit (1: enable all)
T0IE = 1; // TMR0 overflow
interrupt enable bit (1: enable TMR0)
The following is a simple example to check the timer and interrupt
function of the PIC.
Understand the Timer2 function is very easy using the following picture.
The clock frequency divided by 4 pass to a prescaler with 3 possible
set 1:1, 1:4 or 1:16 and it is compared with the PR2 register
value.
If the result of compare is an equal the frequency pass to a postscaler
with all the value from 1:1 to 1:16.
Follows an easy example to switch on and switch off a led
every second.
#include
<pic.h>
__CONFIG(WDTDIS
& XT & UNPROTECT & LVPDIS);
#define
XTAL
4000000 // crystal
frequency - 4MHz
long tics =
0l; int flag = 1;
void
interrupt prv_int(void) {
if (!TMR2IF)
return;
//****************************************************************
// TMR2IF is 1 when the counter TMR2 is arrived to the
// PR2 register value (default: 0xFF = 255)
// so to calculate when will enter here:
//
// Freq = (clock cycle / 4 / 16 / 255 / 16 = 15Hz
// Period = 1 / 15Hz = 65msec
//****************************************************************
TMR2IF = 0;
tics++;
if (tics == 15l)
{
tics = 0l;
//***********************************************************
// To calculate when will enter here:
// Freq = 15Hz / 15 = 1Hz and periord is 1 second
//******************************+****************************
if (flag == 1)
{
RB5 = 1;
flag = 0;
}
else
{
RB5 = 0;
flag = 1;
}
} }
//******************************************************
// The following lines set the T2CON control register
TOUTPS3 = 1; // these are the 6,5,4,3 bits of the
TOUTPS2 = 1; // control register T2CON and set
TOUTPS1 = 1; // the postscale value
TOUTPS0 = 1; //
TMR2ON = 1; // this enable the Timer2
T2CKPS1 = 1; // these are the 1 and 0 bits of the
T2CKPS0 = 1; // control register T2CON and set the
// prescale value
// Is also possible set the bits of T2CON control register
// with a unique comand like the following:
//
// T2CON = 0x7E;
//
// here the hexadecimal value 7E means
// 76543210
// 1111110
// 1111 -> postscale value 1:16
// 1 -> enable timer2
// 1x -> prescaler value 1:16
//******************************************************
TMR2IE = 1; // TMR2 to PR2 enable match interrupt
// PR2 = 0xFF; default value
INTCON = 0; // reset all the flag bits for all the interrupts
PEIE = 1; // peripheral interrupt enable bit
GIE = 1; // global interrupt enable bit (1:
enable all)
The Tamiya 70097 Twin-Motor Gearbox is a small
(3in long) plastic gearbox. It contains two small DC motors that drive
separate 3mm hexagonal output shafts. There are two ways to put the kit
together: with a high-speed 58:1 gear ratio or with a slower 203:1 gear
ratio. Either way, the motors provide plenty of power to drive any
small robot.
This motor unit togheter with the Tamiya 70144 Ball Caster and with the
circular laser-cut plastic
robot chassis produced by Pololu makes
a great base for small mobile robot.
(click on image to enlarge)
With a diameter of only five inches (slightly bigger than a CD),
this acrylic chassis is ideal for building sturdy robots capable of
navigating tight spaces. As shown below, the circular chassis has many
holes and slots for mounting sensors, motors, and other hardware.
And now start the game ...
You can assemble the gearboxes to have a 58:1 or a 204:1 gear
ratio but only the 204:1 (C) is valid for the integration with the
Tamiya 70144 Ball Caster .
THE MOTOR CONTROLLER
If we want a speed regulator for the motors become necessary use a
motor controller.
The Pololu
Micro Dual Serial Motor Controller can individually control two
motors and set each motor to go forward or backward at any of 127
speeds.
For complete specifications and information see the user's guide
The connection with the microcontroller and with the two motors are
very simple.
Module Pinout:
PIN
FUNCTION
1
motor supply (1.8-9.0 V)
2
ground (0 V)
3
logic supply (2.5-5.5V)
4
serial control input
5
reset
6
motor 1, positive output
7
motor 1, negative output
8
motor 0, negative output
9
motor 0, positive output
In this following test I have connected both pin 1 and 3 of the motor
controller to the power supply pack of the motors 3 x AA in series.
The reset pin (5) has been connected to the pin 9 (RB3) of the PIC
16F627 and the input pin (4) to the pin 8 (RB2/TX) of the PIC.
From the datasheet of the PIC:
Follows the simple code to drive the two motors with this Micro Dual
Serial Motor Controller.
// please add here the
heater of code like the previous examples
// Here I define some constant to
create an easy to understand call to the motor() function. #define
MOTOR1 (1) #define MOTOR2 (2) #define FOWARD (1) #define REVERSE (2) #define HALFSPEED (127/2) #define FULLSPEED (127)
void motor(int motor, int
direction, int speed) { int bits = 0;
while(TXIF ==
0); // loop while the
USART transmit buffer is full
TXREG = 0x80;
// first byte always 0x80 from the Pololu datasheet
while(TXIF == 0);
TXREG =
0x00;
// second byte always 0x00 from the Pololu datasheet
while(TXIF == 0);
if (motor ==
MOTOR2) // set to 1 the second bit
bits += 2;
if (direction ==
FOWARD) // set to 1 the first bit
bits += 1;
//***************************************************************** // Following the
datasheet in the section of // UNIVERSAL
SYNCHRONOUS/ASYNCHRONOUS RECEIVER/TRANSMITTER (USART) // // these lines
set the TXSTA register // CSRC =
0; // in async. mode don't used TX9 =
0; // 0: set 8 bit transmission TXEN =
1; // 1: transmit enable SYNC =
0; // 0: asynchronous mode BRGH =
1; // 1: async. high speed TRMT =
0; // 0: transmit shift register full TX9D =
0; // 9th bit of transmit data // // Is also
possible set all the bits of TXSTA control register // with a unique
command like the following: // TXSTA =
0b00100100;
//***************************************************************** // these lines
set the RCSTA register // SPEN =
1; // 1: serial port enable RX9 =
0; // 0: set 8 bit reception SREN =
0; // in async. mode don't used CREN =
1; // 1: enable continuous receive ADEN =
0; // in 8 bit mode don't used FERR =
0; // framing error bit ? OERR =
0; // 0: no overrum error RX9D =
0; // 9th bit of received data // // Is also
possible set all the bits of RCSTA control register // with a unique
command like the following: // RCSTA =
0b10010000;
//***************************************************************** // these lines
set the UART Baud Rate Generator // SPBRG = 51; // // with the
calculation formula is not very easy to find this value // but the
tables in the datasheet show the decimal value to set for // many baud
rate and many clock frequency // If we use
want a baud rate of 19200 (19.2 K) and the cpu quartz is // 4 MHz the
value is 51.
// Now reset the
Motor controller with these following command because I have // connected the
reset pin of the controller to the RB3 pin RB3 = 0; DelayMs(200); RB3 = 1; DelayMs(200);
// This function
will be usefull to control the 2 motors and now it is used to
// start the two motors at half speed
motor(MOTOR1, FOWARD, HALFSPEED); motor(MOTOR2,
FOWARD, HALFSPEED);
// switch-on the
2 led RB4 = 1; RB5 = 1;
while(1) {
// Will be easy to control the motors with the four
buttons
// Now reset the
Motor controller with these following command because I have // connected the
reset pin of the controller to the RB3 pin RB3 = 0; DelayMs(200); RB3 = 1; DelayMs(200);
// This function
will be usefull to control the 2 motors motor(MOTOR1,
FOWARD, HALFSPEED); motor(MOTOR2,
FOWARD, HALFSPEED);
// Just to save
the status motor1 = FOWARD; motor2 = FOWARD;
// switch-on the
2 led RB4 = 1; RB5 = 1;
while(1) {
// Will be easy to control the motors with the four
buttons