Forum: Mikrocontroller und Digitale Elektronik Probleme bei Programmausführung


von Marius S. (fhler)


Lesenswert?

Hallo,

mein ATmega16 führt das draugeflashte Programm zunächst richtig aus.

Dann stoppt er. Macht Quatsch.

Danach geht es dann wieder Ordnungsgemäß.

Dann stoppt er. Macht Quatsch.

Danach geht es dann wieder Ordnungsgemäß.

Dann stoppt er. Macht Quatsch.

[...]

Bis er schließlich ganz aufgibt.


Es sind auch keine festen Zeitabstände dazwischen.


Ordnungsgemäß heisst: PORTC verschieden setzen. (Ausgang)


Entw-Board: easyAV6. Die ADC´s sind in Betrieb, ein LCD an PORT B und 
eine PWM an PD5.

Ich hab den uC auch schon ausgetauscht.

Da der Code länger ist wollte ich Ihn hier nicht direkt posten.

von 42 (Gast)


Lesenswert?

Marius S. schrieb:
> Macht Quatsch.
Was genau?

> Da der Code länger ist wollte ich Ihn hier nicht direkt posten.
Meine Glaskugel wird gerade repariert.

von Peter II (Gast)


Lesenswert?

Marius S. schrieb:
> Da der Code länger ist wollte ich Ihn hier nicht direkt posten.

dann können wir aber auch nicht helfen.

Vermutlich steckt der fehler im code. (speicherüberschreiber oder 
stackoverflow)

von Marius S. (fhler)


Lesenswert?

1
 
2
#define TASTERPORT PIND
3
#define TASTERBIT1 PD2
4
#define TASTERBIT2 PD3
5
6
#include <avr/io.h>
7
#include <stdlib.h>
8
#include <util/delay.h>
9
#include "lcd-routines.h"
10
#include "lcd_functions.c"
11
#include <avr/interrupt.h>
12
#include "entprellung.h"
13
14
15
volatile int gew_Diode = 4;
16
volatile int adcval_max = 0;
17
volatile int adcval_alt = 0;
18
volatile int adcval;  //für das ADC-Ergebnis
19
volatile int adcval_neu;
20
volatile int an= 0x11;      //linkslauf
21
volatile int andersrum = 0x22;  //rechtslauf
22
23
volatile int zaehler=0; //für ADC-ISR
24
25
volatile int differenz;
26
volatile int differenz_alt  = 0;
27
volatile int differenz_alt2 = 0;
28
29
volatile double zeit;
30
volatile double altezeit;
31
32
char Buffer2[20]; //für das ADC-Ergebnis
33
char Buffer3[20]; //für die gewählte Diode
34
35
//-----------------------------------------
36
// ADC-Funktionen
37
//-----------------------------------------
38
39
/* ADC initialisieren */
40
void ADC_Init(void) 
41
{
42
 
43
    uint16_t result;
44
 
45
    ADMUX = (0<<REFS1) | (0<<REFS0);    // PIN AREF als Referenz nutzen
46
    ADCSRA = (1<<ADPS1) | (1<<ADPS0);   // Frequenzvorteiler : 8  
47
    ADCSRA |= (1<<ADEN);                // ADC aktivieren
48
  ADCSRA |= (1<<ADIE);        // ADC-Interrupt aktivieren
49
 
50
    /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
51
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
52
 
53
    ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung 
54
    while (ADCSRA & (1<<ADSC) );          // auf Abschluss der Konvertierung warten
55
    /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der naechsten
56
     Wandlung nicht uebernommen. */
57
    result = ADCW;
58
}
59
 
60
/* ADC Einzelmessung */
61
uint16_t ADC_Read( uint8_t channel )
62
{
63
    // Kanal waehlen, ohne andere Bits zu beeinflu?en
64
    ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
65
    ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
66
    while (ADCSRA & (1<<ADSC) )     // auf Abschluss der Konvertierung warten
67
    ;
68
    return ADCW;                    // ADC auslesen und zurueckgeben
69
}
70
 
