PWM auf D9, D10 und D5, D6

Hallo,

kann mir jemand beim PWM etwas helfen?
Habe bislang nur mal ne LED gedimmt per analogWrite, brauche nun aber folgendes:

auf D10 ein PWM von 30Khz, auf D9 genau den gleichen PWM aber invertiert!
und
auf D6 ein PWM von 30Khz, auf D5 genau den gleichen PWM aber invertiert!

Die Frequenz habe ich auf D10/D9 hinbekommen, 30.30kHz (laut Logiktester)
D5/6 sind aber noch immer auf 970Hz.

was bedeutet diese Zeile?
TCCR2B = TCCR2B & 0b11111000 | 0x00;

Timer1.initialize(33);
Timer1.attachInterrupt(interupt_buck);

kann mir jemand erklären, wie ich invertierte Signale hinbekomme und wie man D5/6 auf 30KHz setzt?

Desweiteren, gibt es auch ne Möglichkeit, eine Totzeit zwischen abfallender Flanke von D10 und steigender Flanke von D9 zu programmieren?

Das ganze ist Teil von einem Versuchs-Buck-Boost-Wandlers.

Hallo,

naja, ohne den Zusammenhang zu kennen, wenn es ich um eine Initialisierung des Timers handelt, dann ist die Zeile etwas seltsam.

was bedeutet diese Zeile?
TCCR2B = TCCR2B & 0b11111000 | 0x00;

Im Zusammenhang mit einer Änderung kann das Sinn machen, wobei die Binärschreibweise nicht lesbar ist.

TCCR2B = TCCR2B & 0b11111000;

Die Veroderungen mit 0 dagegen nicht.

Alle 4 Pins mit 30kHz und einer invertiert sind sicherlich machbar. Für die Totzeit sehe ich noch keine Idee.

ich hab einen Teil hinbekommen...

void setup()
{
  pinMode(5, OUTPUT);
  digitalWrite(5, LOW);
  pinMode(6, OUTPUT);
  digitalWrite(6, LOW);
  pinMode(9, OUTPUT);
  digitalWrite(9, LOW);
  pinMode(10, OUTPUT);
  digitalWrite(10, LOW);

  bitSet (TCCR0B, CS20);
  bitClear (TCCR0B, CS21);
  bitClear (TCCR0B, CS22);
  bitClear (TCCR0A, COM0A0);
  bitSet (TCCR0A, COM0A1);
  bitSet (TCCR0A, COM0B0);
  bitSet (TCCR0A, COM0B1);
  bitSet (TCCR0A, WGM20);
  bitClear (TCCR0A, WGM21);
  bitClear (TCCR0B, WGM22);

  bitSet (TCCR1B, CS20);
  bitClear (TCCR1B, CS21);
  bitClear (TCCR1B, CS22);
  bitClear (TCCR1A, COM1A0);
  bitSet (TCCR1A, COM1A1);
  bitSet (TCCR1A, COM1B0);
  bitSet (TCCR1A, COM1B1);
  bitSet (TCCR1A, WGM20);
  bitClear (TCCR1A, WGM21);
  bitClear (TCCR1B, WGM22);
}

void loop()
{
  analogWrite(5, 8);
  analogWrite(6, 8);

  analogWrite(9, 128);
  analogWrite(10, 128);
}

aber wie kann ich eine Totzeit zwischen D9/10 und D5/6 hinbekommen?

Habe nun mit der DIO2 Library per digitalWrite das PWM mit deadtime hinbekommen! :slight_smile:

#include <arduino2.h>

const uint8_t Q18 = 5;
const uint8_t Q15 = 6;
const uint8_t Q16 = 9;
const uint8_t Q17 = 10;

int t = 10;  // µS
int dead = 1;  // µS

void setup()
{
  pinMode2(5, OUTPUT);
  digitalWrite2(5, LOW);
  pinMode2(6, OUTPUT);
  digitalWrite2(6, LOW);
  pinMode2(9, OUTPUT);
  digitalWrite2(9, LOW);
  pinMode2(10, OUTPUT);
  digitalWrite2(10, LOW);
}

void loop()
{
  digitalWrite2(Q18, HIGH);
  delayMicroseconds(t);
  digitalWrite2(Q18, LOW);
  delayMicroseconds(dead);
  digitalWrite2(Q15, HIGH);
  delayMicroseconds(t);
  digitalWrite2(Q15, LOW);
  delayMicroseconds(dead);
 
}

Der Vorteil gegenüber "normalen" PWM ist, es funktioniert auf jeden Pin!
Nachteile werden sich ergeben, wenn der 328 noch was anderes tun soll.
Aber so gehts erstmal!
Bei t = 10µS erhalte ich immer eine Taktfrequenz von 36KHz !

t muss nun abhängig vom analogeingang mehr oder weniger werden.

Hallo,

soll keine Vorschrift sein, jedoch schreibt man die Timersettings üblicherweise so. Ist einfach besser lesbar. Mal ein Bsp.

void set_Timer1()   //  CTC, Mode 4
{
  cli();         // Interrupts ausschalten
  TCCR1A = 0;    // Reset TCCR1A Register 
  TCCR1B = 0;    // Reset TCCR1B Register
  TIMSK1 = 0;    // Reset TIMSK1 Register (disable Timer Compare Interrupts)
  TCNT1  = 0;    // Timer Counter nullen
  OCR1A = 31999; // TOP Wert bestimmt mit Prescaler den Takt, 250Hz
  OCR1B = 23999; // 3/4 zeitlicher Versatz zum OC1A Output Pin, ebenfalls 250Hz
  TCCR1A = (1<<COM1A0)|(1<<COM1B0);  // Toggle Pin 11 und 12 aktviert
  TCCR1B = (1<<WGM12)|(1<<CS10);     // Mode 4 und Prescaler 1 
  sei();         // Interrupts einschalten
}  // end Funktion

