Forum: Mikrocontroller und Digitale Elektronik Problem bei SingleShunt Strommessung


von Michael M. (eos400dman)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich versuche gerade einen BLDC-Regler mit feldorientierter Regelung und 
singleshunt Strommessung aufzubauen. Allerdings stellen mich die 
Messergebnisse nicht ganz zufrieden. Vielleicht hat ja jemand Erfahrung 
damit und kann mir dabei etwas helfen. Für die Strommessung verwende ich 
einen ACS709 Hall-Effekt-Stromsensor. Im Anhang mal ein Screenshot, wie 
die Ströme aktuell aussehen.

Die Ströme werden zweimal pro PWM-Periode gemessen und über das 
Kirchhoffsches Gesetz der jeweils fehlende dritte Strom berechnet. 
Anschließend werden die Ströme tiefpass gefiltert. Ich weiß nun nicht, 
ob der Fehler bereits in der Hardware liegt oder in meiner Software. Bei 
Bedarf poste ich gerne die restlichen Teile des Codes.
1
void strom_auswerten(void)
2
{
3
     ADC_Strom_1 -= ACS_ref + ACS_0_Strom_offset;
4
     ADC_Strom_2 -= ACS_ref + ACS_0_Strom_offset;
5
6
     ADC_Strom_1 = ADC_Strom_1 << 3;
7
     ADC_Strom_2 = ADC_Strom_2 << 3;
8
9
  Strom_3 = - ADC_Strom_1 + ADC_Strom_2;
10
  switch (sektor)
11
        {
12
    case 1:
13
    {
14
      I_V_raw = gleitender_mittelwert(I_V_raw, ADC_Strom_1, filter_gewichtung_strom);
15
          I_U_raw = gleitender_mittelwert(I_U_raw, - ADC_Strom_2, filter_gewichtung_strom);
16
          I_W_raw = - I_V_raw - I_U_raw;
17
          break;
18
        }
19
        case 2:
20
        {
21
          I_W_raw = gleitender_mittelwert(I_W_raw, ADC_Strom_1, filter_gewichtung_strom);
22
          I_U_raw = gleitender_mittelwert(I_U_raw, - ADC_Strom_2, filter_gewichtung_strom);
23
          I_V_raw = - I_W_raw - I_U_raw;
24
          break;
25
        }
26
        case 3:
27
        {
28
          I_W_raw = gleitender_mittelwert(I_W_raw, ADC_Strom_1, filter_gewichtung_strom);
29
          I_V_raw = gleitender_mittelwert(I_V_raw, - ADC_Strom_2, filter_gewichtung_strom);
30
          I_U_raw = - I_V_raw - I_W_raw;
31
          break;
32
        }
33
        case 4:
34
        {
35
          I_U_raw = gleitender_mittelwert(I_U_raw, ADC_Strom_1, filter_gewichtung_strom);
36
          I_V_raw = gleitender_mittelwert(I_V_raw, - ADC_Strom_2, filter_gewichtung_strom);
37
          I_W_raw = - I_V_raw - I_U_raw;
38
          break;
39
        }
40
        case 5:
41
        {
42
          I_U_raw = gleitender_mittelwert(I_U_raw, ADC_Strom_1, filter_gewichtung_strom);
43
          I_W_raw = gleitender_mittelwert(I_W_raw, - ADC_Strom_2, filter_gewichtung_strom);
44
          I_V_raw = - I_W_raw - I_U_raw;
45
                  break;
46
        }
47
        case 6:
48
        {
49
          I_V_raw = gleitender_mittelwert(I_V_raw, ADC_Strom_1, filter_gewichtung_strom);
50
          I_W_raw = gleitender_mittelwert(I_W_raw, - ADC_Strom_2, filter_gewichtung_strom);
51
          I_U_raw = - I_V_raw - I_W_raw;
52
          break;
53
        }
54
        default: break;
55
  }
56
}

Vielen Dank im Voraus!

Viele Grüße Michael

von Michael M. (eos400dman)


Angehängte Dateien:

Lesenswert?

Hallo,

kennt sich niemand damit aus?
Mittlerweile sehen meine Ströme so wie auf dem Bild aus, ist meiner 
Meinung nach schon mal etwas besser.

Viele Grüße Michael

von Fritz (Gast)


Lesenswert?

Michael Mayer schrieb:
> kennt sich niemand damit aus?

Mit deinen Vorgaben offensichtlich nicht!

Abgesehen davon, dass wahrscheinlich hier doch nicht jeder ohne Googeln 
weiß was ein BLCD-Regler ist, gibst du so gut wie gar nicht zu 
wesentlichen Details bekannt.
1.) Schaltung zeichnen, zumindest Prinzipschaltbild.
2.) Wie, womit (AD-Wandler) wird gemessen?
3.) Deine Diagramme sind ja ganz nett, aber ohne Bezug zur Realität 
sinnlos = Einheiten was gemessen wird fehlen sowohl x als auch y! Sowohl 
die Spannungen am Eingang der ADC's als auch die damit umgerechneten 
realen Strom- und Spannungswerte, sowie die Zeitachsen in s oder ms oder 
us oder in Abtastwerten, dann müßte man aber auch die Abtastfrequenz 
kennen.
4.) Bevor man sich die Details der Software anschaut, sollten alle 
obigen Punkte geklärt sein, sonst hat es nicht sehr viel Sinn sich in 
die Software zu vertiefen.

von Harald W. (wilhelms)


Lesenswert?

Fritz schrieb:

> Abgesehen davon, dass wahrscheinlich hier doch nicht jeder ohne Googeln
> weiß was ein BLCD-Regler ist,

Auch mit Googlen weiß ichs nicht, aber ich denke,du meinst einen BLDC!
:-)

von Pandur S. (jetztnicht)


Lesenswert?

Wenn jemand noch nichts von einem BLDC gehoert hat, kann er auch nicht 
antworten. Die Diagramme sind etwas schwer lesbar, koennen wie nicht 3 
einzelne Kurven haben. Auf den ersten Blick sind die Stroeme nicht 
symmetrisch.

Ein kleiner Programmfehler :

  ADC_Strom_1 -= ACS_ref + ACS_0_Strom_offset;
  ADC_Strom_2 -= ACS_ref + ACS_0_Strom_offset;

  ADC_Strom_1 = ADC_Strom_1 << 3;
  ADC_Strom_2 = ADC_Strom_2 << 3;

  Strom_3 = - ADC_Strom_1 + ADC_Strom_2;


die ersten zwei Zeilen sind identisch.

: Bearbeitet durch User
von Michael M. (eos400dman)


Angehängte Dateien:

Lesenswert?

Hallo,

zuerst mal vielen dank für die Antworten.

Harald Wilhelms schrieb:
> Auch mit Googlen weiß ichs nicht, aber ich denke,du meinst einen BLDC!
Oh ja. Sorry war ein Tipp-Fehler.

Fritz schrieb:
> 1.) Schaltung zeichnen, zumindest Prinzipschaltbild.

Schaltplan des betroffenen Teils ist im Anhang.

Fritz schrieb:
> 2.) Wie, womit (AD-Wandler) wird gemessen?

Mit dem ADC 2 des STM32F103, dieser wird zwei mal pro PWM Periode über 
einen Timer getriggert.

Fritz schrieb:
> Deine Diagramme sind ja ganz nett, aber ohne Bezug zur Realität

Stimmt sorry. So werden die im STMStudio nunmal dargestellt. Auf der 
X-Achse sind Abtastwerte des STMStudios (nicht des ADCs). Auf der 
Y-Achse ist der Strom dargestellt. 100 entspricht dabei 600 mA.

Ich hoffe das hilft schon mal weiter.

Viele Grüße und vielen Dank Michael!

von Michael M. (eos400dman)


Lesenswert?

Jetzt Nicht schrieb:
> die ersten zwei Zeilen sind identisch.

Ja sind sie absichtlich, ich muss von beiden Messwerten den Offset 
abziehen.

von Michael M. (eos400dman)


Angehängte Dateien:

Lesenswert?

Hier nun nochmal ein Diagramm mit denn 3 Kurven getrennt.

Viele Grüße Michael

von avion23 (Gast)


Lesenswert?

Es scheint so, als würde die obere Halbwelle fehlen.

von Michael M. (eos400dman)


Lesenswert?

avion23 schrieb:
> Es scheint so, als würde die obere Halbwelle fehlen.

Ich hätte eher gesagt die unter Halbwelle fehlt, aber warum? Hast du 
evtl. eine Vermutung?

Viele Grüße Michael

von avion23 (Gast)


