用 Arduino Nano作为控制板(16MHZ),红外U型传感器,20线编码盘,利用中断触发计数,原理图如下,遇到的问题是,电机正转的时候,每隔200ms,采样计数差为16或17个(正常),反转的时候,每隔200ms/,采样计数为12,13,14,15,16,17(不正常,波动比较大),想实现的目标是行程控制,比方说,电机第一次正转走A个计数,存入EEPROM,反转的时候,从EEPROM中读出A,当中断计数触发达到A的时候,电机停止,由于是利用继电器控制,停止的时候,有惯性误差(暂且忽略不计),但是,利用这种U型传感器来说,会有失步的现象,不知是程序还未完善?还是硬件电路受到干扰?请大神们支招!#include <IRremote.h>
#include <EEPROM.h>
union data //EEPROM 数据类型 字节拆分 转换
{
long a;
byte b[4];
};
data col;
int addr = 0;
int addr1 = 9;
int RECV_PIN = 12; //红外脚
int Frelay=11; // 继电器控制电机 启/停
int Drelay=10; // 继电器控制电机 正/反转 通过H桥改变电源正/反
unsigned long time1 = 0, time2 = 0 ,time3 = 0 ,time4 = 0 ,old_time4 = 0; // 时间标记
unsigned long S=2; //空隙距离
long F1; //行程计数
long F3; //行程计数
long num;
long num1; //每100ms 计数
long num2; //每200ms 计数
int count=0; //计数
int Start=0; //开启计数变量
int Pause=0; //暂停按键变量
int Change=0; //100ms 200ms交换变量
int d=0; //F1存入EEPROM变量
int e=0; //开启行程比较变量
int f=0; //行程设置自动返回变量
int g=0; //行程比较变量
int Direction=0; //方向变量
int Function=0;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
Serial.begin(9600);
pinMode(Frelay,OUTPUT);
pinMode(Drelay,OUTPUT);
pinMode(2,INPUT_PULLUP);
attachInterrupt(0,Count,CHANGE);
irrecv.enableIRIn();
}
void loop()
{
Infrared(); //红外遥控
SpeedCompare(); //速度比较
}
void Infrared()
{
if (irrecv.decode(&results))
{
Serial.println(results.value, HEX);
if(Direction==0)
{
if(results.value==0xFFA25D) //正转按钮
{
for(addr ; addr < 4 ; addr++) //从EEPROM中读出数值 并赋值与F3
{
col.b[addr]=EEPROM.read(addr);
delay(3);
}
F3=col.a;
digitalWrite(Frelay,1);
Start=1;
e=1;
Serial.print("F3=");
Serial.println(F3);
}
if(g==1) //中途返回按键
{
if(results.value==0xFF629D)
{
count=0;
num=0;
num1=0;
num2=0;
digitalWrite(Frelay,1);
digitalWrite(Drelay,1);
Start=1;
e=1;
}
}
}
if(Direction==1)
{
if(results.value==0xFF629D) //反转按钮
{
for(addr ; addr < 4 ; addr++) //从EEPROM中读出数值 并赋值与F3
{
col.b[addr]=EEPROM.read(addr);
delay(3);
}
F3=col.a;
digitalWrite(Frelay,1);
digitalWrite(Drelay,1);
Start=1;
e=1;
Serial.print("F3=");
Serial.println(F3);
}
if(g==1) //中途返回
{
if(results.value==0xFFA25D)
{
count=0;
num=0;
num1=0;
num2=0;
digitalWrite(Frelay,1);
Start=1;
e=1;
}
}
}
if(results.value==0xFFC23D) //暂停键
{
if(Pause==0)
{
g=1;
digitalWrite(Frelay,0);
Start=0;
F1=count;
Pause=1;
Serial.print("F1=");
Serial.println(F1);
}else{
digitalWrite(Frelay,1);
Start=1;
Pause=0;
g=0;
}
}
if(results.value==0xFF906F) //行程设置键
{
Function = EEPROM.read(addr1);
delay(3);
if(Function==0)
{
Function=1;
EEPROM.write(addr1, Function);
delay(3);
digitalWrite(Frelay,1);
Start=1;
f=1;
Serial.print("Function=");
Serial.println(Function);
}else{
for(int i=0; i<512 ; i++) //清除EEPROM内容
{
EEPROM.write(i, 0);
delay(3);
}
for(addr1; addr1<10 ; addr1++) //清除EEPROM内容
{
EEPROM.write(addr1, 0);
delay(3);
}
Serial.print("col.a=");
Serial.println(col.a);
Serial.print("Function=");
Serial.println(Function);
F3=0;
}
}
irrecv.resume();
}
}
void Count()
{
if(Start==1)
{
if((millis()-time3)>5) //为了不计入噪音干扰脉冲,
{ //当2次中断之间的时间大于5ms时,计一次有效计数
count += 1; //当编码器码盘的OUTA脉冲信号下跳沿每中断一次,编码器码盘计数加一
Serial.print("count=");
Serial.println(count);
DirectionCompare(); //行程比较控制停止
}
time3=millis();
}
}
void SpeedCompare()
{
if(Start==1)
{
if ((millis()-time1>=100) && Change==0)
{
time1=millis();
num1=count;
Change=1;
}
if ((millis()-time2>=200) && Change==1)
{
time2=millis();
num2=count;
num=num2-num1;
Serial.print("num=");
Serial.println(num);
Change=0;
}
if(num==0 && count>10)
{
digitalWrite(Frelay,0);
Start=0;
if(d==1)
{
col.a=count;
for(addr ; addr < 4 ; addr++) //将count写入EEPROM
{
EEPROM.write(addr, col.b[addr]);
delay(3);
}
Serial.println("1111111111");
}
d=0;
count=0;
if(f==1)
{ //行程设置 闭合后 自动返回
//delay(2000);
digitalWrite(Drelay,1);
digitalWrite(Frelay,1);
Start=1;
d=1;
f=0;
Serial.println("222222222");
}
}
}
}
void DirectionCompare()
{
if(F3-S<count && e==1 && g==0) //全程 行程比较
{
digitalWrite(Frelay,0);
digitalWrite(Drelay,0);
Start=0;
count=0;
e=0;
if(Direction==0)
{
Direction=1;
}else{
Direction=0;
}
}
if(F1-1<count && e==1 && g==1) //中途返回 行程比较
{
digitalWrite(Frelay,0);
digitalWrite(Drelay,0);
Start=0;
count=0;
e=0;
g=0;
}
}
|