動作テスト
速度一定で動かすサンプル
回路
Arduinoコード
//ピン番号
/*-----モータ-----*/
#define MOTORA 7
#define MOTORB 10
#define MOTORP 11
/*-----エンコーダ-----*/
#define PINENCA 2
#define PINENCB 4
//プロトタイプ宣言
void Pid_calc();
void EncCount();
//変数定義
/*-----エンコーダ-----*/
volatile int pulses;
volatile bool currDir;
unsigned char pinENCA;
unsigned char pinENCB;
/*-----目標設定-----*/
float target_vel = 0.10; // 目標速度
/*----エンコーダ----*/
int encValue; // エンコーダ値
int oldencValue; // 直前のエンコーダ値
/*-----PID-----*/
// 12 V時
float pid = 0.0; // T = Kp * e + Kd * e'+ Ki * ∫edt
float kp = 220; // P制御の係数
float ki = 0; // I制御の係数
float kd = 0; // D制御の係数
float f = 220;
float prevP;
unsigned long oldtime = 0;
unsigned long now = 0;
float all_time = 0;
/*-----モータ-----*/
int motorPWM = 0;
const int maxPWM = 255; // モータトルク最高
const int minPWM = 0; // モータトルク最低
const int EPR = 4700; // モータ一回転あたりのエンコーダ値
const float r = 0.015;
const float CM = 2*r*3.1415; // 円周
void Pid_calc() {
encValue = pulses;
//Serial.println(encValue);
int diffencValue = encValue - oldencValue;
oldencValue = encValue;
now = micros();
float dt =((float)(now - oldtime))/1000000.0;
all_time += dt;
/*---PIDによるモータ制御---*/
float P,I,D;
float v = ((float)diffencValue/(float)EPR*CM)/dt;
P = target_vel - v; // 比例項 目標速度-現在の速度
I += P; // 積分項 比例項の総和
D = (P - prevP)/ dt; // 微分項 エンコーダ値-直前のエンコーダ値=角速度
pid = kp * P + ki * I + kd * D;
prevP = P;
if(v != 0) Serial.println(v,4);
int motorSpeed = 0;
motorSpeed = f*target_vel;
motorSpeed += (int)pid;
// PWM制限
motorPWM = constrain(abs(motorSpeed), minPWM, maxPWM);
oldtime = now;
}
// エンコーダーの処理
void EncCount() { // A相変化時に処理
//currDir=!(digitalRead(PINENCA)^digitalRead(PINENCB));
currDir = !(((PIND >> PINENCA) & 0b00000001) ^ ((PIND >> PINENCB) & 0b00000001));
currDir == HIGH ? ++pulses : --pulses;
}
void setup() {
TCCR2B = TCCR2B & B11111000 | B00000001; //3,11番pinのpwmを高周波化
pinMode (MOTORA, OUTPUT);
pinMode (MOTORB, OUTPUT);
pinMode (MOTORP, OUTPUT);
pinMode(PINENCA, INPUT);
pinMode(PINENCB, INPUT);
Serial.begin(9600);
attachInterrupt(PINENCA - 2, EncCount, CHANGE);
}
void loop() {
if(all_time > 1){
target_vel *= -1;
all_time = 0.0;
}
Pid_calc();
// モータ回転
//motorPWM = 30;
analogWrite(MOTORP, motorPWM);
if (target_vel >= 0)
{ // 正転
digitalWrite(MOTORB, HIGH);
digitalWrite(MOTORA, LOW);
}
else
{ // 逆転
digitalWrite(MOTORA, HIGH);
digitalWrite(MOTORB, LOW);
}
}