71
/* ADC Mehrfachmessung mit Mittelwertbbildung */
72
uint16_t ADC_Read_Avg( uint8_t channel, uint8_t average )
73
{
74
    uint32_t result = 0;
75
 
76
    for (uint8_t i = 0; i < average; ++i )
77
  {
78
      result += ADC_Read( channel );
79
    _delay_ms(20);
80
   }
81
    return (uint16_t)( result / average );
82
}
83
84
//-----------------------------------------
85
// Motor-Drehrichtung
86
//-----------------------------------------
87
88
void change_direction()
89
{
90
  if( (an & 0x11) == 0x11)
91
  {
92
    an = 0x02;
93
    andersrum = 0x11;
94
  }
95
  else if ( (an & 0x22) == 0x02)
96
  {
97
    an = 0x01;
98
    andersrum = 0x22;
99
  }
100
}
101
102
//-----------------------------------------
103
//Interrupt Service Routinen
104
//-----------------------------------------
105
106
107
ISR(INT0_vect)  //PD2 gedrückt
108
{
109
  
110
  int pgd = tasterhoch();
111
112
    if( (pgd == 1 ) ^ (gew_Diode < 8) )
113
    {
114
115
      if( gew_Diode == 2)
116
      {
117
        gew_Diode +=2;
118
        
119
      }
120
  
121
      else if ( gew_Diode == 5)
122
            {
123
                 gew_Diode +=2;           
124
      }
125
126
      else
127
      {
128
        gew_Diode +=1;
129
      }
130
            
131
    }
132
133
    else
134
    {
135
      
136
    }
137
  
138
    an = 0x22;      //rechtslauf
139
  andersrum = 0x11;  //linkslauf
140
141
  adcval_max = 0;
142
  zaehler = 0;
143
144
  //Erste Zeile löschen
145
  lcd_setcursor( 0, 1 );
146
  lcd_string("                 ");
147
    lcd_setcursor( 0, 1 );
148
    
149
  //Ausgabe der gewählten Diode auf dem LCD
150
  itoa( gew_Diode, Buffer3, 10 );
151
    lcd_string("Diode ");
152
  lcd_string(Buffer3);
153
154
}
155
156
ISR(INT1_vect)  //PD3 gedrückt
157
{
158
  int mgd = tastertief();
159
         
160
    if ( (mgd == 1) ^ (gew_Diode > 1) )
161
    {
162
163
      if( gew_Diode == 2)
164
      {
165
        gew_Diode = gew_Diode;        
166
      }
167
168
      else if ( gew_Diode == 4)
169
            {
170
                 gew_Diode -=2;
171
      }
172
173
      else if ( gew_Diode == 7)
174
            {
175
                 gew_Diode -=2;
176
      }
177
178
      else
179
      {
180
        gew_Diode -=1;
181
      }
182
183
    }
184
185
    else
186
    {
187
      
188
    }
189
190
  an = 0x11;      //linkslauf
191
  andersrum = 0x22;  //rechtslauf
192
193
  adcval_max = 0;
194
  zaehler = 0;
195
196
  //Erste Zeile löschen
197
  lcd_setcursor( 0, 1 );
198
  lcd_string("                 ");
199
  lcd_setcursor( 0, 1 );
200
    
201
  //Ausgabe der gewählten Diode auf dem LCD
202
  itoa( gew_Diode, Buffer3, 10 );
203
  lcd_string("Diode ");
204
  lcd_string(Buffer3);
205
206
}
207
208
209
ISR(ADC_vect)  //Interrupt nach Abschluss einer ADC Wandlung
210
{
211
212
  if(adcval > 0)
213
  {
214
    adcval_neu = ADC_Read_Avg( (gew_Diode - 1),100); //neuer ADC_Wert zum "Arbeiten"
215
216
    if(adcval_neu > adcval_max)
217
    {  
218
      adcval_max = adcval_neu;  
219
    }
220
221
    if(adcval_neu < adcval_alt)
222
      
223
    {
224
      change_direction();
225
    }
226
227
    /*
228
229
    differenz = 300 - adcval_neu;                        //300 = Sollwert
230
    //                q0              q1                  q2
231
    zeit =  0.1*differenz + 0.2*differenz_alt + 0.3*differenz_alt2;  //Reglergleichung
232
233
    differenz_alt2 = differenz_alt;
234
    differenz_alt = differenz;
235
    altezeit = zeit;
236
237
    int zeitganz = (int) zeit;
238
239
    lcd_setcursor( 10, 1 );
240
    lcd_int(zeitganz);
241
242
    if(zeit>80)
243
    {
244
      zeit = 80;
245
    }
246
247
    PORTC = an;
248
    _delay_ms(zeitganz);
249
    PORTC = andersrum;
250
    _delay_ms(zeitganz/2);
251
252
    */
253
254
    zaehler += 1;
255
    
256
    if(zaehler == 1)
257
    {  
258
      PORTC = an; 
259
      _delay_ms(180);
260
      PORTC = andersrum;
261
      _delay_ms(50);
262
      
263
      PORTC = 0x00;  //STOPP - Laserpointerstrahl ist prinzipiell auf der Diode
264
    }
265
266
    else if(( (zaehler >=31) & ((adcval_max - adcval_neu) < 50) ))
267
    {
268
      PORTC = 0x00;
269
    }
270
271
    else  // 1 < zaehler < 31
272
    {
273
      
274
      PORTC = an;
275
      _delay_ms(80);
276
      PORTC = andersrum;
277
      _delay_ms(50);
278
      PORTC = 0x00;
279
      
280
      
281
      
282
    }
283
  }
284
  
285
  else
286
  {
287
    PORTC = an;
288
    _delay_ms(100);
289
290
    PORTC = andersrum;
291
    _delay_ms(50);
292
293
    PORTC = 0x00;
294
295
    zaehler = 0;
296
  }
297
298
  adcval_alt = adcval_neu;
299
300
}
301
302
//-----------------------------------------
303
// Start Hauptprogramm
304
//-----------------------------------------
305
 
