dc_motor.c
Go to the documentation of this file.00001
00043 #include "dc_motor.h"
00044 #include "hw_dc_motor.h"
00045
00046 #include <algo/pid_control.h>
00047
00048 #include <drv/timer.h>
00049 #include <drv/adc.h>
00050
00051 #include <cfg/debug.h>
00052
00053 #include <kern/proc.h>
00054
00055 #define DC_MOTOR_TARGET_TRIM 0
00056
00057 #if DC_MOTOR_TARGET_TRIM
00058 #define DC_MOTOR_TARGET_TRIM_SAMPLE_PER 50
00059 static int tgt_sample_period = 0;
00060 #endif
00061
00065 static DCMotor dcm_all[CONFIG_NUM_DC_MOTOR];
00066
00068 static cpustack_t dc_motor_poll_stack[200];
00069
00071 static mtime_t sample_period;
00072
00073
00074
00075
00076
00077 static void dc_motor_do(int index);
00078
00093 static void NORETURN dc_motor_poll(void)
00094 {
00095 for (;;)
00096 {
00097 mtime_t max_sample_delay = 0;
00098 int i;
00099
00100
00101
00102
00103
00104 for (i = 0; i < CONFIG_NUM_DC_MOTOR; i++)
00105 {
00106 dc_motor_do(i);
00107 max_sample_delay = MAX(max_sample_delay, dcm_all[i].cfg->sample_delay);
00108 }
00109
00110
00111 timer_delay(sample_period - max_sample_delay);
00112
00113 for (i = 0; i < CONFIG_NUM_DC_MOTOR; i++)
00114 {
00115 if (dcm_all[i].status & DC_MOTOR_ACTIVE)
00116 {
00117 DC_MOTOR_DISABLE(dcm_all[i].index);
00118 pwm_enable(dcm_all[i].cfg->pwm_dev, false);
00119 }
00120 }
00121
00122
00123 timer_delay(max_sample_delay);
00124
00125 #if DC_MOTOR_TARGET_TRIM
00126 if (tgt_sample_period == DC_MOTOR_TARGET_TRIM_SAMPLE_PER)
00127 {
00128 dc_speed_t tgt_speed = ADC_RANGECONV(adc_read(6), 0, 65535);
00129
00130 for (i = 0; i < CONFIG_NUM_DC_MOTOR; i++)
00131 {
00132 if ((dcm_all[i].tgt_speed >= tgt_speed - 100) && (dcm_all[i].tgt_speed <= tgt_speed + 100))
00133 TRACEMSG("DCmt[%d]> tgt[%d]", i, tgt_speed);
00134
00135 dc_motor_setSpeed(i, tgt_speed);
00136 }
00137 tgt_sample_period = 0;
00138 }
00139 tgt_sample_period++;
00140 #endif
00141 }
00142 }
00143
00144
00145
00146
00147
00148 static void dc_motor_do(int index)
00149 {
00150 DCMotor *dcm = &dcm_all[index];
00151
00152 dc_speed_t curr_pos;
00153 pwm_duty_t new_pid;
00154
00155
00156 if (!(dcm->status & DC_MOTOR_ACTIVE))
00157 return;
00158
00159
00160 curr_pos = ADC_RANGECONV(adc_read(dcm->cfg->adc_ch), dcm->cfg->adc_min, dcm->cfg->adc_max);
00161
00162
00163 new_pid = pid_control_update(&dcm->pid_ctx, dcm->tgt_speed, curr_pos);
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 pwm_setDuty(dcm->cfg->pwm_dev, new_pid);
00178
00179
00180 pwm_enable(dcm->cfg->pwm_dev, true);
00181
00182 DC_MOTOR_ENABLE(dcm->index);
00183 }
00184
00191 void dc_motor_setDir(int index, bool dir)
00192 {
00193 DCMotor *dcm = &dcm_all[index];
00194
00195 if (dir != (dcm->status & DC_MOTOR_DIR))
00196 {
00197
00198 dcm->status &= ~DC_MOTOR_DIR;
00199 dcm->status |= DC_MOTOR_DIR;
00200 DC_MOTOR_SET_DIR(index, dir);
00201 }
00202
00203 }
00204
00205
00209 void dc_motor_setSpeed(int index, dc_speed_t speed)
00210 {
00211 dcm_all[index].tgt_speed = speed;
00212 }
00213
00217 void dc_motor_enable(int index, bool state)
00218 {
00219 DCMotor *dcm = &dcm_all[index];
00220
00221
00222
00223
00224
00225 pid_control_reset(&dcm->pid_ctx);
00226
00227 if (state)
00228 {
00229 dcm->status |= DC_MOTOR_ACTIVE;
00230 }
00231 else
00232 {
00233 pwm_enable(dcm->cfg->pwm_dev, false);
00234 DC_MOTOR_DISABLE(dcm->index);
00235
00236 dcm->status &= ~DC_MOTOR_ACTIVE;
00237 }
00238 }
00239
00243 void dc_motor_setup(int index, DCMotorConfig *dcm_conf)
00244 {
00245 DCMotor *dcm = &dcm_all[index];
00246
00247 dcm->cfg = dcm_conf;
00248
00249
00250
00251
00252 dcm->index = index;
00253
00254 DC_MOTOR_INIT(dcm->index);
00255
00256 pwm_setFrequency(dcm->cfg->pwm_dev, dcm->cfg->freq);
00257 pwm_enable(dcm->cfg->pwm_dev, false);
00258
00259
00260 pid_control_init(&dcm->pid_ctx, &dcm->cfg->pid_cfg);
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 if (!sample_period)
00274 sample_period = dcm->cfg->pid_cfg.sample_period;
00275
00276 ASSERT(sample_period == dcm->cfg->pid_cfg.sample_period);
00277
00278
00279 DC_MOTOR_SET_DIR(dcm->index, dcm->cfg->dir);
00280
00281 TRACEMSG("DC motort[%d]> kp[%f],ki[%f],kd[%f]", dcm->index, dcm_conf->pid_cfg.kp, dcm_conf->pid_cfg.ki, dcm_conf->pid_cfg.kd);
00282 TRACEMSG(" > pwm_dev[%d], freq[%ld], sample[%ld]", dcm_conf->pwm_dev, dcm_conf->freq, dcm_conf->sample_delay);
00283 TRACEMSG(" > adc_ch[%d], adc_max[%d], adc_min[%d]", dcm_conf->adc_ch, dcm_conf->adc_max, dcm_conf->adc_min);
00284 TRACEMSG(" > dir[%d]", dcm->cfg->dir);
00285
00286 }
00287
00288
00292 void dc_motor_init(void)
00293 {
00294 for (int i = 0; i < CONFIG_NUM_DC_MOTOR; i++)
00295 dcm_all[i].status &= ~DC_MOTOR_ACTIVE;
00296
00297
00298 sample_period = 0;
00299
00300
00301 proc_new(dc_motor_poll, NULL, sizeof(dc_motor_poll_stack), dc_motor_poll_stack);
00302
00303 }
00304