DC motor control program using TA7291P type driver and rotary encoder with A, B phase.
Dependencies: QEI mbed-rtos mbed
Revision 14:1196c2d455ae, committed 2012-12-02
- Comitter:
- kosaka
- Date:
- Sun Dec 02 10:03:09 2012 +0000
- Parent:
- 13:4116d4b6c2a5
- Child:
- 15:744a81d5b7ac
- Commit message:
- more readable
Changed in this revision
| main.cpp | Show annotated file Show diff for this revision Revisions of this file |
--- a/main.cpp Sun Dec 02 07:28:39 2012 +0000
+++ b/main.cpp Sun Dec 02 10:03:09 2012 +0000
@@ -22,9 +22,11 @@
float _Kp4i=10.0; // P gain for PID from motor volt. to motor current.
float _Ki4i=10.0; // I gain for PID from motor volt. to motor current.
float _Kd4i=0.0; // D gain for PID from motor volt. to motor current.
-#define iTS 0.0001 // [s], iTS, sampling time[s] of motor current i control PID using timer interrupt
-#define thTS 0.001 // [s], thTS>=0.001[s], sampling time[s] of motor angle th PID using rtos-timer
-#define TS2 0.01 // [s], TS2>=0.001[s], sampling time[s] to save data to PC using thread. But, max data length is 1000.
+#define TS0 0.0001 // [s], sampling time (priority highest: Ticker IRQ) of motor current i control PID using timer interrupt
+#define TS1 0.001 // [s], sampling time (priority high: RtosTimer) of motor angle th PID using rtos-timer
+#define TS2 0.01 // [s], sampling time (priority =main(): precision 4ms) to save data to PC using thread. But, max data length is 1000.
+#define TS3 0.05 // [s], sampling time (priority low: precision 4ms)
+#define TS4 0.1 // [s], sampling time (priority lowest: precision 4ms) to display data to PC tera term
#define TMAX 10 // [s], experiment starts from 0[s] to TMAX[s]
#define UMAX 3.3 // [V], max of control input u
#define UMIN -3.3 // [V], max of control input u
@@ -95,7 +97,7 @@
#ifdef GOOD_DATA
float data[1000][5]; // memory to save data offline instead of "online fprintf".
unsigned int count3; //
-unsigned int count2=(int)(TS2/iTS); //
+unsigned int count2=(int)(TS2/TS0); //
#endif
extern "C" void mbed_reset();
@@ -149,7 +151,7 @@
// y_old = _th; // y_old=y(t-TS) is older than y by 1 sampling time TS[s]. update data
#ifdef SIMULATION
- y = _th + thTS/0.1*(0.2*_iref*100-_th); //=(1-TS/0.1)*_y + 0.2*TS/0.1*_iref; // G = 0.2/(0.1s+1)
+ y = _th + TS1/0.1*(0.2*_iref*100-_th); //=(1-TS/0.1)*_y + 0.2*TS/0.1*_iref; // G = 0.2/(0.1s+1)
#else
// semaphore1.wait(); //
y = (float)encoder.getPulses()/(float)N_ENC*2.0*PI; // get angle [rad] from encoder
@@ -171,10 +173,10 @@
}
if( _f_imax==0 ){ // u is saturated?
// if( _e>((360.0/N_ENC)/180*PI) || _e<-((360.0/N_ENC)/180*PI) ){ // e is inside minimum precision?
- _eI = _eI + thTS*_e; // integral of e(t)
+ _eI = _eI + TS1*_e; // integral of e(t)
// }
}
- u = _Kp4th*_e + _Kd4th*(_e-e_old)/thTS + _Ki4th*_eI; // PID output u(t)
+ u = _Kp4th*_e + _Kd4th*(_e-e_old)/TS1 + _Ki4th*_eI; // PID output u(t)
#if CONTROL_MODE==1||CONTROL_MODE==2 // frequency response, or Step response
wt = _freq_u *2.0*PI*_time;
@@ -186,14 +188,14 @@
else u = UMIN;
#endif
#if CONTROL_MODE==3 // u=rand() to identify motor transfer function G(s) from V to angle
- if(count2==(int)(TS2/iTS)){
+ if(count2==(int)(TS2/TS0)){
u = ((float)rand()/RAND_MAX*2.0-1.0) * (UMAX-1.5)/2.0 + (UMAX+1.5)/2.0;
}else{
u = _iref;
}
#endif
#if CONTROL_MODE==4 // FFT identification, u=repetive signal
- if(count2==(int)(TS2/thTS)){
+ if(count2==(int)(TS2/TS1)){
u = data[count3][4];
}else{
u = _iref;
@@ -233,9 +235,9 @@
e_old = _ei; // e_old=e(t-TS) is older than e by 1 sampling time TS[s]. update data
_ei = _iref - y; // error e(t)
if( _f_umax==0 ){
- _eiI = _eiI + iTS*_ei; // integral of e(t)
+ _eiI = _eiI + TS0*_ei; // integral of e(t)
}
- u = _Kp4i*_e + _Kd4i*(_ei-e_old)/iTS + _Ki4i*_eiI; // PID output u(t)
+ u = _Kp4i*_e + _Kd4i*(_ei-e_old)/TS0 + _Ki4i*_eiI; // PID output u(t)
// u is saturated? for anti-windup
if( u>UMAX ){
@@ -259,10 +261,10 @@
u2Hbridge(_u); // input u to TA7291 driver
//-------- update data
- _time += iTS; // time
+ _time += TS0; // time
debug[0]=v_shunt_r; if(_f_u_plus==0){ debug[0]=-debug[0];}
#ifdef GOOD_DATA
- if(count2==(int)(TS2/iTS)){
+ if(count2==(int)(TS2/TS0)){
// j=0; if(_count>=j&&_count<j+1000){i=_count-j; data[i][0]=_r; data[i][1]=debug[0]; data[i][2]=_th; data[i][3]=_time; data[i][4]=_u;}
if( count3<1000 ){
data[count3][0]=_r; data[count3][1]=debug[0]; data[count3][2]=_th; data[count3][3]=_time; data[count3][4]=_u;
@@ -290,7 +292,7 @@
#endif
}
void moror_control() { // motor control ON for TMAX seconds.
- RtosTimer timer_controller(th_controller);
+ RtosTimer timer_controller(th_controller); // RtosTimer priority is osPriorityAboveNormal, just one above main()
FILE *fp; // save data to PC
float t=0;
#ifdef GOOD_DATA
@@ -305,9 +307,10 @@
if ( NULL == (fp = fopen( "/local/data.csv", "w" )) ){ error( "" );} // save data to PC
// start control (ON)
- controller_ticker.attach(&i_controller, iTS ); // Sampling period[s] of i_controller
- timer_controller.start((unsigned int)(thTS*1000.)); // Sampling period[ms] of th controller
+ controller_ticker.attach(&i_controller, TS0 ); // Sampling period[s] of i_controller
+ timer_controller.start((unsigned int)(TS1*1000.)); // Sampling period[ms] of th controller
+ t = _time;
while ( _time <= TMAX ) {
// BUG!! Dangerous if TS2<0.1 because multi interrupt by fprintf is not prohibited! 1st aug of fprintf will be destroyed.
// fprintf returns before process completed.
@@ -329,16 +332,34 @@
fclose( fp ); // release mbed USB drive
}
-void thread_print2PC(void const *argument) { // print to PC (tera term)
+void display2PC(){ // display to tera term on PC
+ pc.printf("%8.1f[s]\t%8.5f[V]\t%4d [deg]\t%8.2f\r\n", _time, _u, (int)(_th/(2*PI)*360.0), _r);//debug[0]*3.3/R_SHUNT); // print to tera term
+}
+void TS3timer(void const *argument) { // make sampling time TS4 timer (priority low: precision 4ms)
+ int ms;
+ unsigned long c;
while (true) {
- pc.printf("%8.1f[s]\t%8.5f[V]\t%4d [deg]\t%8.2f\r\n", _time, _u, (int)(_th/(2*PI)*360.0), _r);//debug[0]*3.3/R_SHUNT); // print to tera term
- Thread::wait(1);
+ c = _count;
+ //dummy(); // dummy() is called every TS3[s].
+ if( (ms=(int)(TS3*1000-(_count-c)*TS0*1000))<=0 ){ ms=1;}
+ Thread::wait(ms);
+ }
+}
+
+void TS4timer(void const *argument) { // make sampling time TS4 timer (priority lowest: precision 4ms)
+ int ms;
+ unsigned long c;
+ while (true) {
+ c = _count;
+ display2PC(); // display to tera term on PC. display2PC() is called every TS4[s].
+ if( (ms=(int)(TS4*1000-(_count-c)*TS0*1000))<=0 ){ ms=1;}
+ Thread::wait(ms);
}
}
int main() {
- Thread print2PC(thread_print2PC,NULL,osPriorityBelowNormal);
-// osStatus set_priority(osPriority osPriorityBelowNormal );
+ Thread startTS3timer(TS3timer,NULL,osPriorityBelowNormal);
+ Thread startTS4timer(TS4timer,NULL,osPriorityLow);
// Priority of Thread (RtosTimer has no priority?)
// osPriorityIdle = -3, ///< priority: idle (lowest)--> then, mbed ERROR!!
// osPriorityLow = -2, ///< priority: low