306
int main(void)
307
{
308
309
//-----------------------------------------
310
// Datenrichtung (Ein-/Ausgänge) setzen
311
//-----------------------------------------
312
313
  DDRC |= (1 << PD0 | 1 << PD1 | 1 << PD4 | 1 << PD5);
314
315
  DDRD |= (1 << PD4 | 1 << PD5);
316
317
//-----------------------------------------
318
// PWM-Einstellungen
319
//-----------------------------------------  
320
321
  //            COM: verhalten bei match                               WGM: Phase Correct Mode  
322
  TCCR1A |= ( 1 <<COM1A1 | 0 << COM1A0| 1 << COM1B1| 0 << COM1B0| 1 << WGM11 | 0 << WGM10 );
323
  //            WGM: Phase Correct Mode              CS Prescaler
324
  TCCR1B |= ( 1 << WGM13 | 0 << WGM12 | 0 << CS12 | 0 << CS11 | 1 << CS10);
325
326
  
327
  ICR1 = 8000;  // Frequenz 500 Hz mit prescaler 1
328
329
  OCR1A = 2000;
330
331
//-----------------------------------------
332
// ADC einstellen / aktivieren
333
//-----------------------------------------  
334
335
  ADC_Init();
336
337
//-----------------------------------------
338
// Interrupt-Register
339
//-----------------------------------------  
340
341
  MCUCR = 0x0F;  //auf steigende Flanken reagieren (Taster mit externem Pull-Down)
342
343
  GICR = 0xC0;  //Interrupts INT0 + INT1 aktivieren
344
345
//-----------------------------------------
346
// für die Ausgabe auf dem LCD
347
//-----------------------------------------  
348
349
  lcd_init();          // Initialisierung des LCD
350
351
  lcd_string("  Neustart");
352
    lcd_setcursor( 0, 2 );    // Die Ausgabemarke in die 2te Zeile setzen
353
    lcd_string("    Neustart");
354
355
    _delay_ms(1000);
356
  
357
  //Erste Zeile löschen
358
  lcd_setcursor( 0, 1 );
359
  lcd_string("                 ");
360
  lcd_setcursor( 0, 1 );
361
    
362
  //Ausgabe der gewählten Diode auf dem LCD
363
  itoa( gew_Diode, Buffer3, 10 );
364
  lcd_string("Diode ");
365
  lcd_string(Buffer3);  
366
  
367
  sei(); //Interrupts anschalten
368
369
//-----------------------------------------
370
// Start Endlosschleife
371
//-----------------------------------------
372
373
    while(1) 
374
  {  
375
    if( ((PORTC == 0x00) & (zaehler >=31)) )
376
    {
377
      //2. Zeile löschen
378
        lcd_setcursor( 0, 2 );
379
      lcd_string("                 ");
380
        lcd_setcursor( 0, 2 );      
381
382
      lcd_string("Ausgerichtet :-)");
383
    }
384
    
385
    else
386
    {
387
      // Kanal x (gew_Diode - 1) wandeln
388
      adcval = ADC_Read(gew_Diode - 1);
389
      
390
      lcd_setcursor( 10, 1 );
391
      lcd_int(zaehler);
392
393
      //Umwandlung "Zahl" in einen "String"
394
      itoa( adcval_neu, Buffer2, 10 );
395
396
      //2. Zeile löschen
397
        lcd_setcursor( 0, 2 );
398
      lcd_string("                 ");
399
        lcd_setcursor( 0, 2 );  
400
401
      //Vorbereitung Ausgabe des Wandlungsergebnisses der gew. Diode
402
      lcd_string("ADC_Diode");
403
      lcd_string( Buffer3 );
404
      lcd_string(": ");
405
    
406
      //Ausgabe Wandlungsergebnis    
407
      lcd_string( Buffer2 );
408
    }
409
    
410
    _delay_ms(500);    
411
412
    }
413
 
414
    return (0);
415
}

von Peter II (Gast)


Lesenswert?

du machst zuviel im der ISR. das LCD sollte an dieser stelle nicht 
beschrieben werden weil das viel zu lange dauert.

Das sollte aber nicht zu solchen Problemen führen.

Warum hast du immer int verwendet? Das ganze ist damit langsam und 
eventuell fehlerhaft weil alles operrationen mit der Variable mit atomic 
sind.

von Εrnst B. (ernst)


Lesenswert?

Peter II schrieb:
> Das sollte aber nicht zu solchen Problemen führen.

Doch, weil das LCD sowohl aus der ISR als auch aus main angesprochen 
wird.

von Marius S. (fhler)


Lesenswert?

Ordnungsgemäß:

PC0 setzen 0,1s halten
PC0 rücksetzen PC1 setzen 0,05s halten
PORTC ganz aus.

0,5sek Pause

PC0 setzen 0,1s halten
PC0 rücksetzen PC1 setzen 0,05s halten
PORTC ganz aus.

0,5sek Pause

[...]

Quatsch:

PORTC ganz aus.
PC0 setzen. (halten <  0,1s)
PC0 rücksetzen PC1 setzen  halten < 0,1s
PORTC ganz aus.

kurze Pause (länger als 0,5s)

dies 3-4 mal

nahcdem PORTC ganz aus ist
PC0 setzen. (extrem kurz)
PC0 rücksetzen PC1 setzen  (extrem kurz)
PORTC ganz aus.

danach geht es dann aber wieder ordnungsgemäß

von Purzel H. (hacky)


Lesenswert?

Aeh. Ja. Fehler zu haben ist ueblich. Dann ist nun Debuggen angesagt. 
Debuggen ist keine Krankheit, sondern Teil des Entwicklungsprozesses. 
Der Programmaufbau sollte auch schon mit Debuggen geplant sein.
Das bedeutet mit den kleinstmoeglichen Codeeinheiten gepruefte Bloecke 
aufzubauen. Dann lass das Ganze mal ohne Interrupts laufen. Dann mit 
einem, dann mit zweien. Bis der/die Fehler gefunden sind.

von Karl H. (kbuchegg)


Lesenswert?

Verrätst du uns auch noch, was das Ganze sein soll?

(In deinem Code findet sich ziemlich viel unübersichtliches und ich 
würde sogar nach einem ersten Drüberschauen sagen "unsinniges", dass es 
schwer ist, den Sinn hinter der ganzen Sache zu verstehen. Deine 
exzessive Verwendung von Hex-Konstanten macht die Sache dann auch nicht 
leichter.)

von Marius S. (fhler)


Lesenswert?

Bei PORTA werden Signale von Fotodioden digitalisiert.

An PORTB hängt ein Display zur Ausgabe auf welche Diode sich ein 
Laserpointer ausrichten soll. Und zur Ausgabe des ADC-Wertes.

PORTC ist für die Steuerung einer H-Brücke. Links- / Rechtslauf eines 
Motors.

Auf PORTD(PD5) liegt eine PWM. (H-Brücke)

