Prof. J. Walter - Informationstechnik, Mikrocomputertechnik, Digitale Medien Softwaredoku
Hochschule Karlsruhe Logo Entwicklungsprojekt
universalCNC
Wintersemester 16/17
Maximilian Bryg, Stefan Kleinschmidt,
Patrick Suing, Rapahel Zöhner

Mikrocontroller / Software Dokumentation

Als Mikrocontroller/Embeddes System wurde uns von Herrn Walter das Entwicklungsboard STM32F746G-DISCOVERY zu Verfügung gestellt. Vorteil an diesem Board ist die Mensch-Maschine-Schnittstelle, welche als direkt montiertes Touchdisplay ausgeführt ist.

stm32f746gdisco

Abb.: STM32F746G-DISCOVERY

Das Board besitzt einen ARM Cortex M7 Kern und bietet sich für verschiedenste Anwendungsszenarien an. Die Hauptmerkmale lassen sich auf der Herstellerwebsite einsehen. Für unser Projekt war der Quadratur-Eingang des Boards ein wichtiges Merkmal. Das Weglängenmesssystem von Balluff überträgt die Messgröße als differentielles Spannungssignal (Signal A und Signal B). Die beiden Signale sind elektrisch um 90° Grad phasenversetzt. Das Vorzeichen der Phasenverschiebung hängt von der Bewegungsrichtung des Sensors ab. Der Flankenabstand A/B entspricht der mechanischen Auflösung des Sensorkopfes (z. B. 1 µm).

balluff_signal_a_b

Abb.: Signalverlauf Balluff Messsystem

Im sogenannten Encoder-Mode des Boards wird ein Hardware Timer benutzt, um die Flankenwechsel zu zählen. Je nach Richtung (Phasenverschiebung) zählt der Timer hoch oder runter. Die Richtung wird über das Setzen eines DIR-Bits gekennzeichnet. Das Board kennt somit zu jedem Zeitpunkt die genaue Position des Sensors ohne diesen periodisch abfragen zu müssen (Echtzeitfähigkeit).

stm32f746gdisco_encoder_mode

Abb.: Bespiel aus dem STM32F7 Datenblatt

Weitere Informationen zum Weglängenmesssystem und Encoder-Mode sind in der Anleitung von Balluff und im STM32 cross-series timer overview zu finden.


Für die vorhandene Hardware STM32F7gibt es eine open Source IDE namens System Workbench for STM32. Diese basiert auf dem Programm Eclipse und ist auf der Website openstm32 nach einer kostenlosen Registrierung erhältlich. Auf dieser Website sind auch Erklärungen zur Installation und ersten Einrichtung zu finden.

Um die Hardware des Entwicklungsboards zu konfigurieren, stellt STMicroelectronics das Programm CubeMX zur Verfügung, welches auf der Herstellerwebsite nach einer kostenlosen Registrierung heruntergeladen werden kann.

Auf einer anderen Website des Herstellers finden sich auch allgemeine Informationen, Anleitungen, Handbücher und Treiber. Das Firmware Package STM32CubeF7 ist unter dieser Website erhältlich. In diesem Paket befinden sich unter anderem HAL, Low-Layer APIs, Beispielprogramme und Software, um eine GUI zu erstellen (STemWin).

Eine weitere hilfreiche Website nennt sich microElk. Hier gibt es Anleitungen zur Hardware-Einrichtung und weitere Hinweise zur Erstellung von Projekten mit dem STM32F7.

  Wir beschäftigten uns zunächst mit der grundlegenden Einrichtung des STM32F7. Hierbei verwendeten wir eine, aus einem anderem Projekt vorhandene, graphische Oberfläche und programmierten diese um. Damit war es uns möglich nach Toucheingabe eine Status-LED auf dem Board leuchten zu lassen. Nach weiterer Recherche fanden wir ein anderes Projekt, indem eine Schrittmotorsteuerung mit dem STM32F7 realisiert wurde. Anhand dieses Projektes konnten wir eine graphische Oberfläche, samt Ansteuerung der Endstufe, realisieren. Die Erklärung zur Bedienung ist auf der Seite Bedienungsanleitung zu finden.

gui

Abb.: Graphische Benutzeroberfläche

 



Nachfolgend sollen die entscheidenen Stellen des Sourcecodes gezeigt werden.

Im folgenden Ausschnitt wird das Abfragen der Endschalter in der Datei main.c gezeigt. Die Abfrage findet in der Main Loop statt, welche eine while-Schleife ist. Die Endschalter sind als Öffner ausgelegt, um Drahtbruchsicherheit zu gewährleisten. Daraus folgt: Wenn der Schalter betätigt ist, liegt ein LOW-Pegel am Eingang der Mikrocontrollers an, wenn er nicht betätigt wird, liegt ein HIGH-Pegel am Eingang des Mikrocontrollers an. Das ist der Grund, warum die Variablen EndStopLeft und EndStopRight negiert abgefragt werden. Sobald einer der beiden Endschalter erreicht ist, wird ein Flag gesetzt damit dies im ganzen Programm bekannt ist.
  main.c
.
.
.

// Main Loop
while(1)
{
.
.
.

// Abfragen der Endschalter
// Endschalter links

EndStopLeft = HAL_GPIO_ReadPin(GPIOI, GPIO_PIN_2);
// Endschalter rechts
EndStopRight = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15);

// Wenn Endschalter links erreicht, Endschalter sind Oeffner -> Drahtbruchsicherheit
if (!EndStopLeft)
{
// Flag Endschalter links erreicht setzen
StopLeftReached = 1;
// Flag Endschalter rechts zurücksetzen
StopRightReached = 0;
}
else
{
// Wenn Endschalter rechts erreicht, Endschalter sind Oeffner -> Drahtbruchsicherheit
if (!EndStopRight)
{
// Flag Endschalter links zurücksetzen
StopLeftReached = 0;
// Flag Endschalter rechts erreicht setzen
StopRightReached = 1;
}

.
.
.
}
 


In diesem Ausschnitt wird die Auswahl des manuellen Verfahrmodus in der Datei main.c gezeigt. Die Abfrage findet in der Main Loop statt, welche eine while-Schleife ist. Sobald einer der Taster Move Left oder Move Right gedrückt wird, der Automatik-Modus nicht aktiv ist und die jeweiligen Endschalter nicht betätigt sind, wird ein Flag für den manuellen Modus gesetzt, das jeweilige Richtungsflag gesetzt und der andere Endschalter deaktiviert.
  main.c
.
.
.

// Main Loop
while(1)
{
.
.
.

// manueller Modus
//linke Richtung
// Wenn Taste Move Left gedrückt, Automatik-Modus aus und Endschalter links nicht erreicht
if (BuMoveLeft && !AutoModeActive && !StopLeftReached)
{
// Flag manueller Modus setzen
ManModeActive = 1;
// Motorrichtung links setzen
StepperDirection = 0;
// Flag Endschalter rechts erreicht zuruecksetzen
StopRightReached = 0;
}
else
{
//rechte Richtung
// Wenn Taste Move Left gedrückt, Automatik-Modus aus und Endschalter rechts nicht erreicht

if (BuMoveRight && !AutoModeActive && !StopRightReached)
{
// Flag manueller Modus setzen
ManModeActive = 1;
// Motorrichtung rechts setzen
StepperDirection = 1;
// Flag Endschalter links erreicht zuruecksetzen
StopLeftReached = 0;
}
else
{
// Flag manueller Modus zuruecksetzen
ManModeActive = 0;
}
}

.
.
.
}
 

In diesem Ausschnitt sehen wir die Interrupt Routine, in welcher die Funktion für die Ansteuerung der Schrittmotor-Endstufe aufgerufen wird. Der Interrupt wird jede Millisekunde ausgeführt. Wenn das Flag für den manuellen Modus gesetzt ist (ManModeActive), wird die Funktion MoveStepperContinous aufgerufen. In diesem Aufruf werden die Richtung und die Position des Sliders (Geschwindigkeit) übergeben. Wenn das Flag für den Automatik-Modus gesetzt ist (AutoModeActive), wird die Funktion AutoMode aufgerufen.
  main.c
.
.
.

void HAL_SYSTICK_Callback(void)
{
// Interrupt jede Millisekunde

.
.
.
// Wenn manueller Modus aktiv
if (ManModeActive)
{
// Aufrufen der Funktion für die Ansteuerung
MoveStepperContinuous(StepperDirection, SliderPosition);
}
// Wenn Automatik-Modus aktiv
if (AutoModeActive)
{
// Aufrufen der Funktion für Automatik-Modus
AutoMode();
}

.
.
.

}
 


In der Datei stepper.c befindet sich die Funktion MoveStepperContinous. Diese setzt je nach Richtung den Pegel von D2 auf HIGH oder LOW. D2 ist mit dem Richtungseingang der Endstufe verbunden. Über den Pin D1 wird ein Rechtecksignal durch das Wechseln von HIGH und LOW Pegeln an die Endstufe gegeben.
  stepper.c
.
.
.

void MoveStepperContinuous(int Direction, int Speed)
{

.
.
.

// wenn Direction-Flag mit Bewegung nach links gesetzt ist
if (Direction == 0)
{
// Setzen von D2 auf LOW-Pegel, Richtungseingang an der Endstufe, LOW -> links
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_RESET);

switch (StepNo)
{
case 1:
// Setzen von D1 auf HIGH-Pegel, Pulseingang an der Endstufe
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_SET);

if (NextStep == 1)
{
StepNo = 2;
NextStep = 0;
StepCounter--;
}
break;
case 2:
// Setzen von D1 auf LOW-Pegel, Pulseingang an der Endstufe
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6,GPIO_PIN_RESET);

if (NextStep == 1)
{
StepNo = 1;
NextStep = 0;
StepCounter--;
}
break;

default:
// Zurücksetzen der Pins
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_RESET);
StepNo = 1;
break;
}
}
else
{
// wenn Direction-Flag mit Bewegung nach rechts gesetzt ist
if (Direction == 1 && Period > 0)
{
// Setzen von D2 auf HIGH-Pegel, Richtungseingang an der Endstufe, HIGH -> rechts
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6,GPIO_PIN_SET);

switch (StepNo)
{
case 1:
// Setzen von D1 auf HIGH-Pegel, Pulseingang an der Endstufe
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6,GPIO_PIN_SET);

if (NextStep == 1)
{
StepNo = 2;
NextStep = 0;
StepCounter++;
}
break;
case 2:
// Setzen von D1 auf LOW-Pegel, Pulseingang an der Endstufe
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6,GPIO_PIN_RESET);

if (NextStep == 1)
{
StepNo = 1;
NextStep = 0;
StepCounter--;
}
break;
break;

default:
// Zurücksetzen der Pins
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_6, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_6, GPIO_PIN_RESET);
StepNo = 1;
break;
}
}
}
}
 

Struktogramm

Abb.: Struktogramm
download_struktogramm_xlsx download_struktogramm_xlsx
Download Struktogramm (.xlsx) Download Struktogramm (.pdf)




  Mit Unterstützung von Prof. J. Walter Wintersemester 16/17