www.mikrocontroller.net

Forum: Compiler & IDEs ADC wert über RS232 senden


Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Zusammen

Ich bin kein µC Profi und arbeite mich gerade durch Beispielprogramme
sowie das Tutorial.
Zur Zeit experimentiere ich gerade mit einem atmega 8 auf der STK500 
Platine

Zu tun:  gewandelten AD-Wert per UART auf dem Hyperterminal 
darzustellen.


Zu der Hardware:
1. ATMega8 auf dem STK500 Platine
2. extene Quarz 4 Mhz
3. int AREF also AREF-Jumper gesetzt.
4. Analog eingang direckt an PINC.0 verbunden.

Schon ausprobieren:
uart (senden und empfangen funktionieren)

Zu der Software:
Ich habe aus ADC-Beispielen eine eigene Code zusammengebastelt.

Code:

#ifndef F_CPU
#warning "F_CPU was not defined yet, now make up with 4000000"
#define F_CPU 4000000L 
#endif


#define BAUD 9600L
#define UBRR_VAL ((F_CPU+BAUD * 8)/(BAUD*16)-1)     //clever round
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))         //real baud rate
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000)     //Error per thousand


#if ((BAUD_ERROR>10)||(BAUD_ERROR<-10))
#error Systematic error in the baud rate more than 1% and thus too high!
#endif


#include <avr/io.h>
#include <stdlib.h>
#include <inttypes.h>
#include <util/delay.h>

void uart_Init() 
{
  
  UBRRH = (unsigned char)(UBRR_VAL>>8);  
  UBRRL = (unsigned char)UBRR_VAL;  
  UCSRB |= (1<<RXEN)|(1<<TXEN);  
  UCSRC = (1<<URSEL) | (1<<UCSZ0)|(1<<UCSZ1);

}//end uart_Init()

void uart_Putc(unsigned char c)
{
    while (!(UCSRA & (1<<UDRE)));     
  UDR = c; 
   _delay_ms(10);   
}//end uart_Putc()

void uart_Puts (char *string)
{
    while( *string != '\0' )
    {  
        uart_Putc(*string);
        string++;
    }
}//end uart_Puts()

void ADC_Init (uint8_t Mux_channel)
{
        DDRC = 0x00;  //Define as Input
  PORTC = 0xFF;    //Enables Pull-Up on PC0

  ADCSRA = (1<<ADEN);   //Enables the ADC
  ADCSRA |= (1<<ADPS2) | (1<<ADPS0); //Set ADC with Prescaler 32 
  
  ADMUX = Mux_channel;    //Select pin ADC0 using MUX
  _delay_us(40);
  ADMUX |= (1<<REFS0) | (1<<REFS1);//Int. REF Voltage Reference 
  ADMUX |= (0<<ADLAR);  //The result is right adjusted
}

  
uint16_t ADC_Read(uint8_t Mux_channel) 
{
  uint8_t i;
  uint16_t result = 0;
  
  //interrupt
  TCNT0 = 5;    //Zählregister setzen
  TIMSK |= (1<<TOIE0);  
  TCCR0 |= (1<<CS01);
  TCCR0 |= (1<<CS00);  //CPU Takt wird verwendet --> 4MHz
  TIFR |= (1<<TOV0);//startet interrupt bei jedem überlauf
  
  
  ADC_Init (Mux_channel);

  ADCSRA |= (1<<ADSC);//Start conversion
  while(ADCSRA & (1<<ADSC));//wait until converstion completed
  result = ADCW;  
    result = 0;  
                          

  //Mittwert von vier messwerte
  for(i=0; i<4; i++) 
  {    
    ADCSRA |= (1<<ADSC);  //A single conversion    
    while(ADCSRA & (1<<ADSC));
    result += ADCW;
  }
  
  ADCSRA &= (0<<ADEN);      // ADC reanables  
  result /= 4;
    
  return result;
}//End int ADC_Read() 

