- 3D-Druck Einstieg und Tipps         
Seite 2 von 2 ErsteErste 12
Ergebnis 11 bis 17 von 17

Thema: Timing bzw. Semi-multitasking

  1. #11
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo

    Annahme: Stopwatch steht bei 40

    If Stopwatch3 < 80 ---> ist True
    If Stopwatch3 < 80+80 ---> ist aber ebenfalls True
    Wo ist denn das "else" geblieben? < 160 wird nur geprüft, wenn die StopWatch >= 80 ist...

    Warum eigentlich 80+80 und nicht gleich 160?
    So sieht man auf einen Blick ohne großen Kommentar, wie der Wert entsteht. Da es sich um Konstanten handelt, wird beim Kompilieren beides gleich übersetzt:
    Code:
    // testzeile +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       if (getStopwatch3() < 80)
         24c:	80 91 b8 00 	lds	r24, 0x00B8
         250:	90 91 b9 00 	lds	r25, 0x00B9
         254:	80 35       	cpi	r24, 0x50	; 80
         256:	91 05       	cpc	r25, r1
         258:	90 f0       	brcs	.+36     	; 0x27e <eigenefunktion+0x32>
       {
    		setLEDs(63);
          //PORTC |= IO_PC7;
          //PORTC |= IO_PC5;
       }
    	else if (getStopwatch3() < 80+80)
         25a:	80 91 b8 00 	lds	r24, 0x00B8
         25e:	90 91 b9 00 	lds	r25, 0x00B9
         262:	80 3a       	cpi	r24, 0xA0	; 160
         264:	91 05       	cpc	r25, r1
         266:	20 f4       	brcc	.+8      	; 0x270 <eigenefunktion+0x24>
    	//testzeile
       {
    		setLEDs(0);
         268:	80 e0       	ldi	r24, 0x00	; 0
         26a:	0e 94 a6 01 	call	0x34c <setLEDs>
         26e:	08 95       	ret
          //PORTC &= ~IO_PC7;
          //PORTC &= ~IO_PC5;
       }
       else if (getStopwatch3() < 80+80+80)
         270:	80 91 b8 00 	lds	r24, 0x00B8
         274:	90 91 b9 00 	lds	r25, 0x00B9
         278:	80 3f       	cpi	r24, 0xF0	; 240
         27a:	91 05       	cpc	r25, r1
         27c:	10 f4       	brcc	.+4      	; 0x282 <eigenefunktion+0x36>
       {
    		setLEDs(63);
         27e:	8f e3       	ldi	r24, 0x3F	; 63
         280:	f4 cf       	rjmp	.-24     	; 0x26a <eigenefunktion+0x1e>
          //PORTC |= IO_PC7;
          //PORTC |= IO_PC5;
       }
       else if (getStopwatch3() < 80+80+80+100)
         282:	80 91 b8 00 	lds	r24, 0x00B8
         286:	90 91 b9 00 	lds	r25, 0x00B9
         28a:	84 55       	subi	r24, 0x54	; 84
         28c:	91 40       	sbci	r25, 0x01	; 1
         28e:	60 f3       	brcs	.-40     	; 0x268 <eigenefunktion+0x1c>
       {
    		setLEDs(0);
          //PORTC &= ~IO_PC7;
          //PORTC &= ~IO_PC5;
       }
       else setStopwatch3(0);
         290:	10 92 b9 00 	sts	0x00B9, r1
         294:	10 92 b8 00 	sts	0x00B8, r1
         298:	08 95       	ret
    
    0000029a <main>:
    }
    // testzeile +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    Bei meinem RP6 funktioniert das Programm oben wie erwartet. Wenn man z.b. die 100 in 1000 ändert, sieht man deutlich den geänderten Blinkrythmus. Warum dein Piepen nicht funktioniert liegt möglicherweise an der Erweiterung.

    Gruß

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  2. #12
    Erfahrener Benutzer Roboter Genie Avatar von SlyD
    Registriert seit
    27.11.2003
    Ort
    Paderborn
    Alter
    39
    Beiträge
    1.516
    Nur so als kleiner Tipp:

    Auch bei dem Programm mit den LEDs werden die "setLEDs" Funktionien ständig aufgerufen - ohne große Pause. Nur merkt man das da nicht da es nichts ändert (mach mal ne Textausgabe da rein ).

    Bei den Beep Funktionen merkt man das natürlich sofort.

    Eine Bedingung wie "if(x > 2000)"
    ist IMMER wahr wenn x größer als 2000 ist... auch bei 2100, 2455, 43432...
    Genauso ist eine Bedingung wie "if(x < 2000)" IMMER wahr solange x kleiner als 2000 ist - also bei 0, 100, 143, 1423, 1999...


    Da muss man schon zusätzliche Dinge einbauen damit das klappt.

    z.B. so etwas:
    Code:
    startStopwatch1(); // Stopwatch1 starten!
    uint8_t count = 0; // Sekundenzähler
    while(true)
    {
       if(getStopwatch1() > 1000) // 1000ms = 1s
       {                   
          switch(count) // Sekundenzähler auswerten
          {
             case 1: 
                writeString_P("Bin jetzt bei Sekunde 1\n");
    			writeString_P("Wird auch nur einmal ausgegeben!\n");
             break;
             case 4: 
                writeString_P("Jetzt bei Sekunde 4\n");
             break;
             case 8: 
                writeString_P("Jetzt bei Sekunde 8\n");
    			count = 0;
    			writeString_P("Ich fang jetzt mal wieder von vorn an...\n\n");
             break;
          }
          count++; // Sekundenzähler erhöhen
          setStopwatch1(0);
       }
    }
    Nicht verwechseln - die Ausgabe erfolgt hier BEI Sekunde 1, 4 und 8 - es wird also nicht 4 Sekunden dazwischen gewartet, sondern 3 bzw. 4.

    Die Stopwatches sind vor allen dazu gedacht irgendetwas periodisch auszuführen, oder verzögert nach einer gewissen Zeit.
    Eine einzige für sequenzen zu benutzen ist mit einem kleinen Automaten wie oben gezeigt deutlich einfacher.

    (das switch-case kann man natürlich auch durch if-else-if-else ersetzen wenn man das schöner findet)

    MfG,
    SlyD

  3. #13
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Bild hier  
    (http://www.youtube.com/watch?v=8cTLP5knsfk)

    Das ist die Ausgabe von diesem Programm:
    Code:
    #include "RP6RobotBaseLib.h"
    
    void eigenefunktion(void)
    {
    // testzeile +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       if (getStopwatch3() < 800)
       {
    		setLEDs(63);
          //PORTC |= IO_PC7;
          //PORTC |= IO_PC5;
       }
    	else if (getStopwatch3() < 800+800)
    	//testzeile
       {
    		setLEDs(0);
          //PORTC &= ~IO_PC7;
          //PORTC &= ~IO_PC5;
       }
       else if (getStopwatch3() < 800+800+800)
       {
    		setLEDs(63);
          //PORTC |= IO_PC7;
          //PORTC |= IO_PC5;
       }
       else if (getStopwatch3() < 800+800+800+1000)
       {
    		setLEDs(0);
          //PORTC &= ~IO_PC7;
          //PORTC &= ~IO_PC5;
       }
       else setStopwatch3(0);
    }
    // testzeile +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
    
    int main(void)
    {
    	initRobotBase();
    	setLEDs(0);
    	//DDRC |= IO_PC7 | IO_PC6 | IO_PC6 | IO_PC4
       //PORTC &= ~IO_PC7;
       //PORTC &= ~IO_PC6;
       //PORTC &= ~IO_PC5;
       //PORTC &= ~IO_PC4;
    
    	setStopwatch3(0);
    	startStopwatch3();
    
    	while(true)
    	{
    	   eigenefunktion();
    	}
    	return 0;
    }
    und wird auf einem RP6-Base ausgeführt. Einzige Änderung gegenüber der ersten Version sind die geänderten StopWatch-Werte.

    Die else-Zweige in den Abfragen werden doch erst ausgeführt, wenn die vorhergehende Prüfung auf "kleiner als" false ergab. "Case" würde mir hier auch besser gefallen...

    Gruß

    mic

    [Edit]
    Mit "case" sieht's nicht wirklich besser aus:
    Code:
    #include "RP6RobotBaseLib.h"
    
    void eigenefunktion(void)
    {
    	uint8_t step;
    	uint16_t temp;
    	
    	temp = getStopwatch3();
    	step = (temp < 800) << 0 \
    				| (temp < 800+800) << 1 \
    					| (temp < 800+800+800) << 2 \
    						| (temp < 800+800+800+1000) << 3 \
    							| (temp >= 800+800+800+1000) << 4;
    	//writeInteger(step, 2);
    	//writeString_P("\n\r");
    
    	switch (step)
    	{
    	   case(16-1): setLEDs(32+4); break;
    	   case(16-2): setLEDs(0b10010); break;
    	   case(16-4): setLEDs(9); break;
    	   case(16-8): setLEDs(0); break;
    	   case(16): setStopwatch3(0); break;
    	}
    }
    int main(void)
    {
    	initRobotBase();
    	setLEDs(0);
    	setStopwatch3(0);
    	startStopwatch3();
    
    	while(true)
    	{
    	   eigenefunktion();
    	}
    	return 0;
    }
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  4. #14
    Erfahrener Benutzer Roboter Genie Avatar von SlyD
    Registriert seit
    27.11.2003
    Ort
    Paderborn
    Alter
    39
    Beiträge
    1.516
    @mic:

    Ich glaub da hast Du mich nicht so ganz verstanden.

    Probier mal das aus und schau Dir die Ausgaben im Terminal an - dann sollte deutlich werden was ich meine:
    Code:
       startStopwatch3();
    
       while(true)
       {
         
    		if (getStopwatch3() < 800)
    		{
    		  setLEDs(63);
    		  writeString_P("das hier wird gaaanz oft aufgerufen. Stopwatch: ");
    		  writeInteger(getStopwatch3(),DEC);
    		  writeChar('\n');
    		}
    		else if (getStopwatch3() < 800+800)
    		{
    		  setLEDs(0);
    		  writeString_P("Noch mehr...  Stand der Stopwatch: ");
    			writeInteger(getStopwatch3(),DEC);
    		  writeChar('\n');
    		}
    		else if (getStopwatch3() < 800+800+800)
    		{
    		  setLEDs(63);
    		  writeString_P("und noch mehr ... Stopwatch: ");
    		  writeInteger(getStopwatch3(),DEC);
    		  writeChar('\n');
    		}
    		else if (getStopwatch3() < 800+800+800+1000)
    		{
    		  // hier mal zur Abwechslung nix ausgeben
    		  setLEDs(0);
    		}
    		else setStopwatch3(0);
    		
    		mSleep(10); // ja das ist absichtlich hier drin, damit die
    					// Ausgaben nicht noch schneller erfolgen...
       }

    Bei den setLEDs Funktionen macht es natürlich keinen Unterschied ob man 1x setLEDs(0) aufruft oder 1000x.
    Bei einer Sound Ausgabe aber schon! Die sollte man nur ein einziges mal Aufrufen sonst klappt es nicht richtig.

    Mit "case" sieht's nicht wirklich besser aus:
    Naja - geht aber auch deutlich einfacher

    Code:
    startStopwatch1(); // Stopwatch1 starten!
    uint16_t count = 0; // 100-Millisekunden Zähler 
    while(true)
    {
       if(getStopwatch1() > 100) // 100ms = 0.1s
       {                   
           switch(count)
          {
    		case 8: // 800ms	
    			setLEDs(0); 
    		break;
    		case 8+8:  // 1600ms
    			setLEDs(63); 
    		break;
    		case 8+8+8: // 2400ms
    			setLEDs(0); 
    		break;
    		case 8+8+8+8: // 3200ms
    			setLEDs(63); 
    			count = 0;
    		break;
          }
          count++; // 100-Millisekunden Zähler erhöhen
          setStopwatch1(0);
       }
    }
    Das ist übrigens equivalent zu:
    Code:
    startStopwatch1(); // Stopwatch1 starten!
    uint16_t count = 0; // 100-Millisekunden Zähler 
    while(true)
    {
       if(getStopwatch1() > 100) // 100ms = 0.1s
       {                   
    		if(count==8) {
    			setLEDs(0); 
    		}
    		else if (count == 8+8) { 
    			setLEDs(63); 
    		}
    		else if (count == 8+8+8) { 
    			setLEDs(0); 
    		}
    		else if (count == 8+8+8+8) { 
    			setLEDs(63); 
    			count = 0;
    		}
    		count++; // 100-Millisekunden Zähler erhöhen
    		setStopwatch1(0);
       }
    }
    wenn man if-else lieber mag.

    MfG,
    SlyD

  5. #15
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Ach, jetzt hat's geklingelt. Und die Case-Lösung sieht auch nett aus. Danke.

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  6. #16
    Neuer Benutzer Öfters hier
    Registriert seit
    04.01.2008
    Beiträge
    9
    Hallo zusammen,

    das heißt, ich muss die LED´s über einen Zähler laufen lassen, der wiederum von der Stopwatch "gefüttert wird"?

    Macht für mich grad keinen Sinn? Funktion ist doch funktion, oder? Ob ich jetzt sage:

    Wenn Stopwatch>100 dann mach das Licht an

    müsste es doch mit:

    Wenn Stopwatch>100 dann setz den Zähler hoch

    gleich sein oder?? Ich meine in beiden Fällen soll er eine Aktion durchführen?!

    Kann man eigentlich alle C-Befehle für den Atmel verwenden?

    Gruß

    Markus

  7. #17
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Der Unterschied ist folgender:

    Wenn du die StopWatch() mit > bzw. < abfragst, wird die Bedingung in mehreren Durchgängen erfüllt, also die LEDs mehrfach gesetzt oder die Sounds mehrfach gestartet. Also müßte man auf == testen, mit dem Risiko, dass die StopWatch() blöderweise genau unseren Prüfwert überspringt, weil wir den Aufruf zu lange verzögert haben.

    Die Lösung ist deshalb z.B. ein zusätzlicher Zähler. Weil wir den Zähler nur erhöhen, wenn wir die Funktion ausführen, können wir keinen Wert überspringen. Allerdings stimmt das Timing nicht, wenn wir langsamer aufrufen als die StopWatch() auf 100 zählt.

    Das AVR-C ist eine Untermenge von C, es funktioniert nur, was auch Sinn macht. Ein Tutorial bei den Mikrocontrollern: http://www.mikrocontroller.net/artic...R-GCC-Tutorial

    Gruß

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

Seite 2 von 2 ErsteErste 12

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

fchao-Sinus-Wechselrichter AliExpress