PWM Pin umschalten

Gast #3992252
Lesenswert?

Ich möchte gernen einen PWM zwischen zwei Ausgängen schalten.

Wie gehe ich da am besten vor? Ich nutzte einen Attiny841.

1
int main(void)
2
{
3
  DDRA |= (1<<PORTA3); // Ausgang 1
4
  DDRA |= (1<<PORTA4); // Ausgang 2
5
  
6
  TCCR1A |= (1<<COM1B1) | (1<<WGM10);
7
  TCCR1B |= (1<<WGM12);
8
  TCCR1B |= (0<<CS12) | (1<<CS11) | (1 <<CS10);
9
  TOCPMSA0 |= (1<<TOCC2S0);
10
  TOCPMSA0 |= (1<<TOCC2S1); // ? richtig fuer Ausgang 2
11
  TOCPMCOE |= (1<<TOCC2OE);
12

13
  while(1)
14
  {
15
    if(a == 0 && start) /*Ausgang 1 aktiv, Ausgang 2 = 0*/;
16
    else if(a == 1 && start) /*Ausgang 2 aktiv, Ausgang 1 = 0*/; 
17
    else /*Beide Ausgänge = 0*/;
18
  }
19
}
Gast #3992309
Lesenswert?

Hab noch einmal ein bisschen angepasst,
1
  DDRA |= (1<<PORTA3); 
2
  DDRA |= (1<<PORTA4);
3
  
4
  TCCR1A |= (1<<COM1B1) | (1<<WGM10);
5
  TCCR1B |= (1<<WGM12) | (0<<WGM11) | (1<<WGM10);    // Fast PWM, 8-bit
6
  TCCR1B |= (0<<CS12) | (1<<CS11) | (1 <<CS10);  // Prescaler clk/64
7
  
8
  TOCPMSA0 |= (1<<TOCC2S0); // 01 OC1B
9
  TOCPMSA0 |= (1<<TOCC3S0); // 01 OC1A
10
  
11
  TOCPMCOE |= (1<<TOCC2OE); // Ausgang PORTA3 aktivieren
12
  TOCPMCOE |= (1<<TOCC3OE); // Ausgang PORTA4 aktivieren

Jedoch bekomme ich in die Zuweisung auf OC1A nicht hin. Die werden nicht 
übernommen.
Gast #3992321
Lesenswert?

Sepp schrieb:
> Jedoch bekomme ich in die Zuweisung auf OC1A nicht hin. Die werden nicht
> übernommen.

Vielleicht erklärst erstmal du mal klar und deutlich und ausführlich, 
was du eigentlich willst und was dadran jetzt nicht geht. Ich hab zB 
keine Lust aus deinem Code mir das zusammenzureimen.
Gast #3992767
Lesenswert?

Kai Mauer schrieb:
> horstrüdiger schrieb:
>> ....und was dadran jetzt nicht geht. Ich hab zB
>> keine Lust aus deinem Code mir das zusammenzureimen.
>
> Wenn Du das aus den Kommentaren nicht ersehen und aus der
> Fehlerbeschreibung nicht entnehmen kannst, ist auch nicht
> zu erwarten, daß ausgerechnet DU ihm eine Hilfe sein könntest.

Wenn dir alles klar ist, warum erläuterst DU es nicht für die, die 
wenigstens etwas verstehen wollen und nicht rumrätseln wollen.

Eine deutlich formuliertes Ziel, welche Auswirkungen zu beobachten sind 
und klare Fragen dazu sehe ich halt nicht. Ohne Vermutungen anstellen zu 
müssen oder wie spess53 herumzustochern wird es wohl nur sehr zäh 
weitergehen.
Gast #3994059
Lesenswert?

So,

habe das soweit gelöst. Stellt sich nur die Frage, ob es so richtig ist.
1
  DDRA |= (1<<DDRA3);
2
  DDRA |= (1<<DDRA4);
3
  
4
  TCCR1A |= (1<<COM0A1) | (1<<COM1B1) | (1<<WGM10);
5
  TCCR1B |= (1<<WGM12) | (0<<WGM11);    // Fast PWM, 8-bit
6
  TCCR1B |= (0<<CS12) | (1<<CS11) | (1 <<CS10);  // Prescaler clk/64
7
  
8
  TOCPMSA0 |= (1<<TOCC2S0) | (1<<TOCC3S0); //  OC1B | OC1A
9
  TOCPMCOE |= (1<<TOCC2OE) | (1<<TOCC3OE);

Wenn ich nun einen Wert in OC1A lade von 0, glimmt eine Led noch gaanz 
schwach. Ist das irgendwie zu beheben?

Ich lösche derzeit bei Wert 0 einfach die DDR zuweisung und setze sie 
wieder wenn Wert > 0 ist.
Gast #3994092
Lesenswert?

Ich hatte mich zu Beginn vielleicht etwas undeutlich ausgedrückt, was 
evtl. auch auf fehlendes KnowHow zurückzuführen ist.

Über die PWM steuere ich einen Motor-Treiber an. Nun dürfen beide PWMs 
nicht gleichzeitig laufen. Ansonsten kommt es dazu, dass der Motor 
anhält. Nun wollte ich eigentlich das so machen, dass der Wert für die 
Motorgeschwindigkeit über ein Register entsprechend gemapped wird. War 
hier aber nachhinein nicht nötig.

Ich nutzte das A und B Register eines Timers, was mir ausreicht. Das 
ganze funktioniert nun soweit.