//Interrupt Service Routine für AD Wandlung
ISR(TIMER0_OVF_vect) 
{
  ADIteiler++;     //clocks interrupt counter value on each ms 
  if(ADIteiler >= 60)  //Counter cycle for all ms 60
  {
    ADIteiler=0;  //counter 0 set
        
  uint16_t result = ADC_Read(0);  //Read the Analog volt. on PinC 0
  uart_Puts("\r\n\n");
  utoa( result, s, 10 );   
  uart_Puts( s );  
    uart_Putc('$');
  }
}//End ISR(TIMER0_OVF_vect)


int main()
{
  uart_Init();
  
  uart_Puts("\r\n");
  uart_Puts("Messung fängt an:");
  uart_Puts("\r\n");
  
  sei(); //Enable Globale Interrupts

  for (;;); 

  return (0);
}

Problem:
ADC-Werte sind falsch. Für den selben Analog Eingang kriege ich 
Unterschiedliche Digital Wert.
beispiel: für 2.04v ausgabe: 1023 oder 255 oder 3 oder 166 oder 875...

Ist eventuell ein Fehler in meinen Code? fehlt mir eine elektronische 
montage? Kann jemand mirhelfen?

Danke im Voraus.

Gruss carine

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
probier es doch erstmal ohen deine Interrupt Service Routine für AD 
Wandlung

sondern stoss über _delay_ms jede sek ein wandlung in der main an...

Was sucht das _delay_ms in der putc?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
carine schrieb:

> Ist eventuell ein Fehler in meinen Code? fehlt mir eine elektronische
> montage? Kann jemand mirhelfen?

Möglich.
Der Code ist so verworren, das man den erst einmal gründlich auseinander 
nehmen muss

Was hältst du davon, erst einmal die ADC-Routine aus dem Tutorial, so 
wie sie ist, zu benutzen. Und zwar ohne den ganzen Timer Klimbim
int main()
{
  uint16_t result;
  ...

  while( 1 ) {
    uint16_t result = ReadChannel( 0 );

    uart_Puts("\r\n\n");
    utoa( result, s, 10 );   
    uart_Puts( s );  
    uart_Putc('$');
  }
}

Die ReadChannel Funktion ist die Funktion aus dem Tutorial
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Wenn du danach immer noch seltsame Werte hast, könnte es ein Hardware 
Problem sein.
Wenn die Werte plausible aussehen, kannst du jetzt immer noch anfangen, 
die ReadChannel Funktion auseinanderzunehmen und umzugestalten. Tauchen 
dann plötzlich seltsame Werte auf, kann es nur noch mit deiner zuletztz 
durchgeführten Änderung zu tun haben.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Der Code ist so verworren

In der Tat. Bei dem geposteten Code kommt z.B. überhaupt nie eine 
ADC-Wandlung zustande. Der einzige ADC_Read Aufruf steckt im 
Timer-Overflow-Interrupt, aber der Timer wird überhaupt erst in ADC_Read 
in Gang gebracht. Es ist somit schon völlig unerklärlich, wie der OP 
überhaupt zu diesem Ergebnis kommt:
> ADC-Werte sind falsch. Für den selben Analog Eingang kriege ich
> Unterschiedliche Digital Wert.
> beispiel: für 2.04v ausgabe: 1023 oder 255 oder 3 oder 166 oder 875...
Da dürfte dann ja wohl mal wieder einiges an relevantem Code fehlen.

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielen Dank an alle für die viele Tipps,

leider könnte ich gestern wegen Internet unterbrechung nichts mehr 
machen.

jetzt habe ich eins zu eins den Tutorial Code copier, aber diesmal 
bekommen ich für irgend eine Spannung eingang 1023.