In der ADC-ISR soll gesteuert werden. (wenn möglich später geregelt).

von Udo S. (urschmitt)


Lesenswert?

Das die Ursache ein aktiver Watchdog ist, oder ein reset wegen Brown-Out 
Detection bzw. wegen Unterspannungspulsen kann ausgeschlossen werden?

von Εrnst B. (ernst)


Lesenswert?

Geh bei der Fehlersuche systematisch vor.
Behebe zuerst die Fehler, die aus dem Quelltext offensichtlich sind und 
wir dir schon genannt haben.
Dann teste neu.

Fang z.B. damit an, die LCD-Ausgabe in Ordnung zu bringen. Vielleicht 
läuft das Programm ja korrekt, nur die Ausgabe spinnt?

Also: entweder alle LCD-Zugriffe aus den ISRs entfernen (gut), oder 
wenigstens während allen LCD-Zugriffen im main() die Interrupts sperren 
(quick&dirty).

(
schnelle Lösung: das _delay_ms(500) im Main durch
sei(); _delay_ms(500); cli(); ersetzen, das andere sei() weiter oben 
entfernen.
)

Dann schauen wir weiter.

von Marius S. (fhler)


Lesenswert?

Brown-out kann ausgeschlossen werden.

Ich hab mittlerweile herausgefunden das er mit dem ADC_interrupt so 
seine Schwierigkeiten hat.
1
int main()
2
[...]
3
sei();
4
5
while(1) 
6
  {  
7
    //1. Zeile löschen
8
      lcd_setcursor( 0, 1 );
9
    lcd_string("                 ");
10
      lcd_setcursor( 0, 1 );
11
  
12
    //Ausgabe der gewählten Diode auf dem LCD
13
    itoa( gew_Diode, Buffer3, 10 );
14
      lcd_string("Diode ");
15
    lcd_string(Buffer3);
16
17
    if( ((PORTC == 0x00) & (zaehler >=31)) )
18
    {
19
      //2. Zeile löschen
20
        lcd_setcursor( 0, 2 );
21
      lcd_string("                 ");
22
        lcd_setcursor( 0, 2 );      
23
24
      lcd_string("Ausgerichtet :-)");
25
    }
26
    
27
    else
28
    {
29
      // Kanal x (gew_Diode - 1) wandeln
30
      //ADC_Read(gew_Diode - 1);
31
      
32
      lcd_setcursor( 10, 1 );
33
      lcd_int(zaehler);
34
35
      //Umwandlung "Zahl" in einen "String"
36
      itoa( adcval_neu, Buffer2, 10 );
37
38
      //2. Zeile löschen
39
        lcd_setcursor( 0, 2 );
40
      lcd_string("                 ");
41
        lcd_setcursor( 0, 2 );  
42
43
      //Vorbereitung Ausgabe des Wandlungsergebnisses der gew. Diode
44
      lcd_string("ADC_Diode");
45
      lcd_string( Buffer3 );
46
      lcd_string(": ");
47
    
48
      //Ausgabe Wandlungsergebnis    
49
      lcd_string( Buffer2 );
50
    }
51
52
    PORTC = an;
53
    _delay_ms(50);
54
    PORTC = andersrum;
55
    _delay_ms(50);
56
    PORTC = 0x00;
57
    
58
    _delay_ms(500);    
59
60
    }
61
 
62
    return (0);

Obwohl erst Interrupts vor der Endlosschliefe freigegeben werden. Und er 
auch eigentlich keinen werfen dürfte (ADC-Read ist auskommentiert). 
Springt er wenn er wenn im ADC-Register der ADC-Interrupt aktiviert wird 
in die ISR.

Die LCD-Zugriffe sind auch aus allen ISR raus.

von Marius S. (fhler)


Lesenswert?

bzw. jetzt springt er überhaupt nicht mehr rein obwohl er sollte.


//

Also jetzt funktioniert es wieder richtig. (k.A. warum)

mist zu früh gefreut.

es kann aber nicht sein das es erst funktioniert und dann irgendwann 
nicht mehr.

von Εrnst B. (ernst)


Lesenswert?

Marius S. schrieb:
> Obwohl erst Interrupts vor der Endlosschliefe freigegeben werden. Und er
> auch eigentlich keinen werfen dürfte (ADC-Read ist auskommentiert).
> Springt er wenn er wenn im ADC-Register der ADC-Interrupt aktiviert wird
> in die ISR.

