PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : adc wert auf die uart



servusssss
23.10.2006, 16:22
hallo,

ich lauf wider einmal im kreis. ich versuche die werte des adc auf der RN-control 1.4 auf die uart auszugeben . die uart funktioniert aber die wert vom adc sind irgendwie nicht richtig glaub ich zumindest?
den Port c ist nur zur kontrolle ob der atmel läuft.
Jetzt hat jemand eine ahnung wieso ich solche ergebnise bekomme wie: adcval 5c spannung 1f ? aber am PA6 1,7V sind?
liegt es an der Konvertierung?
sind die werte des ADC falsch?
wenn ja wie sollte man den ADC auswerten?
mit result = ADCH;
oder result = ADCL + (ADCH << 8 );


hier mein quellcode:




#include <avr/io.h>
#include <stdlib.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/signal.h>
#include <string.h>
#include "uart.h"

#ifndef F_CPU
#define F_CPU 16000000UL // 16MHz Taktfrequenz
#endif

/* 9600 baud */
#define UART_BAUD_RATE 9600
#define CR \r\n


#define DELAY_LOOPS 50 // So viele Schleifendurchgaenge lang muss erledigt werden

struct{

uint8_t bPin:1 ; // Aktuelles Signal am Pin (Taster)
uint8_t bStatus:1; // Status des Tasters ob dieser beim voriegen durchlauf gedrückt war!


} bportd;

uint8_t nCounter; // Zähler wie oft der Taster gedrückt war
uint8_t nKeyPress; // Schleifenzähler wie viele Schleifen der Taster schon gedrückt war!

//Prototypen
void init(void);
uint16_t RADCC(uint8_t mux);

int main (void){


// Uart Initalisierung
uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) );

//Interrupt enable
sei();
// Initialisierung der Register
DDRA = 0x00;
PORTA = 0xff;
DDRC = 0xff;
DDRD = 0x00;
PORTD = 0x01;

// Initialisierung der Varialblen
char buffer[15];

bportd.bPin =1;
bportd.bStatus =0;
nCounter =0;
uint16_t adcval ;
uint16_t spann;


uart_puts("\n\r Test Prog V1.0 RS232 Start\n\r");
for(;;){

if(bit_is_clear (PIND,PIND0)){ // wenn der knopf gedrückt ist logisch 0
if(bportd.bPin){ // wenn der knopf nicht gedrückt war dann wird alles zurückgesetzt!
nCounter =0;
bportd.bPin =0;
bportd.bStatus =0;
}
else if(!bportd.bStatus){ // wenn der knopf immer noch gedrückt

if(++nCounter > DELAY_LOOPS){
nKeyPress++; //zähler erhöhen
PORTC = nKeyPress; // ausgabe am Port c

adcval = RADCC(6); //
spann = (4,88*adcval)/255;

itoa( adcval, buffer, 16);
uart_puts("\n\r adcval ");
uart_puts(buffer);

itoa( spann, buffer, 16);
uart_puts("\n\r spannung ");
uart_puts(buffer);

bportd.bStatus=1; // status merken
}
}

}
else
{
bportd.bPin = 1;
}
}}



uint16_t RADCC(uint8_t mux){
uint8_t i;
uint16_t result =0; // Initialisierung wichtig

ADCSRA = (1<<ADEN) | (1<<ADPS1)| (1<<ADPS2)| (1<<ADPS0); //Prescaler 128 & ADC aktivieren
ADMUX = mux; //Kanalwählen
ADMUX |= (1<<REFS1) |(1<<ADLAR); //VCC = Referenz

ADCSRA |= (1<<ADSC); //adc wandlung
while(!ADCSRA & (1<<ADIF));//Warten


for(i=0;i<4;i++)
{
ADCSRA |= (1<<ADSC); // adc wandlung

while ( ADCSRA & (1<<ADSC) ); // Warten

result += ADCH; // Wandlungsergebnisse addiern
//result += ADCW; //einspricht ADCL + (ADCH <<8);
}

ADCSRA &= ~(1<<ADEN); // ADC deaktivieren

result /= 4; // arithm. Mittelwert

return result;
}




