PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Mit Arduino 180° Phasenverschobenen Impuls erzeugen



alex91
14.11.2018, 16:00
Hallo!

Mit dem folgenden Code erzeuge ich mir einen Impuls am Pin 3 meines Arduino uno.
Ich möchte jatzt aber auch noch auf einem zweiten Pin einen um 180° phasenverschobenen Impuls erzeugen.
Kann mir da bitte jemand weiterhelfen?

// A sketch that creates an 250 kHz 6-bit resolution PWM with varying duty cycle

#include <avr/io.h>
#include <util/delay.h>

void setup()
{
pinMode(3, OUTPUT); // Output pin for OCR2B

// Set up the 250 kHz output
TCCR2A = bit(COM2A1) | bit(COM2B1) | bit(WGM21) | bit(WGM20);
TCCR2B = bit(WGM22) | bit(CS20);
OCR2A = 63;
OCR2B = 0;
}

void loop()
{

}



Viele Dank!

Moppi
14.11.2018, 17:20
Hallo alex91!

Es fehlt so was wie: digitalWrite(3,HIGH) / digitalWrite(3,LOW) (https://www.arduino.cc/reference/de/language/functions/digital-io/digitalwrite/)

90 Grad sind an der Spitze der Amplitude erreicht, 180 Grad, wenn die Schwingung die Null-Linie kreuzt, bevor sie in den negativen Bereich eintritt. Bei Digitalsignalen musst Du das äquivalent denken, nur mit einem Rechtecksignal.

33787


MfG
Moppi

PS: Irrtum vorbehalten

Searcher
14.11.2018, 18:15
Hallo!
Mit dem folgenden Code erzeuge ich mir einen Impuls am Pin 3 meines Arduino uno.
Ich möchte jatzt aber auch noch auf einem zweiten Pin einen um 180° phasenverschobenen Impuls erzeugen.
Kann mir da bitte jemand weiterhelfen?

// A sketch that creates an 250 kHz 6-bit resolution PWM with varying duty cycle

#include <avr/io.h>
#include <util/delay.h>

void setup()
{
pinMode(3, OUTPUT); // Output pin for OCR2B
pinMode(11, OUTPUT); // Output pin for OCR2A

// Set up the 250 kHz output
// TCCR2A = bit(COM2A1) | bit(COM2B1) | bit(WGM21) | bit(WGM20);
TCCR2A = bit(COM2A1) | bit(COM2A0) | bit(COM2B1) | bit(WGM21) | bit(WGM20); // invertierenden und non invertierenden mode für OC2A bzw OC2B
TCCR2B = bit(WGM22) | bit(CS20);
OCR2A = 63;
// OCR2B = 0;
OCR2B = 63; //compare match Wert für OC2B
}

void loop()
{

}



Hallo,
ich habe mal in Deinem Code etwas editiert. Rot soll raus und grün rein. Der ATMega328 kann mit den COM1Ax und COM2Bx Bits auf einen inverting mode und non-inverting mode im Fast PWM mode eingestellt werden.

Aus dem Datenblatt für OC2A. Das Gleiche gilt auch für OC2B:

Clear OC2A on Compare Match, set OC2A at BOTTOM, (non-inverting mode).
Set OC2A on Compare Match, clear OC2A at BOTTOM, (inverting mode)

Also OC2A auf Output schalten und die entsprechenden COM2xx Bits setzen und dann noch den Comparewert in OCR2A und OCR2B setzten. Es sollten jetzt zwei 180° phasenversetzte Signal an OC2A (Digitalpin 11) und OC2B (Digitalpin 3) vorhanden sein.

Fehler vorbehalten, da ich Arduino nicht, den Controller aber schon kenne.

Gruß
Searcher

Klebwax
14.11.2018, 19:18
Der ATMega328 kann mit den COM1Ax und COM2Bx Bits auf einen inverting mode und non-inverting mode im Fast PWM mode eingestellt werden.

Was aber genau genommen nur bei 50% Dutycycle einer Phasenverschiebung von 180° entspricht. Bei allen anderen Werten müsste man das Signal um 2µs (eine halbe Periode bei 250kHz) verschieben.

MfG Klebwax

Searcher
14.11.2018, 19:45
Was aber genau genommen nur bei 50% Dutycycle einer Phasenverschiebung von 180° entspricht. Bei allen anderen Werten müsste man das Signal um 2µs (eine halbe Periode bei 250kHz) verschieben.

Ja, ich hatte bei der Frage sofort ein invertiertes Signal im Kopf :( .

Gruß
Searcher

Klebwax
14.11.2018, 22:48
Ja, ich hatte bei der Frage sofort ein invertiertes Signal im Kopf

Mein erster Gedanke war, bei einem Puls gibt es keine Phase und damit auch keine Verschiebung. Von PWM ist erst später die Rede. Ich vermute mal, die 180° sind Quatsch und das invertierte Signal ist in Wirklichkeit gemeint.

MfG Klebwax

alex91
15.11.2018, 10:00
Hallo,
danke für die Antworten ich meine 180° Phasenverschiebung und nicht Invertierung.
Wollte es mit dem Phase-Correct PWM Mode machen aber leider geht das nicht so,
weil das Register mit dem ich die Frequenz einstelle das gleiche ist mit dem ich den einen Impuls machen möchte:
"Note that in this mode, only output B can be used for PWM; OCRA cannot be used both as the top value and the PWM compare value."
(http://www.righto.com/2009/07/secrets-of-arduino-pwm.html)

Dachte ich könnte vllt einfach einen Interrupt auslösen wenn ich die obere Grenze erreiche und einen Pin toggeln.
Ist zwar nicht optimal aber besser als beide pulse in Software zu erzeugen.

Leider funktioniert mein Programm nicht, da ich nicht in die isr rein komme.
kann mir jemand meinen Fehler sagen?


// A sketch that creates an 250 kHz 6-bit resolution PWM with varying duty cycle

#include <avr/io.h>
#include <util/delay.h>

void setup()
{
Serial.begin(115200);
pinMode(3, OUTPUT); // Output pin for OCR2B
pinMode(2, OUTPUT);

// Set up the 250 kHz output
TCCR2A = bit(COM2A1) | bit(COM2B1) | bit(WGM21) | bit(WGM20);
TCCR2B = bit(WGM22) | bit(CS20);
TIMSK2 |= (1 << OCIE2A); // enable timer compare interrupt
OCR2A = 63;
OCR2B = 0;
sei();//allow interrupts
}

ISR(Timer2_COMPA_vect) // timer compare interrupt service routine
{
PORTD |= 0x4;
PORTD &= ~0x4;
}

void loop()
{

}

Moppi
15.11.2018, 10:37
Vielleicht generiert man von einem PWM-Ausgang zwei Signale. Das erste Signal wird einfach weitergereicht und, für den zweiten Ausgang, in einer digitalen Stufe um eine gewisse Zeit verzögert (wegen der 180°) und kann dann dort abgegriffen werden. Man müsste das PWM-Signal an dem zweiten Ausgang des Atmega zeitversetzt starten - geht das überhaupt?

Vielleicht auch andere Aussagen dazu lesen: https://forum.arduino.cc/index.php?topic=224085.0

MfG

Moppi
15.11.2018, 19:04
Es gab mal ein ähnliches Problem.

Hier der Code:

const byte PWMUhv = 3; // Spannung für Treiber
const byte PWMUdesat = 11; // Spannung für Desat


void initTimer2PWM()
{
TCCR2B= _BV(CS21); //prescaler8=3,9KHz; CS22=0; CS21=1; CS20=0; Timer2
TCCR2A= _BV(WGM21) | _BV(WGM20) | _BV(COM2A1) | _BV(COM2B1)| _BV(COM2A0)| _BV(COM2B0);
OCR2B= 128; //Duty 50% für Pin 3
}

void setup()
{
pinMode(PWMUhv, OUTPUT); // PWMUhv als Ausgang deklariert
pinMode(PWMUdesat, OUTPUT); // PWMUdesat als Ausgang deklariert
initTimer2PWM();
}


int nacheilung = 0;
void loop()
{
OCR2A= 128 + nacheilung;
delay(200);
nacheilung++;
if(nacheilung>100) nacheilung = 0;
}


Und zwar von hier: https://forum.arduino.cc/index.php?PHPSESSID=166ggv1vlva7lfvkahec9mvg45&topic=366453.15

MfG
Moppi

Klebwax
15.11.2018, 20:52
Dachte ich könnte vllt einfach einen Interrupt auslösen wenn ich die obere Grenze erreiche und einen Pin toggeln.
Ist zwar nicht optimal aber besser als beide pulse in Software zu erzeugen.

Wenn die 250kHz von oben richtig sind, wirst du weder mit Soft-PWM noch mit einem Interrupt etwas reißen. Das ist alles viel zu langsam.

MfG Klebwax