Deine "ADC_init" schaltet zuerst den ADC Irq frei, und macht danach 
einen Dummy-Read. Dieser Dummy-Read löst natürlich auch einen IRQ aus.

Also:
 ADCSRA |= (1<<ADIE);
ans Funktionsende schieben.

Bei Global deaktivierten IRQs sollte das jedoch wurscht sein. Sicher 
dass der noch vor dem "sei()" dort reinspringt?
Eventuell enthält dein rest-Quelltext (lcd, enprellung, ..) ein sei() ?

von -schumi- (Gast)


Lesenswert?

Dein Programm ist nicht gerade "klein" (deine LCD-Routinen und 
entprellung kommen ja auch noch dazu) und du verwendest viele sehr große 
Variablen.. Gib mal folgendes auf deinem PC ein:
1
avr-size --mcu=atmega16 -C foo.elf
foo.elf ist die elf-Datei deines Programms, die wird beim Übersetzen in 
die .hex mit erzeugt.

Jetzt wird dir angzeigt wie viel RAM du schon verbraucht hast, 
vielleicht isses ja wirklich schon so weit dass du nen größeren 
Controller brauchst (Atmega32)

von Εrnst B. (ernst)


Lesenswert?

-schumi- schrieb:
> Jetzt wird dir angzeigt wie viel RAM du schon verbraucht hast,
> vielleicht isses ja wirklich schon so weit dass du nen größeren
> Controller brauchst (Atmega32)

Soweit isses noch nicht... Mit wenig Aufwand könnte er z.B. alle 
String-Konstanten vom Ram in den Flash verbannen... PSTR(), lcd_string_P 
()...

von Purzel H. (hacky)


Lesenswert?

Ein delay ist sowieso Schrott.

Besser ist ein konstrukt wie

timer_isr {
 timer_came=1
 rimerreload...
 }

main
 ..
 if (timer_came==1)
 {
 ..
 timer_came=1;
 }

von anc (Gast)


Lesenswert?

Pico Oschi schrieb:
>  if (timer_came==1)
>  {
>  ..
>  timer_came=1;
>  }

if...
timer_came=0;

von Marius S. (fhler)


Lesenswert?

Εrnst B✶ schrieb:
> -schumi- schrieb:
>> Jetzt wird dir angzeigt wie viel RAM du schon verbraucht hast,
>> vielleicht isses ja wirklich schon so weit dass du nen größeren
>> Controller brauchst (Atmega32)
>
> Soweit isses noch nicht... Mit wenig Aufwand könnte er z.B. alle
> String-Konstanten vom Ram in den Flash verbannen... PSTR(), lcd_string_P
> ()...

AVR Memory Usage
----------------
Device: atmega16

Program:    5670 bytes (34.6% Full)
(.text + .data + .bootloader)

Data:        426 bytes (41.6% Full)
(.data + .bss + .noinit)


Build succeeded with 0 Warnings...

von Marius S. (fhler)


Lesenswert?

Mittlerweile läuft es recht stabil. Nach einer langen Zeit hat er immer 
noch nen kurzen Aussetzer.

-Ich mach jetzt direkt am Anfang der main erstmal ein cli();

-sei(); direkt vor der Endlosschleife.

-Ich hab mich um die Datenrichtung bei allen Ports gekümmert.

-Alle Interrupts schalte ich jetzt in der main, direkt vor dem sei(); ,
ein (externe (Taster), ADC).

-in der ADC_ISR:

   zuerst adif & adie = 0;

   am ende adie = 1

-Displayzugriffe alle ausserhalb der ISRn.

-Es läuft allerdings immer noch mit delays anstatt dem timer.


Und auch wenn es nicht zum Beitrag passt:

Habe ich ne Chance auf einen Regler wenn ich in dem Sinne keinen 
Sollwert habe außer das der entspr. Wert maximal sein soll?

Ich meine nein. Da ich ja in dem Sinne keinen Wert habe mit dem ich den 
aktuellen Wert vergleichen kann. Zudem habe ich ja dann nie eine 
Abweichung wo dann der Stellwert/Stellgröße entspr. 
zurückgefahren/invertiert wird.

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.