Hallo liebes Forum,
Ich habe ein Verständnisproblem bezüglich der Timer (8 u. 16 bit).
Ich habe versucht ein PWM-Signal zu generieren, jedoch zeigt das oszi keins an.
Was ich erwartet habe: alle 20ms wird eine entsprechende Pulsbreite von den Timern erzeugt. 0,6ms bis 2,6ms sollte die range der Breite sein.
Die pulsbreite wird über LDRs realisiert, die einen Spannungsteiler bilden. So liegen am ADC1 werte von 0V bis 5V an. Wenn beide LDRs gleich stark beleuchtet sind, liegen ca. 2,5V am ADC1 an. Der Teil des Speicherns in eine Variable funktioniert soweit (0...1024 -> 2,5V = 512).
Ich habe es versucht mit einem Timer1 (16-Bit) zu realisieren aber ich bekomme es einfach nicht hin.
Ich benutze einen Atmega1284p-pu der mit dem internen Clock von 8Mhz arbeitet.
Hier mein Code:
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 (TIMER1_COMPA_vect) //Interrupt sub routine
{
OCR1A = 10000 - OCR1A; // hier werden die 20ms erzeugt die der servo benötigt
}
int main(void)
{
DDRD = (1<<PIND5); //Der Ausgang
ADC_Init(); //ADC initialisieren
double adcwert_1_LDRs; //speicherort für den ADCwert
TCCR1A = (1<<COM1A1) | (1<<COM1B1); //CTC Modus (Clear OC1A on compare match), set OC1A at bottom non-inverting
TCCR1B = (1<<WGM13) | (1<<CS11); //(1<<WGM12) vllt raus, (ICRn aktivieren), OCR1A auf direkt, TOV1 Flag auf MAX, prescaler=8
OCR1A = 799; //(8Mhz/(2*8*(1+799)))=625Hz=1,6ms Mittelstellung, (8Mhz/(2*8*(1+750)))=665,7Hz=1,5ms Mittelstellung,
TIMSK1 = (1<<OCIE1A);//(1<<TOIE1); //Timer-compare-Interrupt an
_delay_ms(2000);
while(1)
{
adcwert_1_LDRs = ADC_Read(1);
if (adcwert_1_LDRs <= 490 && OCR1A > 301) //servo dreht links bis max. 0,6ms
{ //(8MHz/(2*8*(1+9699)))=51,54Hz;20ms-0,6ms=19,4ms->1/19,4ms=51,54Hz->(8MHz/(2*8*51,54Hz))-1=9699->10000-9699=301!
//(8MHz/(2*8*(1+301)))=1655,6Hz=0,6ms
cli(); //interrupts global deaktivieren
OCR1A -= 5; //OCR1A so lange um 5 verringern, bis panel direkt zur sonne gerichtet ist
sei(); //interrupts globl aktiviren
_delay_ms(50); //50ms warten
}
if (adcwert_1_LDRs >= 530 && OCR1A < 1301) //servo dreht rechts
{
cli();
OCR1A += 5; //1301;
sei();
_delay_ms(50);
}
}
}
Ich hoffe Ihr könnt mir helfen.
Mit freundlichen Grüßen
Technik_Amateur
Lesezeichen