PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : zeitverzögerung



Spongebob85
11.08.2007, 21:40
Moin!!!
Ich hab grade versucht eine Zeitverzögerung zu programmieren.
Es soll wenn man einen Taster drückt nach 1s eine LED leuchten.
Im MFile steht F_CPU = 8000000. Ich hab aber noch keinen Quarz. D.h. ich will mit dem internen Oszillator arbeiten.
Mein Quellcode sieht so aus:


#include <avr/io.h>
#include <stdint.h>
#define F_CPU [8000000]UL
#include <avr/delay.h>

int main (void)
{
DDRA |= (1<<DDA0);
DDRD &= ~(1<<DDD0);
PORTA &= ~(1<<PA0);

while(1)
{
if ((PIND & (1<<PD0)) != 0)
{
_delay_ms(1000)
PORTA |= (1<<PA0);
}

else
PORTA &= ~(1<<PA0);

}
return 0;
}

Hoffe mir kann jemand helfen.
MfG Jan

izaseba
11.08.2007, 21:57
Hoffe mir kann jemand helfen

Ich kann Dir helfen \:D/

Diese (http://www.nongnu.org/avr-libc/user-manual/index.html) Seite speicherst Du dir in Deine Bookmarks und schaust auch mal rein ;-)

Was für Dich interessant ist, kannst Du hier (http://www.nongnu.org/avr-libc/user-manual/group__util__delay.html) nachlesen.

viel Erfolg

Gruß Sebastian

P.S.
Dein Kompiler hat sicherlich eine Warnung/Fehler gemeldet...
Wenn man liest, was da so steht, kommt man sicher auch von alleine darauf, was fault ist.

Spongebob85
11.08.2007, 22:27
Naja, erlich gesagt hab ich mich noch nie an so eine Englische Seite getraut, aber einmal is ja immer das erste mal :-)
Ich versuch mal was zu erreichen, sonst kann ich ja immernoch fragen.
Danke erstmal.

izaseba
11.08.2007, 22:31
Haja, Englisch ist auch nicht unbedingt meine Lieblingssprache, leider geht es nicht ohne wenn man mit Elektronik was macht.
Schau mal, so schwer ist es auch nicht, sonst frag nochmal...

Gruß Sebastian

Spongebob85
11.08.2007, 23:13
Das is voll zum Kotzen. Hab mich grade voll abgequält mal diesen Text zu übersetzen:
<util/delay.h>: Convenience functions for busy-wait delay loops
Note:
As an alternative method, it is possible to pass the F_CPU macro down to the compiler from the Makefile. Obviously, in that case, no #define statement should be used.
The functions in this header file are wrappers around the basic busy-wait functions from <util/delay_basic.h>. They are meant as convenience functions where actual time values can be specified rather than a number of cycles to wait for….

Notiz:
So wie in einer Alternativen Methode ist es möglich den F_CPU befehl vom Makefile zum Compiler zu übertragen. Es ist offensichtlich das in diesem Fall keine #define-Anweisung benutzt werden sollte.
Die Funktionen in diesem Header-file sind Zusätze rund um die Grundsätzlichen busy-wait-funktionen aus <util/delay_basic.h>. Sie sind als Vereinfachungsfunktionen gedacht in denen gegenwärtige Zeitwerte eher festgelegt werden können als eine Anzahl von Schleifen auf die man warten muss....

Bin kein bisschen schlauer. Weiß immernochnicht wie ich damit umgehen soll. Hab auch keine Ahnung ob jetzt die interne Taktung läuft oder was sonst falsch ist. Ich könnt echt heulen!!!

izaseba
11.08.2007, 23:31
:-s kotzen ?
Ok, noch 2 Tips:
1.Im 2. Link lies mal was zwischen < und > steht und vergleiche es mit Deinem Programm
2.
Function Documentation
void _delay_ms ( double __ms )


Perform a delay of __ms milliseconds, using _delay_loop_2().

The macro F_CPU is supposed to be defined to a constant defining the CPU clock frequency (in Hertz).

The maximal possible delay is 262.14 ms / F_CPU in MHz.

_delay_ms war hier gefragt, oder ?



Hab auch keine Ahnung ob jetzt die interne Taktung läuft oder was sonst falsch ist. Ich könnt echt heulen!!!

Da kann Dir keiner helfen, du mußt schon selber wissen wie Du den µC gefused hast...

Spongebob85
11.08.2007, 23:39
Davon hab ich auch keine Ahnung, wie man den fused.
Das dumme ist, das es über winavr und so auch nicht ein buch gibt oder so.
Mal sehen ob ich noch was hinbekomme. sonst wird man sicher morgen wieder von mir hören.
Bis dann

Spongebob85
12.08.2007, 17:05
Moin!!!
Ich hab das jetzt mal weiter durchgetestet.
Hab einen weiteren Pin genommen und den auf druck des gleichen Tasters ohne verzögerung auch setzen lassen.
Der Code ist so:



#include <avr/io.h>
#include <stdint.h>
#define F_CPU 8000000UL
#include <util/delay.h>

int main (void)
{
DDRA |= (1<<DDA0) | (1<<DDA1);
DDRD &= ~(1<<DDD0);
PORTA &= ~(1<<PA0) | (1<<PA1);

while(1)
{
if ((PIND & (1<<PD0)) != 0)
{
PORTA |= (1<<PA1);
_delay_ms(100);
PORTA |= (1<<PA0);
}

else
PORTA &= ~(1<<PA0);
PORTA &= ~(1<<PA1);

}
return 0;
}


Das hab ich gemacht um zu sehen ob das verzögert.
Es funktioniert. Nur leider ist die verzögerungszeit immer die selbe.
wenn ich "_delay_ms(100)" eingebe ist die verzögerung genau so lange als wenn ich "_delay_ms(10000)" eingebe. Es kommt aber keine Fehlermeldung oder so.

Spongebob85
12.08.2007, 18:18
Ich hab mir grade eben mal das Datenblatt vom ATMega32 angesehen.
Hab da was von Oscillator kallibrierung gelesen.
Da steht was vom register OSCCAL. Wenn man das Null setzt ist der Takt auf 1MHz gesetzt.
Also hab ich im Quellcode #define F_CPU 1000000UL eingegeben und vor While(1) OSCCAL = 0x00; eingegeben.
Die zeiten sind dann bei verschiedenen ms-eingaben tatsächlich unterschiedlich. Das geht aber auch wenn ich OSCCAL = 00; eingebe.
Kann mir das mal jemand erklähren?
Hoffe es antwortet mal wieder jamand :-)
Bis dann.