Lesenswert?

Ich vermute Datentypen signed unsigned und Sicherheitsabfragen.

von Stefan F. (Gast)


Lesenswert?

Als erstes würde ich mal die Sensoren einzeln überprüfen, und zwar nicht 
an diesem Motor sondern zum Beispiel mit dem Magnetfeld eines einfachen 
Elektromagneten bei einfachen 50Hz Sinus.

Zeig mal, welche Spannungen diese Sensoren liefern (Oszilloskop).

Dann wissen wir, ob wir im Programmcode oder in der Elektronik weiter 
suchen müssen.

von Michael M. (eos400dman)


Angehängte Dateien:

Lesenswert?

Hallo,

zuerst einmal danke für eure Antworten. Ich habe nun mit einem 50 Hz 
Sinus getestet und mit dem Oszi den Ausgang betrachtet. Im Anhang ist 
einmal die Ausgangsspannung des ACS709 mit DC-Offset und einmal nur der 
Wechselanteil.
Für mich sieht das soweit gut aus, oder was meint ihr?

Viele Grüße Michael

von Michael M. (eos400dman)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe nun noch etwas weiter versucht. Wenn ich die Ströme nicht über
STMStudio betrachte, sondern die Werte in Excel, dann erhalte ich das
Bild im Anhang. Sieht etwas besser aus, aber die negative Halbwelle
fehlt immer noch :/. Hat jemand eine Idee woran dass liegen könnte

Viele Grüße Michael

von Disco (Gast)


Lesenswert?

Beim Freilauf fließt kein Strom durch den Shunt. Evtl ist das das 
Problemen.

von Michael M. (eos400dman)


Lesenswert?

Hallo,

wie meinst du das mit dem Freilauf? Ich stehe gerade etwas auf dem 
Schlauch...

Viele Grüße Michael

von Thorsten O. (Firma: mechapro GmbH) (ostermann) Benutzerseite


Lesenswert?

Er hat ja keinen Shunt, sondern einen Hallsensor. Ich verstehe 
allerdings nicht, wie du mit einem Hallsensor im Massezweig der Brücke 
die drei Phasenströme berechnen willst?!

Wie sieht denn das Ausgangssignal deines Hallsensors aus, wenn du es mit 
dem Scope misst? Dann bekommt man mal eine Idee, ob zumindest die 
Messsignale richtig sind.

So aus dem Bauch heraus würde ich sagen, dass zwei Messungen pro 
PWM-Zyklus zu wenig ist. Aber da sollte ein Vergleich zwischen Messung 
per Scope und per µC schnell Klarheit bringen.

Mit freundlichen Grüßen
Thorsten Ostermann

: Bearbeitet durch User
von Disco (Gast)


Lesenswert?

Ich meine, wenn das PWM abschaltet treibt die Induktivität den Strom 
durch die Mosfets in umgekehrter Richtung weiter. Diesen Strom kannst du 
nicht messen. Den Strom misst du also am besten genau in dem Moment 
bevor das PWM abschaltet.

von Michael M. (eos400dman)


Angehängte Dateien:

Lesenswert?

Thorsten Ostermann schrieb:
> Ich verstehe
> allerdings nicht, wie du mit einem Hallsensor im Massezweig der Brücke
> die drei Phasenströme berechnen willst?!

Im Anhang eine kurze Skizee, die es verdeutlicht. In einem PWM-Zyklus 
kann man jeweils zwei Ströme messen und da der Sternpunkt ja nicht 
angeschlossen ist, kann man über Kirchhoffsches Gesetz den dritten Strom 
berechnen.

Ich hoffe es ist verständlich, ansonsten einfach nochmals Fragen.

Thorsten Ostermann schrieb:
> Wie sieht denn das Ausgangssignal deines Hallsensors aus, wenn du es mit
> dem Scope misst?

Das Problem ist, dass man hier nicht viel erkennen kann. Mann müsste die 
Messwerte abhängig vom Aktuellen PWM-Zustand aufteilen um sinnvolle 
Signalverläufe zu bekommen. Aber ich kann nachher Trotzdem mal einen 
Messung machen und hier Posten.

Viele Grüße Michael

: Bearbeitet durch User
von Michael M. (eos400dman)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe nun des Ausgang des ACS709 und einen Kanal des PWMs gemessen. 
Habe leider nur ein Zweikanaloszilloskop. Der Ausgang sieht etwas 
komisch aus, oder was meint ihr? Kann sich jemand den Verlauf erklären? 
Und warum funktioniert die Messung für die positive Halbwelle dann?