Jedoch steht noch die Frage nach dem Deaktivieren der PWM aus. 
Desweiteren macht es was, wenn ich jedes mal den DDR setze bzw lösche? 
Gibt es da einen unteschied zu einer "last_" Variable, die dann in einer 
Anweisung abgefragt wird

Pseudocode
1
static int last_val = 0;
2
if(last_val != val)
3
{
4
if(!val) OCR1A = 0;
5
else OCR1A = val;
6

7
last_val = val;
8
}
#3994127
Lesenswert?

Kai Mauer schrieb:
> horstrüdiger schrieb:
>> ....und was dadran jetzt nicht geht. Ich hab zB
>> keine Lust aus deinem Code mir das zusammenzureimen.
>
> Wenn Du das aus den Kommentaren nicht ersehen und aus der
> Fehlerbeschreibung nicht entnehmen kannst, ist auch nicht
> zu erwarten, daß ausgerechnet DU ihm eine Hilfe sein könntest.

Da steht "keine Lust" und nicht "kann nicht".

Außerdem: Welche Fehlerbeschreibung? Das ist nicht dein Erst, oder?

Weder die spärliche Absichtserklärung noch die "Fehlerbeschreibung" sind 
Eindeutig. Die Quelltextkomentierung ist auch kaum Aussagekräftig. Der 
erste Schritt besteht immer darin das Problem eindeutig in klare und 
präzise Worte zu fassen. Dann kommt man oft selber drauf. Der Code ist 
kaum eine Hilfe da er nicht leistet was er soll.


Sepp schrieb:
> Ich möchte gernen einen PWM zwischen zwei Ausgängen schalten.

Und zwei Beiträge später kommt dann erst

Sepp schrieb:
> Jedoch bekomme ich in die Zuweisung auf OC1A nicht hin.


Das ist hier kein Hellseherforum in dem man erraten oder ausknobeln soll 
was genau gewollt ist.


Mit der letzen Beschreibung ist das etwas klarer. Ein Schaltplan wäre 
hilfreich. Was für ein Treiber soll das sein? Ich unterstelle mal das Du 
ein PWM-Signal erzeugen willst und dann mit "zwischen zwei Ausgägen 
schalten" meinst, daß du entscheiden können willst ob das ganze Signal 
komplett in einem Stück auf dem einen oder dem anderen Pin erscheint. 
Man kann das Signal auch anders aufteilen. Willst Du damit die 
Drehrichtung des Motors umkehren?
Gast #3994135
Lesenswert?

Hallo,

ja es geht um die Drehrichtungsumschaltung eines TI DRV88xx 
Motortreibers. Habe AIN1 und AIN2 zur Bestimmung der Drehrichtung. Beide 
Eingänge können mit PWM angetrieben werden. Eine einzelnen Pin für die 
Drehrichtung gibt es bei dem DRV8833 nicht.
1
void motor_ctrl(int8_t direction, uint8_t speed)
2
{
3
  if(direction)
4
  {
5
    DDRB &= ~(1<<DDRB2);
6
    
7
    if(speed >= PWM_MIN) DDRA |= (1<<DDRA3);
8
    else DDRA &= ~(1<<DDRA3);
9
    
10
    OCR1B = speed;
11
  }
12
  else
13
  {
14
    DDRA &= ~(1<<DDRA3);
15
    
16
    if(speed >= PWM_MIN) DDRB |= (1<<DDRB2);
17
    else DDRB &= ~(1<<DDRB2);
18
    
19
    OCR1A = speed;
20
  }
21
}
22

23
  DDRA |= (1<<DDRA3);  // Linkslauf
24
  DDRB |= (1<<DDRB2);  // Rechtslauf
25
  
26
  // Fast PWM 10-bit, nicht invertiert, Vorteiler 64
27
  TCCR1A |= /*(1<<COM0A1) |*/ (1<<COM1B1) | (1<<WGM11) | (1<<WGM10);
28
  TCCR1B |= (1<<WGM12) | (1<<CS12) | (0<<CS11) | (0 <<CS10); // ?? Prescaler > 64 geht nicht
29
  
30
  TOCPMSA0 |= (1<<TOCC2S0);  // PORTA3 OCI1B
31
  TOCPMSA1 |= (1<<TOCC7S0);  // PORTB2 OCI1A
32
  TOCPMCOE |= (1<<TOCC2OE) | (1<<TOCC7OE);
Gast #3994146
Lesenswert?

"// ?? Prescaler > 64 geht nicht"

Hatte da einen Fehler gemacht. Der Register wurden an einer anderen 
Stelle bereits betrieben. Jedoch vielleicht eine kleine Frage noch.

Normalerweise sollte man für Motor in Verbindung mit PWM ~10kHz fahren. 
Wenn ich den Prescaler auf 1024 setze, hört sich der MiniaturMotor wie 
nen Verbrennungsmotor an (tocker, tocker, tocker,).

F_CPU = 8MHz
F_PWM = F_CPU/1024 = 7,8kHz
#3994163
Lesenswert?

Weil Du da gerade den Takt des Counters mit der PWM-Frequenz 
verwechselst.

Der Counter zählt mit knapp 8 kHz von 0-255 bei 8 Bit (ein kompletter 
PWM-Zyklus). Das ergibt am Ende eine PWM-Frequenz von knapp über 30 Hz. 
Über die Nachkommastellen will ich da nicht steiten.

Dein Prescaler ist also viel zu hoch.

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