找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 21984|回复: 7
收起左侧

arduino+L298N直流电机调速程序(注释很详细)

  [复制链接]
ID:489436 发表于 2019-3-12 19:17 | 显示全部楼层 |阅读模式
  1. //定义变量程序段
  2. //把小车左轮电机编码器码盘的OUTA信号连接到Arduino控制器的数字端口2,
  3. //数字端口2是Arduino的外部中断0的端口。
  4. #define PinA_left 2 //外部中断0
  5. #define PinB_left 8 //小车左车轮电机编码器码盘的OUTB信号连接到数字端口8
  6. //把小车右车轮电机编码器码盘的OUTA信号连接到Arduino控制器的数字端口3,
  7. //数字端口3是Arduino的外部中断1的端口。
  8. #define PinA_right 3 //外部中断1
  9. #define PinB_right 9 //小车右车轮电机编码器码盘的OUTB信号连接到数字端口9
  10. int E_left =5; //L298P直流电机驱动板的左轮电机使能端口连接到数字接口5
  11. int M_left =4; //L298P直流电机驱动板的左轮电机转向端口连接到数字接口4
  12. int E_right =6; //连接小车右轮电机的使能端口到数字接口6
  13. int M_right =7; //连接小车右轮电机的转向端口到数字接口7
  14. int val_right; //小车右轮电机的PWM功率值
  15. int val_start;//上位机控制字节,用于控制电机是否启动;
  16. int val_FB;   //上位机控制字节,用于控制电机是正转还是反转;
  17. int val_left;//上位机控制字节,用于提供给左轮电机PWM功率值。
  18. int count1 = 0;  //左轮编码器码盘脉冲计数值
  19. int count2= 0; //右轮编码器码盘脉冲计数值
  20. int rpm1 = 0;  //左轮电机每分钟(min)转速(r/min)
  21. int rpm2 = 0;  //右轮电机每分钟(min)转速(r/min)
  22. int rpm1_HIGH = 0;//左轮电机转速分解成高、低两个字节数据,以方便上传给PC机
  23. int rpm1_LOW = 0;
  24. int rpm2_HIGH = 0;//右轮电机转速分解成高、低两个字节数据
  25. int rpm2_LOW = 0;
  26. int flag;//设置小车行车状态,是前进、后退还是停止
  27. unsigned long time = 0, old_time = 0; // 时间标记
  28. unsigned long time1 = 0, time2 = 0; // 时间标记


  29. //初始化程序段
  30. void setup()
  31. {
  32.   Serial.begin(9600);    // 启动串口通信,波特率为9600b/s
  33.   pinMode(M_left, OUTPUT);   //L298P直流电机驱动板的控制端口设置为输出模式
  34.   pinMode(E_left, OUTPUT);
  35.   pinMode(M_right, OUTPUT);
  36.   pinMode(E_right, OUTPUT);
  37.   pinMode(PinA_left,INPUT); //伺服电机编码器的OUTA和OUTB信号端设置为输入模式
  38.   pinMode(PinB_left,INPUT);
  39.   pinMode(PinA_right,INPUT);
  40.   pinMode(PinB_right,INPUT);
  41.   //定义外部中断0和1的中断子程序Code(),中断触发为下跳沿触发
  42.   //当编码器码盘的OUTA脉冲信号发生下跳沿中断时,
  43.   //将自动调用执行中断子程序Code()。
  44.   attachInterrupt(0, Code1, FALLING);//小车左车轮电机的编码器脉冲中断函数
  45.   attachInterrupt(1, Code2, FALLING);//小车右车轮电机的编码器脉冲中断函数
  46. }


  47. //子程序程序段
  48. void advance()//小车前进
  49. {
  50.      digitalWrite(M_left,HIGH);
  51.      analogWrite(E_left,val_left);
  52.      digitalWrite(M_right,LOW);
  53.      analogWrite(E_right,val_right);
  54. }
  55. void back()//小车后退
  56. {
  57.      digitalWrite(M_left,LOW);
  58.      analogWrite(E_left,val_left);
  59.      digitalWrite(M_right,HIGH);
  60.      analogWrite(E_right,val_right);
  61. }
  62. void Stop()//小车停止
  63. {
  64.      digitalWrite(E_right, LOW);
  65.      digitalWrite(E_left, LOW);
  66. }
  67.   
  68. //主程序段
  69. void loop()
  70. {
  71.   if (Serial.available()>0) //如果Arduino控制器读缓冲区中存在上位机下达的字节
  72.   {
  73.       val_start= Serial.read(); //从读缓冲区中读取上位机的三个控制字节
  74.       delay(5);
  75.       val_FB = Serial.read();
  76.       delay(5);  
  77.       val_left= Serial.read();
  78.       delay(5);      
  79.      if(val_start==0x11)     //如果读出的第一个字节为小车启动标志字节0x11
  80.      {
  81.        if(val_FB ==0xAA)   //如果读出的第二个字节为小车前进标志字节0xAA
  82.        {
  83.          //读出的第三个字节为小车左车轮电机的PWM功率值,把它赋值给右车轮电机功率变量
  84.          val_right=val_left;
  85.          advance(); //小车前进
  86.          flag='a';   //设置小车前进标志字符     
  87.          count1 = 0; //恢复到编码器测速的初始状态
  88.          count2 = 0;
  89.          old_time=  millis();   
  90.        }
  91.        else if(val_FB ==0xBB) //如果读出的第二个字节为小车后退标志字节0xBB   
  92.        {
  93.          val_right=val_left;
  94.          back();  //小车后退
  95.          flag='b'; //设置小车后退标志字符      
  96.          count1 = 0; //恢复到编码器测速的初始状态
  97.          count2 = 0;
  98.          old_time=  millis();        
  99.        }
  100.      }
  101.       else if(val_start==0x22) //如果读出的第一个字节为小车停止标志字节0x22
  102.       {
  103.          Stop(); //小车停止
  104.          flag='s'; //设置小车停止标志字符         
  105.       }
  106.   }


  107.   
  108.   time = millis();//以毫秒为单位,计算当前时间
  109.   //计算出每一秒钟编码器码盘计得的脉冲数,
  110.   if(abs(time - old_time) >= 1000) // 如果计时时间已达1秒
  111.   {
  112.     detachInterrupt(0); // 关闭外部中断0
  113.     detachInterrupt(1); // 关闭外部中断1   
  114.      //把每一秒钟编码器码盘计得的脉冲数,换算为当前转速值
  115.      //转速单位是每分钟多少转,即r/min。这个编码器码盘为12个齿。
  116.     rpm1 =(float)count1*60/12;//小车左车轮电机转速
  117.     rpm2 =(float)count2*60/12; //小车右车轮电机转速
  118.     rpm1_HIGH=rpm1/256;//把转速值分解为高字节和低字节
  119.     rpm1_LOW=rpm1%256;
  120.     rpm2_HIGH=rpm2/256;
  121.     rpm2_LOW=rpm2%256;
  122.    //根据左右车轮转速差rpm1-rpm2,乘以比例因子0.4,获得比例调节后的右车轮电机PWM功率值
  123.     val_right=(float)val_right+(rpm1-rpm2)*0.4;
  124.     Serial.print(rpm1_HIGH,BYTE);//向上位计算机上传左车轮电机当前转速的高、低字节
  125.     Serial.print(rpm1_LOW,BYTE);
  126.     Serial.print(rpm2_HIGH,BYTE);//向上位计算机上传右车轮电机当前转速的高、低字节
  127.     Serial.print(rpm2_LOW,BYTE);
  128.     Serial.print(val_right,BYTE);// 向上位计算机上传PID调节后的右轮电机PWM功率值   
  129.     if(flag=='a') //根据刚刚调节后的小车电机PWM功率值,及时修正小车前进或者后退状态
  130.     advance();
  131.     if(flag=='b')
  132.     back();   
  133.    //恢复到编码器测速的初始状态
  134.     count1 = 0;   //把脉冲计数值清零,以便计算下一秒的脉冲计数
  135.     count2 = 0;
  136.     old_time=  millis();     // 记录每秒测速时的时间节点   
  137.     attachInterrupt(0, Code1,FALLING); // 重新开放外部中断0
  138.     attachInterrupt(1, Code2,FALLING); // 重新开放外部中断1
  139.   }
  140. }


  141. // 左侧车轮电机的编码器码盘计数中断子程序
  142. void Code1()//算编码器脉冲


  143. {  
  144.   //为了不计入噪音干扰脉冲,
  145.    //当2次中断之间的时间大于5ms时,计一次有效计数
  146.   if((millis()-time1)>5)
  147.   //当编码器码盘的OUTA脉冲信号下跳沿每中断一次,
  148.   count1 += 1; // 编码器码盘计数加一  
  149.   time1==millis();
  150. }
  151. // 右侧车轮电机的编码器码盘计数中断子程序
  152. void Code2()
  153. {  
  154.   if((millis()-time2)>5)
  155.   //当编码器码盘的OUTA脉冲信号下跳沿每中断一次,
  156.   count2 += 1; // 编码器码盘计数加一
  157.   time2==millis();  
  158. }