PS. Wenn ich statt 1000ms 10000 eingebe ist da wieder keine Veränderung.

izaseba
12.08.2007, 18:39
Ja,das sieht schon nicht schlecht aus...

Ich weiß ich bin ein Ar***, ich könnte Dir die Lösung direkt sagen, aber Du kommst schon selber drauf.
Auf jedem Fall kannst Du nicht lesen [-X
Ich hab Dir einen Auszug aus der Doku geschrieben, geh nochmal nach oben und lies den letzten Satz !
.......
Und wie löst man das Problem ?
Ein Tip, man könnte eine Schleife nehmen in der .....

Bis dann Sebastian

Spongebob85
12.08.2007, 19:07
Ha, damit hast du mir die Lösung ja schon fast direkt gesagt. Auf den letzten Satz bin ich ja bis jetzt noch gar nicht so wirklich eingegangen. Das heißt bei einer Taktfrequenz von 1 MHz ist die Maximale verzögerung 262.14ms und je höher die Frequenz um so kleiner ist die maximal mögliche delayzeit.
Ich denke eine for-Schleife wäre da ganz nutzlich :-)
Find ich komisch. wenn ich 100 ms eingebe und danach 1000 kommt mir die verzögerungszeit schon extrem länger vor. Aber egal. werde in meiner for-schleife dann aber 100ms nehmen.
Danke!!!
Aber das nächste Problem kommt sicher bald. Werde mich heut abend mal mit den Fuses auseinander setzen.
Bis bald.

izaseba
12.08.2007, 19:39
;-) ,
Es ist doch schöner auf die Lösung selber zu kommen, oder?
Wenn Du mal hier in Forum etwas gesucht hättest... auf jedem Fall bist Du nicht der erste, der mit delay Probleme hatte.
Dazu muß ich noch sagen, benutz die delays nicht all zu oft, sie sind gut um mal eben Blinki,Blinki zu nachen, oder ein LCD zu bedienen, am sonsten ist es kein guter Programierstil den µC die Zeit totschlagenzulassen.
Eleganter ist es Timer zu nutzen, aber für den Anfang sind die "Zeitvernichtungsroutinen" ok.
Zu Fusebits, sei gewarnt,
solltest Du irgendwas falsch einstellen, wirst Du keinen Zugriff mehr auf den µC haben
Auch dafür gibt es genug Beiträge hier in Forum.
Mit welchem Programm brennst Du ?

Gruß Sebastian

