Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 24 lis 2024, o 02:50


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 12 ] 
Autor Wiadomość
PostNapisane: 23 kwi 2016, o 18:17 
Offline
Nowy

Dołączył(a): 13 lip 2015
Posty: 13
Pomógł: 0

Witam szanownych forumowiczów!

Mam problem z wyświetlaniem wartości natężenie prądu. Korzystałem z zagadnienia poruszonego w "Blubuku" jednak na potrzeby zmieniłem trochę program pod ATmegę32, ponieważ nie posiadam ATtiny26. Zmiana została dokonana w linijce w której wylicza się średnią ( zmienna -> srednia):

zamiast:
Składnia: [ Pobierz ] [ Ukryj ]
język cpp
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

mamy:
Składnia: [ Pobierz ] [ Ukryj ]
język cpp
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


żeby wyświetlane wartości pokrywały się z prawdą (zrobiłem do tego arkusz w excelu taki jak w rozdziale 4.8.2. Różnicowy pomiar napięcia). Zmieniłem również rejestr ADCSR który występuje w ATtiny26 na ADCSRA z ATmegi32.
Przepisałem elegancko cały kod do Eclipsa, skompilowałem i niestety wartość prądu na wyświetlaczu nie nie dla każdej wartości ADC odzwierciedla realną wartość prądu (sprawdzane multimetrem). Maksymalna wartość jaką udało mi się wyświetlić i się pokrywała z wcześniejszymi wyliczeniami to 0,5 [A], potem nie wyświetlało wyższych wartości.
Dodatkowo wyświetliłem wartość ADC, na podstawie której była wyliczana wartość prądu i tu akurat wartość była zgodna z tą wyliczoną z Excela dla całego zakresu. zacząłem więc wyświetlać obok wartości ADC wartość "srednia", żeby zobaczyć jakie wartości pokaże. Były to wartości z zakresu zmiennej typu int16_t (-32k do 32k) mimo, że typ zmiennej zmieniałem wielokrotnie, na te mogące pomieścić większe liczby. Ponadto dodałem dla sprawdzenia nową zmienną "uint64_t srednia2 = 100000;" i gdy wyświetliłem jej wartość funkcją "lcd_int();"
pokazała się wartość "-31072", tak jakby przewijało cały czas wartość int16_t. Nie mam pojęcia na czy polega mój błąd. Załączam kod programu, bliźniaczo podobny do tego z książki z rozdziału 4.8.2. .

Składnia: [ Pobierz ] [ Ukryj ]
język cpp
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


P.S. Jeśli to ważne, to oglądałem serię filmików o ADC ponad dwa razy.



Ostatnio edytowano 25 kwi 2016, o 08:01 przez skiero, łącznie edytowano 3 razy

Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 23 kwi 2016, o 18:23 
Offline
Moderator zasłużony dla forum.atnel.pl
Avatar użytkownika

Dołączył(a): 18 lip 2012
Posty: 3206
Lokalizacja: Kraków - obok FAB5 ATMEL'a
Pomógł: 90

Kod źle wstawiony.

_________________
http://www.jaglarz.info



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 23 kwi 2016, o 19:21 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 09 gru 2014
Posty: 1540
Pomógł: 269

skiero napisał(a):
nową zmienną "uint64_t srednia2 = 100000;" i gdy wyświetliłem jej wartość funkcją "lcd_int()

Zwróć uwagę na funkcję lcd_int(), a w niej użytą itoa(). Przecież ona nie będzie prawidłowo wyświetlać liczb większych od int, prawda?
Napisz sobie blizniaczą funkcję, z tym, że zamiast itoa(), użyj ltoa() lub nawet lepiej ultoa().



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 25 kwi 2016, o 08:05 
Offline
Nowy

Dołączył(a): 13 lip 2015
Posty: 13
Pomógł: 0

Jaglarz napisał(a):
Kod źle wstawiony.

Już poprawiłem.

anshar napisał(a):
skiero napisał(a):
nową zmienną "uint64_t srednia2 = 100000;" i gdy wyświetliłem jej wartość funkcją "lcd_int()

Zwróć uwagę na funkcję lcd_int(), a w niej użytą itoa(). Przecież ona nie będzie prawidłowo wyświetlać liczb większych od int, prawda?
Napisz sobie blizniaczą funkcję, z tym, że zamiast itoa(), użyj ltoa() lub nawet lepiej ultoa().


Słuszna uwaga, poprawię to (jak tylko wrócę do domu). Natomiast obawiam się, że nie rozwiąże to problemu całkowicie, ponieważ do obliczeń nie brane są zmienne sczytywane z wyświetlacza, więc w obliczeniach prowadzonych przez mikrokontroler nie powinno być tego problemu.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 25 kwi 2016, o 08:33 
Offline
Użytkownik

Dołączył(a): 25 lip 2015
Posty: 140
Zbananowany użytkownik

Pomógł: 18

A skąd to równanie wyprowadziłeś:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 25 kwi 2016, o 09:45 
Offline
Nowy

Dołączył(a): 13 lip 2015
Posty: 13
Pomógł: 0

Sparrow-hawk napisał(a):
A skąd to równanie wyprowadziłeś:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Jest to wartość ADC pomnożona przez milion (ponieważ dalej jest ona przez ten milion dzielona, żeby uzyskać wartość całkowitą i tą po przecinku). Działałem na podstawie wzoru z "blubuka", tylko nie ma do niego wystarczająco jasnych wyjaśnień.
Pierwotna wartość z książki, czyli:
Składnia: [ Pobierz ] [ Ukryj ]
język cpp
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

jest to wartość tak naprawdę prądu (zmienna "srednia" przyjmuje w powyższym wyrażeniu wartość od 5626 do 5 501 250 ponieważ "value" przyjmuje wartość od 1 do 978. Po podzieleniu tego przez milion dale to wartość od 0,005 do 5, 5 [A])

W moim równaniu:
Składnia: [ Pobierz ] [ Ukryj ]
język cpp
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


wartość "srednia" przyjmuje wartość od 910 080 do 512 557 056, dla wartości "value" od 1 do 512...
Już widzę błąd.

Dalej jednak nie wiem, dlaczego obliczenia w zakresie prądów od 0 do 0,3 [A] były ok a reszta nie... Wrócę do domu, podłączę i dam znać jak poszło.

P.S. Dziękuję za pytanie, dużo wprowadziło do moich rozważań :)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 25 kwi 2016, o 11:14 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 09 gru 2014
Posty: 1540
Pomógł: 269

Proponuję zatem zapoznać się z tym tematem:
http://atnel.pl/domyslna-promocja-do-typu-int.html



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 25 kwi 2016, o 20:00 
Offline
Nowy

Dołączył(a): 13 lip 2015
Posty: 13
Pomógł: 0

Dziękuję wszystkim za pomoc, amperomierz działa tak jak powinien.
anshar napisał(a):
Proponuję zatem zapoznać się z tym tematem:
http://atnel.pl/domyslna-promocja-do-typu-int.html

Fantastyczna podpowiedź!

Dodatkowo jeszcze poprawiłem funkcję "int_to_str", teraz nazywa się "ulint_to_str" (w kodzie poniżej) i pobieranie wartość ADC ułożyłem w funkcję "pomiar_i1".

Niestety podsycony sukcesem zacząłem dalej kombinować i chciałem dołożyć pomiar napięcia metodą jak z filmów o ADC Pana Mirka. Niestety w pomiary w jakiś sposób na siebie wpływają i gdy tylko funkcja "pomiar()" jest wstawiona w kod to pomiar prądu nagle przestaje mieć sens, co widać na zdjęciach. Na wyświetlaczu od górnego wiersze w prawo idąc jest kolejno wartość ADC, potem wartość zmiennej średnia i na dole już sama wartość prądu.

ObrazekObrazek

a poniżej kod, w którym część odpowiedzialna za pomiar napięcia jest wykreskowana, ponieważ w takiej konfiguracji nie działa:

Składnia: [ Pobierz ] [ Ukryj ]
język cpp
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 26 kwi 2016, o 07:19 
Offline
Użytkownik

Dołączył(a): 25 lip 2015
Posty: 140
Zbananowany użytkownik

Pomógł: 18

Jeżeli ustawiasz jakieś bity w rejestrze korzystając z zapisu: REG |= VALUE; to zadbaj też o wcześniejsze ich skasowanie.

Dla przykładu:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Jaką wartość będzie miała zmienna val?

W obu funkcjach pomiar ustawiasz ADMUX, ale czy na pewno ma on taką wartość jakiej oczekujesz?



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 26 kwi 2016, o 22:44 
Offline
Nowy

Dołączył(a): 13 lip 2015
Posty: 13
Pomógł: 0

Sparrow-hawk napisał(a):
Jeżeli ustawiasz jakieś bity w rejestrze korzystając z zapisu: REG |= VALUE; to zadbaj też o wcześniejsze ich skasowanie.

Dla przykładu:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

Jaką wartość będzie miała zmienna val?

W obu funkcjach pomiar ustawiasz ADMUX, ale czy na pewno ma on taką wartość jakiej oczekujesz?


Odpowiedz:

0xA5 = 1010 0101
0x5A = 0101 1010

---|1010 0101
or-|0101 1010
----------------
---|1111 1111

Teraz wpisałem na sztywno i rzeczywiście zaczęło działać:

Składnia: [ Pobierz ] [ Ukryj ]
język cpp
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


...więc problem leży w w "orowaniu".
Niestety dziś nie miałem wystarczająco czasu, żeby wystarczająco zgłębić temat, jutro postaram się przeliczyć wszystko dokładniej.

Niemniej dziękuję, za nakreślenie miejsca, gdzie jest problem :)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 27 kwi 2016, o 07:37 
Offline
Użytkownik

Dołączył(a): 25 lip 2015
Posty: 140
Zbananowany użytkownik

Pomógł: 18

A co tu chcesz przeliczać? W tym przypadku należy wyzerować 5 najmniej znaczących bitów rejestru ADMUX, a następnie dodać logicznie numer kanału.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

I jeszcze taka uwaga:
Cytuj:
Note:
1. The differential input channels are not tested for devices in PDIP Package. This feature is only
guaranteed to work for devices in TQFP and QFN/MLF Packages.

Polecam również obejrzeć: http://mirekk36.blogspot.com/2014/03/maskowanie-bajtow-z-przymruzeniem-oka.html



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 27 kwi 2016, o 10:40 
Offline
Nowy

Dołączył(a): 13 lip 2015
Posty: 13
Pomógł: 0

Mówiąc, że przeliczę sobie jeszcze, miałem na myśli, że prześledzę jak zmienia się rejestr ADMUX w programie, żeby znaleźć moment w którym się przestaje zgadzać.

Sparrow-hawk napisał(a):
I jeszcze taka uwaga:
Cytuj:
Note:
1. The differential input channels are not tested for devices in PDIP Package. This feature is only
guaranteed to work for devices in TQFP and QFN/MLF Packages.

Tak wiem o tym, mam Atmegi32 w TQFP, ale na płytce prototypowej ciężko jest ją umieścić :) chciałem jeszcze przećwiczyć zanim zrobię odpowiednią płytkę w Eaglu.

Sarrow-hawk - dziękuję za pomoc.



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 12 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 0 gości


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO