Stappenmotor 1 rondje laten draaien

Arduino specifieke Software
Berichten: 13
Geregistreerd: 03 Jul 2020, 23:45

Stappenmotor 1 rondje laten draaien

Berichtdoor Oudholland » 21 Apr 2021, 23:28

Beste techneuten, ik ben (als redelijk beginneling helaas) bezig een stappenmotor (NEMA17) aan te sturen met een TB6600-driver.
De uiteindelijke functie wordt een automatische hoogteverstelling van een houtbewerkingsmachine (daar zit nu een handwiel aan om aan te draaien).
En een 2e knop die 3/4 slag gedraaid wordt om de boel te ontgrendelen/vergrendelen. (maar voor de test nu heb ik ff precies 1 slag genomen, dat pas ik later aan)

Die 1e gaat me denk ik lukken; als ik op knop Omhoog druk gaat de motor linksom draaien en als ik op de knop Omlaag druk gaat de motor rechtsom draaien. De motor blijft draaien zolang ik op de knop druk. De snelheid kan worden geregeld met een potmeter. Voor de fijnregeling heb ik ook al en idee, maar die moet ik nog verder uitwerken. Daar kom ik mogelijk later nog op terug.

Het gaat me vooral om de 2e. De knop om te blokkeren en deblokkeren.
Dat wordt een keuzeschakelaar, dus A = high OF B = high.
Daardoor is het geen pulsschakelaar, maar blijft de schakelaar ingedrukt (high) totdat de andere stand wordt gekozen.

Als schakelaar_A wordt ingedrukt (en dus ingedrukt blijft) moet de motor precies 1 slag de ene kant op draaien. En dus niet meer, ook al blijft die knop een uur ingedrukt.
Zodra schakelaar_B wordt ingedrukt (en dus daarmee automatisch schakelaar_A laag wordt, het is immers een toggleswitch) moet de motor weer precies 1 rondje de andere kant op draaien.
Het maakt dus niet uit of het getriggerd wordt door het aangaan van B of het uitgaan van A. Dat ga ik regelen met een If...else als ik de basis (precies 1 rondje draaien) onder de knie heb.

Nu heb ik 'm redelijk onder controle (denk ik); als ik de knop kort indruk draait de motor netjes 1 rondje. MAAR... in mijn code blijft de motor draaien als ik de knop vasthoud. Hoe kan ik deze aanpassen zodat deze stopt na 1 ronde, ook al blijft de knop ingedrukt?
Ik wil namelijk ook enkele controleLED's aansturen met de knoppen A en B, dus die vervangen door pulsknoppen is niet echt een optie. Plus de motor mag niet 2x dezelfde kant achter elkaar op draaien zonder eerst teruggedraaid te hebben.

cpp code
int Button_A = 2;  // Push button A
int LED = 4; // ControleLED, brandt zolang de motor draait en gaat uit sla de motor stopt
int spd = A0; // Potentiometer
int EnablePin = 8; // low = enable, motor is spanningsloos (disable) als hij niets hoeft te doen
int dirPin = 6; // Direction, high = clockwise
int stepPin = 7; // Aansturingspin voor de stappenmotordriver
int pd = 500; // Pulse Delay period
#define stepsPerRevolution 1600


void setup() {
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(EnablePin, OUTPUT);
pinMode(LED, OUTPUT);
pinMode (Button_A, INPUT);
pinMode (spd, INPUT);
}
void loop() {

pd = map((analogRead(spd)), 0, 1023, 100, 1000);


if (digitalRead(Button_A) == HIGH) {

digitalWrite(EnablePin, LOW); // Enable the stepper motor
digitalWrite(dirPin, HIGH); // Set the spinning direction clockwise:
digitalWrite(LED, HIGH);
// Spin the stepper motor 1 revolution:
for (int i = 0; i < stepsPerRevolution; i++) {
// These lines result in 1 step:
digitalWrite(stepPin, HIGH);
delayMicroseconds(pd);
digitalWrite(stepPin, LOW);
delayMicroseconds(pd);
}
digitalWrite(LED, LOW);
digitalWrite(EnablePin, HIGH);
}
}


Ik heb ook al een buttonStateChange toegevoegd (kwam ik hier op het forum ergens tegen) maar dat was niet de oplossing.
Code: Alles selecteren
  buttonState = digitalRead(ButtonUp);

  // compare the buttonState to its previous state
  if (buttonState != lastButtonState)

(maar dan netjes ook verwerkt in de setup etc natuurlijk)


Alvast bedankt voor het meedenken!

Groet, Rob

Advertisement

Berichten: 3602
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: Stappenmotor 1 rondje laten draaien

Berichtdoor shooter » 22 Apr 2021, 09:32

als de knop nog steeds ingedrukt is en je bent klaar met draaien dus een dubbele if dan niks doen ofwel if buttonA && !vlagklaar dan draaien en net onderaan de for next loop zet je de vlagklaar=true neer
paul deelen
shooter@home.nl