Spongebob85
12.08.2007, 21:36
Bringt auf jeden fall mehr spaß selbst drauf zu kommen.
Hab das jetzt so gemacht:



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

int main (void)
{
uint8_t i;
DDRA |= (1<<DDA0) | (1<<DDA1);
DDRD &= ~(1<<DDD0);
PORTA &= ~(1<<PA0) | (1<<PA1);

OSCCAL = 0x00;

while(1)
{
if ((PIND & (1<<PD0)) != 0)
{
PORTA |= (1<<PA1);

for (i=1; i<=100; i=i+1)
{
_delay_ms(10);
}
PORTA |= (1<<PA0);
}

else
PORTA &= ~(1<<PA0);
PORTA &= ~(1<<PA1);

}
return 0;
}


wenn ich jetzt den Taster drück, dauert das aber ca. 3 sec bis die Lampe leuchtet. sollte soch nur 1 sec dauern, denke ich. 10ms mal 100 sind doch 1000ms also 1 sec. is alles komisch. Dann gibts da noch das problem das es nochmal ca. die gleiche zeit dauert bis beide LEDs wieder ausgehen. Hast da ne Idee? Glaub ich besorg mir mal ein Quarz... hilft mir auf jeden fall mit den Zeiten.
Ich brenne mit "Programmers Notepad 2". Drück da auf "programm". Das meinst du doch, ne? Ich hab das mit den Gefahren bei Fuses schon gehört.
Werde auch nur was ändern wenn ich mir 100% sicher bin.
Kuck mir gleich mal Timer an.

izaseba
12.08.2007, 23:13
Ich denke es hat mit OSCCAL = 0x00; zu tun, lass das mal weg,
Der µC ist vom Werk aus für 5V bei 20 Grad kalibriert(glaub ich)
Hab jetzt keine Lust genau nachzusehen, also nicht schlagen, wenn das nicht ganz stimmt.
OSCAL wird interessant, wenn Du mit kleineren Spannungen arbeitest.
Sonst brauchst Du fürs erste keinen Quarz.
Das andere Problem, weiß ich nicht genau, aber was hast Du für ein Board ?
Oder Steckbrett?
Dieser Zeile nach zu urteilen


if ((PIND & (1<<PD0)) != 0)

Tastest Du VCC (5V) mit dem Taster auf PD0 richtig?
Taste gedrückt PD0 -> VCC
Taste los PD0 -> ? was ? hängt in der Luft, oder hast Du einen Pulldown Widerstand dran?
Wenn in der Luft, dann ist es schlecht, nimm irgendein Widerstand von etwa 10 Kohm
und schalte ihn zwischen PD0 und GND(0V,minus)
Üblich ist es Pullup Widerstände zu nehmen(also zwischen PD0 und VCC) und mit dem Tastendruck GND auf den Pin zu schalten, dann könnte man sich sogar den Widerstand sparen und einen internen einschalten.
Wenn Du jetzt nicht weißt, was ich von Dir will :-k schau Dir die Bildchen auf meiner HP (http://www.izaseba.roboterbastler.de/index.php?popup=Tutorial&section=Lektion5) an.
Es geht sich da zwar um Assembler, das Prinzip bleibt aber gleich :-)

Gruß Sebastian

Spongebob85
13.08.2007, 01:15
Jetzt klappt das mit den Zeiten! Danke :-) Ich bastel jetzt grade an einem Lauflicht rum.
Ja, wenn man den Taster drückt dann schaltet man 5V auf den Eingang.
Klar hab ich Pull down widerstände. Kenn das aus meiner Lehrzeit von der TTL-Technik, aber als ich die Schalterplatine gelötet hab, hab ich 1,8kOhm oder so genommen. Hab ein Steckbrett. Aber dazu hab ich auch 2 Bilder angehängt. Deine Homepage is echt gut gelungen. Wollte auch mal eine machen aber das ist ne andere Geschichte.
Bis bald,
Gruß Jan

izaseba
13.08.2007, 10:25
Klar hab ich Pull down widerstände. Kenn das aus meiner Lehrzeit von der TTL-Technik, aber als ich die Schalterplatine gelötet hab, hab ich 1,8kOhm oder so genommen. Hab ein Steckbrett.
Das ist gut,man weißt ja nicht wie fit jemand in der Technik ist, und unkontrolierte Schaltvorgänge würden auf offene Eingänge hindeuten ;-)

Gruß Sebastian

P.S.
Schönes Netzteil...

