(10-03-2020, 21:56)Robson Kerman napisał(a): Napisałem kiedyś dla kolegi z forum taki prosty licznik.
Jest dosyć dokładny,
Jak może być dokładny licznik programowy w dodatku używający millis gdzie pewne wartości się nigdy nie pojawiają?
Jakie częstotliwości i z jaką dokładnością można tak mierzyć?
Zacznę od niuansu czas wejścia w przerwanie. Gdy wykonuje się jakieś przerwanie, to z wejścia INT wykona się po nim. Na błędy rzędu nawet dziesiątek us trzeba liczyć. Tu to nie problem, bo bo licznikiem jest programowy millis. To oznacza, że teoretycznie co 1ms zmienia swoja wartość. Gdy w ten sposób trzeba zmierzyć 100Hz to licznik teoretycznie zliczy w okresie( 1/100Hz = 10ms) "aż" 10 impulsów. Zaiste, super dokładność, błąd 10%! Gdy dodać do tergo fakt, ze co jak pamiętam 125ms licznik jest korygowany o 8 to taki licznik nadaje się do liczenia czasów rzędu sekund gdy nie jest wymagana duża dokładność. Taki kod demo jak i to całe arduino.
Ten kod do liczenia prędkości obrotowej silnika, nie nadaje się co najwyżej do jego zgrubnego oszacowania na zasadzie kręci się, nie kręci, wolno, szybko, bardzo szybko.
(11-03-2020, 21:16)m72 napisał(a): Chyba trzeba będzie poświęcić jedno arduino żeby tylko mierzyło impulsy i nic poza tym i przesyłać do drugiego np przeze SPI któro będzie się zajmować wyświetlaniem wyników. :/
Podejście naprawdę "profesjonalne" godne początkującego arduinowca a nie kogoś, kto podobno bez problemu pisze programy na STM32.
W to pisanie i znajomość STM32 nie chce mi się wierzyć. Kto raz użył STM32 nie wraca do AVR tym bardziej do arduino.
Naprawdę nie mogę uwierzyć jak nad takim banałem osoba biegle znająca AVR i STM32 może się męczyć 4 dni? Wystarczy, jak już pisałem, ICP ewentualnie filtr na wejściu (nie jestem pewny na 100% czy w AVR można włączyć w trybie ICP) jak nie to bramka Schmitta lub jak już było napisane, dolnoprzepustowy RC.
Na STM32 sam odczyt okresu to banał
Można sprawdzić czy pomiar skończył się:
Kod:
if( TIM2->SR & TIM_IT_TRIGGER ) { // Czy flaga wyzwolenia ustawiona ?
TIM2->SR &= ~TIM_IT_TRIGGER; // Kasuj flagę
Okres = TIM2->CCR1;
inicjalizacja samego timera
Kod:
TIM2->ARR = UINT32_MAX;
TIM2->PSC = 0;
TIM2->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_1;
TIM2->CCER = TIM_CCER_CC2P | TIM_CCER_CC1E | TIM_CCER_CC2E;
TIM2->SMCR = TIM_SMCR_TS_2 | TIM_SMCR_TS_0 | TIM_SMCR_SMS_2;
TIM2->CR1 = TIM_CR1_CEN;
Dla AVR wygląda to jeszcze prościej ale AVR ma liczniki 16 a często tylko 8-bit, dlatego wolę STM32, który w wielu uC posiada liczniki 32-bit co pozwala mi mierzyć czasy od 10ns (taktowanie timerów 100MHz) do ponad 42 sekund bez kombinowania z preskalerami czy przerwaniami.
Zakładając, że raczej więcej niż 10tysś obr/min nie będzie, co daje ok 160Hz czyli mierzysz okres ok 6ms. W AVR timer 16-bit taktowany 8MHz w 6ms zliczy 48000 impulsów więc mieścisz się w 16-bit. Na Elektrodzie swego czasu @niveasoft pokazał prosty program w Bascom liczący okres. Ni używał funkcji Bascom do liczenia czasu bo on takowych nie posiada, wszystko robił na rejestrach. Poszukaj sobie kodu i będziesz miał praktycznie gotowca a nie bezsensowana walka z góry skazana na niepowodzenie albo kilka uC do realizacji banalnego zadania.
(11-03-2020, 21:16)m72 napisał(a): do tak pierdółkowatych projektów jak obrotomierz + jakaś temperatura itp nie będę się męczył z AS i ansi C
Czyli pierdółki na kilku uC są ok, a użycie C bez wykorzystania beznadziejnych arduinowych bibliotek czy lepszego uC już nie?
Wolisz napisać kilku kB kodu używając tego co oferuje arduino, kombinować z uśredniamiem wyniku niż zrobić to dosłownie kilkoma linijkami kodu?
Nie pisz, że zaśmiecam wątek, bo dostałeś praktycznie gotowy kod na STM32.
(11-03-2020, 21:16)m72 napisał(a): Kolega jak taki mądry to niech pomoże.
No to
pomogłem więc "rączką w górę".
(11-03-2020, 22:30)elvis napisał(a): Okazało się że w szafie z przydasiami znalazłem moduł AD9850 Podłączając do Arduino mam dokładnie takie same objawy, czyli reakcję na oba zbocza.
Z ciekawości podłączyłem oscyloskop:
Niby wszystko fajnie, ale widać że wyzwalanie wariuje, natomiast samo zbocze już idealne nie jest:
Brak lub zły filtr na wyjściu AD9850.