Hallo Mikrocontroller-Mitglieder,
ich möchte ein Code schreiben, mit dem man das Tastverhältnis einer PWM
laufend ändert. Dafür habe ich zwei if-Anweisungen geschrieben, jedoch
wird das Tastverhältnis nicht geregelt. Wenn ich nach dem Debugen,
schrittweise die Anweisungen durchklickte, wird zwar die Variable
CCR2_Value erhöht, das lässt sich aber nicht bemerkbar machen. Ich messe
am Oszilloskop das PWM Signal laufend, dieser rennt aber mit dem im Main
fix eingestellten Tastverhältnis. Hat einer von euch Tipps bzw.
Anregungen? Jeder Hinweis ist brauchbar.
Danke und LG
Michael
#include <stm8s.h>
#include <stm8s_eval_lcd.h>
#include <stdio.h>
uint8_t StrName[16]={0};
uint16_t Conversion_Value = 0;
float Stufe = 0.00488;
float Nominal_Min = 3.500;
float Nominal_Max = 4.500;
float Conversion_Value_Current = 0;
uint16_t CCR2_Val = 27 ;
// Parametrisierung des PI Reglers !!!! MUSS NOCH IN MATLAB BESTIMMT
WERDEN !!!! //
float kp = 0.001;
float tn = 0.04;
int main(void){
// Systemtakt
CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);
// Erzeuge PWM
TIM3_DeInit();
TIM3_TimeBaseInit(TIM3_PRESCALER_1, 45);
TIM3_OC2Init(TIM3_OCMODE_PWM1, TIM3_OUTPUTSTATE_ENABLE,CCR2_Val,
TIM3_OCPOLARITY_HIGH);
TIM3_ARRPreloadConfig(ENABLE);
TIM3_OC2PreloadConfig(ENABLE);
TIM3_Cmd(ENABLE);
// Initialisiere ADC und LCD
STM8S_EVAL_LCD_Init();
GPIO_DeInit(GPIOB);
ADC2_DeInit();
GPIO_Init(GPIOB, GPIO_PIN_2, GPIO_MODE_IN_PU_NO_IT);
ADC2_Init(ADC2_CONVERSIONMODE_CONTINUOUS, ADC2_CHANNEL_2,
ADC2_PRESSEL_FCPU_D4, ADC2_EXTTRIG_TIM, DISABLE , ADC2_ALIGN_RIGHT,
ADC2_SCHMITTTRIG_CHANNEL9, DISABLE);
ADC2_Cmd(ENABLE);
LCD_Clear();
LCD_BacklightCmd(ENABLE);
ADC2_StartConversion();
LCD_SetCursorPos(LCD_LINE1, 0);
LCD_Print("Convers.Value.:");
LCD_Print(" ");
while(1)
{
while(!ADC2_GetFlagStatus()){}
Conversion_Value = ADC2_GetConversionValue();
Conversion_Value_Current = Conversion_Value*Stufe;
//Regelung der Duty Cycle für einen erwünschten Ausgangsstrom
if(Conversion_Value_Current > Nominal_Max)
{
CCR2_Val--;
}
else if (Conversion_Value_Current < Nominal_Min)
{
CCR2_Val++;
}
TIM3_OC2Init(TIM3_OCMODE_PWM1, TIM3_OUTPUTSTATE_ENABLE,CCR2_Val,
TIM3_OCPOLARITY_HIGH);
sprintf((char*)StrName, "%.3f ", (Conversion_Value*Stufe));
LCD_SetCursorPos(LCD_LINE2, 0);
LCD_Print(StrName);
ADC2_ClearFlag();
}
}
Du musst, um den Fehler zu finden, etwas systematischer vor gehen als
"geht nicht, hiiiiilfeeeee".
Grenze den Fehler ein, analysieren warum sich der Tastgrad nicht ändert.
Was passiert wenn du den Comparewert manuell hoch und runter zählst,
ohne die if-Bedingung, ändert er sich dann? Was passiert wenn du den
Comparewert innerhalb der while(1) auf einen anderen Wert als den bei
der Initialisierung setzt? Wird er übernommen oder bleibt er auf dem
Wert bei Initialisierung?
Michael L. schrieb:> while(!ADC2_GetFlagStatus()){}
Kommt er dran hier überhaupt vorbei? Eine while(irgendwas) ohne ein
Timeout ist gefährlich...
Ingo Less schrieb:> Grenze den Fehler ein, analysieren warum sich der Tastgrad nicht ändert.> Was passiert wenn du den Comparewert manuell hoch und runter zählst,> ohne die if-Bedingung, ändert er sich dann? Was passiert wenn du den> Comparewert innerhalb der while(1) auf einen anderen Wert als den bei> der Initialisierung setzt? Wird er übernommen oder bleibt er auf dem> Wert bei Initialisierung?
Hallo Igno,
ja du hast recht, bin systematischer vorgegangen und folgendes entdeckt:
1. Wenn ich die if-Anweisung weglasse und in den CCR2_Value händisch
erneut definiere, wird dieser neuere Wert in übernommen und es stellt
sich der neue Tastgrad ein
2. Sobald ich aber die if-Anweisung wieder einfüge, und folgenden
Teil-Code verwende:
if(Conversion_Value_Current > Nominal_Max)
{
CCR2_Val = 10;
}
else if (Conversion_Value_Current < Nominal_Min)
{
CCR2_Val = 38;
}
TIM3_SetCompare2(CCR2_Val);
ändert sich der Tastgrad für den jeweiligen Fall.
Also wird mein Decrement bzw. Increment fehlerhaft sein oder? Was meinst
du?
Michael L. schrieb:> Was meinst du?
Das das hier
> TIM3_SetCompare2(CCR2_Val);
was Anderes ist als das hier
> TIM3_OC2Init(TIM3_OCMODE_PWM1, TIM3_OUTPUTSTATE_ENABLE,CCR2_Val,> TIM3_OCPOLARITY_HIGH);
Aber das hier ist wohl der Fehler:
1
if(Conversion_Value_Current>Nominal_Max)
2
{
3
CCR2_Val--;
4
}
5
elseif(Conversion_Value_Current<Nominal_Min)
6
{
7
8
CCR2_Val++;
9
10
}
ist ziemlicher Unsinn, grundsätzlich. Denn wenn CCR2_Val = 0 ist und du
einen abziehst, geht der Tastgrad von 0 auf 2^16-1 UND es erfolgt kein
Compare-Match mehr. Also, du musst deinen Tastgrad schon in den
zulässigen Grenzen bewegen und die nicht verlassen. Also nicht größer
als 45 werden... Also einen Limitter hinter die if, else if Abfrage.
Dann wirst du sehen, dass dein Tastgrad vermutlich auf 0 oder 100%
rast...
Hallo,
ich habe eine Frage bezüglich der PWM Erzeugung bei STM8. Ich brauche
ein 350kHz Signal, und möchte aber den Duty Cycle in 1% Schritten
erhöhen.
Laut dem Formel im ST Sheet, PWm_Freq = Timer_Freq/ARR + 1
Setzte ich als Timer_Freq 16MHz, ungeteilt vom Clock Frequenz
hergeleitet und hierbei komme ich auf ca. ARR = 45 um 353kHz zu kommen.
45 entspricht aber eine Auflösung von 2,2% Schrittweite, welches für
meine Anwendung nicht brauchbar ist.
Gibt es eine Möglichkeit, trotz dieser Tatsache eine feinere Auflösung
zu erreichen?
Hallo,
ich habe eine Frage bezüglich zwei unterschiedlichen
Versorgungsspannungen. Ich muss ein µC versorgen mit 5V, brauche aber
auch für die weitere Beschaltung 3,3V.
Muss ich dafür zwei LDOs nehmen oder kann ich am Ausgang des 5V LDOs
auch einen Spannungsteiler machen um die 3,3V zu bekommen.
Wären dann die 3,3V genauso stabil wie die 5V am LDO ausgang?
LG
Jürgen schrieb:> Muss ich dafür zwei LDOs nehmen oder kann ich am Ausgang des 5V LDOs> auch einen Spannungsteiler machen um die 3,3V zu bekommen.
Schlechte Lösung, sehr schlecht. Der Strom ist nicht konstant und du
brauchst daher eine Regelung.