www.mino-elektronik.de/soft-pwm/pwm_software.htm
www.mikrocontroller.net/articles/Soft-PWM
Diese beiden Links vielleicht als Ansatz.
Hi @ll,
wie erstelle ich eine Soft-PWM?
Habe was gelesen über Timer... aber ich verstehe es nicht
Normales PWM habe/benutze ich schon an 2 PB0 und PB1 für 2 Servos.
Was ich suche, ist jetzt eine Soft-PWM für ansteuerung meines IC L293 D(2 Getriebemotoren).
Danke!
www.mino-elektronik.de/soft-pwm/pwm_software.htm
www.mikrocontroller.net/articles/Soft-PWM
Diese beiden Links vielleicht als Ansatz.
Hi,
habe mir mal die links angeschaut.
Zum 2 Link eine frage:
// PWM einstellen
PWM_DDR = 0xFF; // Port als Ausgang
// Timer 1 OCRA1, als variablem Timer nutzen
TCCR1B = 1; // Timer läuft mit vollem Systemtakt
TIMSK |= (1<<OCIE1A); // Interrupt freischalten
OCRA1 benutze ich doch schon, also klappt das damit nicht oder verstehe ich das jetzt falsch (man kann doch OCRA1 nur 1 mal benutzen)?
Du kannst jeden freien Timer benutzen.
Welche PWM-Frequenz möchtest du haben( bei den Servos ist es 50Hz), in wie vielen Stufen möchtest du die Geschwindigkeit einstellen.
Ich möchte nur 2 Stufen haben 100% und 50%.
Mehr soll die 2 Ausgänge nicht machen.
Dann lässt du den Timer laufen, der toggled bei jedem Überlauf ein Bit, damit hast du deine 50%.
Mh,
ich habe das leider nicht so genau verstanden
z.B. PWM_DDR = 0xFF; was für ein Ausgangpin an D ist das (Ich brauche z.B. PC4)?
Hier mal mein Code wie ich mir das vorstelle. Fehlt aber das mit 50% und 100%:
Code:#define F_CPU 8000000L // Systemtakt in Hz #define F_PWM 100 // PWM-Frequenz in Hz #define PWM_STEPS 256 // PWM-Schritte pro Zyklus(1..256) #define PWM_PORT PORTD // Port für PWM #define PWM_DDR DDRD // Datenrichtungsregister für PWM #define T_PWM (F_CPU/(F_PWM*PWM_STEPS)) // Systemtakte pro PWM-Takt #if (T_PWM<(152+5)) #error T_PWM zu klein, F_CPU muss vergrösst werden oder F_PWM oder PWM_STEPS verkleinert werden #endif #include <stdint.h> #include <string.h> #include <avr/io.h> #include <avr/interrupt.h> // globale Variablen volatile uint8_t pwm_setting[8]; // Timer 1 Output COMPARE A Interrupt ISR(TIMER1_COMPA_vect) { static uint8_t pwm_cnt=0; uint8_t tmp=0, i=0, j=1; OCR1A += (uint16_t)T_PWM; for (; i<8; i++) { if (pwm_setting[i] > pwm_cnt) tmp |= j; j<<=1; } PWM_PORT = tmp; // PWMs aktualisieren if (pwm_cnt==(uint8_t)(PWM_STEPS-1)) pwm_cnt=0; else pwm_cnt++; } int main(void) { // PWM einstellen PWM_DDR = 0xFF; // Port als Ausgang DDRD &= (~ (1<<PD2)|(1<<PD3)); /* Pin D2,D3,als Eingang */ PORTD |= (1<<PD2)|(1<<PD3); /* Pull Up von PIN D2,D3 aktivieren */ // Timer 1 OCRA1, als variablem Timer nutzen TCCR1B = 1; // Timer läuft mit vollem Systemtakt TIMSK |= (1<<OCIE1A); // Interrupt freischalten sei(); // Interrupts gloabl einschalten if (!( PIND & (1<<PIND2))) { /* mache was wenn PinD2 low ist */ // Hier: der Getriebemotor an L293D soll mit 100% laufen } if (!( PIND & (1<<PIND3))) { /* mache was wenn PinD3 low ist */ //Hier: der Getriebemotor an L293D soll mit 50% laufen } return 0; }
volatile uint8_t takt;
ISR(TIMER0_OVF_vect){
takt++;
}
int main(void) {
TCCR0=(1<<CS00); //kein Prescaler
TIMSK|=(1<<TOIE0); // Overflow Interrupt en
DDRD=(1<<PD3);// PortD3 wird Ausgang
if(takt>=10){ //Takt bis 10 zählen
PORTD^=(1<<PD3); //PortD3 toggelt 50% PWM
}
Code:Dieses Port-togglen kannst du natürlich weiter verknüpfen. Du machst am Ende deines Code ein return0, damit beginnst du aber wieder am Anfang bei main. Damit wird immer alles neu initialisiert. Ich mache nach den Einstellungen im main ein for(;;){ und hier kommt mein sich wiederholender Code hinein} ohne return0 am Ende. Der Compiler sollte da auch ein Warning ausgeben.
Cool @hubert:
Code im Zitatfenster und Text im Codefenster
Tja, kann auch mal passieren, sieht doch gut aus
Lesezeichen