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
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.
Je nach Lasertyp ist dann nichts mit Pulsen lassen, per gepulster Speisung. Der Laser hat auch seine eigene Differentialgleichung.
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....
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 ;-)
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.
Sollte irgendwie so aussehen: Digi-Pin: ---------------------- _____| |_________ DAC-Pin: ___ _____| | _____| | _____| | ______| |__________ Ist das verständlich ?
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ß
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ß
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.