Weizen Eingießanlage: Unterschied zwischen den Versionen

Aus HSHL Mechatronik
Zur Navigation springen Zur Suche springen
 
(18 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 65: Zeile 65:
  Datei:Technischer Systementwurf Weizen Eingiesanlage.png | Technischer Systementwurf
  Datei:Technischer Systementwurf Weizen Eingiesanlage.png | Technischer Systementwurf
Datei: RegelKreis_Weizenglas.png| Weizen Eingießanlage Regelkreis
Datei: RegelKreis_Weizenglas.png| Weizen Eingießanlage Regelkreis
</gallery>
'''Ansatz zur Herleitung der Übertragungsfunktion:'''
<gallery widths="500" heights="500">
Datei:ÜbertragungsfunktionHerleitungAnsatz.png | Ansatz zur Herleitung der Übertragungsfunktion
</gallery>
</gallery>
<!-- Füllen Sie Ihre Projektskizze bis hierher aus. Fügen Sie einen Projektplan unten ein.  -->
<!-- Füllen Sie Ihre Projektskizze bis hierher aus. Fügen Sie einen Projektplan unten ein.  -->
Zeile 84: Zeile 90:
|-
|-
| 2
| 2
| ADM442 Motortreiber
| DM442 Motortreiber
|  
|  
* Vollschritt Einstellung
* Vollschritt Einstellung
Zeile 95: Zeile 101:
* Versorgungsspannung 5V
* Versorgungsspannung 5V
* Messbereich: bis zu 5Kg
* Messbereich: bis zu 5Kg
* 24 Bit ADC
|-
|-
| 4.1
| 4.1
Zeile 126: Zeile 133:
Die Konstruktion der Halterung ist auf den ersten Blick sehr simpel. Dennoch galt es für uns die Kosten sowie das Gewicht niedrig zu halten. Daher belaufen sich fast alle Komponenten auf Holz und Kunststoff. Für die meisten Komponenten konnten wir auf unser Betriebsinternes Lager zurückgreifen lediglich die Holzplatte und die Halterungen für Flasche und Glas waren noch nicht vorhanden. Die Halterungen für Glas und Flasche wurden durch einen 3D-Kunststoffdruck gefertigt. Zudem mussten wir uns überlegen wie wir die Flasche in der Halterung befestigen. Um auch hier eine günstige, einfache und leichte Lösung zu erreichen, setzen wir auf die Spannkraft zweier Gummis, welche die Flasche im Halter halten.  
Die Konstruktion der Halterung ist auf den ersten Blick sehr simpel. Dennoch galt es für uns die Kosten sowie das Gewicht niedrig zu halten. Daher belaufen sich fast alle Komponenten auf Holz und Kunststoff. Für die meisten Komponenten konnten wir auf unser Betriebsinternes Lager zurückgreifen lediglich die Holzplatte und die Halterungen für Flasche und Glas waren noch nicht vorhanden. Die Halterungen für Glas und Flasche wurden durch einen 3D-Kunststoffdruck gefertigt. Zudem mussten wir uns überlegen wie wir die Flasche in der Halterung befestigen. Um auch hier eine günstige, einfache und leichte Lösung zu erreichen, setzen wir auf die Spannkraft zweier Gummis, welche die Flasche im Halter halten.  


'''Wägezelle HX711:'''  
'''Wägezelle HX711:'''  
 
Messprinzip: Durch das zu messende Gewicht wird die Wägezelle leicht gebogen. An der Seite befinden sich 4 Dehnungsmesstreifen, welche als Wheatsstone Brücke angeordnet sind. Der Widerstand der Messstreifen ändert sich mit dem Dehnungsgrad. Somit ändert sich bei einer Last der Widerstand und damit auch der Spannungsabfall der Brückenschaltung. Der Spannungsabfall zwischen den Punkten A und B wird mit einem A/D Wandler ausgewertet.
<gallery widths="500" heights="500">
Datei:Messschaltung HX711 DMS.png | - Messchaltungsaufbau
</gallery>
   


Da die Wägezelle über die physikalische Kraft der Gewichtskraft funktioniert, war es eine Herausforderung in unserem drehenden System die korrekten Werte für den Füllstand zu erhalten. Dies war deshalb so schwierig weil sich die Wägezelle immer in einem anderen Winkel zur Gewichtskraft des Füllstandes befindet. Aus diesem Grund mussten wir die Messwerte noch einmal mit dem cos des Winkels multiplizierten um die korrekte Gewichtskraft zu erhalten. Wir verwenden außerdem einen Look-up-Table um uns die Verarbeitung der Messdaten zu vereinfachen. Konkret subtrahieren wir unseren gemessenen wert mit dem Wert aus dem Look-up-Table an der gleichen Winkelstellung. Somit Erhalten wir die korrekte Gewichtskraft des Pegelstandes des Glases. Dies ist dann dementsprechend unser IST-Wert.  
Da die Wägezelle über die physikalische Kraft der Gewichtskraft funktioniert, war es eine Herausforderung in unserem drehenden System die korrekten Werte für den Füllstand zu erhalten. Dies war deshalb so schwierig weil sich die Wägezelle immer in einem anderen Winkel zur Gewichtskraft des Füllstandes befindet. Aus diesem Grund mussten wir die Messwerte noch einmal mit dem cos des Winkels multiplizierten um die korrekte Gewichtskraft zu erhalten. Wir verwenden außerdem einen Look-up-Table um uns die Verarbeitung der Messdaten zu vereinfachen. Konkret subtrahieren wir unseren gemessenen wert mit dem Wert aus dem Look-up-Table an der gleichen Winkelstellung. Somit Erhalten wir die korrekte Gewichtskraft des Pegelstandes des Glases. Dies ist dann dementsprechend unser IST-Wert.  
Zeile 132: Zeile 145:
'''PI-Regler:'''
'''PI-Regler:'''


Der IST-Wert wird nun mit dem SOLL-Wert von 500 (500ml/Kg) subtrahiert. Somit erhalten wir unsere Regelabweichung welche wir weiterhin mit dem PI-Regler verarbeiten.  Aufgrund dessen, dass 1-Motorschritt in 0,39 Grad am äußeren Umfang der Holzplatte entspricht benötigen wir eine sehr schnelle Regulierung der Motorschritte, sobald Flüssgkeit in das Glas läuft. Daher benötigen wir eine möglichst schnelle Sprungantwort und somit einen großen P-Anteil in unserem Regler. Für unser System haben sich die Werte Kp=0,0135 und Ki=0,00675 als praktikabel erwiesen. Die Stellgröße des Reglers wird direkt als Ansteuerung für den Motor genutzt.
Der IST-Wert wird nun mit dem SOLL-Wert von 500 (500ml/Kg) subtrahiert. Somit erhalten wir unsere Regelabweichung welche wir weiterhin mit dem PI-Regler verarbeiten.  Aufgrund dessen, dass 1-Motorschritt in 0,39 Grad am äußeren Umfang der Holzplatte entspricht, benötigen wir eine sehr schnelle Regulierung der Motorschritte, sobald Flüssgkeit in das Glas läuft. Daher benötigen wir eine möglichst schnelle Sprungantwort und somit einen großen P-Anteil in unserem Regler. Für unser System haben sich die Werte Kp=0,014 und Ki=0,00675 als praktikabel erwiesen. Die Stellgröße des Reglers wird direkt als Ansteuerung für den Motor genutzt.


'''Motoransteuerung:'''
'''Motoransteuerung:'''
Zeile 149: Zeile 162:
Datei:Verdrahtungsplan Eingießanlage.png| Verdrahtungsplan Eingießanlage - [[Datei:Verdrahtungsplan Hopfomat.zip|mini]]
Datei:Verdrahtungsplan Eingießanlage.png| Verdrahtungsplan Eingießanlage - [[Datei:Verdrahtungsplan Hopfomat.zip|mini]]
</gallery>
</gallery>


=== Software ===
=== Software ===
'''Programmablaufplan:'''
'''Programmablaufplan:'''
 
[[Datei:Berechnung Regelabweichung.png|mini]]
<gallery widths="500" heights="500">
<gallery widths="500" heights="500">
Datei:Programmablaufplan Hopfomat.png| Programmablaufplan - [[Datei:PAPHopfomat.zip|mini]]
Datei:Hopfomat PAP.png| Programmablaufplan - [[Datei:HopfomatPAP.zip|mini]]
</gallery>
</gallery>


Zeile 161: Zeile 173:


<gallery widths="500" heights="500">
<gallery widths="500" heights="500">
Datei:Simulink-Regler-Final.png| Weizenglas Eingießanlage - Regler - Simulink - [[Datei:Simulink Regler.zip|mini]]
[[Datei:Simulink-Regler-Final.png| Weizenglas Eingießanlage - Regler - Simulink - [[Datei:Simulink Regler.zip|mini]]]]
</gallery>
</gallery>
{| class="mw-datatable"
! style="font-weight: bold;" |
! style="font-weight: bold;" |
|+ style = "text-align: left"|
|-
|[[Datei:Berechnung Regelabweichung.png|300px|mini|links|Berechnung der Regelabweichung Subsystem]]
|[[Datei:PI-Regler.png|300px|mini|rechts|PID-Regler Subsystem]]
|}


'''DM442.h:'''
'''DM442.h:'''
Zeile 174: Zeile 195:
#define LEFT (bool) false
#define LEFT (bool) false


/**
//Motor Driver Leadshine DM442
This class is only configured for the Arduino Mega 2560
You should only use Pins: 2, 3, 7, 8, 12, 13
Timer4 is the one which is configured, so every pwm signal on these pins are
*/
 
class DM442
class DM442
{
{
Zeile 188: Zeile 204:


//Use the defines for setting the direction
//Use the defines for setting the direction
void setDirection(bool direction);
void setDirection(bool direction); //sets the rotating direction
void setFrequency(int stepsPerSecond);
void setFrequency(int stepsPerSecond); //sets the speed
void setDutyCycle(int percent);
void setDutyCycle(int percent); //sets the torque


void resetSteps();
void resetSteps(); //Reset of counted steps


void singleStep();
void singleStep(); //Drive one step
void driveSteps(int steps);
void driveSteps(int steps); //Drive many steps


long getSteps();
long getSteps(); //Get driven steps


private:
private:
Zeile 298: Zeile 314:
#include "HX711.h"
#include "HX711.h"


#define OFFSET 66981
#define OFFSET 66981 //Calibration Value
#define SCALE (float) (145173 - OFFSET) / 200
#define SCALE (float) (145173 - OFFSET) / 200 //Scaling factor of raw Values


HX711 loadCell;
HX711 loadCell;
Zeile 316: Zeile 332:
/* Start_BEGIN */
/* Start_BEGIN */
#ifndef MATLAB_MEX_FILE
#ifndef MATLAB_MEX_FILE
     Serial.begin(9600);
     //Initialisation of LoadCell
        loadCell.begin((int) DOUT[0], (int) SCK[0]);
    loadCell.begin((int) DOUT[0], (int) SCK[0]);
        loadCell.set_offset(OFFSET);
    loadCell.set_offset(OFFSET);
        loadCell.set_scale(SCALE);
    loadCell.set_scale(SCALE);
#endif
#endif
/* Start_END */
/* Start_END */
Zeile 331: Zeile 347:
/* Output_BEGIN */
/* Output_BEGIN */
#ifndef MATLAB_MEX_FILE
#ifndef MATLAB_MEX_FILE
    //Read force
     float f = loadCell.get_units(10);
     float f = loadCell.get_units(10);
    Serial.println(f);
     force[0] = (double) f;
     force[0] = (double) f;
    Serial.println(force[0]);
#endif
#endif
/* Output_END */
/* Output_END */
Zeile 387: Zeile 402:
/* Start_BEGIN */
/* Start_BEGIN */
#ifndef MATLAB_MEX_FILE
#ifndef MATLAB_MEX_FILE
    //Initialise and start Steppermotor
     stepper.begin(DIR[0], ENA[0], PUL[0]);
     stepper.begin(DIR[0], ENA[0], PUL[0]);
     stepper.setDirection(RIGHT);
     stepper.setDirection(RIGHT);
     stepper.setFrequency(30);
     stepper.setFrequency(30);
     stepper.start();
     stepper.start();
}
#endif
#endif
/* Start_END */
/* Start_END */
}
}


void drive_Steps_Outputs_wrapper(const boolean_T *shouldStep,
void drive_Steps_Outputs_wrapper(const uint16_T *stepsToDrive,
                                const uint16_T *stepsToDrive,
                                 uint16_T *stepsDriven,
                                 uint16_T *stepsDriven,
                                 const real_T *xD,
                                 const real_T *xD,
Zeile 406: Zeile 420:
/* Output_BEGIN */
/* Output_BEGIN */
#ifndef MATLAB_MEX_FILE
#ifndef MATLAB_MEX_FILE
     if(shouldStep[0]) {
     //Drive x-Steps in 1 second
        stepper.setFrequency(stepsToDrive[0]);
    stepper.setFrequency(stepsToDrive[0]);
        stepper.driveSteps(stepsToDrive[0]);
    stepper.driveSteps(stepsToDrive[0]);
        long steps = stepper.getSteps();
    long steps = stepper.getSteps();
        stepsDriven[0] = steps;
    stepsDriven[0] = steps;
    }
#endif
#endif
/* Output_END */
/* Output_END */
}
}


void drive_Steps_Update_wrapper(const boolean_T *shouldStep,
void drive_Steps_Update_wrapper(const uint16_T *stepsToDrive,
                                const uint16_T *stepsToDrive,
                                 uint16_T *stepsDriven,
                                 uint16_T *stepsDriven,
                                 real_T *xD,
                                 real_T *xD,
Zeile 450: Zeile 462:
#include "DM442.h"
#include "DM442.h"


//Debug Funktionen
//#define DEBUG
//#define DEBUG
//#define DEBUG_PID
//#define DEBUG_PID


// Definitionen für die Konfiguration
#define OFFSET 66981
#define OFFSET 66981
#define SCALE (float) (145173 - OFFSET) / 200
#define SCALE (float) (145173 - OFFSET) / 200
Zeile 459: Zeile 473:
#define ROUND_OFFSET 0.1f
#define ROUND_OFFSET 0.1f


#define KP 0.0135
#define KP 0.014
#define KI 0.00675
#define KI 0.00675
#define KD 0
#define KD 0
Zeile 471: Zeile 485:


int arrayLength = 50;
int arrayLength = 50;
//Daten für Lookuptable
float forceArray[50] = {-590.41, -574.05, -554.12, -534.25, -514.57, -494.57, -474.99, -455.52, -436.21, -417.06, -389.06, -379.36, -360.83, -342.52, -324.58, -306.87, -289.52, -272.52, -255.77, -239.32, -223.36, -207.89, -192.75, -178.08, -162.85, -150.12, -136.92, -124.11, -111.74, -99.90, -88.64, -77.87, -67.81, -58.80, -49.67, -41.64, -34.24, -27.44, -21.46, -15.85, -11.08, -7.04, -3.68, -0.94, 1.15, 2.47, 3.17};
float forceArray[50] = {-590.41, -574.05, -554.12, -534.25, -514.57, -494.57, -474.99, -455.52, -436.21, -417.06, -389.06, -379.36, -360.83, -342.52, -324.58, -306.87, -289.52, -272.52, -255.77, -239.32, -223.36, -207.89, -192.75, -178.08, -162.85, -150.12, -136.92, -124.11, -111.74, -99.90, -88.64, -77.87, -67.81, -58.80, -49.67, -41.64, -34.24, -27.44, -21.46, -15.85, -11.08, -7.04, -3.68, -0.94, 1.15, 2.47, 3.17};
double angleArray[50] = {90, 88.05, 86.10, 84.15, 82.20, 80.25, 78.30, 76.35, 74.40, 72.45, 70.50, 68.55, 66.60, 64.65, 62.70, 60.75, 58.80, 56.85, 54.90, 52.95, 51.00, 49.05, 47.10, 45.15, 43.20, 41.25, 39.30, 37.35, 35.40, 33.45, 31.50, 29.55, 27.60, 25.65, 23.70, 21.75, 19.80, 17.85, 15.90, 13.95, 12.00, 10.05, 8.10, 6.15, 4.20, 2.25, 0.30, 0};
double angleArray[50] = {90, 88.05, 86.10, 84.15, 82.20, 80.25, 78.30, 76.35, 74.40, 72.45, 70.50, 68.55, 66.60, 64.65, 62.70, 60.75, 58.80, 56.85, 54.90, 52.95, 51.00, 49.05, 47.10, 45.15, 43.20, 41.25, 39.30, 37.35, 35.40, 33.45, 31.50, 29.55, 27.60, 25.65, 23.70, 21.75, 19.80, 17.85, 15.90, 13.95, 12.00, 10.05, 8.10, 6.15, 4.20, 2.25, 0.30, 0};


// Initialisierung der Lastzelle
void setupHX711() {
void setupHX711() {
   loadCell.begin(8, 9);
   loadCell.begin(8, 9);
Zeile 480: Zeile 496:
}
}


// Initialisierung des Schrittmotors
void setupDM442() {
void setupDM442() {
   stepper.begin(3, 4, 5);
   stepper.begin(3, 4, 5);
Zeile 487: Zeile 504:
}
}


// Aufruf der Setup-Funktionen und Initialisierung des seriellen Ports
void setup() {
void setup() {
   setupDM442();
   setupDM442();
   setupHX711();
   setupHX711();
   pinMode(START_SWITCH, INPUT_PULLUP);
   pinMode(START_SWITCH, INPUT_PULLUP);
   Serial.begin(9600);
   #if defined(DEBUG) || defined(DEBUG_PID)
    Serial.begin(9600);
  #endif
}
}


Zeile 499: Zeile 519:
   static float angle = 90;
   static float angle = 90;


  //Schalter AUS resette das Programm
   if(digitalRead(START_SWITCH) != 0) {
   if(digitalRead(START_SWITCH) != 0) {
     angle = 90;
     angle = 90;
Zeile 505: Zeile 526:
     return;
     return;
   }  
   }  
  if(angle < 0) return; //Für sporadische Messunsicherheiten
   #ifdef DEBUG   
   #ifdef DEBUG   
     Serial.print("ANGLE:");
     Serial.print("ANGLE:");
Zeile 510: Zeile 533:
     Serial.print(",");
     Serial.print(",");
   #endif
   #endif
  //Messe die anliegende Kraft
   float force = loadCell.get_units(10);
   float force = loadCell.get_units(10);
   #ifdef DEBUG   
   #ifdef DEBUG   
Zeile 517: Zeile 541:
   #endif
   #endif
   double cosVal = cos(angle * 3.14 / 180);
   double cosVal = cos(angle * 3.14 / 180);
  //Durch Lookuptable die genullte Kraft bestimmen
   double zeroForce = interpolateY(angleArray, forceArray, arrayLength, angle);
   double zeroForce = interpolateY(angleArray, forceArray, arrayLength, angle);
   #ifdef DEBUG   
   #ifdef DEBUG   
Zeile 523: Zeile 548:
     Serial.print(",");
     Serial.print(",");
   #endif
   #endif
  //Die Kraft differenz zwischen Nullkraft und anliegender Kraft
   double dF = force - zeroForce;
   double dF = force - zeroForce;
   #ifdef DEBUG   
   #ifdef DEBUG   
Zeile 529: Zeile 555:
     Serial.print(",");
     Serial.print(",");
   #endif
   #endif
  //Berechne die senkrechte Kraft -> Füllstand
   double fillLevel =  cosVal * dF;
   double fillLevel =  cosVal * dF;
   #if defined(DEBUG) || defined(DEBUG_PID)  
   #if defined(DEBUG) || defined(DEBUG_PID)  
Zeile 535: Zeile 562:
     Serial.print(",");
     Serial.print(",");
   #endif
   #endif
  //Berechne die Differenz zum vollen Glas
   double error = MAX_FILL_LEVEL - fillLevel;
   double error = MAX_FILL_LEVEL - fillLevel;
   #ifdef DEBUG_PID   
   #ifdef DEBUG_PID   
Zeile 541: Zeile 569:
     Serial.print(",");
     Serial.print(",");
   #endif
   #endif
  //Benutze PID-Regler um Schritte für Motor zu ermitteln
   int steps = (int) pid(error, false);
   int steps = (int) pid(error, false);
   #ifdef DEBUG_PID  
   #ifdef DEBUG_PID  
Zeile 547: Zeile 576:
     Serial.print(",");
     Serial.print(",");
   #endif
   #endif
  //Fahre in einer Sekunde die vorgegebenen Schritte
   stepper.setFrequency(steps);
   stepper.setFrequency(steps);
   stepper.driveSteps(steps);
   stepper.driveSteps(steps);
  //Speichere die insgesamt gefahrenen Schritte abe
   unsigned long drivenSteps = stepper.getSteps();
   unsigned long drivenSteps = stepper.getSteps();
    
    
Zeile 555: Zeile 586:
     Serial.print(drivenSteps);
     Serial.print(drivenSteps);
   #endif
   #endif
  //Ziehe vom Startwinkel den insgesamt gefahrenen Winkel ab
   angle = 90 - drivenSteps * ANGLE_PER_STEP;
   angle = 90 - drivenSteps * ANGLE_PER_STEP;
   Serial.println();
   Serial.println();
}
}


//Umsetzung eines PID-Reglers
int pid(double error, bool reset) {
int pid(double error, bool reset) {
   static unsigned long startMillis = 0;
   static unsigned long startMillis = 0;
Zeile 585: Zeile 618:
   if(out > PID_MAX) return PID_MAX;
   if(out > PID_MAX) return PID_MAX;
   else if(out < PID_MIN) return PID_MIN;
   else if(out < PID_MIN) return PID_MIN;
  else if(out < 0) return 0;
   else return out;
   else return out;
}
}


//Interpolationsfunktion als Look-up Table
float interpolateY(double X[], float Y[], int n, double X_interpolated) {
float interpolateY(double X[], float Y[], int n, double X_interpolated) {
     for (int i = 0; i < n - 1; i++) {
     for (int i = 0; i < n - 1; i++) {
Zeile 602: Zeile 635:
}
}


//Rundet nicht bei 0.5 sondern bei 0.1
int roundTo(float x) {
int roundTo(float x) {
   float diff = x - (int) x;
   float diff = x - (int) x;
Zeile 680: Zeile 714:
Dieses Projekt ist Teil des Moduls GET-Fachpraktikum. Dieses Projekt konzentriert sich auf die Regelung und Ansteuerung eines Motors zur Füllstandsregelung eines 0,5 Liter Glases.  
Dieses Projekt ist Teil des Moduls GET-Fachpraktikum. Dieses Projekt konzentriert sich auf die Regelung und Ansteuerung eines Motors zur Füllstandsregelung eines 0,5 Liter Glases.  
Zu Beginn des Projektes ging es vorwiegend um die Konzeptplanung und die damit verbundenen benötigten Bauteile. Als nächstes wurden die benötigten Bauteile beschafft und auf ihre Eignung geprüft. Des Weiteren wurden die einzelnen Komponenten zu einem Gesamtsystem zusammengebaut und die Funktion des Motors getestet. Dabei fiel auf, dass wir einen stärkeren Motor für unser System benötigten. Nach Einbindung des neuen Motors in das System begannen wir damit die Messwerte zu klassifizieren und den Regler auszulegen. Abschließend legten wir diese Dokumentation im HSHL Wiki an.
Zu Beginn des Projektes ging es vorwiegend um die Konzeptplanung und die damit verbundenen benötigten Bauteile. Als nächstes wurden die benötigten Bauteile beschafft und auf ihre Eignung geprüft. Des Weiteren wurden die einzelnen Komponenten zu einem Gesamtsystem zusammengebaut und die Funktion des Motors getestet. Dabei fiel auf, dass wir einen stärkeren Motor für unser System benötigten. Nach Einbindung des neuen Motors in das System begannen wir damit die Messwerte zu klassifizieren und den Regler auszulegen. Abschließend legten wir diese Dokumentation im HSHL Wiki an.
=== Projektdaten ===
ZIP-Archiv: [[Datei:165 Weizen Eingiessanlage.zip|mini]] <br clear="all">


== YouTube Video ==
== YouTube Video ==
In dem folgenden Youtube Video [https://www.youtube.com/watch?v=sYGwO6g5ZXg YouTube-Video] werden die Funktionen Funktion der Weizeneingießanlage gezeigt.
In dem folgenden Youtube Video [https://youtu.be/AbGATzM_GaI YouTube-Video] werden die Funktionen Funktion der Weizeneingießanlage gezeigt.
{{#ev:youtube|https://www.youtube.com/watch?v=sYGwO6g5ZXg| 750 | | Video 1: Funktion der Weizeneingießanlage |frame}}
{{#ev:youtube|https://youtu.be/AbGATzM_GaI| 750 | | Video 1: Funktion der Weizeneingießanlage |frame}}


== Weblinks ==
== Weblinks ==

Aktuelle Version vom 18. Januar 2024, 00:34 Uhr

Autor: Philipp Sander, Dennis Fleer
Betreuer: Prof. Dr. Mirek Göbel


Einleitung

Dieser Artikel beschreibt den Aufbau und die Funktion einer Weizenglas-Eingießanlage. Hierbei gibt es eine Halterung für die Flasche und eine für ein Glas. Beide sind jeweils an einer rotierenden Holzplatte montiert. Diese Holzplatte wird mittels Elektromotor rotiert. Über einem Drucksensor wird der Füllstand des Weizenglases ermittelt und eine optimale Einfüllung des Glases erreicht.

Anforderungen

Teilanforderungen
Nr. Beschreibung Bereich Zuständig
1 Die Halterungen müssen an der Holzplatte befestigt werden. Hardware Dennis Fleer, Philipp Sander
2 Der Motor muss die Holzplatte drehen können. Hardware Dennis Fleer, Philipp Sander
3 Die Elektrik muss eingebaut und verkabelt werden. Hardware Dennis Fleer, Philipp Sander
4 Die Regelung muss durch den Kraftsensor erfolgen. Software Dennis Fleer, Philipp Sander
5 Der Motor muss mittels Regler angesteuert werden. Software Dennis Fleer, Philipp Sander

Funktionaler Systementwurf/Technischer Systementwurf

Im folgenden Systementwurf wird das Projekt in Systemkomponenten unterteilt:

  • Arduino: In Matlab Simulink programmierte Ansteuerung des Motors und Regelung.
  • Motor: Drehbewegung der Holzplattform
  • Drucksensor: Kraftmessung für die Füllstandserkennung
  • Regler: Füllstandsregelung des Weizenglases


Ansatz zur Herleitung der Übertragungsfunktion:

Komponentenspezifikation

Nr. Bauteil Beschreibung
1 Arduino MEGA 2560
  • Versorgungsspannung: 7V-12V (empfohlen)
  • Betriebsspannung: 5V
  • 54 digitale Ein-/Ausgänge und 16 analoge Eingänge
2 DM442 Motortreiber
  • Vollschritt Einstellung
  • Versorgungsspannung 24V
3 HX711 Wägezelle
  • Versorgungsspannung 5V
  • Messbereich: bis zu 5Kg
  • 24 Bit ADC
4.1 Schrittmotor ...
  • Betriebsspannung 3V
  • Haltedrehmoment mind. 1,6 Nm

Umsetzung (HW/SW)

Hardware

Projektübersicht:

In unserem Projekt liegen die Anforderung vorrangig darin eine motorbetriebene drehbare Holzplatte zu konstruieren und dieses System mit einer geeigneten Motoransteuerung zu betreiben. In bezug auf Kosten und Gewicht haben wir uns daher für eine Holzkonstruktion entschieden. Die Holzplatte, an welcher die Halterungen für die Bierflasche und Weizenflasche sowie der Sensor befestigt ist, wird von einer Massivholzwelle getragen. Diese Welle wird mittels Lageraufständen auf einer Holzgrundplatte befestigt. Die Welle wird durch eine Riemenübersetzung mit dem Schrittmotor angetrieben.

3D Ansicht:

Baugruppen Model

Motor:

Wir wollten zunächst den Motor des Arduino-Mega-Sets verwenden. Allerdings ist uns nach einer kleinen Testfahrt aufgefallen dass dieser zu wenig Haltedrehmoment aufweist. Daher haben wir auf einen ausgediehnten Motor aus unsere Partnerfirma "Diebold-Nixdorf Inc." gesetzt. Dieser Motor war nun auch in der Lage unsere Anforderungen zu erfüllen. Um diesen Motor zu betreiben wählten wir einen Motortreiber welchen wir ebenfalls in einem ausgediehnten Geldautomaten-System fanden.

Konstruktion:

Die Konstruktion der Halterung ist auf den ersten Blick sehr simpel. Dennoch galt es für uns die Kosten sowie das Gewicht niedrig zu halten. Daher belaufen sich fast alle Komponenten auf Holz und Kunststoff. Für die meisten Komponenten konnten wir auf unser Betriebsinternes Lager zurückgreifen lediglich die Holzplatte und die Halterungen für Flasche und Glas waren noch nicht vorhanden. Die Halterungen für Glas und Flasche wurden durch einen 3D-Kunststoffdruck gefertigt. Zudem mussten wir uns überlegen wie wir die Flasche in der Halterung befestigen. Um auch hier eine günstige, einfache und leichte Lösung zu erreichen, setzen wir auf die Spannkraft zweier Gummis, welche die Flasche im Halter halten.

Wägezelle HX711:

Messprinzip: Durch das zu messende Gewicht wird die Wägezelle leicht gebogen. An der Seite befinden sich 4 Dehnungsmesstreifen, welche als Wheatsstone Brücke angeordnet sind. Der Widerstand der Messstreifen ändert sich mit dem Dehnungsgrad. Somit ändert sich bei einer Last der Widerstand und damit auch der Spannungsabfall der Brückenschaltung. Der Spannungsabfall zwischen den Punkten A und B wird mit einem A/D Wandler ausgewertet.


Da die Wägezelle über die physikalische Kraft der Gewichtskraft funktioniert, war es eine Herausforderung in unserem drehenden System die korrekten Werte für den Füllstand zu erhalten. Dies war deshalb so schwierig weil sich die Wägezelle immer in einem anderen Winkel zur Gewichtskraft des Füllstandes befindet. Aus diesem Grund mussten wir die Messwerte noch einmal mit dem cos des Winkels multiplizierten um die korrekte Gewichtskraft zu erhalten. Wir verwenden außerdem einen Look-up-Table um uns die Verarbeitung der Messdaten zu vereinfachen. Konkret subtrahieren wir unseren gemessenen wert mit dem Wert aus dem Look-up-Table an der gleichen Winkelstellung. Somit Erhalten wir die korrekte Gewichtskraft des Pegelstandes des Glases. Dies ist dann dementsprechend unser IST-Wert.

PI-Regler:

Der IST-Wert wird nun mit dem SOLL-Wert von 500 (500ml/Kg) subtrahiert. Somit erhalten wir unsere Regelabweichung welche wir weiterhin mit dem PI-Regler verarbeiten. Aufgrund dessen, dass 1-Motorschritt in 0,39 Grad am äußeren Umfang der Holzplatte entspricht, benötigen wir eine sehr schnelle Regulierung der Motorschritte, sobald Flüssgkeit in das Glas läuft. Daher benötigen wir eine möglichst schnelle Sprungantwort und somit einen großen P-Anteil in unserem Regler. Für unser System haben sich die Werte Kp=0,014 und Ki=0,00675 als praktikabel erwiesen. Die Stellgröße des Reglers wird direkt als Ansteuerung für den Motor genutzt.

Motoransteuerung:

Die Motoransteuerung erfolgt über den Motortreiber DM441 dieser braucht eine externe Versorgungsspannung von 24V. Außerdem werden zur Steuerung drei Pins angeschlossen.

- ENA: Sorgt für das Starten des Motors und zusätzlich auch für einen Haltestrom.

- DIR: Gibt die Richtung, in die der Motor fahren soll.

- PUL: Über diesen Pin wird ein PWM-Signal gesendet, welches das Drehmoment und die Geschwindigkeit bestimmt.

Verdrahtungsplan:

Software

Programmablaufplan:

Simulink Regler Model:

Berechnung der Regelabweichung Subsystem
PID-Regler Subsystem

DM442.h:

#ifndef DM442_h
#define DM442_h

#define RIGHT (bool) true
#define LEFT (bool) false

//Motor Driver Leadshine DM442
class DM442
{
public:
	void begin(int dir, int ena, int pul);
	void start();
	void stop();

	//Use the defines for setting the direction
	void setDirection(bool direction); //sets the rotating direction
	void setFrequency(int stepsPerSecond); //sets the speed
	void setDutyCycle(int percent); //sets the torque

	void resetSteps(); //Reset of counted steps

	void singleStep(); //Drive one step
	void driveSteps(int steps); //Drive many steps

	long getSteps(); //Get driven steps

private:
	int dir; //Direction-Pin address
	int ena; //Enable-Pin address
	int pul; //Pulse-Pin address
	int frequency; //highs per second
	int dutyCycle; //in %
	bool running; //Motor can drive
	bool direction; //motor rotates in direction TRUE = right | FALSE = left viewed from the front 
	long steps; //positive value for right steps | negative for left steps

};

#endif

DM442.cpp:

#include "DM442.h"
#include "Arduino.h"

void DM442::begin(int dir, int ena, int pul) {
	this->dir = dir;
	this->ena = ena;
	this->pul = pul;
	pinMode(dir, OUTPUT);
	pinMode(ena, OUTPUT);
	pinMode(pul, OUTPUT);
	this->steps = 0;
	this->running = false;
	this->direction = RIGHT;
	this->dutyCycle = 50;
	this->frequency = 1;
	TCCR4B = TCCR4B & 0b11111000 | 0x01;
}

void DM442::start() {
	digitalWrite(this->ena, LOW);
}

void DM442::stop() {
	digitalWrite(this->ena, HIGH);
}

void DM442::setDirection(bool direction) {
	this->direction = direction;
	if (direction) digitalWrite(this->dir, HIGH);
	else digitalWrite(this->dir, LOW);
}

void DM442::setFrequency(int stepsPerSecond) {
	this->frequency = stepsPerSecond;
}

void DM442::setDutyCycle(int percent) {
	this->dutyCycle = percent;
}

void DM442::singleStep() {
	//analogWrite(this->pul, 255 * this->dutyCycle / 100);
	if (this->frequency == 0) return;
	long delayHigh = (float) this->dutyCycle / 100 * 500 / this->frequency;
	long delayLow = (float) (100 - this->dutyCycle) / 100 * 500 / this->frequency;
	digitalWrite(this->pul, HIGH);
	delay(delayHigh);
	digitalWrite(this->pul, LOW);
	delay(delayLow);
	this->steps++;
}

void DM442::driveSteps(int steps) {
	int percentPerStep = 40 / steps;
	for (int i = 0; i < steps; i++) {
		setDutyCycle(10 + i * percentPerStep);
		singleStep();
	}
}

long DM442::getSteps() {
	return this->steps;
}

void DM442::resetSteps() {
	this->steps = 0;
}

read_HX711 S-Function:

/* Includes_BEGIN */
#ifndef MATLAB_MEX_FILE

#include "HX711.h"

#define OFFSET 66981 //Calibration Value
#define SCALE (float) (145173 - OFFSET) / 200 //Scaling factor of raw Values

HX711 loadCell;

#endif
/* Includes_END */

/* Externs_BEGIN */
/* extern double func(double a); */
/* Externs_END */

void read_HX711_Start_wrapper(real_T *xD,
                              const uint8_T *SCK, const int_T p_width0,
                              const uint8_T *DOUT, const int_T p_width1)
{
/* Start_BEGIN */
#ifndef MATLAB_MEX_FILE
    //Initialisation of LoadCell
    loadCell.begin((int) DOUT[0], (int) SCK[0]);
    loadCell.set_offset(OFFSET);
    loadCell.set_scale(SCALE);
#endif
/* Start_END */
}

void read_HX711_Outputs_wrapper(real_T *force,
                                const real_T *xD,
                                const uint8_T *SCK, const int_T p_width0,
                                const uint8_T *DOUT, const int_T p_width1)
{
/* Output_BEGIN */
#ifndef MATLAB_MEX_FILE
    //Read force
    float f = loadCell.get_units(10);
    force[0] = (double) f;
#endif
/* Output_END */
}

void read_HX711_Update_wrapper(real_T *force,
                               real_T *xD,
                               const uint8_T *SCK, const int_T p_width0,
                               const uint8_T *DOUT, const int_T p_width1)
{
/* Update_BEGIN */

/* Update_END */
}

void read_HX711_Terminate_wrapper(real_T *xD,
                                  const uint8_T *SCK, const int_T p_width0,
                                  const uint8_T *DOUT, const int_T p_width1)
{
/* Terminate_BEGIN */
/*
 * Custom Terminate code goes here.
 */
/* Terminate_END */
}

drive_Steps S-Function:

/* Includes_BEGIN */
#ifndef MATLAB_MEX_FILE

#include "DM442.h"

DM442 stepper;

#endif
/* Includes_END */

/* Externs_BEGIN */
/* extern double func(double a); */
/* Externs_END */

void drive_Steps_Start_wrapper(real_T *xD,
                               const uint8_T *ENA, const int_T p_width0,
                               const uint8_T *DIR, const int_T p_width1,
                               const uint8_T *PUL, const int_T p_width2)
{
/* Start_BEGIN */
#ifndef MATLAB_MEX_FILE
    //Initialise and start Steppermotor
    stepper.begin(DIR[0], ENA[0], PUL[0]);
    stepper.setDirection(RIGHT);
    stepper.setFrequency(30);
    stepper.start();
#endif
/* Start_END */
}

void drive_Steps_Outputs_wrapper(const uint16_T *stepsToDrive,
                                 uint16_T *stepsDriven,
                                 const real_T *xD,
                                 const uint8_T *ENA, const int_T p_width0,
                                 const uint8_T *DIR, const int_T p_width1,
                                 const uint8_T *PUL, const int_T p_width2)
{
/* Output_BEGIN */
#ifndef MATLAB_MEX_FILE
    //Drive x-Steps in 1 second
    stepper.setFrequency(stepsToDrive[0]);
    stepper.driveSteps(stepsToDrive[0]);
    long steps = stepper.getSteps();
    stepsDriven[0] = steps;
#endif
/* Output_END */
}

void drive_Steps_Update_wrapper(const uint16_T *stepsToDrive,
                                uint16_T *stepsDriven,
                                real_T *xD,
                                const uint8_T *ENA, const int_T p_width0,
                                const uint8_T *DIR, const int_T p_width1,
                                const uint8_T *PUL, const int_T p_width2)
{
/* Update_BEGIN */

/* Update_END */
}

void drive_Steps_Terminate_wrapper(real_T *xD,
                                   const uint8_T *ENA, const int_T p_width0,
                                   const uint8_T *DIR, const int_T p_width1,
                                   const uint8_T *PUL, const int_T p_width2)
{
/* Terminate_BEGIN */
/*
 * Custom Terminate code goes here.
 */
/* Terminate_END */
}

Arduino Regler:

#include "HX711.h"
#include "DM442.h"

//Debug Funktionen
//#define DEBUG
//#define DEBUG_PID

// Definitionen für die Konfiguration
#define OFFSET 66981
#define SCALE (float) (145173 - OFFSET) / 200
#define MAX_FILL_LEVEL 500
#define ANGLE_PER_STEP (float) 0.39
#define ROUND_OFFSET 0.1f

#define KP 0.014
#define KI 0.00675
#define KD 0
#define PID_MAX 30
#define PID_MIN 0

#define START_SWITCH 2

HX711 loadCell;
DM442 stepper;

int arrayLength = 50;
//Daten für Lookuptable
float forceArray[50] = {-590.41, -574.05, -554.12, -534.25, -514.57, -494.57, -474.99, -455.52, -436.21, -417.06, -389.06, -379.36, -360.83, -342.52, -324.58, -306.87, -289.52, -272.52, -255.77, -239.32, -223.36, -207.89, -192.75, -178.08, -162.85, -150.12, -136.92, -124.11, -111.74, -99.90, -88.64, -77.87, -67.81, -58.80, -49.67, -41.64, -34.24, -27.44, -21.46, -15.85, -11.08, -7.04, -3.68, -0.94, 1.15, 2.47, 3.17};
double angleArray[50] = {90, 88.05, 86.10, 84.15, 82.20, 80.25, 78.30, 76.35, 74.40, 72.45, 70.50, 68.55, 66.60, 64.65, 62.70, 60.75, 58.80, 56.85, 54.90, 52.95, 51.00, 49.05, 47.10, 45.15, 43.20, 41.25, 39.30, 37.35, 35.40, 33.45, 31.50, 29.55, 27.60, 25.65, 23.70, 21.75, 19.80, 17.85, 15.90, 13.95, 12.00, 10.05, 8.10, 6.15, 4.20, 2.25, 0.30, 0};

// Initialisierung der Lastzelle
void setupHX711() {
  loadCell.begin(8, 9);
  loadCell.set_offset(OFFSET);
  loadCell.set_scale(SCALE);
}

// Initialisierung des Schrittmotors
void setupDM442() {
  stepper.begin(3, 4, 5);
  stepper.setDirection(RIGHT);
  stepper.setFrequency(30);
  stepper.start();
}

// Aufruf der Setup-Funktionen und Initialisierung des seriellen Ports
void setup() {
  setupDM442();
  setupHX711();
  pinMode(START_SWITCH, INPUT_PULLUP);
  #if defined(DEBUG) || defined(DEBUG_PID)
    Serial.begin(9600);
  #endif
}

bool run = true;

void loop() {
  static float angle = 90;

  //Schalter AUS resette das Programm
  if(digitalRead(START_SWITCH) != 0) {
    angle = 90;
    stepper.resetSteps();
    pid(0, true);
    return;
  } 

  if(angle < 0) return; //Für sporadische Messunsicherheiten
  #ifdef DEBUG  
    Serial.print("ANGLE:");
    Serial.print(angle);
    Serial.print(",");
  #endif
  //Messe die anliegende Kraft
  float force = loadCell.get_units(10);
  #ifdef DEBUG  
    Serial.print("FORCE:");
    Serial.print(force);
    Serial.print(",");
  #endif
  double cosVal = cos(angle * 3.14 / 180);
  //Durch Lookuptable die genullte Kraft bestimmen
  double zeroForce = interpolateY(angleArray, forceArray, arrayLength, angle);
  #ifdef DEBUG  
    Serial.print("ZERO:");
    Serial.print(zeroForce);
    Serial.print(",");
  #endif
  //Die Kraft differenz zwischen Nullkraft und anliegender Kraft
  double dF = force - zeroForce;
  #ifdef DEBUG  
    Serial.print("dF:");
    Serial.print(dF);
    Serial.print(",");
  #endif
  //Berechne die senkrechte Kraft -> Füllstand
  double fillLevel =  cosVal * dF;
  #if defined(DEBUG) || defined(DEBUG_PID) 
    Serial.print("Level:");
    Serial.print(fillLevel);
    Serial.print(",");
  #endif
  //Berechne die Differenz zum vollen Glas
  double error = MAX_FILL_LEVEL - fillLevel;
  #ifdef DEBUG_PID  
    Serial.print("ERROR:");
    Serial.print(error);
    Serial.print(",");
  #endif
  //Benutze PID-Regler um Schritte für Motor zu ermitteln
  int steps = (int) pid(error, false);
  #ifdef DEBUG_PID 
    Serial.print("STEPS:");
    Serial.print(steps);
    Serial.print(",");
  #endif
  //Fahre in einer Sekunde die vorgegebenen Schritte
  stepper.setFrequency(steps);
  stepper.driveSteps(steps);
  //Speichere die insgesamt gefahrenen Schritte abe
  unsigned long drivenSteps = stepper.getSteps();
  
  #ifdef DEBUG_PID  
    Serial.print("DRIVEN:");
    Serial.print(drivenSteps);
  #endif
  //Ziehe vom Startwinkel den insgesamt gefahrenen Winkel ab
  angle = 90 - drivenSteps * ANGLE_PER_STEP;
  Serial.println();
}

//Umsetzung eines PID-Reglers
int pid(double error, bool reset) {
  static unsigned long startMillis = 0;
  long iterationTime = millis() - startMillis;
  static double errorSum = 0;
  static double lastError = 0;
  
  if(reset) {
    startMillis = millis();
    errorSum = 0;
    lastError = 0;
    return 0;
  }

  errorSum += error;
  double d = (error - lastError) / iterationTime;
  lastError = error;

  double regulated = KP * error + KI * errorSum / iterationTime + KD * d;
  #ifdef DEBUG_PID  
    Serial.print("PID:");
    Serial.print(regulated);
    Serial.print(",");
  #endif
  int out = roundTo(regulated);
  if(out > PID_MAX) return PID_MAX;
  else if(out < PID_MIN) return PID_MIN;
  else return out;
}

//Interpolationsfunktion als Look-up Table
float interpolateY(double X[], float Y[], int n, double X_interpolated) {
    for (int i = 0; i < n - 1; i++) {
        if (X[i] <= X_interpolated && X_interpolated <= X[i + 1]) {
            double X1 = X[i];
            double X2 = X[i + 1];
            float Y1 = Y[i];
            float Y2 = Y[i + 1];
            return (float) ( Y1 + ((Y2 - Y1) / (X2 - X1)) * (X_interpolated - X1));
        }
    }
    return 0.0;
}

//Rundet nicht bei 0.5 sondern bei 0.1
int roundTo(float x) {
   float diff = x - (int) x;
   if(diff > ROUND_OFFSET) return (int) x + 1;
   else return (int) x;
}

Komponententest

Teilanforderungen
Nr. Beschreibung Testmethode Zuständigkeit Testergebnis
1 Die Halterungen müssen an der Holzplatte befestigt werden. Die Halterungen wurden korrekt befestigt und halten dem Gewicht und der Rotation stand. Fleer, Sander Bestanden
2 Der Motor muss die Holzplatte drehen können. Der Motor kann sowohl beide Gewichte als auch nur die Flasche ohne Probleme heben und halten. Fleer, Sander Bestanden
3 Die Elektrik muss eingebaut und verkabelt werden. Die Verdrahtung der Bauteile wurde korrekt durchgeführt und nochmals mittels Durchgangsprüfung geprüft. Fleer, Sander Bestanden
4 Die Regelung muss durch den Kraftsensor erfolgen. Die Wägezelle misst jede Sekunde die Gewichtskraft des Inhalts. Dieser Ist-Wert wird mit dem Soll-Wert subtrahiert und geht als Regelfehler in unseren Regler. Fleer, Sander Bestanden
5 Der Motor muss mittels Regler angesteuert werden Die Ansteuerung erfolgt softwareseitig durch die Stellgröße unseres Reglers. Fleer, Sander Bestanden

Ergebnis

Das Projekt zur Füllstandsregelung eines Bierglases an der HSHL im Fachgebiet der Mechatronik führte zu einem positiven Ergebnis. Die Anlage ist in der Lage durch umlegen eines Schalters ein 0,5Liter Bierglas einzuschenken. Zu Beginn des Einfüllvorgangs werden die maximalen Motorschritte gefahren. Sobald der Füllstand erkannt wird, werden, je nach Füllstand, weniger Schritte gefahren.

Zusammenfassung

Lessons Learned

Wir haben am Anfang viele Überlegungen getroffen. Aufgrund von Berechnungsfehlern oder falschen Datenblättern haben wir viele Rükschläge erleiden müssen. Schlussendlich konnten wir unseren Anfangs geplanten Ablauf nicht in die Tat umsetzen und sind ziehmlich in Zeitstress gekommen. Daraus haben wir gelernt jedes Datenblatt zweimal zu überprüfen und Berechnungen auch in der Realität auszuprobieren und nicht auf theoretische Annahmen zu vertrauen.

Auch die Programmierung mit Simulink war eine Tortur. Aufgrund unseres Zeitdrucks haben wir uns dann dazu entschieden erstmal ein Arduino Programm zu entwickeln, womit wir immerhin schonmal alles testen konnten und weiter kamen. Später haben wir dann die Reglereinstellungen und Ansteuerungen für Sensor und Aktor in S-Function-Blöcke übernommen und so ein lauffähiges Simulink Modell kreiert. Die Schlüsse die wir hier raus gezogen haben, sind erstmal den vertrauten einfachen Weg gehen und später erst den unkonventionellen Weg nehmen. Auch haben wir gelernt nie wieder auf Matlab Simulink etwas für einen Arduino zu programmieren, da dies um ein viel faches schwieriger ist als ein sauber aufgebautes Arduino Projekt.

In der Programmierung gab es noch ein weiteres Problem. Für den HX711 gab es eine lauffähige Bibliothek schon zur Verfügung. Da wir nicht auf den Anfangs geplanten Motor von Funduino zurück greifen konnten mussten wir einen anderen Motor nehmen. Da dieser Motor eine Anfertigung für die Firma Diebold Nixdorf ist gibt es keine öffentlichen Bibliotheken zur Steuerung. Somit musste hier eine eigene Bibliothek zur Steuerung programmiert werden. Diese musste dann auch wieder getestet und Fehler behoben werden. Auch hier wäre mit mehr Zeit es einfacher gewesen einen Motor zu beschaffen der schon eine fertige Bibliothek öffentlich verfügbar hat.

Projektunterlagen

Projektplan

Projektdurchführung

Dieses Projekt ist Teil des Moduls GET-Fachpraktikum. Dieses Projekt konzentriert sich auf die Regelung und Ansteuerung eines Motors zur Füllstandsregelung eines 0,5 Liter Glases. Zu Beginn des Projektes ging es vorwiegend um die Konzeptplanung und die damit verbundenen benötigten Bauteile. Als nächstes wurden die benötigten Bauteile beschafft und auf ihre Eignung geprüft. Des Weiteren wurden die einzelnen Komponenten zu einem Gesamtsystem zusammengebaut und die Funktion des Motors getestet. Dabei fiel auf, dass wir einen stärkeren Motor für unser System benötigten. Nach Einbindung des neuen Motors in das System begannen wir damit die Messwerte zu klassifizieren und den Regler auszulegen. Abschließend legten wir diese Dokumentation im HSHL Wiki an.

Projektdaten

ZIP-Archiv: Datei:165 Weizen Eingiessanlage.zip

YouTube Video

In dem folgenden Youtube Video YouTube-Video werden die Funktionen Funktion der Weizeneingießanlage gezeigt.

Video 1: Funktion der Weizeneingießanlage

Weblinks

Literatur


→ zurück zur Übersicht: WS 22/23: Angewandte Elektrotechnik (BSE)