- fchao-Sinus-Wechselrichter AliExpress         
Ergebnis 1 bis 10 von 14

Thema: ATtiny2313 ISR wirft mein Timing durcheinander

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    23.07.2011
    Beiträge
    16
    Ich habs jetzt doch nochmal mit dem Timer versucht, aber zusätzlich einen Servo angeschlossen; dadurch sieht man noch genauer wann das delay wie oft übersprungen wird. Und zwar läuft das so ab, dass der Servo (Hauptschleife) ca. 25 Schritte korrekt macht, also mit 500ms dazwischen und die nächsten zehn dann mit geschätzten 50ms delay. Komischerweise hab ich das Problem auch in diesem Fall nicht mehr, wenn ich Batterien anstatt der USB-Stromversorgung nehme. (Und wenn man dem Servo eigene Batterien gibt, flackert nichtmal irgentwas).

    Code:
    #define F_CPU 1000000UL
    
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>
    
    volatile  uint8_t OCR0Adirection=0, OCR0Avalue=1;
                             //0->OCR0A raufzählen 1-> OCR0A runterzählen
    
            ISR(TIMER0_COMPA_vect){
    
                    if(OCR0Adirection==0){
                            OCR0Avalue += 1;
                            if(OCR0Avalue==254) OCR0Adirection=1;
                    }else
                    {
                            OCR0Avalue -= 1;
                            if(OCR0Avalue==1) OCR0Adirection=0;
                    }
                    OCR0A = OCR0Avalue;
            }
    
    
    int main (void)
    {               
                    TCCR0A = (1 << COM0A1) | (1 << COM0A0) | (1 << WGM00) | (1 << WGM01)
                                                            | (1 << COM0B1) | (1 << COM0B0);//OC0B für den servo              
    
                                    //TCCR0B = (1 << CS00);//no Prescaler
                    //TCCR0B = (1 << CS01);//Prescaler CPU/8
                                    TCCR0B = (1 << CS00) | (1 << CS01);//Prescaler CPU/64
                                    //TCCR0B = (1 << CS02);//Prescaler CPU/256
                                    //TCCR0B = (1 << CS00) | (1 << CS02);//Prescaler CPU/1024
    
                    OCR0A = 1; //Startwert, pendelt dann zwischen 0..255
    
                    DDRB = (1 << PB2); //pin PB2 auf Ausgang (das ist OC0A)
                                   
                                    //blinkende led PB4, PD5, PA0
                     DDRD |= (1 << PD5);
                                    DDRB |= (1 << PB4);
                                    DDRA |= (1 << PA0);
    
                                    //ISRs für OCR0A Compare Match
                                    TIMSK = (1 << OCIE0A);
                                     
                                    sei();
    
                                    uint8_t i=215;
                                    //servoausschlag liegt bei 8bit-Timer, Prescaler von 64 und Fast-PWM
                                    //bei 215: -90°    245: +90°
                    while(1){
                                   
                                            for(;i<245;i++){
                                                    OCR0B=i;
                                                    _delay_ms(500);
                                            }
                                            for(;i>=215;i--){
                                                    OCR0B=i;
                                                    _delay_ms(500);
                                            }
                          
                    }
    }

  2. #2
    Neuer Benutzer Öfters hier
    Registriert seit
    23.07.2011
    Beiträge
    16
    Nochmal eine andere Frage: Um Strom zu sparen und da der Servo nicht permanent mit Kraft die Stellung halten muss, wollte ich den jetzt ohne Timer versorgen. Und zwar über eine ganz einfache Funktion, die in einer Schleife 30 mal erst für 1-2ms ein High am Port ausgibt, gefolgt von 15ms Low. (Die Länge des High-Zustandes bestimmt die Position und da sich der Servo scheinbar nur in den kurzen 15ms lang bewegt und in der Zeit keine 180° schafft, mach ich es 30 mal).
    Meine Frage bezieht sich auf den Typ der Zählvariablen in der Schleife für die 1-2ms Wartezeit.
    Um RAM zu sparen wollte ich nämlich eine 8bit statt einer 16bit Variablen benutzen, aber leider funktioniert das nicht.

    Code:
    #define F_CPU 1000000UL
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h> 
    
    volatile  uint8_t OCR0Adirection=0, OCR0Avalue=1; 
    			 //0->OCR0A raufzählen 1-> OCR0A runterzählen
    
    	ISR(TIMER0_COMPA_vect){
    
    		if(OCR0Adirection==0){
    			OCR0Avalue += 1;
    			if(OCR0Avalue==254) OCR0Adirection=1;
    		}else
    		{
    			OCR0Avalue -= 1;
    			if(OCR0Avalue==1) OCR0Adirection=0;
    		}
    		OCR0A = OCR0Avalue; 
    	}
    
    
    void moveServo(uint8_t time){
    	cli();
    	PORTB |= (1<<PB4);//Servo Stromversorgung an
    
    	uint8_t i=0;
    	uint16_t j=0; //<-----Diese Stelle ist gemeint----->
    
    	for(;i<50;i++){//es wird ein paar mal der folgende drehbefehl durchgegeben
    
    		PORTD |= (1<<PD5);//servo-takt-pin an
    		for(j=0;j<time;j++){//eine ganz bestimmte zeit lang an lassen (1-2ms)
    			_delay_us(1);}
    
    		PORTD &= ~(1<<PD5);//dann wieder aus
    		_delay_ms(15);//und bis zum nächsten warten (10-20ms)
    	}
    
    	PORTB &= ~(1<<PB4);//Servo Stromversorgung aus
    	sei();
    }
    
    int main (void)
    {
            
                   
                    TCCR0A = (1 << COM0A1) | (1 << COM0A0) | (1 << WGM00) | (1 << WGM01);
                    
    
    				//TCCR0B = (1 << CS00);//no Prescaler
                    //TCCR0B = (1 << CS01);//Prescaler CPU/8 
    				TCCR0B = (1 << CS00) | (1 << CS01);//Prescaler CPU/64 
    				//TCCR0B = (1 << CS02);//Prescaler CPU/256
    				//TCCR0B = (1 << CS00) | (1 << CS02);//Prescaler CPU/1024
    
                    OCR0A = 1; //Startwert, pendelt dann zwischen 0..255
    
                    DDRB = (1 << PB2); //pin PB2 auf Ausgang (das ist OC0A)
    				
    				//blinkende led PB4, PD5, PA0
    				DDRB |= (1 << PB4);//Strom für Servo
                   	DDRD |= (1 << PD5);//OC0B (Servo)
    				DDRA |= (1 << PA0);
    
    				//ISRs für OCR0A Compare Match 
    				TIMSK = (1 << OCIE0A);
    			   	
    				sei();
    
    				uint8_t i;
    				
                    while(1){
    					
    					if(OCR0Avalue==20)
    					{	i=70;
    						moveServo(i);
    					}
    					if(OCR0Avalue==240)
    					{	i=170;
    						moveServo(i);
    					}
    					if(OCR0Avalue==128)
    					{	i=250;
    						moveServo(i);
    					}        
                    }
    }
    Die anderen, betroffenen Variablen (i in der main und time als Parameter) sind auch nur 8bit groß.
    D.h. wenn ich die Zählvariable j auch nur 8bit groß mache, müsste es doch alles glatt laufen (einen Überlauf kanns nicht geben). Aber trotzdem scheint die Schleife mit (uint8_t j schon ganz früh abzubrechen, denn der Servo dreht sich bis zum Anschlag in die Richtung der kurzen Impulsdauern. Mit uint16_t j; gehts komischerweise.

Ähnliche Themen

  1. Atmega8 identify wirft wechselnde id
    Von apohero im Forum AVR Hardwarethemen
    Antworten: 8
    Letzter Beitrag: 20.03.2008, 13:16
  2. AVR controller.. bin durcheinander
    Von Robin1508 im Forum AVR Hardwarethemen
    Antworten: 19
    Letzter Beitrag: 11.11.2007, 20:35
  3. Antworten: 6
    Letzter Beitrag: 09.09.2006, 09:46
  4. Motor bringt Controller durcheinander
    Von scales im Forum Elektronik
    Antworten: 8
    Letzter Beitrag: 01.09.2006, 17:36
  5. RN-Control piept bei Programmablauf - kommt durcheinander
    Von robinhh im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 5
    Letzter Beitrag: 10.02.2006, 08:53

Berechtigungen

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

LiFePO4 Speicher Test