Wo liegt jetzt mein Fehler?
Danke für eure Hilfe im voraus
uint16_t ReadChannel(uint8_t mux)
{
  uint8_t i;
  uint16_t result;
 
  ADMUX = mux;                      // Kanal waehlen
  ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen
 
  ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler 
                               // setzen auf 8 (1) und ADC aktivieren (1)
 
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
  ADCSRA |= (1<<ADSC);              // eine ADC-Wandlung 
  while ( ADCSRA & (1<<ADSC) ) {
     ;     // auf Abschluss der Konvertierung warten 
  }
  result = ADCW;  // ADCW muss einmal gelesen werden,
                  // sonst wird Ergebnis der nächsten Wandlung
                  // nicht übernommen.
 
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
  result = 0; 
  for( i=0; i<4; i++ )
  {
    ADCSRA |= (1<<ADSC);        // eine Wandlung "single conversion"
    while ( ADCSRA & (1<<ADSC) ) {
      ;   // auf Abschluss der Konvertierung warten
    }
    result += ADCW;    // Wandlungsergebnisse aufaddieren
  }
  ADCSRA &= ~(1<<ADEN);         // ADC deaktivieren (2)
 
  result /= 4;              // Summe durch vier teilen = arithm. Mittelwert
 
  return result;
}

  
int main()
{
  uint16_t result;
  DDRC = 0x00;  //Define as Input
  PORTC = 0xFF;    //Enables Pull-Up on PC0

  uart_Init(); 
  
  uart_Puts("\r\n");
  uart_Puts("Messung gestartet:");

  while( 1 ) {
  result = ReadChannel( 0 );

    uart_Puts("\r\n\n");
    utoa( result, s, 10 );   
    uart_Puts( s );  
    uart_Putc('$');
  }
}