Berichten: 13
Geregistreerd: 03 Jul 2020, 23:45

Re: Stappenmotor 1 rondje laten draaien

Berichtdoor Oudholland » 22 Apr 2021, 10:24

Bedankt voor je snelle reactie! Zou je die in iets meer jip-en-janneketaal (of code) willen verduidelijken?
Ik zie 'm nog niet helemaal voor me helaas...

Berichten: 3602
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: Stappenmotor 1 rondje laten draaien

Berichtdoor shooter » 22 Apr 2021, 20:36

Code: Alles selecteren
 if (digitalRead(Button_A) == HIGH) {// hier gaat het motortje dus lopen
 
      digitalWrite(EnablePin, LOW);      // Enable the stepper motor
      digitalWrite(dirPin, HIGH);       // Set the spinning direction clockwise:
      digitalWrite(LED, HIGH);
      // Spin the stepper motor 1 revolution:
      for (int i = 0; i < stepsPerRevolution; i++) {
        // These lines result in 1 step:
        digitalWrite(stepPin, HIGH);
        delayMicroseconds(pd);// zet dit standaard op 10
        digitalWrite(stepPin, LOW);
        delayMicroseconds(pd); hier kun je dus de snelheid bepalen en meeste stappenmotoren kunnen dus niet sneller stappen dan in 50000 microseconden
      // je zou hier kunnen zeggen if knopB dan break}
      digitalWrite(LED, LOW);
      digitalWrite(EnablePin, HIGH);
    }// of een andere manier is geen gebruik maken van een for maar de loop telkens laten lopen tot je ?rond bent dus (stepsmade== stepsper rovolution of || knop B is ingedrukt)
  }
paul deelen
shooter@home.nl

Berichten: 13
Geregistreerd: 03 Jul 2020, 23:45

Re: Stappenmotor 1 rondje laten draaien

Berichtdoor Oudholland » 23 Apr 2021, 01:10

Ik dacht dat ik het of nog niet doorhad of toch dingen fout doe...
Het lukte me nog steeds niet om de motor te laten stoppen na 1 rondje, ondanks dat de startknop ingedrukt blijft.
shooter schreef: // je zou hier kunnen zeggen if knopB dan break}

Het is in deze schakeling juist de bedoeling dat de motor stopt, ook al is knop A nog steeds ingedrukt. Als knop B wordt ingedrukt (of A losgelaten) gebeurt hetzelfde maar dan de andere kant op.
Dus niet dat er pas gestopt wordt als B wordt ingedrukt. En dat lijkt jouw suggestie wel te doen?

shooter schreef: // of een andere manier is geen gebruik maken van een for maar de loop telkens laten lopen tot je ?rond bent dus (stepsmade== stepsper rovolution of || knop B is ingedrukt)

Ik heb onderstaande code toegevoegd maar zonder resultaat:
cpp code
//      stepsmade = stepsmade + 1;
if (stepsmade == stepsPerRevolution) { // Stop na 1 rondje
break;
}


Uiteindelijk ben ik nav jouw hints nog wat gaan googlen en nadenken en uitgekomen op een variant van wat ik al eerder had toegepast, namelijk de lastButtonState.
Ik ben nu bij de volgende code gekomen:
cpp code
int ButtonUp = 2;  // Push button (toggleswitch) Omhoog
int ButtonDown = 3; // Push button (toggleswitch) Omlaag
int LED = 4;
int spd = A0; // Potentiometer
int EnablePin = 8; // low = enable
int dirPin = 6; // Direction, high = clockwise
int stepPin = 7;
int pd; // Pulse Delay period
#define stepsPerRevolution 1600
int stepsmade = 0;
int buttonState1; // the current reading from the input pin
int lastButtonState1 = LOW; // the previous reading from the input pin
int buttonState2; // the current reading from the input pin
int lastButtonState2 = LOW; // the previous reading from the input pin

