Skocz do zawartości

Usunięte z: Miernik długości przewodów


Anonim

Pomocna odpowiedź

Nie, nie podawaj mi tu jakichś kursów tylko jasno i wyraźnie powiedz, dlaczego do prostego zliczania impulsów trzeba używać jakiegoś timera, ze szczególnym uwzględnieniem Input Compare. I podaj kod. który będzie krótszy i bardziej zrozumiały dla początkującego. Oczywiście ograniczając się do materiałów zawartych w kursach Arduino na Forbocie.

Przypominam: zadanie polega na tym, że na wejście przychodzą sobie nieregularnie impulsy, a jak skończą przychodzić to trzeba powiedzieć ile ich było. Tyle.

Link to post

Nie mam pod ręką aktualnie żadnego arduino ale przykładowy program może wyglądać tak:

#include <avr/interrupt.h>
#include <Wire.h>              // standardowa biblioteka Arduino
#include <LiquidCrystal_I2C.h> // dolaczenie pobranej biblioteki I2C dla LCD

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Ustawienie adresu ukladu na 0x27
  
void initTimer(void) { 

	TCCR1B |= _BV(ICES1) | _BV(CS10);   //licz zbocza narastające, bez preskalera
	TIFR1 =  _BV(TOV1);					// ustaw przerwanie od przepełnienia 
	TIMSK1 = _BV(TOIE1);				// włącz generowanie przerwań

	pinMode(8, INPUT);                  // icp jako wejście
	digitalWrite(8, 0);	                // ustaw stan niski na pinie icp

}

volatile uint8_t licznik_przerwan;
ISR(TIMER1_OVF_vect) {
  licznik_przerwan++; 
}

void reset(void){
   ICR1 = 0; 
   licznik_przerwan = 0;
}

void setup() {
	
    Serial.begin(9600);
    lcd.begin(16, 2);               // Inicjalizacja LCD 2x16
    pinMode(4, INPUT_PULLUP);       // reset pin


    initTimer();
    attachInterrupt(digitalPinToInterrupt(4), reset, FALLING); // ;)

    
}

void loop(){

uint32_t licznik_impulsow = 0;

/// jakiś kod

delay(300);

licznik_impulsow = (0xFFFF * licznik_przerwan) + ICR1; // ICR1 jest 16-bitowy
Serial.println(licznik_impulsow);
lcd.clear();                  // Czysci ekran
lcd.setCursor(1, 0);          // Ustawienie kursora w pozycji 1,0 (drugi wiersz, pierwsza kolumna)
//lcd.print((licznik_impulsow *15) / 10); //wyswietla dane
lcd.print(licznik_impulsow);
    

}

Trzeba tylko przełączyć pin czujnika na 8 czyli icp i powinno śmigać.

Link to post

Uważasz, że:

10 minut temu, atMegaTona napisał:

TCCR1B |= _BV(ICES1) | _BV(CS10);

 

jest zrozumiałe dla gościa, który właśnie zaczyna się uczyć C++? Poza tym kod miał być krótszy, a nie dłuższy.

  • Lubię! 1
Link to post

Jeszcze jedna uwaga względem Input Compare, jeśli nadajnik impulsów ma tendencję do drgania styków itp, to jest możliwość włączenie funkcji noise canceler ustawiając dodatkowo bit TCCR1B |= _BV(ICNC1);  Wtedy wejście jest próbkowane wielokrotnie, po szczegóły odsyłam do dokumentacji.

http://ww1.microchip.com/downloads/en/devicedoc/2503s.pdf

@ethanak, przecież jest krótszy. Ponadto pozwala zupełnie się nie przejmować zliczaniem impulsów a samego delaya można zastąpić funkcją millis pod ifem a w pętli głównej robić cokolwiek innego nie zastanawiając się czy się zdąży zliczać impulsy na czas bo się zliczają same.

Link to post
14 minut temu, atMegaTona napisał:

samego delaya można zastąpić funkcją millis

Po grzyba tam jakiś delay?

 

16 minut temu, atMegaTona napisał:

przecież jest krótszy

Nie jest.

16 minut temu, atMegaTona napisał:

pozwala zupełnie się nie przejmować zliczaniem impulsów [...]a w pętli głównej robić cokolwiek innego nie zastanawiając się czy się zdąży zliczać impulsy na czas bo się zliczają same.

A co robi mój program?

 

Link to post

Ja nie twierdzę, że Twoje rozwiązanie jest złe, przedstawiłem po prostu inne. Imput Compare powstał z myślą o takich właśnie zastosowaniach. Podstawową różnicą pomiędzy tymi rozwiązaniami jest ilość generowanych przerwań.  W przypadku przerwania od zmiany stanu przerwanie jest generowane co impuls, natomiast w przypadku input compare co 65535 impulsów. Można oczywiście włączyć generowanie co impuls ale nie widzę w tym sensu w tym konkretnym przypadku jeśli można rzadziej.

Dla jasności funkcja arduino

pinMode(4, INPUT_PULLUP);

robi dokładnie to samo co odwołania do rejestru:

DDRD &= ~_BV(PD4);

PORTD |= _BV(PD4);

