通过电机编码器AB相输出确定电机转向
AB相输出相差90度,即当A相"正跳变"时如果B相是高电平那么是"正转",反之是"反转"
图片:
正转
反转
#include <TimerOne.h>
#define D_Left_PIN 7
#define D_Right_PIN 8
#define IN1 22
#define IN2 23
#define IN3 24
#define IN4 25
#define ENA 5
#define ENB 13
#define FIREPIN 9
#define Kp 0.5
#define Ki 0.5
#define Kd 0.0 #define MOTOR_GO_FORWARD {STOP=0; digitalWrite(IN1,LOW);digitalWrite(IN2,HIGH);digitalWrite(IN3,LOW);digitalWrite(IN4,HIGH);}
#define MOTOR_GO_BACK {STOP=0; digitalWrite(IN1,HIGH);digitalWrite(IN2,LOW);digitalWrite(IN3,HIGH);digitalWrite(IN4,LOW);}
#define MOTOR_GO_RIGHT {STOP=0; digitalWrite(IN1,HIGH);digitalWrite(IN2,LOW);digitalWrite(IN3,LOW);digitalWrite(IN4,HIGH);}
#define MOTOR_GO_LEFT {STOP=0; digitalWrite(IN1,LOW);digitalWrite(IN2,HIGH);digitalWrite(IN3,HIGH);digitalWrite(IN4,LOW);}
#define MOTOR_GO_STOP {STOP=1; digitalWrite(IN1,LOW);digitalWrite(IN2,LOW);digitalWrite(IN3,LOW);digitalWrite(IN4,LOW);} int Left_Speed[]={,,,,,,,,,};//左侧速度档位
int Right_Speed[]={,,,,,,,,,};//右侧速度档位 int Left_Speed_Hold=;//定义左侧速度变量
int Right_Speed_Hold=;//定义右侧速度变量 byte Fireing=;
long FireStopTime=;
unsigned long lastSendTime=;
unsigned long lastReceiveTime=;
byte RecCache[];
volatile int CacheIndex=; byte STOP=;
//=============================PID Args===========================
float left_LastError=0.0; // Error[-1]
float left_SumError=0.0; // Sums of Errors float right_LastError=0.0; // Error[-1]
float right_SumError=0.0; // Sums of Errors int flag=; //定义定时器中断标志,用于判断是否发生中断 long counter_val_right[] = {,}; //定义数组,用于存放外部中断计数值
byte CurCnt_right = ; //定义当前计数器标志,用于判断当前正在计数的数组
byte Direction_right=;
int rightSpeed=;
float rightPWM=0.0; long counter_val_left[] = {,}; //定义数组,用于存放外部中断计数值
byte CurCnt_left = ; //定义当前计数器标志,用于判断当前正在计数的数组
byte Direction_left=;
int leftSpeed = ;
float leftPWM=0.0;
unsigned long lastPrintTime=;
//========================End PID========================= void setup() { Serial.begin();//初始化波特率为115200
initWifi();
initIO();
setCache(,); attachInterrupt(,counter_left,RISING);
attachInterrupt(,counter_right, RISING);//设置中断方式为上升沿 Timer1.initialize();// 设置定时器中断时间,单位微秒,此处为1秒
Timer1.attachInterrupt( timerIsr ); // 打开定时器中断
interrupts(); //打开外部中断
}
void initIO(){
pinMode(D_Left_PIN,INPUT);
pinMode(D_Right_PIN,INPUT);
pinMode(IN1,OUTPUT);
pinMode(IN2,OUTPUT);
pinMode(IN3,OUTPUT);
pinMode(IN4,OUTPUT);
pinMode(ENA,OUTPUT);
pinMode(ENB,OUTPUT);
pinMode(FIREPIN,OUTPUT);
digitalWrite(IN1,LOW);
digitalWrite(IN2,LOW);
digitalWrite(IN3,LOW);
digitalWrite(IN4,LOW); digitalWrite(FIREPIN,LOW); }
void loop()
{
handleTXR();
checkStopFire();
speedControl(); } void setSpeed(){ float leftP=0.0,rightP=0.0,leftD=0.0,rightD=0.0; // 比例常数 Proportional Const
leftP=(Left_Speed[Left_Speed_Hold]- leftSpeed);
rightP=(Right_Speed[Right_Speed_Hold] - rightSpeed); //积分常数 Integral Const
left_SumError +=leftP;
right_SumError+=rightP; //微分常数 Derivative Const
// leftD=leftP-left_LastError;
// rightD=rightP-right_LastError;
// left_LastError=leftD;
// right_LastError=rightD;
// leftPWM=(leftP * Kp) + (left_SumError * Ki) +(leftD * Kd);
// rightPWM=((rightP) * Kp) + (right_SumError * Ki) +(rightD * Kd) ; leftPWM=(leftP * Kp) + (left_SumError * Ki) ;
rightPWM=((rightP) * Kp) + (right_SumError * Ki) ; if(leftPWM>)leftPWM=;
if(leftPWM<)leftPWM=; if(rightPWM>)rightPWM=;
if(rightPWM<)rightPWM=; analogWrite(ENA,rightPWM);
analogWrite(ENB,leftPWM);
} void speedControl(){ if(flag==) //判断是否发生定时器中断,即定时时间是否到达
{
flag=; //清除定时器中断标志位
if((CurCnt_left&0x01) == ) //当前使用的是偶数计数器,则上次频率值存放在第二个元素中
{
leftSpeed =counter_val_left[]; //读取数组第二个元素中的数值
counter_val_left[]=; //读完清除原来的数值,以便下次使用
}
else //当前使用的是奇数计数器,则上次频率值存放在第一个元素中
{
leftSpeed =counter_val_left[]; //读取数组第二个元素中的数值
counter_val_left[]=; //读完清除原来的数值,以便下次使用
} if((CurCnt_right&0x01) == ) //当前使用的是偶数计数器,则上次频率值存放在第二个元素中
{
rightSpeed =counter_val_right[]; //读取数组第二个元素中的数值
counter_val_right[]=; //读完清除原来的数值,以便下次使用
}
else //当前使用的是奇数计数器,则上次频率值存放在第一个元素中
{
rightSpeed =counter_val_right[]; //读取数组第二个元素中的数值
counter_val_right[]=; //读完清除原来的数值,以便下次使用
} if(!STOP) setSpeed(); if((millis()-lastPrintTime)>){
Serial.print("L:"); //发送帧头大写S
Serial.print( leftSpeed); //发送频率数据,并回车换行
Serial.print(",");
Serial.print(Direction_left);
Serial.print(",R:");
Serial.print(rightSpeed);
Serial.print(",");
Serial.print(Direction_right);
Serial.println("");
Serial.println(leftPWM);
Serial.println(rightPWM);
lastPrintTime=millis();
}
}
}
//外部中断处理函数 void counter_left(){
counter_val_left[CurCnt_left & 0x01] +=;
Direction_left=digitalRead(D_Left_PIN);
} void counter_right()
{
//通过当前计数器来实现对外部中断计数值存储的切换
counter_val_right[CurCnt_right& 0x01] += ; //发生一次中断则加1
Direction_right=digitalRead(D_Right_PIN);
} //定时器中断处理函数
void timerIsr()
{
flag=; //置位定时器中断标志位
CurCnt_right++; //当前计数器的值加1,实现另一个计数值切换
CurCnt_left++;
} //===================End PID ===============
void initWifi(){
Serial2.begin(); delayAndRead();
Serial2.println("AT+CIOBAUD=38400");
delayAndRead();
Serial2.println("AT+RST");
delayAndRead();
Serial2.begin();
Serial2.println("AT+CIPMUX=1");
delayAndRead();
Serial2.println("AT+CIPSERVER=1");
delayAndRead();
Serial2.println("AT+CIPSTO=60");
delayAndRead(); } void fire(long fireDelay){
if(Fireing==)return;
digitalWrite(FIREPIN,HIGH);
Fireing=;
FireStopTime=millis() + fireDelay;
Serial.println(FIREPIN);
Serial.println("fireDelay" + (String)fireDelay);
Serial.println(FireStopTime);
}
void checkStopFire(){
//check stop fire
if(Fireing== && (FireStopTime <=millis())){
Fireing=;
digitalWrite(FIREPIN,LOW);
}
} void reply(bool isOk,String cmd,String msg){
String rStr="";
if(isOk){
rStr="$FOK-" + cmd +":" +msg +"$E";
Serial2.println("AT+CIPSEND=0," + (String)rStr.length());
delay();
Serial2.println(rStr);
}else{
rStr="$FEE-" + cmd +":" +msg +"$E";
Serial2.println("AT+CIPSEND=0," + (String)rStr.length());
delay();
Serial2.println(rStr); } } void replyBytes(bool isOk,String cmd,byte msg[],int msgLen){
String rStr="";
int sendLen=;
if(isOk){
rStr="$FOK-" + cmd +":" ;
sendLen= rStr.length() + msgLen +; //2 is "$E"
Serial2.println("AT+CIPSEND=0," + (String)sendLen);
delay();
Serial2.print(rStr);
for(int i=;i<msgLen;i++){
Serial2.write(msg[i]);
}
Serial2.println("$E");
}else{
rStr="$FEE-" + cmd +":" ;
sendLen= rStr.length() + msgLen +; //2 is "$E"
Serial2.println("AT+CIPSEND=0," + (String)sendLen);
delay();
Serial2.print(rStr);
for(int i=;i<msgLen;i++){
Serial2.write(msg[i]);
}
Serial2.println("$E");
} } void cls(){
while(Serial2.available()){
Serial2.read();
}
} void delayAndRead(int waitTime){
delay(waitTime);
while(Serial2.available()){
Serial.write(Serial2.read());
}
} void handleTXR(){ while(Serial2.available()){
byte c=(byte) Serial2.read();
RecCache[CacheIndex++]=c; }
if(CacheIndex>){
CacheIndex=;
setCache(,);
Serial.println("Cut");
} int bIndex=bIndexOf("$F",);
if(bIndex>=){
int eIndex=bIndexOf("$E",bIndex);
if(eIndex>bIndex){
//Extra Data
int dataLen= eIndex - (bIndex +);
byte data[dataLen];
for(int i=;i<dataLen;i++){
data[i]= RecCache[bIndex+ +i] ; } for(int w=(eIndex +);w<CacheIndex && w<;w++){
RecCache[w-(eIndex + )]=RecCache[w];
}
CacheIndex = CacheIndex - (eIndex +);
setCache(CacheIndex,); lastReceiveTime=millis();
handleCmd(data,dataLen); }
} if(CacheIndex>){
CacheIndex=;
setCache(,);
} } void setCache(int start,int endIndex){
for(int i=start;i<endIndex;i++){
RecCache[i]=;
}
}
boolean bStartsWith(byte data[],int len, String fStr){
int fLen=fStr.length() ;
byte fBytes[fLen + ];
fStr.getBytes(fBytes,fLen+); if(len<=)return false;
if(len<fLen)return false;
byte flag=;
for(int j=;j<fLen;j++){
if(fBytes[j]!=data[j])
{
flag=;
break;
} }
if(flag) return true; return false;
} int bIndexOf(String fStr,int start){
int fLen=fStr.length() ;
byte fBytes[fLen + ];
fStr.getBytes(fBytes,fLen+); for(int i=start;i<(CacheIndex + -fLen);i++){ if(RecCache[i]==fBytes[])
{
byte flag=;
for(int j=;j<fLen;j++){
if(fBytes[j]!=RecCache[i+j])
{
flag=;
break;
}
}
if(flag)return i;
}
}
return -;
} void handleCmd(byte data[], int len){ if(bStartsWith(data,len,"HB:")){
hbCmd();
}else if(bStartsWith(data,len,"F:")){
fireCmd(data,len);
}else if(bStartsWith(data,len,"C:")){
controlCmd(data,len);
}
} void hbCmd(){
byte bs[];
unsigned long mlis=millis();
long2byte(mlis,bs);
Serial.println(mlis);
replyBytes(true,"HB",bs,);
} void fireCmd(byte data[], int len){ byte duration=data[];
if(duration>) duration=;
if(duration<=)duration=; long longDuration= duration * ;
fire(longDuration);
reply(true,"F","");
} void controlCmd(byte data[], int len){
byte bs[]={,};
bs[]=data[];bs[]=data[];
byte isMatch=; if(data[]==0x01 && data[]==0x01){
//Forward
isMatch=;
MOTOR_GO_FORWARD;
}else if(data[]==0x01 && data[]==0x02){
//Back
isMatch=;
MOTOR_GO_BACK;
}else if(data[]==0x01 && data[]==0x03){
//Turn Left
isMatch=;
MOTOR_GO_LEFT;
}else if(data[]==0x01 && data[]==0x04){
//Turn Right
isMatch=;
MOTOR_GO_RIGHT;
}else if(data[]==0x01 && data[]==0x05){
//Stop
isMatch=;
MOTOR_GO_STOP;
Serial.println("Stop");
}else if(data[]==0x02 && data[]==0x01){
//Left Speed
isMatch=;
byte ena=data[];
if(ena>= && ena<=){
Left_Speed_Hold=ena;
} }else if(data[]==0x02 && data[]==0x02){
//Right Speed
isMatch=;
byte enb=data[];
if(enb>= && enb<=){
Right_Speed_Hold=enb;
} }
if(isMatch==)replyBytes(true,"C",bs,); } void long2byte(unsigned long res,byte targets[] ) {
targets[] = (byte) (res & 0xff);// 鏈�浣庝綅
targets[] = (byte) ((res >> ) & 0xff);// 娆′綆浣�
targets[] = (byte) ((res >> ) & 0xff);// 娆¢珮浣�
targets[] = (byte) (res >> );// 鏈�楂樹綅,鏃犵鍙峰彸绉汇�� } unsigned long bytes2long(byte buf[]) {
unsigned long firstByte = ;
unsigned long secondByte = ;
unsigned long thirdByte = ;
unsigned long fourthByte = ;
int index = ;
firstByte = (0x000000FFU & ( buf[index+]));
secondByte = (0x000000FFU & ( buf[index + ]));
thirdByte = (0x000000FFU & ( buf[index + ]));
fourthByte = (0x000000FFU & ( buf[index ]));
index = index + ;
return ((unsigned long) (firstByte << | secondByte << | thirdByte << | fourthByte)) & 0xFFFFFFFFUL;
}
通过电机编码器AB相输出确定电机转向的更多相关文章
- 电机AB相编码器测速
控制任务 检测编码器的脉冲并测速 电路设计 图1 直流电机带减速器和编码器 图2 编码器接线定义 编码器接线定义如下 M1:电机电源接口,绿色的 GND:编码器电源负极输入口,橙色的 C1:编码器A ...
- STM32—TIMx实现编码器四倍频
文章目录 一.储备知识 二.TIMx的编码器模式介绍 1.计数边沿设置 2.选择极性和使能 3.使能 4.计数方向 三.代码部分 一.储备知识 通过STM32的定时器编码器接口模式对编码器进行四倍频, ...
- 玩转X-CTR100 l STM32F4 l 电机正交编码器
我造轮子,你造车,创客一起造起来!塔克创新资讯[塔克社区 www.xtark.cn ][塔克博客 www.cnblogs.com/xtark/ ] 本文介绍X-CTR100控制器的电机正交编码器,X- ...
- 实现硬件PWM控制电机旋转和通过编码器计算所转圈数的简单例程
该例程所用的硬件设备: 直流电机驱动模块YYH-LWZ: H桥 大功率 正反转 刹车 PWM 调速 5/12/24V 12V直流减速电机JGB37-520B:ASLONG JGB37-520B编码器减 ...
- 伺服驱动器UVW电机电源线相序错误
我们有必要先了解此讨论的前提:编码器初始安装相位正确.伺服驱动器将全然"採信"电机编码器的初始安装相位所表征的电机电角度相位,无需在伺服电机 的UVW动力线接线连接后进行额外 ...
- 【一】工程配置与电机控制part1
前言 学校发的无刷电机: 我们准备的有刷电机: 带霍尔编码器! 电机参数: 名称:驰名电机(直流减速电机) 型号:JGA25-370 电压:12V 转数:1360r/min 做云台,核心是使用PID控 ...
- YASKAWA电机控制(1)---接线
实验室所购置电机型号为YASKAWA-AC SERVO MOTOR SGM7J-01AFC6S型,配SGD7S-R90A00A002伺服控制器.电机和控制器的操作说明书由安川中文官网安川电机资料提供. ...
- stm32电机控制之控制两路直流电机
小车使用的电机是12v供电的直流电机,带编码器反馈,这样就可以采用闭环速度控制,这里电机使用PWM驱动,速度控制框图如下: 由以上框图可知,STM32通过定时器模块输出PWM波来控制两个直流电机的转动 ...
- stm32电机控制之控制两路直流电机!看完你会了吗
手头上有一个差分驱动的小车,使用两个直流电机驱动,要实现小车的在给定速度下运动,完成直线行驶,转向,加速,刹车等复杂运动. 使用的电机是12v供电的直流电机,带编码器反馈,这样就可以采用闭环速度控制, ...
随机推荐
- 5 python 内置类
1.实例属性和类属性 给实例绑定属性的方法是通过实例变量,或者通过self变量: class Chinese: def __init__(self,name,sex,age): self.name = ...
- TEXT 3 Food firms and fat-fighters
TEXT 3 Food firms and fat-fighters 食品公司与减肥斗士 Feb 9th 2006 From The Economist Global Agenda Five lead ...
- 关于Git的礼节
(这里的内容本来是<怎样尊重一个程序员>的一小节,但由于Git的使用引起了很普遍的不尊重程序员的现象,现在特别将这一节提出来单独成文.) Git是现在最流行的代码版本控制工具.用外行话说, ...
- ios 真机测试与发布详细流程,基于最新的开发者网站,ios7,xcode5(有截图的哦)[[[第一部分真机测试]]]
转载于:http://blog.csdn.net/lv_ruanruan/article/details/14446597 真机测试及发布详细流程,最新版 第一次一个人搞一个项目,我们老大规定,一个周 ...
- delphi TEdit透明
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...
- Hibernate迫切左外连接和迫切内连接
•迫切左外连接: •LEFT JOIN FETCH 关键字表示迫切左外连接检索策略. –list() 方法返回的集合中存放实体对象的引用, 每个 Department 对象关联的 Employee ...
- -moz 火狐 -msIE -webkit[chrome safari]
-moz代表firefox浏览器私有属性 -ms代表IE浏览器私有属性 -webkit代表chrome.safari私有属性
- Genetics in geographically structured populations: defining, estimating and interpreting FST
摘要:Wright’s F‑statistics, and especially FST, provide important insights into the evolutionary proce ...
- referer null
Referer表示超链接源的URL!你想看到实验效果,要从a-->(能过<a href="b.jsp")b页面,然后在B里可以取得Refere参数! String ur ...
- python3 django连接mysql,同步表结构
第一步:安装PyMySQ代替MySQLdb pip3 install PyMySQL 然后在工程目录的__init__.py中填写下面两句话 import pymysql pymysql.inst ...