-         

Ergebnis 1 bis 6 von 6

Thema: RP6 - Stopwatch

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    13.02.2011
    Ort
    Wien
    Alter
    37
    Beiträge
    9

    RP6 - Stopwatch

    Anzeige

    Hallo zusammen,

    ich hab seit ein paar Tagen einen RP6 und bin gerade dabei mich mit ihm bzw. der Robotertechnik im Allgemeinen anzufreunden.

    Heute hab ich mich ein wenig mit der Stopwatch beschäftigt und dabei ein eigenartiges Phänomen festgestellt.
    Hier ein einfaches Programm das die Stopwatch1 verwendet um alle 600ms die LEDS paarweise weiterlaufen zu lassen
    Code:
    #include "RP6RobotBaseLib.h" 	// The RP6 Robot Base Library.
    
    int main(void)
    {
    	initRobotBase();
    	writeString_P("Do some LED stuff!\n");
    	startStopwatch1();
    
    	uint8_t runningLight = 9;
    	uint16_t stopVal = 0;
    	
    	while(true)
    	{	
    		stopVal = getStopwatch1();
    		if (stopVal > 600)
    		{
    			writeInteger(getStopwatch1(), DEC);
    			writeChar('\n');
    			writeInteger(stopVal, DEC);
    			writeChar('\n');
    			writeChar('\n');
    			
    			setLEDs(runningLight); 	
    			runningLight <<= 1;
    			if(runningLight > 36)
    				runningLight = 9;
    			setStopwatch1(0);
    		}		
    
    	}
    
    	return 0; 
    }
    Dazu habe ich mir eine Ausgabe eingebaut um den Wert der Stopwatch zu sehen.
    Unerwarteterweise sieht jetzt der Output auf der Konsole so aus:
    Code:
    [READY]
    Do some LED stuff!
    601
    601
    
    601
    601
    
    601
    601
    
    601
    601
    
    601
    601
    
    512
    767
    
    512
    767
    
    512
    767
    
    601
    601
    das heißt der Wert den die Stopwatch liefert stimmt nicht immer mit dem Wert in der Variable (die eigentlich auch den Stopwatch-Wert haben sollte) überein.

    Gibt es dafür eine plausible erklärung?

    danke schon mal im voraus,
    Gruß,
    Martin

  2. #2
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    54
    Beiträge
    5.782
    Blog-Einträge
    8
    Hallo

    Code:
    #include "RP6RobotBaseLib.h"    // The RP6 Robot Base Library.
    
    int main(void)
    {
       initRobotBase();
       writeString_P("Do some LED stuff!\n");
       startStopwatch1();
    
       uint8_t runningLight = 9;
       uint16_t stopVal = 0;
    
       while(true)
       {
          cli();
    		stopVal = getStopwatch1();
    		sei();
          if (stopVal > 600)
          {
             writeInteger(getStopwatch1(), DEC);
             writeChar('\n');
             writeInteger(stopVal, DEC);
             writeChar('\n');
             writeChar('\n');
    
             setLEDs(runningLight);
             runningLight <<= 1;
             if(runningLight > 36)
                runningLight = 9;
             setStopwatch1(0);
          }
    
       }
    
       return 0;
    }
    Genau bei stopVal = getStopwatch1(); tritt ein ISR-Aufruf auf. Das Highbyte der StopWatch ist schon erhöht, das Lowbyte noch nicht:

    511 ist binär 01 11111111
    512 ist binär 10 00000000
    767 ist binär 10 11111111

    Deshalb ist stopVal größer als 600 und die Stoppuhr aber immer noch kleiner als 600 ;)

    Das Stichwort heißt "atomar".

    Eigentlich logisch, aber das hat bisher noch keiner bemerkt. Glückwunsch!

    Gruß

    mic

    [Edit]
    Code:
    #include "RP6RobotBaseLib.h"    // The RP6 Robot Base Library.
    
    int main(void)
    {
       initRobotBase();
       startStopwatch1();
    
       while(true)
       {
          if (getStopwatch1() > 600)
          {
             writeInteger(getStopwatch1(), DEC);
             if(getStopwatch1() < 601) writeChar('*');
             writeChar('\n');
             setStopwatch1(0);
          }
       }
       return 0;
    }
    Code:
    #include "RP6RobotBaseLib.h"    // The RP6 Robot Base Library.
    
    int main(void)
    {
       initRobotBase();
       startStopwatch1();
    
       while(true)
       {
          cli();
    		if (getStopwatch1() > 600)
          {
             sei();
    			writeInteger(getStopwatch1(), DEC);
             if(getStopwatch1() < 601) writeChar('*');
             writeChar('\n');
             setStopwatch1(0);
          }
          else sei();
       }
       return 0;
    }
    Schlanker und schneller wäre wohl ein schlichtes

    }
    sei();

    anstelle von

    }
    else sei();

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

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    13.02.2011
    Ort
    Wien
    Alter
    37
    Beiträge
    9
    Dankeschön radbruch - für die Hilfe und die Glückwünsche
    da hätte ich sonst wohl noch länger daran zu grübeln gehabt

    mfG,
    Martin

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    13.02.2011
    Ort
    Wien
    Alter
    37
    Beiträge
    9
    ...dabei drängt sich noch folgende Frage auf: empfiehlt es sich dann generell vor timer-abfragen interrupts zu blockieren?

    weil "verloren gehen" sollten sie ja ohnehin nicht wenn ich sie nachher mit sei() wieder freigebe

    mfG,
    Martin

  5. #5
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    54
    Beiträge
    5.782
    Blog-Einträge
    8
    Hallo

    Ob man die Interrupts bei StopWatch-Abfragen generell sperren sollte hängt wohl in erster Linie von der geforderten Genauigkeit der Anwendung und dem gewählten Zeitintervall ab. Wenn man die Interrupts nicht sperren will, könnte man den Effekt auch mit einer kleinen Plausibilitätsprüfung vermeiden:

    Code:
     #include "RP6RobotBaseLib.h"    // The RP6 Robot Base Library.
    
    int main(void)
    {
       initRobotBase();
       writeString_P("Do some LED stuff!\n");
       startStopwatch1();
    
       uint8_t runningLight = 9;
       uint16_t stopVal = 0;
    
       while(true)
       {
          stopVal = getStopwatch1();
          if(stopVal != getStopwatch1())
          	stopVal = getStopwatch1();
          	
          if (stopVal > 600)
          {
             writeInteger(getStopwatch1(), DEC);
             writeChar('\n');
             writeInteger(stopVal, DEC);
             writeChar('\n');
             writeChar('\n');
    
             setLEDs(runningLight);
             runningLight <<= 1;
             if(runningLight > 36)
                runningLight = 9;
             setStopwatch1(0);
          }
    
       }
    
       return 0;
    }
    Entweder stört der Interrupt die erste Zuweisung oder die If-Abfrage oder er tritt dazwischen auf. In allen Fällen wird dann die zweite Zuweisung nicht mehr gestört sein. Oder der Interrupt stört gar nicht, dann ist schon die erste Zuweisung erfolgreich gewesen.

    Oder allgemein:
    Code:
     #include "RP6RobotBaseLib.h"    // The RP6 Robot Base Library.
    
    int main(void)
    {
       initRobotBase();
       startStopwatch1();
    
       while(true)
       {
          if ((getStopwatch1() > 600) && (getStopwatch1() > 600))
          {
             writeInteger(getStopwatch1(), DEC);
             if(getStopwatch1() < 601) writeChar('*');
             writeChar('\n');
             setStopwatch1(0);
          }
       }
       return 0;
    }
    Gruß

    mic

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

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    13.02.2011
    Ort
    Wien
    Alter
    37
    Beiträge
    9
    alles klar - danke nochmal für die Hilfe

    mfG,
    Martin

Berechtigungen

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