Spongebob85
13.08.2007, 12:30
Ja, auf die Idee mit den Pulldown Widerständen wäre ich glaub ich auch zuerst gekommen, wenn ich du wäre. Ich hab jetzt noch das problem das die LED zwar verzögert aufleuchtet aber auch nach loslassen des Tasters auch verzögert wieder ausgeht, bzw. beide gehen verzögert aus. Hab im "else Zweig" doch gar keine Verzögerung programmiert. Versteh nicht woran das liegen kann.
MfG Jan

izaseba
13.08.2007, 13:16
Versteh nicht woran das liegen kann.

Ich sag mal, das Problem ist eher logischer Natur :-k
Schau Dir den Programmablauf in Ruhe an...
Du Testest, ob ein Pin HIGH ist, wenn ja schaltest Du eine LED sofort an, dann gehst Du in die "1Sekunde vernichten" Schleife rein, in der der µC jetzt gefangen ist, dann fragst Du wieder den Pin ab, wenn HIGH wieder 1 Sekunde nichts tun, egal ob die LEDs schon an ist, oder nicht
Wenn Du jetzt ungünstig Deinen Taster loslässt, also wenn i sag
ich mal 2 ist, wie lange dauert es, bis die nächste Pin Prüfung gemacht wird? :-b
Besser wäre hier auf Flankenwechsel zu reagieren, also in die Zeilen mit LED an und delay nur dann springen wenn der Pegel am PD0 von LOW auf HIGH wechselt.

Mögliche Lösung sieht dann so aus:



uint8_t flanke = 0;
...
...
if (PIND & (1<<PD0)) {
if (!flanke){
flanke = 1;
PORTA |= (1<<PA1);
for (i=1; i<=100; i=i+1)
{
_delay_ms(10);
}
PORTA |= (1<<PA0);
}
}

else{
flanke = 0;
PORTA &= ~(1<<PA0);
PORTA &= ~(1<<PA1);
}

Naja, ein Durchlauf ist jetzt aber nötig, Du mußt also die Taste solange drücken, bis PA0 HIGH wird, dafür gehen die LEDs sofort aus...
Logisch?
Gruß Sebastian

Spongebob85
13.08.2007, 22:27
Moin!!!
Hatte heut nicht so viel Zeit. Meine Freundin und ich haben Monatstag.
Ich hab das programm grade mal auf den uC gebrannt und es funzt auch gut,
nur das die LED an PA1 immer noch verzögert ausgeht. Das kann ich mir echt nicht mehr erklähren.
Das mit der Flankensteuerung find ich echt cool. Hat mir aber echt zu denken gegeben, wegen der Logik.
Hatte die ganze Zeit so einen blöden denkfehler.
Weißt du da auch noch eine Lösung? Warum werden die beiden Prots den unterschiedlich behandelt? Die stehen doch beide unter "else" und das die Flankensteuerung bezieht sich doch auch auf beide. Durch "Flanke = 1" kann das delay doch nur einmal ablaufen und dann erst wieder, wenn der taster losgelassen und erneut gedrückt wird.
Es müsste sowas wie einen Debugger geben das man das schrittweise durchlaufen lassen könnt. Dann würde man sehen wo´s hackt.
Naja,
MfG Jan

izaseba
13.08.2007, 23:12
Hallo,


Hatte heut nicht so viel Zeit. Meine Freundin und ich haben Monatstag.
Verständlich, meine Frau würd mir auch was antun, wenn ich an unserem Jahrestag an was anderem basteln würde...

Aber zu Deinem Problem, zuerst wolte ich schon das Programmchen auf meinen STK500 aufspielen um diesem "Phänomen" nachzugehen.
Es war aber nicht nötig (hoffe ich)
Vergleiche mal Deine Schleife mit der, die ich gepostet habe...
Ein Tip:
C erlaubt es Klammern{} wegzulassen, wenn ... was ?
Sowas fällt auf, wenn man das automatische Einrücken einschaltet...

Gruß Sebastian

P.S.
Das sollte schon früher auffallen... sowas sowas

Spongebob85
13.08.2007, 23:39
Ich hab dein Programm kopiert und bei mir eingefügt. Hab auch bisschen an den klammern rumgebastelt.
Man kann klammern weglassen, wenn nur eine Anweisung folgt, oder?

Hier nochmal der ganze Code von mir:


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

