Forum: Mikrocontroller und Digitale Elektronik ATmega delay Fehlfunktion


von Matt B. (mbico)


Lesenswert?

Hallo Leute,

Habe dieses programm auf ein ATmega8 am laufen und folgendes problem 
dabei.
Dies ist bei der ansteuerung eines Servo Motors angewendet.
Beim ausführen bearbeit der uC die erste FOR schleife und auch das Delay 
danach, jetzt auch noch die zweite FOR schleife, doch das Delay lässt er 
dabei komplett weg und springt wieder direkt zu ersten FOR schleife.

Anstatt das der Servo so auch in der zweiten position 2 sekunden lang 
bleibt, fährt er dort hin und dann aber wieder sofort zurück, und hält 
nur pause wieder nach der ersten schleife.??

Habe da lange hin und her gemacht, auch die delays anders angeordnet 
usw.
Ich benutze AVR Studio/ Winavr / GCC.

Habe auch die schleifen in zwei unterprogramme gepackt, doch bleibt es 
alles beim selben.

Kann mir jemand da helfen?? Habe ich da was nicht beachtet??

Vielen Dank!


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <stdlib.h>


#define F_CPU 1000000UL
#include <util/delay.h>

//int ciclo = 1;
int a;
int i;
int adch1;


int main(void)
{
DDRD |= ( 1 << DDD0);        // SETAR PD5 como SAIDA
//PORTB |= (1<<PB3);  //LED4 Aktiv = 1
int c;


  while(1)
  {
  sei();
  //adch1 = ReadChannel(1);
  //b = 2*adch1;
  //a=0;
  //cli();
    for(a=0;a<=200;a++)
    {
      PORTD |= (1<<PD0);  //LED4 Off = 0
      _delay_us(1000);
      PORTD &= ~(1<<PD0);  //LED4 Aktiv = 1
      _delay_us(20000);
    }

    _delay_ms(2000);

    for(i=0;i<=200;i++)
    {
      PORTD |= (1<<PD0);  //LED4 Off = 0
      _delay_us(2100);
      PORTD &= ~(1<<PD0);  //LED4 Aktiv = 1
      _delay_us(20000);
    }

    _delay_ms(2000);

  }
}

: Verschoben durch User
von Karl H. (kbuchegg)


Lesenswert?

Den Optimizer des Compilers hast du eingeschaltet?

von Karl H. (kbuchegg)


Lesenswert?

Matt Bico schrieb:

> Anstatt das der Servo so auch in der zweiten position 2 sekunden lang
> bleibt,

Das passiert sowieso nicht.
Du steuerst dein Servo ca. 4 Sekunden lang auf eine bestimmte Position 
hin. Danach überlässt du das Servo 2 Sekunden lang sich selbst.

Ein Servo muss ständig angesteuert werden. Einfach einen delay_ms(2000) 
ist zuwenig um ein Servo an einer bestimmten Position zu halten.

von Matt B. (mbico)


Lesenswert?

Doch aber wenn ich ein servo auf eine bestimmten position fahre und dann 
die impulse ausschalte, dann bleibt er wo es gerade ist, ohne das er 
wegläuft.

von Matt B. (mbico)


Lesenswert?

Der Servo fährt ja auch die 2 position an, und zwar ganz genau da wo ich 
den haben möchte. Kein grund dazu zu sagen das das sowieso nicht 
passiert.

von Karl H. (kbuchegg)


Lesenswert?

Matt Bico schrieb:
> Doch aber wenn ich ein servo auf eine bestimmten position fahre und dann
> die impulse ausschalte, dann bleibt er wo es gerade ist, ohne das er
> wegläuft.

dann drück mal ein bischen am servoarm, wenn es in dieser position ist.
das servo wird keinen widerstand leisten

von Karl H. (kbuchegg)


Lesenswert?

Matt Bico schrieb:
> Der Servo fährt ja auch die 2 position an, und zwar ganz genau da wo ich
> den haben möchte. Kein grund dazu zu sagen das das sowieso nicht
> passiert.


ok falsch ausgedrückt

deine zeitangaben sind ein wenig zweifelhaft.
das servo sollte alle 6 sekunden die position wechseln.

Was ist jetzt mit dem Optimizer? Ist der auf -Os?
(Ansonsten stimmen die Delay Zeiten nicht)

