RTV forum PL | NewsGroups PL

Sprawdzanie działania kodu do pomiaru częstotliwości sinusoidy 2-150Hz na ATmega128

AVR ATmega, pomiar częstotliwości przebiegu, prośba o spraw

NOWY TEMAT

elektroda NewsGroups Forum Index - Elektronika Polska - Sprawdzanie działania kodu do pomiaru częstotliwości sinusoidy 2-150Hz na ATmega128

Goto page 1, 2, 3  Next

Robbo
Guest

Wed Feb 09, 2011 1:54 pm   



Witam,

Jakiś czas temu pytałem o sprawy związane z pomiarem częstotliwości
sinusoidy o częstotliwości od 2 do 150Hz oraz zmiennej amplitudzie (od kilku
V do 400V). Mam już układ elektroniczny przekształcający sinusoidę na
prostokąt (brana jest pod uwagę tylko dodatnia połówka, a ujemna jest
usuwana). Jest tu kilka rezystorów, mostek, tranzystor, dioda oraz
transformatorek. (Może działanie tego układu da się jeszcze ulepszyć, ale to
w sumie nie jest teraz tematem). Uzyskany z dodatniej połówki sinusoidy
prostokąt jest podawany na nóżkę PE7(INT7) mikrokontrolera ATmega128 (kwarc
16MHz). Dokładność pomiaru, którą chciałbym osiągnąć to 0,2Hz przy
częstotliwości 50Hz. Chciałem Was prosić o sprawdzenie mojego kodu, którego
zadaniem jest nieustanne mierzenie czasu trwania dodatniej połówki, a
następnie wypisywanie tej wartości na wyświetlacz. Kod, który napisałem
wygląda na działający, ale może ma jakiś ukryty błąd.

volatile unsigned long int timer = 100000;
volatile short actualTime;

../* procedura wywoływana 100000 razy na sekundę */
SIGNAL (SIG_OUTPUT_COMPARE2)
{
cli();

if (timer < 100000)
timer++;

sei();
}

/* wyzwalane zboczem narastającym i opadającym */
SIGNAL (SIG_INTERRUPT7)
{
cli();

if (PINE & PINE7) {
timer = 0;
TCCR2 = 0; // stop timera
TCNT2 = 0; // zerowanie licznika
TCCR2 = _BV(WGM21) | // start timera
_BV(C21); // (prescaler Cool
} else {
actualTime = timer;
}

sei();
}

int main(void)
{
char s[16];

initLCD();

cli();

EICRB |= _BV(ISC70);
EIMSK |= _BV(INT7);

TCCR2 = 0;
OCR2 = 19;
TIFR |= _BV(OCF2);
TIMSK |= _BV(OCIE2);
while (ASSR & _BV(OCR2UB))
;

sei();

while (1) {

if (timer == 100000)
LCDshowString("---");
else {
sprintf(s, "%d ", actualTime);
LCDshowString(s);
}
}

return 0;
}

***
Jak to się sprawuje:
Jako źródło sygnału podłączyłem po prostu zasilanie sieciowe 230V/50Hz.
Wczoraj wieczorem przed godziną 22 liczba na wyświetlaczu wynosiła 996
(ostatnia cyfra niekiedy migała na "5"). Potem zaczęło to rosnąć... 997/8. O
godzinie 22 było jakieś 999. Potem zaczęło spadać do 996. Teraz (godzina
13:40) mam 996/7.
***

W szczególności chciałem zapytać o to, czy poprawnie zastosowałem cli() i
sei() w procedurach obsługi przerwań. Ponadto chciałem zapytać, czy kod
wewnątrz while(1) jest poprawny i czy nie lepiej byłoby zapisać to tak:

while (1) {
unsigned long int timerLatch;
short actualTimeLatch;

cli();
timerLatch = timer;
actualTimeLatch = actualTime;
sei();

if (timerLatch == 100000)
LCDshowString("---");
else {
sprintf(s, "%d ", actualTimeLatch);
LCDshowString(s);
}
}

Chodzi o sytuację, w której w pętli głównej jest przetwarzana wartość
zmiennej timer albo actualTime (np. został odczytany pierwszy bajt) i w
trakcie nastąpi przerwanie, zmieni wartość zmiennej, obsługa przerwania się
skończy, zostanie dokończone przetwarzanie zmiennej timer albo actualTime --
wartość chyba będzie błędna (jeden bajt z poprzedniej wartości, reszta
bajtów po aktualizacji w przerwaniu).

Z góry dziękuję za rady.

Robbo

RoMan Mandziejewicz
Guest

Wed Feb 09, 2011 2:02 pm   



Hello Robbo,

Wednesday, February 9, 2011, 1:54:01 PM, you wrote:

Quote:
Jakiś czas temu pytałem o sprawy związane z pomiarem częstotliwości
sinusoidy o częstotliwości od 2 do 150Hz oraz zmiennej amplitudzie (od kilku
V do 400V). Mam już układ elektroniczny przekształcający sinusoidę na
prostokąt (brana jest pod uwagę tylko dodatnia połówka, a ujemna jest
usuwana). Jest tu kilka rezystorów, mostek, tranzystor, dioda oraz
transformatorek. (Może działanie tego układu da się jeszcze ulepszyć, ale to
w sumie nie jest teraz tematem). Uzyskany z dodatniej połówki sinusoidy
prostokąt jest podawany na nóżkę PE7(INT7) mikrokontrolera ATmega128 (kwarc
16MHz). Dokładność pomiaru, którą chciałbym osiągnąć to 0,2Hz przy
częstotliwości 50Hz. Chciałem Was prosić o sprawdzenie mojego kodu, którego
zadaniem jest nieustanne mierzenie czasu trwania dodatniej połówki, a

Ja bym liczył czas pomiedzy dwoma narastającymi zboczami. Ale ja
herbatę cukrem...

[...]

--
Best regards,
RoMan mailto:roman@pik-net.pl
Nowa strona: http://www.elektronika.squadack.com (w budowie!)

Michoo
Guest

Wed Feb 09, 2011 3:39 pm   



W dniu 09.02.2011 13:54, Robbo pisze:
Quote:
W szczególności chciałem zapytać o to, czy poprawnie zastosowałem cli()
i sei() w procedurach obsługi przerwań.
Nie.


Jeżeli nie deklarujesz przerwań explicite jako nieblokujących to one
dbają o wyłączność za Ciebie. Pisząc sei na końcu przerwania umożliwiasz
odpalenie przerwania po 2 cyklach a prawdopodobnie wyjście z przerwania
trwa chwilę dłużej - przy dużym nagromadzeniu przerwań do obsługi
skończy się to przepełnieniem stosu.

--
Pozdrawiam
Michoo

Marcin Wasilewski
Guest

Wed Feb 09, 2011 3:56 pm   



Użytkownik "Robbo" <yyy@mmm.com> napisał w wiadomości
news:4d528e6b$0$2436$65785112@news.neostrada.pl...

Quote:
W szczególności chciałem zapytać o to, czy poprawnie zastosowałem cli() i
sei() w procedurach obsługi przerwań.

Widzisz, tak to jest jak się nigdy żadnego kodu w assemblerze na AVR-a nie
napisało.

Otóż procesor AVR wchodząc w obsługę przerwania sam wyłącza przerwania. Więc
stan jest taki, że do czasu zakończenia obsługi aktualnego przerwania,
obsługa kolejnych przerwań jest wyłączona.

Więc cli() po wejściu w obsługę przerwania nie ma sensu (bo przerwania już
są wyłączone), natomiast sei() dajesz wtedy jak chcesz włączyć ręcznie
obsługę przerwań, co oczywiście jest możliwe, tylko na stos trzeba uważać
(jeśli tych przerwań jest dużo w jednostce czasu).

sei() na końcu też nie ma sensu, ponieważ procedury obsługi przerwania nie
opuszcza się poprzez ret, tylko poprzez reti, będące niczym innym jak
połączeniem: ret + sei.

Cezar
Guest

Wed Feb 09, 2011 4:10 pm   



On 09/02/2011 13:02, RoMan Mandziejewicz wrote:
Quote:
Hello Robbo,

Wednesday, February 9, 2011, 1:54:01 PM, you wrote:

Jakiś czas temu pytałem o sprawy związane z pomiarem częstotliwości
sinusoidy o częstotliwości od 2 do 150Hz oraz zmiennej amplitudzie (od kilku
V do 400V). Mam już układ elektroniczny przekształcający sinusoidę na
prostokąt (brana jest pod uwagę tylko dodatnia połówka, a ujemna jest
usuwana). Jest tu kilka rezystorów, mostek, tranzystor, dioda oraz
transformatorek. (Może działanie tego układu da się jeszcze ulepszyć, ale to
w sumie nie jest teraz tematem). Uzyskany z dodatniej połówki sinusoidy
prostokąt jest podawany na nóżkę PE7(INT7) mikrokontrolera ATmega128 (kwarc
16MHz). Dokładność pomiaru, którą chciałbym osiągnąć to 0,2Hz przy
częstotliwości 50Hz. Chciałem Was prosić o sprawdzenie mojego kodu, którego
zadaniem jest nieustanne mierzenie czasu trwania dodatniej połówki, a

Ja bym liczył czas pomiedzy dwoma narastającymi zboczami. Ale ja
herbatę cukrem...

truskawki :P

.... no chyba ze znamy inne dowcipy

c.

RoMan Mandziejewicz
Guest

Wed Feb 09, 2011 4:46 pm   



Hello Cezar,

Wednesday, February 9, 2011, 4:10:31 PM, you wrote:

[...]

Quote:
zadaniem jest nieustanne mierzenie czasu trwania dodatniej połówki, a
Ja bym liczył czas pomiedzy dwoma narastającymi zboczami. Ale ja
herbatę cukrem...
truskawki Razz

Truskawki to ja ze śmietaną, najlepiej bitą.

Quote:
... no chyba ze znamy inne dowcipy

To nie dowcip.

--
Best regards,
RoMan mailto:roman@pik-net.pl
Nowa strona: http://www.elektronika.squadack.com (w budowie!)

4CX250
Guest

Wed Feb 09, 2011 6:50 pm   



Nie bawiłem się jeszcze przerwaniami w atmedze i muszę zaraz sprawdzić
w nocie jak jest ale zapytam wybiegiem a czy aby nie ma przypadkiem
zatrzasku przerwań przychodzących podczas obsługi przerwań i
priorytetów przerwań?

Marek

4CX250
Guest

Wed Feb 09, 2011 6:58 pm   



Użytkownik "Robbo" <yyy@mmm.com> napisał w wiadomości
news:4d528e6b$0$2436$65785112@news.neostrada.pl...

A może wykorzystac dwa liczniki.
Jeden zliczający uformowane impulsy a drugi z autoresetem wyzwalający
przerwanie co określony czas. W przerwaniu sprawdzałbym stan licznika
zliczającego, następnie kasował go i opuszczał przerwanie.

Marek

4CX250
Guest

Wed Feb 09, 2011 7:00 pm   



Użytkownik "RoMan Mandziejewicz" <roman@pik-net.pl> napisał w
wiadomości news:514110838.20110209164612@pik-net.pl...
Quote:
Hello Cezar,

Wednesday, February 9, 2011, 4:10:31 PM, you wrote:

[...]

zadaniem jest nieustanne mierzenie czasu trwania dodatniej
połówki, a
Ja bym liczył czas pomiedzy dwoma narastającymi zboczami. Ale ja
herbatę cukrem...
truskawki :P

Truskawki to ja ze śmietaną, najlepiej bitą.

... no chyba ze znamy inne dowcipy

To nie dowcip.

Pan policjant widzę chyba po służbie bo też pozwala sobie na NTG.
Wiem wiem. Jedzie pan na sygnale jako pojazd uprzywilejowany.

Marek

Grzegorz Kurczyk
Guest

Wed Feb 09, 2011 7:40 pm   



W dniu 09.02.2011 13:54, Robbo pisze:
Quote:
Witam,

Jakiś czas temu pytałem o sprawy związane z pomiarem częstotliwości
sinusoidy o częstotliwości od 2 do 150Hz oraz zmiennej amplitudzie (od
kilku V do 400V). Mam już układ elektroniczny przekształcający sinusoidę
na prostokąt (brana jest pod uwagę tylko dodatnia połówka, a ujemna jest
usuwana). Jest tu kilka rezystorów, mostek, tranzystor, dioda oraz
transformatorek. (Może działanie tego układu da się jeszcze ulepszyć,
ale to w sumie nie jest teraz tematem). Uzyskany z dodatniej połówki
sinusoidy prostokąt jest podawany na nóżkę PE7(INT7) mikrokontrolera
ATmega128 (kwarc 16MHz). Dokładność pomiaru, którą chciałbym osiągnąć to
0,2Hz przy częstotliwości 50Hz. Chciałem Was prosić o sprawdzenie mojego
kodu, którego zadaniem jest nieustanne mierzenie czasu trwania dodatniej
połówki, a następnie wypisywanie tej wartości na wyświetlacz. Kod, który
napisałem wygląda na działający, ale może ma jakiś ukryty błąd.


Witam
Na wstępie to się zapytam, na czym Koledze tak naprawdę zależy ? Na
pomiarze czasu (okresu) czy częstotliwości ? Bo pisze Kolega o
"dokładności 0,2Hz" i o "wyświetlaniu czasu trwania dodatniej połówki".
Ponieważ zakres częstotliwości jest stosunkowo niewielki, można to
zrobić na dwa sposoby i kilka wariacji Wink.
1. Pomiar ilości impulsów w stałym przedziale czasu. Przy wymaganej
rozdzielczości 0,2Hz pomiar musiałby trwać co najmniej 5 sekund. Metod
realizacji jest wiele. Przy tak małej częstotliwości zbocze sygnału
mierzonego można sobie wykrywać programowo w pętli (pod warunkiem, że w
systemie nie istnieją przerwania, których obsługa zajmuje ponad 6ms).
Jako bramkę czasu najprościej wykorzystać któryś z timerów. Bardziej
elegancko liczyć zbocza w obsłudze zewnętrznego przerwania. Można
zliczać impulsy sprzętowo za pomocą licznika 16-bitowego, a 8-bitowym
realizować bramkę czasu. Można również całkowicie sprzętowo z
wykorzystaniem rejestru ICR licznika 16-bitowego i licznika 8-bitowego
generującego na wyjściu OCx impulsy o czasie bramkowania.
2. Pomiar czasu między impulsami (okresu). Tu aż się prosi wykorzystać
Input Capture Register.

