PICで鉄道模型をPWM高精度制御するやつを作ってる

最近、ぼちぼちPICやってます。

最初は全部レジスタ直打ちで全部の機能を使おうとしていたのですが、あまりにも非効率なので、一旦諦めてMicrochipがMPLABXに付属させているMCCというコードジェネレータを使うことにしました。コードジェネレータと言っても、GUIで設定するとハードウェアを使う機能の関数が用意されるだけで、その関数をどう使うかは自分次第です。

なれるとなかなか便利な代物で、例えばPWM1_DutyCycleSet(100);とか書くだけでDuty比がセットできるようになったりするので、高度な制御をするときは必須かなと思いました。

今回は高周波PWM制御で鉄道模型を精密制御するものを作りました。被制御側(ハード、PIC)はこんな感じで良さそうですが、Pythonとかで制御するソフトウェアが未完成なので、まだシリアルから手動で叩く必要があります。

今回は書籍「C言語によるPICプログラミング大全」を参考にしました。基本から書いてありますが、いきなりレベルが吹っ飛びすぎて、下地がないと厳しいかもしれないです。MPLAB XとMCCの使い方については参考となる日本語資料が少ないので助かりました。

ハードについては、今回、唐突にPICがリセットされる問題が発生して解決に時間を要しました。結局、電源ラインにセラミックコンデンサを入れ忘れておりず、ノイズでリセットされていたことがわかりました。基本的なことなので、書籍などを参考にしなかったのが原因かもしれないです。まあ、気づけてよかったです。


#include "mcc_generated_files/mcc.h"
#include <stdio.h>
void move(unsigned char direction)
{
if (direction == 1) {
PWM1_DutyCycleSet(639);
PWM1_LoadBufferSet();
} else {
PWM2_DutyCycleSet(639);
PWM2_LoadBufferSet();
}
__delay_ms(10);
}
void main(void)
{
// initialize the device
SYSTEM_Initialize();
// Enable the Global Interrupts
INTERRUPT_GlobalInterruptEnable();
// Enable the Peripheral Interrupts
INTERRUPT_PeripheralInterruptEnable();
unsigned int level = 0;
unsigned int new_level = 0;
unsigned char direction = 1;
unsigned char got_char;
dir2_SetLow();
PWM1_Start();
PWM1_DutyCycleSet(0);
PWM1_LoadBufferSet();
printf("init\n\r");
while (1)
{
got_char = EUSART_Read();
// if (PIR1bits.RCIF) {
// got_char = RCREGbits.RCREG;
// }
if (got_char < '!'){
if (direction == 1) {
if (level) {
PWM1_DutyCycleSet(level * 3 / 4);
PWM1_LoadBufferSet();
__delay_ms(500);
}
PWM1_DutyCycleSet(0);
PWM1_LoadBufferSet();
PWM1_Stop();
__delay_ms(500);
dir2_SetHigh();
__delay_ms(200);
PWM2_Start();
PWM2_DutyCycleSet(level);
PWM2_LoadBufferSet();
printf("houten to 2\n\r");
direction = 2;
if (level) {
move(direction);
}
} else {
if (level) {
PWM2_DutyCycleSet(level * 3 / 4);
PWM2_LoadBufferSet();
__delay_ms(500);
}
__delay_ms(500);
PWM2_DutyCycleSet(0);
PWM2_LoadBufferSet();
PWM2_Stop();
dir2_SetLow();
__delay_ms(200);
PWM1_Start();
PWM1_DutyCycleSet(level);
PWM1_LoadBufferSet();
printf("houten to 1\n\r");
direction = 1;
if (level) {
move(direction);
}
}
} else if (got_char < '~') {
new_level = (got_char – '!') * 5;
printf("%d", new_level);
}
if (new_level > level) {
move(direction);
}
//ADC1_GetConversion(channel_AN11)
level = new_level;
if (direction == 1) {
PWM1_DutyCycleSet(level);
PWM1_LoadBufferSet();
} else {
PWM2_DutyCycleSet(level);
PWM2_LoadBufferSet();
}
__delay_ms(50);
}
}

カテゴリー: コンピュータ, 鉄道, 電気電子 パーマリンク

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中