• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Accelestepper i kłopoty
#1
Potrzebuje sterować dwoma silnikami, tak by jeden wykonał "a" kroków a drugi "b". Powinno to być wykonane "n" razy.
Znalazłem przykład na wykorzystanie biblioteki Accelerstepper (kod poniżej), który chciałem dostosować do swoich potrzeb. W oryginale silnik jedzie do przodu i wraca. Próbowałem zlikwidować ten powrót na różne sposoby. Bezskutecznie. Silnik albo się nie ruszał, albo wracał.
Druga kwestia to faktycznie przebyty dystans (w mm). Przy napędzie kołem zębatym (20 zębów) i mikrokroku 1/16 - 2400 kroków powinno odpowiadać 30mm. W rzeczywistości jest prawie 2 razy więcej. Nie wydaje mi się, by miały na to wpływ zastosowane parametry przyspieszenia czy max prędkości. Moje doświadczenie z Arduino, a tym bardziej z bibliotekami jest na razie znikome, dlatego bardzo proszę o pomoc.

#include <AccelStepper.h>


AccelStepper stepper1(1, 7, 6);
AccelStepper stepper2(1, 9, 8);

int poz1 = 2400;
int poz2 = 192;

void setup()
{
  stepper1.setMaxSpeed(2000);
  stepper1.setAcceleration(100);
  stepper2.setMaxSpeed(1000);
  stepper2.setAcceleration(100);
}

void loop()
{
  if (stepper1.distanceToGo() == 0)
  {
    poz1 = -poz1;
    stepper1.moveTo(poz1);
  }
  if (stepper2.distanceToGo() == 0)
  {
    poz2 = -poz2;
    stepper2.moveTo(poz2);
  }
  stepper1.run();
  stepper2.run();
 
}
 
Odpowiedź
#2
if (stepper1.distanceToGo() == 0)
{
poz1 = -poz1;
stepper1.moveTo(poz1);
}
Ten blok nakazuje stepperowi 1 wrócić, analogiczny dla drugiego. Pokaż kod, który Ci nie działał.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#3
Próbowałem m. innymi tak:
if (stepper1.distanceToGo() == 0)
{
stepper1.moveTo(poz1);
}
oraz tak:
if (stepper1.distanceToGo() == 0)
{

stepper1.moveTo(poz1);
}
stepper1.run();
stepper1.setCurrentPosition(0);

}
 
Odpowiedź
#4
Nie może iść do pozycji poz1, bo tu już jest if (stepper1.distanceToGo() == 0).
Ma być po prostu stepper1.run();, a jak już tam będzie to nic więcej się nie wydarzy.
Zajrzyj do pliku w bibliotece, keywords.txt, wybierz coś dla swojego pomysłu na program, np. jest keywords moveTo, czyli stepper1.moveTo(poz1 ) w setup i run w loop.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#5
Potrzebuję, by funkcja ruch() wykonała się 4 razy. Zrobiłem tak jak poniżej, ale silniki nie ruszają: Ręce już mi opadają.

void setup()
{
stepper1.setMaxSpeed(2000);
stepper1.setAcceleration(100);
stepper2.setMaxSpeed(1000);
stepper2.setAcceleration(100);
stepper1.moveTo(poz1);
stepper2.moveTo(poz2);
}
void loop() {

if(flag){
for(int i = 0; i <= 4; i++){
ruch();}
flag=false;
}
}
void ruch(){

stepper1.run();
stepper2.run();

delay(1000);
}
 
Odpowiedź
#6
Na wszelki wypadek przezyłam ponownie cało kod:
#include <AccelStepper.h>

bool flag = true;
AccelStepper stepper1(1, 7, 6);
AccelStepper stepper2(1, 9, 8);

int poz1 = 2400;
int poz2 = 1000;

void setup()
{
stepper1.setMaxSpeed(2000);
stepper1.setAcceleration(100);
stepper2.setMaxSpeed(1000);
stepper2.setAcceleration(100);
stepper1.moveTo(poz1);
stepper2.moveTo(poz2);
}
void loop() {

if(flag){
for(int i = 0; i <= 4; i++){
ruch();}
flag=false;
}
}
void ruch(){

stepper1.run();
stepper2.run();

delay(1000);
}
 
