Forum: Mikrocontroller und Digitale Elektronik ADC, uint16_t und Multiplikationsproblem


von Daniel S. (daniels)


Lesenswert?

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

von Johannes M. (johnny-m)


Lesenswert?

Hast Du es mal mit einem "standardkonformen" break anstelle des "i = 
40" versucht? In welchem Bereich liegen denn überhaupt die mit ADCRead 
erfassten Werte?

von Niemand (Gast)


Lesenswert?

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.

von Daniel S. (daniels)


Lesenswert?

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.

von Daniel S. (daniels)


Lesenswert?

@Niemand
Ja genau sowas war auch meine Vermutung, nur beweisen kann ich es leider 
nicht.

von Niemand (Gast)


Lesenswert?

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.

von Niemand (Gast)


Lesenswert?

Deine Grenze ist noch zu hoch 80*700 ergibt 56000.

von Johannes M. (johnny-m)


Lesenswert?

> if(leistung>=60000)
Versuch mal
if(leistung>=60000UL)

von Daniel S. (daniels)


Lesenswert?

Wieso zu hoch, ein 16Bit Wert hat doch 65536. Und die Leistung ist ein 
32Bit Wert. Das sollte doch so passen?!

von Daniel S. (daniels)


Lesenswert?

was macht das UL wenn ich mal so fragen darf? werd's gleich testen.

von Daniel S. (daniels)


Lesenswert?

Bitte verrat mir mal was dieses UL macht, weil das scheint zu 
funktionieren, da er bei der eingestellten Leistung stoppt! DANKE DANKE 
DANKE!

von Niemand (Gast)


Lesenswert?

Das macht aus deiner Zahl ein unsigned long.

von Daniel S. (daniels)


Lesenswert?

Alles klar. Ich meld mich später nochmal ob's so läuft wie ich mir das 
vorstelle. Schonmals vielen DANK!

von Thomas B. (detritus)


Lesenswert?

Ausserdem
1
    leistung = strom * spannung;

umbauen zu
1
    leistung = (uint32_t) strom * spannung;

von Johannes M. (johnny-m)


Lesenswert?

Thomas B. wrote:
>
1
>     leistung = (uint32_t) strom * spannung;
2
>
Richtig, das hatte ich auch übersehen...

von Norgan (Gast)


Lesenswert?

1
leistung = strom * spannung;
1
leistung = (uint32_t)strom * (uint32_t)spannung;

von Thomas B. (detritus)


Lesenswert?

Einmal casten tuts auch.

von Daniel S. (daniels)


Lesenswert?

Das mit dem casten funktioniert. Das mit dem UL hat ohne das casten 
(uint32_t) nichts gebracht. Dann vielmals Dankeschön!!!

von Johannes M. (johnny-m)


Lesenswert?

Daniel S. wrote:
> Das mit dem casten funktioniert. Das mit dem UL hat ohne das casten
> (uint32_t) nichts gebracht. Dann vielmals Dankeschön!!!
Kann es auch nicht...

von Karl H. (kbuchegg)


Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.