Regelung des Radschlupfes eines Modellautos: Unterschied zwischen den Versionen

Aus HSHL Mechatronik
Zur Navigation springen Zur Suche springen
Zeile 514: Zeile 514:
<pre>
<pre>


<!-- 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>
<!DOCTYPE HTML>
<html>
<html>
<head>
<head>

Version vom 6. Januar 2023, 11:20 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

Tabelle 1: Testbare, atomare 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.


Technischer Systementwurf

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);
      /* Old browsers */
      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)