Odpowiedź
#7
Andrzeju, nie denerwuj się, ale w ogóle nic nie zrozumiałaś jak to ma działać. Nie możesz sobie w loop wstawiać delajów w ogóle, a po 1000ms w szczególności. W żadną część kodu w sumie też nie.
stepper1.run(); ma się uruchamiać milion x na sekundę i sprawdzać czy już upłynęło te 50us (czy ile tam ma upłynąć zależnie od wybranej prędkości i przyspieszenia) by wykonać 1/pierdyliarderową obrotu. Jak wstawisz delaya 1000 to on się kręci, ale efekty kręcenia zauważysz, jak już Twoje wnuki pójdą na studia. Albo i nie jeśli inna część programu ustaliła błędnie, że stepper1.distanceToGo() == 0, ujemną prędkość lub przyspieszenie.
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#8
(02-02-2022, 14:34)kaczakat napisał(a): Andrzeju, nie denerwuj się, ale w ogóle nic nie zrozumiałaś jak to ma działać. Nie możesz sobie w loop wstawiać delajów w ogóle, a  po 1000ms w szczególności. W żadną część kodu w sumie też nie.
stepper1.run(); ma się uruchamiać milion x na sekundę i sprawdzać czy już upłynęło te 50us (czy ile tam ma upłynąć zależnie od wybranej prędkości i przyspieszenia) by wykonać 1/pierdyliarderową obrotu. Jak wstawisz delaya 1000 to on się kręci, ale efekty kręcenia zauważysz, jak już Twoje wnuki pójdą na studia. Albo i nie jeśli inna część programu ustaliła błędnie, że stepper1.distanceToGo() == 0, ujemną prędkość lub przyspieszenie.
Na początku wydawało mi się to takie proste. Chciałem wykonać jednocześnie dwoma silnikami różne ilości kroków, odczekać jakiś czas, zrobić to ponownie zadaną ilość razy. Spędziłem już w internecie ponad 10 godzin. I wszystko jak krew w piach. Jedyne co zrobiłem to to (szkic poniżej). Silniki wprawdzie się kręcą, ale nie jednocześnie.  Dlatego prosiłbym Cię bardzo, abyś wprowadził do tego kodu odpowiednie zmiany. Myślę, że w ten sposób pomożesz mi zrozumieć gdzie robiłem błędy.

#include <AccelStepper.h>

const int stepPin1 = 7; // Silnik nr 1  ruch poziomy
const int dirPin1 = 6;

const int stepPin2 = 9;  //Silnik nr 2 ruch obrotowy głowicy
const int dirPin2 = 8;

AccelStepper stepper1 = AccelStepper(1, stepPin1, dirPin1);
AccelStepper stepper2 = AccelStepper(1, stepPin2, dirPin2);

void setup() {

  pinMode(stepPin1,OUTPUT);
  pinMode(dirPin1,OUTPUT);
  pinMode(stepPin2,OUTPUT);
  pinMode(dirPin2,OUTPUT);
  stepper1.setMaxSpeed(1000);
  stepper1.setAcceleration(500);
  stepper2.setMaxSpeed(1000);
  stepper2.setAcceleration(500);
}


void loop() {

if(flag){
for(int i = 0; i <= 2; i++){
ruch();

delay(3000); //trzeba wpisać 100*Omk
}
flag=false;
}
}


  void ruch(){
   
  stepper1.move(1000); 
  stepper2.move(2000); 
  stepper1.runToPosition(); 
  stepper2.runToPosition();
     
  }
 
Odpowiedź
#9
Może ustawiasz złą prędkość/przyspieszenie. Jak miałem takie silniczki za 1$ to tylko się grzały w bezruchu jak się ustawiło coś za dużo.
To powinno działać, ale nie mam aktualnie żadnego krokowca pod ręką, ustaw swoje piny, akurat na tych miałem ledy:
Kod:
#include <AccelStepper.h>

const int stepPin1 = 4; // Silnik nr 1  ruch poziomy
const int dirPin1 = 6;

const int stepPin2 = 5;  //Silnik nr 2 ruch obrotowy głowicy
const int dirPin2 = 8;

AccelStepper stepper1 = AccelStepper(1, stepPin1, dirPin1);
AccelStepper stepper2 = AccelStepper(1, stepPin2, dirPin2);

uint32_t czasTeraz,czasPoprzedni,tik=10;
uint8_t nTik,sekundy,minuty,godziny,dni;
bool fnTik,fsekundy,fminuty,fgodziny,fdni;
char napis[64];

void setup() {
Serial.begin(115200);

  stepper1.setMaxSpeed(100);
  stepper1.setAcceleration(50);
  stepper1.moveTo(100);
  stepper2.setMaxSpeed(300);
  stepper2.setAcceleration(100);
  stepper2.moveTo(100);
}


