Forum: Mikrocontroller und Digitale Elektronik PWM Pin umschalten


von Sepp (Gast)


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
}

: Bearbeitet durch User
von Sepp (Gast)


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.

von horstrüdiger (Gast)


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.

von Kai M. (kai_mauer)


Lesenswert?

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.

von spess53 (Gast)


Lesenswert?

Hi

>  TCCR1B |= (1<<WGM12) | (0<<WGM11) | (1<<WGM10);    // Fast PWM, 8-bit

WGM11 und 10 befinden sich in TCCR1A

MfG Spess

von horstrüdiger (Gast)


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.

von Sepp (Gast)


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.

von ?!? (Gast)


Lesenswert?

Sepp schrieb:
> Ist das irgendwie zu beheben?

@Kai Mauer: Jetzt ist deine Hilfe gefragt. Du bist doch wohl der 
einzige, der
das kann (sagst du wenigstens).

Kai Mauer schrieb:
> Wenn Du das aus den Kommentaren nicht ersehen und aus der
> Fehlerbeschreibung nicht entnehmen kannst, ...

von Sepp (Gast)


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
}

von Carsten R. (kaffeetante)


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?

: Bearbeitet durch User
von Sepp (Gast)


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);

von Sepp (Gast)


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

von Carsten R. (kaffeetante)


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.

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.