Spouštění a zastavení motoru 28BYJ-48 Arduinem

Diskuze a poradna o programátorech a programování různých obvodů

Moderátor: Moderátoři

Zpráva
Autor
Uživatelský avatar
hafca
Příspěvky: 4723
Registrován: 27 črc 2004, 00:00
Bydliště: 25km na západ od Prahy

Spouštění a zastavení motoru 28BYJ-48 Arduinem

#1 Příspěvek od hafca »

Potřebuji spouštět a zastavovat motor 28BYJ-48+ULN2003 koncovými spínači. Motor by měl po zapnutí začít zvedat páku, která nahoře najede na koncák a motor vypne. Páka jede pomalu samočinně dolů, dole najede na koncák, který motor zapne a páka jede zase nahoru. A tak pořád dokola.
Nedokážu nastavit podmínky tak, aby se motor po nájezdu na dolní koncák zapnul.
Mohl by mi někdo poradit jak to dát dohromady?

Kód: Vybrat vše

#include <Stepper.h>

#define OUTPUT1   11                
#define OUTPUT2   10               
#define OUTPUT3   9                
#define OUTPUT4   8                
// Define the number of steps per rotation
const int stepsPerRotation = 2048;  
int switch_H  = 4; // up button
int switch_D = 5; // down button


Stepper myStepper(stepsPerRotation, OUTPUT2, OUTPUT4, OUTPUT1, OUTPUT3);  


void setup() {
 pinMode(4,INPUT_PULLUP);// push button pin as input
 pinMode(5,INPUT_PULLUP);// push button pin as input 
 pinMode(2, OUTPUT);
  myStepper.setSpeed(15);  // 15 RPM

 }
void loop() {
  
  myStepper.step(stepsPerRotation);  
  
if (digitalRead(4)==LOW)

    {
              myStepper.setSpeed(0);
              delay (20);
              digitalWrite(4, HIGH);
    }
    
    
else (digitalRead(5)==LOW);

   {
            myStepper.setSpeed(15);
              digitalWrite(4, HIGH);
              delay (20);
       
     }
  }  

Naposledy upravil(a) hafca dne 19 led 2025, 15:02, celkem upraveno 2 x.
Kdyby Edison nevynalezl elektřinu, do teď se díváme na televizi při svíčkách.
Uživatelský avatar
Valdano
Příspěvky: 3118
Registrován: 01 led 2023, 00:00
Bydliště: Česká Lípa

#2 Příspěvek od Valdano »

Úprava zdrojáku viz níže.

Kód: Vybrat vše

#include <Stepper.h>

#define OUTPUT1   11
#define OUTPUT2   10
#define OUTPUT3   9
#define OUTPUT4   8
#define SW_H      4
#define SW_D      5

const int stepsPerRotation = 2048; 

Stepper myStepper(stepsPerRotation, OUTPUT2, OUTPUT4, OUTPUT1, OUTPUT3); 

void setup()
{
  pinMode(SW_H,INPUT_PULLUP);
  pinMode(SW_D,INPUT_PULLUP);
  pinMode(2, OUTPUT);
  myStepper.setSpeed(15);
}

void loop()
{
  myStepper.step(stepsPerRotation); 
  if (digitalRead(SW_H)==LOW) {
    // sepnul horní koncák tj. vypnout motor
    myStepper.setSpeed(0);
    delay(20);
  } else {
    if (digitalRead(SW_D)==LOW) {
      // sepnul dolní koncák tj. zapnout motor
      myStepper.setSpeed(15);
      delay(20);
    }
  }
}
Naposledy upravil(a) Valdano dne 04 pro 2024, 18:05, celkem upraveno 3 x.
Uživatelský avatar
samec
Příspěvky: 6669
Registrován: 19 pro 2017, 00:00

#3 Příspěvek od samec »

Valdano, o čo sa snažíš? Prepísal si nefunkčnú blbosť na funkčnú blbosť. Myslíš, že už to pôjde?

hafca, nemôžeš do vstupu zapisovať digitalWrite(4, HIGH);.
Potrebuješ ešte jednu premennu definujúcu aktuálny stav a podľa nej kontrolovať horný alebo dolný spínač. Po zadetekovaní zopnutia spínača, zmeniť stav a zapnúť alebo vypnúť motor.
Uživatelský avatar
Valdano
Příspěvky: 3118
Registrován: 01 led 2023, 00:00
Bydliště: Česká Lípa

#4 Příspěvek od Valdano »

Oprava. Teď by to mělo být funkční.

Úprava zdrojáku viz níže.