void setup() {
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(EnablePin, OUTPUT);
pinMode(LED, OUTPUT);
pinMode (ButtonUp, INPUT);
pinMode (ButtonDown, INPUT);
pinMode (spd, INPUT);

digitalWrite(EnablePin, HIGH);
}
void loop() {

pd = map((analogRead(spd)), 0, 1023, 100, 1000);

if (digitalRead(ButtonUp) == HIGH) {
buttonState1 = HIGH;
lastButtonState2 = LOW;
}

if (digitalRead(ButtonDown) == HIGH) {
buttonState2 = HIGH;
lastButtonState1 = LOW;
}

// Als knop Omhoog wordt ingedrukt, draait de motor 1 rondje clockwise.
// Bij lang ingedrukt houden of meerdere keren indrukken wordt er toch maar 1 rondje gedraaid,
// tot knop Omlaag wordt ingedrukt (= ook reset van deze knop).
if (digitalRead(ButtonUp) == HIGH && lastButtonState1 != buttonState1) {
lastButtonState1 = buttonState1;
digitalWrite(EnablePin, LOW); // Enable the stepper motor
digitalWrite(dirPin, HIGH); // Set the spinning direction clockwise:
digitalWrite(LED, HIGH);
// Spin the stepper motor 1 revolution:
for (int i = 0; i < stepsPerRevolution; i++) {
// These lines result in 1 step:
digitalWrite(stepPin, HIGH);
delayMicroseconds(10);
digitalWrite(stepPin, LOW);
delayMicroseconds(pd);
}
digitalWrite(LED, LOW);
digitalWrite(EnablePin, HIGH);
}


// Als knop Omlaag wordt ingedrukt, draait de motor 1 rondje counterclockwise.
// Bij lang ingedrukt houden of meerdere keren indrukken wordt er toch maar 1 rondje gedraaid,
// tot knop Omhoog wordt ingedrukt (= ook reset van deze knop).
if (digitalRead(ButtonDown) == HIGH && lastButtonState2 != buttonState2) {
lastButtonState2 = buttonState2;
digitalWrite(EnablePin, LOW); // Enable the stepper motor
digitalWrite(dirPin, LOW); // Set the spinning direction counterclockwise:
digitalWrite(LED, HIGH);
// Spin the stepper motor 1 revolution:
for (int x = 0; x < stepsPerRevolution; x++) {
// These lines result in 1 step:
digitalWrite(stepPin, HIGH);
delayMicroseconds(10);
digitalWrite(stepPin, LOW);
delayMicroseconds(pd);
}
digitalWrite(LED, LOW);
digitalWrite(EnablePin, HIGH);
}

}

Het lijkt op het eerste gezicht nu te werken: als ik knop 1 (omhoog) indruk, draait de motor 1 rondje. Als ik deze ingedrukt houd draait hij niet verder, als ik deze meerdere keren indruk draait hij niet nogmaals.
Bij het indrukken van knop 2 (omlaag) draait hij 1 rondje de andere kant op.

MAAR... Ik heb een vlaggetje aan de as zitten. En ik zie bij iedere omschakeling dat de vlag een klein stukje opschuift (counterclockwise). Wat heb ik fout zitten in de code waardoor dat wordt veroorzaakt?
(het 2e deel is een exacte kopie van het eerste, maar dan de knopnaam aangepast + (last)buttonstate 1 gewijzigd in 2 voor de status van de andere knop).

Berichten: 3602
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: Stappenmotor 1 rondje laten draaien

Berichtdoor shooter » 23 Apr 2021, 09:01

Ik zie wel dat je heel snelle stappen doet, die plus puls van 10 microseconde is voldoende voor een stap, echter een wachttijd van 100 micro is teweinig voor een feitelijke stap, dus en maak de map groter, waardoor de motor langzamer gaat draaien, en tijden horen in een long unsigned te staan, echter map kan dat niet want die maakt er een int van.(zie uitleg van map bij de reference)
de motor maakt volgens je programma altijd een rondje links en dan weer terug, je kunt voorkomen dat hij doordraait door een flag aan te zetten voor de stand dus een flag=1 als motor links staat en flag =0 als rechts staat, die kun je dus in die if erbij zetten als voorwaarde.
paul deelen
shooter@home.nl

Berichten: 13
Geregistreerd: 03 Jul 2020, 23:45

Re: Stappenmotor 1 rondje laten draaien

Berichtdoor Oudholland » 24 Apr 2021, 00:54

De potmeter waarmee ik de snelheid regel, staat op een kwart tot halverwege, en daarmee maakt hij dus niet exact een heel rondje (1600 stappen). De ene kant op dus wel, de andere kant op niet. Worden er dan toch ergens stappen overgeslagen omdat de motor het niet kan bijhouden?
Als ik de waarde van pd uitlees met de seriële monitor, heb ik nu een waarde van 200; ik denk dat ik met de ideale snelheid op 250-500 zal zitten.
Maar waardoor kan ik de map-functie dan vervangen? Want ik zal op een of andere manier de waarde van de potmeter (0-1023) toch moeten vertalen naar de range in pulsedelays (200-800 waarschijnlijk in het definitieve) om de motorsnelheid te kunnen regelen.

Verder snap ik de flag-functie niet helemaal. Waar (en hoe) moet ik deze invoegen + is dat de oplossing voor het teveel draaien?

Berichten: 3602
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: Stappenmotor 1 rondje laten draaien

Berichtdoor shooter » 24 Apr 2021, 09:58

als je het langzaam zet, dus 1 stap elke seconde dat zijn dus 1 lijoen micros (en dat is weer te groot voor een INT dus je programma omzetten van micros naar mills en dan kijken of het wel netjes links en recchtsom gaat.
Die flag is bedoeld om te zorgen dat het programma als je nog een keer op de knop drukt niet weer een slag maakt maar wacht tot de motor in ruststand staat, dat moet dus voor beide richtingen apart, maar daar kom je snel genoeg achter.
paul deelen
shooter@home.nl

Terug naar Arduino software

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 2 gasten