Po prostu inna metodologia, używanie funkcji arduino jest zazwyczaj łatwiejsze i wygodniejsze ale też najczęściej dłużej trwa i więcej pamięci zużywa.

Tak samo z tą funkcją

attachInterrupt(digitalPinToInterrupt(4), reset, FALLING);

Ustawia i włącza ona przerwanie od zmiany stanu pinu, w odróżnieniu jednak od jawnego odwołania do wektora pobiera adres mającej się wykonać w przerwaniu funkcji co z kolei wydłuża czas egzekucji przerwania. Stosowanie jawnego odwołania do wektora przerwania jak w tym przypadku ISR(TIMER1_OVF_vect) sprawia, że kod zawarty w funkcji wektora wykonuje się najszybciej jak się da. Funkcja ta również się odwołuje w swojej implementacji do wektora przerwania ale używa wskaźnika do którego przypisuje podany jako jeden z argumentów adres funkcji, która ma się wykonać i wywołuje ją z funkcji wektora przerwania przez ten wskaźnik

Niestety niektóre biblioteki arduino wykorzystują urządzenia peryferyjne mikrokontrolera co może powodować konflikty niejako uniemożliwiając wykorzystanie tych urządzeń według własnych potrzeb.

Link to post
57 minut temu, ethanak napisał:

Nie bardzo rozumiem tok Twojego rozumowania, ale tutaj 1 impuls to ok. 1.5 cm, dlaczego chcesz mierzyć coś z dokładnością do kilometra... możesz to jakoś przybliżyć?

nie zrozumieliśmy się, do żadnego kilometra tylko co do impulsu. to przerwanie od przepełnienia to zabezpieczenie gdyby przyszło koledze do głowy mierzyć kilometry tego przewodu.

Być może się nie nadaję ale kiedy ktoś robiąc za nauczyciela przeczy rzeczywistości to jeszcze gorzej niż miałby nauczać nieporadnie.

edit:

W funkcji reset powinno być zerowanie zmiennej licznik_impulsow a zmienna powinna być globalna ze względu na użycie w przerwaniu.

volatile uint8_t licznik_impulsow;

void reset(void){
   ICR1 = 0; 
   licznik_impulsow = 0;
}

 

Edytowano przez Anonim
Link to post

Jest jeszcze jeden niuans dotyczący 16-bitowych i większych zmiennych w 8-bitowych systemach ale to może przy innej okazji.

Link to post
26 minut temu, ethanak napisał:

I dlaczego bez ifów? Czy uważasz, że miernik musi koniecznie wyświetlać stan sprzed 300 milisekund? Jeśli tak to dlaczego nie bieżący?

Wyświetla bieżący w chwili odczytu, istnieje jakiś ważny powód dla którego powinno się go odczytywać i wyświetlać częściej?

Mam wrażenie drogi@ethanak -u, że nie rozumiesz jak działa ten input compare albo sobie dworujesz beztrosko. Ale pozwól, że wyjaśnię. Otóż działa on jak każdy inny timer z tą różnicą, że źródłem jego taktowania są zbocza narastające lub opadające na pinie wejściowym a jego rejestr można w dowolnej chwili odczytać, zmienić i wyzerować. Tak jak inne timery można włączyć generowanie przez niego przerwań różnego typu o czym polecam poczytać w załączonej do mikrokontrolera dokumentacji.

Link to post
7 godzin temu, atMegaTona napisał:

Wyświetla bieżący w chwili odczytu,

No wiesz co...

Jeśli w kodzie masz delay(300) to dla mnie oznacza, że na wyświetlaczu jest wynik sprzed od 0 do 300 milisekund. A 300 milisekund to prawie dokładnie tyle, ile trwa powiedzenie słowa "długo". I nie wyświetla wyniku w chwili odczytu (mój kod owszem).

7 godzin temu, atMegaTona napisał:

Mam wrażenie drogi@ethanak -u, że nie rozumiesz jak działa ten input compare albo sobie dworujesz beztrosko

A ja mam wrażenie, że chcesz się popisać przed naszym nowym kolegą jaki to jesteś mądry i wszystko wiesz.

7 godzin temu, atMegaTona napisał:

Tak jak inne timery można włączyć generowanie przez niego przerwań różnego typu

Więc w czym do k... nędzy jest ten Twój kod lepszy od mojego? W obu są przerwania, w obu w przerwaniu zwiększa się jakiś licznik, tyle że u mnie jest to w przerwaniu zewnętrznym a u Ciebie od przepełnienia timera. Gdybyś się pozbył w ogóle przerwania - o, to może było by coś. Gdyby trzeba było liczyć impulsy o częstotliwości przekraczającej możliwości obliczeniowe atmegi - wtedy to by miało sens. A tak? Tylko niepotrzebnie angażujesz timer do czegoś, co równie dobrze może wykonywać procek.

W dodatku twierdzisz że Twój kod jest krótszy i prostszy... skontaktuj mnie ze swoim dilerem bo też chcę coś takiego zajarać.

Skończmy tę bezsensowną dyskusję albo załóż sobie wątek o wyższości przerwań timera nad przerwami zewnętrznymi - tam sobie pogadajmy bez śmiecenia na czyimś podwórku.

 

Link to post
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

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