| Author |
Message
|
Elektricon Poziom 12

Joined: 24 Apr 2005 Posts: 97
|
#1
10 Aug 2007 20:28 wynik z przetwornika ,atmega16 i C |
|
|
|
chodzi mi o wynik z przetwornika, nie moge dojsc do tego jak to wyswietlic na lcd...
rozumiem ze wynik jest na 10 bitach z rejestrow ADCL i ADCLH
jezeli przetwornik ma 1024 "progow" to rozumiem ze wynik zawiera rowniez czesc ulamkowa prawda...
wiec mam osobno wyliczyc calkowita wartosci i ulamkowa i przeliczac wedlug wzorow (wartosc*1024)/5 V ?
na jakich bitach jest czesc ulamkowa?
i w jaki sposob wyswietlic to na LCD,czyli jak przeliczyc na ASCII ?
bede wdzieczny za nakierowanie
bo jestem zielony w temacie
pozdrawiam
|
|
| Back to top |
|
 |
pubus Poziom 21

Joined: 13 May 2004 Posts: 1248 Location: Kraków
|
#2
10 Aug 2007 21:29 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
Przepisujesz do zmiennej 16-bit (unsigned int) z ADC (nie trzeba rozbijać odczytu na L i H bo tym się zajmie kompilator)...
Napięcie w mV wyliczasz ze wzoru (który jest w dokumentacji) Vin = (ADC * Vref) / 1024...
Co do wyświetlania...
| Code: |
unsigned char volt[4], i=0;
i=4;
do
{
volt[i] = (Vin%10) + 0x30;
Vin/=10;
i--;
}while(i);
|
W ten oto sposób w tablicy masz już liczbę w postaci kodów ASCII...
|
|
| Back to top |
|
 |
Elektricon Poziom 12

Joined: 24 Apr 2005 Posts: 97
|
#3
10 Aug 2007 22:01 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
przy okazji..
co robie zle ? :/
pubus ,wielkie dzieki..:D
jeszcze nie uwzglednilem ponizej twojego kodu..wiec sie nie przejmuj ;)
| Code: |
SIGNAL(SIG_ADC) //obsługa przerwania od A/C
{
double adc;
unsigned char wynik;
adc = ADCW; //pod zmienną adc podstawiona jest wartość odczytana z rejestrów ADCH i ADCL
//adc=(adc*1024)/5;
itoa(adc, wynik, 10);
instrukcja((0*0x40+0)|0x80);
tekst("W: ");
tekst(wynik);
}
w mainie .....
sei();
DDRA=0x00;
PORTA=0x00;
ADMUX=0x41; //ADC1, VCC, ADCL - 0-7 ADCH 8-7 (0,1)
ADCSRA|=_BV(ADIE);
ADCSRA|=_BV(ADEN);
ADCSRA|=_BV(ADSC);
ADCSRA|=_BV(ADATE);
ADCSRA|=_BV(ADPS2);
ADCSRA|=_BV(ADPS1);
ADCSRA&=~_BV(ADPS0); |
|
|
| Back to top |
|
 |
dturczak Poziom 17

