Arduino Leonardo - jak zrobić miernik prędkości do samochodu

Masz problem z Arduino? Tutaj możesz szukać pomocy.
ODPOWIEDZ
gbk
Młodszy majsterkowicz
Posty: 9
Rejestracja: 2 lip 2015, 12:04

Arduino Leonardo - jak zrobić miernik prędkości do samochodu

Post autor: gbk » 2 lip 2015, 12:11

Cześć, jestem początkującym jeśli chodzi o arduino i C.
Chcę zrobić komputerek pokładowy do auta. Jak na razie poległem na pierwszym problemie - licznik prędkości.
Wyprowadziłem kabel VSS z auta, wysyła on 4000 impulsów (ok 4.6V) na jedną milę. W jaki sposób to zliczyć i zamienić na km/h?
Z góry dziękuje i pozdrawiam

Co miesiąc do wygrania nagrody o wartości ponad 1600 zł!


Arturr300
Starszy majsterkowicz
Posty: 307
Rejestracja: 16 paź 2013, 17:24

Re: Arduino Leonardo - jak zrobić miernik prędkości do samoc

Post autor: Arturr300 » 2 lip 2015, 13:37

Napisałeś już jakiś kod?
bicker
Majsterkowicz
Posty: 71
Rejestracja: 9 gru 2013, 09:53

Re: Arduino Leonardo - jak zrobić miernik prędkości do samoc

Post autor: bicker » 2 lip 2015, 13:46

gbk
Młodszy majsterkowicz
Posty: 9
Rejestracja: 2 lip 2015, 12:04

Re: Arduino Leonardo - jak zrobić miernik prędkości do samoc

Post autor: gbk » 7 lip 2015, 18:29

Przepraszam nie było mnie.

Mam coś takiego:

Kod: Zaznacz cały

#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,5,4,3,2);
volatile int licznik;
int pin = 7;
int nr_przerwania = 4; //IRQ that matches to pin 2

void setup() {
  lcd.begin(16,2);
  lcd.setCursor (0,0);
   attachInterrupt(nr_przerwania, liczenie, FALLING);
}

void liczenie() {
  licznik++;
}

void loop() {
  lcd.setCursor (0,0);
  int wynik = licznik;
  lcd.print(wynik);
  delay(200);
  
}
Zlicza mi te impulsy jako przerwanie i wyświetla na lcd. Wygląda na to, że działa. Tylko teraz nie wiem jak napisać, abym miał wynik w km/h... Nie wiem jak się za to zabrać, trzeba odliczyć czas, ale jak...
gbk
Młodszy majsterkowicz
Posty: 9
Rejestracja: 2 lip 2015, 12:04

Re: Arduino Leonardo - jak zrobić miernik prędkości do samoc

Post autor: gbk » 8 lip 2015, 22:33

Wiem jak to ma wyglądać logicznie, jednak nie wiem jak mam to zapisać... Program ma sprawdzać co sekundę ile impulsów dostał i przeliczyć to na prędkość. O ile z algorytmem przeliczania nie będę miał problemów o tyle z przerwaniem i timerem będę... Mógłby ktoś pomóc?
siwy2411
Młodszy majsterkowicz
Posty: 29
Rejestracja: 4 cze 2013, 14:56

Re: Arduino Leonardo - jak zrobić miernik prędkości do samoc

Post autor: siwy2411 » 9 lip 2015, 18:50

spróbuj może ugryźć to z innej strony.
sygnał generowany z samochodu ma prawdopodobnie stałe wypełnienie równe około 50%. zmienna natomiast jest częstotliwość tego sygnału (a więc czasy trwania stanów wysokich i niskich). zawarta w Arduino funkcja "pulsein" https://www.arduino.cc/en/Reference/pulseIn powinna pozwolić Ci zmierzyć czas trwania poszczególnych stanów w sygnale, z czego będziesz w stanie wyznaczyć aktualną prędkość.
gbk
Młodszy majsterkowicz
Posty: 9
Rejestracja: 2 lip 2015, 12:04

Re: Arduino Leonardo - jak zrobić miernik prędkości do samoc

Post autor: gbk » 9 lip 2015, 18:58

@up

Tylko, że czas trwania mi do niczego nie potrzebny, te impulsy są zawsze takiej samej długości. Owszem funkcja pulsein moze mi się przydać, ale do obliczenia spalania.

Mam coś takiego:

Kod: Zaznacz cały

#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,5,4,3,2);
volatile int IRQcount;
volatile int IRQcounted;
int pin = 7;
int pin_irq = 4; 

void setup() {
  lcd.begin(16,2);
  attachInterrupt(pin_irq, TIMER1_OVF_vect, FALLING);
  TCCR1A = 0x00;
  TCNT1 = 3036; // 64 for 1/4 of sec 
  TCCR1B |= ((1 << CS10) | (1 << CS11));
  TIMSK1 |= (1 << TOIE1);
}

ISR(TIMER1_OVF_vect) {

TCNT1 = 3036;

  IRQcount++;
  IRQcounted = IRQcount;
  IRQcount == 0;

TCNT1 = 3036;
}



void loop() {

  int result = IRQcounted;
  float speed = (result/4000)*3600
  lcd.setCursor (0,0);
  lcd.print(speed);
  delay(200);
   
}
Jednak nie chce to się skompilować - wywala błąd w attachInterrupt(pin_irq, TIMER1_OVF_vect, FALLING); . Czy ktoś mi może wytłumaczyć w jaki sposób powinno wyglądać te przerwanie z timerem? Idea jest taka, żeby timer wywoływał przerwanie co sekundę i zliczał impulsy w każdej z sekund.
stiven
Złota rączka
Posty: 1598
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Arduino Leonardo - jak zrobić miernik prędkości do samoc