Krokový motor 28BYJ-48 má 32 kroků na otáčku motoru a s převodovkou 64:1 je to 2048 kroků na otáčku výstupního hřídele.

Kód: Vybrat vše

#include <Stepper.h>

#define OUTPUT1   11
#define OUTPUT2   10
#define OUTPUT3   9
#define OUTPUT4   8
#define SW_H      4
#define SW_D      5

// řízení chodu
int chod = 0;

// počet kroků na jednu otáčku motoru
const int stepsPerRotation = 32;

Stepper myStepper(stepsPerRotation, OUTPUT2, OUTPUT4, OUTPUT1, OUTPUT3);

void setup()
{
  pinMode(SW_H,INPUT_PULLUP);
  pinMode(SW_D,INPUT_PULLUP);
  pinMode(2, OUTPUT);
  // tímto se nastavuje rychlost otáčení na 1024 RPM tj. 1024 otáček motoru za minutu
  // na převodovce 64:1 to bude 16 RPM tj. 16 otáček výstupního hřídele za minutu
  myStepper.setSpeed(1024);
  chod = 1;
}

void loop()
{
  if (chod) {
    // pokud má běžet motor volá se step(256) 
    // 256 kroků (tj. 8 otáček motoru) během jednoho cyklu loop()
    // na převodovce 64:1 to bude 0,125 otáčky výstupního hřídele
    // funkce je blokující tj. čeká až motor dokončí pohyb 256 kroků
    // při rychlosti 1024RPM a při počtu 32 kroků na jednu otáčku motoru
    // bude její provedení trvat cca 256 * (60 / (1024 * 32)) tj. cca 470ms
    myStepper.step(256);
  };
  if (digitalRead(SW_H)==LOW) {
    // sepnul horní koncák tj. vypnout motor
    // páka pojede samočinně dolů bez motoru
    chod = 0;
    delay(20);
  } else {
    if (digitalRead(SW_D)==LOW) {
      // sepnul dolní koncák tj. zapnout motor
      // motor začne zvedat páku nahoru
      chod = 1;
      delay(20);
    }
  }
}
Uživatelský avatar
hafca
Příspěvky: 4723
Registrován: 27 črc 2004, 00:00
Bydliště: 25km na západ od Prahy

#5 Příspěvek od hafca »

Dík za snahu, ale nefunguje to. Navíc se motor po zapnutí nerozběhne, jen "vrní".
V původním programu jsem měl pohyb motoru v pořádku. To není potřeba řešit.
Problém byl a je jen v jeho (ne)reagování na koncáky. Dokáži ho po zapnutí napájení rozběhnout a horním koncákem zastavit. Ale dolní koncák ho nespustí.
Kdyby Edison nevynalezl elektřinu, do teď se díváme na televizi při svíčkách.
Uživatelský avatar
asdf
Příspěvky: 707
Registrován: 06 říj 2022, 00:00
Kontaktovat uživatele:

#6 Příspěvek od asdf »

Mě tam udivuje tahle konstrukce:

Kód: Vybrat vše

else (digitalRead(5)==LOW);
To asi má být:

Kód: Vybrat vše

else if (digitalRead(5)==LOW)
Uživatelský avatar
Valdano
Příspěvky: 3118
Registrován: 01 led 2023, 00:00
Bydliště: Česká Lípa

#7 Příspěvek od Valdano »

A co tohle?

Kód: Vybrat vše

#include <Stepper.h>

#define OUTPUT1   11
#define OUTPUT2   10
#define OUTPUT3   9
#define OUTPUT4   8
#define SW_H      4
#define SW_D      5

int chod = 0;
const int stepsPerRotation = 2048;

Stepper myStepper(stepsPerRotation, OUTPUT2, OUTPUT4, OUTPUT1, OUTPUT3);

void setup()
{
  pinMode(SW_H,INPUT_PULLUP);
  pinMode(SW_D,INPUT_PULLUP);
  pinMode(2, OUTPUT);
  myStepper.setSpeed(15);
  chod = 1;
}

void loop()
{
  if (chod) {
    myStepper.step(stepsPerRotation);
  };
  if (digitalRead(SW_H)==LOW) {
    // sepnul horní koncák tj. vypnout motor
    // páka pojede samočinně dolů bez motoru
    chod = 0;
    delay(20);
  } else {
    if (digitalRead(SW_D)==LOW) {
      // samozřejmě bez toho v úvodu chybně uvedeného středníku
      // sepnul dolní koncák tj. zapnout motor
      // motor začne zvedat páku nahoru
      chod = 1;
      delay(20);
    };
  };
}
Naposledy upravil(a) Valdano dne 04 pro 2024, 21:12, celkem upraveno 4 x.
Uživatelský avatar
samec
Příspěvky: 6669
Registrován: 19 pro 2017, 00:00

