Arduino - PWM an zwei Ausgängen

OP #6160369
Lesenswert?

ich versuche nun seit zwei Tagen, jetzt hoffe ich hier Unterstützung zu 
bekommen:
ich benötige an zwei Ausgängen des Arduinos ein ~130Hz PWM-Signal, ich 
verwende in meinem Code D9 und D10. D10 gibt das Signal aus, wie 
gewünscht. D9 gibt nur ein HIGH aus, ohne PWM. hat jemand eine Idee was 
im Code fehlt oder falsch ist?

hier der Code:
1
int interruptNumber = 0;
2
int tasterPin = 2;
3
bool on = 1;
4

5
void setup() {
6
  Serial.begin(9600);
7
  DDRB = 0b00000110;
8
  TCCR1A = 0;
9
  TCCR1A = _BV(WGM10) | _BV(WGM11) | _BV(COM1A1) | _BV(COM1B1);     //Clear OC1A/OC1B on compare match, set OC1A/OC1B at BOTTOM, WGM10, WGM11(Fast-PWM)
10
  TCCR1B = 0;
11
  TCCR1B = _BV(CS12) | _BV(WGM12) | _BV(WGM13);   //CS12 - Prescaler 256; WMG12 & WGM13 für Fast-PWM
12
  OCR1A = 490;    //für benötigte Frequenz von 130Hz
13
  OCR1B = 100;   //duty-cycle
14
  pinMode(tasterPin, INPUT_PULLUP);
15
  attachInterrupt(interruptNumber, interruptfunction, FALLING);   //sollte PWM-Signal zwischen D9 und D10 hin und herschalten
16
}
17

18
void loop() {
19
 OCR1A = map(analogRead(A0), 0, 1023, 0, 490);   //Steuerung von duty-cycle
20
}
21

22
void interruptfunction() {
23
  if (on == 1) {
24
    TCCR1A = _BV(WGM10) | _BV(WGM11) | _BV(COM1A1) | _BV(COM1B1);
25
    on = 0;
26
  }
27
  else {
28
    TCCR1A = _BV(~WGM10) | _BV(~WGM11) | _BV(~COM1A1) | _BV(~COM1B1);
29
    on = 1;
30
  }
31
}
#6160428
Lesenswert?

Mike C. schrieb:
> TCCR1A = _BV(WGM10) | _BV(WGM11) | _BV(COM1A1) | _BV(COM1B1);
> //Clear OC1A/OC1B on compare match, set OC1A/OC1B at BOTTOM, WGM10,
> WGM11(Fast-PWM)

Das ist aber //Set OC1A/OC1B on compare match, clear OC1A/OC1B at
BOTTOM (inverting mode)

Mike C. schrieb:
> OCR1A = 490;    //für benötigte Frequenz von 130Hz

Wenn du OCR1A im Mode 15 ( Fast PWM, TOP = OCR1A, Update of OCR1x at 
BOTTOM) einsetz, dann definiert OCR1A deine Frequenz. Richtig.

Mike C. schrieb:
> OCR1A = map(analogRead(A0), 0, 1023, 0, 490);   //Steuerung von
> duty-cycle

Dann kannst du aber vergessen den DutyCycle damit festlegen zu wollen.
Du änderst hier die PWM-Frequenz, nicht den DutyCylce.

Außerdem änderst du praktisch die ganze Zeit die PWM Frequenz (in der 
Loop) und deshalb bleibt OC1A = D9 immer high, weil immer ein Compare 
Match für OCR1A auftritt.

Wenn du Fast PWM nutzen willst und auf D9 und D10 unterschiedliche DC 
ausgeben willst, musst du WGM Mode 14 mit dem ICR1 als Register für die 
Definition der Frequenz verwenden.
Gast #6160481
Lesenswert?

Im richtigen Modus setzt und löscht der Atmel für dich ganz alleine den 
Port Ausgang bei der verwendung von PWM. Dein Code ist also schonmal 
viel komplizierter, als er sein müsste. Ich empfehle mal folgende 2 
Links zu lesen und dabei das augenmerk auf FastPWM zu legen.

https://www.mikrocontroller.net/articles/AVR_PWM
https://www.mikrocontroller.net/articles/AVR-Tutorial:_PWM
OP #6160497
Lesenswert?

Timo N. schrieb:
> Wenn du Fast PWM nutzen willst und auf D9 und D10 unterschiedliche DC
> ausgeben willst, musst du WGM Mode 14 mit dem ICR1 als Register für die
> Definition der Frequenz verwenden.

Danke dir Timo, so funktioniert es natürlich, so ist es auch total 
logisch.

int interruptNumber = 0;
int tasterPin = 2;
bool on = 1;

void setup() {
  Serial.begin(9600);
  DDRB = 0b00000110;
  TCCR1A = 0;
  TCCR1A = _BV(WGM11) | _BV(COM1A1) | _BV(COM1B1);
  TCCR1B = 0;
  TCCR1B = _BV(CS12) | _BV(WGM12) | _BV(WGM13);
  ICR1 = 490;
  pinMode(tasterPin, INPUT_PULLUP);
  attachInterrupt(interruptNumber, interruptfunction, FALLING); 
//sollte PWM-Signal zwischen D9 und D10 hin und herschalten
}

void loop() {
  OCR1A = map(analogRead(A0), 0, 1023, 0, 490);   //Steuerung von 
duty-cycle
  OCR1B = OCR1A;
}

void interruptfunction() {
  if (on == 1) {
    TCCR1A = _BV(WGM11) | _BV(COM1A1) | _BV(COM1B1);
    on = 0;
  }
  else {
    TCCR1A = 0;
    on = 1;
  }
  Serial.println(TCCR1A, BIN);
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren