Универсальный блок управления шаговым двигателем. Нужна помощь в написании программы для мотора.
- Войдите на сайт для отправки комментариев
Всем привет. Потихоньку пилю дальше свой блок управления шаговым мотором. Механическая часть оказалась самой простой и уже закончена на 90%. На 1-й фото видно как все подключено. В блоке 2 Ардуинки (Nano и Mini Pro), Nano показывает меню и график силы тока на дисплее, а Mini Pro должна управлять мотор шилдом (EasyDriver) и караулить 2 конечных выключателя. В зависимости от программы, при нажатии одного такого конечника должно происходить либо остановка мотора либо смена направления вращения на противоположную. Но на этом этапе осознал что написать программу намного сложнее чем я раньше думал.
Если с первой Ардуинкой (Nano) все более менее ясно, меню показывает, кнопки считывает нормально, параметры мотора можно менять, показ графика силы тока прикручен. То 2-я Ардуинка не готова совершенно не могу придумать как синхронизировать параметры мотора на обоих платах. Как сделать чтобы ардуинка (номер 2, Mini Pro) и мотор крутила без остановки и следила за кнопками, при увеличении значений крутим быстрее, при уменьшении медленнее. 2 концевика хочу повесить на прерывания на Mini как раз 2 пина для этого есть. Уважаемы гуру программирования подскажите в какую сторону искать. Или существуют более простые пути реализации такого функционала?
![]()
https://www.youtube.com/watch?v=frXeMvSc5k0&feature=youtu.be
Скетч для первой Ардуинки ниже.
#include <SPI.h>
#include <AccelStepper.h>
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>
/* Rotes Display 1,8" Fast Speed SPI:
CS -> 10
A0 (DC) -> 9
RESET (RST) -> 8
SDA -> 11
SCK (CLK) -> 13 */
#define cs 10
#define dc 9
#define rst 8
AccelStepper stepper (1, 5, 4); // Defaults to AccelStepper::FULL4WIRE (5 pins) on 4, 5, 6, 7, 12
int MS_1 = 6;
int MS_2 = 7;
//#define Neutral 0
#define Mode 1
#define Up 2
#define Down 3
int stepsMotor = 200; // Steps pro Umdrehung
int divider = 8; // Teiler für Mikrosteps
int acceleration = 1000;
int motorSpeed = 100; // steps pro sek
int motorSpeedRPM = ((stepsMotor*motorSpeed*divider)/60); // Umdrehungen pro Minute
int motorRevolution = 10; // Umdrehungen
int moveDirection = 1; // Richtung
int stepsMode = 1; // Microsteps Mode
boolean motorGo = false;
int pos = 36000;
int buttonValue = 0;
int selected = 0;
int lastButtonState = 0;
long lastDebounceTime = 0; long debounceDelay = 110;
int menuState = 0;
int xPos = 10;
Adafruit_ST7735 tft = Adafruit_ST7735(cs, dc, rst);
void setup()
{
attachInterrupt(0, endSwitch1Arrive, RISING);
attachInterrupt(1, endSwitch2Arrive, RISING);
tft.initR(INITR_BLACKTAB);
tft.setRotation(3);
menuStart();
Serial.begin(9600);
delay(20);
}
void loop()
{
menuSelect();
checkButton();
tftUpDate();
delay(20);
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void menuStart(){
tft.fillScreen(ST7735_BLACK);
tft.setTextColor(ST7735_GREEN);
tft.setTextSize(1);
tft.setCursor(0, 4);
tft.println(" Display mode");
tft.setCursor(0, 15);
tft.println(" Steps per rev");
tft.setCursor(0, 26);
tft.println(" Speed rpm");
tft.setCursor(0, 37);
tft.println(" Revolutions");
tft.setCursor(0, 48);
tft.println(" Steps mode");
tft.fillRoundRect(15, 60, 76, 14, 4, ST7735_RED);
tft.setCursor(23, 63);
tft.setTextSize(1);
tft.setTextColor(ST7735_WHITE);
tft.println("START/STOP");
tft.fillRoundRect(85, 3, 30, 10, 3, ST7735_GREEN);
tft.fillRoundRect(85, 14, 30, 10, 3, ST7735_GREEN);
tft.fillRoundRect(85, 25, 30, 10, 3, ST7735_GREEN);
tft.fillRoundRect(85, 36, 30, 10, 3, ST7735_GREEN);
tft.fillRoundRect(85, 47, 30, 10, 3, ST7735_GREEN);
tft.setCursor(89, 48);
tft.setTextColor(ST7735_BLACK, ST7735_GREEN);
tft.print("full");
tft.fillRoundRect(122, 5, 35, 70, 4, ST7735_WHITE);
tft.fillRoundRect(123, 7, 33, 66, 3, ST7735_RED);
tft.drawRoundRect(124, 10, 31, 60, 3, ST7735_WHITE);
tft.drawTriangle(139, 12 , 135, 20, 143, 20, ST7735_WHITE);
tft.drawTriangle(139, 67 , 135, 59, 143, 59, ST7735_WHITE);
tft.setCursor(130, 34);
tft.setTextSize(1);
tft.setTextColor(ST7735_WHITE);
tft.println("to");
tft.setCursor(128, 40);
tft.print("move");
axis_xy(14, 117, 60);
// switchLeft();
// switchRight();
}
void axis_xy(uint16_t x0, uint16_t y0, uint16_t lenght) {
tft.drawFastHLine(x0, y0, lenght, ST7735_GREEN);
tft.fillTriangle(x0+lenght+7, y0, x0+lenght, y0+2, x0+lenght, y0-2, ST7735_GREEN);
tft.drawFastVLine(x0+20, y0-2, 5, ST7735_GREEN);
tft.drawFastVLine(x0+40, y0-2, 5, ST7735_GREEN);
tft.drawFastVLine(x0+60, y0-2, 5, ST7735_GREEN);
tft.drawFastVLine(x0, y0-40, 40, ST7735_GREEN);
tft.drawFastHLine(x0-2, y0+25, 5, ST7735_GREEN);
tft.drawFastHLine(x0-2, y0-20, 5, ST7735_GREEN);
tft.fillCircle(x0, y0, 2, ST7735_GREEN);
tft.fillTriangle(x0, y0-45, x0+2, y0-40, x0-2, y0-40, ST7735_GREEN);
tft.setCursor(x0-12, y0-42);
tft.setTextColor(ST7735_GREEN);
tft.setTextSize(1);
tft.println("10 dA");
tft.setCursor(x0-10, y0-22);
tft.println("5");
tft.setCursor(x0-8, y0+4);
tft.println("0 5 10 15 min"); }
void tftUpDate(){
tft.setCursor(91, 4);
tft.setTextSize(1);
tft.setTextColor(ST7735_BLACK, ST7735_GREEN);
tft.print("S.M.");
tft.setCursor(91, 15);
tft.setTextColor(ST7735_BLACK, ST7735_GREEN);
tft.print(stepsMotor);
tft.setCursor(91, 26);
tft.setTextColor(ST7735_BLACK, ST7735_GREEN);
tft.print(motorSpeed);
tft.setCursor(91, 37);
tft.setTextColor(ST7735_BLACK, ST7735_GREEN);
tft.print(motorRevolution);
if( (millis() % 20) == 0){
int drawGraph = (motorSpeed/2);
Serial.println(drawGraph);
if(xPos >= 160 ){
xPos = 10;
tft.fillRect(10, 55, 150, 55, ST7735_BLACK);
} else {
xPos++;
//tft.drawFastVLine(xPos, 125-drawGraph, drawGraph, ST7735_YELLOW);
tft.drawPixel(xPos, 125-drawGraph, ST7735_RED);
// oneDirection();
}
}
}
int checkButton(){
int buttonState = analogRead(0);
if(500<buttonState && buttonState <701) {
menuState ++;
Serial.print("menuState Änderung");
Serial.println(menuState);
return Mode;}
if(350<buttonState && buttonState <501) {
Serial.print("Up");
return Up;}
if(120<buttonState && buttonState <351) {
Serial.print("Down");
return Down;}
// Logik für's Debouncen (=Entprellen):
if(selected != lastButtonState) {
lastDebounceTime = millis();
lastButtonState = selected;
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if(selected == lastButtonState) {
lastDebounceTime = millis();
return selected;
}
}
}
void menuSelect(){
switch (menuState){
case 0:
delay(20);
tft.drawRoundRect(121, 4, 37, 72, 4, ST7735_BLACK);
tft.drawRoundRect(120, 3, 39, 74, 5, ST7735_BLACK);
tft.drawRoundRect(0, 2, 121, 12, 4, ST7735_CYAN);
tft.drawRoundRect(1, 3, 119, 10, 3, ST7735_CYAN);
Serial.println( "Case 0 ");
switch (checkButton()){
case Up:
break;
case Down:
break;
case Mode:
menuState--; }
break;
case 1:
delay(20);
tft.drawRoundRect(0, 2, 121, 12, 4, ST7735_BLACK);
tft.drawRoundRect(1, 3, 119, 10, 3, ST7735_BLACK);
tft.drawRoundRect(0, 13, 121, 12, 4, ST7735_CYAN);
tft.drawRoundRect(1, 14, 119, 10, 3, ST7735_CYAN);
Serial.println( "Case 1 ");
switch (checkButton()){
case Up:
stepsMotor++;
break;
case Down:
stepsMotor--;
break;
case Mode:
menuState--; }
break;
case 2:
delay(20);
tft.drawRoundRect(0, 13, 121, 12, 4, ST7735_BLACK);
tft.drawRoundRect(1, 14, 119, 10, 3, ST7735_BLACK);
tft.drawRoundRect(0, 24, 121, 12, 4, ST7735_CYAN);
tft.drawRoundRect(1, 25, 119, 10, 3, ST7735_CYAN);
Serial.println( "Case 2 ");
switch (checkButton()){
case Up:
motorSpeed++;
break;
case Down:
motorSpeed--;
break;
case Mode:
menuState--; }
break;
case 3:
delay(20);
tft.drawRoundRect(0, 24, 121, 12, 4, ST7735_BLACK);
tft.drawRoundRect(1, 25, 119, 10, 3, ST7735_BLACK);
tft.drawRoundRect(0, 35, 121, 12, 4, ST7735_CYAN);
tft.drawRoundRect(1, 36, 119, 10, 3, ST7735_CYAN);
Serial.println( "Case 3 ");
switch (checkButton()){
case Up:
motorRevolution++;
break;
case Down:
motorRevolution--;
break;
case Mode:
menuState--; }
break;
case 4:
delay(20);
tft.drawRoundRect(0, 35, 121, 12, 4, ST7735_BLACK);
tft.drawRoundRect(1, 36, 119, 10, 3, ST7735_BLACK);
tft.drawRoundRect(0, 46, 121, 12, 4, ST7735_CYAN);
tft.drawRoundRect(1, 47, 119, 10, 3, ST7735_CYAN);
Serial.println( "Case 4 ");
switch (checkButton()){
case Up:
delay(50);
stepsMode++;
if(stepsMode > 4) stepsMode = 1;
break;
case Down:
delay(50);
stepsMode--;
if(stepsMode < 1) stepsMode = 4;
break;
case Mode:
menuState--; }
switch(stepsMode){
case 1:
Serial.println( "StepsMode 1"); // Aktivieren Voll-Schritt (MS1=0, MS2=0)
for (int i=0; i <=1; i++){
tft.fillRoundRect(85, 47, 30, 10, 3, ST7735_GREEN);
tft.setTextSize(1);
tft.setCursor(89, 48);
tft.setTextColor(ST7735_BLACK, ST7735_GREEN);
tft.print("full"); }
digitalWrite(MS_1, LOW);
digitalWrite(MS_2, LOW);
break;
case 2:
Serial.println( "StepsMode 2"); // Aktivieren Halb-Schritt (MS1=1, MS2=0)
for (int i=0; i <=1; i++){
tft.fillRoundRect(85, 47, 30, 10, 3, ST7735_GREEN);
tft.setTextSize(1);
tft.setCursor(89, 48);
tft.setTextColor(ST7735_BLACK, ST7735_GREEN);
tft.print("1/2 "); }
digitalWrite(MS_1, HIGH);
digitalWrite(MS_2, LOW);
break;
case 3:
Serial.println( "StepsMode 3"); // Aktivieren Viertel-Schritte (MS1=0, MS2=1)
for (int i=0; i <=1; i++){
tft.fillRoundRect(85, 47, 30, 10, 3, ST7735_GREEN);
tft.setTextSize(1);
tft.setCursor(89, 48);
tft.setTextColor(ST7735_BLACK, ST7735_GREEN);
tft.print("1/4 "); }
digitalWrite(MS_1, LOW);
digitalWrite(MS_2, HIGH);
break;
case 4:
Serial.println( "StepsMode 4"); // Aktivieren 1/8-Schritte (MS1=1, MS2=1)
for (int i=0; i <=1; i++){
tft.fillRoundRect(85, 47, 30, 10, 3, ST7735_GREEN);
tft.setTextSize(1);
tft.setCursor(89, 48);
tft.setTextColor(ST7735_BLACK, ST7735_GREEN);
tft.print("1/8 "); }
digitalWrite(MS_1, HIGH);
digitalWrite(MS_2, HIGH);
break; }
break;
case 5:
delay(20);
tft.drawRoundRect(0, 46, 121, 12, 4, ST7735_BLACK);
tft.drawRoundRect(1, 47, 119, 10, 3, ST7735_BLACK);
if ((millis() / 500) % 2){
tft.drawRoundRect(14, 59, 78, 16, 5, ST7735_CYAN);
tft.drawRoundRect(15, 60, 76, 14, 4, ST7735_CYAN);}
else{
tft.drawRoundRect(14, 59, 78, 16, 5, ST7735_BLACK);
tft.drawRoundRect(15, 60, 76, 14, 4, ST7735_BLACK); }
Serial.println( "Case 5 ");
switch (checkButton()){
case Up: // Start /motorStart()
motorGo = !motorGo;
break;
case Down:
motorGo = !motorGo;
break;
case Mode:
menuState--; }
motorDrive();
break;
case 6:
delay(20);
tft.drawRoundRect(14, 59, 78, 16, 5, ST7735_BLACK);
tft.drawRoundRect(15, 60, 76, 14, 4, ST7735_BLACK);
tft.drawRoundRect(78, 90, 80, 22, 7, ST7735_CYAN);
Serial.println( "Case 6 ");
switch (checkButton()){
case Up:
//motorForwardDirect();
break;
case Down:
//motorBackDirect();
break;
case Mode:
menuState--; }
break;
case 7:
delay(20);
tft.drawRoundRect(78, 90, 80, 22, 7, ST7735_BLACK);
tft.drawRoundRect(121, 4, 37, 72, 4, ST7735_CYAN);
tft.drawRoundRect(120, 3, 39, 74, 5, ST7735_CYAN);
Serial.println( "Case 7 ");
stepper.setMaxSpeed(10000);
stepper.setSpeed(8000);
switch (checkButton()){
case Up:
digitalWrite(4, HIGH);
stepper.runSpeed();
break;
case Down:
digitalWrite(4, LOW);
stepper.runSpeed();
break;
case Mode:
menuState=-1; }
break;
}
}
void endSwitch1Arrive (){}
void endSwitch2Arrive (){}
void motorDrive()
{
if(motorGo){
stepper.moveTo(pos);
stepper.setMaxSpeed(3000);
stepper.setAcceleration(10000);
Serial.print("Distance To Go = ");
Serial.println(stepper.distanceToGo());
if(stepper.distanceToGo() != 0){
stepper.run(); }
}
}
Наконец-то! Финальная версия блока управления готова.
Реализовано не совсем все, что желалось, но и это достигнутое состояние перекрывает 99% моих потребностей. Ниже фото и видео работы устройства.
https://www.youtube.com/watch?v=8wseeSLeROE&feature=youtu.be
Ссылки на фотках битые причем тут политика не понимаю перекидывает на http://pikucha.ru/idzxr
боюсь даже cказать arduino mega 2560