Forum: Compiler & IDEs Endlosschleife


von Kilian H. (qwert)


Lesenswert?

Hallo,

ich versuche gerade, einen PWM zu programmieren. Nur zu Testzwecken habe 
ich folgenden Codeabschnitt programmiert:
1
int main(void) {
2
  double X, Xold, Xp, Xd, P, D;
3
4
  P = 0.1;
5
  D = 60;
6
7
  DDRB = 0xff;
8
  PORTB = 0x00;
9
  
10
  ADMUX = (1<<REFS0);
11
  ADCSRA = (1<<ADEN)|(1<<ADPS2);
12
13
  TCCR0 = (1<<CS00);
14
  TIMSK = (1<<TOIE0);
15
16
  sei();
17
18
19
  while(1) {    
20
    pwm = 128;
21
...

Setze ich die lezte Zeile "pwm = 128" vor die while-Schleife, so 
funktioniert meine Regelung. In der while-Schleife aber nicht mehr.

Ich habe leider überhaupt keine Idee an was das liegen könnte.

Vielen Dank für eure Unterstützung! :)

von Nicolas S. (Gast)


Lesenswert?

Welche Farbe hat denn die Tischdecke?

von Peter II (Gast)


Lesenswert?

Kilian Herbst schrieb:
> Ich habe leider überhaupt keine Idee an was das liegen könnte.

wenn es spannend wird, ist leider der sichtbare code zu ende.

von Rene H. (Gast)


Lesenswert?

Zeig mal bitte die ganze while Schleife.

Grüsse,
René

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Kilian Herbst schrieb:
>   while(1) {
>     pwm = 128;
> ...
>
> Setze ich die lezte Zeile "pwm = 128" vor die while-Schleife, so
> funktioniert meine Regelung. In der while-Schleife aber nicht mehr.

Der Rest der while() wäre interessanter.

Dadurch dass die Zuweisung innerhalb der while() steht, wird der 
Variable "pwm" zu Beginn jedes Durchlaufes erneut der Wert 128 
zugewiesen. Vermutlich willst du aber eben diese Variable stetig ändern.

von Marc (gierig) Benutzerseite


Lesenswert?

Kilian Herbst schrieb:

> Setze ich die lezte Zeile "pwm = 128" vor die while-Schleife, so
> funktioniert meine Regelung. In der while-Schleife aber nicht mehr.

Denkst du nicht das der Rest des Codes auch Interesant ist ?

von Kilian H. (qwert)


Lesenswert?

Der Rest der while-Schleife:
1
    for(int i=0; i< 8;i++) {
2
      X =  X + ADC_Read();
3
    }
4
    X = X/8;
5
    if(X < 512) X = 512;
6
    Xp = X - 512;
7
    Xp = Xp * P;
8
    
9
    Xd = X - Xold;
10
    Xold = X;
11
    Xd = Xd * D;
12
  
13
    Y = Xp + Xd;
14
    Y = Y/2;
15
    
16
    if(Y > 255) Y = 255;
17
    if(Y < 0) Y = 0;

Den habe ich nicht mit gepostet, weil der an der Variable pwm nichts 
ändert. (soll er natürlich in der Endversion dann schon machen)

Wenn ich in die Main-Methode einfach nur pwm=128; schreibe, funktioniert 
es - die Leuchtdioden blinken also. Schreibe ich aber:
1
while(1) { pwm = 128;}

Dann geht gar nichts, die LEDs bleiben aus.

von Nicolas S. (Gast)


Lesenswert?

Ich habe schon lange keinen Quelltext mehr gesehen, der mit "int(main)" 
anfängt.

von Peter II (Gast)


Lesenswert?

Kilian Herbst schrieb:
> Wenn ich in die Main-Methode einfach nur pwm=128; schreibe, funktioniert
> es - die Leuchtdioden blinken also. Schreibe ich aber:while(1) { pwm =
> 128;}
>
> Dann geht gar nichts, die LEDs bleiben aus.

wie wissen nicht wo PWM überhaupt verwendet wird. Wenn wir das nicht 
sehen das können wir nicht helfen.

von Nicolas S. (Gast)


Lesenswert?

P.S.: Zumindest keinen, der funktioniert.

von Marc (gierig) Benutzerseite


Lesenswert?

> while(1) { pwm = 128;}

Wenn du das so schreibst kein wunder, die Schleife wird
ja nie verlassen.

die PWN var taucht in deinem Codefragmentauch nicht wieder auf
und ist auch nirgentwo definiert/declariert.
Also auch unötig und kann wegbleiben.


Kilian Herbst schrieb:
> Der Rest der while-Schleife:

BITTE, den ganzen code, mit allen drum und dran. Keine Fragmente
oder einzelne Zeilen Stück für Stück preisgeben.

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

- Wie sieht dein TOIE0 Interrupthandler aus?
- ist "pwm" als volatile deklariert?

von Kilian H. (qwert)


Lesenswert?

Ok, hier der ganze Quelltext ;): Teilweise habe ich den aus dem 
avr-Tutorial genommen. Das mit dem int(main) habe ich hieraus:
http://www.kreatives-chaos.com/artikel/codeschnipsel-avr-gcc

Ich weiß, dass ADC_init() nicht aufgerufen wird, das sollte aber mein 
Problem nicht beeinträchtigen.
1
#include <avr/io.h>
2
#include <util/delay.h>
3
#include <stdlib.h>
4
#include <stdint.h>
5
#include <avr/interrupt.h>
6
7
8
uint8_t pwm = 0, cnt = 0;
9
uint16_t Y = 0;
10
11
void ADC_Init(void) {
12
 
13
  uint16_t result;
14
 
15
  // die Versorgungsspannung AVcc als Refernz wählen:
16
  ADMUX = (1<<REFS0);    
17
  // oder interne Referenzspannung als Referenz für den ADC wählen:
18
  // ADMUX = (1<<REFS1) | (1<<REFS0);
19
 
20
  // Bit ADFR ("free running") in ADCSRA steht beim Einschalten
21
  // schon auf 0, also single conversion
22
  ADCSRA = (1<<ADPS1) | (1<<ADPS0);     // Frequenzvorteiler
23
  ADCSRA |= (1<<ADEN);                  // ADC aktivieren
24
 
25
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
26
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
27
 
28
  ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung 
29
  while (ADCSRA & (1<<ADSC) ) {         // auf Abschluss der Konvertierung 
30
31
warten
32
  }
33
  /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
34
     Wandlung nicht übernommen. */
35
  result = ADCW;
36
}
37
38
uint16_t ADC_Read()
39
{
40
  ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
41
  while (ADCSRA & (1<<ADSC) ) {   // auf Abschluss der Konvertierung warten
42
  }
43
  return ADCW;                    // ADC auslesen und zurückgeben
44
}
45
46
int main(void) {
47
  double X, Xold, Xp, Xd, P, D;
48
49
  P = 0.1;
50
  D = 60;
51
52
  DDRB = 0xff;
53
  PORTB = 0x00;
54
  
55
  ADMUX = (1<<REFS0);
56
  ADCSRA = (1<<ADEN)|(1<<ADPS2);
57
58
  TCCR0 = (1<<CS00);
59
  TIMSK = (1<<TOIE0);
60
61
  sei();
62
63
  while(1) {
64
                pwm = 128;
65
    for(int i=0; i< 8;i++) {
66
      X =  X + ADC_Read();
67
    }
68
    X = X/8;
69
    if(X < 512) X = 512;
70
    Xp = X - 512;
71
    Xp = Xp * P;
72
    
73
    Xd = X - Xold;
74
    Xold = X;
75
    Xd = Xd * D;
76
  
77
    Y = Xp + Xd;
78
    Y = Y/2;
79
    
80
    if(Y > 255) Y = 255;
81
    if(Y < 0) Y = 0;
82
  }
83
84
  return 0;
85
}
86
87
ISR (TIMER0_OVF_vect) {
88
  uint8_t temp = 0x00;
89
  cnt++;
90
  if(cnt == 0xff)
91
    cnt = 0;
92
  if(cnt < pwm)
93
    temp = 0xff;
94
  PORTB = temp;
95
}

von ich (Gast)


Lesenswert?

Deklariere mal pwm als volatile...

von Kilian H. (qwert)


Lesenswert?

Das war die Lösung! Vielen Dank! :)

von Falk B. (falk)


Lesenswert?

zum Thema volatile, siehe Interrupt

von Martin K. (maart)


Lesenswert?

Kilian Herbst schrieb:
> Das war die Lösung! Vielen Dank! :)

Perfekt! Und den int main(void)-Unken kann man klammheimlich den 
Mittelfinger zeigen.

von Nicolas S. (Gast)


Lesenswert?

Martin Kreiner schrieb:
> Und den int main(void)-Unken kann man klammheimlich den
> Mittelfinger zeigen.

Wenn Dich das glücklich macht. Wobei Du zugeben must, daß der Fehler im 
Quelltext erst dann gefunden wurde, als er nicht mehr mit "main" sondern 
mit den Includes anfing.

von Kilian H. (qwert)


Lesenswert?

Falk Brunner schrieb:
> zum Thema volatile, siehe Interrupt

Danke, aber volatile und co. ist mir hinlänglich aus Java bekannt :), 
hab nur in dem anderen Kontext das Problem völlig vergessen.

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Kilian Herbst schrieb:
> uint16_t Y = 0;
(...)
>     if(Y < 0) Y = 0;

Dieses "if" ist übrigens für den Allerwertesten.

von Peter S. (psavr)


Lesenswert?

>Kilian Herbst schrieb:
>> uint16_t Y = 0;
>(...)
>>     if(Y < 0) Y = 0;
>
>Dieses "if" ist übrigens für den Allerwertesten.
Das merkt der Compiler zum Glück  selber und schmeisst den unnötigen 
Code gleich in den Mülleimer.

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.