von Matt B. (mbico)


Lesenswert?

Also, der optimizer ist auf -OS.

von Matt B. (mbico)


Lesenswert?

Habe das gleiche verhalten auch auf anderen Ucontrolern bereits 
ausprobiert.
Attiny13, Attiny25.

Nur mit ein Attiny 2313 habe ich es zum laufen gebracht, doch dieser hat 
kein ADC eingang denen ich auch noch benötige.

von Karl H. (kbuchegg)


Lesenswert?

Hmm.
Die Simlation zeigt:
Nach jeweils 6 Sekunden wird die jeweils andere for-Schleife erreicht. 
So wie es sein soll und sich aus dem Code ergibt.

Kanstt du noch zwei LED irgendwo anhängen und die vor den for Schleifen 
wechselseitig anschalten? Die müssten sich im 6 Sekunden Takt 
abwechseln.

von Stefan E. (sternst)


Lesenswert?

Und das da oben ist der komplette Code?
Denn diese beiden Zeilen sind verdächtig:
1
#include <avr/interrupt.h>
2
...
3
  sei();
Ich würde darauf tippen, dass nach dem Anfahren der 2. Position ein 
Soft-Reset auftritt.

von Matt B. (mbico)


Lesenswert?

Hatte bereits eine LED mit im Takt zweig eingebunden, so das nach jeder 
schleife einmal die LED an, und nach 1 sekunde delay wieder aus geht, 
und dann erst in die 2 schleife geht, so das ich auch eine kontrolle 
darüber hätte wo das programm sich z.Zt. befindet.
Auch nach der 2 schleife hatte ich solch ein "großes" delay auf der 
selben leitung programmiert.

Also so würde es aussehen für jede schleife:

for(i=0;i<=200;i++)
    {
      PORTD |= (1<<PD0);  //LED4 Off = 0
      _delay_us(2100);
      PORTD &= ~(1<<PD0);  //LED4 Aktiv = 1
      _delay_us(20000);
    }

PORTD |= (1<<PD0);  //LED4 Off = 0
_delay_ms(1000);
PORTD &= ~(1<<PD0);  //LED4 Aktiv = 1
_delay_ms(1000);

Doch auch hier kann ich nur zusehen das die LED einmal ganz schwach 
blinkt(impulse/pausen verhältnis sehr klein), und darach eine sekunde an 
ist, dann wieder blinkt, doch ist der servo dann ja auch bereits auf dem 
weg in die 1 position.

Das programm ist eigentlich noch größer, doch wenn gar nicht einmal 
dieses teil funktioniert, dann brauch ich den rest gar nicht mal 
mitlaufen lassen, obwohl der rest des programms aller bestens 
funktioniert. Nur dieses teil halt nicht.

Was meinen Sie mit ein SOFT-Reset?

von ... (Gast)


Lesenswert?

Lass das "SOFT" weg, dann weist Du was er meint.
Testen kannst Du das, indem Du ganz am Anfang in main (noch vor dem 
while(1)) mal eine LED ein- und wieder ausschaltest.
Ein Grund dafür könnte z.B. der Watchdog sein (das wäre dann ein 
HARD-Reset :)

von ... (Gast)


Lesenswert?

Achso, kommentier mal das von Stefan angesprochene "sei();" auch aus. 
Ein auftretender Interrupt ohne zugehörige Interruptroutine erzeugt 
ebenfalls eine Art 'Reset' (diesmal dann einen SOFT-Reset :)

von Matt B. (mbico)


Lesenswert?

Nein,nein auch das ganze ohne sei(); und pipapo alles bleibt so wie es 
ist.
Habe eine woche lang daran gemacht, und deshalb habe ich mich mal hier 
im Forum erkündigen wollen.

Mir ist im sinne gekommen das auch eine störung ein reset auslösen 
könnte, über den Motor nach + oder masse, doch dann würde ja auch mal 
die erste schleife rausfallen, wenn man es so betrachtet.

von Matt B. (mbico)


Lesenswert?

Also, noch dazu!
Wenn man das ganze eine weile laufen lässt, passiert es auch mal das der 
Servo in der 2 position sein Delay einhält, doch wann und wieso dann 
auch nur manchmal??

von ... (Gast)


Lesenswert?

Ja Störungen vom Motor können auch sein.
Probier mal ganz am Anfang in main (noch vor dem
while(1)) eine ansonsten unbenutzte LED ein- und wieder ausschaltest.
Dann siehst Du, ob es tatsächlilch ein Reset ist.

von Matt B. (mbico)


Lesenswert?

Gute idee! das mache ich mal...

von Karl H. (kbuchegg)


Lesenswert?

Matt Bico schrieb:

> Das programm ist eigentlich noch größer, doch wenn gar nicht einmal
> dieses teil funktioniert, dann brauch ich den rest gar nicht mal
> mitlaufen lassen, obwohl der rest des programms aller bestens
> funktioniert. Nur dieses teil halt nicht.

Dann solltest du erst mal nur diesen Teil für sich alleine, ohne alles 
andere testen.

WEnn du noch 2 LED irgendwo anhängen kannst, dann lass folgendes 
Programm laufen. Die einzige ANpassung ist die Einstellung des Ports an 
dem die Led hängen bzw. der Pins an denen die LED hängen. Den Rest lässt 
du so wie er ist (ausser natürlich ich habe hier beim tippen Tippfehler 
gemacht)
1
#define F_CPU 1000000UL
2
3
#include <stdlib.h>
4
#include <avr/io.h>
5
#include <util/delay.h>
6
7
#define LED_PORT    PORTB
8
#define LED_1       PB2
9
#define LED_2       PB3
10
11
int main(void)
12
{
13
  unsigned char i;
14
15
  LED_PORT |= (1<<LED_1) | ( 1<<LED_2);
16
  _delay_ms( 500 );
17
  LED_PORT &= ~( (1<<LED_1) | ( 1<<LED_2) );
18
  _delay_ms( 500 );
19
20
  while(1)
21
  {
22
    LED_PORT |= ( 1 << LED_1 );
23
    LED_PORT &= ~( 1 << LED_2 );
24
25
    for( i = 0; i < 200; i++ )
26
    {
27
      PORTD |= (1<<PD0);  //LED4 Off = 0
28
      _delay_us(1000);
29
      PORTD &= ~(1<<PD0);  //LED4 Aktiv = 1
30
      _delay_us(20000);
31
    }
32
33
    _delay_ms(2000);
34
35
    LED_PORT |= ( 1 << LED_2 );
36
    LED_PORT &= ~( 1 << LED_1 );
37
38
    for( i = 0; i < 200; i++ )
39
    {
40
      PORTD |= (1<<PD0);  //LED4 Off = 0
41
      _delay_us(2100);
42
      PORTD &= ~(1<<PD0);  //LED4 Aktiv = 1
43
      _delay_us(20000);
44
    }
45
46
    _delay_ms(2000);
47
  }
48
}


Beim Programmstart leuchten beide LED gemeinsam auf, danach immer 
wechselseitig, alle 6 Sekunden wird gewechselt und gleichzeitig fährt 
das Servo in die andere Position.
Wenn irgendwann beide LED wieder gemeinsam aufleuchten, dann ist der µC 
abgeschmiert und das Programm beginnt von vorne.

Das Verhalten der beiden LED erzählt daher was unter Umständen passiert 
sein könnte. Mit Raten kommen wir nicht weiter. Fakten müssen her.

von Matt B. (mbico)


Lesenswert?

Ich Habs!!! Danke Leute für das mit in gänge bringen. Obwohl es nichts 
mit dem programm zu tun hat, doch die gedanken schiene hat geholfen!!! 
RESET !!

Habe die Schaltung über 12 Volt Versorgt mit ein 7805 in seiner 
"normalen" konfiguration" mit nur ein 100nF ein- und ausgangsmäßig 
beschaltet.

Es muß dann passieren das der 7805 in die Knie geht und das ganze nicht 
laufen lässt, obwohl der Servo ja nur um die 300mA zieht!!

Habe jetzt ein 100uF mit an Ausgang vom 7805 und es läuft wie 
geschrieben!!

Endlich kann ich das Abschliessen!

Vielen dank!

Schön das es solche Forums gibt!! Muß daher das auch mal gerne 
unterstützen!!

von Matt B. (mbico)


Lesenswert?

PS.: Liegt wohl an meiner Versorgung(trafo) der doch nur 450mA macht!!

von ... (Gast)


Lesenswert?

Na also, geht doch :)

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.