Caddy
A 2005 Roborodentia entry with vision and path planning capability
 All Data Structures Files Functions Variables Typedefs Macros Pages
motor_control.c
1 /*
2  * This file is part of Caddy.
3  *
4  * Caddy is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * Caddy is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with Caddy. If not, see <http://www.gnu.org/licenses/>.
16  */
17 #include "motor_control.h"
18 #include "encoder.h"
19 #include "tweak_data.h"
20 #include "lcd_16x2.h"
21 
22 // avr-libc
23 #include <stdint.h>
24 
25 void forward(uint8_t motorSelect, uint8_t speed)
26 {
27  switch (motorSelect)
28  {
29  case LEFT_MOTOR:
30  sbi(MC_PORT, FORWARD_LEFT);
31  cbi(MC_PORT, REVERSE_LEFT);
32  PWM_LEFT(speed);
33  break;
34  case RIGHT_MOTOR:
35  sbi(MC_PORT, FORWARD_RIGHT);
36  cbi(MC_PORT, REVERSE_RIGHT);
37  PWM_RIGHT(speed);
38  break;
39  case BOTH_MOTORS:
40  // both motors forward
41  sbi(MC_PORT, FORWARD_LEFT);
42  sbi(MC_PORT, FORWARD_RIGHT);
43  cbi(MC_PORT, REVERSE_LEFT);
44  cbi(MC_PORT, REVERSE_RIGHT);
45  PWM_RIGHT(speed);
46  PWM_LEFT(speed);
47  break;
48  }
49 }
50 
51 void tickWheels(int16_t leftTicks, int16_t rightTicks, uint8_t speed)
52 {
53  if (leftTicks >= 0)
54  {
55  forward(LEFT_MOTOR, speed);
56  }
57  else
58  {
59  reverse(LEFT_MOTOR, speed);
60  leftTicks *= -1;
61  }
62 
63  if (rightTicks >= 0)
64  {
65  forward(RIGHT_MOTOR, speed);
66  }
67  else
68  {
69  reverse(RIGHT_MOTOR, speed);
70  rightTicks *= -1;
71  }
72 
73  encoderSetPosition(LEFT_ENC, 0);
74  encoderSetPosition(RIGHT_ENC, 0);
75 
76  while (encoderGetPosition(LEFT_ENC) < leftTicks
77  || encoderGetPosition(RIGHT_ENC) < rightTicks)
78  {
79  if (encoderGetPosition(LEFT_ENC) >= leftTicks)
80  {
81  brake(LEFT_MOTOR);
82  }
83 
84  if (encoderGetPosition(RIGHT_ENC) >= rightTicks)
85  {
86  brake(RIGHT_MOTOR);
87  }
88 #if DEBUGGING
89  lcdPrintHex(encoderGetPosition(1) >> 8, 1, 8);
90  lcdPrintHex(encoderGetPosition(1), 1, 10);
91  lcdPrintHex(encoderGetPosition(0) >> 8, 1, 12);
92  lcdPrintHex(encoderGetPosition(0), 1, 14);
93 #endif
94  }
95  neutral();
96 }
97 
98 /*
99  * Move staight forward (positive) or straight back (negative)
100  */
101 void moveStraight(int16_t ticks, uint8_t speed)
102 {
103  tickWheels(ticks, ticks, speed);
104 }
105 
106 /*
107  * Brake one wheel, turn the other
108  */
109 void tractorTurn(uint8_t speed, int8_t brads)
110 {
111  if (brads > 0)
112  {
113  tickWheels(brads, 0, speed);
114  delay(tractorOvershootDelay);
115  tickWheels(brads - encoderGetPosition(LEFT_ENC), 0, speed);
116  delay(tractorOvershootDelay); //***temporary?
117  }
118  else
119  {
120  brads *= -1;
121  tickWheels(0, brads, speed);
122  delay(tractorOvershootDelay);
123  tickWheels(0, brads - encoderGetPosition(RIGHT_ENC), speed);
124  delay(tractorOvershootDelay); //***temporary?
125  }
126 }
127 
128 /*
129  * Turn on a dime (like a tank!)
130  */
131 void tankTurn(uint8_t speed, int8_t brads)
132 {
133  int8_t halfBrads = brads / 2;
134  tickWheels(halfBrads, (-1 * halfBrads), speed);
135 
136  // Now we correct/prevent overshoot
137  delay(16000);
138 
139  if (brads < 0)
140  {
141  tickWheels(encoderGetPosition(LEFT_ENC) + halfBrads,
142  -1 * halfBrads - encoderGetPosition(RIGHT_ENC),
143  speed);
144  }
145  else
146  {
147  tickWheels(halfBrads - encoderGetPosition(LEFT_ENC),
148  encoderGetPosition(RIGHT_ENC) - halfBrads,
149  speed);
150  }
151 }
152 
153 void reverse(uint8_t motorSelect, uint8_t speed)
154 {
155  switch (motorSelect)
156  {
157  case LEFT_MOTOR:
158  sbi(MC_PORT, REVERSE_LEFT);
159  cbi(MC_PORT, FORWARD_LEFT);
160  PWM_LEFT(speed);
161  break;
162  case RIGHT_MOTOR:
163  sbi(MC_PORT, REVERSE_RIGHT);
164  cbi(MC_PORT, FORWARD_RIGHT);
165  PWM_RIGHT(speed);
166  break;
167  case BOTH_MOTORS:
168  // both motors reverse
169  sbi(MC_PORT, REVERSE_LEFT);
170  sbi(MC_PORT, REVERSE_RIGHT);
171  cbi(MC_PORT, FORWARD_LEFT);
172  cbi(MC_PORT, FORWARD_RIGHT);
173  PWM_RIGHT(speed);
174  PWM_LEFT(speed);
175  break;
176  }
177 }
178 
179 void neutral(void)
180 {
181  // both motors coast, disable
182  PWM_RIGHT(0);
183  PWM_LEFT(0);
184 }
185 
186 //brake selected motor
187 //full brake assumed
188 void brake(uint8_t motorSelect)
189 {
190  switch (motorSelect)
191  {
192  case LEFT_MOTOR:
193  cbi(MC_PORT, REVERSE_LEFT);
194  cbi(MC_PORT, FORWARD_LEFT);
195  break;
196  case RIGHT_MOTOR:
197  cbi(MC_PORT, REVERSE_RIGHT);
198  cbi(MC_PORT, FORWARD_RIGHT);
199  break;
200  case BOTH_MOTORS:
201  // both motors reverse
202  cbi(MC_PORT, REVERSE_LEFT);
203  cbi(MC_PORT, REVERSE_RIGHT);
204  cbi(MC_PORT, FORWARD_LEFT);
205  cbi(MC_PORT, FORWARD_RIGHT);
206  break;
207  }
208  PWM_RIGHT(MAX_BRAKE);
209  PWM_LEFT(MAX_BRAKE);
210 }
211 
212 void enableMotors(void)
213 {
214  timer1PWMAOn();
215  timer1PWMBOn();
216 }
217 
218 void disableMotors(void)
219 {
220  timer1PWMAOff();
221  timer1PWMBOff();
222 }