Универсальный блок управления шаговым двигателем. Нужна помощь в написании программы для мотора.

Visor5
Offline
Зарегистрирован: 16.02.2014

Всем привет. Потихоньку пилю дальше свой блок управления шаговым мотором. Механическая часть оказалась самой простой и уже закончена на 90%. На 1-й фото видно как все подключено. В блоке 2 Ардуинки (Nano и Mini Pro), Nano показывает меню и график силы тока на дисплее, а Mini Pro должна управлять мотор шилдом (EasyDriver) и караулить 2 конечных выключателя. В зависимости от программы, при нажатии одного такого конечника должно происходить либо остановка мотора либо смена направления вращения на противоположную. Но на этом этапе осознал что написать программу намного сложнее чем я раньше думал. 

Если с первой Ардуинкой (Nano) все более менее ясно, меню показывает, кнопки считывает нормально, параметры мотора можно менять, показ графика силы тока прикручен. То 2-я Ардуинка не готова совершенно не могу придумать как синхронизировать параметры мотора на обоих платах. Как сделать чтобы ардуинка (номер 2, Mini Pro) и мотор крутила без остановки и следила за кнопками, при увеличении значений крутим быстрее, при уменьшении медленнее. 2 концевика хочу повесить на прерывания на Mini как раз 2 пина для этого есть. Уважаемы гуру программирования подскажите в какую сторону искать. Или существуют более простые пути реализации такого функционала? 



[​IMG] [​IMG] [​IMG]

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(); }
  }
}

 

Visor5
Offline
Зарегистрирован: 16.02.2014

Наконец-то! Финальная версия блока управления готова. 

Реализовано не совсем все, что желалось, но и это достигнутое состояние перекрывает 99% моих потребностей. Ниже фото и видео работы устройства.

    

https://www.youtube.com/watch?v=8wseeSLeROE&feature=youtu.be

detek@yandex.ru
Offline
Зарегистрирован: 20.04.2013

Ссылки на фотках битые причем тут политика не понимаю перекидывает на  http://pikucha.ru/idzxr

 

art100
Offline
Зарегистрирован: 09.03.2014

боюсь даже cказать arduino mega 2560