更新了一下程序,加了一个计数器变量,arduino上电的时候,变量初始化为0,当调焦筒伸出时每个脉冲计数器+1,当计数值到达30000的时候,按键也不再发送脉冲让调焦筒伸出。收回的时候计数值每个脉冲递减1,当脉冲计数大于1000时,以2000HZ的速度收回,当计数小于1000时,开始以100HZ收回,计数值到达0时,按键不也不再发送脉冲。这样就可以保护机械部分,避免调焦筒伸出、收回的时候到达限位时继续让电机运转造成机械部件的损伤。由于使用了步进电机控制,所以完全可以用程序来保护,不用加什么限位开关之类的了。另外,30000的上限是按照我的电机调速以及调焦筒最大伸出算的,方法很简单,在调焦筒上画一条线,控制电机让调焦筒伸出到达线停止,此时查看一下用了多少个脉冲即可~
更新程序如下:
#include <Key.h>
#include <Keypad.h>
#include <TimerOne.h>
//define ena for all motors
#define ENA_PIN 8
//define motor pins
#define XDIR_PIN 5
#define YDIR_PIN 6
#define XSTEP_PIN 2
#define YSTEP_PIN 3
//define keypad rows and cols
#define ROWS 3
#define COLS 3
//define a keymap
unsigned char keys[ROWS][COLS] =
{
{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'}
};
//row->pin, col->pin
byte rowPins[ROWS] = {A3, 13, 12};
byte colPins[COLS] = {A2, A1, A0};
//register keymap and pins
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
//XPUL_STATE保存X电机驱动电平状态
volatile byte XPUL_STATE = LOW;
//X电机,Y电机开关
volatile byte XMOTOR_TOGGLE = LOW;
volatile byte YMOTOR_TOGGLE = LOW;
//电机使能开关
volatile byte ENA_TOGGLE = HIGH;
//Y电机状态,指示哪个键被长按
volatile unsigned char YMOTOR_STATE = 0;
//Y电机的累计脉冲数, 不受电机使能、Y电机开关置0,上电后初始化为0
volatile unsigned int YSTEP_CNT = 0;
void setup() {
//set pin mod
pinMode(ENA_PIN, OUTPUT);
pinMode(XDIR_PIN, OUTPUT);
pinMode(XSTEP_PIN, OUTPUT);
pinMode(YDIR_PIN, OUTPUT);
pinMode(YSTEP_PIN, OUTPUT);
//set pin value
digitalWrite(ENA_PIN, ENA_TOGGLE);
digitalWrite(XDIR_PIN, HIGH);
//设置timer1的频率为32HZ,则每31.25ms触发一次
Timer1.initialize(31250);
Timer1.attachInterrupt(timer1_ISR);
//set keypad listener
keypad.addEventListener(keypadEvent);
//set hold dealy
keypad.setHoldTime(500);
//set serail
Serial.begin(9600);
}
//timer1的触发频率为32HZ,也就是1秒触发32次高低电平转换,则1秒为16HZ的方波信号,600秒产生9600个周期
void timer1_ISR()
{
if (XMOTOR_TOGGLE == HIGH)
{
XPUL_STATE = !XPUL_STATE;
digitalWrite(XSTEP_PIN, XPUL_STATE);
}
}
void loop() {
//listern keypad
keypad.getKey();
//drive Y-MOTOR
switch (YMOTOR_STATE)
{
//长按按键4、5,产生2000HZ的方波
case '4':
if(YSTEP_CNT>0)
{
if(YSTEP_CNT>1000)
{
digitalWrite(YSTEP_PIN, HIGH);
delayMicroseconds(250);
digitalWrite(YSTEP_PIN, LOW);
delayMicroseconds(250);
}
else
{
digitalWrite(YSTEP_PIN, HIGH);
delay(5);
digitalWrite(YSTEP_PIN, LOW);
delay(5);
}
YSTEP_CNT--;
}
break;
case '5':
if(YSTEP_CNT<30000)
{
digitalWrite(YSTEP_PIN, HIGH);
delayMicroseconds(250);
digitalWrite(YSTEP_PIN, LOW);
delayMicroseconds(250);
YSTEP_CNT++;
}
break;
//长按按键7、8,产生100HZ的方波
case '7':
if(YSTEP_CNT>0)
{
digitalWrite(YSTEP_PIN, HIGH);
delay(5);
digitalWrite(YSTEP_PIN, LOW);
delay(5);
YSTEP_CNT--;
}
break;
case '8':
if(YSTEP_CNT<30000)
{
digitalWrite(YSTEP_PIN, HIGH);
delay(5);
digitalWrite(YSTEP_PIN, LOW);
delay(5);
YSTEP_CNT++;
}
break;
}
}
void keypadEvent(KeypadEvent key)
{
switch (keypad.getState())
{
//有按键发生时
case PRESSED:
switch (key)
{
//按键1控制电机使能
case '1':
ENA_TOGGLE = !ENA_TOGGLE;
if (ENA_TOGGLE == HIGH)
{
XMOTOR_TOGGLE = LOW;
YMOTOR_TOGGLE = LOW;
}
digitalWrite(ENA_PIN, ENA_TOGGLE);
break;
//按键2控制X轴电机开关
case '2':
if (ENA_TOGGLE == LOW)
XMOTOR_TOGGLE = !XMOTOR_TOGGLE;
break;
//按键3控制Y轴电机开关
case '3':
if (ENA_TOGGLE == LOW)
YMOTOR_TOGGLE = !YMOTOR_TOGGLE;
break;
//按下按键4、7时,控制Y轴电机转向为HIGH
case '4':
case '7':
digitalWrite(YDIR_PIN, HIGH);
break;
//按下5、8时,控制Y轴电机转向为LOW
case '5':
case '8':
digitalWrite(YDIR_PIN, LOW);
break;
}
break;
//有按键长按时
case HOLD:
if (YMOTOR_TOGGLE == HIGH)
{
if (key == '4' || key == '5' || key == '7' || key == '8')
YMOTOR_STATE = key;
}
break;
//有按键释放时
case RELEASED:
if (YMOTOR_TOGGLE == HIGH)
{
if (key == '4' || key == '5' || key == '7' || key == '8')
{
YMOTOR_STATE = 0;
digitalWrite(YSTEP_PIN, LOW);
}
}
break;
}
} |