Forum der Firma Krause Robotik

Normale Version: Einrichtung weiterer PWMs
Du siehst gerade eine vereinfachte Darstellung unserer Inhalte. Normale Ansicht mit richtiger Formatierung.
Hallo,

ich würde gerne mit dem Kr-Mega 32-16 zu den beiden, auf dem Board intergrierten, PWMs noch einige weitere erzeugen.

Ist es möglich die normalen digitalen Ausgänge dafür zu verwenden, oder sie so zu programmieren, dass sie als PWM arbeiten.

Wenn ja wie?

Grüße
Frederik
Hallo Frederik!

Ja, du kannst auch weitere Ports als PWM-Ausgänge nutzen.
Schnell genug sind dafür die Ports 1 bis 16.
17 bis 21 sind dafür zu langsam.

Zur Umsetzung:
Für eine PWM nutzt man einen Timer. Auf dem Atmel mit der von uns genutzten Bibliothek ist der der Timer 2 noch frei und kann dafür genutzt werden.

Man weist dem Timer2 eine Interruptroutine mit dem Befehl:

timerAttach(TIMER2OVERFLOW_INT, pwm_funktion ) zu.

dann muss die Routine dazu geschrieben werden. Diese könnte so aussehen.


int globales_i;
int gobaler_motorx;

void pwm_routine(void)
{
globales_i = globales_i + 1;
if (globales_i > 100) globales_i = 0;

if (globales_i < globaler_motorx) setDigitalOut(deinPWMPort);
else clearDigitalOut(deinPWMPort);
}


Die Variable globaler_motorx kannst du nun in jeder Funktion beliebig zwischen 0 und 100 setzen und bestimmst somit, mit wie viel Prozent der Leitung die PWM arbeiten soll. Weitere PWM-Ausgänge kannst du analog nutzen und in die gleiche Interruptroutine parallel einbauen. Dabei erhöhen sich nur die If-Abfragen. Für jede PWM eine. Und du brauchst natürlich für jede PWM eine weitere globale Variable zum vergleichen und über die du den Ausgang steuern kannst.

Ich hoffe, das hilft.

Grüße

Thomas
Hallo Thomas,

ich habe den, von dir vorgeschlagenen, Quelltext zur Einrichtung weiterer PWMs in den Compiler unter Verwendung der mitgelieferten Bibliothek eingegben, jedoch zeigt das Programm einen Fehler an.
Der GCC Compiler kann die Funktion

''timerAttach(TIMER2OVERFLOW_INT, pwm_funktion )''

nicht identifizieren und zeigt den Fehler

'' error 'pwm_funktion' undeclared'' an.

Ist es möglich das die Funktion einen Schreibfehler enthält oder liegt es an der Bibliothek, dass sie nicht erkannt wird?
Der andere Teil der PWM Routine hat zumindest schon mal funktioniert.

Grüße

Frederik
Hallo Frederik!

Die Fehlermeldung deutet darauf hin, dass dem Compiler die Funktion an der angegeben Stelle noch nicht bekannt ist. Ich vermute, du hast sie erst hinter dem Main Programm angeordnet.
Damit der Compiler das im Hauptprogramm bereits zuordnen kann, muss man am Anfang der Datei, hinter den includes die Prototypen der Funktionen definieren. DAs geschiet einfach so, dass der Funktionsaufruf oben noch einmal hingeschrieben wird. In deinem Fall sollte diese Zeile dann so aussehen:

void pwm_funktion(void);

Wichtig, das Semikolon nicht vergessen.
Dann sollte die Funktion auch schon im Hauptprogramm bekannt sein. Durch diesen Prototypen, kann der Compiler den benütigten Speicherplatz bereits reservieren und die Funktion somit festlegen. Weiter unten, wird dann festgelegt, was dort alles ausgeführt werden soll.

Grüße

Thomas
Hallo,

die selbst erzeuten PWMs funktionieren. Beim Anschluß an eine LED ließ sich die Helligkeit problemlos regeln.

Allerdings stieß ich noch auf ein Problem;
Als ich die PWM Funktion in ein Programm integrierte, in dessen Endlosschleife sich eine Wartefunktion befindet (nur von einigen Millisekunden) flimmerten die PWMs.
Auch bei längeren Programmen lief der selbst erzeugte PWM sehr langsam.

Zum Vergleich band ich die beiden ,,echten, schon vorhandenen PWMs'' auf dieselbe Weise in mein Programm ein und diese flimmerte nicht.

Ist es möglich, dass das Die Übertaktung der PWM-Routine da irgendwie außer Kraft gesetzt wurde?




#include "kr-mega32v23.h"
void PWMtest(void);
void pwm_funktion(void);

int m3;
int i;

int main(void)
{
timerAttach(TIMER2OVERFLOW_INT, pwm_funktion );
pwm_funktion();
timerInit();
motorInit();

while(1)
{
pwmfunktion();
m3=20;
motor(1,20);
timerPause(10);
}

return 0;
}

void pwm_funktion(void)
{
i = i + 1;
if (i > 100) i = 0;

if (i < m3) setDigitalOut(11);
else clearDigitalOut(11);
}

Befindet sich im Programm ein Fehler?

Grüße
Frederik
Hallo Frederik!

Ja, du hast da einen kleinen Denkfehler drin. Big Grin

Die Funktion pwm_funktion(void) wird zyklisch durch den Timer aufgerufen.
Das richtest du mit der Zeile:

timerAttach(TIMER2OVERFLOW_INT, pwm_funktion );

ein. Immer wenn der Timer 2 über läuft wird die Funktion aufgerufen. Das geschieht unabhängig vom Programm immer in gleichen Zeitabständen.
Damit ist die PWM eingerichtet. Das Licht ändert sich jetzt, je nach dem was in die Variable m3 eingetragen wird.

Jetzt hast du zusätzlich in deine While-Schleife den Funktionsaufruf pwm_funktion() eingebaut. Jetzt tritt das Problem auf, dass du diese Funktion, einmal aus deinem Hauptprogramm aus aufrufst und aus dem Timerinterrupt heraus. Und genau das erzeugt dir das Flimmern. Denn jetzt sind die Zeitabstände nicht mehr gleich sondern überlagern sich.
Nimm den Funktionsaufruf in deiner While-Schleife heraus. Dann sollte das wieder bestens funktionieren.

Grüße

Thomas
Referenz-URLs