ESP32利用AccelStepper庫去驅動A4988 Stepper Motor Driver控制42步進馬達, 並且經由Serial Port來控制馬達的前進, 後退的步數.
ESP32 uses the AccelStepper library to drive the A4988 Stepper Motor Driver to control the 42-stepper motor, and control the forward and backward steps of the motor through the Serial Port.
Architectures:
Fundamental:
A4988 Stepper Motor Driver
步進馬達的轉矩大小。大致說來,扭力在0.8N.m以下,選擇20、28、35、39、42(馬達的機身直徑或方度,單位:mm);扭力在1N.m左右的,選擇57馬達較為合適。扭力在幾個N.m或更大的情況下,就要選擇86、110、130等規格的步進馬達。
The torque of the stepper motor. Generally speaking, if the torque is below 0.8N.m, choose 20, 28, 35, 39, 42 (the diameter or squareness of the motor body, unit: mm); if the torque is around 1N.m, it is more appropriate to choose a 57 motor. When the torque is several N.m or more, it is necessary to choose a stepper motor with specifications such as 86, 110, and 130.
下圖為A4988的pin out
Basic wiring步進電機走一步為1.8度, 走一圈就是200步, 若是使用1/16步進則需3200為一圈.
Basic wiring步進電機走一步為1.8度, 走一圈就是200步, 若是使用1/16步進則需3200為一圈.
LM2596 Low Component Count Step-Down Regulator
Reference the previous article link on blog:
Arduino應用之3D印表機改裝成繪圖機
Arduino應用之3D印表機改裝成繪圖機
YouTube Demo:
ESP32 Code:
#include <AccelStepper.h>
#include <MultiStepper.h>
//--------- Flag structure --------------------------------------
typedef struct _vFlag
{
uint8_t LEDFlag = 1;
} vFlag;
vFlag *flag_Ptr;
vFlag flag;
//------LED------------------
#define LED_BUILTIN 2
char ctemp[20];
//--------- uart structure --------------------------------------
//----------uart--------------
#define LINE_BUFFER_LENGTH 64
typedef struct _vUart
{
char c;
int lineIndex = 0;
int line1Index = 0;
int BTlineIndex = 0;
bool lineIsComment;
bool lineSemiColon;
//char *line;
char line[128];
//char line1[128];
char BTline[20];
//char R_line[20];
//char L_line[20];
String inputString;
String BTinputString;
String S1inputString;
int V[16];
char ctemp[30];
char I2C_Data[80];
int DC_Spped = 50;
float Voltage[16];
int Buffer[128];
int StartCnt = 0;
int ReadCnt = 0;
int sensorValue = 0;
} vUart;
vUart *Uart_Ptr;
vUart Uart;
//--------- motor structure --------------------------------------
typedef struct _axis_state_t
{
uint8_t pulPin[6]; //--X,Y,Z,A,B,C
uint8_t dirPin[6];
uint8_t enaPin[6];
uint8_t HomePin[6];
long RotatorAngle[6];
boolean AXISFlag[6];
uint8_t HomeFlag[6];
uint8_t RotatorFlag[6];
float FeedRate[6];
float MaxSpeed[6];
float Acceleration[6];
int AXISNumber[2];
int DC_Speed[6];
//long positions[2][3];
} axis_state_t;
axis_state_t *gc_Ptr;
axis_state_t gc;
//----------multi motor ---------------------------------------
MultiStepper steppers;
long positions[3]; //gc.pulPin[0]
AccelStepper stepperX (1,14,12); // name of stepper motor (1 = driver, pin 2 = pulse, pin 3 = direction)
AccelStepper stepperY (1,32,33); // name of stepper motor (1 = driver, pin 4 = step, pin 5 = direction)
AccelStepper stepperZ (1,16,17); // name of stepper motor (1 = driver, pin 6 = step, pin 7 = direction)
//------------------------------------------------------------------------------
//-------------------------------------
TaskHandle_t huart;
TaskHandle_t hfunction;
TaskHandle_t hmultimotor; //TaskHandler
void MultiMotorTask(void *pvParameters);
void vUARTTask(void *pvParameters);
//------------------------------------------------------------------------------
void initial()
{
Serial.println(F("Create Task"));
//----------------------------------------------------------------------
xTaskCreatePinnedToCore(
vUARTTask, "UARTTask" // A name just for humans
,
1024 // This stack size can be checked & adjusted by reading the Stack Highwater
,
NULL, 3 // Priority, with 3 (configMAX_PRIORITIES - 1) being the highest, and 0 being the lowest.
,
&huart //handle
,
0);
//----------------------------------------------------------------------
initMultiMotorTask();
//----------------------------------------------------------------------
}
void initMultiMotorTask(void)
{
// Create the task
xTaskCreatePinnedToCore(MultiMotorTask, "MultiMotorTask", 1024, NULL, 3, &hmultimotor, 1);
// Check the results
if (hmultimotor == NULL)
{
Serial.println("Create MultiMotor task failed");
}
else
{
Serial.println("MultiMotor task up and running");
vTaskSuspend(hmultimotor);
}
}
//------------------------------------------------------------------------------
void MultiMotorTask(void *pvParameters)
{
(void)pvParameters;
while(1)
{
if (gc.AXISFlag[0] || gc.AXISFlag[1] || gc.AXISFlag[2])
{
if (gc.RotatorFlag[0] == 1)
{
//Serial.println( "1" );
gc.RotatorAngle[0] = gc.RotatorAngle[0] * 500;
//gc.RotatorAngle[0] = gc.RotatorAngle[0] * 100; //F4設定
positions[0] = gc.RotatorAngle[0];
}
else
{
positions[0] = stepperX.currentPosition();
}
if (gc.RotatorFlag[1] == 1)
{
//Serial.println( "2" );
gc.RotatorAngle[1]=gc.RotatorAngle[1]*500;//F4設定
positions[1] = gc.RotatorAngle[1];
}
else
{
positions[1] = stepperY.currentPosition();
}
if (gc.RotatorFlag[2] == 1)
{
//Serial.println( "3" );
gc.RotatorAngle[2] = gc.RotatorAngle[2] * 100;
//gc.RotatorAngle[2] = gc.RotatorAngle[2] * 250;//F4設定
positions[2] = gc.RotatorAngle[2];
}
else
{
positions[2] = stepperZ.currentPosition();
}
//----multi motor
//positions[0]=gc.RotatorAngle[0];
//positions[1]=gc.RotatorAngle[1];
//vTaskSuspend(hled);
steppers.moveTo(positions);
steppers.runSpeedToPosition();
//steppers.run();
if (abs(stepperX.currentPosition()) == abs(gc.RotatorAngle[0]))
{
gc.AXISFlag[0] = false;
if (gc.RotatorFlag[0] == 1)
{
gc.AXISNumber[0]--;
}
Serial.println( "X_OK" );
//vTaskSuspend( hmultimotor );
}
if (abs(stepperY.currentPosition()) == abs(gc.RotatorAngle[1]))
{
gc.AXISFlag[1] = false;
if (gc.RotatorFlag[1] == 1)
{
gc.AXISNumber[0]--;
}
Serial.println( "Y_OK" );
//vTaskSuspend( hmultimotor );
}
if (abs(stepperZ.currentPosition()) == abs(gc.RotatorAngle[2]))
{
gc.AXISFlag[2] = false;
if (gc.RotatorFlag[2] == 1)
{
gc.AXISNumber[0]--;
}
Serial.println( "Z_OK" );
//vTaskSuspend( hmultimotor );
}
if (gc.AXISNumber[0] == 0)
{
//vTaskResume(hled);
for (int i = 0; i < 6; i++)
{
gc.RotatorFlag[i] = 0;
}
//vTaskSuspend(hmultimotor);
}
}
vTaskDelay(1);
//vTaskDelay(configTICK_RATE_HZ);
}
}
void initMultiMotorSetup(void)
{
gc.pulPin[0] = 26;
gc.dirPin[0] = 25;
//gc.HomePin[0] = 8;
//gc.enaPin[0]=8;
gc.pulPin[1] = 32;
gc.dirPin[1] = 33;
//gc.enaPin[1]=8;
//gc.HomePin[1] = 9;
gc.pulPin[2] = 34;
gc.dirPin[2] = 35;
//gc.enaPin[2]=8;
//gc.HomePin[2] = 10;
for (int i = 0; i < 6; i++)
{
gc.RotatorAngle[i] = 0;
gc.AXISFlag[i] = false;
gc.HomeFlag[i] = 0;
gc.RotatorFlag[i] = 0;
gc.FeedRate[i] = 1000;
gc.MaxSpeed[i] = 4000;
gc.Acceleration[i] = 800;
}
gc.AXISNumber[0] = 0;
gc.AXISNumber[1] = 0;
pinMode(25, OUTPUT);
pinMode(26, OUTPUT);
stepperX.setMaxSpeed(4000);
stepperX.setAcceleration(1000);
stepperX.setSpeed(4000); //:f4000,4000,4000
stepperY.setMaxSpeed(4000); //:ms8000,8000,8000
stepperY.setAcceleration(800);
stepperY.setSpeed(1000);
stepperZ.setMaxSpeed(4000);
stepperZ.setAcceleration(800);
stepperZ.setSpeed(2000);
// Then give them to MultiStepper to manage
steppers.addStepper(stepperX);
steppers.addStepper(stepperY);
steppers.addStepper(stepperZ);
}
//-------------------------------------------------
void setup()
{
Serial.begin(9600);
Serial.println(F("init"));
initial();
initMultiMotorSetup();
}
//-----------------------------------------
void loop()
{
Serial.print(F("Main at core:"));
Serial.println(xPortGetCoreID());
while(1)
{
vTaskDelay(1);
}
}
//----------------------------------------
void processCommand(char *data)
{
int len, xlen, ylen, zlen, alen;
int tempDIO;
String stemp;
len = Uart.inputString.length();
//memset(ctemp, 0, sizeof(ctemp));
//---------------------------------------
if (strstr(data, "VER") != NULL)
{
Serial.println(F("ESP32_20231210"));
}
//-----------Motor----------------------
if (strstr(data, ":X") != NULL)
{
gc.HomeFlag[0] = 3;
gc.AXISFlag[0] = true;
for (int i = 2; i < len; i++)
{
ctemp[i - 2] = data[i];
}
ctemp[len - 2] = '\0';
gc.RotatorAngle[0] = atoi(ctemp);
gc.RotatorFlag[0] = 1;
//Serial.println(gc.RotatorAngle[0]);
gc.AXISNumber[0] = 1;
vTaskResume(hmultimotor);
}
if (strstr(data, ":Y") != NULL)
{
gc.AXISFlag[1] = true;
for (int i = 2; i < len; i++)
{
ctemp[i - 2] = data[i];
}
ctemp[len - 2] = '\0';
gc.RotatorAngle[1] = atoi(ctemp);
//Serial.println(gc.RotatorAngle[1]);
gc.RotatorFlag[1] = 1;
gc.AXISNumber[0] = 1;
vTaskResume(hmultimotor);
}
if (strstr(data, ":Z") != NULL)
{
gc.AXISFlag[2] = true;
for (int i = 2; i < len; i++)
{
ctemp[i - 2] = data[i];
}
ctemp[len - 2] = '\0';
gc.RotatorAngle[2] = atoi(ctemp);
//Serial.println(gc.RotatorAngle[2]);
gc.RotatorFlag[2] = 1;
gc.AXISNumber[0] = 1;
vTaskResume(hmultimotor);
}
}
//-----------------------------------------
//-------------------------------------------
void vUARTTask(void *pvParameters)
{
(void)pvParameters;
Serial.print(F("UARTTask at core:"));
Serial.println(xPortGetCoreID());
for (;;)
{
while (Serial.available() > 0)
{
Uart.c = Serial.read();
if ((Uart.c == '\n') || (Uart.c == '\r'))
{ // End of line reached
if (Uart.lineIndex > 0)
{ // Line is complete. Then execute!
Uart.line[Uart.lineIndex] = '\0'; // Terminate string
//Serial.println( F("Debug") );
//Serial.println( Uart.inputString );
processCommand(Uart.line);
Uart.lineIndex = 0;
Uart.inputString = "";
}
else
{
// Empty or comment line. Skip block.
}
Uart.lineIsComment = false;
Uart.lineSemiColon = false;
Serial.println(F("ok>"));
}
else
{
//Serial.println( c );
if ((Uart.lineIsComment) || (Uart.lineSemiColon))
{
if (Uart.c == ')')
Uart.lineIsComment = false; // End of comment. Resume line.
}
else
{
if (Uart.c == '/')
{ // Block delete not supported. Ignore character.
}
else if (Uart.c == '~')
{ // Enable comments flag and ignore all characters until ')' or EOL.
Uart.lineIsComment = true;
}
else if (Uart.c == ';')
{
Uart.lineSemiColon = true;
}
else if (Uart.lineIndex >= LINE_BUFFER_LENGTH - 1)
{
Serial.println("ERROR - lineBuffer overflow");
Uart.lineIsComment = false;
Uart.lineSemiColon = false;
}
else if (Uart.c >= 'a' && Uart.c <= 'z')
{ // Upcase lowercase
Uart.line[Uart.lineIndex] = Uart.c - 'a' + 'A';
Uart.lineIndex = Uart.lineIndex + 1;
Uart.inputString += (char)(Uart.c - 'a' + 'A');
}
else
{
Uart.line[Uart.lineIndex] = Uart.c;
Uart.lineIndex = Uart.lineIndex + 1;
Uart.inputString += Uart.c;
}
}
}
} //while (Serial.available() > 0)
vTaskDelay(1);
}
}
沒有留言:
張貼留言