复制代码


回复

使用道具 举报

ID:1 发表于 2019-3-13 02:48 | 显示全部楼层
本帖需要重新编辑补全电路原理图,源码,详细说明与图片即可获得100+黑币(帖子下方有编辑按钮)
回复

使用道具 举报

ID:98249 发表于 2019-3-22 13:23 | 显示全部楼层
有用,正要做相关的应用,参考参考.感谢楼主
回复

使用道具 举报

ID:688391 发表于 2021-2-6 20:45 | 显示全部楼层
非常有用
回复

使用道具 举报

ID:932910 发表于 2021-11-12 22:06 | 显示全部楼层
    Serial.write(rpm1_HIGH);
    Serial.write(rpm1_LOW);
    Serial.write(rpm2_HIGH);
    Serial.write(rpm2_LOW);
    Serial.write(val_right);
1.0版本后没有BYTE这个关键字     130行到134行用这段替换可通过编译
回复

使用道具 举报

ID:985357 发表于 2021-11-27 18:43 | 显示全部楼层
谢谢大佬指点
回复

使用道具 举报

ID:1055770 发表于 2022-12-5 14:12 | 显示全部楼层
这不是L298P的代码吗?请问有无L298N的代码
回复

使用道具 举报

ID:138707 发表于 2023-7-29 17:51 | 显示全部楼层
谢谢大佬指点
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表