bestendank für eure mühe

sg servusssss

SprinterSB
23.10.2006, 17:12
-- es heisst nicht 4,88 sondern 4.88!
-- die Multiplikation mit 4.88 wird so wohl nicht gehen. besser:

const uint16_t faktor = (double) 4.88/255 * (1L << 15);
spann = (adcval*faktor) >> 15;
Man erweitert also mit 2**15, um die Genauigkeit weiter zu verbesser.
-- Wenn du die Zahlen als Dezimal willst, muss es heissen itoa (..., 10);
Aber auch das ist wohl nicht das, was du willst? So bekommst du nämlich nur die Vorkommastellen...
-- Wo ist/sind deine Interrupt-Routinen? Bzw warum machst du ein sei()?

servusssss
23.10.2006, 20:12
-das stimmt 4.88 ist ja c ](*,)
das "(double)" ist mir klar aber für was ist das " * (1L << 15);" und das >> 15; ist das für die genauigkeit hab ich das richtig verstanden??

und ich hätte gerne das ich 1.7 raus kommt wie kann man das machen?!

das sei(); ist von einem anderen programm wo ich befehle über die Uart schicke, wollte nur die tasterabfrage kopieren hab ich übersehen beim löschen vom rest.

SprinterSB
24.10.2006, 16:38
Dein ADC liefert 4.88/255 V pro Inkrement. Die Spannung für den ADC-Wert adcwert ist also 4.88/255*adcwert. Der Faktor 4.88/255 ist kleiner als 1, was einem 2 Möglichkeiten lässe
-1- Man nimm float-Arithmetik. Das funktioniert, ist aber teuer.
-2- Man macht eine Fixpunkt-Rechnung mit int-Arithmetik.

Für -2- erweitert man die entstehenden Ausdrücke mit 10000 (oben hatte ist 32768, ist aber nicht so toll wen man Dezimaldarstellung braucht).
4.88/255*10000*adcwert ist dann die Gemessene Spannung in Einheiten von 1e-5V = 100µV = 0.1mV

const uint16_t faktor = (double) 4.88/255 * 10000L;
uint16_t spann_100uV = faktor*adcval;
Da faktor = 191 und adcval < 256 passt das in 16 Bit rein.
Die Vorkommastelle deiner Spannung ist dann spann_100uV / 10000, die Nachkommastellen sind spann_100uV % 10000.

Beachte, daß du für die Ausgabe der Nachkommastellen eine 1 als "0001" ausgeben musst, eine 33 als "0033", etc.

servusssss
28.10.2006, 18:43
ich hab mich noch mit dem format problem beschäftigt :


Beachte, daß du für die Ausgabe der Nachkommastellen eine 1 als "0001" ausgeben musst, eine 33 als "0033", etc.


ich hab mir mal eine lösung zusammen gebastelt die auch funktioniert, aber wie ist das mit dem speicher wenn ich solche funktionen (strlen, strcat) nutze gut/schlecht?
verbrauch ich da zuviel speicher?
gibt es eine speicher sparendere lösung?
hier mein code:



itoa(vork_spann, buffer, 10.0);
uart_puts("\n\r Spannung: ");
uart_puts(buffer);
uart_putc(',');


itoa( nachk_spann, buffer, 10.0);
char ausgabe[5] = "";
uint8_t charanz;

if(strlen(buffer) <=4){ // fals ein ergebnis mit x,0032
for(charanz = strlen(buffer); charanz <=3 ;charanz ++){
strcat(ausgabe,"0");// mit nullen ergänzen auf 4 stellen
}
strcat(ausgabe,buffer);//wert anhängen
}
else{
strcat(ausgabe,buffer);//umleiten in den ausgabe string
}
uart_puts(ausgabe);


besten dank