Schrittmotoransteuerung mit Matlab GUI und Arduino

Hallo zusammen,

mit Hilfe eines GUI moechte ich in MATLAB die Geschwindigkeit und die Richtung meines Steppermotors einlesen - diese an Arduino uebergeben und damit meinen Steppermotor ansteuern.

Die Teile meines Matlab-Programms sehen wie folgt aus:

        function StartSerialButtonValueChanged(app, event)
            value = app.StartSerialButton.Value;
            global temp
            
             if ~isempty(instrfind)      % use instrfind() to detect the possible open port 
                fclose(instrfind);
                delete(instrfind);       % and to delete the object if found
             end

            temp=serial('COM3');         % assign serial port object
            
            set(temp, 'BaudRate', 9600); % set BaudRate to 9600
            set(temp, 'Parity', 'none'); % set Parity Bit to None
            set(temp, 'DataBits', 8);    % set DataBits to 8
            set(temp, 'StopBit', 1);     % set StopBit to 1

            %display the properties of serial port object in MATLAB Window
            disp(get(temp,{'Type','Name','Port','BaudRate','Parity','DataBits','StopBits'}));
            fopen(temp);                 % Open Serial Port Object
            pause(2);

            disp('Serial port is opened');
            app.StatusTextArea.Value = 'Serial port is opened'; 
        end

Beispiel, wenn der Button "CW Rotation" gedrueckt wird:

  value = app.CWRotationButton.Value;
            global temp
            global dataOut
            
            valueRpm = app.rpmEditField_3.Value;
            valueRpm = ((valueRpm/60)*app.StepsperrevolutionEditField.Value)/100;            % conversion rpm -> steps/sec
            
            dataOut(2) = valueRpm;
            dataOut(3) = 2;
            
            fwrite(temp,dataOut);                                                            % print character to the serial port
            disp(dataOut);
            disp('Motor is rotating in clockwise direction');
            app.StatusTextArea.Value = 'Motor is rotating in clockwise direction';           % updating GUI text

Arduino Code:

// Include the AccelStepper library:
#include <AccelStepper.h>

#define dirPin 2
#define stepPin 3
#define motorInterfaceType 1

// Create a new instance of the AccelStepper class:
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

int matlab[4];      // received data matlab
int mchoice;                      
int mspeed,msteps;

void setup() {
 //put your setup code here, to run once:
Serial.begin(9600);
stepper.disableOutputs();
pinMode(13, OUTPUT);
}

void loop() {
 //put your main code here, to run repeatedly:
  if(Serial.available()>=3)
  {
     for(int i=0; i<3;i++)
    {
     matlab[i]= Serial.read();
    }

    msteps = matlab[0];
    mspeed = matlab[1]*100;
    mchoice = matlab[2];
  
    if (mchoice == 1)
   {

   }

   else if (mchoice == 2)
    {
      stepper.enableOutputs();
      stepper.setCurrentPosition(0);
      
      while(stepper.currentPosition()!= 4000){        // returns the current motor position in steps
        stepper.setSpeed(mspeed);
        stepper.runSpeed();
      }
      stepper.disableOutputs();
    }

   else if (mchoice == 3)
    {
       stepper.setCurrentPosition(0);
       while(stepper.currentPosition()!= (-4000)){         // returns the current motor position in steps
        stepper.setSpeed((-1*mspeed));
        stepper.runSpeed();
       }
    }
  
  }
}

Mir geht es aktuell nur um mchoice = 2 - das heist der Motor soll mit der uebergebenen Geschwindigkeit CW rotieren.

Mein Problem: Wenn ich den Steppermotor nur mit Arduino ansteuere und ihn nach vorne und hinten fahren lasse, klappt alles ohne Probleme.

Verwende ich zusaetzlich MATLAB, pfeift der Motor und bewegt sich leider nicht:( (Allerdings versucht er es - schafft es aber nicht…)

Vielleicht koennt ihr mir sagen, wo mein Problem liegt…

Freu mich ueber alle Ratschlaege, Hinweise und Hilfe.

Vielen Dank im Voraus
Verena

Hallo Verena,
wie sieht denn dein Sketch aus, mit dem es funktioniert?

Ansonsten: Das setSpeed gehört nicht in die Whileschleife, sondern davor. Das musst Du nur einmal setzen.
Und welche Stepgeschwindigkeiten erwartest Du?

  mspeed = matlab[1]*100;

Was wird da von matlab übergeben? setSpeed fährt auch keine Rampe, da ist evtl. auch dein Stepper schnell überfordert.

P.S.

     for(int i=0; i<3;i++)
    {
     matlab[i]= Serial.read();
    }

Schickt dein matlab tatsächlich Binärdaten? Und nur im Bereich 0..255? Ich kenne mich mit matlab zwar nicht aus, aber das halte ich für sehr unwahrscheinlich.

Edit: Außerdem scheinst Du in Matlab mit U/min zu arbeiten, setSpeed erwartet aber Steps/sec. Bei der Schnittstelle matlab<->Arduino scheint es noch sehr zu haken.

Nochmal Edit: Woran willst Du eigentlich Anfang und Ende der Übertragung von Matlab erkennen? Üblicherweise braucht es da mindestens ein eindeutiges Trennzeichen zwischen den Übertragungen um die Daten eindeutig zuordnen zu können.

Hi

mspeed kann maximal 32767 (oder -32768) (signed int) annehmen - übergibst Du also nur Geschwindigkeiten von 1 bis 32?
War das .runspeed() nicht blockierend?
Da kein Ziel angegeben wurde, könnte so der Stepper 'mit Vollgas' CW rennen und sich dabei sogar immer weiter vom Ziel entfernen.

Das .setspeed(...) wird nur 1x benötigt, um die Geschwindigkeit 'bis zur nächsten Änderung' einzustellen - wie bereits geschrieben wurde - 1x reicht, nicht laufend wiederholen - also raus aus der WHILE.

Hast Du Dir die Werte z.B. für .setspeed(...) Mal anzeigen lassen?
Wie sehen die Rampen aus?

MfG

Hallo zusammen,

erst mal entschuldigung fuer die spaete Antwort...

MicroBahner:
Ansonsten: Das setSpeed gehört nicht in die Whileschleife, sondern davor. Das musst Du nur einmal setzen.

Das hab ich tatsaechlich gemerkt, nachdem ich das ganze hier gepostet habe :smiley: :smiley: Seitdem funktioniert auch alles !!

MicroBahner:
Edit: Außerdem scheinst Du in Matlab mit U/min zu arbeiten, setSpeed erwartet aber Steps/sec. Bei der Schnittstelle matlab<->Arduino scheint es noch sehr zu haken.

Das stimmt, allerdings rechne ich in Steps/sec um, bevor ich meine Werte an Arduino uebergebe.

Nachdem ich jetzt noch einiges hinzugefuegt habe - stehe ich leider vor meinem naechsten Problem.

Ich habe in MATLAB zwei Button: "Set Reference Position" und "Go to the Reference Position"

Wird "Set Reference Position" gedrueckt, uebergebe ich Nr. 4 an Arduino und es wird folgender Code ausgefuehrt:

else if (mchoice == 4)
    {
       stepper.setCurrentPosition(0);
    }

Nun fahre ich mit meinem Slider an Eine andere Stelle und druecke dann "Go to the Reference Position".
Es wird in MATLAB Nr. 5 an Arduino uebergeben und mein Slider sollte an die zuvor eingestellte Position fahren - tut er aber leider nicht … Mein Arduino Code sieht wie folgt aus:

  else if (mchoice == 5)
    {
      stepper.enableOutputs();
      refSteps = stepper.currentPosition();
      stepper.moveTo(refSteps);
      stepper.run();
      stepper.disableOutputs();
    }

Kann mir da vielleicht jemand sagen, was ich falsch mache?

Vielen lieben Dank!
Verena

Hallo Verena,
die 'stepper.run()' Funktion arbeitet anders, als Du offensichtlich vermutest. Mit jedem Aufruf von 'stepper.run() wird maximal 1 Schritt ausgeführt. Du musst stepper.run() deshalb im loop häufiger aufrufen, als es deiner erforderlichen Steprate entspricht. Wenn kein kein Step anliegt, macht es einfach nichts. Du kannst es deshalb auch unabhängig von einem moveTo-Kommando aufrufen. Es muss nur möglichst oft sein.

Alternativ könntest Du es mit meinen MobaTools machen (können über den Bibliotheksverwalter installiert werden). Da ist die Steperzeugung unabhängig vom loop. Allerdings funktioniert es nur auf den 'standard' Arduinos ( mit AVR-Prozessor ).
Welchen setzt Du denn ein?

MicroBahner:
Alternativ könntest Du es mit meinen MobaTools machen (können über den Bibliotheksverwalter installiert werden). Da ist die Steperzeugung unabhängig vom loop. Allerdings funktioniert es nur auf den 'standard' Arduinos ( mit AVR-Prozessor ).
Welchen setzt Du denn ein?

Hab ich versucht - funktioniert einwandfrei - vielen lieben Dank dafuer!:slight_smile:

Super, freut mich wenn Du es nutzen kannst 8)