Krokový motor - Start/Stop

Odpovědět
User34
Příspěvky: 17
Registrován: 5. 8. 2020, 9:36

11. 8. 2020, 9:04

Zdravím,
podařilo se mi rozjet krokáč tak jak bych si to zhruba představoval, ale zjistil jsem, že budu potřebovat naprogramovat ještě jedno, nebo dvě funkční tlačítka ( to je celkem jedno).
Zkrátka jedno by sloužilo na start a druhé na pomalé zastavení až do nulové rychlosti.
Zkoušel jsem dost variant , ale zatím bez úspěchu...
nevím jestli jít cestou detekování náběžné hrany a pak následné vykonání podprogramu, nebo nějaký jiný způsob ?
viz tento NEFUNKČNÍ program

Kód: Vybrat vše

bool lastInput2; //proměnná s minulým stavem vstupu 2
bool lastInput3; //proměnná s minulým stavem vstupu 3
bool presentInput2; //proměnná s aktuálním stavem vstupu2 
bool presentInput3; //proměnná s aktuálním stavem vstupu 3
void setup() {
pinMode(2, INPUT); //vstup 1 (tlačítko ON)
pinMode(3, INPUT); //vstup 2 (tlačítko OFF)
//pinMode(13, OUTPUT); //výstup (signalizační LED)
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
digitalWrite(6, HIGH);
}
void loop() {
//načtení vstupů do proměnných
presentInput2 = digitalRead(2);
presentInput3 = digitalRead(3);
if (presentInput2 != lastInput2) {
//aktuální a minulý stav tlačítka není stejný
//bylo stisknuto, nebo povoleno tlačítko na pinu 2
if (presentInput2 == HIGH) {
//aktuální stav je HIGH, tlačítko je stisknuto
//je detekována náběžná hrana

digitalWrite(7, LOW);
 digitalWrite(7, HIGH);
 delayMicroseconds(100);
}
else {
//aktuální stav je LOW, tlačítko je povoleno
//je detekována sestupná hrana
}
}

if (presentInput3 != lastInput3) {
//aktální a minulý stav tlačítka není stejný
//bylo stisknuto, nebo povoleno tlačítko na pinu 3
if (presentInput3 == HIGH) {
//aktuální stav je HIGH, tlačítko je stisknuto
//je detekována náběžná hrana
//nahradit zpomalením !!!!!
digitalWrite(7, LOW);
 digitalWrite(7, HIGH);
 delayMicroseconds(800);
}
}
lastInput2 = presentInput2; //uložení aktuálního stavu tlačítka do minulého stavu
lastInput3 = presentInput3; //uložení aktuálního stavu tlačítka do minulého stavu
}

našel jsem i nějakou knihovnu, která by mohla být užitečná (máte sní někdo zkušenosti ?)

Kód: Vybrat vše

// zpomaleni.pde
// -*- mode: C++ -*-
//
// Make a single stepper bounce from one limit to another
//
// Copyright (C) 2012 Mike McCauley
// $Id: Random.pde,v 1.1 2011/01/05 01:51:01 mikem Exp mikem $

#include <AccelStepper.h>

// Define a stepper and the pins it will use
//AccelStepper stepper; // Defaults to AccelStepper::FULL4WIRE (4 pins) on 2, 3, 4, 5
AccelStepper stepper(1,7,6);

void setup ()
{
    stepper.setMaxSpeed (10800);
    stepper.setSpeed (10800);
}

void loop ()
{
     stepper.runSpeed ();
}
radši to shrnu :D
1. jak udělat, aby tlačítka (PushButtoon) fungovali tak, že po zmačknutí pojede podprogram "do nekončna"
2. jak vymyslet zpomalení až do nuly ?
(používám Arduino UNO rev.3)

Díky moc za rady !
Uživatelský avatar
Thomeeque
Příspěvky: 8870
Registrován: 30. 1. 2012, 10:20
Bydliště: Mimo ČR

11. 8. 2020, 9:36

Zaprvé pro použití AccelStepper knihovny ti musí stačit 4000 steps per second, což je její maximum. Stačí? Psal jsi myslím něco o 60RPM, takže to by mohlo (pokud se smíříš s 1/16 microstepem, což už je celkem pěkné).
mimooborová naplavenina • kolowratský zázrak™ • NPS • GCU • HirthCalc • ncDP.ino
User34
Příspěvky: 17
Registrován: 5. 8. 2020, 9:36

11. 8. 2020, 10:08

nakonec mám 80rpm a těch 4000 steps/s by mělo stačit ....
Uživatelský avatar
zz912
Příspěvky: 1348
Registrován: 25. 5. 2008, 7:16