#8 Příspěvek od samec »

asdf píše:Mě tam udivuje tahle konstrukce:

Kód: Vybrat vše

else (digitalRead(5)==LOW);
To asi má být:

Kód: Vybrat vše

else if (digitalRead(5)==LOW)
Ale veď o tom je hneď prvý komentár, Mlho. :lol:
Uživatelský avatar
samec
Příspěvky: 6669
Registrován: 19 pro 2017, 00:00

#9 Příspěvek od samec »

Valdano, nechceš radšej použiť to, čo funguje? To jest myStepper.setSpeed(0); a myStepper.setSpeed(15); ? :D
Uživatelský avatar
asdf
Příspěvky: 707
Registrován: 06 říj 2022, 00:00
Kontaktovat uživatele:

#10 Příspěvek od asdf »

To setSpeed(0) v původním kódu taky není dobrý nápad. Kdo ví, co to udělá, protože se tam pak dělí nulou. Je to totiž naprogramováno takhle:

Kód: Vybrat vše

void Stepper::setSpeed(long whatSpeed)
{
  this->step_delay = 60L * 1000L * 1000L / this->number_of_steps / whatSpeed;
}
Ten Valdanův kód by to mohl řešit.
Uživatelský avatar
asdf
Příspěvky: 707
Registrován: 06 říj 2022, 00:00
Kontaktovat uživatele:

#11 Příspěvek od asdf »

samec píše:Ale veď o tom je hneď prvý komentár, Mlho. :lol:
Aha, ten jsem nějak vynechal. :oops:
Uživatelský avatar
Valdano
Příspěvky: 3118
Registrován: 01 led 2023, 00:00
Bydliště: Česká Lípa

#12 Příspěvek od Valdano »

samec píše:Valdano, nechceš radšej použiť to, čo funguje? To jest myStepper.setSpeed(0); a myStepper.setSpeed(15); ? :D
Nechci, protože podle mého názoru je to nesprávné použití funkce setSpeed() viz citace.

Zdroj: Stepper - setSpeed()
Tato funkce nastavuje otáčky motoru v otáčkách za minutu (RPM). Tato funkce nespouští motor, pouze nastavuje rychlost, kterou se bude otáčet, když zavoláte step().
Při běhu motoru se má volat step() a při zastavení motoru se step() prostě nevolá. Navíc setSpeed(0) je chyba i vzhledem k tomu dělení nulou, které zde již zmínil asdf.

Proto mám v příkladu volání step() s podmínkou dle stavu proměnné chod, setSpeed(0) vůbec nevolám a setSpeed(15) stačí pro daný účel nastavit jen jednou v setup().

S tou poslední změnou tj. vrácením stepsPerRotation zpět na 2048 by to už mělo fungovat.
Uživatelský avatar
dj_Paul
Příspěvky: 2715
Registrován: 19 zář 2004, 00:00
Bydliště: Laškov

#13 Příspěvek od dj_Paul »

není popsán důvod použití arduina ale nestačila by jedna L297 + 555 ?
Uživatelský avatar
hafca
Příspěvky: 4723
Registrován: 27 črc 2004, 00:00
Bydliště: 25km na západ od Prahy

#14 Příspěvek od hafca »

Valdano píše:A co tohle?
...
Ano, tohle už funguje. Velké díky za pomoc všem.
Jen je zajímavé, že zastavování funguje až na několikátý pokus, ale rozběh hned. Ale možná je to tím, že to zatím mám na "prkénku". Uvažuji o spínání buď magnetem a jazýčkovým zátavem nebo magnet a Hallovo čidlo. Tam by asi nebylo potřeba řešit debounce.
Kdyby Edison nevynalezl elektřinu, do teď se díváme na televizi při svíčkách.
Uživatelský avatar
hafca
Příspěvky: 4723
Registrován: 27 črc 2004, 00:00
Bydliště: 25km na západ od Prahy

#15 Příspěvek od hafca »

dj_Paul píše:není popsán důvod použití arduina ale nestačila by jedna L297 + 555 ?
Máš pravdu, je to asi s kanonem na vrabce, ale nic jiného mi nenapadlo. I vzhledem k jednoduššímu nastavení parametrů otáčení. Asi by to šlo i s ATTINY, to ale neumím vůbec.
Kdyby Edison nevynalezl elektřinu, do teď se díváme na televizi při svíčkách.
Odpovědět

Zpět na „Programování PIC, ATMEL, EEPROM a dalších obvodů“