ARDUINO ,TB6612 ,MG310 电机,PID调速

 ARDUINO ,TB6612 ,MG310 电机,PID调速

#include <PID_v1.h>

int AIN1 = 9;
int AIN2 = 8;
int PWMA = 3;
int STBY = 10;

int motor_A = 21;  // 编码器连接的引脚
int motor_B = 20;  // 编码器连接的引脚
volatile int count = 0;  // 编码器计数

void count_A() {
     //单频计数实现
  //手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比
  /*if(digitalRead(motor_A) == HIGH){

    if(digitalRead(motor_B) == LOW){//A 高 B 低
      count++;  
    } else {//A 高 B 高
      count--;  
    }


  }*/

  //2倍频计数实现
  //手动旋转电机一圈,输出结果为 一圈脉冲数 * 减速比 * 2
  if(digitalRead(motor_A) == HIGH){

    if(digitalRead(motor_B) == HIGH){//A 高 B 高
      count++;  
    } else {//A 高 B 低
      count--;  
    }


  } else {

    if(digitalRead(motor_B) == LOW){//A 低 B 低
      count++;  
    } else {//A 低 B 高
      count--;  
    }  

  }

}

void count_B() {
    if(digitalRead(motor_B) == HIGH){

    if(digitalRead(motor_A) == LOW){//B 高 A 低
      count++;
    } else {//B 高 A 高
      count--;
    }


  } else {

    if(digitalRead(motor_A) == HIGH){//B 低 A 高
      count++;
    } else {//B 低 A 低
      count--;
    }

  }

}

int reducation = 20;  // 减速比
int pulse = 260;  // 编码器旋转一圈产生的脉冲数
int per_round = pulse * reducation * 4;  // 车轮旋转一圈产生的脉冲数
long start_time = millis();  // 一个计算周期的开始时刻,初始值为 millis()
long interval_time = 50;  // 一个计算周期 50ms
double current_vel;

// 获取当前转速的函数
void get_current_vel() {
    long right_now = millis();
    long past_time = right_now - start_time;
    if (past_time >= interval_time) {
        // 禁止中断
        noInterrupts();
        // 计算转速
        current_vel = (double)count / per_round / past_time * 1000 * 60;
        // 清零计数器
        count = 0;
        // 重置开始时间
        start_time = right_now;
        // 重启中断
        interrupts();

        Serial.println(current_vel);
    }
}

// 创建 PID 对象
// 1.当前转速 2.计算输出的pwm 3.目标转速 4.kp 5.ki 6.kd 7.当输入与目标值出现偏差时,向哪个方向控制
double pwm;  // 电机驱动的PWM值
double target = 40;
double kp = 1, ki = 3.0, kd = 0.1;
PID pid(&current_vel, &pwm, &target, kp, ki, kd, DIRECT);

// 速度更新函数
void update_vel() {
    // 获取当前速度
    get_current_vel();
    // 计算需要输出的PWM
    pid.Compute();
    // 激活电机驱动
    digitalWrite(STBY, HIGH);
    // 根据pwm的正负值设置电机转向和PWM
    if (pwm >= 0) {
        digitalWrite(AIN1, HIGH);
        digitalWrite(AIN2, LOW);
        analogWrite(PWMA, pwm);
    } else {
        digitalWrite(AIN1, LOW);
        digitalWrite(AIN2, HIGH);
        analogWrite(PWMA, -pwm); // 取pwm的绝对值
    }
}


void setup() {
    Serial.begin(57600);  // 设置波特率
    pinMode(motor_A, INPUT);
    pinMode(motor_B, INPUT);
    // 设置电机驱动引脚为输出
    pinMode(AIN1, OUTPUT);
    pinMode(AIN2, OUTPUT);
    pinMode(PWMA, OUTPUT);
    pinMode(STBY, OUTPUT);

    // 设置编码器中断
    attachInterrupt(digitalPinToInterrupt(motor_A), count_A, CHANGE);
    attachInterrupt(digitalPinToInterrupt(motor_B), count_B, CHANGE);

    pid.SetMode(AUTOMATIC);
}

void loop() {
    delay(10);
    update_vel();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悸尢

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值