Hilfe Servos Ansteuerung mit PWM Timer und Eingabe durch einen Joystick.



  • Hallo zusammen,

    programmiere gerade eine Lenkung mit einem Joystick und Servo, doch ich bekomme keinen PWM Signal an dem gewünschtem Pin, ich wollte die CTC mode (Clear Timer on Compare Match) verwenden mit dem 16 - bit Timer 1 da ich da die gewünschten 25 ms Perioden Dauer einstellen kann.
    Hoffe die Fehlerbeschreibung ist ausführloch genug.
    Ich Programmiere mit einem Arduino Atmega328p in atmelStudio.
    Bin zum erstem mal auf so einem Forum und hoffe es ist richtig formatiert.
    Hier noch den Code den ich geschrieben habe:

    /*
     * Servo.c
     *
     * Created: 05.10.2020 12:51:00
     * Author : zechn
     */ 
    #define F_CPU 16000000
    #include <avr/io.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    
    
    
    volatile int joyx=0;	//globale Variablen
    volatile int joyy=0;
    
    void ADC_Init(void)
    {
      // die Versorgungsspannung AVcc als Referenz wählen:
    	ADMUX = (1<<REFS0);    
      // oder interne Referenzspannung als Referenz für den ADC wählen:
      //ADMUX = (1<<REFS1) | (1<<REFS0);
    
      // Bit ADFR ("free running") in ADCSRA steht beim Einschalten
      // schon auf 0, also single conversion
      ADCSRA = (1<<ADPS1) | (1<<ADPS0);     // Frequenzvorteiler
      ADCSRA |= (1<<ADEN);                  // ADC aktivieren
    
      /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
         also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
    
      ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung 
      while (ADCSRA & (1<<ADSC) ) {         // auf Abschluss der Konvertierung warten
      }
      /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
         Wandlung nicht übernommen. */
      (void) ADCW;
    }
    
    /* ADC Einzelmessung */
    uint16_t ADC_Read( uint8_t channel )
    {
      // Kanal waehlen, ohne andere Bits zu beeinflußen
      ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
      ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
      while (ADCSRA & (1<<ADSC) ) {   // auf Abschluss der Konvertierung warten
      }
      return ADCW;                    // ADC auslesen und zurückgeben
    }
    
    //Impuls sarten
    ISR (TIMER1_COMPA_vect)
    {
    	PORTB |= (1<<2);
    }
    
    // impuls beenden
    ISR (TIMER1_COMPB_vect)
    {
    	PORTB = (1<<PB1);
    }
    
    int main(void)
    {
    	ADC_Init();
    	DDRD |= (1<<0) |(1<<6);
    	DDRB |= (1<<PB1) | (1<<PB2);
    	
    	TCCR1B |= (1<<CS10)|(1<<CS12);
    	TCCR1A |= (1<<COM1A1) | (1<<WGM11);
    	TCCR1B |= (1<<WGM13) | (1<<CS10)|(1<<CS12);		//OCR0A und B initalisieren so wie den Timer der die Takt Flanke heraufzählt auf 25ms
    	TIMSK1 |= (1<<OCIE1A) | (1<<TOIE1);
    	OCR1A = 50000;			
    	OCR1B = 1000;			// Servo Postion festlegen
    	//TCNT1 = 5000; 
    	
    	sei();
        while (1) 
       {
    		joyx = ADC_Read(0);
    		if ( joyx<500 )
    		{ 
    			PORTD |= (1<<0); //nur zur kontrolle da 
    			 OCR1B++;
    			_delay_ms(1);			
    		}
    		if ( joyx>600)
    		{
    			 OCR1B--;
    			_delay_ms(1);
    		}
       }
    }
    

  • Mod

    Bearbeite deinen Beitrag noch einmal und setze ``` (3 Backticks) in die Zeile vor und die Zeile nach deinem Code, dann kann man ihn auch lesen.

    "Funktioniert nicht" ist eine denkbar schlechte Problembeschreibung oder Frage, insofern als das es keine Problembeschreibung oder Frage ist. Niemand wird sich so langen Code durchlesen, wenn man vorher nicht einmal weiß, ob du nur meinst, ein Semikolon vergessen zu haben, oder ob du Hilfe mit den magischen Werten deiner Hardware brauchst.


  • Mod

    Ich pushe diesen Thread mal, da du ihn überarbeitet hast, und sich jetzt vielleicht jemand finden kann, der die Frage beantworten kann.