Joined: 02 Feb 2003 Posts: 400 Location: Kraków
|
#4
11 Aug 2007 02:10 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
a ja mam takie pytanie..
czy da sie pogodzic taką rzecz,ze wyprowadzenie LCD tzn DB7 mam na pinie A.7 ? (chociaz nie uzywam go jako wejscia przetwornika mam krzaki na wyswietlaczu :(
|
|
| Back to top |
|
 |
Google

|
#
11 Aug 2007 02:10 |
|
|
|
|
|
| Back to top |
|
 |
zumek Poziom 23

Joined: 08 Oct 2003 Posts: 3122 Location: Włocławek
|
#5
11 Aug 2007 10:21 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
| Elektricon wrote: |
przy okazji..
co robie zle ? :/ ... |
Sprawdź w pliku nagłówkowym stdlib.h , jak wygląda prototyp funkcji itoa().
Piotrek
|
|
| Back to top |
|
 |
Elektricon Poziom 12

Joined: 24 Apr 2005 Posts: 97
|
#6
11 Aug 2007 11:13 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
zostosowalem sie do pomyslu Pubus'a...
ale niestety nie dziala...
| Code: |
SIGNAL(SIG_ADC) // przerwanie z przetwornika ADC
{
unsigned int adc;
adc = ADC;
adc=(adc*5)/1024;
unsigned char pom, i=0;
instrukcja((0*0x40+0)|0x80);
tekst("W: ");
i=4;
do
{
pom= (adc % 10) + 48;
adc=adc/10;
dana(pom);
i--;
}while(i);
}
|
o ile pierwsza liczbe przetwarza to na pozostalych miejscach sa zawsze zera...
czemu trzeba stosowac unsigned int a nie mozna double?
moze to w tym problem ?
ale z kolei jak zamienie na double to operacji % 10 kompilator nie chce przepuscic...
|
|
| Back to top |
|
 |
jedrek_1981 Poziom 12

Joined: 23 Apr 2006 Posts: 81 Location: Kraków
|
#7
11 Aug 2007 11:16 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
| dturczak wrote: |
czy da sie pogodzic taką rzecz,ze wyprowadzenie LCD tzn DB7 mam na pinie A.7 ? (chociaz nie uzywam go jako wejscia przetwornika mam krzaki na wyswietlaczu :( |
Ocyzwicie, ze tak.
Napewno nie jest to powodem krzakow na wyswietlaczu.
|
|
| Back to top |
|
 |
pubus Poziom 21

Joined: 13 May 2004 Posts: 1248 Location: Kraków
|
#8
11 Aug 2007 12:47 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
Ja tu kombinuje co może być nie tak i nawet nie zauważyłem od razu tego "kwiatuszka"...
Napięcie referencyjne masz rozumiem 5mV...? Tak...?
Jeśli masz jednak 5V to wypadało by jako referencyjne przy obliczeniach dać 5000mV, nieprawdaż...?
Zmienna adc może być unsigned long int...
|
|
| Back to top |
|
 |
Elektricon Poziom 12

Joined: 24 Apr 2005 Posts: 97
|
#9
11 Aug 2007 13:05 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
to ja juz nie wiem o co chodzi:
| Code: |
SIGNAL(SIG_ADC) // przerwanie z przetwornika ADC
{
unsigned long int adc;
adc=(ADC*5000)/1024;
unsigned char pom, i=0;
instrukcja((0*0x40+0)|0x80);
tekst("W: ");
i=4;
do
{
pom = (adc % 10) + 48;
adc=adc/10;
dana(pom);
i--;
}while(i);
}
|
rzeczywiscie z tym napiecie ref... niedopatrzenie,nie zauwazylbym wogole
.tylko ze teraz jeszcze dziwniej sie to zachowuje ;)
po pierwsze zmieniaja sie tylko 2 pierwsze pozycje...
i tak np. dla napiecia 2.307 mam na lcd W: 5400 ,dla 2,424 - 4300
z czego moze to wynikac ? :/
do Aref 100nF, do Avcc napiecie przez filtr(dlawik+C)....gnd do gnd ..
ADMUX=0x41;
ADCSRA|=_BV(ADPS2);
ADCSRA|=_BV(ADPS1);
ADCSRA&=~_BV(ADPS0);
ADCSRA|=_BV(ADIE);
ADCSRA|=_BV(ADEN);
w petli while co jakis czas ADCSRA|=_BV(ADSC);
|
|
| Back to top |
|
 |
Google

|
#
11 Aug 2007 13:05 |
|
|
|
|
|
| Back to top |
|
 |
pubus Poziom 21

Joined: 13 May 2004 Posts: 1248 Location: Kraków
|
#10
11 Aug 2007 14:35 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
Wypróbuj ten kod...
| Code: |
#include <avr/interrupt.h>
#include <inttypes.h>
#include <stdlib.h>
#include <math.h>
#include <avr/io.h>
#define F_CPU 8000000 //20000000 //18432000 //3686400
#define CYCLES_PER_US ((F_CPU+500000)/1000000)
/****** Zmienne globalne ****************************************************************************/
volatile unsigned char koniec=0;
volatile unsigned long int adc;
/**************************************************************************************************/
SIGNAL (ADC_vect)
{
adc = ADC;
koniec=1;
}
int main(void)
{
unsigned int pom=0;
unsigned char i=0;
ADMUX |= _BV(REFS0) | _BV( MUX2);
ADCSRA |= _BV(ADEN) | _BV(ADSC) | _BV( ADIE) | _BV(ADPS2) | _BV( ADPS1) | _BV(ADFR);
for(;;)
{
if(koniec)
{
koniec=0;
i=4;
pom = (adc*5000) / 1024;
do
{
dana((pom%10)+48); //dana zakładam, że jest funkcją wyświetlającą na LCD znak
pom/=10;
i--;
}while(i);
}
}
return 0;
}
|
|
|
| Back to top |
|
 |
Google

|
#
11 Aug 2007 14:35 |
|
|
|
|
|
| Back to top |
|
 |
Elektricon Poziom 12

Joined: 24 Apr 2005 Posts: 97
|
#11
11 Aug 2007 15:18 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
do wejscia adc1 mam dolaczony potencjometr..
normalny" program w bascomie smiga..
tutaj nie chce :/
ja juz nie wiem,te wartosci z kosmosu u mnie sie biora chyba..
nawet z twoim programem..
o ile jest dobry...
ADFR to chyba nie atmega16 (ADATA),i zalaczylem sei i wybralem adc1..
reszte nie zmienialem wogole i lipa.. :/
eh...jeszcze raz.... zrobilem nawet bez przerwan
//wejscie ADC1, do AREF podlaczony 100nF,jako napiecie odniesienia AVCC...
ADMUX=0x41;
//preskaler 64
ADCSRA|=_BV(ADPS2);
ADCSRA|=_BV(ADPS1);
ADCSRA&=~_BV(ADPS0);
//wlaczenie przetwornika
ADCSRA|=_BV(ADEN);
while(1)
{
ADCSRA|=_BV(ADSC); //pomiar
while(bit_is_set(ADCSRA,ADSC)){}; //oczekiwanie na koniec pomiaru
pom = (ADC*5000) / 1024; //przeliczenie wartosci
instrukcja((0*0x40+0)|0x80); //kursor lcd na 0,0
i=0;
do
{
pom/=10;
dana((pom%10)+48); //wyswietlenie kolejnej cyfry
i++;
}while(i<4);
}
}
przeciez to jest niemozliwe zeby nie dzialalo :(
|
|
| Back to top |
|
 |
pubus Poziom 21

Joined: 13 May 2004 Posts: 1248 Location: Kraków
|
#12
11 Aug 2007 16:13 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
No tak fakt w atmega16 inaczej się tryb free run odpala...
Ok to może inaczej...
Wypróbuj ten kod...
| Code: |
#include <avr/interrupt.h>
#include <inttypes.h>
#include <stdlib.h>
#include <math.h>
#include <avr/io.h>
#define F_CPU 8000000 //20000000 //18432000 //3686400
#define CYCLES_PER_US ((F_CPU+500000)/1000000)
int main(void)
{
unsigned long int adc=0;
unsigned int pom=0;
unsigned char i=0;
for(;;)
{
ADMUX |= _BV(REFS0) | _BV(MUX2);
ADCSRA |= _BV(ADEN) | _BV(ADSC) | _BV( ADIE) | _BV(ADPS2) | _BV( ADPS1);
do{}while(!(ADCSRA&0x10));
adc = ADC;
ADCSRA |= _BV(ADIF);
pom = (adc*5000) / 1024;
i=4;
do
{
dana((pom%10)+48);
pom/=10;
i--;
}while(i);
}
return 0;
}
|
|
|
| Back to top |
|
 |
Elektricon Poziom 12

Joined: 24 Apr 2005 Posts: 97
|
#13
11 Aug 2007 17:06 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
no nie wiem..
przedziwne zachowanie..
ale po stronie sprzetowej jestem pewien ze wszystko jest ok.
zamieszczam pelny kod ktory wykorzystuje..
jakby ktos to mogl wrzucic i sprawdzic u siebie bylbym wdzieczny...
wejscie na PA1,piny lcd ustawic na poczatku+zmienic DDR'y do nich w mainie
glowny kod (pubusa wiekszosc (dzieki za wlozony wysilek.. ):
| Code: |
int main(void) //program główny
{
DDRA&=~_BV(1);
PORTA&=~_BV(1);
PORT_DB6|=_BV(PIN_DB6);
PORT_DB7|=_BV(PIN_DB7);
DDRC|=_BV(PIN_RS);
DDRC|=_BV(PIN_E);
DDRC|=_BV(PIN_DB4);
DDRC|=_BV(PIN_DB5);
DDRD|=_BV(PIN_DB6);
DDRA|=_BV(PIN_DB7);
ini_lcd();
instrukcja(0x0c); //0f
instrukcja(0x01);
unsigned long int adc=0;
unsigned int pom=0;
unsigned char i=0;
for(;;)
{
ADMUX |= _BV(REFS0) | _BV(MUX0);
ADCSRA |= _BV(ADEN) | _BV(ADSC) | _BV( ADIE) | _BV(ADPS2) | _BV( ADPS1);
do{}while(!(ADCSRA&0x10));
adc = ADC;
ADCSRA |= _BV(ADIF);
pom = (adc*5000) / 1024;
i=4;
instrukcja((0*0x40+0)|0x80);
do
{
dana((pom%10)+48);
pom/=10;
i--;
}while(i);
delay_us(1000000);
}
return 0;
} |
reszta w zalaczniku..
zaczynam sie poddawac
|
|
| Back to top |
|
 |
pubus Poziom 21

Joined: 13 May 2004 Posts: 1248 Location: Kraków
|
#14
11 Aug 2007 18:12 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
Jak możesz to zamieść schemat podłączenia LCD...
|
|
| Back to top |
|
 |
Elektricon Poziom 12

Joined: 24 Apr 2005 Posts: 97
|
#15
11 Aug 2007 18:22 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
lcd jest sprawny..
adc pod bascomem smiga z lcd
a kazdy pin mozna przypisac...
| Code: |
#define PORT_E PORTC
#define PIN_E 3
#define PORT_RS PORTC
#define PIN_RS 2
#define PORT_DB4 PORTC
#define PIN_DB4 4
#define PORT_DB5 PORTC
#define PIN_DB5 5
#define PORT_DB6 PORTD
#define PIN_DB6 7
#define PORT_DB7 PORTA
#define PIN_DB7 7
|
tylko ddry w mainie trzeba pozmieniac..
to napewno nie problem z lcd..
|
|
| Back to top |
|
 |
Google

|
#
11 Aug 2007 18:22 |
|
|
|
|
|
| Back to top |
|
 |
dturczak Poziom 17

Joined: 02 Feb 2003 Posts: 400 Location: Kraków
|
#16
11 Aug 2007 20:18 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
ladnie sie tutaj widze meczycie ;)
przede wszystkim w odwrotnej kolejnosci wyswietlacie na lcd.. stad moze te kosmiczne liczby.., przy metodzie "wylawiania cyfr z pozycji" jedziemy przeciez od prawej do lewej..
wiecej nie zauwazylem,ale moze ktos odkryje..
pozdrawiam..
|
|
| Back to top |
|
 |
Elektricon Poziom 12

Joined: 24 Apr 2005 Posts: 97
|
#17
11 Aug 2007 23:53 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
no dzieki,to troszke wyjasnia,
heh ze wczesniej na to nie wpadlem...
oczywiste to jest..
tylko ze nadal w czyms tkwi blad :|
|
|
| Back to top |
|
 |
dturczak Poziom 17

Joined: 02 Feb 2003 Posts: 400 Location: Kraków
|
#18
11 Aug 2007 23:59 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
przede wszystkim wynik jezeli ma byc w int musi byc formie unsigned long int.... przy zwyklym unsigned int bedziesz mial to co obserwujesz czyli 2 pozycje ci obetnie..
| Code: |
ADMUX |= _BV(REFS0) | _BV(MUX0);
ADCSRA |= _BV(ADEN) | _BV(ADSC) | _BV( ADIE) | _BV(ADPS2) | _BV( ADPS1) | _BV(ADATE) ;
sei();
SIGNAL(SIG_ADC)
{
unsigned long int adc,pom;
unsigned char i;
adc = ADC;
pom = (adc*5000) / 1024;
i=4;
instrukcja((0*0x40+0)|0x80);
do
{
dana((pom%10)+48);
pom/=10;
i--;
}while(i);
}
|
ze to dziala ,prawie jest pewne ;)
oczywiscie wynik w odwrotnej kolejnosci...
pozdrawiam :)
|
|
| Back to top |
|
 |
Elektricon Poziom 12

Joined: 24 Apr 2005 Posts: 97
|
#19
12 Aug 2007 00:02 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
dzieki wielkie ,dziala cos :)
a moze ktos mi powiedziec jak wyeliminowac to ze ostatnie 2 cyfry strasznie mi skacza.... wina zaklocen? ,co sie z tym przewaznie robi ?
|
|
| Back to top |
|
 |
