#include "A4988.h"
#define MOTOR_STEPS 200 //全步脉冲
#define MICROSTEPPING 16 //细分
#define SM_DIR 5
#define SM_STEP 2
A4988 stepper1(MOTOR_STEPS, SM_DIR, SM_STEP);
#include <Arduino_FreeRTOS.h>
#include "task.h"
TaskHandle_t task1_handler; //定义任务句柄(结构体指针)
TaskHandle_t task2_handler; //定义任务句柄(结构体指针)
void task1(void* args);
void task2(void* args);
//菜单
int8_t MenuIndex=0;
String MenuStr[]={
"RPM",//转速
"ACCEL",//加速度
"DECEL",//减速度
"FORWARD",
"REVERSE",
};
int SMARG[]={//步进电机参数 步进1正转圈数,步进1反转圈数,步进2正转圈数,步进2反转圈数。。。
100, //SMS_RPM_转速 0
500, //加速度 1
500, //减速度2
3200,
800,
};
//EEPROM
#include <EEPROM.h>
void SettingRead();
void SettingWrite();
//LCD1602
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
//编码器
#include <EncoderButton.h>
#define Encoder_CLK A0
#define Encoder_DT A1
#define Encoder_SW A2
EncoderButton eb1(Encoder_CLK, Encoder_DT);
//独立按钮
#include <Bounce2.h>
#define Button_ST A3
Bounce2::Button stButton = Bounce2::Button();
Bounce2::Button swButton = Bounce2::Button();//EncoderButton那个占用性能太多了,换成Bounce2比较小。
bool RUNTAGGER=false;
void stButtonClicked() {//运行按钮
if (RUNTAGGER==true){
RUNTAGGER=false;
vTaskDelete(task2_handler);
Serial.println("急停");
}
else{
Serial.println("启动");
xTaskCreate(task2, "task2", 150, NULL, 0, &task2_handler);//运行电机任务
}
}
bool MenuEdit=false;
void onEb1Clicked() {
if (MenuEdit==true){
MenuEdit=false;
SettingWrite();
if(MenuIndex==0){//RPM重设
stepper1.setRPM(SMARG[MenuIndex]);
}
if(MenuIndex==1){//加速度重设
stepper1.setSpeedProfile(BasicStepperDriver::LINEAR_SPEED, SMARG[1], SMARG[2]);//设置加速度
}
if(MenuIndex==2){//加速度重设
stepper1.setSpeedProfile(BasicStepperDriver::LINEAR_SPEED, SMARG[1], SMARG[2]);//设置加速度
}
}
else{
MenuEdit=true;
}
vTaskResume(task1_handler);//恢复刷新屏幕任务
}
/**
* A function to handle the 'encoder' event
*/
void onEb1Encoder(EncoderButton& eb) {
Serial.print("eb1 incremented by: ");
Serial.println(eb.increment());//当前动作
//Serial.print("eb1 position is: ");
//Serial.println(eb.position());//计数器
uint8_t MenuCount=(sizeof(MenuStr) / sizeof(MenuStr[0]))-1;
if (MenuEdit==false){//非编辑即菜单选择
Serial.print("MenuCount:");
Serial.println(MenuCount);
if (eb.increment()==1){//正转
MenuIndex++;
if (MenuIndex>=MenuCount){
MenuIndex=MenuCount;
Serial.println("最大值");
}
}
else{//反转
MenuIndex--;
if (MenuIndex<=0){
MenuIndex=0;
Serial.println("最小值");
}
}
}
else{//数值编辑状态
if (eb.increment()==1){//正转
SMARG[MenuIndex]=SMARG[MenuIndex]+10;
}
else{//反转
SMARG[MenuIndex]=SMARG[MenuIndex]-10;
}
}
vTaskResume(task1_handler);//恢复刷新屏幕任务
}
void SettingRead(){
uint8_t MenuCount=(sizeof(MenuStr) / sizeof(MenuStr[0]));
int t_SMARG[4];
memcpy(t_SMARG,SMARG,sizeof(SMARG));
bool BADEEPROM=false;
EEPROM.get(0, t_SMARG);
for (uint8_t i=0;i<MenuCount;i++){
if (t_SMARG[i]==-1){//如果有任意-1值
BADEEPROM=true;
break;
}
}
if (BADEEPROM==true){
EEPROM.update(0, SMARG);
}
else{
memcpy(SMARG,t_SMARG,sizeof(t_SMARG));
}
}
void SettingWrite(){
EEPROM.update(0, SMARG);
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
lcd.init();
lcd.backlight();
SettingRead();
//Link the event(s) to your function
eb1.setEncoderHandler(onEb1Encoder);
stButton.attach(Button_ST, INPUT_PULLUP);
swButton.attach(Encoder_SW, INPUT_PULLUP);
xTaskCreate(task1, "Task1", 150, NULL, 2, &task1_handler);//驱动菜单任务
stepper1.begin(SMARG[0],MICROSTEPPING);
stepper1.setSpeedProfile(BasicStepperDriver::LINEAR_SPEED, SMARG[1], SMARG[2]);//设置加速度
}
void loop() {
// put your main code here, to run repeatedly:
eb1.update();
stButton.update();
swButton.update();
if(stButton.rose()){
stButtonClicked();
}
if(swButton.rose()){
onEb1Clicked();
}
}
//任务1 更新菜单
static void task1(void* pvParameters) {
while (1) {
vTaskDelay(5);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(MenuStr[MenuIndex]);
lcd.setCursor(0,1);
lcd.print(SMARG[MenuIndex]);
if(MenuEdit==true){
lcd.setCursor(15,1);
lcd.print("<");
}
vTaskSuspend(NULL);//更新后挂起
}
}
//任务2 执行电机
static void task2(void* pvParameters) {
while (1) {
RUNTAGGER=true;
Serial.println("运行");
//vTaskDelay(500);
stepper1.move(SMARG[3]);
stepper1.move(-SMARG[4]);
Serial.println("停止");
RUNTAGGER=false;
vTaskDelete(NULL);//执行后删除任务
}
}