Wenn du bei deinen einzelnen Bit Einstellungen durchblickts, dann ist gut, liest nur ungern jemand anderes. Zudem es leichter ist das gesamte Register zu nullen und dann nur die gewünschten Bits zu setzen.

Wegen den Pins. Du musst beim Timer nicht die zugehörigen Hardware Timer Pins verwenden. Du kannst auch eine der ISRs nutzen. Compare Match ISR zum Bsp. Darin kannste irgendeinen Pin toggeln lassen. Damit bist du auch unabhängig. Die Totzeit kann man dann garantiert in einer Abhängigkeit programmieren. analogWrite zu nutzen bringt dann aber nichts mehr. Weil 255 nicht mehr 100% entspricht. Du müsstest dich dann tiefer mit dem Timer an sich befassen.

danke für den Tip!
das lässt sich wirklich besser lesen!

Aber was hälst Du denn von der Methode, per FastDigitalWrite das zu realisieren?
Könnte man das auch in einem IRQ laufen lassen, so daß die Ausgabe immer gemacht wird und in der loop dann,
wenn Zeit ist, die AnalogEingänge gelesen werden?

Hallo,

alles was du in der loop machst, verändert die Frequenz deiner Pins. Das sollte dir bewußt sein. Da hilft auch kein FastDigitalWrite. Außer! die loop macht nur das, wirklich nur das alleine.

Das was du mit der IRQ ansprichst, meinte ich mit dem Timer ISR. Interrupt Service Routine vom Timer. Die läuft dann Timer präzise regelmäßig ab. Was du darin machst ist dann deiner Fantasie überlassen. Jeder Timer hat mehrere verschiedene ISRs die man nutzen kann.

Aufruf per attachInterrupt (boost) oder so?

was willste damit bewirken?

na meine Routine im IRQ laufen lassen!
Sorry, aber mit den Timern und IRQs hab ich mich nur auf dem alten 8Bit ATARI unter Assembler beschäftigt, auf nen µC noch nicht!

Hallo,

na schon in einem Interrupt, dass ist klar. Nur attachInterrupt ist für externe Eingangssignale gedacht. Die Pins können sich nicht selbst aufrufen. Geht nicht. Dafür ist der Timer angedacht, der sehr präzise seine Runden dreht und eine gewünschte Interrupt Service Routine aufruft. Wenn du das alles schon einmal gemacht hast, wirste da sehr schnell wieder Zugang finden. Das Prinzip ist gleich. Nur andere Namen für die Settings und ISRs. Das wird schon.

Nu klappt es auch mit den Timern inkl. Totzeit!

void buck()
{
  TCCR0A = 0b00000000;  // D5 / D6 aus
  TCCR0B = 0b11000000;  //

  TCCR1A = 0b10110001;  //PWM-Modus 1 D9 / D10 pwm
  TCCR1B = 0b11000001;  // 31KHz
  OCR1A=duty-dead;
  OCR1B=255-duty+dead;

  digitalWrite2(Q18, HIGH); // Q18 dauern einschalten
}
void boost()
{
  TCCR1A = 0b00000000;  // D9 / D10 aus
  TCCR1B = 0b11000000;  //

  TCCR0A = 0b10110001;  //PWM-Modus 1 D5 / D6  pwm
  TCCR0B = 0b11000001;  // 31KHz

  OCR0A=duty-dead;
  OCR0B=255-duty+dead;

  digitalWrite2(Q17, HIGH); // Q17 dauern einschalten
}

Die laufen im Mode 1, Phase Corrected PWM.

Selbst die Abfrage der DACs funktioniert nun!
Eine Abfrage in der Loop funktioniert nun auch, ohne die PWM zu stören!

Eben mit Spule und Last (100 Ohm) ausprobiert, klappt prima!
Und Spule und MOSFETs bleiben selbst bei 16W eiskalt! (haben noch keine Kühlkörper)

Das Biest macht bisjetzt genau das was es soll!

Hallo,

na siehste, geht doch. :slight_smile:

Das ganze ist Teil von einem Versuchs-Buck-Boost-Wandlers.

Würdest du uns auch den Schaltplan zeigen?

Klar

Layout ist nicht optimal, aber für die ersten Test gehts.

Schaltplan

Hier der ganze Artikel

Danke für Tips!

Danke für die Infos!
So wird mir einiges klarer, was du da überhaupt tust.

Bitte.

Die Timer kann man nicht irgendwie von extern mit Takt versorgen, oder?

mega-hz:
Bitte.

Die Timer kann man nicht irgendwie von extern mit Takt versorgen, oder?

Suche mal nach TOSC1 und TOSC2 im Datenblatt

Musst dann aber den Quarz/Resonator runter fummeln.

Hallo,

doch kann man. 328er .pdf Manual, ab Kapitel 19 gehts mit Timer 0 los. Timer 1 wäre Kapitel 20.
Extern takten lassen wäre am Pin T0 bzw. T1.

Ne combie, am Quarz muß man nicht rumfummeln. Der Timer wird nur einfach durch einen anderen Takt, extern weitergezählt. Das ist unabhängig vom eigentlichen µC Takt.

Edit:
aber wenn der TO in 2 Foren die gleichen Fragen stellt, dann bin ich raus.
https://www.mikrocontroller.net/topic/424491

  1. SPI – Serial Peripheral Interface

? ? ?