PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
robot.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 #include "pic24_all.h"
30 #include <stdio.h>
31 
32 /** \file
33 Capstone project for a small 3-wheeled robot with
34 IR control and collision detection.
35 */
36 
37 extern uint8_t irFifoRead(void);
38 extern void configTimer2(void);
39 extern void configInputCapture1(void);
40 extern void configOutputCapture1(void);
41 extern uint8_t irFifoDataRdy(void);
42 
43 #define WHEEL_PWM_STEPS 10 //number of PWM steps
44 #define WHEEL_PWM_STEPSIZE 500 //in microseconds
45 #define MAN_DRIVE 0
46 #define AUTO_DRIVE 1
47 
48 #define BLOCKAGE_PRESENT 560 //1.8 V
49 #define BLOCKAGE_CLEAR 434 //1.4 V
50 
51 
52 uint8_t u8_leftDC, u8_rightDC; //left, right duty cycles, left period
53 uint8_t u8_leftPeriod,u8_rightPeriod ; //left/right period counters
54 uint16_t u16_adcVal;
55 
56 
57 typedef struct tagFLAGBITS {
58 unsigned u1_mode:
59  1;
60 unsigned u1_obstacle:
61  1;
62 unsigned u1_irCmdFlag:
63  1;
64 } FLAGBITS;
65 static volatile FLAGBITS flags;
66 
67 
68 #define WHEEL_LEFT_1A _LATB1
69 #define WHEEL_LEFT_2A _LATB3
70 #define WHEEL_LEFT_EN _LATB2
71 #define WHEEL_RIGHT_1A _LATB14
72 #define WHEEL_RIGHT_2A _LATB12
73 #define WHEEL_RIGHT_EN _LATB13
74 
75 
76 #define WHEEL_LEFT_FORWARD() { WHEEL_LEFT_1A = 1; WHEEL_LEFT_2A = 0; }
77 #define WHEEL_LEFT_REVERSE() { WHEEL_LEFT_1A = 0; WHEEL_LEFT_2A = 1; }
78 #define WHEEL_LEFT_STOP() { WHEEL_LEFT_1A = 0; WHEEL_LEFT_2A = 0; }
79 #define WHEEL_RIGHT_FORWARD() { WHEEL_RIGHT_1A = 1; WHEEL_RIGHT_2A = 0; }
80 #define WHEEL_RIGHT_REVERSE() { WHEEL_RIGHT_1A = 0; WHEEL_RIGHT_2A = 1; }
81 #define WHEEL_RIGHT_STOP() { WHEEL_RIGHT_1A = 0; WHEEL_RIGHT_2A = 0; }
82 
83 static inline void configLeftWheel(void) {
84  CONFIG_RB1_AS_DIG_OUTPUT();
85  CONFIG_RB2_AS_DIG_OUTPUT();
86  CONFIG_RB3_AS_DIG_OUTPUT();
87 }
88 
89 static inline void configRightWheel(void) {
90  CONFIG_RB12_AS_DIG_OUTPUT();
91  CONFIG_RB13_AS_DIG_OUTPUT();
92  CONFIG_RB14_AS_DIG_OUTPUT();
93 }
94 
95 
96 void _ISRFAST _T3Interrupt (void) {
97  uint16_t u16_temp;
98  _T3IF = 0; //clear the timer interrupt bit
99  if (u8_rightDC) {
100  if ( u8_rightPeriod == WHEEL_PWM_STEPS || !u8_rightPeriod) {
101  u8_rightPeriod = 0;
102  WHEEL_RIGHT_EN = 1;
103  } else if (u8_rightPeriod >= u8_rightDC) WHEEL_RIGHT_EN = 0;
104  u8_rightPeriod++;
105  } else {
106  WHEEL_RIGHT_EN = 0;
107  u8_rightPeriod = 0;
108  }
109  if (u8_leftDC) {
110  if ( u8_leftPeriod == WHEEL_PWM_STEPS || !u8_leftPeriod) {
111  u8_leftPeriod = 0;
112  WHEEL_LEFT_EN = 1;
113  } else if (u8_leftPeriod >= u8_leftDC) WHEEL_LEFT_EN = 0;
114  u8_leftPeriod++;
115  } else {
116  WHEEL_LEFT_EN = 0;
117  u8_rightPeriod = 0;
118  }
119  u16_temp = ADC1BUF0;
120  if (u16_temp > BLOCKAGE_PRESENT ) flags.u1_obstacle = 1;
121  else if (u16_temp < BLOCKAGE_CLEAR) flags.u1_obstacle = 0;
122  AD1CON1bits.SAMP = 1; //start next ADC conversion for next interrupt
123 }
124 
125 void configTimer3(void) {
126  //ensure that Timer2,3 configured as separate timers.
127  T2CONbits.T32 = 0; // 32-bit mode off
128  T3CON = T3_OFF |T3_IDLE_CON | T3_GATE_OFF
129  | T3_SOURCE_INT
130  | T3_PS_1_8 ;
131  PR3 = usToU16Ticks (WHEEL_PWM_STEPSIZE, getTimerPrescale(T3CONbits)) - 1;
132  TMR3 = 0; //clear timer3 value
133  _T3IF = 0; //clear interrupt flag
134  _T3IP = 1; //choose a priority
135  _T3IE = 1; //enable the interrupt
136  T3CONbits.TON = 1; //turn on the timer
137 }
138 
139 /*
140 Configure Timer3 for a WHEEL_PWM_STEPSIZE periodic interrupt, do
141 manual PWM on both wheels
142 */
143 
144 void configWheels(void) {
145  u8_leftDC = 0;
146  u8_rightDC = 0;
147  u8_leftPeriod = 0;
148  u8_rightPeriod = 0;
149  configLeftWheel();
150  configRightWheel();
151  WHEEL_LEFT_FORWARD();
152  WHEEL_RIGHT_FORWARD();
153  configTimer3();
154 }
155 
156 #define CMD_STOP 0x36 //VCR stop button
157 #define CMD_SPEEDUP 0x29 //VCR pause button
158 #define CMD_SLOWDOWN 0x37 //VCR record button
159 #define CMD_FORWARD 0x35 //VCR play button
160 #define CMD_TURN_LEFT 0x32 //VCR rewind button
161 #define CMD_TURN_RIGHT 0x34 //VCR fast forward button
162 #define CMD_REVERSE 0x05 //VCR numeral 5
163 #define CMD_SPIN 0x09 //VCR numeral 9
164 #define CMD_MODESWAP 0x01 //VCR numeral 1
165 #define CMD_NOP 0x00
166 
167 #define DEFAULT_SPEED 4
168 #define DEFAULT_SPEED 4
169 #define BACK_SPEED 6
170 
171 void doSpeedUp(uint8_t u8_speed) {
172  u8_leftDC = 0;
173  u8_rightDC = 0;
174  do {
175  u8_leftDC++;
176  u8_rightDC++;
177  DELAY_MS(100);
178  } while (u8_leftDC < u8_speed);
179 }
180 
181 void allStop(void) {
182  //slow to a stop
183  while (u8_leftDC || u8_rightDC) {
184  if (u8_leftDC) u8_leftDC--;
185  if (u8_rightDC) u8_rightDC--;
186  DELAY_MS(100);
187  }
188 }
189 
190 void goForward(uint8_t u8_speed) {
191  WHEEL_LEFT_FORWARD();
192  WHEEL_RIGHT_FORWARD();
193  doSpeedUp(u8_speed);
194 }
195 
196 void goReverse(uint8_t u8_speed) {
197  WHEEL_LEFT_REVERSE();
198  WHEEL_RIGHT_REVERSE();
199  doSpeedUp(u8_speed);
200 }
201 
202 void processCmd(uint8_t u8_cmd) {
203  switch (u8_cmd) {
204  case CMD_SPEEDUP:
205  if (u8_leftDC < WHEEL_PWM_STEPS) u8_leftDC += 1;
206  if (u8_rightDC < WHEEL_PWM_STEPS) u8_rightDC += 1;
207  break;
208  case CMD_SLOWDOWN:
209  if (u8_leftDC) u8_leftDC -= 1;
210  if (u8_rightDC) u8_rightDC -= 1;
211  break;
212  case CMD_STOP:
213  allStop();
214  break;
215  case CMD_FORWARD:
216  allStop();
217  goForward(DEFAULT_SPEED);
218  break;
219  case CMD_REVERSE:
220  allStop();
221  goReverse(DEFAULT_SPEED);
222  break;
223  case CMD_TURN_LEFT:
224  if (u8_leftDC) u8_leftDC -= 1;
225  break;
226  case CMD_TURN_RIGHT:
227  if (u8_rightDC) u8_rightDC -= 1;
228  break;
229  case CMD_SPIN:
230  allStop();
231  WHEEL_LEFT_FORWARD();
232  WHEEL_RIGHT_REVERSE();
233  doSpeedUp(DEFAULT_SPEED);
234  break;
235  case CMD_MODESWAP:
236  allStop();
237  flags.u1_mode = !flags.u1_mode;
238  break;
239  default: //do nothing
240  break;
241  }
242 }
243 
244 uint8_t getIRCMD(void) {
245  uint8_t u8_x, u8_cmd;
246  u8_x = irFifoRead();
247  u8_cmd = irFifoRead();
248  if (u8_x & 0x20) outString("Toggle = 1, ");
249  else outString("Toggle = 0, ");
250  outString("Addr: ");
251  outUint8(u8_x & 0x1F);
252  outString(",Cmd: ");
253  outUint8(u8_cmd);
254  outString("\n");
255  if (flags.u1_irCmdFlag) flags.u1_irCmdFlag = 0;
256  else flags.u1_irCmdFlag = 1;
257  if (flags.u1_irCmdFlag) return u8_cmd;
258  else return CMD_NOP;
259 }
260 
261 void checkIR(void) {
262  uint8_t u8_cmd;
263  if (irFifoDataRdy()) {
264  u8_cmd = getIRCMD();
265  processCmd(u8_cmd);
266  }
267 }
268 
269 void doTurn(uint8_t u8_ltarg, uint8_t u8_rtarg) {
270  u8_leftDC = 0;
271  u8_rightDC = 0;
272  while ((u8_leftDC != u8_ltarg) ||
273  (u8_rightDC != u8_rtarg) ) {
274  if (u8_leftDC != u8_ltarg) u8_leftDC++;
275  if (u8_rightDC != u8_rtarg) u8_rightDC++;
276  DELAY_MS(80);
277  }
278 }
279 
280 
281 void autoDrive(void) {
282  if (flags.u1_obstacle) {
283  allStop();
284  //backup, pivot
285  WHEEL_LEFT_REVERSE();
286  WHEEL_RIGHT_REVERSE();
287  doSpeedUp(BACK_SPEED);
288  DELAY_MS(300);
289  u8_leftDC = 2; //slow down wheel to turn
290  DELAY_MS(800); //turning
291  allStop();
292  DELAY_MS(200);
293  WHEEL_LEFT_FORWARD();
294  WHEEL_RIGHT_FORWARD();
295  doTurn(BACK_SPEED,2);
296  DELAY_MS(600);
297  doSpeedUp(DEFAULT_SPEED);
298  } else if (u8_leftDC != DEFAULT_SPEED ||
299  u8_rightDC != DEFAULT_SPEED ) {
300  WHEEL_LEFT_FORWARD();
301  WHEEL_RIGHT_FORWARD();
302  doSpeedUp(DEFAULT_SPEED);
303  }
304 }
305 
306 int main (void) {
307  configBasic(HELLO_MSG);
308  CONFIG_AN1_AS_ANALOG();
309  configADC1_ManualCH0( ADC_CH0_POS_SAMPLEA_AN1, 31, 1 );
310  SET_SAMP_BIT_ADC1(); //start first conversion
311  configTimer2();
312  configInputCapture1();
313  configWheels();
314  while (1) {
315  checkIR();
316  if (flags.u1_mode == AUTO_DRIVE) autoDrive();
317  doHeartbeat();
318  } //end while(1)
319 }