Forum: Mikrocontroller und Digitale Elektronik Mit STM32F4 einen Laser ansteuern


von Daniel B. (dbuergin)


Lesenswert?

Hallo

Ich würde gerne, zu experimentellen Zwecken, einen OEM Industrielaser 
mit einem STM32F407ZGT6 (Olimex STM32-P407) ansteuern.

Ich brauche zwei Ausgänge:

1). Digitaler Pin mit einer Frequenz (PWM ?) von 0.1hz - 200khz
    Pulsbreite von 50us bis 100us oder höher (in 1us Schritten).
    Die Pulsbreite und Frequenz kommen über eine serielle Verbindung von
    einer SPS. Während der seriellen Uebetragung sind die Pins
    abgestellt, läuft also nichts auf dem Laser.

2). Ein Analoger Pin, auf welchem, während einem Puls auf dem digitalen
    Pin, eine Treppenfunktion anliegt. So analog dem DAC-"Escalator"
    Beispiel aus den STM32F4 DSP Examples. Es werden also nacheinander
    Werte, welche in einem Array liegen, auf den Analogausgang gelegt.
    Es wird wohl mehrere, fixe Sets von Stützwerten geben, welche je
    nach Pulsbreite ausgegeben werden.

Die Beispiele aus der DSP Lib, habe ich alle zum Laufen gebraucht,
und auch so in etwa dem Sinn nach verstanden. Bin aber ziemlich
erschlagen von all den Möglichkeiten, die diese Funktionen bieten.
Vorallem weiss ich im Moment nicht, wie ich diese Möglichkeiten für
mein Problem kompinieren kann/muss.

Fragen:

Wie berechne ich aus der Frequenz in Hertz und der Pulsbreite
in Microsekunden die Konfigurationswerte für eine PWM ?
Geht das überhaupt ?

Wie verknüpfe ich den analogen Port mit dem digitalen Port,
so dass nur bei einem Puls die Analogwerte ausgegeben werden ?

Mein naiver Ansatz im Moment wäre ein 1us Timer mit einer 
Interruptroutine, in welcher ich Alles versuche zu erledigen ?
Also ohne PWM oder so, aber da gibt es wohl deutlich elegantere
Möglichkeiten oder ?

Tönt das völlig wirr und unmöglich, oder gibt es Hoffung ;-)

Ich bin sehr dankbar für jeden möglichen Tipp.

Gruss

Daniel

von Omega G. (omega) Benutzerseite


Lesenswert?

Was ist bei dir ein OEM Industrielaser? Willst du direkt eine Diode 
ansteuern? Oder hast du ein Netzteil bzw. eine Steuerung der du vorgaben 
machen willst?

Um was für einen Lasertyp handelt es sich? Diode, Gas oder Festkörper? 
Die üblichen Netzteile für Diodenlaser sind zu träge um zw. einem 50µs 
und 51µs Puls unterscheiden zu können.

Ich spekuliere mal, dass du eine Steuerung ansteuerst oder ein Netzteil. 
Vermutlich gibt es eine analoge Leistungs- oder Stromvorgabe und ein 
Enable, sowie ein paar Rückmeldungen. Je nachdem wie deine Steuerung 
reagiert könntest du diese dauerhaft aktivieren, und die Stromvorgabe 
mit deinen Pulsen mit gegebener Spannung ansteuern.

Am einfachsten das PWM Signal auf Gate eines N-MOSFET, Drain über 
Widerstand auf deine Stromvorgabe, außerdem Drain an den entsprechenden 
Eingang der Steuerung, Source auf Masse.

von Rumpel & Stilz (Gast)


Lesenswert?

Je nach Lasertyp ist dann nichts mit Pulsen lassen, per gepulster 
Speisung. Der Laser hat auch seine eigene Differentialgleichung.

von Daniel B. (dbuergin)


Lesenswert?

Es ist ein grüner Ytterbium Fibre Laser. Dieser Laser hat eine geteilte
Steuerung. Ein interner Teil (welchen ich ansteuern will), und einen
externen Teil. Den externen Teil kann man kaufen, oder eben selber
schreiben. Die käufliche Steuerung hat für unsere Zwecke leider einen
zu eingeschränkten Umfang von Möglichkeiten.

Also ja, ich kommunziere mit einer Steuerung. Dort hat es zwei Pins,
welche mich interessieren:

Analogeingang : (0-4V) wobei 0V = no current und 4V = max. current power
Digitaleingang: Hight = emission on, Low = emission off

D.h. über den digitalen Port sage ich dem Laser wann er aussenden soll,
und über den analogen Port, mit welcher Leistung.

Der Witz ist nun, dass man, während der Digi-port on ist, über den
Analogport ein treppenförmiges Ansteigen der Leistung erreicht.

Im Moment bin ich an der trivialen Lösung mit einem 1us Timer und
zwei Zählern, mit welchen ich den Puls und die Frequenz einstellen
kann. Läuft soweit gut. Jetzt kommt die Treppenfunktion auf dem
Analogport....

von Daniel B. (dbuergin)


Lesenswert?

Ach ja, und hier noch der Code, eventuell hat ja jemand noch einen
Tip ;-)

Hauptprogramm:
1
#include "stm32f4xx.h"
2
3
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
4
GPIO_InitTypeDef GPIO_InitStructure;
5
6
void TIM_Config(void);
7
8
//===========================================================
9
// Main
10
//===========================================================
11
12
int main(void)
13
{
14
  TIM_Config();
15
  while (1)
16
  {
17
  }
18
}
19
20
//===========================================================
21
// TIM_Config
22
//===========================================================
23
24
void TIM_Config(void)
25
{
26
  NVIC_InitTypeDef NVIC_InitStructure;
27
28
  /* Enable the TIM2 gloabal Interrupt */
29
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
30
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
31
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
32
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
33
  NVIC_Init(&NVIC_InitStructure);
34
  
35
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
36
  // 1us Timer
37
  TIM_TimeBaseStructure.TIM_Period = 2 - 1; // ergibt 1us 
38
  TIM_TimeBaseStructure.TIM_Prescaler = 42 - 1; // 84 MHz Clock down to 2 MHz (adjust per your clock)
39
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
40
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
41
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
42
  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
43
  TIM_Cmd(TIM2, ENABLE);
44
  
45
  /* GPIOF */
46
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
47
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
48
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
49
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
50
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
51
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
52
  GPIO_Init(GPIOF, &GPIO_InitStructure);
53
}
54
55
#ifdef  USE_FULL_ASSERT
56
57
/**
58
  * @brief  Reports the name of the source file and the source line number
59
  *         where the assert_param error has occurred.
60
  * @param  file: pointer to the source file name
61
  * @param  line: assert_param error line source number
62
  * @retval None
63
  */
64
void assert_failed(uint8_t* file, uint32_t line)
65
{
66
  /* User can add his own implementation to report the file name and line number,
67
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
68
69
  while (1)
70
  {}
71
}
72
73
#endif

Und die Interrupt Routine
1
volatile uint32_t counter  = 0;
2
volatile uint32_t puls     = 0;
3
volatile uint32_t periode  = 0;
4
5
void TIM2_IRQHandler(void)
6
{
7
  if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
8
  {
9
    TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
10
11
    if ((puls == 0) && (periode == 0))
12
    {
13
      puls = 1;
14
      counter = 0;
15
      periode = 0;
16
      GPIO_SetBits(GPIOF, GPIO_Pin_6);
17
    }
18
19
    if ((puls == 1) && (counter > 55))
20
    {
21
      GPIO_ResetBits(GPIOF, GPIO_Pin_6);
22
      counter = 0;
23
      puls = 0;
24
    }
25
    else
26
    {
27
      /* hier sind wir im Puls */
28
      counter++;
29
      periode++;
30
    }
31
32
    if ((puls == 0) && (periode > 200))
33
    {
34
      periode = 0;
35
    }
36
  }
37
}

Das erzeugt jetzt einen 55us Puls bei ca. 5khz. Sieht richtig schön aus 
auf dem Oszi ;-)

von Arm (Gast)


Lesenswert?

der stm32F4 hat einen DA Wandler. Warum benutzt du den nicht?

von Daniel B. (dbuergin)


Lesenswert?

Will ich ja ? Der gepostete Code ist nur der erste Teil mit dem
digitalen Port. Jetzt kommt der analoge Teil, aber hier habe ich
eben meine Schwierigkeiten, den mit dem digitalen Pin zu verknüpfen,
so dass nur während einem Highpuls auf dem digitalen Pin ein analoger
Wert anliegt.
Respektive während dem Puls mehrere analoge Werte hintereinander
ausgegeben werden.

von Daniel B. (dbuergin)


Lesenswert?

Sollte irgendwie so aussehen:

Digi-Pin:

      ----------------------
_____|                      |_________


DAC-Pin:
                         ___
                   _____|   |
             _____|         |
       _____|               |
______|                     |__________


Ist das verständlich ?

von Arm (Gast)


Lesenswert?

bitte grundsätzlich darauf achten den kompletten Code zu posten und die 
Problembeschreibung verständlich gestalten! Dann fällt es dem Leser 
leichter dein Problem zu verstehen. Danke!

Wo genau liegt denn dein Problem? Hast du es schon geschafft einen 
Analogen Wert auszugeben oder hapert es noch am Ansteuern des 
DA-Wandlers?

Eventuell wäre es praktikabel im Interrupt für deinen Puls gleichzeitig 
einen DMA-Transfer zu triggern, der dann den DA-Wandler automatisch eine 
vordefinierte Treppenfunktion "abklappern" lässt, welche du in einem 
Array definiert hast.

Auch solltest du mal gucken wie fein deine analoge Treppe sein soll, 
denn danach musst du die Änderungsgeschwindigkeit des DA-Ausganges 
bemessen. Der DA-Wandler ist aber nicht beliebig schnell.

Bitte das Problem genauer schildern!!

Gruß

von Daniel B. (dbuergin)


Angehängte Dateien:

Lesenswert?

Arm schrieb:
> bitte grundsätzlich darauf achten den kompletten Code zu posten und die
> Problembeschreibung verständlich gestalten! Dann fällt es dem Leser
> leichter dein Problem zu verstehen. Danke!

Ok, sorry, habe gedacht, der Codeteil reicht, da man ja jeder eine
eigene Umgebung hat. Habe mal das ganze Makefile-Projekt
angehängt. Was es noch braucht ist die "STM32F4xx_StdPeriph_Driver".

>
> Wo genau liegt denn dein Problem? Hast du es schon geschafft einen
> Analogen Wert auszugeben oder hapert es noch am Ansteuern des
> DA-Wandlers?

Nein, grundsätzlich kann ich einen DA Wert ausgeben, das klappt. Es
gibt ja diese DAC-Beispiel in den DSP-Examples. Das läuft gut.

> Eventuell wäre es praktikabel im Interrupt für deinen Puls gleichzeitig
> einen DMA-Transfer zu triggern, der dann den DA-Wandler automatisch eine
> vordefinierte Treppenfunktion "abklappern" lässt, welche du in einem
> Array definiert hast.

Genau das würde ich gerne, weiss aber nicht, wie ich den DMA Transfer
von meinem selbst gestrickten Puls aus triggern kann ?
Die automatische Triggerung geht nach meinem Verständnis nur bei
einem direkten Verknüpfen mit einem Timer. Und da ich einen 1us Timer
habe, würde ja jede Microsekunde der DMA-Transfer aufgerufen.

> Auch solltest du mal gucken wie fein deine analoge Treppe sein soll,
> denn danach musst du die Änderungsgeschwindigkeit des DA-Ausganges
> bemessen. Der DA-Wandler ist aber nicht beliebig schnell.

Ist mir klar. Ich will mal mit ein paar wenigen Werten anfangen,
und dann schauen wie weit ich komme. Plan-B wäre dann einen externen
DA-Wandler zu verwenden.

> Bitte das Problem genauer schildern!!

Versuche ich ja ;-)

> Gruß

von Daniel B. (dbuergin)


Angehängte Dateien:

Lesenswert?

Ok, funktioniert soweit so gut. Während dem Puls auf der digitalen
Leitung wird auf den AD-Ausgang (PA4) eine Treppenfunktion von
0V - ~3V ausgegeben.

Jetzt habe ich aber ein kleines Problem und zwar funktioniert das
Ganze nur auf dem STM32F4-Discovery Board.

Wenn ich die Software auf dem Olimex STM32-P407 laufen lasse,
riegelt der AD-Port bei etwa ~1.6V ab. Respektive die Kurve
wird flach. Hoeher als die besagten 1.6V komme ich nicht.

Board: https://www.olimex.com/Products/ARM/ST/STM32-P407/

Der VREF+ Pin liegt auf 3.2V, an dem kann es nicht liegen.
Software ist bis auf die 8Mhz (Discovery) --> 25Mhz (Olimex)
Anpassung gleich.

Die Beschaltungen sehen für mich beide gleich aus, aber ich bin
zuwenig Elektroniker um da Feinheiten zu sehen.

Wäre sehr dankbar für Hilfe.

Gruss

Daniel

von Daniel B. (dbuergin)


Lesenswert?

Die Kamera auf dem Board ausstecken oder ganz entfernen,
dann geht es.

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.