Skocz do zawartości

Czujnik prędkości wiatru


Pomocna odpowiedź

1 godzinę temu, ethanak napisał:
if (!half_costam) rpm = 0;
else rpm = ileśtam/half_cośtam;

Albo coś w tym stylu...

Czyż nie zastosowałem podobnej logiki w pierwszych linijkach mojej funkcji temporary rpm, które to linijki wkleiłem na pierwszej stronie tego tematu?

 

IMG_1451.PNG

(edytowany)
Dnia 27.10.2024 o 09:16, Sylba napisał:

To wszystko to kinematyka i przeliczanie jednostek.
Zauważcie, że średnica wirnika jest podana w calach, prędkość wiatru w milach na godzinę.  1 mph = 5280 feet/h (stóp na godzinę), a jedna stopa to 12 cali.

Dlatego diameter/12 => przeliczenie cali na stopy, a 1/5280 to przeliczenie  mili na stopy.
3,14 to ludolfina czyli pi. 60 to przelicznik prędkości obrotowej 1/minutę na prędkość obrotowa w obrotach na godzinę.

Ogólnie wzór wynika z kinematyki prędkości liniowej obracającej się bryły V=w*R = pi*n *R/30

1736739464_Predkoobrotowa.thumb.png.e8171ceb6fcfcf2b965eff16a9e29869.png

gdzie:

w (omega) to prędkość kątowa = pi * n/30
n  to prędkość obrotowa 1/minutę) - jeden obrót to 2*pi
R to promień wirnika w metrach (jeśli inne jednostki np cale,  mm lub cm to trzeba je przeliczyć na mile lub metry jak kto chce)

 

Obliczenia opisane wzorem powyżej są słuszne przy założeniu, że prędkość liniowa elementu wirnika jest równa prędkości wiatru. Ale tak nie jest. Zauważ, że nie przez cały obrót wiatr wieje prosto na "miseczkę". Wiatr wieje także na pozostałe miseczki. Kształt miseczek sprawia, że opór jaki stawiają wiatrowi jest mniejszy gdy wypukłością są zwrócone do wiatru niż gdy wiatr wieje od strony wklęsłej. Można więc sądzić, że założenie iż prędkość liniowa miseczki jest równa prędkości wiatru jest błędne. Jest mniejsza stąd konieczność skorygowania - np. współczynnik 3,5. Tak naprawdę trzeba ten współczynnik wyznaczyć doświadczalnie mierząc prędkość obrotową przy znanej prędkości wiatru.

Na koniec, tego rodzaju turbiny są mało dokładne, a ich prędkość obrotowa oscyluje (to wpływ konstrukcji) nawet przy tej samej prędkości wiatru. Dlatego w przyrządach do pomiaru prędkości czy przepływu są stosowane turbiny osiowe (śmigłowe).

Zaletą takich wiatromierzy jest to, że działają niezależnie od kierunku wiatru podczas gdy turbinowe pokazują poprawnie gdy tacza turbiny jest ustawiona prostopadle do kierunku wiatru.

Promień r od środka urządzenia do środka miseczek wynosi 7.5cm.

Czy mój wzór jest prawidlowy?

kmh = 6.28 * 0.075 * averageRpm * 3.6;

?

 

Edytowano przez SOYER
(edytowany)
19 godzin temu, SOYER napisał:

Czyż nie zastosowałem podobnej logiki w pierwszych linijkach mojej funkcji temporary rpm, które to linijki wkleiłem na pierwszej stronie tego tematu?

 

IMG_1451.PNG

@ethanak niestety mój i Twój przykład zakłada, że wiatraczek się obraca. Bardzo wolno ale się obraca. Jeśli wiatraczek stoi, a jego ostatni czas półobrotu wynosił poniżej 2000ms, to ten szkic nie wyzeruje nam zmiennej rpm. 

Muszę wymyslić jak to zrobić. Czy można jakoś sprawdzić czy w ciągu ostatnich 2s mieliśmy przerwanie z pinu. Bo jeśli nie mieliśmy, to znaczy, że wiatrak stoi...