Autor: Lord Ziu (lordziu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo hast du denn bitte 's' deklariert?

Ich glaube nicht, dass das so ohne Compilerwarnung kompiliert.

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
s ist global deklariert
char s[20];

Build succeeded with 0 Warnings...

Autor: Lord Ziu (lordziu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie sieht denn die Beschaltung des ADC-Pins aus?

Autor: STK500-Besitzer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>bekommen ich für irgend eine Spannung eingang 1023.

Klingt irgendwie nach eingeschaltetem Pull-Up oder einem anderen 
Hardware-Fehler.

(Fehlerfrei) compilierbarer Code wäre übrigens sehr hilfreich.

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Analog Strom vom Laser ----- direckt an PINC.0
(Ich habe kein Poti benutzt weil der Strom im bereich 0v bis 2,005v 
liegt)
AREF------100n condensator (weil int AREF wird benutzt)

ist das richtig?
danke

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>STK500-Besitzer
dachte ich auch und habe ich den Pull-up ausgeschaltet, leider keine 
Änderung.

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
bitte hilfe!!!
ich glaube, dass mein Fehler an der Schaltung liegt!!!!!

Autor: Lord Ziu (lordziu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
carine schrieb:
> bitte hilfe!!!
> ich glaube, dass mein Fehler an der Schaltung liegt!!!!!

Tja, nur wenn du sie uns nicht ordnetlich zeigst, woher sollen wir 
wissen, WIE deine Schaltung aussieht?

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Analog Strom vom Laser ----- direckt an PINC.0
(Ich habe kein Poti benutzt weil der Strom im bereich 0v bis 2,005v
liegt)

lies mal bitte noch mal den Unterschied von Strom und Spannung nach...

Was kommt von deinem Sensor? ein Strom oder eine Spannung? Wenn eine 
Spannung was zeigt das Multimeter an?

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
entschuldigung Spannung meine ich

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das Multimeter zeigt 1,8v jetzt.
Aber für den Analog Wert bekomme ich 1023 angezeigt

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> PORTC = 0xFF;    //Enables Pull-Up on PC0
> Analog Strom vom Laser ----- direckt an PINC.0

Warum schaltest du die Pull-ups an PC0 an?

> AREF------100n condensator (weil int AREF wird benutzt)

Wo ist der Kondensator noch angeschlossen?
Schaltplan wäre gut!

Wie ist das STK500 gejumpert, speziell der VTARGET und der AREF Jumper? 
Bei "interne Referenzspannung" im Programm würde ich den AREF Jumper 
entfernen.
http://www.atmel.com/dyn/resources/prod_documents/...

>  ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen
Internal 2.56V Voltage Reference with external capacitor at AREF pin

> (Ich habe kein Poti benutzt weil der Strom im bereich 0v bis 2,005v liegt)
Bist du 100% sicher, dass die zu messende Spannung nicht über Internal 
2.56V Voltage Reference liegt. Wurde das schon im Betrieb nachgemessen? 
Wie wurde das gemessen? Besteht eine Chance kurzzeitige 
Spannungsüberschreitungen zu sehen?

Nicht vergessen der ADC soll laut Datenblatt mit 50 bis 200 kHz messen!

>> 2. extene Quarz 4 Mhz
> ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    // Frequenzvorteiler
> // setzen auf 8 (1) und ADC aktivieren (1)

Vorteiler 8 ist nicht ausreichend. Stell mal einen höheren ein.


Dabei auch beachten, dass die 2.56V kein in Stein gemeisselter Wert 
sind. Der Wert hängt von der Bandgap Referenz ab und die ist abhängig 
von der Versorgungsspannung und der Temperatur.

Ich würde versuchsweise mal AVcc als Referenz einstellen.
ADMUX |= (1<<REFS0); // AVcc als Referenz verwenden

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antwort.
Aber ist das Problem immer noch nich gelöst, weil für unterschiedlichen 
Werte wird anstatt 1023, jetzt 16 angezeigt.

Initialisierung:
void ADC_Init (uint8_t Mux_channel)
{
  ADCSRA = (1<<ADEN);   //Enables the ADC
  ADCSRA |= (1<<ADPS2) | (1<<ADPS0); // ADC Prescaler 32 --> 4Mhz/32 = 125kHz Tmin = 20 , Tmax = 80   
  ADMUX = Mux_channel;    //pin ADC0
  ADMUX |= (1<<REFS0); // AVcc als Referenz verwenden
  ADMUX |= (0<<ADLAR);  //The result is right adjusted
}
Ich habe keine Software um Schaltungen aufzuzeichnen, ich hoffe dies 
wird verständlich sein:

AREF----100nF---GND
Analog eingang Spannung-----100K poti-----Masse
                              |
                              |
                             PCO

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe der Spannung am AREF von atmega8 gemessen.
Ich merke, dass die Spannung wackeln (Es wird immer weniger).
Ist das normal? wieso verändern sich die Spannung?
danke für euere Hilfe

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und sobald ich mit dem Multimeter messen will vergrössert sich der 
angezeigt Didigitalwert

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mal 'ne ganz blöde Frage: AVCC ist aber schon auch angeschlossen, oder?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>> PORTC = 0xFF;    //Enables Pull-Up on PC0
>> Analog Strom vom Laser ----- direckt an PINC.0
>Warum schaltest du die Pull-ups an PC0 an?

Ist das verbessert? IMHO ist es kontraproduktiv per Pull-up Vcc auf den 
ADC Messeingang zu geben.

> Analog eingang Spannung-----100K poti-----Masse
>                               |
>                               |
>                              PCO

Das 100k Poti hättest du ganz am Anfang erwähnen müssen!

Warum ist das überhaupt drin?

Wo steht der Schleifer bei deinen Experimenten?

Was sagt das Atmega8 Datenblatt zu dem u.U. riesigen Widerstand in der 
zu messenden Leitung?

Kommt durch diese künstliche Einschürung der Messleitung innerhalb der 
Messzeit überhaupt genügend Saft an den ADC?

Aus dem Atmega8 Datenblatt:

"The ADC is optimized for analog signals with an output impedance of 
approximately 10 kΩ or less. If such a source is used, the sampling time 
will be negligible. If a source with higher impedance is used, the 
sampling time will depend on how long time the source needs to charge 
the S/H capacitor, with can vary widely. The user is recommended to only 
use low impedant sources with slowly varying signals, since this 
minimizes the required charge transfer to the S/H capacitor."

> Initialisierung:
> void ADC_Init (uint8_t Mux_channel)

Initialisierst du jetzt zweimal? Einmal in dem ADC_Init() und einmal in 
dem ReadChannel() aus 
Beitrag "Re: ADC wert über RS232 senden"

Würde ich nicht machen. Ich würde bei einer Programmversion bleiben.

> Aber ist das Problem immer noch nich gelöst, weil für unterschiedlichen
> Werte wird anstatt 1023, jetzt 16 angezeigt.

Du hast leider keinen Quellcode angegeben, bei der man sieht, wie du den 
ADC Wert einlesen tust.

Die Timer-Variante (Beitrag "ADC wert über RS232 senden") 
hatten wir ja schon verworfen

Und die ReadChannel()-Variante 
(Beitrag "Re: ADC wert über RS232 senden") hast du 
anscheinend abgeändert indem du eine ADC_Init() geschrieben hast.

Offen ist: Wie und wo wird ADC_Init() aufgerufen. Wie und wo werden die 
Ergebnisse der Wandlung eingelesen, gibt es ein verändertes 
ReadChannel()?

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>Mal 'ne ganz blöde Frage: AVCC ist aber schon auch angeschlossen, oder?

ADMUX |= (1<<REFS0); entspricht im Datenblatt AVCC with external 
capacitor at AREF pin

deswegen habe ich
AREF----100nF---GND
bei mir ist gar nichts an AVCC angeschlossen.

habe ich etwas falsch verstanden!!?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja. AVcc und AGND muss immer angeschlossen werden. Das sollte aber auf 
dem STK500 automatisch erledigt werden (Vcc---AVcc und GND---AGND)

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie sieht es hiermit aus:

> Wie ist das STK500 gejumpert, speziell der VTARGET und der AREF Jumper?
> Bei "interne Referenzspannung" im Programm würde ich den AREF Jumper
> entfernen.

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, danke

AREF-Jumper ist nicht gesetzt
VTARGET-Jumper ist gesetzt

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ok, gut so.

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich benutze den STK500 und Prozessor Atmega8
und finde keine AGND!

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> AVcc und AGND muss immer angeschlossen werden. Das sollte aber auf
>>dem STK500 automatisch erledigt werden (Vcc---AVcc und GND---AGND)

ich finde keine Pin für AVCC und AGND um die beide anzuschliessen, ich 
nehme also an dass es vom STK500 schon gemacht wurde.

am PORTE/AUX
schliessen ich an
PE4 (REF)-------100nF--------PE5 (GND)

ist das so richtig ?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja.

Woher kommt deine Messspannung und was ist deren Bezugspunkt (Masse, 
GND)? Ist dieses GND das gleiche, wie das GND des STK500 oder - im 
anderen Fall - sind beide GNDs miteinander verbunden? => Schaltplan?

Deine Messungen mit dem Multimeter: Wo genau befinden sich die 
Kontaktpunkte der Messleitungen an der Schaltung?

Bereits gestellte und noch offene Fragen:
Was ist mit dem 100k Poti?
Wie sieht der aktuelle Quellcode aus?

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>Das 100k Poti hättest du ganz am Anfang erwähnen müssen!
>>Warum ist das überhaupt drin?
>>Wo steht der Schleifer bei deinen Experimenten?

ICh will eine Spanung von ov bis 2,05v messen, um sicher zu sein, dass 
meine zu messende Spannung nicht die Internal Ref 2.56 überschreit, 
benutze ich das Poti.
Wo der Schleifer steht, kann ich nicht genau sagen.
Aber für Spannung eingang 1,8v zum Beipiel habe ich 1,6v am PCO.
Und jetzt benutze ich 1k Poti.

Analog eingang Spannung-----1K poti-----Masse
                              |
                              |
                             PCO

>>Woher kommt deine Messspannung und was ist deren Bezugspunkt (Masse,
>>GND)? Ist dieses GND das gleiche, wie das GND des STK500 oder - im
>>anderen Fall - sind beide GNDs miteinander verbunden? => Schaltplan?

Messspannung kommt aus einer Laser (DT50 vom Sick)

(GND = Masse) verbunden mit GND von STK500


>>Wie sieht der aktuelle Quellcode aus?
#include <avr/io.h>
#include <inttypes.h>
#include <stdlib.h>

#include "uart.h"

//defineglobal variables
int ADIteiler=0;
char s[20];

uint16_t ReadChannel(uint8_t mux)
{
  uint8_t i;
  uint16_t result;
 
  ADCSRA = (1<<ADEN);   //Enables the ADC
  ADCSRA |= (1<<ADPS2) | (1<<ADPS0); // ADC Prescaler 32 --> 4Mhz/32 = 125kHz Tmin = 20 , Tmax = 80   
  ADMUX = Mux_channel;    //pin ADC0
  ADMUX |= (1<<REFS0); // AVcc als Referenz verwenden
  ADMUX |= (0<<ADLAR);  //The result is right adjusted

  while ( ADCSRA & (1<<ADSC) ) {
     ;     // auf Abschluss der Konvertierung warten 
  }
  result = ADCW; 
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
  result = 0; 
  for( i=0; i<4; i++ )
  {
    ADCSRA |= (1<<ADSC);      // eine Wandlung "single conversion"
    while ( ADCSRA & (1<<ADSC) ) {
      ;   // auf Abschluss der Konvertierung warten
    }
    result += ADCW;        // Wandlungsergebnisse aufaddieren
  }

  ADCSRA &= ~(1<<ADEN);           // ADC deaktivieren 
  result /= 4;             // Summe durch vier teilen = arithm. Mittelwert 
  return result;
}

  
int main()
{
  uint16_t result;
  DDRC = 0x00;  //Define as Input
  uart_Init(); 
  
  uart_Puts("\r\n");
  uart_Puts("Messung gestartet:");

  while( 1 ) {
    result = ReadChannel( 0 );

    uart_Puts("\r\n\n");
    utoa( result, s, 10 );   
    uart_Puts( s );  
    uart_Putc('$');
  }
}

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
carine schrieb:

> Messspannung kommt aus einer Laser (DT50 vom Sick)

http://www.sick.co.uk/de/products/productnews/indu...
DT50 - Abstandsensor mit Analogausgang
    * HDDM - modernste Lichtlaufzeittechnologie
    * Messbereich 200 ... 10.000 mm
    * 4... 20 mA Analogausgang + zusätzlich 1x PNP Schaltausgang
      ^^^^^^^^^^^^^^^^^^^^^^^^
    * Display mit intuitiv bedienbarer Menüführung
    * Fremdlichtsicher bis 40 klux
    * Großer Betriebstemperaturbereich von -30 °C bis +65 °C
    * Robustes Druckguss-Zinkgehäuse 

Der Sensor gibt also analog 4 mA (minimaler Abstand) bis 20 mA 
(maximaler Abstand) aus.

Das wäre in den Bereich ca. 0V (minimaler Abstand) bis ca. Aref 
(maximaler Abstand) umzuformen.

Das Umformen kann nach dem Ohmschen Gesetz U = R * I mit einem 
Widerstand gemacht werden.

Sensor Out o----------+----------o ADC0 (PC0) µC
                      |
                      #
                    R #
                      #
                      |
Sensor GND o----------+----------o AGND (GND) µC

Angenommen du hast Aref auf Vcc (5V) eingestellt. Dann soll bei Imax. = 
20 mA die maximale Spannung 5V an R abfallen:
R <= 5V / 20 mA <= 250 Ohm

Wenn du für R einen 1 kOhm Poti nimmst:

Sensor Out o----------+
                      |
                      #
                    R #<---------o ADC0 (PC0) µC
                      #
                      |
Sensor GND o----------+----------o AGND (GND) µC

Dann fällt an R eine max. Spannung von 20 mA * 1 kOhm = 20V ab, wenn der 
Sensor versucht 20 mA auszugeben. Damit der Sensor das schafft müsste er 
allerdings eine Spannung von 20V an Sensor Out ausgeben. Bei einer 
Betriebsspannung des DT50 von 10..30V wäre das sogar denkbar.

Bei dem 100 kOhm Poti kann der Sensor allerdings nur bis zu seiner 
Betriebsspannung schuften, die 2000 V um 20 mA zu treiben, wird er nicht 
schaffen...

Steht in diesen Fällen der Schleifer des Potis ganz oben, ist der µC 
vielleicht Geschichte, weil die Absolute Maximal Electrical Ratings 
überschritten werden (ADC0 Eingangsspannung >> Vcc+0,5V).

Zurück zu den 250 Ohm...

Beim unteren Messwert (Mindestabstand) liefert der Sensor 4 mA. Das 
ergibt nach der Umformung U = 4 mA * 250 Ohm = 1 V.

Dein 4 mA .. 20 mA Sensorsignal wird also in ein ca. 1 V .. ca. 5 V 
Spannungssignal umgeformt. Das ca. weil die Präzision von R und 
Leitungswiderstände zusammenwirken.  Du musst deinen ADC Messwert 
kalibrieren.

Wenn du max. 2,56 V haben willst, dann wäre R <= 2,56 V / 20 mA <= "128" 
Ohm. Der Messbereich wäre dann 0,512V...2,56V

>>>Wie sieht der aktuelle Quellcode aus?
>   ADMUX |= (1<<REFS0); // AVcc als Referenz verwenden
>   ADMUX |= (0<<ADLAR);  //The result is right adjusted

Hier fehlt das Einschalten der ADC Single Conversion. Die nächste 
Schleife ist deswegen endlos. Das gezeigte Programm kann keine Werte 
ausgeben!

>   while ( ADCSRA & (1<<ADSC) ) {
>      ;     // auf Abschluss der Konvertierung warten
>   }

Abhilfe:

ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" auslösen

vor der while-Schleife einfügen.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stopp, Fehler meinerseits, die Schleife ist nicht endlos, sondern 
rauscht direkt durch. Der Sinn der Schleife (Dummyreadout des ersten 
ADC-Wertes) wird verfehlt. Die vorgeschlagene Zeile sollte dennoch 
eingefügt werden.

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielen Dank Stefan

Wenn du max. 2,56 V haben willst, dann wäre R <= 2,56 V / 20 mA <= "128"
Ohm. Der Messbereich wäre dann 0,512V...2,56V

ich habe einen Wiederstand R=100 Ohm genohmen und so angeschlossen

Sensor Out o----------+----------o ADC0 (PC0) µC
                      |
                      #
                    R #
                      #
                      |
Sensor GND o----------+----------o AGND (GND) µC

>>Dein 4 mA .. 20 mA Sensorsignal wird also in ein ca. 1 V .. ca. 5 V
>>Spannungssignal umgeformt. Das ca. weil die Präzision von R und
>>Leitungswiderstände zusammenwirken.  Du musst deinen ADC Messwert
>>kalibrieren.
Wie mache ich die Kalibrierung?
versuche ich noch es hinzukriegen.
und melde mich dann wieder

>>Abhilfe:
>>ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" auslösen

ja, schon korriegiert

Autor: carine (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielen vielen Dank
problem gelöst.

Problem
vorher:
GND sensor -------GND voltmeter(12v Betriebsspannung des DT50 )

lösung:
)

Sensor Out o----------+
                      |
                      #
                    R #<---------o ADC0 (PC0) µC
                      #
                      |
Sensor GND o----------+----------o AGND (GND) µC

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.