Post autor: stiven » 9 lip 2015, 21:20

Przerwanie zegarowe (z timerem) to przerwanie zegarowe, a przerwanie zewnętrze - wyzwalane zmianą stanu na pinie, to już inny rodzaj przerwania i nie połączysz tego tak.

Jakbyś chciał co sekundę mieć przerwanie zegarowe, to po jego wywołaniu zliczanie musiałoby trwać też sekundę, czyli musiałbyś w inny sposób sprawdzać czy już minęła sekunda. By trzeba było dodatkowo jakoś kombinować z tymi czasami, żeby przerwania na siebie nie zaczęły nachodzić, więc ogólnie jest to pomysł bez sensu.

Najlepiej te impulsy zliczać cały czas (przez przerwanie zewnętrzne) i sprawdzać czy minęła sekunda (może to być na przykład właśnie przerwaniem zegarowym zrobione) i wtedy obliczyć prędkość (i wyzerować ilość zliczonych impulsów).

Czyli do tego pierwszego programu możesz dodać osobne przerwanie zegarowe, w którym byś właśnie robił obliczenia i zerował impulsy.
gbk
Młodszy majsterkowicz
Posty: 9
Rejestracja: 2 lip 2015, 12:04

Re: Arduino Leonardo - jak zrobić miernik prędkości do samoc

Post autor: gbk » 10 lip 2015, 11:02

Ok, dziękuje @stiven zaczynam rozumieć. Mam coś takiego:

Kod: Zaznacz cały

#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,5,4,3,2);
volatile int IRQcount;
volatile int IRQcounted;
float speedo;
int pin = 7;
int pin_irq = 4; 

void setup() {
  lcd.begin(16,2);
  attachInterrupt(pin_irq, liczenie, FALLING);
  TCCR1A = 0x00;
  TCNT1 = 3036; // 64 for 1/4 of sec 
  TCCR1B |= ((1 << CS10) | (1 << CS11));
  TIMSK1 |= (1 << TOIE1);
}

void liczenie() {
  IRQcount++;
}
ISR(TIMER1_OVF_vect) {

  TCNT1 = 3036;
  IRQcounted = IRQcount;
  speedo = ((IRQcounted/4000)*3600)*4;
  IRQcount = 0;
  TCNT1 = 3036;
}



void loop() {
  lcd.setCursor (0,0);
  lcd.print(speedo);
  lcd.setCursor (0,1);
  lcd.print(IRQcount);
  lcd.setCursor (5,1);
  lcd.print(IRQcounted);
  delay(20);
   
}
Liczniki IRQcount i IRQcounted zerują się co sekundę jednak zmienna speedo jest nadal pusta. Wyświetla 0.00, nie chce wyświetlić prędkości. Co jest nie tak?
stiven
Złota rączka
Posty: 1598
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Arduino Leonardo - jak zrobić miernik prędkości do samoc

Post autor: stiven » 10 lip 2015, 12:05

Tak jest, bo do obliczenia floata korzystasz z inta. Licząc na intach na przykład 100/4000 będzie równe 0, więc cały wynik też będzie równy 0. Trzeba "pokazać" kompilatorowi, że chcesz uzyskać wynik typu float, przez rzutowanie typu:

Kod: Zaznacz cały

  speedo = ((float(IRQcounted)/4000)*3600)*4;
albo w ten sposób:

Kod: Zaznacz cały

  speedo = ((IRQcounted/4000.0)*3600)*4;
gbk
Młodszy majsterkowicz
Posty: 9
Rejestracja: 2 lip 2015, 12:04

Re: Arduino Leonardo - jak zrobić miernik prędkości do samoc

Post autor: gbk » 10 lip 2015, 12:27

Super, dziękuje. Teraz pozostaje zrobić prawidłowe obliczenie prędkości, bo to pokazuje za niskie prędkości (bez tego *4, bo myślałem, że ten timer wywołuje przerwanie co 1/4 sec).
Czy może ktoś potwierdzić mój tok rozumowania, że przerwania są już zrobione dobrze tylko teraz muszę pomyśleć jak obliczyć prędkość z tych danych?
stiven
Złota rączka
Posty: 1598
Rejestracja: 13 maja 2014, 08:47
Lokalizacja: Zielona Góra

Re: Arduino Leonardo - jak zrobić miernik prędkości do samoc

Post autor: stiven » 10 lip 2015, 12:55

Nie umiem tych przerwań ustawiać. Zobacz jak to będzie wyglądało z wykorzystaniem millis().

Kod: Zaznacz cały

#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,5,4,3,2);
volatile int IRQcount;
volatile int IRQcounted;
float speedo;
int pin = 7;
int pin_irq = 4; 
unsigned long czas = millis();

void setup() {
  lcd.begin(16,2);
  attachInterrupt(pin_irq, liczenie, FALLING);
}

void liczenie() {
  IRQcount++;
}

void loop() {

  if(millis() - czas > 1000)
  {
    IRQcounted = IRQcount;
    speedo = ((IRQcounted/4000.0)*3600);
    IRQcount = 0;
    czas = millis();
  }

  lcd.setCursor (0,0);
  lcd.print(speedo);
  lcd.setCursor (0,1);
  lcd.print(IRQcount);
  lcd.setCursor (5,1);
  lcd.print(IRQcounted);
  delay(20);
}

Znaczenie może mieć też ten trzeci parametr w ustawianiu przerwania zewnętrznego, zbocze, przy którym jest wyzwalane przerwanie.
ODPOWIEDZ

Strony partnerskie: