Also als erstes habe ich das das langsamer drehen des Servos mit delay_ms ausprobiert mit erfolg.
Des weiteren hab ich das Programm nach den Tipps von Searcher angepasst.
Als nächstes habe ich jetzt mal versucht einen einen Timer für dieses delay_ms zu programmieren.
Wenn in die variable us_counter eine 1 geschrieben wird, soll das 1µs entsprechen (d.h. us_counter =1000 = 1000µs).
Kann das so funktionieren?
Eine Frage habe ich noch: Warum wird erst in der if-Abfrage (if (us_counter == 0)) der Wert von us_counter mit einem Wert beschrieben (us_counter = 1000; ) und nicht schon davor?
Code:
#define F_CPU 8000000UL
#include <avr/io.h>
#include <stdint.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "ADC.h"
ISR TIMER0_OVF_vect //interrupt für timer 0
{
if (us_counter > 0) //wenn us_counter größer als 0 ist, dann...
{
us_counter--; //us_counter-1
}
}
int main(void)
{
uint16_t Servo_soll = 512, Servo_ist;
volatile uint16_t us_counter;
ADC_Init(); //ADC initialisieren
//############################ TIMER1 Einstellen für PWM der Nachführung #######################################
ICR1 = 19999; // ICR1 = 19999 als TOP-Wert, hier werden die 20ms gebildet (8MHz / 8 * (1 + 19999)) = 50Hz
OCR1A = 1499; // OCR1A = 1499, Servomittelstellung, (8MHz / 8 * (1 + 1499)) = 666,6Hz = 1,5ms
TCCR1A = (1<<COM1A1) | (1<<WGM11); //clear OC1A on compare match, set at bottom (non-inverting)
TCCR1B = (1<<WGM12) | (1<<WGM13) | (1<<CS11); //WGM12,WGM13,WGM11 -> Mode14 -> Fast PWM, ICRn, set OCR1A at Bottom | prescaler = 8
DDRD = (1<<PIND5); //PORTD pin 5 auf ausgang
//############################ TIMER0 Einstellen für Millisekunden #######################################
OCR0A = 3; //OCR0A = 3 als TOP-Wert festlegen
TCCR0A = (1<<WGM01) | (1<<WGM00); //Topwert = 3, CTC-Modus,bei overflow den Timer0 auf 0 setzen
TCCR0B = (1<<CS00); //prescaler = 1 -> (8MHz/(2*1*(1+3))=1MHz = 1µs
TCNT0 = 0;
TIMSK0 = (1<<TOIE0); //interrupts freischalten
_delay_ms(2000); // kurz warten bis der Servo sich ausgerichtet hat
while(1)
{
//########################################### Nachführung des Panels #######################################
if (us_counter == 0)
{
us_counter = 1000;
//_delay_ms(1); //der Motor brauch 2s um sich um 180° zu drehen -> (2000 schritte und je schritt 1ms)
Servo_ist = ADC_Read(1); //ADC kanal 1 auslesen und in die variable adcwert_1_LDRs speichern
if (Servo_ist != Servo_soll) //Wenn der ADC-Wert der LDRs nicht mit dem Servo_soll Wert von 512 überein stimmt, dann...
{
if (Servo_ist < Servo_soll && OCR1A > 600) //Wenn der ADC-Wert kleiner ist als 512 und 0,6ms noch nicht erreicht sind...
{
OCR1A = OCR1A--; //verringere OCR1A um 1
}
if (Servo_ist > Servo_soll && OCR1A < 2600) //Wenn der ADC-Wert größer ist als 512 und 2,6ms noch nicht erreicht sind...
{
OCR1A = OCR1A++; //erhöhe OCR1A um 1
}
}
}
}
}
Gruß
Technik_Amateur
Lesezeichen