From 5eca2f642a501901f49c8f8dafc9f5d341b22f75 Mon Sep 17 00:00:00 2001
From: Tobias Hopp <tobi@gaminggeneration.de>
Date: Mon, 23 Jan 2023 10:21:04 +0100
Subject: [PATCH] =?UTF-8?q?=E2=80=9Edoc/Arduino=E2=80=9C=20=C3=A4ndern?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 doc%2FArduino.md | 284 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 284 insertions(+)
 create mode 100644 doc%2FArduino.md

diff --git a/doc%2FArduino.md b/doc%2FArduino.md
new file mode 100644
index 0000000..7c73954
--- /dev/null
+++ b/doc%2FArduino.md
@@ -0,0 +1,284 @@
+# Arduino
+Hier befindet sich das gesamte Arduino-Projekt, zum iTender Proxy.
+
+
+## Full-Code
+
+```c
+/**
+* Official proxy code for iTender GPIO Communication
+**/
+#include <ArduinoJson.h>
+#include "HX711.h"
+
+// Define the size of the JSON buffer
+#define JSON_BUFFER_SIZE 256
+
+// Create a JSON object for incoming messages
+StaticJsonDocument<JSON_BUFFER_SIZE> incomingJson;
+
+// Create a JSON object for outgoing messages
+DynamicJsonDocument outgoingJson(JSON_BUFFER_SIZE);
+
+void setup() {
+  // Initialize serial communication
+  Serial.begin(9600);
+}
+
+void (*resetFunc)(void) = 0;  //declare reset function @ address 0
+
+void loop() {
+  // Wait for a new line on the serial console
+  if (Serial.available()) {
+    // Read the incoming JSON message
+    DeserializationError error = deserializeJson(incomingJson, Serial);
+    if (error) {
+      // Handle error
+    } else {
+      // Extract the "type" and "data" fields from the JSON object
+      String id = incomingJson["id"];
+      int type = incomingJson["type"];
+      JsonVariant data = incomingJson["data"];
+
+      // Create a nested object in the root object
+      JsonObject outgoingData = outgoingJson.to<JsonObject>().createNestedObject("data");
+
+      outgoingData["success"] = true;
+
+      // Handle the message based on the "type" field
+      switch (type) {
+        case 1:
+          // Handle SET_PIN message
+          pinMode((int)data["pin"], OUTPUT);
+          if (data["mode"] == "DIGITAL") {
+            digitalWrite((int)data["pin"], data["value"]);
+          } else {
+            analogWrite((int)data["pin"], (data["value"] == 255) ? HIGH : LOW);
+          }
+          break;
+        case 2:
+          // Handle GET_VAL message
+          pinMode((int)data["pin"], INPUT);
+          int val;
+          if (data["mode"] == "DIGITAL") {
+            val = digitalRead((int)data["pin"]);
+          } else {
+            val = analogRead((int)data["pin"]);
+          }
+          break;
+        case 3:
+          // Handle GET_SENSOR message
+
+          /*
+          (WEIGHT_VAL - NO_WEIGHT_VAL) / Sensitivitätsfaktor = Gewicht in Gramm
+          (WEIGHT_VAL - NO_WEIGHT_VAL) / (100g_val /100) ist die Formel zur Berechnung des Gewichts in Gramm nach der Kalibrierung mit einem 100 Gramm Gewicht.
+          100g_val /100 gibt den Sensitivitätsfaktor an, der angibt, wie viel sich der Sensorwert ändert, wenn sich das Gewicht um ein Gramm ändert.
+          Durch die Division von 100g_val durch 100 wird der Sensitivitätsfaktor berechnet, und durch die Division von (WEIGHT_VAL - NO_WEIGHT_VAL) durch den Sensitivitätsfaktor wird das Gewicht in Gramm berechnet.
+
+          Beispiel:
+          (WEIGHT_VAL - NO_WEIGHT_VAL) / (100g_val /100) = Gewicht in Gramm
+          (2400 - 2000) / (2450 /100) = 80 Gramm
+          */
+          // HX711 circuit wiring
+          const int LOADCELL_DOUT_PIN = (int) data["pin_dout"];
+          const int LOADCELL_SCK_PIN = (int) data["pin_sck"];
+          HX711 scale;
+          scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
+
+          // Get the weight value from the scale
+          long weight_val = scale.get_units();
+          outgoingData["value"] = weight_val;
+          break;
+        case 4:
+          resetFunc();  //call reset
+          break;
+        default:
+          // Handle unknown message type
+          outgoingData[""] = 0;
+          break;
+      }
+
+      // Prepare the outgoing JSON message
+      outgoingJson["id"] = id;
+      outgoingJson["type"] = 0;
+      outgoingJson["data"] = outgoingData;
+
+      // Send the outgoing JSON message
+      serializeJson(outgoingJson, Serial);
+    }
+  }
+}
+```
+<br>
+
+Das hier ist erstmal der gesamte Code.<br>
+
+<hr>
+
+## Einzelerklärung
+```c
+#include <ArduinoJson.h>
+#include "HX711.h"
+```
+Dieser Teil importiert erstmal die Bibliotheken ArduinoJson und HX711.
+ArduinoJson wird für den Austausch von Anfragen zwischen dem Arduino und dem Raspberry Pi über die Serielle-Verbindung genutzt.
+HX711 ist die Bibliothek für die Wägezelle, welche verwendet wird um das Gewicht in gramm auszurechnen.
+
+```c
+// Define the size of the JSON buffer
+#define JSON_BUFFER_SIZE 256
+
+// Create a JSON object for incoming messages
+StaticJsonDocument<JSON_BUFFER_SIZE> incomingJson;
+
+// Create a JSON object for outgoing messages
+DynamicJsonDocument outgoingJson(JSON_BUFFER_SIZE);
+```
+Hier wird die Buffer-Größe definiert, welche angibt wie groß das JsonDocument sein kann, welches zwischen Raspberry Pi kommuniziert.
+
+Die größe liegt hier bei 256-Bytes, welche derzeit ausreicht um die Anfragen vom Pi zu verarbeiten und zu beantworten.
+
+Danach erstellen wir ein StaticJsonDocument-Objekt `incomingJson`, welches das eingehende JSON verarbeiten soll. Hier geben wir mit <> unsere Buffer-Größe an.
+
+Zuletzt gibt es das DynamicJsonDocument `outgoingJson`, welches das ausgehende Json enthält.
+
+
+```c
+void setup() {
+  // Initialize serial communication
+  Serial.begin(9600);
+}
+
+void (*resetFunc)(void) = 0;  //declare reset function @ address 0
+```
+
+Hier befinden sich zwei Funktionen. Zum einen die `void setup()`-Methode, welche ausgeführt wird, sobald der Arduino startet, zum anderen die eher merkwürdig aussehende `void (*resetFunc)...`-Methode.
+
+In der `setup()` Methode haben wir nur die initalisierung der Seriellen Verbindung auf 9600-Baud. 9600 Baud gibt die Gewschwindigkeit der Übertragung zwischen Pi und Arduino an. Wir testen erstmal mit 9600, können aber bis 115200 erweitern.
+
+Die `resetFunc` dient zum Neustart des Arduinos per Software. Es gibt leider keine restart Funktion oder ähnliches, weshalb wir uns hier das Prinzip eines Sektor-Schreibens zu nutze machen und eine Funktion auf Adresse 0 im Speicher des Arduinos liegen.
+Er stürzt quasi kontrolliert ab und startet neu.
+
+
+
+Danach beginnen wir den Loop, welcher automatisch ausgeführt wird, sobald
+```c
+void loop() {
+  if (Serial.available()) {
+    // Read the incoming JSON message
+    DeserializationError error = deserializeJson(incomingJson, Serial);
+    if (error) {
+      // Handle error
+    } else {
+      // Extract the "type" and "data" fields from the JSON object
+      String id = incomingJson["id"];
+      int type = incomingJson["type"];
+      JsonVariant data = incomingJson["data"];
+
+      // Create a nested object in the root object
+      JsonObject outgoingData = outgoingJson.to<JsonObject>().createNestedObject("data");
+
+```
+
+Hier wird zuerst geprüft, ob Serielle Daten vorliegen.
+Sollten Sie vorliegen "Deserialisieren" wir die JSON-Daten, welche gerade über die Serielle Verbindung gesendet werden.
+
+Sollte es dabei einen Fehler geben, können wir diesen abfangen.
+Derzeit würde die Anfrage vom Raspberry Pi -> Arduino einfach nach einer Sekunde eine Zeitüberschreitung erhalten, was im Prinzip das selbe ist wie, Arduino hat nicht geantwortet oder etwas stimmt nicht.
+
+Falls erfolgreich speichern wir uns die Anfrage-ID, den Anfrage-Typ sowie ein data-Objekt in Typ `JsonVariant`.
+Die ID ist die Anfrage-ID, welche für unsere Antwort verwendet werden muss. Ansonsten kann Antwort und Anfrage nicht zugeordnet werden.
+
+Der Type ist der Typ der Anfrage. Es gibt GET_PIN, SET_PIN, GET_SENSOR und RESTART.
+
+Danach wird ein outgoingData Objekt erzeigt, welches dazu dient, die ausgehenden Daten zu speichern und zu setzen.
+
+
+```c
+// Handle the message based on the "type" field
+      switch (type) {
+        case 1:
+          // Handle SET_PIN message
+          pinMode((int)data["pin"], OUTPUT);
+          if (data["mode"] == "DIGITAL") {
+            digitalWrite((int)data["pin"], data["value"]);
+          } else {
+            analogWrite((int)data["pin"], (data["value"] == 255) ? HIGH : LOW);
+          }
+          break;
+        case 2:
+          // Handle GET_VAL message
+          pinMode((int)data["pin"], INPUT);
+          int val;
+          if (data["mode"] == "DIGITAL") {
+            val = digitalRead((int)data["pin"]);
+          } else {
+            val = analogRead((int)data["pin"]);
+          }
+          break;
+        case 3:
+          // Handle GET_SENSOR message
+
+          /*
+          (WEIGHT_VAL - NO_WEIGHT_VAL) / Sensitivitätsfaktor = Gewicht in Gramm
+          (WEIGHT_VAL - NO_WEIGHT_VAL) / (100g_val /100) ist die Formel zur Berechnung des Gewichts in Gramm nach der Kalibrierung mit einem 100 Gramm Gewicht.
+          100g_val /100 gibt den Sensitivitätsfaktor an, der angibt, wie viel sich der Sensorwert ändert, wenn sich das Gewicht um ein Gramm ändert.
+          Durch die Division von 100g_val durch 100 wird der Sensitivitätsfaktor berechnet, und durch die Division von (WEIGHT_VAL - NO_WEIGHT_VAL) durch den Sensitivitätsfaktor wird das Gewicht in Gramm berechnet.
+
+          Beispiel:
+          (WEIGHT_VAL - NO_WEIGHT_VAL) / (100g_val /100) = Gewicht in Gramm
+          (2400 - 2000) / (2450 /100) = 80 Gramm
+          */
+          // HX711 circuit wiring
+          const int LOADCELL_DOUT_PIN = (int)data["pin_dout"];
+          const int LOADCELL_SCK_PIN = (int)data["pin_sck"];
+          HX711 scale;
+          scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
+
+          // Get the weight value from the scale
+          long weight_val = scale.get_units();
+          outgoingData["value"] = weight_val;
+          break;
+        case 4:
+          resetFunc();  //call reset
+          break;
+        default:
+          // Handle unknown message type
+          outgoingData[""] = 0;
+          break;
+      }
+```
+
+Es wird gestartet mit einem Switch-Statement.
+Hier finden sich die einzelnen Types wieder, welche anstatt beispielsweise ENUM's wie GET_VALUE in Arduino nur Integer sind, welche diese repräsentieren.
+
+
+In dem `case 1` (SET_PIN) befindet sich der Code um einen Arduino-Pin Digital und Analog auf einen Wert (data["value"] zu setzen.
+
+In `case 2` (GET_PIN) wird ein Arduino-Pin Digital oder Analog ausgelesen.
+
+Bei `case 3` (GET_SENSOR) wird ein HX711-Sensor abgefragt.
+In die Anfrage-Daten kommen als Parameter `pin_dout` sowie `pin_sck` mit, danach wird ein Wagen-Objekt initalisiert und danach versucht auszulesen.
+
+Bei `case 4` (RESTART) soll ein Reset des Arduinos ausgeführt werden. Wie oben erklärt wird die `resetFunc` ausgeführt.
+
+Default sendet einfach leere Daten als Fehler zurück.
+
+```c
+ // Prepare the outgoing JSON message
+      outgoingJson["id"] = id;
+      outgoingJson["type"] = 0;
+      outgoingJson["data"] = outgoingData;
+
+      // Send the outgoing JSON message
+      serializeJson(outgoingJson, Serial);
+    }
+```
+
+Zuletzt wird die outgoingJson-ID, -Type sowie die Daten gesetzt.
+Das JSON wird nun serialized, also in Text-Gewandelt und dann über das Serial-Objekt gesendet.
+
+```c+
+    }
+}
+```
\ No newline at end of file