//***************************************************************************** // 2007/08/18 // Part3. トラ技のおまけ基板でNゲージを自動運転 // //「Part2. トラ技のおまけ基板でNゲージを自動加減速」のPwmPP2.cを改造しました。 // 前回のソフトでは、加減速を繰り返すだけでしたが、 // 今回は、発進→加速→定速走行→減速→停止→逆転発進を繰り返すようにしました。 //***************************************************************************** // 2007/07/29 // トラ技のおまけ基板で自動加減速パワーパックの実験をするソフト // ハードはトランジスタ技術の2007年8月号に付属している基板を使用しました。 // ソフトは付属のCDをインストールすると作成される // C:\CQ\tr0709\projects\AdcThruPwmフォルダ内のAdcThruPwm.cを元に改造しました。 //***************************************************************************** #include #include #include #include //-------------------------------------------------------------------- //ブートローダによる書き込みでは、コンフィグレーションレジスタは //書き込まれません。 // configuration _FWDT(WDT_OFF); // _FGS(CODE_PROT_OFF); _FOSC(CSW_FSCM_OFF & FRC_PLL16); // 7.37x16/4=29.48MHz Clock _FBORPOR(PBOR_OFF & PWRT_64 & MCLR_EN); //-------------------------------------------------------------------- // A/D control register unsigned int _ADCON1; unsigned int _ADCON2; unsigned int _ADCON3; unsigned int _ADCHS; unsigned int _ADPCFG; unsigned int _ADCSSL; // PWM control register unsigned int _PTCON; unsigned int _PWMCON1; unsigned int _PWMCON2; // data unsigned int AdData1; unsigned int PwmData; #define Dir_Cmd _RB8 // 正転/逆転指令出力 #define Dir_SW _RF4 // 正転/逆転スイッチ入力 #define AT_ML _RF5 // 自動/手動スイッチ入力 signed int Kagen; // 加速/減速のフラグです。 signed int MaxSpeed; // 最高速度を設定する変数です。 signed int Teisoku; // 定速のフラグです。これが1だと加減速を禁止します。 unsigned int TeisokuTimer; // 定速で走行する時間のタイマーです。この数値x20msecが定速走行時間になります。 //-------------------------------------------------------------------------------------------------------------------- // タイマー3の割り込みルーチンです。112.5Hz(8.88ms) // 手動モードでは、A/D値(ボリュームムの入力)をPWMのDutyに変換します。 // void __attribute__((__interrupt__, __shadow__, no_auto_psv)) _AltT3Interrupt(void) { _RB6=~_RB6; // タイマー3の周波数の確認用なので不要です。 if (TeisokuTimer !=0) { // 定速タイマーがゼロでなければ(定速走行中ならば) TeisokuTimer--; // 定速タイマーをマイナス1 } // --- A/D is 12bits, then trancate 2bits, PWM is 10bits // while(!IFS0bits.ADIF); // A/D変換終了待ち // AdData12 = ReadADC12(0); // 12bit resolution AD Data // AdData10 = AdData12>>2; // 10bit resolution AD Data AdData1 = ReadADC12(0); // 12bit resolution AD Data AN3 if ( AT_ML==1) { // AT_MLがHi(手動モード)ならば A/D値がPWMデータ。 PwmData = AdData1>>2; // 10bit resolution for PWM SetDCOC2PWM(1024-PwmData); // Duty値をセットしますがモータードライバの入力が負論理なので反転させます。 } IFS0bits.ADIF = 0; // clear A/D interuppt flag IFS0bits.T3IF = 0; // clear T3 interuppt flag } //-------------------------------------------------------------------------------------------------------------------- // タイマー1の割り込みルーチンです。 // 加減速中にタイムアップする度にDUTYを1ディジット加減します。 // void __attribute__((__interrupt__, __shadow__, no_auto_psv)) _AltT1Interrupt(void) { _RB7=~_RB7; // 加減速時間の周波数の確認用なので不要です。 if ( AT_ML==0) { // AT_MLがLo(自動モード)で if (TeisokuTimer !=0) { // 定速タイマーがゼロでなければ(定速走行中ならば) // TeisokuTimer--; // 定速タイマーをマイナス1 } else{ if (Kagen==1) { // 加減フラグが1ならば PwmData++; // 1ディジット加速 if (PwmData>=MaxSpeed){ // 最高速度以上ならば TeisokuTimer=563; // 定速走行へ(563x8.88msec=5secが定速走行時間) Kagen=-1; // 最高速で定速走行後は減速に転じます。 } } else { // 加減フラグが1でなければ PwmData--; // 1ディジット減速 if (PwmData==0){ // 停止(0%Duty)ならば TeisokuTimer=338; // しばらく停止(338x8.88msec=3secが停止時間) Dir_Cmd=~Dir_Cmd; // 停止後は、方向転換して Kagen=+1; // 加速に転じます。 } } } SetDCOC2PWM(1024-PwmData); // Duty値をセットしますがモータードライバの入力が負論理なので反転させます。 } IFS0bits.T1IF = 0; // clear T1 interuppt flagタイマー1の割り込み要因フラグをクリアします。 } // //-------------------------------------------------------------------------------------------------------------------- //   メ イ ン ル ー チ ン //-------------------------------------------------------------------------------------------------------------------- int main(void) { // port init TRISB=0x001F; // RB9:5=OUT,RB4:0=IN TRISF=0b01111100; // RF5:2=IN CNPU2bits.CN17PUE=1; // CN17(RF4)=pullUp 自動/手動スイッチ入力 CNPU2bits.CN18PUE=1; // CN18(RF5)=pullUp 正転・逆転スイッチ入力 // Use Alternate Interrupt Vector Table INTCON2bits.ALTIVT=1; // Confirm to turn off ADC ADCON1bits.ADON=0; // ADC init _ADCHS= ADC_CH0_POS_SAMPLEA_AN3 & ADC_CH0_NEG_SAMPLEA_NVREF; // A-D channel-3 select SetChanADC12(_ADCHS); _ADCON1=ADC_MODULE_ON & ADC_IDLE_CONTINUE & ADC_FORMAT_INTG & ADC_CLK_TMR & ADC_AUTO_SAMPLING_ON & ADC_SAMP_OFF; _ADCON2=ADC_VREF_AVDD_AVSS & ADC_SCAN_OFF & ADC_SAMPLES_PER_INT_1 & ADC_ALT_BUF_OFF & ADC_ALT_INPUT_OFF; // Tad={Tcy(ADCS+1)}/2>334ns, Then ADCS>18.7, Tad=10*Tcy _ADCON3=ADC_SAMPLE_TIME_1 & ADC_CONV_CLK_SYSTEM & ADC_CONV_CLK_10Tcy; _ADPCFG=ENABLE_AN3_ANA & ENABLE_AN4_ANA; // A-D channel-3&4 analog input _ADCSSL=SCAN_NONE; OpenADC12(_ADCON1, _ADCON2, _ADCON3, _ADPCFG, _ADCSSL); // 加減速時間のタイマーにタイマー1を使用しました。 // OpenTimer1(T1_ON & T1_GATE_OFF & T1_PS_1_256 & T1_SOURCE_INT, 1152*4); // この例では約80ms単位で1ディジットずつ加減します。 // OpenTimer1(T1_ON & T1_GATE_OFF & T1_PS_1_256 & T1_SOURCE_INT, 1152*3); // この例では約40ms単位で1ディジットずつ加減します。 OpenTimer1(T1_ON & T1_GATE_OFF & T1_PS_1_256 & T1_SOURCE_INT, 1152*2); // この例では約20ms単位で1ディジットずつ加減します。 // OpenTimer1(T1_ON & T1_GATE_OFF & T1_PS_1_256 & T1_SOURCE_INT, 1152); // この例では約10ms単位で1ディジットずつ加減します。 // OpenTimer1(T1_ON & T1_GATE_OFF & T1_PS_1_256 & T1_SOURCE_INT, 1152/2); // この例では約5ms単位で1ディジットずつ加減します。 // OpenTimer1(T1_ON & T1_GATE_OFF & T1_PS_1_256 & T1_SOURCE_INT, 1152/3); // この例では約3.3ms単位で1ディジットずつ加減します。 // OpenTimer1(T1_ON & T1_GATE_OFF & T1_PS_1_256 & T1_SOURCE_INT, 1152/4); // この例では約2.5ms単位で1ディジットずつ加減します。 // 加減速時間もボリュームで調節出来るようにしたいですね。 ConfigIntTimer1(T1_INT_PRIOR_5 & T1_INT_ON); // タイマー1の割り込み優先順位とON/OFF設定 // ----------------------------------------------------------------------------------------------------------------- // Timer3 setting // OpenTimer3(T3_ON & T3_GATE_OFF & T3_PS_1_1 & T3_SOURCE_INT, 1024-1); // 28.8kHz sampling ADC OpenTimer3(T3_ON & T3_GATE_OFF & T3_PS_1_256 & T3_SOURCE_INT, 1024-1); // 28.8kHz/256=112.5Hz(8.88ms) ConfigIntTimer3(T3_INT_PRIOR_5 & T3_INT_ON); // PWMの周波数を決める部分です。下記の4種類から選べます。 // ロータリースイッチなどで選択可能にするのも面白いかも? // Timer2 setting // OpenTimer2(T2_ON & T2_GATE_OFF & T2_PS_1_1 & T2_SOURCE_INT, 1024-1); // 28.8kHz carrier PWM // OpenTimer2(T2_ON & T2_GATE_OFF & T2_PS_1_8 & T2_SOURCE_INT, 1024-1); // 28.8kHz/8=3.6kHz carrier PWM // OpenTimer2(T2_ON & T2_GATE_OFF & T2_PS_1_64 & T2_SOURCE_INT, 1024-1); // 28.8kHz/64=450Hz carrier PWM OpenTimer2(T2_ON & T2_GATE_OFF & T2_PS_1_256 & T2_SOURCE_INT, 1024-1); // 28.8kHz/256=112.5Hz carrier PWM // ----------------------------------------------------------------------------------------------------------------- OpenOC2(OC_IDLE_CON & OC_TIMER2_SRC & OC_PWM_FAULT_PIN_DISABLE, 0, 0); // enable interrupt DISICNT = 0x0000; MaxSpeed=700; // 最高速度は700に設定しました。 // 100%Dutyは1023(10bitに落としてる為)ですが、 // 1023では早すぎるので上限(最高速度)を設定しています。 // この数値を変えると最高速が変更されます。(1023が最大値) TeisokuTimer=0; // 定速走行時間はゼロ PwmData=0; // 最初は停止状態から Kagen=1; // 加速します。 // main loop while(1){ _RB5=~_RB5; // CPUクロックの確認用。 if ( AT_ML==1) { // 手動モードならば Dir_Cmd=Dir_SW; // 正転・逆転チェック } } }