Arduino nebo STM, jak naprogramovat STEP/DIR řízení

arduino, teensy, atmega, pic a jine (software, hardware)
Selic
Příspěvky: 651
Registrován: 17. 2. 2010, 1:58
Bydliště: Novopacko

4. 4. 2023, 10:03

Ahoj,
potřeboval bych nakopnutí pro blbce (neprogramátora), jak naprogramovat řízení krokového motoru pro jednoduché polohování.
Potřebuji popojet o nějakou zadanou vzdálenost s rozjezdem a dojezdem po rampě s možností ručního zastavení od obsluhy po krátké rampě.
V Arduinu jsem použil knihovnu Accelstepper a narazil jsem na problémy:
1) Pokud použiju mód řízení jako indexovanou osu, tak samotný rozjezd a dojezd na žádanou vzdálenost po rampě funguje, akorát jsem nevymyslel, jak do toho zakomponovat zastavení od stisknutí tlačítka.
2) Když použiju mód rychlostního řízení, tak mi to koliduje s knihovnou pro řízení LCD displeje - obsluha LCD 4x20 znaků trvá moc dlouho. Plus schodová rampa generovaná programem není moc dobrá.

Aplikace je pojezd foťáku, který je na dlouhé tyči na vozíku. Problém je , že bez rampy se tyč rozklepe a uklidnění po zastavení trvá moc dlouho. Druhý problém je, že se kolem toho motá moc lidí, takže je tam optická závora a stop tlačítko, aby se to zastavilo, když se někdo připlete do cesty.
Elektrikář, mechaniku dělám jen z donucení a jako hobby.
Uživatelský avatar
Thomeeque
Příspěvky: 8912
Registrován: 30. 1. 2012, 10:20
Bydliště: Mimo ČR

4. 4. 2023, 10:17

Selic píše: 4. 4. 2023, 10:03 1) Pokud použiju mód řízení jako indexovanou osu...
Můžeš ten mód nějak blíže specifikovat? Na https://github.com/waspinator/AccelStepper nic o těchto módech na první pohled nevidím. Možná přilož ukázku tvého kódu.
mimooborová naplavenina • kolowratský zázrak™ • NPS • GCU • HirthCalc • ncDP.ino
Selic
Příspěvky: 651
Registrován: 17. 2. 2010, 1:58
Bydliště: Novopacko

4. 4. 2023, 10:54

Thomeeque píše: 4. 4. 2023, 10:17
Selic píše: 4. 4. 2023, 10:03 1) Pokud použiju mód řízení jako indexovanou osu...
Můžeš ten mód nějak blíže specifikovat? Na https://github.com/waspinator/AccelStepper nic o těchto módech na první pohled nevidím. Možná přilož ukázku tvého kódu.
kód je zkopírovaný příklad runToPosition () a runSpeedToPosition ()
- to první zahájí pohyb a na další příkaz to skočí až po dojetí na pozici. Během pojezdu není možné vykonávat jiný kód.
- to druhé se volá jako funkce ve smyčce a vrátí příznak po dojetí na pozici. Bohužel to neumí rampy.
Elektrikář, mechaniku dělám jen z donucení a jako hobby.
Uživatelský avatar
Thomeeque
Příspěvky: 8912
Registrován: 30. 1. 2012, 10:20
Bydliště: Mimo ČR

4. 4. 2023, 11:36

Mě přijde, že toto by mělo podle popisu podporovat rampu:

Kód: Vybrat vše

// Run the motor to implement speed and acceleration in order to proceed to the target position
// You must call this at least once per step, preferably in your main loop
// If the motor is in the desired position, the cost is very small
// returns true if the motor is still running to the target position.
boolean AccelStepper::run()
{
    if (runSpeed())
	computeNewSpeed();
    return _speed != 0.0 || distanceToGo() != 0;
}
Ale pokud píšeš, že to ani nedělá moc plynulé rampy, tak to asi stejně nemá smysl moc ladit.

Jakou steprate potřebuješ? Do toho displaye posíláš co, aktuální pozici? V ASCII módu nebo tam posíláš nějakou grafiku?
mimooborová naplavenina • kolowratský zázrak™ • NPS • GCU • HirthCalc • ncDP.ino
Selic
Příspěvky: 651
Registrován: 17. 2. 2010, 1:58
Bydliště: Novopacko

4. 4. 2023, 11:48

Thomeeque píše: 4. 4. 2023, 11:36 Mě přijde, že toto by mělo podle popisu podporovat rampu:

Kód: Vybrat vše

// Run the motor to implement speed and acceleration in order to proceed to the target position
// You must call this at least once per step, preferably in your main loop
// If the motor is in the desired position, the cost is very small
// returns true if the motor is still running to the target position.
boolean AccelStepper::run()
{
    if (runSpeed())
	computeNewSpeed();
    return _speed != 0.0 || distanceToGo() != 0;
}
Ale pokud píšeš, že to ani nedělá moc plynulé rampy, tak to asi stejně nemá smysl moc ladit.