int main (void)
{
uint8_t i;
uint8_t flanke;

DDRA = 0xff;
DDRD &= ~(1<<DDD0);

while(1)
{
if (PIND & (1<<PD0))
{
if (!flanke)
{
flanke = 1;
PORTA |= (1<<PA1);
for (i=1; i<=100; i=i+1)
{
_delay_ms(10);
}
PORTA |= (1<<PA0);
}
}
else
{
flanke = 0;
PORTA &= ~(1<<PA0);
PORTA &= ~(1<<PA1);
}
}

}


Weiß echt nich weiter.
Man bräuchte einen Debugger um das alles mal schritt für schritt durchzuspielen.
Naja, N8.

izaseba
14.08.2007, 11:21
Man bräuchte einen Debugger um das alles mal schritt für schritt durchzuspielen.
Dann lad Dir doch AVRStudio runter, ist recht brauchbar

Das mit den Klammern stimmt, wenn man sie wegläßt wird nur die Zeile, die darunter ist ausgeführt, der rest nicht mehr.
Komisch, das letzte Programm von Dir müßte aber funktionieren, ich hab es doch ausprobiert, mußte zwar was anpassen, weil ich M8 zur Zeit drauf habe, und meine Taster gegen GND schalten, ich taste mir die Finger wund, und es klappt ohne Probleme, beide LED gehen sofort aus(natürlich nachdem man den Taster solange drückt, bis beide an sind) :-k
Hier mein Programm


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


int main (void)
{
uint8_t i;
uint8_t flanke=0;

DDRB = 0xff;
DDRD &= ~(1<<DDD0);

while(1) {
if (!(PIND & (1<<PD0))) {
if (!flanke){
flanke = 1;
PORTB |= (1<<PB1);
for (i=1; i<=100; i=i+1){
_delay_ms(10);
}
PORTB |= (1<<PB0);
}
} else {
flanke = 0;
PORTB &= ~((1<<PB0)|(1<<PB1));
}
}
return 0;
}



Gruß Sebastian

Spongebob85
14.08.2007, 14:21
So wird das auf jeden Fall nie langweilig.
Jetzt setze ich mich mit dem Nächsten Programm auseinander. AVR-Studio4
Das hab ich sogar schon drauf, weil ich das mal von meiner Robotikhardware CD draufgemacht hab.
Dann bis bald.
Gruß Jan

Spongebob85
15.08.2007, 22:02
Moin.
Ich hab grade mal das Programm in AVR-Studio4 geschrieben.Als ich auf Build gedrückt hab kamen erstmal 2 Warnungen. Diese:

C:/WinAVR/avr/include/util/delay.h:136:3: warning: #warning "F_CPU not defined for <util/delay.h>"
../Testing.c: In function `main':

Und diese:

../Testing.c:23: warning: statement with no effect

Ich dachte das Prog is fehlerfrei.
Oder soll ich die einfach ignorieren? Das kann doch irgendwie nich sein, oder?

Wenn ich dann auf F10 durchticker bleibt der irgendwie immer bei der for-Schleife hängen. Hab die jetzt schon geändert. Jetzt: for (i=1; i<=2; i=i+1) aber der geht immer die gleiche schleife durch.

MfG Jan

izaseba
16.08.2007, 11:25
Hallo, erste Warnung ist klar, hast Du F_CPU auch vor #include<util/delay.h> definiert ?
Die zweite Warnung ist an sich auch klar, nur wer soll bitte wissen, was in der Zeile 23 drin steht ?
Zu AVRStudio muß ich im Moment Schulter zucken, da ich keinen Winrechner z.Z. habe, ich kann mich aber daran errinern, daß man komisches Verhalten beobachtet, wenn Optimierung eingeschaltet ist, kannst mal testen...
Das könnte aber wiederum eine neue Warnung mit sich bringen, wiel mal _delay* nicht ohne Optimierung verwenden soll.
Sonst kannst Du die _delay* weglassen und irgendwas anderes reinschreiben, der logische Aufbau bleibt dann doch gleich, oder ?

Spongebob85
16.08.2007, 16:55
](*,) Da hab ich ja wieder eine geistige Glanzleistung vollbracht!!! In Zeile 23 stand:
for (i=1; i<=2; i+1) dabei muss es doch i=i+1 heißen.
Das is echt ziemlich dämlich!!!
Naja, wie man die Optimierung ausstellt hab ich nicht rausgefunden.
Das mit dem #Include... hinterher klappt. Danke!!!

Spongebob85
16.08.2007, 20:48
Hab das nochmal bei AVRStudio durchgespielt. Warum bei mir die LED immernoch verzögert ausgeht werde ich wohl nie verstehen.
Kümmer mich jetzt mal lieber um Timer und so.
Bis Bald
Gruß Jan