Skocz do zawartości

Jak zarejestrować przebieg prędkości silnika wraz z jego przyśpieszeniem?


rizone1234

Pomocna odpowiedź

Witam Wszystkich zarejestrowałem prędkość silnika za pomocą enkodera, problem w tym że wyszedł mi taki wykres jak poniżej. Problem w tym, że mierząc obroty muszę najpierw za pomocą timera odmierzyć 1 sekundę, tak jak tutaj, pewnie dlatego nie widać przyśpieszenia silnika  i stąd te schodki.

void ISR_timerone()

{

   Timer1.detachInterrupt();

  RPM = (encoderValue / (pulsePerRevolution*przekladnia)) *60;

  encoderValue = 0;

  Timer1.attachInterrupt(ISR_timerone);

}

void setup() {

Timer1.initialize(1000000);

Timer1.attachInterrupt(ISR_timerone);


Ma ktoś pomysł jak zarejestrować przyśpieszenie silnika i jego prędkość, aby wykres był liniowy a nie schodkowy? Bardzo proszę o pomoc.

 


 

wykres predkosc2.JPG

Edytowano przez rizone1234
Link do komentarza
Share on other sites

13 minut temu, rizone1234 napisał:

muszę najpierw za pomocą timera odmierzyć 1 sekundę

Nie ma takiej konieczności - czas pomiaru może być znacznie krótszy, np. 0,1 sek; trzeba oczywiście zmodyfikować wzór na prędkość.

Można też mierzyć czas pomiędzy dwoma kolejnymi impulsami z enkodera, będzie jeszcze szybciej.

W procedurze ISR nie ma sensu odłączać i podłączać przerwania - w czasie jej działania przerwania i tak nie są aktywne. Natomiast podczas odczytu w programie wartości RMP można dodać noInterrupts() oraz interrupts() aby przerwanie nie przerwało odczytu.

Link do komentarza
Share on other sites

Dzięki za odpowiedź, czas pomiary zmniejszyłem do 0,1 sek ale nadal pomiar prędkości nie zarajestrował przyspieszenie tylko skoczył od razu na górne obroty, zrobiłem jak poniżej:

#include <TimerOne.h>

#include <Arduino.h>

const int PWM = 6;
const int lewo = 7;
const int prawo = 8;
const int kanalA = 2;
const int kanalB = 3;
volatile long encoderValue = 0;
unsigned long lastEncoderCheck = 0;
float lastEncoderValue = 0;
float pulsePerRevolution = 608;
float RPM = 0;
float RPM1 = 0;
float przekladnia = 19;
float pomiar = 0;
unsigned long currentmillis = millis();
// void ISR_timerone()
// {
//   Timer1.detachInterrupt();
//   speed = (encoderValue / impuls) * 60;
//   encoderValue = 0;
//   Timer1.attachInterrupt(ISR_timerone);
// }



void encoderInterruptA(){
  if(digitalRead(kanalA) == digitalRead(kanalB)){
    encoderValue++;
  }else{
    encoderValue--;
  }
}

void ISR_timerone()
{
   //Timer1.detachInterrupt();


noInterrupts();
  RPM = (encoderValue / (pulsePerRevolution*przekladnia)) *600;
  encoderValue = 0;
    //Timer1.attachInterrupt(ISR_timerone);
      interrupts();
}

void setup() {
Timer1.initialize(100000);
Timer1.attachInterrupt(ISR_timerone);




pinMode(PWM, OUTPUT);
analogWrite(PWM, 255);
pinMode(lewo, OUTPUT);
pinMode(prawo, OUTPUT);
pinMode(kanalA, INPUT_PULLUP);
pinMode(kanalB, INPUT_PULLUP);


attachInterrupt(digitalPinToInterrupt(kanalA), encoderInterruptA, CHANGE);

Serial.begin(115200);
 
}

void loop() {
  digitalWrite(lewo, HIGH);
    digitalWrite(prawo, LOW);
    
  
 Serial.println(RPM);

}
// }

Nie rozumiem co mi da zmierzenie czasu pomiędzy dwoma impulsami i jak mogłbym go wykorzystać do pomiaru predkość [obr/min] z zarejestrowaniem przyspieszenia.

Link do komentarza
Share on other sites

Widocznie silnik osiąga pełne obroty w czasie mniejszym od 0.1s.

 

Czas pomiędzy impulsami jest odwrotnie proporcjonalny do prędkości obrotowej. Jeśli enkoder generuje 10 impulsów na jeden obrót, a odstęp czasu pomiędzy dwoma kolejnymi  impulsami wynosi 0,01 sek, to oznacza że silnik obraca się z prędkością 10 obr/s, czyli 600 obr/min. Ten sposób pomiaru pozwala na najszybszą reakcję na zmieniającą się prędkość.

Porównując różnicę pomiędzy dwiema kolejno obliczonymi prędkościami otrzymujemy przyśpieszenie.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

5 godzin temu, rizone1234 napisał:
RPM = (encoderValue / (pulsePerRevolution*przekladnia)) *60;

Gdzie jest usytuowany enkoder i ile generuje pulsów na obrót? Na wykresie największa wartość to 30 obr/min, to pół obrotu na sekundę czyli 18 stopni na 0,1 s. To raczej sporo by coś dokładnie policzyć.

Jeśli stosujesz takie tarcze jakie są dostępne w Botlandzie,

dysk-do-enkoderow-optycznych-25mm.thumb.png.a781a14fc0a47c01be8c79d9ca878037.png

które mają, jeśli dobrze policzyłem 20 slotów, to w czasie 0,1 s dostajesz 1 (jeden) impuls. Stąd problem. Powinieneś zastosować tarczę z większą ilością slotów lub zamontować w miejscu, w którym będzie się szybciej obracać.

Edytowano przez Sylba
Link do komentarza
Share on other sites

Zależy jak szybko liczysz, jeśli licznik będzie zliczał co 1µS(pomiędzy kolejnymi impulsami enkodera) wartości wyjdą wystarczająco duże aby mieć pogląd na mierzone parametry

@rizone1234 na jakim mikrokontrolerze to robisz? Taki STM32 niezależnie od wersji ma mnóstwo timerów i trybów do ich obsługi

Edytowano przez _LM_
Link do komentarza
Share on other sites

1 godzinę temu, jand napisał:

Widocznie silnik osiąga pełne obroty w czasie mniejszym od 0.1s.

 

Czas pomiędzy impulsami jest odwrotnie proporcjonalny do prędkości obrotowej. Jeśli enkoder generuje 10 impulsów na jeden obrót, a odstęp czasu pomiędzy dwoma kolejnymi  impulsami wynosi 0,01 sek, to oznacza że silnik obraca się z prędkością 10 obr/s, czyli 600 obr/min. Ten sposób pomiaru pozwala na najszybszą reakcję na zmieniającą się prędkość.

Porównując różnicę pomiędzy dwiema kolejno obliczonymi prędkościami otrzymujemy przyśpieszenie.

Dzięki, Enkoder jest 2 kanałowy generuje 64 impulsy na obrót jego prędkość to 530obr/min, problem w tym że mierze tylko kanał A czyli mam tylko 32 impulsy na obrót i czas zmierzony to 700 microsek, z obliczeń zatem wychodzi ze silnik powienien się krecic z predkościa ponad 2500 obr min wykres jest po przeliczeniu przekładni

20 minut temu, Sylba napisał:

Gdzie jest usytuowany enkoder i ile generuje pulsów na obrót? Na wykresie największa wartość to 30 obr/min, to pół obrotu na sekundę czyli 18 stopni na 0,1 s. To raczej sporo by coś dokładnie policzyć.

Jeśli stosujesz takie tarcze jakie są dostępne w Botlandzie,

dysk-do-enkoderow-optycznych-25mm.thumb.png.a781a14fc0a47c01be8c79d9ca878037.png

które mają, jeśli dobrze policzyłem 20 slotów, to w czasie 0,1 s dostajesz 1 (jeden) impuls. Stąd problem. Powinieneś zastosować tarczę z większą ilością slotów lub zamontować w miejscu, w którym będzie się szybciej obracać.

to jest enkoder cpr z czujnikiem Halla obydwa kanały generują 64 impulsy na obrót, ta prędkość 30 obr/min to jest po uwzglednieniu przekładni

15 minut temu, _LM_ napisał:

Zależy jak szybko liczysz, jeśli licznik będzie zliczał co 1µS(pomiędzy kolejnymi impulsami enkodera) wartości wyjdą wystarczająco duże aby mieć pogląd na mierzone parametry

@rizone1234 na jakim mikrokontrolerze to robisz? Taki STM32 niezależnie od wersji ma mnóstwo timerów i trybów do ich obsługi

Robię to na Arduino czas zmierzony pomiędzy dwoma impulsami to 700 microsek to znaczy ze silnik powienien się obracać ponad 2500 obr/min a on tylko się kręci 530 obr/min nie wiem może coś źle zrobiłem kod pniżej:

#include <TimerOne.h>

#include <Arduino.h>

const int PWM = 6;
const int lewo = 7;
const int prawo = 8;
const int kanalA = 2;
const int kanalB = 3;
volatile long encoderValue = 0;
unsigned long lastEncoderCheck = 0;
float lastEncoderValue = 0;
float pulsePerRevolution = 608;
float RPM = 0;
float RPM1 = 0;
float przekladnia = 19;
float pomiar = 0;
unsigned long currentmillis = micros();
volatile unsigned long eventtime = 0;
unsigned long eventtime1 = 0;
float czas = 0;
float flaga = 0;
// void ISR_timerone()
// {
//   Timer1.detachInterrupt();
//   speed = (encoderValue / impuls) * 60;
//   encoderValue = 0;
//   Timer1.attachInterrupt(ISR_timerone);
// }



void encoderInterruptA(){
  if(digitalRead(kanalA) == digitalRead(kanalB)){

    encoderValue++;
    
  if (flaga == 0) {
	eventtime=micros();
	flaga = 1;
  }
 
   
  }else{
    encoderValue--;
  }

}
 
void ISR_timerone()
{
   //Timer1.detachInterrupt();


noInterrupts();
  RPM = (encoderValue / (pulsePerRevolution*przekladnia)) *60;
  encoderValue = 0;
  
    //Timer1.attachInterrupt(ISR_timerone);
      interrupts();
}

void setup() {
Timer1.initialize(1000);
Timer1.attachInterrupt(ISR_timerone);




pinMode(PWM, OUTPUT);
analogWrite(PWM, 255);
pinMode(lewo, OUTPUT);
pinMode(prawo, OUTPUT);
pinMode(kanalA, INPUT_PULLUP);
pinMode(kanalB, INPUT_PULLUP);


attachInterrupt(digitalPinToInterrupt(kanalA), encoderInterruptA, CHANGE);

Serial.begin(115200);
 
}

void loop() {
  digitalWrite(lewo, HIGH);
    digitalWrite(prawo, LOW);
   
   
  if(flaga == 1){
  czas=eventtime-currentmillis; 
  currentmillis = eventtime;
  flaga = 0;
 Serial.println(czas);

}
 }

 

Link do komentarza
Share on other sites

21 minut temu, Sylba napisał:

Jeśli stosujesz takie tarcze jakie są dostępne w Botlandzie,

Chyba nie, w programie mamy:

float pulsePerRevolution = 608;

 

Link do komentarza
Share on other sites

11 minut temu, jand napisał:

Chyba nie, w programie mamy:

float pulsePerRevolution = 608;

 

TO jest silnik z botlandu coś jest nie halo bo pulseperrevolution powinno być 32, Jak daje 32 to nawet po uwzględnieniu przekładni liczy 530 obr/min zamiast około 30 przekłądnia to 19:1

 

Link do komentarza
Share on other sites

Dobra silnik kręci się 530 obr/min po uwzględnieniu przekładni enkoder z czzujnikiem halla znajduje się z tyły silnika. Silnik jest zakupiony  z botlandu, nie wiem dlaczego czas pomiędzy dwoma impulsami wyszedł 700 microsekund coś musi być nie tak

Link do komentarza
Share on other sites

44 minuty temu, rizone1234 napisał:
void encoderInterruptA(){
  if(digitalRead(kanalA) == digitalRead(kanalB)){

    encoderValue++;
    
  if (flaga == 0) {
	eventtime=micros();
	flaga = 1;
  }

A czy ta funkcja poprawnie zlicza impulsy encoderValue?

Link do komentarza
Share on other sites

59 minut temu, Sylba napisał:

A czy ta funkcja poprawnie zlicza impulsy encoderValue?

Szczerze to nie wiem, na jeden obrót zlicza 608 impulsów biorącc po uwage przekładnię to dobrze zlicza bo 19*32 jest 608 przekladnia to 19:1

Link do komentarza
Share on other sites

16 minut temu, rizone1234 napisał:

Szczerze to nie wiem, na jeden obrót zlicza 608 impulsów biorącc po uwage przekładnię to dobrze zlicza bo 19*32 jest 608 przekladnia to 19:1

Jakoś nie zgadzają się te rachunki. Skoro okres impulsów wynosi 700us, zliczona ilość impulsów 608 na 1 obrót, to czas jednego obrotu wynosi 608 * 700us = 0,0426s. To po przeliczeniu na minutę daje 60/0,0426 = 141 obrotów/min. Jeśli pomnożę ten wynik przez 19 to otrzymam 2680 obr/min, czyli to co powinno być.

Link do komentarza
Share on other sites

Silnik mierzy 140 pare obrotów więc chyba jest dobrze, ale teraz nie rozumiem mam czas i jak mam uzyskać przyspieszenie? Poprzez różnicę dwóch pomiarów prędkośći? Te pomiary przecież odejmą się do siebie i nie da to dobrego wyniku. Z pomiarem czasu pomiędzy impulsami od razu wyskakuje pełna prędkość obr/min nie widać przyspieszenia

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.