Hallo,
ich habe folgendes vor. Ich möchte mit einem Taster zwei Kanäle hin und
her schalten.Und dazwischen eine von mir definierte Wartezeit eingeben.
-wenn Taster nicht gedrückt
-schalte PA7 und PA3 aus
-warte
-schalte PA3 ein
-wenn taster gedrückt
-schalte PA3 und PA7 aus
-warte
-schalte PA7 ein
wenn ich keine zeitverzögerung haben wollte, ja gar kein Problem für
mich wäre.
jetzt habe ich, aber bei meinem Code das Problem das ich aus der letzten
while Schleife nicht mehr raus komme. wie kann ich das abändern. ?
1
/*
2
* GccApplication10.c
3
*
4
* Created: 16.10.2016 11:55:50
5
* Author: huber
6
*/
7
8
#define F_CPU 1000000UL
9
#include<util/delay.h>
10
#include<avr/io.h>
11
12
#define warte 4000
13
14
uint8_tx=2;
15
16
17
intmain(void)
18
{DDRA=(1<<PA3)|(1<<PA7);
19
PORTA=(1<<PA0);
20
21
22
23
while(1)
24
{
25
26
anfang();
27
28
if((PINA&(1<<PA0)))
29
{
30
31
PORTA&=~(1<<PA7);
32
PORTA&=~(1<<PA3);
33
//_delay_ms(warte);
34
while(1)
35
{
36
PORTA|=(1<<PA3);
37
38
if(!(PINA&(1<<PA0)))
39
{
40
41
PORTA&=~(1<<PA3);
42
PORTA&=~(1<<PA7);
43
//_delay_ms(warte);
44
while(1)
45
{
46
PORTA|=(1<<PA7);
47
48
}
49
50
}
51
}
52
53
}
54
55
}
56
}
bei diesem Code klappt zwar das Umschalten mit Verzögerung, aber es
verzögert sich auch die Zeit nach dem er gedrückt oder nicht gerdrückt
wurde bis er in den eigentlichen Zustand fällt.Weil er halt die while
Schleife erst zu ende durchläuft. Wie könnte ich denn das abändern.?
1
/* Hallo, an mich;
2
3
also mein code soll nachfolgendes machen.:
4
5
Taster nicht gedrückt
6
schalte PA7 aus
7
warte eine zeit
8
schalte PA3 ein
9
10
Taster gedrückt
11
schalte PA3 aus
12
warte eine zeit
13
schalte PA7 ein
14
15
jetzt habe ich folgendes Problem, wenn ich den taster drücke,
16
geht er nicht sofort in den anderen zustand und umgekehrt. Wie kann ich das ändern.?
17
18
Im prinzip möchte ich mit einem Taster zwischen zwei Kanäle umschalten. Und es soll dabei der jeweills gewhälte
19
Kanal erst aus sein, und nach einer von mir definierten zeit dann einschalten. Und der nicht gewählte kanal natürlich aus.
definiere ein Flag "Abbruchbedingung", welches auf "true" gesetzt wird,
sobald die Abbruchbedingung zutrifft.
und deine Abfrage geht dann auf
while !(Abbruchbedingnung)
{
mache irgendwas
}
Huber M. schrieb:> grüsse Huber
Das hat man dir schon mal gesagt .....
Ich hab "in der Schule" gelernt dass man in C nicht Funktionen
innerhalb von Funktionen definieren darf. Dass der Compiler das
geschachtelte frisst ist erstaunlich, aber das Verhaltens-Ergebnis
ist schlichtweg undurchsichtig ...... und vermutlich irritierend.
Mitlesa schrieb:> Ich hab "in der Schule" gelernt dass man in C nicht Funktionen> innerhalb von Funktionen definieren darf. Dass der Compiler das> geschachtelte frisst ist erstaunlich
Es gibt Compiler, die das als Erweiterung unterstützen, aber
Standardkonform ist es nicht.
wenn ich wüsste wie ich es anders lösen könnte, würde ich es machen.
Im prinzip möchte ich mit einem Taster zwischen zwei Kanäle umschalten.
Und es soll dabei der jeweills gewhälte
Kanal erst aus sein, und nach einer von mir definierten zeit dann
einschalten. Und der nicht gewählte kanal natürlich aus.
Huber M. schrieb:> -wenn Taster nicht gedrückt> -schalte PA7 und PA3 aus> -warte> -schalte PA3 ein>> -wenn taster gedrückt> -schalte PA3 und PA7 aus> -warte> -schalte PA7 ein
Das geht nicht.
Du mußt schon sinnvolle Regeln aufstellen.
Ein Taster kann nur gedrückt oder nicht gedrückt sein.
D.h. die 2.Zeile in beiden Bedingungen schaltet ständig alles aus. Und
nach dem Delay geht einer für wenige µs kurz an, bis wieder die 2.Zeile
erreicht wird.
Regeln für den MC müssen immer eindeutig sein. Erst dann kann man sie
auch programmieren.
Generell fragt man Tasten nicht direkt im Code ab, sondern überläßt das
einer Entprellroutine, die entprellt und die Tastenereignisse (Events)
für das Main aufbereitet.
Für verzögerte Aktionen nehme ich einen Scheduler.
Man kann aber auch Statemachines nehmen, die z.B. in einem 10ms
Zeitraster aufgerufen werden.
Huber M. schrieb:> Im prinzip möchte ich mit einem Taster zwischen zwei Kanäle umschalten.> Und es soll dabei der jeweills gewhälte Kanal erst aus sein, und nach> einer von mir definierten zeit dann einschalten.
Kannst du das mal statt in Prosa in einem Timing-Diagramm darstellen?
Sowas liest sich irgendwie leichter...
> wenn ich wüsste wie ich es anders lösen könnte, würde ich es machen.
Du hast den falschen Ansatz für die Lösung deiner Aufgabe. Stichworte
für den richtigen Ansatz sind: Endlicher Automat, Zustandsautomat, FSM,
State Machine
Ein üblicher und leicht erweiterbarer Code sieht also so aus, dass die
Hauptschleife ständig (schnellstmöglich ohne delay()!) durchlaufen wird
und darin dann lediglich abgefragt wird, ob z.B. wegen einer
abgelaufenen Zeit oder wegen äusseren Eingaben (z.B. Taster, Sensoren)
Aktionen nötig sind. Dazu braucht es aber als "Infrastruktur" einen
Zeitgeber, der z.B. in einem Interrupt einen ms-Zähler (oder
Hundertstelsekunden oder Zehntelsekunden...) hochzählt.
Beim Arduino gibt es dafür die Funktion millis(), die die Millisekunden
seit Power-On zurückgibt. Und dann kann man das so angehen:
https://learn.adafruit.com/multi-tasking-the-arduino-part-1/using-millis-for-timing
Und wenn du diesen Ansatz mit den Zeitdifferenzen und der schnell
durchlaufenen Hauptschleife hast, dann findest du dann auch ganz schnell
den Weg zur State Machine...
Moing;
wäre das eine Möglichkeit die in die richtige Richtung geht? Hier wird
es ja auch langsam, bzw. wo setze ich dann am besten das delay oder
nochmal irgendwie mit Timer intterrupt?
Nico W. schrieb:> finde den Artikel sehr gut beschrieben.
Das Konzept selber ist dort hübsch dargestellt.
Trotzdem sollte dabei im Hinterkopf behalten werden: die von mir
erwähnte Zeitbasis ist dort beim Ampel-Beispiel einfach über das
delay(1000) gemacht. Diese aktive Rechenzeitvernichtung mit dem delay()
verhindert dann auch wirksam, dass z.B. ein Anforderungsknopf einer
Fußgängerampel mit eingebunden werden kann. Denn der Fußgänger wird
nicht mindestens 1 Sekunde lang auf den Anforderungstaster drücken.
Sondern bestenfalls kurz mal draufhauen...
Lothar M. schrieb:> Trotzdem sollte dabei im Hinterkopf behalten werden: die von mir> erwähnte Zeitbasis ist dort beim Ampel-Beispiel einfach über das> delay(1000) gemacht.
Was hindert dich daran das alles über einen Interrupt alle 1000ms oder
so aufzurufen?
ok, das ist jetzt die Statemaschine mit der Ampel. Und auch in meinem
buch ist es ebenfalls mit delay in der Schleife. Nun meine Frage mit
welchen Interrupt kann ich das delay ersetzen zb.TCNT. und wie setzte
ich das dann ein. bzw. welchen verendet man dazu vielleicht komme ich
dann von alleine drauf.
Ganz grob so. Der Code ist jetzt schnell dahin getippt. Fehler dürfen
selbst gefunden und korrigiert werden.
Tick ist hier 1ms. Also dementsprechend den Zähler mal 1000 nehmen oder
irgendwie anders über Prescaler oder so auf eine Sekunde erweitern. Je
wie man das will und braucht.
1
// Tabelle fuer state machine
2
3
ampel_state_tstate_table[8]={
4
5
// AMPEL1 AMPEL2 Induktionsschleife ?
6
// | | | Wartezeit in s <- den hier mal 1000 z.B. um von ms auf s zu kommen
Nico W. schrieb:> Ganz grob so. Der Code ist jetzt schnell dahin getippt. Fehler dürfen> selbst gefunden und korrigiert werden.
ok das ist das was ich brauche. Jetzt habe ich einen 8 bit Timer mit
Timer 0 im Normal Modus. Bei dem im sec. Takt an PB1 eine led toggled.
Aus meinem buch.Da kann ich schneller etwas nachlesen. Und zum späteren
Zeitpunkt mit der Statemaschine vereinigen. Ich habe das eigentlich
alles soweit verstanden, wie ich glaube. Allerdings blinkt es nicht.
Kann aber keinen fehler entdecken
1
#define F_CPU 8000000UL
2
#include<avr/io.h>
3
#include<avr/interrupt.h>
4
5
#define statusled (1<<PB1) // LED an PB1
6
7
uint8_ttimer_overflow_counter=0;
8
9
voidinit_timer_0(void)
10
{
11
TCCR0A=0x00;// weil kein bit gesetzt werden muss für gewüschte Funktion
Huber M. schrieb:> uint8_t timer_overflow_counter = 0;Huber M. schrieb:> if (timer_overflow_counter <= 999) // Zählvariable 999 mal> hochzählenHuber M. schrieb:> Kann aber keinen fehler entdecken
Immer noch nicht???
Selbst meine dreijährige Enkelin weiß, dass sie mit Ihren Fingern nicht
alle Fussballer auf dem Platz zählen kann!
Huber M. schrieb:> Kann aber keinen fehler entdecken
Ich habe zwar keine Ahnung von C, vermute aber, daß in den Datentyp
"uint8_t" nur maximal 255 reinpasst. 999 wäre zu "dick" dafür.
MfG Paul
Route 6. schrieb:> dass sie mit Ihren Fingern nicht> alle Fussballer auf dem Platz zählen kann!
Kann man doch - mit den Fingern einer Hand kann man alle 22 Spieler und
sogar den Schiedrichter und ein paar Linienrichter mitzählen. Für 999
Marathonläufer braucht man allersdings schon die Finger beider Hände,
ein Arbeiter vom Sägewerk, dem zwei Finger fehlen, könnte halt nur bis
255 Marathonläufer zählen...
Thomas E. schrieb:> Kann man doch - mit den Fingern einer Hand kann man alle 22 Spieler und> sogar den Schiedrichter und ein paar Linienrichter mitzählen.
Das weiß aber meine dreijährige Enkelin nicht, und auf diesem
Wissensstand wollte ich dem TO seinen Denfehler aufzeigen.