Forum: Mikrocontroller und Digitale Elektronik STM8 PWM Ändern


von Michael L. (Gast)


Lesenswert?

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

}

von Ingo Less (Gast)


Lesenswert?

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...

von Michael L. (Gast)


Lesenswert?

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?

von Ingo L. (corrtexx)


Lesenswert?

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
    else if (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...

von Robert (Gast)


Lesenswert?

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?

von Jürgen (Gast)


Lesenswert?

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

von so nicht (Gast)


Lesenswert?

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.

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.