www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATmega delay Fehlfunktion


Autor: Matt Bico (mbico)
Datum:

Bewertung
0 lesenswert
nicht 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
Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Den Optimizer des Compilers hast du eingeschaltet?

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

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

Autor: Matt Bico (mbico)
Datum:

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

Autor: Matt Bico (mbico)
Datum:

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

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

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

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

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

Autor: Matt Bico (mbico)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also, der optimizer ist auf -OS.

Autor: Matt Bico (mbico)
Datum:

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

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

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

Autor: Stefan Ernst (sternst)
Datum:

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

Autor: Matt Bico (mbico)
Datum:

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

Autor: ... (Gast)
Datum:

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

Autor: ... (Gast)
Datum:

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

Autor: Matt Bico (mbico)
Datum:

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

Autor: Matt Bico (mbico)
Datum:

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

Autor: ... (Gast)
Datum:

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

Autor: Matt Bico (mbico)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gute idee! das mache ich mal...

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

Bewertung
0 lesenswert
nicht 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)
#define F_CPU 1000000UL

#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>

#define LED_PORT    PORTB
#define LED_1       PB2
#define LED_2       PB3

int main(void)
{
  unsigned char i;

  LED_PORT |= (1<<LED_1) | ( 1<<LED_2);
  _delay_ms( 500 );
  LED_PORT &= ~( (1<<LED_1) | ( 1<<LED_2) );
  _delay_ms( 500 );

  while(1)
  {
    LED_PORT |= ( 1 << LED_1 );
    LED_PORT &= ~( 1 << LED_2 );

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

    _delay_ms(2000);

    LED_PORT |= ( 1 << LED_2 );
    LED_PORT &= ~( 1 << LED_1 );

    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);
  }
}


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.

Autor: Matt Bico (mbico)
Datum:

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

Autor: Matt Bico (mbico)
Datum:

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

Autor: ... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Na also, geht doch :)

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.