11. 8. 2020, 11:58

Pokud píšeš v IDE, nauč se používat ctrl+T, ať se v tom dá vyznat.

Tohle:

Kód: Vybrat vše

if (presentInput2 != lastInput2) {
//aktuální a minulý stav tlačítka není stejný
//bylo stisknuto, nebo povoleno tlačítko na pinu 2
if (presentInput2 == HIGH) {
//aktuální stav je HIGH, tlačítko je stisknuto
//je detekována náběžná hrana
lze nahradit:

Kód: Vybrat vše

if (presentInput2 > lastInput2) {
//je detekováno stisknutí tlačítka 
1. jak udělat, aby tlačítka (PushButtoon) fungovali tak, že po zmačknutí pojede podprogram "do nekončna"
Možnosti jsou dvě, buď stiskem tlačítka uzavřeš nějaký cyklus do While
https://www.arduino.cc/reference/en/lan ... ure/while/
ale musíš:
a) vyřešit vystoupení z While (např. tlačítko stop == TRUE)
b) smířit se s tím, že cokoliv je mimo While, nebude fungovat

nebo

necháš neustále procházet celou smyčku loop() do nekonečna a stisknutím tlačítka třeba změníš parametr Enable na True a pak mu povolíš točit se:
if (Enable == True) {
digitalWrite(7, LOW);
digitalWrite(7, HIGH);
delayMicroseconds(100);
}
Co se týče toho zpomalení, natuduj si tohle:
https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
A až to pochopíš, tak budeš zvyšovat hodnotu delayMicroseconds(100); do "nekonečna". A až budeš u hodnoty, kdy se motor bude točit velmi pomalu, tak ho vypneš.
BACHA funkce delayMicroseconds je omezená 16383 mikrosekundami, takže funkcí delayMicroseconds nedocílíš velmi malých otáček třeba 1 ot/min.
LinuxCNC - MESA 7i96
zz912.webnode.cz
User34
Příspěvky: 17
Registrován: 5. 8. 2020, 9:36

11. 8. 2020, 12:09

ok díky, zkusím.....
User34
Příspěvky: 17
Registrován: 5. 8. 2020, 9:36

12. 8. 2020, 2:43

tak jsem to nakonec trochu předělal na klasický tlačítka (ne push),
ale potřeboval bych pomoct stím zpomalením nějak tomu, nemůžu přijít na kloub

Kód: Vybrat vše

int startTl = 2;
int rychleTl = 3;
int StartBt;
int RychlostBt;
int State = LOW;
            unsigned long previousMillis = 0;
const long interval = 1000;

void setup()
{
  pinMode(startTl, INPUT);
  pinMode(rychleTl, INPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  digitalWrite(6, HIGH);

}
void loop()


{
  unsigned long currentMillis = millis();
  
  StartBt = digitalRead(startTl);
  RychlostBt = digitalRead(rychleTl);


  if  (StartBt == HIGH && RychlostBt == HIGH ) { //pozadovana rychlost
    digitalWrite(7, LOW);
    digitalWrite(7, HIGH);
    delayMicroseconds(100);
  }
  else if (StartBt == HIGH && RychlostBt == LOW ) { //zpomaleni
    //dodelat zpomaleni
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;
      if (State == LOW) {
        State = HIGH;
      } else {
        State = LOW;
      }
      digitalWrite(7, LOW);
      digitalWrite(7, HIGH);
      digitalWrite(7, State);
    
    }
  }
  else if  (StartBt == LOW && RychlostBt == LOW ) { //vypnuto

  }


}


mohl by mi někdo pomoct ?
Díky
Uživatelský avatar
jova
Příspěvky: 2509
Registrován: 2. 11. 2007, 1:40
Bydliště: Chýnov to je kousek od Tábora
Kontaktovat uživatele:

12. 8. 2020, 6:28

Já když něco takového potřebuju provádět v BASICu, tak do té smyčky, která mi generuje impulzy, vložím zpoždění, které každým průchodem nechám zvětšit o určitou hodnotu.
Uživatelský avatar
zz912
Příspěvky: 1348
Registrován: 25. 5. 2008, 7:16

12. 8. 2020, 6:42

User34 píše: 12. 8. 2020, 2:43 tak jsem to nakonec trochu předělal na klasický tlačítka (ne push),
Tudíž jsi to vzdal. Pokud se chceš věnovat programování, potrap svou hlavičku, jinak doporučuji nahradit krokáč stejnosměrným motorem s převodovkou a poté na zpomalování využij potenciiometr. :-)
LinuxCNC - MESA 7i96
zz912.webnode.cz
Uživatelský avatar
Thomeeque
Příspěvky: 8870
Registrován: 30. 1. 2012, 10:20
Bydliště: Mimo ČR

