„doc/Arduino“ ändern
parent
b4e32782f6
commit
5eca2f642a
284
doc%2FArduino.md
Normal file
284
doc%2FArduino.md
Normal file
@ -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+
|
||||
}
|
||||
}
|
||||
```
|
Loading…
x
Reference in New Issue
Block a user