mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ADC, uint16_t und Multiplikationsproblem


Autor: Daniel S. (daniels)
Datum:

Bewertung
0 lesenswert
nicht 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.
int main(void)
{
/* PWM starten */
PORTB = 0x00;  //Alle Bit's löschen
DDRB = 0xFF;  //PortB als Ausgang beschalten für die PWM
PWM_init();    //Die PWM starten


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

uint8_t DC = 0;        

int x=1;
uint16_t strom=0;
uint16_t spannung=0;
uint32_t leistung=0;

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

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

  for(int i=0; i<=30; i++)
  {
    OCR0 = pwmoffset + i;
    Delay(); //Delay() ist ne Wartefunktion von mir
    Delay();
    strom = ADCRead(2);
    Delay();
    spannung = ADCRead(1);
    Delay();
    leistung = strom * spannung;
    if(leistung>=60000) //Wenn die Leistung einen bestimmten
                                    //Wert überschreitet, stehenbleiben
    {
      i=40;
      x=0;
    }    
  }
  x=0;
}

/* ENDE WHILE SCHLEIFE!!! */
}

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

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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Niemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Daniel S. (daniels)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Daniel S. (daniels)
Datum:

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

Autor: Niemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Niemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deine Grenze ist noch zu hoch 80*700 ergibt 56000.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> if(leistung>=60000)
Versuch mal
if(leistung>=60000UL)

Autor: Daniel S. (daniels)
Datum:

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

Autor: Daniel S. (daniels)
Datum:

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

Autor: Daniel S. (daniels)
Datum:

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

Autor: Niemand (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das macht aus deiner Zahl ein unsigned long.

Autor: Daniel S. (daniels)
Datum:

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

Autor: Thomas B. (detritus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ausserdem
    leistung = strom * spannung;

umbauen zu
    leistung = (uint32_t) strom * spannung;

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas B. wrote:
>
>     leistung = (uint32_t) strom * spannung;
> 
Richtig, das hatte ich auch übersehen...

Autor: Norgan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
leistung = strom * spannung;
leistung = (uint32_t)strom * (uint32_t)spannung;

Autor: Thomas B. (detritus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Einmal casten tuts auch.

Autor: Daniel S. (daniels)
Datum:

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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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...

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

Bewertung
0 lesenswert
nicht 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.

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.