Pozdrawiam
Grzegorz

Robbo
Guest

Wed Feb 09, 2011 11:44 pm   



Quote:
Otóż procesor AVR wchodząc w obsługę przerwania sam wyłącza przerwania.
Więc stan jest taki, że do czasu zakończenia obsługi aktualnego
przerwania, obsługa kolejnych przerwań jest wyłączona.

Więc cli() po wejściu w obsługę przerwania nie ma sensu (bo przerwania już
są wyłączone), natomiast sei() dajesz wtedy jak chcesz włączyć ręcznie
obsługę przerwań, co oczywiście jest możliwe, tylko na stos trzeba uważać
(jeśli tych przerwań jest dużo w jednostce czasu).

sei() na końcu też nie ma sensu, ponieważ procedury obsługi przerwania nie
opuszcza się poprzez ret, tylko poprzez reti, będące niczym innym jak
połączeniem: ret + sei.

Dziękuję.
A chciałem jeszcze prosić o odpowiedź na pytanie dotyczące użycia
sei i cli w pętli głównej.

R.

Robbo
Guest

Thu Feb 10, 2011 12:04 am   



Quote:
Ja bym liczył czas pomiedzy dwoma narastającymi zboczami. Ale ja
herbatę cukrem...

Ja miodem...

Sprawdziłem. W tej chwili:
- mierzenie czasu między narastającym a opadającym zboczem dodatniej połówki
daje czas 998/7.
- mierzenie czasu między narastającymi zboczami kolejnych dodatnich połówek
daje czas 2000/1.

R

RoMan Mandziejewicz
Guest

Thu Feb 10, 2011 12:38 am   



Hello Robbo,

Thursday, February 10, 2011, 12:04:44 AM, you wrote:

Quote:
Ja bym liczył czas pomiedzy dwoma narastającymi zboczami. Ale ja
herbatę cukrem...
Ja miodem...

Za mocny smak...

Quote:
Sprawdziłem. W tej chwili:
- mierzenie czasu między narastającym a opadającym zboczem dodatniej połówki
daje czas 998/7.
- mierzenie czasu między narastającymi zboczami kolejnych dodatnich połówek
daje czas 2000/1.

Jak Ci się wydaje - który wynik jest bardziej zbliżony do
rzeczywistości?

--
Best regards,
RoMan mailto:roman@pik-net.pl
Nowa strona: http://www.elektronika.squadack.com (w budowie!)

Robbo
Guest

Thu Feb 10, 2011 12:54 am   



Quote:
Jak Ci się wydaje - który wynik jest bardziej zbliżony do
rzeczywistości?

Wydaje mi się, że oczywiście ten drugi wynik :)

Ale, jeszcze trzeba będzie popracować nad elektroniką
i może uda się wykrzesać coś więcej z metody nr 1
Może też ujemną połówkę uda się użyć i wtedy miałbym
szybszy odczyt częstotliwości z niewielkim błędem.

R.

Robbo
Guest

Thu Feb 10, 2011 1:47 am   



Quote:
Witam
Na wstępie to się zapytam, na czym Koledze tak naprawdę zależy ? Na
pomiarze czasu (okresu) czy częstotliwości ?

Owszem, nieprecyzyjnie napisałem. Mierzyć będę czas i na tej podstawie
będzie działać układ. Użytkownikowi będę jednak prezentował częstotliwość
wyznaczoną na podstawie zmierzonego czasu.


Quote:
2. Pomiar czasu między impulsami (okresu). Tu aż się prosi wykorzystać
Input Capture Register.

I to chyba będzie eleganckie rozwiązanie. Właśnie się tym zająłem i mam
już efekty. Jutro pozwolę sobie wkleić kod do oceny.

R.

Goto page 1, 2, 3  Next

elektroda NewsGroups Forum Index - Elektronika Polska - Sprawdzanie działania kodu do pomiaru częstotliwości sinusoidy 2-150Hz na ATmega128

NOWY TEMAT

Regulamin - Zasady uzytkowania Polityka prywatnosci Kontakt RTV map News map