- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 9 von 9

Thema: Problem beim Konfigurieren von TIMER1 beim M32-Board

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    03.01.2012
    Ort
    Großefehn LK Aurich, Ostfriesland)
    Alter
    43
    Beiträge
    17

    Problem beim Konfigurieren von TIMER1 beim M32-Board

    Anzeige

    Powerstation Test
    Hallo an Alle!

    Ich benötige eine ISR die alle 1µs aufgerufen wird. Ich habe versucht mir dafür den ungenutzten TIMER1 des M32-Boards zu konfigurieren, aber da ich auf diesem Gebiet Null Durchblick habe, ist es mir bislang nicht gelungen.
    Kann mir bitte jemand den Code geben mit dem TIMER1 dementsprechend konfiguriert wird und wie die ISR dann aussehen muss?

    Danke schonmal im Vorraus!

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    30.12.2009
    Ort
    Koblenz
    Alter
    45
    Beiträge
    78
    Moin, vielleicht hilft Dir ja das weiter

    https://www.roboternetz.de/phpBB2/dl...le&file_id=169
    Ich habe bereits bis Unendlich gezählt. Zweimal, und zurück

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    03.01.2012
    Ort
    Großefehn LK Aurich, Ostfriesland)
    Alter
    43
    Beiträge
    17
    Das habe ich auch schon gefunden, nur leider habe ich keinen Schimmer wie ich das was da rauskommt in C schreiben muss.

  4. #4
    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

    1µs ist aber wenig. Das m32 taktet mit 16MHz, ein Takt dauert 1s/16000000Hz = 0,0000000625 Sekunde. Eine Mikrosekunde dauert 0,000001s oder 0,000001s/0,0000000625s = 16Takte! (verblüffend;)

    Was willst du denn mit der 1µs anstellen?

    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!

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    03.01.2012
    Ort
    Großefehn LK Aurich, Ostfriesland)
    Alter
    43
    Beiträge
    17
    Ich möchte damit meine Servos steuern, dies habe ich bislang über den schon vorhandenen Timer0 gemacht, wo ich meine Routine für die Steuerung mit hinzugeschrieben habe:

    if(servo_timer>servo1_pos_d) PORTD &= ~IO_PD6; else PORTD |= IO_PD6;
    if(servo_timer>servo2_pos_d) PORTC &= ~IO_PC4; else PORTC |= IO_PC4;
    if(servo_timer>servo3_pos_d) PORTC &= ~IO_PC6; else PORTC |= IO_PC6;

    if(servo_timer<200) servo_timer++; else servo_timer=0;


    Allerdings ist die Auflösung bei 100µs recht bescheiden (ca. 17 mögliche Servo-Positionen).

    Beim näheren darüber nach denken muss ich aber feststellen das 1µs wirklich etwas wenig sind, 10µs wären (mit dann ca. 170 möglichen Positionen) ja fast schon auf 1° genau. Also 10µs reichen!

  6. #6
    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, es geht um Servoimpulse, alles klar.

    Vielleicht wäre das eine Basis:
    Code:
    // Servoansteuerung mit 16Bit-Timer1 (mit arexx cat16)             mic 18.1.2011
    
    // Die 8 Servos werden an Port B und C angeschlossen:
    // Servo0 - PB0
    // Servo1 - PB1
    // Servo2 - PC2
    // Servo3 - PC3
    // Servo4 - PC4
    // Servo5 - PC5
    // Servo6 - PC6
    // Servo7 - PC7
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    volatile uint8_t count_20ms;
    volatile uint16_t servo[9] ={1700, 1700, 1700, 1700, 1700, 1700, 1111, 1111, 40000}; // Servopositionen
    
    void sleep(uint8_t pause);                    // 1/50 Sekunde blockierende Pause
    
    int main(void)
    {
    	cli();
    
    	// für 16MHz-ATMega16
    	TCCR1A = (0<<WGM11)|(0<<WGM10);       		// CTC-Mode 4
    	TCCR1B = (0<<WGM13)|(1<<WGM12);
    	TCCR1B |= (0<<CS12)|(1<<CS11)|(0<<CS10);	// prescaler /8
    	TIMSK = (1<<OCIE1A);                      // MatchCompare-Interrupt erlauben
    
    	DDRB = 0b00000011;                        // Datenrichtung Servoausgänge setzen
    	DDRC = 0b11111100;
    
    	sei();
    	sleep(100);
    
    	while(1)                                  // Demo
    	{
    		cli();
    		servo[0]=2500;
    		servo[1]=servo[2]=1600;
    		sei();
    		sleep(50);
    
    		cli();
    		servo[0]=servo[1]=servo[2]=1700;
    		sei();
    		sleep(50);
    	}
    	return(0);
    }
    
    ISR(TIMER1_COMPA_vect)
    {
    	static uint8_t nr=8;                      // Nummer des aktuellen Servos
    
    	PORTB &= ~0b00000011;                     // alle Servoimpulse low
    	PORTC &= ~0b11111100;
    
    	if(nr < 3)                                // Impuls für Servo oder Pause? (8 Servos)
    	{
    		if(nr<2) PORTB |= (1<<nr);             // Impulsleitung des aktuellen Servos
    			else PORTC |= (1<<nr);              // auf High setzen und
    		OCR1A = servo[nr];                     // Impulslänge in OCR1A laden
    		servo[8] -= servo[nr];                 // Impulslänge von der Pause abziehen
    		nr++;                                  // nächstes Servo
    	}
    	else
    	{
    		OCR1A = servo[8];                      // servo[8] ist die Impulspause
    		servo[8] = 40000;                      // Startwert 20ms laden
    		nr = 0;             							// beim nächsten ISR-Aufruf Impuls
    															// für Servo 0 erzeugen
    		if(count_20ms) count_20ms--;           // blockierende Pause aktiv?
    	}
    }
    void sleep(uint8_t pause)                    // 1/50 Sekunde blockierende Pause
    {
       count_20ms=pause+1;
       while(count_20ms);
    }
    (Aus https://www.roboternetz.de/community...l=1#post522751)

    Das Programm wurde für einen 16MHz-Mega16 geschrieben, sollte aber auch auf dem Mega32 laufen. Der Timer1 läuft im CTC-Mode mit Prescaler/8 von 0 bis 40000 in 20ms. Während eines Zyklus werden nacheinander jeweils die Impulse für bis zu 8 Servos erzeugt. Die Servopositionen sind in servo[0] bis servo[7] gespeichert, 2000 sind eine Millisekunde (0,001s). In servo[8] ist der Wert für das Zyklusende gespeichert, ein kleinerer Wert (muss aber größer als die Summe der Servos sein, z.B TCNT1+=10) erhöht die Wiederholfrequenz. Mit if(nr < 3) kann man die Anzahl der verwendeten Servos ändern.

    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!

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    03.01.2012
    Ort
    Großefehn LK Aurich, Ostfriesland)
    Alter
    43
    Beiträge
    17
    Wird denn in dem Beispiel der Timer1 (ISR(TIMER1_COMPA_vect)) alle 10µs ausgeführt? Und was muss ich wie ändern um das auf dem Mega32 mit 10µs auszuführen?

  8. #8
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Warum bestehst du nun auf den 10µs? Diese Variante ruft die ISR in einem 20ms-Zyklus genau Servos+1 mal auf. Viel Resourcenschonender gehts nimmer und das auch noch quasi fertig zur Verwendung. Du brauchst nur noch die Pins eintragen:

    Code:
    // Servoansteuerung mit 16Bit-Timer1                                          mic 10.1.2012
    
    // Drei Servos an PD6,PC4 und PC6
    // https://www.roboternetz.de/community/threads/56242-Problem-beim-Konfigurieren-von-TIMER1-beim-M32-Board
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    volatile uint8_t count_20ms;
    volatile uint16_t servo[9] ={1700, 1700, 1700, 1700, 1700, 1700, 1111, 1111, 40000}; // Servopositionen
    
    void sleep(uint8_t pause);                    // 1/50 Sekunde blockierende Pause
    
    int main(void)
    {
    	cli();
    
    	// für 16MHz-ATMega16
    	TCCR1A = (0<<WGM11)|(0<<WGM10);       		// CTC-Mode 4
    	TCCR1B = (0<<WGM13)|(1<<WGM12);
    	TCCR1B |= (0<<CS12)|(1<<CS11)|(0<<CS10);	// prescaler /8
    	TIMSK = (1<<OCIE1A);                      // MatchCompare-Interrupt erlauben
    
    	//DDRB = 0b00000011;                        // Datenrichtung Servoausgänge setzen
    	//DDRC = 0b11111100;
    	DDRC |= (1<<PC6)|(1<<PC4);
    	DDRD |= (1<<PD6);
    
    	sei();
    	sleep(100);
    
    	while(1)                                  // Demo
    	{
    		cli();
    		servo[0]=2500;
    		servo[1]=servo[2]=1600;
    		sei();
    		sleep(50);
    
    		cli();
    		servo[0]=servo[1]=servo[2]=1700;
    		sei();
    		sleep(50);
    	}
    	return(0);
    }
    
    ISR(TIMER1_COMPA_vect)
    {
    	static uint8_t nr=8;                      // Nummer des aktuellen Servos
    
    	//PORTB &= ~0b00000011;                     // alle Servoimpulse low
    	//PORTC &= ~0b11111100;
    	PORTC &= ~((1<<PC6)|(1<<PC4));
    	PORTD &= ~(1<<PD6);
    
    	if(nr < 3)                                // Impuls für Servo oder Pause? (8 Servos)
    	{
    		//if(nr<2) PORTB |= (1<<nr);             // Impulsleitung des aktuellen Servos
    			//else PORTC |= (1<<nr);              // auf High setzen und
    		if(nr==0) PORTD |= (1<<PD6);
    		else if(nr==1) PORTC |= (1<<PC4);
    			else if(nr==2) PORTC |= (1<<PC6);
    		OCR1A = servo[nr];                     // Impulslänge in OCR1A laden
    		servo[8] -= servo[nr];                 // Impulslänge von der Pause abziehen
    		nr++;                                  // nächstes Servo
    	}
    	else
    	{
    		OCR1A = servo[8];                      // servo[8] ist die Impulspause
    		servo[8] = 40000;                      // Startwert 20ms laden
    		nr = 0;             							// beim nächsten ISR-Aufruf Impuls
    															// für Servo 0 erzeugen
    		if(count_20ms) count_20ms--;           // blockierende Pause aktiv?
    	}
    }
    void sleep(uint8_t pause)                    // 1/50 Sekunde blockierende Pause
    {
       count_20ms=pause+1;
       while(count_20ms);
    }
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    03.01.2012
    Ort
    Großefehn LK Aurich, Ostfriesland)
    Alter
    43
    Beiträge
    17
    Na ja, eigentlich wollte ich gerne meine eigene Methode verwenden, weil ich gerne möglichst viel von dem was da passiert verstehen möchte. Und das tut man am besten wenn man es sich selber erarbeitet hat.

    Ich habe das o.g. Beispiel mal kopiert und ausprobiert. Die Servos gehen beim Programmstart auf die fest eingestellten Positionen, aber wenn man in der Hauptschleife andere Werte einstellt, tut sich gar nichts.
    Geändert von dirty_bird_981 (11.01.2012 um 00:06 Uhr)

Ähnliche Themen

  1. Timer1 beim Attiny45
    Von Razer im Forum Assembler-Programmierung
    Antworten: 1
    Letzter Beitrag: 27.04.2007, 09:38
  2. Timer1 beim Mega128 initialisieren
    Von ceekay im Forum AVR Hardwarethemen
    Antworten: 1
    Letzter Beitrag: 08.08.2006, 20:52
  3. Problem mit Capture-Interrupt beim TIMER1 (IR-Empfaenger)
    Von Ulfens im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 20.03.2006, 12:46
  4. Ein neues Problem beim RN Board
    Von patti16 im Forum Schaltungen und Boards der Projektseite Mikrocontroller-Elektronik.de
    Antworten: 6
    Letzter Beitrag: 29.07.2005, 17:04
  5. Antworten: 9
    Letzter Beitrag: 14.03.2005, 21:08

Berechtigungen

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

LiFePO4 Speicher Test