Viele Grüße Michael

von avion23 (Gast)


Lesenswert?

Du kannst anscheinend keine negativen Werte einlesen.

Warum das so ist, weiß ich nicht. Laut Datenblatt kann der Sensor beide 
Stromrichtungen messen und auch ausgeben. Kann er das auch, wenn die 
Ausgangsspannung dann unter 0V sein müsste? Und wie wird das dann 
ausgegeben? Ich konnte das Datenblatt leider nur überfliegen.

Du könntest eine separate Spannungsversorgung des Sensors über Akku 
probieren.

von Michael M. (eos400dman)


Lesenswert?

Der Sensor gibt bei 0 Strom VCC/2 aus. Bei positivem Storm steigt die 
Ausgangsspannung. Bei negativer Stromrichtung sinkt die 
Ausgangsspannung.

Viele Grüße Michael

von Thorsten O. (Firma: mechapro GmbH) (ostermann) Benutzerseite


Lesenswert?

Ich kann auf den Screenshots nichts erkennen. Welcher Kanal ist was, und 
wie ist die Skalierung?

Aber wo sollen eigentlich die negativen Ströme am Hall-Sensor herkommen? 
Du misst ja im Fußpunkt der Brücke, da fließt immer nur der Summenstrom. 
Nur im Generatorbetrieb des Motors wirst du da ggf. eine andere 
Stromrichtung sehen, wenn der Motor ins Netzteil zurück speist.

Mit freundlichen Grüßen
Thorsten Ostermann

von Michael M. (eos400dman)


Lesenswert?

Thorsten Ostermann schrieb:
> Ich kann auf den Screenshots nichts erkennen. Welcher Kanal ist was, und
> wie ist die Skalierung?

Oh sorry, hatte ich vergessen zu schreiben. Blau ist der Ausgang des ACS 
und Gelb ist das PWM-Signal eines Kanals.

Thorsten Ostermann schrieb:
> Aber wo sollen eigentlich die negativen Ströme am Hall-Sensor herkommen?

Vielleicht erklärt es dieses PDF besser: 
http://ww1.microchip.com/downloads/en/AppNotes/01299A.pdf
Theoretisch sollte es funktionieren.

Vielen dank euch allen für eure Mühe und Hilfe!

Viele Grüße Michael

von Michael M. (eos400dman)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

zum Test habe ich jetzt einfach einen Wechselstrom durch den Sensor 
fließen lassen und die Mosfets usw. alles weg gelassen. Dann kommt ein 
relativ schöner Sinus raus. Also sollte die Hardware des Sensors usw. 
passen. Ich vermute es kann nur an der Software liegen. Nur hab ich 
leider keine Idee wo der Fehler ist :/.

Im Anhang ein Bild vom Oszi. Gelb ist die Spannung über dem 
Lastwiderstand, den ich verwendet habe um den Strom zu "erzeugen". Blau 
ist der Ausgang des ACS709, dieser ist als AC eingekoppelt, da der 
ACS-Ausgang ja einen Offset von VCC/2 hat. Zusätzlich auch noch ein Bild 
wie die Werte des STM32 aussehen (nur Qualitativ).

Viele Grüße
Michael

: Bearbeitet durch User
von Michael M. (eos400dman)


Angehängte Dateien:

Lesenswert?

Guten Abend,

nach langen Versuchen habe ich nun etwas, wo man mit viel Fantasie drei 
Sinus-Kurven erahnen kann. Allerdings ist dies noch weit weg von Guten 
Ergebnissen. Gelb ist der Winkel Teta, den ich als Eingang für meinen 
SVPWM-Teil verwende. Ich habe gerade den Verdacht, dass der ACS709 für 
diese Aufgabe etwas zu langsam ist. Kann hierzu jemand etwas sagen?

Bin mittlerweile echt am Verzweifeln. Mit dem Oszi kann ich hier nicht 
vernünftig messen (oder ich weiß nicht was ich noch messen soll) und 
wenn ich einfach nur einen Wechselstrom durch den Sensor schicken, dann 
wird dieser auch korrekt gemessen.

Viele Grüße und noch einen schönen Abend Michael

von Thorsten O. (Firma: mechapro GmbH) (ostermann) Benutzerseite


Lesenswert?

Hallo Michael,

> Thorsten Ostermann schrieb:
>> Aber wo sollen eigentlich die negativen Ströme am Hall-Sensor herkommen?
>
> Vielleicht erklärt es dieses PDF besser:
> http://ww1.microchip.com/downloads/en/AppNotes/01299A.pdf
> Theoretisch sollte es funktionieren.

Lies dir das PDF am Besten nochmal in Ruhe durch und schau dir 
insbesondere die Bilder zu den Stromrichtungen auf Seite 6 nochmal an. 
Der Stromfluss durch den Shunt ist immer positiv, wie ich bereits gesagt 
hatte. Es ist Teil der Rekonstruktion der 3 Phasenströme, das Vorzeichen 
abhängig vom Zustand der FETs richtig zu setzen.

Mit freundlichen Grüßen
Thorsten Ostermann

von Michael M. (eos400dman)


Lesenswert?

Hallo,

ich drehe das Vorzeichen ja auch in der Software. Mir ist bewusst das 
der Strom durch den Shunt immer positiv sein muss. Ich poste heute 
Nachmittag nochmal meinen aktuellen Code, dieser unterscheidet sich aber 
nicht wirklich von dem in meinem ersten Post.

Viele Grüße Michael

von Michael M. (eos400dman)


Lesenswert?

Guten Abend,

hier nochmal der Aktuelle Code zum Auswerten der Messwerte.
1
void strom_auswerten(void)
2
{
3
  ACS_ref = gleitender_mittelwert(ACS_ref, ADCBuffer[0], 3);
4
5
  ADC_Strom_1 -= ACS_ref + ACS_0_Strom_offset;
6
    ADC_Strom_2 -= ACS_ref + ACS_0_Strom_offset;
7
8
    ADC_Strom_1 = ADC_Strom_1 << 3;
9
    ADC_Strom_2 = ADC_Strom_2 << 3;
10
11
  if(flags & erste_adc_messung )
12
          {
13
            flags &= ~erste_adc_messung;
14
            flags &= ~adc_messung_fertig;
15
          }
16
          else
17
          {
18
            flags &= ~adc_messung_fertig;
19
20
            if(counter==2)
21
            {
22
            if(array_counter==2000)
23
            {
24
              asm("nop");
25
            }
26
            else
27
            {
28
                counter = 0;
29
              I_U_array[array_counter] = I_U_flt;//I_U_flt;
30
              I_V_array[array_counter] = I_V_flt;//I_V_flt;
31
              I_W_array[array_counter] = I_W_flt;
32
33
              //I_U_array[array_counter] = ADC_Strom_1;//I_U_flt;
34
              //I_V_array[array_counter] = - ADC_Strom_2;//I_V_flt;
35
              //I_W_array[array_counter] = -ADC_Strom_1 + ADC_Strom_2;
36
37
              teta_array[array_counter++] = teta;
38
            }
39
            }
40
            else
41
            {
42
              counter += 1;
43
            }
44
45
             switch (sektor)
46
                {
47
                case 1:  // 0- 60°
48
                {
49
                  I_W_raw = - ADC_Strom_2;
50
                  I_V_raw = ADC_Strom_1;
51
                  I_U_raw = - I_V_raw - I_W_raw;
52
                  break;
53
                }
54
                case 2:  // 60-120°
55
                {
56
                  I_U_raw = -ADC_Strom_2;
57
                  I_W_raw = ADC_Strom_1;
58
                  I_V_raw = (- I_W_raw - I_U_raw);
59
                  break;
60
                }
61
                case 3:  // 120-180°
62
                {
63
                    I_U_raw = - ADC_Strom_2;
64
                    I_W_raw = ADC_Strom_1;
65
                  I_V_raw = - I_U_raw - I_W_raw;
66
                  break;
67
                }
68
                case 4:  //180-240°
69
                {
70
                  I_U_raw = ADC_Strom_1;
71
                  I_W_raw = - ADC_Strom_2;
72
                  I_V_raw = - I_W_raw - I_U_raw;
73
                  break;
74
                }
75
                case 5:  //240-300°
76
                {
77
                  I_U_raw = ADC_Strom_1; 
78
                  I_W_raw = - ADC_Strom_2;
79
                  I_V_raw = - I_W_raw - I_U_raw;
80
                  break;
81
                }
82
                case 6:  //300-360°
83
                {
84
                  I_V_raw = ADC_Strom_1;
85
                  I_W_raw = - ADC_Strom_2;
86
                  I_U_raw = - I_V_raw - I_W_raw;
87
                  break;
88
                }
89
                default: break;
90
              }
91
          }
92
93
     I_U_flt = gleitender_mittelwert(I_U_flt, I_U_raw, filter_gewichtung_strom);
94
  I_V_flt = gleitender_mittelwert(I_V_flt, I_V_raw, filter_gewichtung_strom);
95
  I_W_flt = gleitender_mittelwert(I_W_flt, I_W_raw, filter_gewichtung_strom);
96
  return;
97
}
ADC_Strom_1 ist dabei der Erste Messwert in der PWM-Periode, also 
zwischen erster und zweiter Umschaltung. ADC_Strom_2 ist der zweite 
Messwert.

Viele Grüße und nochmals Danke für die Hilfe! Michael

von Michael M. (eos400dman)


Lesenswert?

Guten Abend nochmal,

sorry das ich euch nochmal stören muss. Aber evtl. liegt der Fehler ja 
auch in der Initialisierung der Hardware. Ich habe dies zwar so gut ich 
konnte getestet, allerdings kann ja trotzdem jemandes etwas auffallen. 
Timer 1 verwende ich zu PWM Erzeugung. Dieser zählt von 0 bis 2048 und 
dann wieder runter auf 0. Timer 3 läuft synchron zählt aber von 0 bis 
4095. Damit triggere ich den ADC. Dabei wird in der ISR von Timer 3 der 
neue Vergleichswert für die Zweite triggerung des ADCs geladen. In der 
ADC-ISR wird dann wieder der Wert für die erste Triggerung geladen.

Init des Timer 3:
1
void ADC_Timer_ini()
2
{
3
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
4
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
5
6
  #if(timer_3_adc_debug)
7
    TIM_TimeBaseStructure.TIM_Prescaler =  200;
8
  #else
9
    TIM_TimeBaseStructure.TIM_Prescaler =  0;
10
  #endif
11
12
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
13
  TIM_TimeBaseStructure.TIM_Period = 4095;
14
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
15
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
16
17
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
18
  TIM_UpdateRequestConfig(TIM3, TIM_UpdateSource_Global);
19
  TIM_UpdateDisableConfig(TIM3,DISABLE);
20
  TIM_Cmd(TIM3, ENABLE);
21
}
22
23
void ADC_Timer_Compare_ini()
24
{
25
  TIM_OCInitTypeDef TIM_OCInitStructure;
26
27
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
28
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
29
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
30
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
31
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
32
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
33
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Set;
34
  TIM_OCInitStructure.TIM_Pulse = 2048;
35
  TIM_OC4Init(TIM3, &TIM_OCInitStructure);
36
37
  TIM_OCInitStructure.TIM_Pulse = 1024;
38
39
  TIM_OC1Init(TIM3, &TIM_OCInitStructure);
40
  TIM_OCInitStructure.TIM_Pulse = 3072;
41
  TIM_OC3Init(TIM3, &TIM_OCInitStructure);
42
  TIM_DMACmd(TIM3, TIM_DMA_CC1, ENABLE);
43
  TIM_DMACmd(TIM3, TIM_DMA_CC3, ENABLE);
44
}
45
46
void ADC_Timer_Interrupt_ini()
47
{
48
  NVIC_InitTypeDef NVIC_InitStructure;
49
50
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn  ;
51
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
52
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
53
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
54
  NVIC_Init(&NVIC_InitStructure);
55
56
  TIM_ITConfig(TIM3, TIM_IT_CC4, ENABLE);
57
}

Ini des Timer 1:
1
void PWMTimer_ini()
2
{
3
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
4
  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
5
6
  #if(timer_1_pmw_debug)
7
    TIM_TimeBaseStructure.TIM_Prescaler =  200;
8
  #else
9
    TIM_TimeBaseStructure.TIM_Prescaler =  0;
10
  #endif
11
12
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;
13
  TIM_TimeBaseStructure.TIM_Period = 2048;
14
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
15
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
16
17
  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
18
  TIM1->CR1 |= TIM_CR1_URS;  // Nur Over- bzw. Underflow erzeugt Update event
19
  TIM_UpdateRequestConfig(TIM1, TIM_UpdateSource_Regular);
20
  TIM_UpdateDisableConfig(TIM1,DISABLE);
21
  TIM_Cmd(TIM1, ENABLE);
22
23
  TIM_DMAConfig(TIM1, TIM_DMABase_CCR1, TIM_DMABurstLength_3Transfers);
24
}
25
26
void PWMChannel_ini()
27
{
28
  TIM_OCInitTypeDef TIM_OCInitStructure;
29
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
30
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
31
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
32
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
33
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;
34
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
35
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Set;
36
37
    TIM_OCInitStructure.TIM_Pulse = 0;
38
39
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);
40
    TIM_OC2Init(TIM1, &TIM_OCInitStructure);
41
    TIM_OC3Init(TIM1, &TIM_OCInitStructure);
42
43
    TIM_CtrlPWMOutputs(TIM1, ENABLE);
44
45
    TIM1->CCMR1 |= TIM_CCMR1_OC1PE | TIM_CCMR1_OC2PE;  // Compare-Werte erst beim Update-Event übernehmen
46
    TIM1->CCMR2 |= TIM_CCMR2_OC3PE;            // Compare-Werte erst beim Update-Event übernehmen
47
}

ADC Ini:
1
void ADC_2_ini(void)
2
{
3
  RCC_ADCCLKConfig(RCC_PCLK2_Div6);  // ADC Takt max 14MHz.  72MHz/6 = 12MHz
4
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
5
6
  ADC_InitTypeDef ADC_InitStructure;
7
  ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
8
  ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
9
  ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
10
  ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
11
  ADC_InitStructure.ADC_NbrOfChannel = 1;
12
  ADC_InitStructure.ADC_ScanConvMode = ENABLE;
13
  ADC_Init(ADC2, &ADC_InitStructure);
14
15
  ADC_InjectedSequencerLengthConfig(ADC2, 2);
16
  ADC_InjectedChannelConfig(ADC2, ADC_Channel_1, 1, ADC_SampleTime_7Cycles5);
17
  ADC_InjectedChannelConfig(ADC2, ADC_Channel_1, 2, ADC_SampleTime_7Cycles5);
18
  //ADC_InjectedChannelConfig(ADC2, ADC_Channel_1, 3, ADC_SampleTime_1Cycles5);
19
20
  ADC_InjectedDiscModeCmd(ADC2, ENABLE);
21
  ADC_ExternalTrigInjectedConvCmd(ADC2, ENABLE);
22
  ADC_ExternalTrigInjectedConvConfig(ADC2, ADC_ExternalTrigInjecConv_T3_CC4);
23
24
25
  ADC_Cmd(ADC2, ENABLE);
26
27
  // Starte Kalibierung
28
  ADC_ResetCalibration(ADC2);
29
  while(ADC_GetResetCalibrationStatus(ADC2));
30
  ADC_StartCalibration(ADC2);
31
  while(ADC_GetCalibrationStatus(ADC2));
32
}
33
34
void ADC_2_Interrupt_ini()
35
{
36
  NVIC_InitTypeDef  NVIC_InitStructure;
37
  NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
38
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
39
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
40
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
41
  NVIC_Init(&NVIC_InitStructure);
42
  ADC_ITConfig(ADC2, ADC_IT_JEOC, ENABLE);
43
}

ISR Timer 3:
1
void TIM3_IRQHandler(void)
2
{
3
  if(TIM_GetITStatus(TIM3, TIM_IT_CC4))
4
  {
5
    GPIOB->ODR ^= GPIO_Pin_6;
6
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
7
    TIM3->CCR4 =  pwm_aktuell.adc_comp.adc_triggerung_2;
8
  }
9
}

ISR ADC:
1
void ADC1_2_IRQHandler(void)
2
{
3
  ADC_ClearITPendingBit(ADC2, ADC_IT_JEOC);
4
5
6
  ADC_Strom_1 = ADC_GetInjectedConversionValue(ADC2, ADC_InjectedChannel_1);
7
  ADC_Strom_2 = ADC_GetInjectedConversionValue(ADC2, ADC_InjectedChannel_2);
8
9
  TIM3->CCR4 =  pwm_aktuell.adc_comp.adc_triggerung_1;
10
  flags |= adc_messung_fertig;
11
12
  strom_auswerten();
13
}

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.