dturczak Poziom 17

Joined: 02 Feb 2003 Posts: 400 Location: Kraków
|
#20
12 Aug 2007 00:16 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
mozna dac filtr dlawik+cewka na AVCC..
w signal mozna wyswietlac wynik ostatnich 10 pomiarow i robic srednia w ten sposob :
| Code: |
volatile unsigned long int adc;
unsigned char ile_adc;
unsigned long int ad[11];
/**************************************************************************************************/
SIGNAL(SIG_ADC)
{
ile_adc++;
ad[ile_adc]=ADC;
if (ile_adc==10)
{
ile_adc=0;
unsigned long int adc,pom;
unsigned char i;
unsigned char nap[5];
adc=0;
for(i=1;i<11;i++) adc=adc+ad[i];
adc = adc/10.0;
pom = (adc*5000) / 1024;
instrukcja((0*0x40+0)|0x80);
for(i=1;i<5;i++)
{
nap[i]=(pom%10)+48;
pom/=10;
}
dana(nap[4]);
tekst(".");
dana(nap[3]);
dana(nap[2]);
dana(nap[1]);
}
}
|
|
|
| Back to top |
|
 |
Elektricon Poziom 12

Joined: 24 Apr 2005 Posts: 97
|
#21
12 Aug 2007 00:19 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
wow..super :)
caly dzien myslenia,a ty mi wszystko powiedziales w pare chwil..
stokrotne dzieki...
a takie pytanie bardziej teoretyczne..
wynik z miernika rozni mi sie od przetwornika o jakies 30mV...
to normalny margines bledu ?
w zaleznosci ktory kanal zastostuje moge miec rozne bledy?
w jaki sposob wprowadzic poprawke?
widzialem jakies wzory w datashetcie do atmegi..
prosze o naprawdzenie na koniec :)
co to jest to GAIN ?
ADC=(VPOS – VNEG)⋅GAIN⋅512/VREF
jest tez jakis przyklad:
| Code: |
ADMUX = 0xED (ADC3 - ADC2, 10x gain, 2.56V reference, left adjusted result)
Voltage on ADC3 is 300 mV, voltage on ADC2 is 500 mV.
ADCR = 512 * 10 * (300 - 500) / 2560 = -400 = 0x270
ADCL will thus read 0x00, and ADCH will read 0x9C. Writing zero to ADLAR right
adjusts the result: ADCL = 0x70, ADCH = 0x02. |
nie za bardzo mam pojecia o co chodzi...
|
|
| Back to top |
|
 |
pubus Poziom 21

Joined: 13 May 2004 Posts: 1248 Location: Kraków
|
#22
12 Aug 2007 01:28 Re: wynik z przetwornika ,atmega16 i C |
|
|
|
Z tą kolejnością to oczywiście racja...
Trochę się zasugerowałem tym wyświetlaniem od razu z obliczeń...
Dlatego pierwszy przykład był z tablicą...
Przyczepie się tylko do tych zmiennych...
Wiem, że zmienna na której przeliczam z 10-bit na napięcie musi być typu long ale ta do której podstawiam nie...
Nie teoretyzuje bo zawsze tak robię i nie ma problemu...
Ba nawet jako wartość zwracana przez funkcję...
| Code: |
volatile unsigned long int adc;
...
unsigned int volt(void)
{
...
return((adc*5000)/1024);
}
|
Więc z kąd ta rozbieżność...?
|
|
| Back to top |
|
 |