Edytowano przez SOYER
(edytowany)
8 minut temu, SOYER napisał:

@ethanak niestety mój i Twój przykład zakłada, że wiatraczek się obraca. Bardzo wolno ale się obraca. Jeśli wiatraczek stoi, a jego ostatni czas półobrotu wynosił poniżej 2000ms, to ten szkic nie wyzeruje nam zmiennej rpm. 

Muszę wymyslić jak to zrobić. Czy można jakoś sprawdzić czy w ciągu ostatnich 2s mieliśmy przerwanie z pinu. Bo jeśli nie mieliśmy, to znaczy, że wiatrak stoi...

Tak to zrobiłem, do funkcji przerwania dodałem zmienną last_call:

void ICACHE_RAM_ATTR rpm_fan() { //funkcja rpm_fan
  if (millis() - last_event < 5) {   //debouncing
    return;
  }
  half_revolutions_time = (millis() - last_event);
  last_event = millis();
  last_call = millis();
}

a następnie w loop sprawdzam tą zmienną:

void temporaryRPM(){
    noInterrupts(); 
    if((last_call + 2000) < millis()){    
     rpm=0;
    }
    else{ 
      rpm = (30000 / half_revolutions_time) ;
    } 
  ...........

chyba działa, poobserwuję jeszcze....

Edytowano przez SOYER
6 minut temu, ethanak napisał:

Sprawdź np. last_event, jeśli był zbyt dawno to wiatraczej stoi

Faktycznie niepotrzebna ta dodatkowa zmienna bo przecież mam już taką co przechowuje dokładnie to co chcę wiedzieć...

Aktualnie mój szkic do prób z czujnikiem wiatru wygląda tak:

#include <Timers.h>

Timer sekund6;
#define windPin 12 //D6
volatile int half_revolutions_time = 2; //Utworzenie zmiennej połowa pełnego obrotu (half revolutions)
volatile int rpm = 0;
unsigned long static  last_event = 0;
float tempRpm = 0;
float averageRpm = 0;
int sample = 0;
float kmh;

 void ICACHE_RAM_ATTR rpm_fan() { //funkcja rpm_fan
  if (millis() - last_event < 5) {   //debouncing
    return;
  }
  half_revolutions_time = (millis() - last_event);
  last_event = millis();
}
void temporaryRPM(){
    noInterrupts(); 
    if((last_event + 2000) < millis()){    
     rpm=0;
    }
    else{ 
      rpm = (30000 / half_revolutions_time) ;
    } 
    if(sekund6.available()){
      tempRpm = tempRpm + rpm;
      sample++;
      sekund6.restart();
     }
    if(sample==10){
      averageRpm = tempRpm / 10;
      kmh = 6.28 * 0.075 * averageRpm * 3.6;
      //wiatr->setValue(kmh);
      tempRpm = 0;
      sample=0;
      sekund6.restart();
    }
   interrupts() ; //Przywróć przerwania
}
void setup() {
  Serial.begin(9600);
  sekund6.begin(6000);
  pinMode(windPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(windPin), rpm_fan, FALLING);
 last_event = millis();
}

void loop() {
  temporaryRPM();
  Serial.print("czas p/obrotu:  ");
  Serial.println(half_revolutions_time);
  Serial.print("rpm:  ");
  Serial.println(rpm);
  Serial.print("km/h:  ");
  Serial.println(kmh);
    Serial.print("sample:  ");
  Serial.println(sample);  
  Serial.print("temporaryRPM:  ");
  Serial.println(tempRpm);

}

Co 6s robię pomiar, nastepnie zbieram 10 pomiarów, wyciągam średnią i wypisuję tą średnią prędkość z ostatniej minuty....

@SOYER robiłem kiedyś prędkościomierz do motocykla, impulsy z hallotronu i magnesy na szprychach. Miałem dwie metody pomiaru: dla wolnych mierzyłem czas między impulsami, dla szybkich liczyłem impulsy w jednostce czasu. Może coś w tę stronę?

Aktualnie moj szkic wyświetla prędkość chwilową i średnią z ostatniej minuty.

#include <Timers.h>

Timer sekund6;
#define windPin 12 //D6
volatile int half_revolutions_time = 2; //Utworzenie zmiennej połowa pełnego obrotu (half revolutions)
volatile int rpm = 0;
unsigned long static  last_event = 0;
float tempRpm = 0;
float averageRpm = 0;
int sample = 0;
float moment_kmh;
float average_kmh;

 void ICACHE_RAM_ATTR rpm_fan() { //funkcja rpm_fan
  if (millis() - last_event < 5) {   //debouncing
    return;
  }
  half_revolutions_time = (millis() - last_event);
  last_event = millis();
}
void temporaryRPM(){
    noInterrupts(); 
    if((last_event + 2000) < millis()){    
     rpm=0;
     moment_kmh = 0;
    }
    else{ 
      rpm = (30000 / half_revolutions_time) ;
      moment_kmh = 6.28 * 0.075 * rpm * 3.6 / 60;
    } 
    if(sekund6.available()){
      tempRpm = tempRpm + rpm;
      sample++;
      sekund6.restart();
     }
    if(sample==10){
      averageRpm = tempRpm / 10;
      average_kmh = 6.28 * 0.075 * averageRpm * 3.6 / 60; 
      //wiatr->setValue(kmh);
      tempRpm = 0;
      sample=0;
      sekund6.restart();
    }
   interrupts() ; //Przywróć przerwania
}
void setup() {
  Serial.begin(9600);
  sekund6.begin(6000);
  pinMode(windPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(windPin), rpm_fan, FALLING);
 last_event = millis();
}

void loop() {
  temporaryRPM();
  Serial.print("czas p/obrotu:  ");
  Serial.println(half_revolutions_time);
  Serial.print("rpm:  ");
  Serial.println(rpm);
  Serial.print("km/h chwilowa:  ");
  Serial.println(moment_kmh);
    Serial.print("km/h srednia:  ");
  Serial.println(average_kmh);


}

Nadal nie jestem pewny wzoru po poprawkach:

moment_kmh = 6.28 * 0.075 * rpm * 3.6 / 60;
average_kmh = 6.28 * 0.075 * averageRpm * 3.6 / 60;

 

Z wzorami to nie pomogę, ja zawsze stosowałem coś w stylu

const float factor = ...;
  ...
predkosc = rpm * factor;

A co siedzi w factor to sie oddzielnie zastanawiałem.

W Twoim przypadku predkość nie jest wprost proporcjonalna do rpm, trzeba jakiejś funkcji która w miarę inteligentnie przeliczy rpm na m/s czy km/h.

3 godziny temu, SOYER napisał:

Czy mój wzór jest prawidlowy?

kmh = 6.28 * 0.075 * averageRpm * 3.6;

Nie do końca tak. Według mnie to V=3,6/1000*pi*R*f  [km/h

gdzie:

pi = 3,14 (około)
R promień w mm
f częstotliwość impulsów 1/s (przyjąłem 2 impulsy na obrót)

lub jeśli nie częstotliwość tylko obroty n  1/minutę

V=1,2/10000*pi*R*n  [km/h]

 

453662818_Prdkowiatromierz_2.thumb.png.3ccf25a7392e300d113c7b3535f5f968.png

 

(edytowany)
11 minut temu, Sylba napisał:

Nie do końca tak. Według mnie to V=3,6/1000*pi*R*f  [km/h

Uhm... v = 2π rf = 6.28 [1] * 0.075 [m] * (averageRPM [1/min] / 60 [s/min]) * 3.6 [(km/h)/(m/s)]


Tak jakoś by się zgadzało, ale strasznie dziwnie to zapisałeś... czemu dzielisz 3.6 przez 1000 zamiast R przez 1000, u mojej nauczycielki programowania już by wleciały ujemne punkty za brak spójności logicznej 😄

Jedyne czego kolega zapomniał to zamienić rev/min na rev/s 😉 

Edytowano przez H1M4W4R1

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...