libnxter  0.1
Motor.nxc
Go to the documentation of this file.
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  Motor.nxc
4  Copyright (C) 2008 Naba Kumar <naba@gnome.org>
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20 
21 #ifndef _MOTOR_H_
22 #define _MOTOR_H_
23 
24 #include "PID.nxc"
25 #include "Screen.nxc"
26 
35 inline void MotorStart(int motor, int power)
36 {
37  SetOutput(motor,
38  OutputMode, OUT_MODE_MOTORON | OUT_MODE_BRAKE,
39  Power, power,
40  UpdateFlags, UF_UPDATE_MODE | UF_UPDATE_SPEED | UF_UPDATE_RESET_BLOCK_COUNT,
41  RunState, OUT_RUNSTATE_RUNNING);
42 }
43 
47 inline void MotorStop(int motor)
48 {
49  SetOutput(motor,
50  OutputMode, OUT_MODE_BRAKE,
51  Power, 0,
52  UpdateFlags, UF_UPDATE_MODE | UF_UPDATE_SPEED,
53  RunState, OUT_RUNSTATE_IDLE);
54 }
55 
59 inline void MotorSetPower(int motor, int power)
60 {
61  SetOutput(motor, Power, power, UpdateFlags, UF_UPDATE_SPEED);
62 }
63 
71 inline void MotorStartSync(int motor1, int motor2, int power)
72 {
73  int motors[];
74  ArrayBuild(motors, motor1, motor2);
75 
76  SetOutput(motors,
77  OutputMode, OUT_MODE_MOTORON | OUT_MODE_BRAKE | OUT_MODE_REGULATED,
78  Power, power,
79  TurnRatio, 0,
80  RegMode, OUT_REGMODE_SYNC,
81  UpdateFlags, UF_UPDATE_MODE | UF_UPDATE_SPEED | UF_UPDATE_RESET_BLOCK_COUNT,
82  RunState, OUT_RUNSTATE_RUNNING);
83 }
84 
88 inline void MotorStopSync(int motor1, int motor2)
89 {
90  int motors[];
91  ArrayBuild(motors, motor1, motor2);
92  SetOutput(motors,
93  OutputMode, OUT_MODE_BRAKE,
94  Power, 0,
95  UpdateFlags, UF_UPDATE_MODE | UF_UPDATE_SPEED,
96  RunState, OUT_RUNSTATE_IDLE);
97 }
98 
102 inline void MotorSetPowerSync(int motor1, int motor2, int power)
103 {
104  int motors[];
105  ArrayBuild(motors, motor1, motor2);
106  SetOutput(motors, Power, power, UpdateFlags, UF_UPDATE_SPEED);
107 }
108 
113 inline void MotorSetTurnRatio(int motor1, int motor2, int turnRatio)
114 {
115  int motors[];
116  ArrayBuild(motors, motor1, motor2);
117  SetOutput(motors, TurnRatio, turnRatio);
118 }
119 
124 inline void MotorSetTurnRatioPower(int motor1, int motor2, int turnRatio, int power)
125 {
126  int motors[];
127  ArrayBuild(motors, motor1, motor2);
128  SetOutput(motors, TurnRatio, turnRatio, Power, power, UpdateFlags, UF_UPDATE_SPEED);
129 }
130 
135 int MotorRotateAngle(int motor, int power, long angle,
136  long PValue, long IValue, long DValue)
137 {
138  int samplingPeriod = 20; /* msec */
139  long motorTacho, output, lastError;
140  PIDControl pidControl;
141 
142  PIDControlInit(pidControl,
143  1000, /* PID scale */
144  PValue,
145  IValue,
146  DValue,
147  5, /* Steady state counts threshold */
148  2, /* Output gain */
149  power); /* Output absolute maximum */
150 
151  /* Speed is evaluated in the loop below */
152  MotorStart(motor, 0);
153 
154  PIDControlSetPoint(pidControl, angle);
155 
156  while(!PIDControlCheckEnd(pidControl))
157  {
158  motorTacho = GetOutput(motor, BlockTachoCount);
159  output = PIDControlStep(pidControl, motorTacho);
160  MotorSetPower(motor, output);
161  Wait(samplingPeriod);
162  }
163  MotorStop(motor);
164  lastError = PIDControlGetLastError(pidControl);
165  return lastError;
166 }
167 
173 int MotorRotateAngleSync(int motor1, int motor2, int power, long angle,
174  long PValue, long IValue, long DValue)
175 {
176  int samplingPeriod = 20; /* msec */
177  long motorTacho, output, lastError;
178  PIDControl pidControl;
179 
180  PIDControlInit(pidControl,
181  1000, /* PID scale */
182  PValue,
183  IValue,
184  DValue,
185  5, /* Steady state counts threshold */
186  2, /* Output gain */
187  power); /* Output absolute maximum */
188 
189  /* Speed is evaluated in the loop below */
190  MotorStartSync(motor1, motor2, 0);
191 
192  PIDControlSetPoint(pidControl, angle);
193 
194  while(!PIDControlCheckEnd(pidControl))
195  {
196  motorTacho = GetOutput(motor1, BlockTachoCount);
197  output = PIDControlStep(pidControl, motorTacho);
198  MotorSetPowerSync(motor1, motor2, output);
199  Wait(samplingPeriod);
200  }
201  MotorStopSync(motor1, motor2);
202  lastError = PIDControlGetLastError(pidControl);
203  return lastError;
204 }
205 
211 int MotorRotateAngleDiff(int motor1, int motor2, int power, long angle,
212  long PValue, long IValue, long DValue)
213 {
214  int samplingPeriod = 20; /* msec */
215  long motorTacho, output, lastError;
216  PIDControl pidControl;
217 
218  PIDControlInit(pidControl,
219  1000, /* PID scale */
220  PValue,
221  IValue,
222  DValue,
223  5, /* Steady state counts threshold */
224  1, /* Output gain */
225  power); /* Output absolute maximum */
226  PIDControlSetIntegralLimit(pidControl, 20);
227 
228  /* Speed is evaluated in the loop below */
229  MotorStartSync(motor1, motor2, 0);
230 
231  if (angle > 0)
232  MotorSetTurnRatio(motor1, motor2, -100);
233  else
234  MotorSetTurnRatio(motor1, motor2, +100);
235 
236  PIDControlSetPoint(pidControl, angle);
237 
238  while(!PIDControlCheckEnd(pidControl))
239  {
240  motorTacho = GetOutput(motor1, BlockTachoCount);
241  output = PIDControlStep(pidControl, motorTacho);
242 
243  if (output > 0)
244  MotorSetTurnRatioPower(motor1, motor2, -100, output);
245  else
246  MotorSetTurnRatioPower(motor1, motor2, +100, output);
247 
248  Wait(samplingPeriod);
249  }
250  MotorStopSync(motor1, motor2);
251  MotorSetTurnRatio(motor1, motor2, 0);
252  lastError = PIDControlGetLastError(pidControl);
253  return lastError;
254 }
255 
256 /* Test */
257 
258 #define TEST_ANGLE 180
259 
260 task TestMotorRotate ()
261 {
262  MotorRotateAngle(OUT_B, 100, TEST_ANGLE, 450, 0, 0);
263 }
264 
265 task TestMotorRotateSync ()
266 {
267  MotorRotateAngleSync(OUT_B, OUT_C, 100, TEST_ANGLE, 450, 0, 0);
268 }
269 
270 task TestMotorRotateDiff ()
271 {
272  MotorRotateAngleDiff(OUT_B, OUT_C, 100, TEST_ANGLE, 250, 0, 0);
273 }
274 
275 void TestPID()
276 {
277  Plotter pe;
278 
279  ClearScreen();
280  PlotterInit(pe, PLOT_TYPE_LINE, 0, 100, -180, 180);
281 
282  int motor = OUT_B;
283  start TestMotorRotateSync;
284 
285  int t;
286  while (1)
287  {
288  int error = (TEST_ANGLE - GetOutput(OUT_B, TachoCount)) * 32 / TEST_ANGLE;
289  PlotterPlot(pe, t, error);
290  Wait(20);
291  t++;
292  if (t >= 100)
293  {
294  t = 0;
295  Wait(50000);
296  break;
297  }
298  }
299 }
300 
301 #if 0
302 task main()
303 {
304 /*
305  MotorStartSync(OUT_B, OUT_C, 30);
306  Wait(2000);
307 
308  MotorSetPowerSync(OUT_B, OUT_C, 70);
309  Wait(5000);
310 
311  MotorStopSync(OUT_B, OUT_C);
312  Wait(3000);
313 */
314  start TestMotorRotateDiff;
315  TestPID();
316  Wait(20000);
317 }
318 #endif
319 
320 #endif
321 
long PIDControlStep(PIDControl &pidControl, long currentPoint)
Steps the PID controller. currentPoint is the current state of the system. The return value is the ou...
Definition: PID.nxc:142
void MotorStartSync(int motor1, int motor2, int power)
Starts the given 2 motors in synchronous mode with with the given initial power.
Definition: Motor.nxc:71
void MotorStart(int motor, int power)
Starts the given motor with the given power.
Definition: Motor.nxc:35
void MotorSetPowerSync(int motor1, int motor2, int power)
Sets the power of the given motor pair.
Definition: Motor.nxc:102
PID controller class.
Definition: PID.nxc:32
void MotorSetTurnRatio(int motor1, int motor2, int turnRatio)
Sets the turn ratio of the given motor pair running in synchronous mode.
Definition: Motor.nxc:113
void PlotterPlot(Plotter &plotter, long x, long y)
Plots the given point using the plotter on screen.
Definition: Screen.nxc:169
void MotorSetPower(int motor, int power)
Set the power of given motor.
Definition: Motor.nxc:59
void PIDControlInit(PIDControl &pidControl, long PIDScale, long PValue, long IValue, long DValue, int steadyStateCountThreshold, long outputGain, long absMaxOutput)
Initializes a PID controller with the given P, I and D values, output parameters. ...
Definition: PID.nxc:71
bool PIDControlCheckEnd(PIDControl &pidControl)
Checks if the PID controller has ended.
Definition: PID.nxc:120
void PlotterInit(Plotter &plotter, int plotType, long minX, long maxX, long minY, long maxY)
Initializes a plotter. There can be multiple plotters (for each graph) active simultaneous to draw on...
Definition: Screen.nxc:154
void MotorStopSync(int motor1, int motor2)
Stops the given two motor pair.
Definition: Motor.nxc:88
int MotorRotateAngleDiff(int motor1, int motor2, int power, long angle, long PValue, long IValue, long DValue)
Rotates the given pair of motors differentially (that is they rotate at the same pace in opposite dir...
Definition: Motor.nxc:211
Generic PID controller implementation.
void MotorStop(int motor)
Stops the given motor.
Definition: Motor.nxc:47
void PIDControlSetIntegralLimit(PIDControl &pidControl, long absIntegralLimit)
Sets integral output absolute maximum used to prevent integral windup. The default is set to absMaxOu...
Definition: PID.nxc:94
int MotorRotateAngle(int motor, int power, long angle, long PValue, long IValue, long DValue)
Rotates the given motor by given angle using the specified P, I and D gain values. The power is the maximum power to use for rotation.
Definition: Motor.nxc:135
void PIDControlSetPoint(PIDControl &pidControl, long setPoint)
Sets a new set point for the controller. The controller state is reset and the new target is pursued...
Definition: PID.nxc:103
long PIDControlGetLastError(PIDControl &pidControl)
Gets the error from the last step.
Definition: PID.nxc:131
void MotorSetTurnRatioPower(int motor1, int motor2, int turnRatio, int power)
Sets the turn ratio and power at the same time of the given motor pair running in synchronous mode...
Definition: Motor.nxc:124
Display functions for text and graphs.
int MotorRotateAngleSync(int motor1, int motor2, int power, long angle, long PValue, long IValue, long DValue)
Rotates the given pair of motors synchromously (that is they rotate at the same pace) by given angle ...
Definition: Motor.nxc:173