宁波网站推广外包服务,服装网站建设多少钱,做网站英文,网站空间需要多大代码功能解释
这段代码是一个基于Arduino平台的控制程序#xff0c;主要功能包括#xff1a;
初始化#xff1a;设置引脚模式、初始化编码器、舵机和EEPROM。按键检测#xff1a;处理按钮的单击、双击和长按事件#xff0c;并根据事件执行相应操作。编码器更新#xff…代码功能解释
这段代码是一个基于Arduino平台的控制程序主要功能包括
初始化设置引脚模式、初始化编码器、舵机和EEPROM。按键检测处理按钮的单击、双击和长按事件并根据事件执行相应操作。编码器更新检测旋转编码器的状态调整变量值并控制LED闪烁。舵机控制根据设定的角度和速度移动舵机。LED控制根据条件交替闪烁两个LED。
详细解释 初始化 设置引脚模式为输入或输出。初始化编码器、舵机和EEPROM。 主循环 持续检测按键状态。更新编码器状态。控制舵机运动。控制LED闪烁。 按键检测 检查每个按钮的状态。根据按键事件长按、双击、单击执行不同操作。 编码器更新 检测编码器旋转方向。根据旋转方向增加或减少变量值。切换LED状态。 舵机控制 根据设定的角度和速度移动舵机。正向和反向移动舵机。 LED控制 控制两个LED交替闪烁。
#include Arduino.h
#include Bounce2.h
#include Servo.h
#include EEPROM.h// 定义引脚
#define EC11_A PB_2 // 编码器A
#define EC11_B PA_7 // 编码器B
#define BUTTON_1 PA_4 // 按钮1
#define BUTTON_2 PA_6 // 按钮2
#define PWM_1 PB_0 // PWM控制
#define LED_0 PA_0 // LED0
#define LED_1 PA_1 // LED1// 定义常量
const unsigned long debounceTime 50;
const unsigned long longPressTime 1000;
const unsigned long doubleClickTime 300;
const long led_interval 300;
const int DEFAULT_START_ANGLE 90;
const int DEFAULT_STEPS 100;// 定义变量
uint8_t fast_num 1; // 运动速度
uint8_t fast_delta 90; // 运动距离
uint8_t Count_step 1; // 运动速度调节步进
bool Duoji_run_Flag false;
bool CounterChanged false;
int pos 0;
int variableA 0;
int variableB 0;
bool isVariableA true;// 定义LED状态
bool led0State LOW;
bool led1State LOW;
unsigned long previousMillis1 0;
unsigned long previousMillis2 0;
bool led0Blinked false;
bool led1Blinked false;// 定义按键状态结构体
struct ButtonState
{int pin;int lastState;int currentState;unsigned long lastDebounceTime;unsigned long lastClickTime;bool isLongPress;bool isSingleClickHandled;
};// 初始化按键状态
ButtonState button1 {BUTTON_1, HIGH, HIGH, 0, 0, false, false};
ButtonState button2 {BUTTON_2, HIGH, HIGH, 0, 0, false, false};// 初始化Bounce对象
Bounce encoderPinAButton Bounce();
Bounce encoderPinBButton Bounce();// 初始化Servo对象
Servo myservo;// 宏定义调试输出
#define _DRV_TAG_ line
#define serial_dbg(fmt, args...) \do \{ \if (1) \{ \Serial.printf( _DRV_TAG_ %d [%s] fmt \n, __LINE__, __FUNCTION__, ##args); \} \} while (0)// 初始化函数
void setup()
{Serial.begin(115200);serial_dbg(Hello, Air001. \n);// 设置LED引脚为输出模式pinMode(LED_0, OUTPUT);pinMode(LED_1, OUTPUT);// 初始化LED状态为灭digitalWrite(LED_0, LOW);digitalWrite(LED_1, LOW);// 设置按键引脚为输入模式pinMode(BUTTON_1, INPUT);pinMode(BUTTON_2, INPUT);// 初始化编码器sys_RotaryInit();// 初始化PWM频率和分辨率pinMode(PWM_1, OUTPUT);myservo.attach(PWM_1, 500, 2500); // 修正脉冲宽度read_eeprom();//读数据
}// 主循环函数
void loop()
{checkButton(); // 检测按键encoder_update(); // 更新编码器状态duoji(); // 控制舵机led_blink_once(); // 控制LED闪烁
}
void blinkLEDsAlternatingTwice() {// 保存当前LED状态bool savedLed0State led0State;bool savedLed1State led1State;// 交替闪烁两次for (int i 0; i 2; i) {digitalWrite(LED_0, HIGH);digitalWrite(LED_1, LOW);delay(led_interval);digitalWrite(LED_0, LOW);digitalWrite(LED_1, HIGH);delay(led_interval);}// 恢复LED状态digitalWrite(LED_0, savedLed0State);digitalWrite(LED_1, savedLed1State);
}
void write_eeprom() {// 写入EEPROMEEPROM.write(0, fast_num);EEPROM.write(1, fast_delta);// 写完EEPROM后两颗LED交替闪烁两次blinkLEDsAlternatingTwice();
}
void read_eeprom() {// 读取EEPROMfast_num EEPROM.read(0);fast_delta EEPROM.read(1);if (fast_num 0 || fast_delta 0) {fast_num DEFAULT_START_ANGLE;fast_delta DEFAULT_STEPS;write_eeprom();}serial_dbg(fast_num: %d, fast_delta: %d, fast_num, fast_delta);
}
// 初始化编码器
void sys_RotaryInit()
{pinMode(EC11_A, INPUT);pinMode(EC11_B, INPUT);pinMode(BUTTON_1, INPUT_PULLUP);encoderPinAButton.attach(EC11_A);encoderPinAButton.interval(5);encoderPinBButton.attach(EC11_B);encoderPinBButton.interval(5);
}// 检测按键状态
void checkButton()
{checkButtonState(button1);checkButtonState(button2);
}// 处理按键状态
void checkButtonState(ButtonState button)
{int reading digitalRead(button.pin); // 读取按钮状态// 去抖动处理if (reading ! button.lastState){button.lastDebounceTime millis();}if ((millis() - button.lastDebounceTime) debounceTime){if (reading ! button.currentState){button.currentState reading;if (button.currentState LOW){button.lastClickTime millis();button.isLongPress false;button.isSingleClickHandled false; // 新增标志位}else{unsigned long pressDuration millis() - button.lastClickTime;if (pressDuration longPressTime){button.isLongPress true;handleLongPress(button.pin);}else if (!button.isLongPress){// 检查是否为双击if ((millis() - button.lastClickTime) doubleClickTime !button.isSingleClickHandled){if (digitalRead(button.pin) HIGH){handleDoubleClick(button.pin);button.isSingleClickHandled true; // 标记双击已处理}}else if (!button.isSingleClickHandled){// 如果不是双击则处理单击事件handleSingleClick(button.pin);button.isSingleClickHandled true;}}}}}button.lastState reading;
}// 处理长按事件
void handleLongPress(int pin)
{switch (pin){case BUTTON_1:serial_dbg(Button 1 Long Press);isVariableA !isVariableA;if (isVariableA){digitalWrite(LED_1, LOW);led1State LOW;serial_dbg(Switching to Variable A);}else{digitalWrite(LED_1, HIGH);led1State HIGH;serial_dbg(Switching to Variable B);}break;case BUTTON_2:serial_dbg(Button 2 Long Press);Duoji_run_Flag true;break;default:break;}
}// 处理双击事件
void handleDoubleClick(int pin)
{switch (pin){case BUTTON_1:serial_dbg(Button 1 Double Click);Duoji_run_Flag true;break;case BUTTON_2:serial_dbg(Button 2 Double Click);break;default:break;}
}// 处理单击事件
void handleSingleClick(int pin)
{switch (pin){case BUTTON_1:write_eeprom();serial_dbg(Button 1 Single Click);break;case BUTTON_2:serial_dbg(Button 2 Single Click);Duoji_run_Flag true;break;default:break;}
}// 更新编码器状态
void encoder_update()
{encoderPinAButton.update();encoderPinBButton.update();// 检测编码器旋转if (encoderPinAButton.fell()){if (encoderPinBButton.read() HIGH){if (isVariableA){variableAfast_num;variableA Count_step; // 顺时针旋转fast_num variableA;}else{variableB fast_delta;variableB Count_step; // 顺时针旋转fast_delta variableB;}}else{if (isVariableA){variableAfast_num;variableA - Count_step; // 逆时针旋转fast_num variableA;}else{variableB fast_delta;variableB - Count_step; // 逆时针旋转fast_delta variableB;}}CounterChanged true;if (isVariableA){serial_dbg(Variable A %d , variableA);}else{serial_dbg(Variable B %d , variableB);}led0Blinked false;led_blink_once();}
}// 控制舵机
void duoji()
{if (Duoji_run_Flag){int DEFAULT_END_ANGLE fast_delta DEFAULT_START_ANGLE;Duoji_run_Flag false;unsigned long startTime millis();int totalTime fast_num * 200;// 正向移动moveServo(DEFAULT_START_ANGLE, DEFAULT_END_ANGLE, DEFAULT_STEPS, startTime, totalTime);startTime millis();// 反向移动moveServo(DEFAULT_END_ANGLE, DEFAULT_START_ANGLE, DEFAULT_STEPS, startTime, totalTime);}
}// 移动舵机的辅助函数
void moveServo(int startAngle, int endAngle, int steps, unsigned long startTime, int totalTime)
{unsigned long stepDuration totalTime / steps;float deltaAngle (endAngle - startAngle) * 0.5;for (int i 0; i steps; i){float t (float)i / steps;int angle startAngle deltaAngle * (1 - cos(t * PI));myservo.write(angle);delay(totalTime / steps);// 非阻塞延时while (millis() - startTime (i 1) * stepDuration){checkButton();yield(); // 或者其他适合的多任务处理方法}}
}// 控制LED闪烁
void led_blink_once()
{unsigned long currentMillis millis();// 控制LED1闪烁一次blinkLEDOnce(LED_0, led0State, previousMillis1, currentMillis, led_interval, led0Blinked);// 控制LED2闪烁一次blinkLEDOnce(LED_1, led1State, previousMillis2, currentMillis, led_interval, led1Blinked);
}// 闪烁LED一次
void blinkLEDOnce(int pin, bool state, unsigned long previousMillis, unsigned long currentMillis, long led_interval, bool blinked)
{if (!blinked){if (currentMillis - previousMillis led_interval){previousMillis currentMillis;state !state; // 切换LED状态digitalWrite(pin, state);if (state LOW){blinked true; // 标记LED已经闪烁}}}
}