/***************************************************
Stepper2.ino
Timer1コンペアマッチAの割り込みでステッピングモータドライバへ送信するパルスを生成する。
割り込み周期を変えることで、ステッピングモータの速度を変更する。
loop関数のswitch文で加速、定速を制御している。
****************************************************/
const byte cw_ccw_pin = 8;
const byte steps_pin = 9; //9,10pinでなければtimer1が使えない?
const byte switch_pin = 7; //タクトスイッチ接続ピン
byte acc_stat = 0; //加減速制御用変数
bool motor_running = false; // モータが動作中かを判定するフラグ
bool switch_state = false; // スイッチの現在の状態
bool last_switch_state = false; // スイッチの前回の状態
unsigned short loop_cnt; //loop関数カウント用変数
const short loop_delay = 50; //loop関数周期設定変数
short vel_pwtime; //速度周期指令変数
//ocr1aに代入する 16bitカウンタなので0-65535の範囲で指定
unsigned short vel0 = 1000; //初期速度
unsigned short velmax = 100; //最高速度でのパルス周期を設定(ステッピングモータによって変える必要がある)
const float gain = 0.05; //加速時のゲイン 小さいほどゆっくり加速
/***************************************************
ISR(TIMER1_COMPA_vect)
Timer1コンペアマッチAの割り込み関数
OCR1A の 値が小さければ割り込み周期が短く、大きいと周期は長い
Timer1は16bitタイマなのでOCR1Aの最大値は65535
この関数内でステッピングモータドライバへ送信するパルスを生成する
****************************************************/
ISR(TIMER1_COMPA_vect) //timer1がOCR1Aに到達したときに呼び出される
{
static bool state = false; //state 静的変数に設定 初期値を0 2回目以降は =falseは無視される?
state = !state; // toggle highとlowを切り替える !~は~を反転する
digitalWrite(steps_pin, state ? HIGH : LOW); //パルス入力 条件式 ? 真の時の処理:偽の時の処理
}
void setup() {
pinMode(cw_ccw_pin, OUTPUT);
pinMode(steps_pin, OUTPUT);
pinMode(switch_pin, INPUT_PULLUP); // スイッチピンをプルアップ抵抗付きで入力設定
digitalWrite(cw_ccw_pin, HIGH);
Serial.begin(9600);
vel_pwtime = 0; //vel0 / (1 + (loop_cnt * gain)); 初期速度 vel0でもよいが、滑らかにするため
loop_cnt = 0;
// set up Timer 1
TCCR1A = 0; // モード設定 :通常モード(ピン出力無効化)
TCCR1B = 0; // 初期状態で停止させるため loop内でモードを設定する
TIMSK1 = bit (OCIE1A); // 割り込み設定:コンペアマッチAで割り込み
}
void loop() {
//unsigned long start_time = micros(); // 処理開始時刻 処理速度測定用
switch_state = !digitalRead(switch_pin); // プルアップのため、LOWで未押下、HIGHで押下
// スイッチが押されたときのみ動作を切り替え
if (switch_state && !last_switch_state) {
motor_running = !motor_running; // モータの動作状態をトグル
if (!motor_running) {
TCCR1B = 0; // モータ停止: タイマ停止
acc_stat = 0; // 加速制御状態をリセット
vel_pwtime = 0; // 速度を初期値に戻す
loop_cnt = 0;
}
}
last_switch_state = switch_state; // スイッチ状態を更新
if (motor_running) {
loop_cnt++;
switch (acc_stat) {
/*case0:加速フェーズ*/
case 0:
TCCR1B = bit(WGM12) | bit(CS11); // CTC1設定 + クロック周期/8 (スケーラ8)
vel_pwtime = vel0 / ((loop_cnt * gain) + 1);
if (vel_pwtime <= velmax) {
loop_cnt = 0;
acc_stat = 1;
}
break;
//case1:最高速度保持フェーズ
case 1:
vel_pwtime = velmax;
break;
}
OCR1A = vel_pwtime; //タイマ割り込み周期を設定 TCN1(カウンタ)がこの値(ocr1a)と一致するとリセット
//ocr1aは16bitカウンタなので0-65535の範囲で指定
}
Serial.print(vel_pwtime); //指令速度をPC表示
Serial.print("\r\n"); //キャリッジリターン+改行
Serial.print("Motor Running: ");
Serial.print(motor_running ? "YES" : "NO");
// unsigned long end_time = micros(); // 処理終了時刻
// Serial.print("処理時間 (μs): ");
// Serial.println(end_time - start_time);
delay(loop_delay); //loop関数の処理周期を規定
}