ADC Problem und anliegen zu "FLAG"

OP #4432818
Hallo,

ich lese einen Fotowiderstand mittels ADC aus. Das klappt auch soweit. 
Den Wert speichere ich und lasse ihn mir auf einem Display ausgeben.

Allerdings "springt" der Wert während der Wandlung. Also alle 5 Sekunden 
ticken die Zahlen da ganz schnell und dann ist der Wert wieder konstant. 
Also jedesmal während der Wandlung.

Wie umgehe ich dieses Problem?

Der Wert des ADCs kann ja 0 - 1023 sein. Soweit so gut. Ich benötige 
allerdings einen Wert von 0 - 100. Die Umrechnung will irgendwie nicht 
so ganz.

Also der Fotowiderstand soll die Display Helligkeit regeln. Diese geht 
von 0 - 100. Also je Heller es ist um so Heller auch das Display.

Der ADC wird mit einem 4,7k gepullt. Der Fotowiderstand schaltet GND.

Jedoch klappt das nicht so ganz sondern genau andersrum. Wie 
"invertiere" ich den Wert nun? Also jetzt ist es so, je dunkler es ist 
um so heller das Display.

Hier mal der ADC Code
1
/* ADC initialisieren */
2
void ADC_Init(void)
3
{
4
  ADMUX = (1<<REFS0);    
5
  ADCSRA = (1<<ADPS2) |(1<<ADPS1) | (1<<ADPS0);
6
  ADCSRA |= (1<<ADEN);
7
  ADCSRA |= (1<<ADSC);
8
  while (ADCSRA & (1<<ADSC) ) {}
9

10
  (void) ADCW;
11
}
12
 
13
uint16_t ADC_Read( uint8_t channel )
14
{
15
  ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
16
  ADCSRA |= (1<<ADSC);
17
  while (ADCSRA & (1<<ADSC) ) {}
18
  return ADCW;
19
}
20

21

22
void read_fotowiderstand(void)
23
{  
24
  if (sekunde%10 == 0) {
25
    
26
      fotowid_temp = ADC_Read(6);
27
    
28
      if ( fotowid_temp > 1000)
29
        {
30
          bcdata[FOTOWIDERSTAND] = ((1000  / 10) - 100) + 100;
31
        }
32
        else
33
        {
34
          bcdata[FOTOWIDERSTAND] = ((fotowid_temp / 10) - 100) + 100;
35
        }
36
    }
37
}

Dann habe ich noch ein Problem mit den sogenannten "Flags".

Also ich habe folgenden Code:
1
void read_tuertaster(void)
2
{
3
  if ( !(PING & (1<<PING0)) )
4
  {
5
    bcdata[TUERLINKS_OPEN] = 1;
6
  }
7
  else
8
  {
9
    bcdata[TUERLINKS_OPEN] = 0;
10
  }
11
  
12
  if ( !(PING & (1<<PING1)) )
13
  {
14
    bcdata[TUERRECHTS_OPEN] = 1;
15
  }
16
  else
17
  {
18
    bcdata[TUERRECHTS_OPEN] = 0;
19
  }
20
}

Hier brauche ich nun eine Funktion die bei einer 1 einen PIN für 100ms 
auf HIGH schaltet. Aber nur einmal. Ob der Wert weiter 1 bleibt oder 
nicht. Und erst wenn er sich auf 0 ändern den PIN für 300ms HIGH 
schaltet. Wenn er dann wieder 1 ist für 100ms usw.

Wie macht man das mit diesen "flags"?

Ein Timer im ms Bereich ist vorhanden und funktioniert Einwand frei.

Ich danke euch schon mal.
Gast #4433113
>         {
>           bcdata[FOTOWIDERSTAND] = ((1000  / 10) - 100) + 100;
>         }
>         else
>         {
>           bcdata[FOTOWIDERSTAND] = ((fotowid_temp / 10) - 100) + 100;
>         }

Ich könnte mich ja wieder mal irren, aber warum (100-100)+100?

Das -100)+100 ergibt doch immer Null, nur dass der Wert in der Klammer 
erstmal negativ (oder groß positiv bei uint) wird.

Versuche doch diesen Pseudocode mal:

Wert=(1023-adcwert)/103

Gibt Werte bis (nahezu) 100.

Danach vielleicht eine Lookuptabelle als const in den Code schreiben.
#4433178
Bert B. schrieb:
> Divisionen auf dem AVR vermeide ich gerne:
>
> Wert=((1023-adcwert)*100)>>10;
>
> Gruß... Bert

Hm
1
Wert=((1023-adcwert)*100)/103;
ist aber nicht das Selbe wie
1
Wert=((1023-adcwert)*100)>>10;
schreibst.

Und heutige Compiler sind recht klug und erkennen eine Division durch 
eine Zweierpotenz (d.h die machen Automatisch eine Shift-Operation 
daraus). Für bessere Code-Lesbarkeit würde ich da eher eine Division 
(oder auch Multiplikation) benutzen statt eine Shift-Operation.

Felix Adam schrieb:
> Wert=(1023-adcwert)/103
>
> Gibt Werte bis (nahezu) 100.

Wie das? Bei deinem Pseudo-Code kommt bestenfalls was knapp unter 10 
raus, der ADC-Wert kann ja nicht negativ werden. Oder hast du dich nur 
vertippt und wolltest 10 schreiben?
#4433210
Michael K. schrieb:

> Hm
>
1
> Wert=((1023-adcwert)*100)/103;
2
>
> ist aber nicht das Selbe wie
>
1
> Wert=((1023-adcwert)*100)>>10;
2
>
> schreibst.

Hat ja auch niemand behauptet. Der Originalautor wollte aber den ADC auf 
Werte von 0-100 skaliert haben.

Du hast ja selbst geschrieben, daß die erste Codezeile das um den Faktor 
10 nicht erfüllt, meine aber schon.


Gruß... Bert
Gast #4433218
Eigentlich fehlt in meiner Rechnung das *10, bevor durch 103 geteilt 
wird. Dann hätte es gestimmt. Aber auf meinem kleinen Tablet ging mir 
das durch die Lappen...

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 10 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.