ADC, uint16_t und Multiplikationsproblem

OP #885393
Hallo zusammen,

vllt. ist das Problem leicht behoben, ich schätze ich mache einen 
Denkfehler. Also zuerst mal die Theorie welche dahinter steht.
Ich habe eine Strom und eine Spannungsmessung. Beide werden über OP's 
verstärkt. Beim Strommess-OP kommen hinten max. 2V raus, beim 
Spannungs-OP max. 2,5V(im Test kommen immer um die 1,75V raus, da 
konstante Spannung). Nun nehme ich die Werte mit dem ADC auf(10Bit, 
Referenz sind 2,56V).
Nun habe ich ein Programm geschrieben, welches mir den Strom, über ein 
PWM Signal mit anschließender Elektronik, einstellt.
Ich hatte dann in meinem Programm zwei Abfragen, welche mir Strom und 
Spannung überwachen und bei überschreiten eines bestimmten Stromes 
anhalten und den Strom auf den eingestellten Wert begrenzen. Soweit 
funktionierte das. Nun wollte ich aber nicht mehr über Strom und 
Spannung begrenzen, sondern über die Leistung.
Also einfach die Werte multiplizieren und fertig. Aber er läuft immer 
bis ans Ende der Schleife. Hat das vllt. was mit den Datentypen zu tun? 
Strom und Spannung sind uint16_t Typen, die Leistung muss dann also ein 
uint32_t Typ sein (16Bit*16Bit=32Bit). Denk ich mir zumindest! Der µC 
ist ein Mega32. Ich häng mal nur den Source vom eigentlichen Programm 
an, da der ADC und die PWM funktionieren.
1
int main(void)
2
{
3
/* PWM starten */
4
PORTB = 0x00;  //Alle Bit's löschen
5
DDRB = 0xFF;  //PortB als Ausgang beschalten für die PWM
6
PWM_init();    //Die PWM starten
7

8

9
uint8_t const pwmoffset = 126;  //ADC Offset von 2,5V(2^8*0.5)
10
                                //Der Offset wird von der Elektronik
11
                                //dahinter benötigt
12

13
uint8_t DC = 0;        
14

15
int x=1;
16
uint16_t strom=0;
17
uint16_t spannung=0;
18
uint32_t leistung=0;
19

20
while(1)  //Endlosschleife für den µC
21
{
22

23
/* TESTPROGRAMM */
24
while(x==1)
25
{
26
        //for-Schleife soll langsam den Strom erhöhen, PWM ist DAC als
27
        //Sollwertgeber für einen Tiefpass für die Elektronik
28

29
  for(int i=0; i<=30; i++)
30
  {
31
    OCR0 = pwmoffset + i;
32
    Delay(); //Delay() ist ne Wartefunktion von mir
33
    Delay();
34
    strom = ADCRead(2);
35
    Delay();
36
    spannung = ADCRead(1);
37
    Delay();
38
    leistung = strom * spannung;
39
    if(leistung>=60000) //Wenn die Leistung einen bestimmten
40
                                    //Wert überschreitet, stehenbleiben
41
    {
42
      i=40;
43
      x=0;
44
    }    
45
  }
46
  x=0;
47
}
48

49
/* ENDE WHILE SCHLEIFE!!! */
50
}
51

52
return 0; //Damit der Compiler nicht meckert, der Punkt wird allerdings nie erreicht!
53
}

Meine Vermutung liegt irgendwie darin, das er beim berechnen der 
Leistung ein Problem hat. Mit einer getrennten Abfrage von Strom und 
Spannung klappt's ja.
Kann das was mit dem uint32_t zu tun haben?
Hoffe das die Beschreibung in soweit verständlich ist!!!

Gruß Daniel
Gast #885418
Kann es sein, dass das Ergebnis nicht in das 32bit Register gepackt 
wird?

Ich hatte mal ein ähnliches Problem bei der Multiplikation mit einer 
Konstanten.
OP #885435
Das "break", nein da hab ich nicht mehr dran gedacht, ist alles schon 
etwas länger her. Werd ich aber versuchen. Aber wie gesagt, vorher bei 
der Stromabfrage hat's ja geklappt.
Die Werte des ADC liegen für
1) Strom bei 0 bis 80 (Ausgabe des ADC in Decimal)
2) Spannung bei 0 bis 700 (Ausgabe des ADC in Decimal)

Zu 1) 80 entspricht etwa 1A, bei dem er dann anhalten soll, was er auhc 
macht
Zu 2) Ich habe eine konstante Eingangsspannung von etwa 30V, das ergibt 
dann die 700.

Multipliziere ich die beiden Werte und überprüfe das Produkt, dann läuft 
er die Schleife bis zum Ende durch. Aber warum ist mir unerklärlich.
Gast #885455
Ich glaub mir ist das mal beim PIC passiert, da hat er nur die 16bit in 
das 32bit register geschrieben und den Rest weggeschmissen. Abhilfe war 
hier ein "cast" meiner Konstanten in einen 32bit Wert.
#885546
Hast du auch verstanden, warum das so ist?

Deine Variable 'leistung' ist zwar ein uint32_t, aber das
interessiert bei der Multiplikation herzlich wenig.

Bei jeder arithmetischen Operation sieht sich der Compiler
die beteiligten Operanden an. In deinem (ursprünglichen) Fall
sind das 2 Stück uint16_t. Also wird die Multiplikation auch
als 16 Bit unsigned Multiplikation ausgeführt. Erst danach
wird nachgesehen, was mit diesem Ergebnis passieren muss, damit
es in einen uint32_t geschoben werden kann.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 18 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.