Jakou steprate potřebuješ? Do toho displaye posíláš co, aktuální pozici? V ASCII módu nebo tam posíláš nějakou grafiku?
To použití "computeNewSpeed()" bude ono. To mně nenapadlo. Vyzkouším.
Na tom LCD se nastavuje rychlost přejezdu a vzdálenost o jakou se má přejet. Na malou vzdálenost si obsluha přejíždí joystickem a na větší si zadá o kolik cm to má přejet a pak jen tlačítkem potvrdí na kterou stranu to má odjet aby nemusel držet joystick protože přejetí celé dráhy na max rychlost trvá asi 1,5 minuty. Během přejezdu není potřeba nic zobrazovat.
Elektrikář, mechaniku dělám jen z donucení a jako hobby.
Uživatelský avatar
Thomeeque
Příspěvky: 8912
Registrován: 30. 1. 2012, 10:20
Bydliště: Mimo ČR

4. 4. 2023, 12:00

To boolean AccelStepper::run() je přímo příkaz té knihovny, použítí viz https://github.com/waspinator/AccelStep ... Bounce.pde

Edit: dá se využít i jeho návratová hodnota, imho elegantnější:

Kód: Vybrat vše

void loop() {
    if (!stepper.run()) {
        // If at the end of travel go to the other end
        stepper.moveTo(-stepper.currentPosition());
    }
}
mimooborová naplavenina • kolowratský zázrak™ • NPS • GCU • HirthCalc • ncDP.ino
Selic
Příspěvky: 651
Registrován: 17. 2. 2010, 1:58
Bydliště: Novopacko

4. 4. 2023, 1:23

Thomeeque píše: 4. 4. 2023, 12:00 To boolean AccelStepper::run() je přímo příkaz té knihovny, použítí viz https://github.com/waspinator/AccelStep ... Bounce.pde

Edit: dá se využít i jeho návratová hodnota, imho elegantnější:

Kód: Vybrat vše

void loop() {
    if (!stepper.run()) {
        // If at the end of travel go to the other end
        stepper.moveTo(-stepper.currentPosition());
    }
}
Tohle mám právě na obsluhu od ovládání joystickem. Problém je, že se musí stepper.run volat dostatečně často, minimálně jednou na krok, a není tam místo pro vložení obsluhy něčeho časově náročnějšího jako je to LCD.
GRBL to má vyřešené lépe přes přerušení na pozadí, ale je to momentálně vysoce nad moje možnosti pochopení, abych to byl schopný přizpůsobit na moje potřeby.
Elektrikář, mechaniku dělám jen z donucení a jako hobby.
Uživatelský avatar
Thomeeque
Příspěvky: 8912
Registrován: 30. 1. 2012, 10:20
Bydliště: Mimo ČR

4. 4. 2023, 2:41

Jaký display to je, jak s ním komunikuješ? A ptal jsem se tě i na tu steprate (při které to má zároveň komunikovat s displayem).
mimooborová naplavenina • kolowratský zázrak™ • NPS • GCU • HirthCalc • ncDP.ino
lubbez
Příspěvky: 3159
Registrován: 21. 6. 2012, 9:26
Bydliště: Praha

4. 4. 2023, 4:36

Knihovna Accel Stepper je sice uživatelsky přívětivá, ale protože vše počítá v reálném čase, nezbývá už moc času na nic jiného. Já osobně jsem ji přestal používat a rampy si buď počítám nebo nebo čtu z matice. Na LCD pak zapisovat když motor stojí. Do generování kroků prostě zobrazení dát nejde. Ovšem dá se to "očůrat" tím že arduina použiješ dvě. Jedno pracuje a druhé zobrazuje. Použil jsem to už hodně složitých aplikacích 2x a pohoda. Překvapivě pokud použiješ STM32 s emulovaným wiringem, tak je výsledek ještě pomalejší.
Selic
Příspěvky: 651
Registrován: 17. 2. 2010, 1:58
Bydliště: Novopacko

4. 4. 2023, 6:40

lubbez píše: 4. 4. 2023, 4:36 Knihovna Accel Stepper je sice uživatelsky přívětivá, ale protože vše počítá v reálném čase, nezbývá už moc času na nic jiného. Já osobně jsem ji přestal používat a rampy si buď počítám nebo nebo čtu z matice. Na LCD pak zapisovat když motor stojí. Do generování kroků prostě zobrazení dát nejde. Ovšem dá se to "očůrat" tím že arduina použiješ dvě. Jedno pracuje a druhé zobrazuje. Použil jsem to už hodně složitých aplikacích 2x a pohoda. Překvapivě pokud použiješ STM32 s emulovaným wiringem, tak je výsledek ještě pomalejší.
To dvouprocesorové řešení mně napadlo, ale přišel jsem na to, že během přejezdu zapisovat na LCD nepotřebuju. Jenom jsem nepřišel na cestu, jak dosáhnout zastavení po rampě od zmáčknutí tlačítka.
Displej je nějaký klon HD44xxxx má to vícedrátové řízení (nemám tam I2C), pak tam mám ještě maticovou klávesnici.
Frekvence stačí 4kHz.
Elektrikář, mechaniku dělám jen z donucení a jako hobby.
Uživatelský avatar
Cjuz
Příspěvky: 2422
Registrován: 17. 2. 2013, 6:27
Bydliště: Předklášteří
Kontaktovat uživatele:

4. 4. 2023, 9:15

budu řešit něco podobného a po testech různých knihoven mě na většinu pohybů stačí tupé cyklování step výstupu s definovanou prodlevou.
plynulost vyřeším jednoduchým prodlužováním / zkracováním prodlevy, jednoduchá for smyčka.
výhoda je že si do každého pohybu doplním sledování potřebných podmínek, můžu tak snadno houmovat na snímače, zpomalit před plánovanou polohou apod.

akorát to je řízení step by step
Na konci poznávacího procesu je omyl zcela vyvrácen a my nevíme nic. Zato to víme správně.
miv
Příspěvky: 777
Registrován: 17. 9. 2019, 11:55

4. 4. 2023, 9:35

Selic píše: 4. 4. 2023, 6:40 .... Jenom jsem nepřišel na cestu, jak dosáhnout zastavení po rampě od zmáčknutí tlačítka.
Ta "knihovna" je ve formě zdrojového kódu, tak si ji můžeš upravit.
Jde v podstatě o to, doplnit do třídy funkci Stop(), která nastaví požadovanou pozici na takovou, kterou by pohon dosáhl při brždění z aktuální rychlosti na nulu.
Když se podíváš do funkce pro získání nové rychlosti, pak tam najdeš výraz

long stepsToStop = (long)((_speed * _speed) / (2.0 * _acceleration));

který to řeší.

Takže jde pouze o to změnit aktuální požadovanou pozici na pozici spočítanou z aktuální skutečné pozice plus nebo minus (podle směru otáčení) stepsToStop.
Uživatelský avatar
Thomeeque
Příspěvky: 8912
Registrován: 30. 1. 2012, 10:20
Bydliště: Mimo ČR

5. 4. 2023, 9:15

miv píše: 4. 4. 2023, 9:35 Jde v podstatě o to, doplnit do třídy funkci Stop(), která nastaví požadovanou pozici na takovou, kterou by pohon dosáhl při brždění z aktuální rychlosti na nulu.
Když se podíváš do funkce pro získání nové rychlosti, pak tam najdeš výraz

long stepsToStop = (long)((_speed * _speed) / (2.0 * _acceleration));

který to řeší.
Ta funkce už tam je :)

Kód: Vybrat vše

void AccelStepper::stop()
{
  if (_speed != 0.0) {
    long stepsToStop = (long)((_speed * _speed) / (2.0 * _acceleration)) + 1; // Equation 16 (+integer rounding)
    if (_speed > 0)
      move(stepsToStop);
    else
      move(-stepsToStop);
  }
}
Po jejím zavolání stále musíš volat ve smyčce run(), dokud nevrátí false, což je asi trochu matoucí.
mimooborová naplavenina • kolowratský zázrak™ • NPS • GCU • HirthCalc • ncDP.ino
miv
Příspěvky: 777
Registrován: 17. 9. 2019, 11:55

5. 4. 2023, 4:15

Thomeeque píše: 5. 4. 2023, 9:15
miv píše: 4. 4. 2023, 9:35 Jde v podstatě o to, doplnit do třídy funkci Stop(), která nastaví požadovanou pozici na takovou, kterou by pohon dosáhl při brždění z aktuální rychlosti na nulu.
Když se podíváš do funkce pro získání nové rychlosti, pak tam najdeš výraz

long stepsToStop = (long)((_speed * _speed) / (2.0 * _acceleration));

který to řeší.
Ta funkce už tam je :)

Kód: Vybrat vše

void AccelStepper::stop()
{
  if (_speed != 0.0) {
    long stepsToStop = (long)((_speed * _speed) / (2.0 * _acceleration)) + 1; // Equation 16 (+integer rounding)
    if (_speed > 0)
      move(stepsToStop);
    else
      move(-stepsToStop);
  }
}
Po jejím zavolání stále musíš volat ve smyčce run(), dokud nevrátí false, což je asi trochu matoucí.
No vidíš, vymyslel jsem kolo. :D
To, že se musí run volat ve smyčce i nadále, plyne celkem jasně ze způsobu obsluhy. Po pravdě nejlepší je udělat si irq rutinu od nějakého časovače a volat to z ní. Pak to neotravuje.
Selic
Příspěvky: 651
Registrován: 17. 2. 2010, 1:58
Bydliště: Novopacko

5. 4. 2023, 8:29

Myslím, že jsem to pochopil. Na stránce s popisem knihovny AccelStepper je odkaz na http://web.archive.org/web/201407051439 ... rofile.pdf
Na poslední stránce je schéma jak to generovat pomocí hw prostředků CPU. Ve výpočtech stačí jen nahradit úhel za dráhu a je to :)
Elektrikář, mechaniku dělám jen z donucení a jako hobby.
Odpovědět

Zpět na „MCU“