Wpis z mikrobloga

Robię sobie do auta taki komputer pokładowy, projekt jak i oprogramowanie nie jest moje, tylko z neta. Ja go tylko troche przerabiam na własne potrzeby, inny wyświetlacz, arduino duo zamiast uno, dwa czujniki temperatury itp.
Komputerek liczy spalanie, prędkość, ilość przejechanych kilometrów i takie tam. Wyniki są całkiem dokładne np. ilość przejechanych kilometrów. Problem jest z wyświetlaniem prędkość czy spalania.
Chodzi o to, że, np. jadąc ze stałą prędkością 60km/h, arduino pokazuje mi te 60km/h ale co chwilę to się zmienia i pokazuje nagle 63km/h później przez chwilę znowu 60km/h i nagle 63km/h.
Wiem że problem leży w metodzie obliczania prędkości.
Arduiino zlicza ilość impulsów w ciągu sekundy i z tego oblicza prędkość, a że w sekundzie zmieści się 100 impulsów a raz 101 więc stąd te zmiany w wyświetlanej prędkości.
Zna ktoś jakiś sposób aby te obliczenia były bardziej dokładne, czy chociaż żeby na wyświetlaczu wyglądało to przyzwoicie?
Próbowałem moving average ale zmiany nadal występowały tylko były wolniejsze.
Tu jest oryginalny kod jak i projekt:
https://www.instructables.com/id/How-to-Build-a-Bi-Fuel-LPG-Unleaded-Trip-Computer-/

#arduino #sterowniki #forbot #matematyka #zainteresowania #diy #samochody #majsterkowanie #programista15k #programowanie #elektronika #pomocy #codeschool #naukaprogramowania
  • 25
@Liberator19: w każdej sekundzie zapamiętuj kiedy była ostatnia próbka i zamiast dzielić przez 1000 milisekund za każdym razem - dziel przez (czas ostatniej próbki tej sekundy - czas ostatniej próbki z poprzedniej sekundy).

Jeśli problemem jest nierówne próbkowanie to powinno pomóc. Jeśli problemem jest błąd pomiaru to musisz kombinować z ruchomą średnią (pobaw się parametrami).

I tak - ruchoma średnia zawsze zwiększa czas reakcji wyświetlacza na pomiar, więc przy przyśpieszaniu czy
@tell_me_more: Może dokładniej opiszę już istniejący kod:
Każdy impuls wywołuje przerwanie, arduino go zapisuje dodaje do reszty. Co sekundę występuje ( TIMER1 overflow interrupt) które wywołuje funkcję która oblicza prędkość:
void instantSpeed()
{
speed = (vsspulsedistance * vss_pulses * 3600);
}
Ilość impulsów w ciągu sekundy razy współczynnik, razy 3600.
Cały kod na pastebin:
https://pastebin.com/UZZCgPJS
@Liberator19: no czyli dobrze myślałem, tylko jednostki masz inne więc mnożysz * ilość sekund w godzinie żeby otrzymać prędkość w km/h.

Problem wynika z tego, że ilość pulsów nie mieści się równo w sekundzie. Np masz pulsy co 0.4 sekundy jedziesz ze stałą prędkością, i dostajesz:

distance() //t=0.4
distance() //t=0.8
instantSpeed() //t=1.0 pulsów 2
distance() //t=1.2
distance() //t=1.6
distance() //t=2.0
instantSpeed() //t=2.0 pulsów 3
distance() //t=2.4
distance() //t=2.8
instantSpeed() //t=3.0 pulsów
@tell_me_more: Doskonale opisałeś problem z którym mam doczynienia. A co do drugiej części, jeśli dobrze zrozumiałem, arduino normalnie tak jak wcześniej będzie zliczać impulsy oraz do tego odmierzać czas (od jednego przerwania do następnego), gdy ten czas zbliży się do sekundy, wywołam funkcję odpowiedzialną za obliczanie prędkości która na podstawie ilości impulsów i czasu w jakim one wstąpiły obliczy prędkość.
Czas i impulsy muszą być liczone cały czas, czy mogą być
@Mof1: Nie ma bardzo czego wymieniać, najdroższe to jest arduino mego ( pomyłka w pierwszym wpisie), równie dobrze możesz zrobić to na uno tak jak koleś który to wymyślił. Wyświetlacz to koło chyba 10zł, trochę kabli, jakaś przetwornica obniżająca zasilanie z 12V do 5v ( nie jest konieczna) i to wszystko.
Zobacz sobie jeszcze Mpguino, bardzo podobny projekt tylko znacznie bardziej zaawansowany, kod napisany bez żadnych bibliotek, nie miałem żadnych szans
@Liberator19: poprawiłem (na sucho, bez kompilowania i testowania, całkiem możliwe że są bugi).

W skrócie zmieniłem:
- dodałem zmienną last_speed_calculation_time
- dodałem ustawianie jej w setup()
- wywaliłem wywoływanie instantSpeed z obsługi przerwania timera sekundowego
- przeniosłem zerowanie vccpulses do instantSpeed()
- dodałem sprawdzanie czasu w distance(), wywoływanie instantSpeed() i uaktualnianie last_speed_calculation_time jak minęła sekunda
- dodałem wyliczanie dt (różnicy czasu między ostatnim wywołaniem instantSpeed i aktualnym) wewnątrz distance()
- dodałem
@tell_me_more: Sprawdziłem dziś na szybko, symulując drugim arduino sygnał z czujnika, stała prędkość bez żadnych nagłych zmian, tylko jedno, przy braku sygnału nie wraca do zera tylko pokazuje ostatnią obliczoną prędkość, pewnie dlatego że do zerowania potrzebne jest przerwanie, a bez sygnału nie będzie przerwania. Ciekaw jestem jak się to będzie zachowywać w samochodzie. Tak czy inaczej, super rozwiązanie, jeszcze raz wielkie dzięki Ci mirku. Spróbuje to zaimplementować w części kodu
@Liberator19: no tak, racja, zapomniałem o zerowaniu jak nie ma przerwań :) - trzeba jeszcze w tej obsłudze przerwania timera sekundowego dodać warunek, że jak last_speed_calculation_time było dawniej niż np 2 albo 1.5 sekundy temu - to trzeba ustawić speed na 0.

wystarczy dodać

unsigned long time = millis();
unsigned long dt = time - last_speed_calculation_time;
if (dt > 2000) { //brak impulsow przez 2s oznacza ze stoimy
speed = 0;
PS te moje poprawki mogą źle działać, jak licznik millis() się przekręci i przekroczy 0. To się dzieje po mniej więcej 50 dniach działania arduino bez wyłączania. Jeśli to jest problem - to trzeba dodać odpowiednie ify wszędzie tam gdzie porównujemy albo odejmujemy 2 wartości pobrane z millis() - czyli u nas tam gdzie porównujemy time, dt, albo last_speed_calculation_time.

Prawdopodobnie błąd objawi się tym, że po 50 dniach ciągle włączonego arduino
@tell_me_more: Próbowałem dodać ten kod do obliczeń aktualnego zużycia paliwa, niestety bez sukcesu.
Wszystko niby działa, dostaje wynik, tylko z jakiegoś powodu on się cały czas zmienia. Wydaje mi się że sytuacja jest analogiczna do tej z prędkością, jedyna różnica w tym że tutaj jest obliczany czas otwarcia wtryskiwacza w ciągu sekundy zamiast dodawania impulsów.
@Liberator19: obczajasz gita? Wrzuć kod na githuba to mogę coś pomóc bo tak wysyłać za każdym razem całość i pisać co się zmienia to strasznie niewygodnie.

Ze zużyciem paliwa może sprawa tak wygląda, że w każdej sekundzie jest inne? Najlepiej byłoby logować gdzieś dane i policzyć ręcznie żeby sprawdzić czy dobrze wychodzi i jaki jest problem.