13. 8. 2020, 5:11


Kód: Vybrat vše

// ContStep v0.1, Thmq 2020

// Config:

#define PIN_START_BTN  3
#define PIN_STOP_BTN   2
#define PIN_DRV_ENABLE 13
#define PIN_DRV_STEP   11
#define PIN_DRV_DIR    12

#define MOTOR_SPR      200
#define DRV_MICROSTEP  16

#define RAMP_UP_SEC    0.5
#define RAMP_DOWN_SEC  5.0
#define TARGET_RPM     80.0
#define DISABLE_DRV_MS 1000

// Calculated:

#define INITIAL_RATE_uSEC (100.0 / 1000000.0)
#define TARGET_RATE_uSEC  (MOTOR_SPR * DRV_MICROSTEP * TARGET_RPM / 60.0 / 1000000.0)
#define ACCEL_UP_uSEC     (TARGET_RATE_uSEC / RAMP_UP_SEC / 1000000.0)
#define ACCEL_DOWN_uSEC   (-TARGET_RATE_uSEC / RAMP_DOWN_SEC / 1000000.0)
#define CALC_COMP_uSEC    (34 + 9 + 20 + 31) // based on https://forum.arduino.cc/index.php?topic=40901.0 & measuring

void setup() {
    pinMode(PIN_START_BTN, INPUT_PULLUP);
    pinMode(PIN_STOP_BTN, INPUT_PULLUP);

    pinMode(PIN_DRV_ENABLE, OUTPUT);
    pinMode(PIN_DRV_STEP, OUTPUT);
    pinMode(PIN_DRV_DIR, OUTPUT);

    digitalWrite(PIN_DRV_ENABLE, LOW);
    digitalWrite(PIN_DRV_DIR, LOW);
    digitalWrite(PIN_DRV_STEP, LOW);

    noInterrupts();
}

boolean startBtnIsPressed() {
    return digitalRead(PIN_START_BTN) == LOW;
}

boolean stopBtnIsPressed() {
    return digitalRead(PIN_STOP_BTN) == LOW;
}

boolean shouldDisable() {
    for (unsigned int i = 0; i < DISABLE_DRV_MS; i++) {
        if (startBtnIsPressed()) {
            return false;
        }
        delayMicroseconds(1000);
    }
    return true;
}

#define STATE_STOPPED 0
#define STATE_ACCELERATING 1
#define STATE_RUNNING 2
#define STATE_DECELERATING 3

unsigned int state = STATE_STOPPED;
float rate;
float acceleration;

void loop() {
    boolean startBtn = startBtnIsPressed();
    boolean stopBtn = stopBtnIsPressed();

    if (state == STATE_STOPPED && startBtn) {
        digitalWrite(PIN_DRV_ENABLE, HIGH);
        state = STATE_ACCELERATING;
        rate = INITIAL_RATE_uSEC;
        acceleration = ACCEL_UP_uSEC;
    }
    else if ((state == STATE_RUNNING || state == STATE_ACCELERATING) && stopBtn) {
        state = STATE_DECELERATING;
        acceleration = ACCEL_DOWN_uSEC;
    }
    else if (state == STATE_DECELERATING && startBtn) {
        state = STATE_ACCELERATING;
        acceleration = ACCEL_UP_uSEC;
    }

    if (state != STATE_STOPPED) {
        digitalWrite(PIN_DRV_STEP, HIGH);

        float stepT = 1.0 / rate; // takes cca 34us

        digitalWrite(PIN_DRV_STEP, LOW);

        float rateDelta = stepT * acceleration; // takes cca 9us

        if (state != STATE_RUNNING) {
            rate += rateDelta;

            if (rate >= TARGET_RATE_uSEC) {
                rate = TARGET_RATE_uSEC;
                state = STATE_RUNNING;
            }

            if (rate <= INITIAL_RATE_uSEC) {
                if (shouldDisable()) {
                    digitalWrite(PIN_DRV_ENABLE, LOW);
                }
                state = STATE_STOPPED;
            }
        } else {
            // compensate
            delayMicroseconds(20);
        }

        if (stepT > CALC_COMP_uSEC) {
            delayMicroseconds(stepT - CALC_COMP_uSEC);
        }
    }
}
Nebyla to úplná trivka, vhodnější by bylo využít časovač, takhle je to dost alchymie, bez měřáku bych to (časové konstanty) ladit nechtěl.

T.
mimooborová naplavenina • kolowratský zázrak™ • NPS • GCU • HirthCalc • ncDP.ino
Odpovědět

Zpět na „Krokové motory“