void loop()
{
  czas();
if (stepper1.distanceToGo() ==0)   stepper1.moveTo (stepper1.currentPosition()-50) ;
if (stepper2.distanceToGo() <=1)   stepper2.moveTo (stepper2.currentPosition()+50) ;

stepper1.run();
stepper2.run();

if(fsekundy) {

  Serial.print(sekundy);
  sprintf(napis," Silnik1: %6d;",stepper1.currentPosition());
  Serial.print(napis);
  sprintf(napis," Silnik2: %6d;",stepper2.currentPosition());
  Serial.println(napis);
}

}






void czas()
{
  czasTeraz=millis();
fnTik=fsekundy=fminuty=fgodziny=fdni=0;
if((uint32_t)(czasTeraz-czasPoprzedni)>=tik)
{
  czasPoprzedni=czasTeraz;
  fnTik=1;
  nTik++;
  if(nTik>=(1000/tik))
  {
    nTik=0;
    sekundy++;
    fsekundy=1;
     if (sekundy>=60)
    {
      sekundy=0;
      minuty++;
      fminuty=1;
      if (minuty>=60)
      {
        minuty=0;
        godziny++;
        fgodziny=1;
        if (godziny>=24)
        {
          godziny=0;
          fdni=1;
          dni++;
   
        }
      }
    }
  }
}
}
Miło być decenianym https://buycoffee.to/kaczakat
 
Odpowiedź
#10
(03-02-2022, 02:15)kaczakat napisał(a): Może ustawiasz złą prędkość/przyspieszenie. Jak miałem takie silniczki za 1$ to tylko się grzały w bezruchu jak się ustawiło coś za dużo.
To powinno działać, ale nie mam aktualnie żadnego krokowca pod ręką, ustaw swoje piny, akurat na tych miałem ledy:
Dziękuję za odpowiedź. Zawsze jestem pod wrażeniem ludzi, którzy poświęcają swój czas, by pomóc innym.
Niestety przesłany kod działa bardzo dziwnie. Najpierw porusza  się w prawo, a potem wolniutko zaczyna wracać w nieskończoność. Pozostałej części kodu to już w ogóle nie rozumiem. Dlatego się poddałem i zrezygnowałem z biblioteki Accelerstepper do robienia time lapsów. Zastąpiłem ja prostym kodem, który najpierw przesuwa głowicę, następnie ją obraca i robi fotkę. To całkowicie zaspakaja moje oczekiwania.
Napisałem natomiast inny program, którego zadaniem jest, by w określonym czasie "s" przesunąć w poziomie wózek z kamerą z konkretną prędkością "Prp" i jednocześnie obrócić głowicę o zadany kąt z prędkością "Pro". Po czasie "s" powinno nastąpić wyłączenie sterowników i zatrzymanie całego ruchu. Prędkości zostały obliczone z uwzględnieniem długości prowadnicy. Do odliczenia czasu użyłem funkcji millis. I znowu klapa. Silniki pracują bez końca. Gdzie jest błąd?
Oto kod:

#include <AccelStepper.h>

const int s = 10  ; // Czas przejazdu (sek)
const int Prp = 800 ; // Prędkość w poziomie( kroki/sek)
const int Pro = 480 ; //Prędkość głowicy( kroki/sek)

unsigned long Ac = 0; // Aktualny cas
unsigned long Zc = 0; // Zapamiętany czas
unsigned long Rc = 0; // Różnica czasu( Ac-Zc)

AccelStepper stepper1(1, 7, 6);
AccelStepper stepper2(1, 9, 8);
const int enablePin1 = 10; // Steruje wyłączaniem sterowników
const int enablePin2 = 11;

void setup() {
  pinMode(enablePin1,OUTPUT);
  pinMode(enablePin2,OUTPUT);
  digitalWrite(enablePin1,LOW);
  digitalWrite(enablePin2,LOW);
 
  stepper1.setMaxSpeed(10000);
  stepper2.setMaxSpeed(10000);

  stepper1.setSpeed(Prp);
  stepper2.setSpeed(Pro);
}

void loop() { 

  Ac = millis();
  Rc = Ac-Zc;
  if (Rc <= 5000UL) {
 
    Zc = Ac;
 
  stepper1.runSpeed();
  stepper2.runSpeed();
  }
  else
{
  digitalWrite(enablePin1,HIGH);
  digitalWrite(enablePin2,HIGH);
}
}
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości