Regelung des Radschlupfes eines Modellautos: Unterschied zwischen den Versionen
Zeile 539: | Zeile 539: | ||
background-size: cover; | background-size: cover; | ||
background: rgb(226, 226, 226); | background: rgb(226, 226, 226); | ||
background: -moz-linear-gradient(top, rgba(226, 226, 226, 1) 0%, rgba(219, 219, 219, 1) 50%, rgba(209, 209, 209, 1) 51%, rgba(254, 254, 254, 1) 100%); | background: -moz-linear-gradient(top, rgba(226, 226, 226, 1) 0%, rgba(219, 219, 219, 1) 50%, rgba(209, 209, 209, 1) 51%, rgba(254, 254, 254, 1) 100%); | ||
/* FF3.6+ */ | /* FF3.6+ */ |
Version vom 6. Januar 2023, 12:27 Uhr
Autoren: Mario Wollschläger, Lukas Honerlage
→ zurück zur Übersicht: WS2022: Angewandte Elektrotechnik (BSE)
Einleitung
Bei dem vorliegenden Artikel handelt es sich um ein Projekt aus dem Praktikum angewandte Elektrotechnik des Studiengangs Business and Systems Engineering (BSE). Ziel des Projektes ist es, den Radschlupf eines Modellautos zu regeln. Hierfür wird die Raddrehzahl über Sensoren erfasst. Die erfassten Daten speisen eine Regelungsalgorithmus, welcher auf einem Mikrocontroller ausgeführt wird. Basierend auf dem Ergebnis des Algorithmus wird in die Motoransteuerung eingegriffen, um den Regelkreis zu schließen.
Die Umsetzung des Projektes erfolgt nach dem V-Modell.
Anforderungen
ID | Inhalt | Ersteller | Datum | Geprüft von | Datum |
---|---|---|---|---|---|
1.0 | Das System muss den Radschlupf begrenzen, sodass ein vollständiges Durchdrehen der Räder verhindert wird. | Mario Wollschläger | 28.09.2022 | Lukas Honerlage | 29.09.2022 |
1.1 | Die Regelung muss in Echtzeit erfolgen. | Mario Wollschläger | 27.09.2022 | Lukas Honerlage | 27.09.2022 |
2.0 | Das System muss ohne externe Stromversorgung zu betreiben sein. | Mario Wollschläger | 27.09.2022 | Lukas Honerlage | 27.09.2022 |
3.0 | Ein Eingriff in den Motoransteuerung muss für den Nutzer angezeigt werden. | Mario Wollschläger | 27.09.2022 | Lukas Honerlage | 27.09.2022 |
4.0 | Das System muss vollständig im Fahrzeug verbaut werden. | Mario Wollschläger | 27.09.2022 | Lukas Honerlage | 27.09.2022 |
5.0 | Die Regelung muss auf einem Arduino Mikrocontroller ausgeführt werden. | Mario Wollschläger | 27.09.2022 | Lukas Honerlage | 27.09.2022 |
6.0 | Die Erschütterungen dürfen die Funktion des Systems nicht beeinträchtigen. | Mario Wollschläger | 27.09.2022 | Lukas Honerlage | 27.09.2022 |
7.0 | Das System muss ohne Nutzereingaben funktionstüchtig sein. | Mario Wollschläger | 27.09.2022 | Lukas Honerlage | 27.09.2022 |
8.0 | Die Reglung des Radschlupfs muss durch den Nutzer abschaltbar sein. | Mario Wollschläger | 27.09.2022 | Lukas Honerlage | 27.09.2022 |
O.1.0 | Optionale Erweiterung: Bietet eine Möglichkeit, Daten über die Raddrehzahl auszuwerten. | Mario Wollschläger | 29.09.2022 | Lukas Honerlage | 29.09.2022 |
O.2.0 | Optionale Erweiterung: Das System regelt den Randschlupf beim Bremsen des Fahrzeuges. | Mario Wollschläger | 29.09.2022 | Lukas Honerlage | 29.09.2022 |
O.2.1 | Optionale Erweiterung: Das Blockieren der Räder im Fahrbetrieb wird verhindert. | Mario Wollschläger | 29.09.2022 | Lukas Honerlage | 29.09.2022 |
Funktionaler Systementwurf / Technischer Systementwurf
Funktionaler Systementwurf
Im funktionalen Systementwurf wurde das System in mehrere Subkomponenten unterteilt, für welche eine Teilaufgabe definiert wurde. In Verbindung erfüllen diese Komponenten die Gesamtaufgabe der Regelung des Radschlupfs.
- Raddrehzahlsensor vorn: Diese Komponente misst die Drehzahl der Vorderachse. Auf diese Weise wird die Geschwindigkeit des Fahrzeuges ermittelt.
- Raddrehzahlsensor hinten: Diese Komponente misst die Drehzahl der Hinterachse. Auf diese Weise wird die Geschwindigkeit der angetriebenen Achse ermittelt.
- Arduino: Der Mikrocontrollern wertet die Sensordaten aus und führt den Regelungsalgorithmus aus. Mit dem Ergebnis wird die Motorsteuerung angesteuert.
- Motorsteuerung: Die Motorsteuerung steuert die Energiezufuhr des Motors und begrenzt somit dessen Leistung.
- Human Machine Interface (HMI): Gibt dem Nutzer Informationen über den Status des Systems. Ermöglicht das Abschalten der Regelung.
- Fahrzeug: Das Fahrzeug ist ein Modellauto. Es beinhaltet Antrieb, Fahrwerk und Energieversorgung.
-
Funktionaler Systementwurf - Projektskizze
-
Funktionaler Systementwurf - Signalfluss
Technischer Systementwurf
-
Technischer Systementwurf - Schnittstellen
Radrehzahlsensor vorne/hinten
Die Komponenten Radrehzahlsensor vorne und hinten sind identisch und besitzen folgende Eingänge:
Eingänge | Beschreibung | Typ |
VCC | Versorgungsspannung | 5 V |
GND | Masse | 0 V |
Die Komponente besitzt folgende Ausgänge:
Ausgänge | Beschreibung | Typ |
DR0 / DR1 | Digitaler Ausgang | Digital |
Arduino
Die Komponente besitzt folgende Eingänge:
Eingänge | Beschreibung | Typ |
Digital Pin2 | Drehzahlsensor vorne | Interrupt |
Digital Pin3 | Drehzahlsensor hinten | Interrupt |
Digital Pin12 | Taster zum Ein- und Ausschaltung der Regelung | Digital |
VCC | Versorgungsspannung über Spannungswandler | 5 V |
GND | Ground | 0 V |
Die Komponente besitzt folgende Ausgänge:
Ausgänge | Beschreibung | Typ |
Digital Pin9 | Motorsteuerung | PWM |
Digital Pin10 | Signalleitung Anzeige, ob das System aktiv ist | Digital |
Digital Pin11 | Signalleitung Anzeige, ob das System regelt | Digital |
Motorsteuerung
Die Komponente besitzt folgende Eingänge:
Eingänge | Beschreibung | Typ |
VCC | Versorgungsspannung | 5 V |
GND | Masse | 0 V |
DM0 | PWM - Eingang | PWM |
VAV | Zuleitung vom RC-Controller des Autos (Vorlauf) | Analog |
VAR | Zuleitung vom RC-Controller des Autos (Rücklauf) | Analog |
VAC | Versorgungsspannung Fahrzeug | ca. 7,2V |
Die Komponente besitzt folgende Ausgänge:
Ausgänge | Beschreibung | Typ |
VMV | Zuleitung zum Motor (Vorlauf) | Analog |
VMR | Zuleitung zum Motor (Rücklauf) | Analog |
Human Machine Interface (HMI)
Die Komponente besitzt folgende Eingänge:
Eingänge | Beschreibung | Typ |
VCC | Versorgungsspannung | 5 V |
GND | Masse | 0 V |
DH0 | System aktiv | Digital |
DH1 | System greift in die Motorsteuerung ein | Digital |
Die Komponente besitzt folgende Ausgänge:
Ausgänge | Beschreibung | Typ |
DH2 | System deaktivieren | Digital |
Fahrzeug
Die Komponente besitzt folgende Eingänge:
Eingänge | Beschreibung | Typ |
VMV | Motor Vorlauf | Analog |
VMR | Motor Rücklauf | Analog |
Die Komponente besitzt folgende Ausgänge:
Ausgänge | Beschreibung | Typ |
VAV | Motorsteuerungskabel Vorlauf | Analog |
VAR | Motorsteuerungskabel Rücklauf | Analog |
VAC | Versorgungsspannung Fahrzeug | ca. 7,2 V |
Spannungswandler
Die Komponente besitzt folgende Eingänge:
Eingänge | Beschreibung | Typ |
VAC | Versorgungsspannung Fahrzeug | ca. 7,2 V |
GND | Masse | 0V |
Die Komponente besitzt folgende Ausgänge:
Ausgänge | Beschreibung | Typ |
VCC | Versorgungsspannung | 5 V |
GND | Masse | 0V |
Komponentenspezifikation
Programmierung
Dashboard
Entwicklung einer Wifi-Schnittstelle, um Daten live Daten vom Auto anzeigen zu können. Die Schnittstelle soll über den Serial Port des Arduinos erfolgen. Das bietet den Vorteil, dass einerseits die Daten direkt über dem seriellen Monitor aus dem Programm Arduino gelesen werden können, wenn eine Kabelverbindung möglich ist. Andererseits muss keine Veränderung am Code vorgenommen werden, um die Daten über die Wifi Schnittstelle auszugeben.
Die einheitliche Schnittstelle wurde wie in der unten stehen Tabelle festgelegt. Ein zu übertragende Byte-String beginnt immer mit dem Zeichen A und endet mit F. Nach jedem fertig übertragenen Parameter muss ein \n \r folgen, dieses ist notwendig für den seriellen Monitor.
Parameter | Beschreibung |
A | Erstes Zeichen im String, der übertragen wird. |
Parameter 1 | Gibt die Drehzahl der vorderen Reifen an. |
Parameter 2 | Gibt die Drehzahl der hinteren Reifen an. |
Parameter 3 | Gibt die Regeldifferenz an. |
Parameter 4 | Kann frei gewählt werden. |
Parameter 5 | Kann frei gewählt werden. |
Parameter 6 | Kann frei gewählt werden. |
F | Letztes Zeichen im String gibt an, dass die Übertragung abgeschlossen ist. |
Der Code für den ESP8266 wurde auf Plattform Visual Studio Code entwickelt.
/********************************************************************** % Hochschule Hamm-Lippstadt * %********************************************************************** % Modul : WIFIDashboard.INO * % * % Datum : 01. Dezember 2022 * % * % Funktion : WIFI Dashboard für das Projekt Regelung des * % Radschlupfes eines Modellautos * % * % Implementation : Arduino 1.8.19 * % * % Autor : Lukas Honerlage, Mario Wollschläger * % * % Bemerkung : * % * % Letzte Änderung : 23. Dezember 2022 * % * %*********************************************************************/ // Libraries einbinden #include <Arduino.h> #include <ESP8266WiFi.h> #include <ESPAsyncWebServer.h> #include <FS.h> //Wlan Daten const char* ssid = "******"; const char* password = "***************"; //Funktion um den String zu trennen String getValue(String data, char separator, int index) { int found = 0; int strIndex[] = { 0, -1}; int maxIndex = data.length()-1; for(int i=0; i<=maxIndex && found<=index; i++){ if(data.charAt(i)==separator || i==maxIndex){ found++; strIndex[0] = strIndex[1]+1; strIndex[1] = (i == maxIndex) ? i+1 : i; } } return found>index ? data.substring(strIndex[0], strIndex[1]) : ""; } AsyncWebServer server(80); //Variablen anlegen String Drehzahl_1 = "1"; String Drehzahl_2 = "2"; String Regeldiff = "3"; String P = "14"; String I = "15"; String D = "16"; char Byte; // Byte einlesen bool Strf =0; //Nach kompletter Übergabe String den Variablen zuordnen static char buffer[64]; //Speicher reservieren char pos = 0; //Zähler für Postion im Array // Funktionen für zur Übergabe der Zeichenketten an die HTML-Seite String eins() { return String(Drehzahl_1);}; String zwei() { return String(Drehzahl_2);}; String drei() { return String(Regeldiff);}; String vier() { return String(P);}; String fuenf() { return String(I);}; String sechs() { return String(D);}; String sieben() { String data = "{\"P\":\""+String(P)+"\", \"I\":\""+ String(I) +"\", \"D\":\""+ String(D) +"\"}"; return String(data);}; void setup(){ // Serial port für die Kommunikation Serial.begin(115200); // Initialize SPIFFS if(!SPIFFS.begin()){ Serial.println("An Error has occurred while mounting SPIFFS"); return; } // Connect to Wi-Fi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi.."); } // Print IP Adresse Serial.println(WiFi.localIP()); // Route for root / web page server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ request->send(SPIFFS, "/index.html"); }); server.on("/drehzahlvorne", HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, "text/plain", eins().c_str()); }); server.on("/drehzahlhinten", HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, "text/plain", zwei().c_str()); }); server.on("/regeldiff", HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, "text/plain", drei().c_str()); }); server.on("/regeldifferenz", HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, "text/plain", drei().c_str()); }); server.on("/readADC", HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, "text/plain", sieben().c_str()); }); // Start server server.begin(); } void loop() { // Zeichen einlesen und in buffer Speichern if (Serial.available()) { Byte = Serial.read(); if(Byte == 'A') pos = 0; if(Byte == 'F') Strf = true; if(Byte == -1 || Byte == 'A' || Byte == 'F'); else{ buffer[pos++] = Byte; } } // String auf die Variablen aufteilen // String bei \n trennen if(Strf == true){ Drehzahl_1 = getValue(buffer, '\n', 1); Drehzahl_2 = getValue(buffer, '\n', 2); Regeldiff = getValue(buffer, '\n', 3); P = String(getValue(buffer, '\n', 4)); I = String(getValue(buffer, '\n', 5)); D = String(getValue(buffer, '\n', 6)); //Entfernen unerwünschter Zeichen P.trim(); I.trim(); D.trim(); Strf = false; } }
Html Code mit CSS und Java Skript
<!-- Hochschule Hamm-Lippstadt --> <!-- Modul: WIFIDashboard.INO --> <!-- Datum: 01. Dezember 2022 --> <!-- Funktion: WIFI Dashboard für das Projekt Regelung des Radschlupfes eines Modellautos --> <!-- Implementation: Arduino 1.8.19 --> <!-- Autor: Lukas Honerlage, Mario Wollschläger --> <!-- Bemerkung: --> <!-- Letzte Änderung: 23. Dezember 2022 --> <!DOCTYPE HTML> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous"> <script src="https://code.highcharts.com/highcharts.js"></script> <title>Document</title> <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons"> <link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.indigo-pink.min.css"> <script defer src="https://code.getmdl.io/1.3.0/material.min.js"></script> <script src = "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script> <style> .container { background-size: cover; background: rgb(226, 226, 226); background: -moz-linear-gradient(top, rgba(226, 226, 226, 1) 0%, rgba(219, 219, 219, 1) 50%, rgba(209, 209, 209, 1) 51%, rgba(254, 254, 254, 1) 100%); /* FF3.6+ */ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, rgba(226, 226, 226, 1)), color-stop(50%, rgba(219, 219, 219, 1)), color-stop(51%, rgba(209, 209, 209, 1)), color-stop(100%, rgba(254, 254, 254, 1))); /* Chrome,Safari4+ */ background: -webkit-linear-gradient(top, rgba(226, 226, 226, 1) 0%, rgba(219, 219, 219, 1) 50%, rgba(209, 209, 209, 1) 51%, rgba(254, 254, 254, 1) 100%); /* Chrome10+,Safari5.1+ */ background: -o-linear-gradient(top, rgba(226, 226, 226, 1) 0%, rgba(219, 219, 219, 1) 50%, rgba(209, 209, 209, 1) 51%, rgba(254, 254, 254, 1) 100%); /* Opera 11.10+ */ background: -ms-linear-gradient(top, rgba(226, 226, 226, 1) 0%, rgba(219, 219, 219, 1) 50%, rgba(209, 209, 209, 1) 51%, rgba(254, 254, 254, 1) 100%); /* IE10+ */ background: linear-gradient(to bottom, rgba(226, 226, 226, 1) 0%, rgba(219, 219, 219, 1) 50%, rgba(209, 209, 209, 1) 51%, rgba(254, 254, 254, 1) 100%); /* W3C */ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#e2e2e2', endColorstr='#fefefe', GradientType=0); /* IE6-9 */ padding: 20px; } canvas{ -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; } /* Data Table Styling */ #dataTable { font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; border-collapse: collapse; width: 100%; } #dataTable td, #dataTable th { border: 1px solid #ddd; padding: 8px; } #dataTable tr:nth-child(even){background-color: #f2f2f2;} #dataTable tr:hover {background-color: #ddd;} #dataTable th { padding-top: 12px; padding-bottom: 12px; text-align: left; background-color: #4CAF50; color: white; } body { min-width: 310px; max-width: 800px; height: 400px; margin: 0 auto; } h2 { font-family: Arial; font-size: 2.5rem; text-align: center; } h1 { font-family: Arial; font-size: 2.5rem; text-align: center; } h3 { font-family: Arial; font-size: 2.5rem; text-align: left; } h4 { font-family: Arial; font-size: 2.5rem; text-align: right; } </style> </head> <body> <h2>Regelung des Radschlupfes eines Modellautos</h2> <div id="chart-Drehzahl-Vorne" class="container"></div> <div id="chart-Drehzahl-Hinten" class="container"></div> <div id="chart-pressure" class="container"></div> </body> <body> <div style="text-align:center;"><b>Parameter</b></div> <div> <table id="dataTable"> <tr><th>Zeit</th><th>P</th><th>I</th><th>D</th></tr> </table> </div> <br> <script> //Java Skript Code für die Tabelle //Variablen für die Tabelle anlegen var ADCvalues = []; var Tvalues = []; var Hvalues = []; var timeStamp = []; setInterval(window.onload = function() { console.log(new Date().toLocaleTimeString()); }, 100); setInterval(function getData() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { //Push the data in array var time = new Date().toLocaleTimeString(); var txt = this.responseText; var obj = JSON.parse(txt); ADCvalues.push(obj.P); Tvalues.push(obj.I); Hvalues.push(obj.D); timeStamp.push(time); //Update Data Table var table = document.getElementById("dataTable"); var row = table.insertRow(1); var cell1 = row.insertCell(0); var cell2 = row.insertCell(1); var cell3 = row.insertCell(2); var cell4 = row.insertCell(3); cell1.innerHTML = time; cell2.innerHTML = obj.P; cell3.innerHTML = obj.I; cell4.innerHTML = obj.D; } }; xhttp.open("GET", "readADC", true); xhttp.send(); }, 100); </script> </body> <script> // Java Skript Code für die Aktualisierung der 3 Charts var chartT = new Highcharts.Chart({ chart: { renderTo: 'chart-Drehzahl-Vorne' }, title: { text: 'Drehzahl Vorne' }, series: [{ showInLegend: false, data: [] }], plotOptions: { line: { animation: false, dataLabels: { enabled: true } }, series: { color: '#059e8a' } }, xAxis: { type: 'datetime', dateTimeLabelFormats: { second: '%H:%M:%S' } }, yAxis: { title: { text: 'Drehzahl 1/s' } }, credits: { enabled: false } }); setInterval(function () { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { var x = (new Date()).getTime(), y = parseFloat(this.responseText); //console.log(this.responseText); if (chartT.series[0].data.length > 40) { chartT.series[0].addPoint([x, y], true, true, true); } else { chartT.series[0].addPoint([x, y], true, false, true); } } }; xhttp.open("GET", "/drehzahlvorne", true); xhttp.send(); }, 100); var chartH = new Highcharts.Chart({ chart: { renderTo: 'chart-Drehzahl-Hinten' }, title: { text: 'Drehzahl-Hinten' }, series: [{ showInLegend: false, data: [] }], plotOptions: { line: { animation: false, dataLabels: { enabled: true } } }, xAxis: { type: 'datetime', dateTimeLabelFormats: { second: '%H:%M:%S' } }, yAxis: { title: { text: 'Drehzahl 1/s' } }, credits: { enabled: false } }); setInterval(function () { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { var x = (new Date()).getTime(), y = parseFloat(this.responseText); if (chartH.series[0].data.length > 40) { chartH.series[0].addPoint([x, y], true, true, true); } else { chartH.series[0].addPoint([x, y], true, false, true); } } }; xhttp.open("GET", "/drehzahlhinten", true); xhttp.send(); }, 100); var chartP = new Highcharts.Chart({ chart: { renderTo: 'chart-pressure' }, title: { text: 'Regeldifferenz' }, series: [{ showInLegend: false, data: [] }], plotOptions: { line: { animation: false, dataLabels: { enabled: true } }, series: { color: '#18009c' } }, xAxis: { type: 'datetime', dateTimeLabelFormats: { second: '%H:%M:%S' } }, yAxis: { title: { text: 'Regeldifferenz' } }, credits: { enabled: false } }); setInterval(function () { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { var x = (new Date()).getTime(), y = parseFloat(this.responseText); if (chartP.series[0].data.length > 40) { chartP.series[0].addPoint([x, y], true, true, true); } else { chartP.series[0].addPoint([x, y], true, false, true); } } }; xhttp.open("GET", "/regeldiff", true); xhttp.send(); }, 100); setInterval(function () { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { document.getElementById("regeldifferenz").innerHTML = this.responseText; } }; xhttp.open("GET", "/regeldifferenz", true); xhttp.send(); }, 100); </script> </html>
Komponententest
Zusammenfassung
Literaturverzeichnis
→ zurück zur Übersicht: WS2022: Angewandte Elektrotechnik (BSE)