add: Arduino Sketch

This commit is contained in:
Rob 2022-11-26 20:58:54 +01:00
parent 40310758ea
commit aa36f6c689
1 changed files with 208 additions and 0 deletions

View File

@ -0,0 +1,208 @@
//
// Grundaufbau des Systems:
//
// 1. Mehrere unabhängige Arduinos mit jeweils bis zu 6 Sensoren
//
// Jeder Arduino hat 1 Taster und je Sensor 1 LED. Bei Tastendruck wird für jeden Sensor,
// welcher einen "zu trockenen" Wert zurückgibt, die LED aktiviert.
// Der Arduino gibt per CAN-Bus mindestens 1x pro Minute aus:
// - Die aktuellen Werte jedes Sensors
// - Die Schnellwertkalibrierung jedes Sensors
// Der Arduino hat ein Konsoleninterface, mit dem die Kalibration eingestellt werden kann.
// Die Sensoren müssen wie folgt angeschlossen sein:
// - VCC jedes Sensors an Pin "5V" am Arduino
// - GND jedes Sensors an Pin "GND" am Arduino
// - AOut der Sensoren an die Pins "A0" bis "A5" am Arduino
// Das CAN-Modul MCP2515 wird so angeschlossen wie unter
// https://github.com/autowp/arduino-mcp2515 dokumentiert
//
// 2. Zentraler Arduino als Anzeigetafel
//
// Dieser Arduino soll anzeigen, auf welchem Beet gegossen werden muss (d. h. wo mindestens ein Sensor "zu trocken" ist).
// Zu diesem Zweck wird auf dem CAN-Bus "mitgelauscht".
// https://github.com/autowp/arduino-mcp2515 --> Auch zur Verkabelung des CAN-Moduls am Arduino nutzen!
#include <mcp2515.h>
struct can_frame canMsg1;
struct can_frame canMsg2;
MCP2515 mcp2515(10);
// Der persistente Speicher wird genutzt
#include <inttypes.h>
#include <avr/eeprom.h>
#include <avr/io.h>
#define EEPROM_MAGIC 0x76
#define DEFAULT_ID 0x13
uint16_t threshold[6];
uint8_t device_id;
void write_threshold(int i_sensor, uint16_t value) {
eeprom_write_byte((uint8_t*)(1+2*i_sensor), (uint8_t)(value % 256)); // % == "Modulo"
eeprom_write_byte((uint8_t*)(2+2*i_sensor), (uint8_t)(value / 256));
};
void setup() {
// Start der seriellen Kommunikation
Serial.begin(9600);
Serial.println("Neustart");
// Setup der digitalen Pins
pinMode(4, OUTPUT); // Anzeige für Sensor 1
pinMode(5, OUTPUT); // f. Sensor 2
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT); // f. Sensor 6
pinMode(3, INPUT_PULLUP); // f. Taster
// Nutzung des persistenten Speichers um Schwellenwerte einzugeben
byte magicbyte = eeprom_read_byte(0);
// Der Speicher kann nur byteweise (0 bis 255) angesprochen werden, unsere Zahlenwerte sind aber bis zu 2 Byte (0 bis 16383) groß.
// Deshalb sind die Werte in zwei Kommandos anzusprechen.
if (magicbyte != EEPROM_MAGIC) {
// Wenn Speicher noch leer, wird die Zahl "470" als Defaultwert hineingeschrieben.
eeprom_write_byte(0, EEPROM_MAGIC);
for (uint8_t i = 0; i < 6; i++) {
write_threshold(i, 475);
}
eeprom_write_byte(13, DEFAULT_ID);
}
// Aus dem Speicher werden nun für jeden Sensor die hinterlegten Werte ausgelesen
// (ggf. auch die gerade gespeicherten Default-Werte)
for (uint8_t i = 0; i < 6; i++) {
threshold[i] = ((uint16_t)eeprom_read_byte((uint8_t*)(1+2*i))) + ((uint16_t)eeprom_read_byte((uint8_t*)(2+2*i)))*256;
}
device_id = eeprom_read_byte(13);
// Initialisierung CAN-Message zur Kommunikation mit anderen Geräten
canMsg1.can_id = "0x40";
canMsg1.can_dlc = 7;
mcp2515.reset();
mcp2515.setBitrate(CAN_5KBPS);
mcp2515.setNormalMode();
// Die Geräteinformationen werden ausgegeben
showinfo();
}
// Methode zum Ausgeben von Werten
void print_values(uint16_t* values) {
for (int i = 0; i < 6; i++) { // i = 0,1,2,3,4,5
Serial.print("S");
Serial.print((char)(0x31+i)); // ASCII: (0x30 = '0'), 0x31 = '1', 0x32 = '2', ...
Serial.print(": ");
Serial.print(values[i]);
Serial.print(" ");
}
Serial.println();
}
uint8_t pause = 0;
void loop() {
// Auslesen der aktuellen Sensorwerte, bis zu 6 Sensoren (Capacitive Soil
// Moisture Sensor v1.2 (Schwingkreis))
uint16_t sensorwert[6];
sensorwert[0] = analogRead(A0);
sensorwert[1] = analogRead(A1);
sensorwert[2] = analogRead(A2);
sensorwert[3] = analogRead(A3);
sensorwert[4] = analogRead(A4);
sensorwert[5] = analogRead(A5);
if (pause)
pause--;
else
print_values(sensorwert);
bool led_ein = (digitalRead(3) == LOW);
for (uint8_t i = 0; i < 6; i++) { // i = 0,1,2,3,4,5
bool trocken = sensorwert[i] > threshold[i];
if (trocken && led_ein) {
// falls Boden trocken und Taster gedrückt
digitalWrite(4+i, HIGH); // für Sensor "i+1" die LED einschalten
}
else
digitalWrite(4+i, LOW); // ansonsten die LED ausschalten
// Angelehnt an das Beispiel für die Bibliothek mcp2515
canMsg1.data[0] = device_id;
canMsg1.data[1] = i;
canMsg1.data[2] = trocken ? 0x0f : 0x00;
canMsg1.data[3] = sensorwert[i] % 256;
canMsg1.data[4] = sensorwert[i] / 256;
canMsg1.data[5] = threshold[i] % 256;
canMsg1.data[6] = threshold[i] / 256;
mcp2515.sendMessage(&canMsg1);
}
delay(1000);
shellinterface();
}
void showinfo() {
// Die Geräte-ID wird angezeigt
Serial.print("Geräte-ID: ");
Serial.println(device_id);
// Die Schwellwerte anzeigen unter Nutzung der Auslesemethode
Serial.print("Schwellenwerte: ");
print_values(threshold);
Serial.print("-------------\n");
}
void shellinterface() {
String line = Serial.readString();
// Leere Eingaben zurückgeben
if (line.length() == 0)
return;
// Zeilenende löschen
if (line[line.length()-1] == '\n')
line = line.substring(0, line.length()-1);
else if (line[line.length()-1] == '\r')
line = line.substring(0, line.length()-1);
// Für Debuggingzwecke die Eingabe anzeigen
Serial.print("Received: ");
Serial.println(line);
// Ab hier werden die Kommandos definiert:
if (line == "show") {
showinfo();
}
else if (line == "pause") {
Serial.println("Stoppe Ausgabe für 60 Sekunden.");
pause = 60;
// Dieser Wert wird in der Loop-Methode dann jede Sekunde heruntergezählt
}
else if (line.startsWith("set S") && line.length() > 7 && line[6] == '=') {
// Sensorkanal auslesen, das ASCII-Zeichen für "0" abziehen um direkt die Zahl von 1 bis 6 zu erhalten
// Außerdem 1 abziehen, da die Sensor-Nummern 1 bis 6 den internen Sensornummern 0-5 entsprechen.
int i_sensor = line[5] - '0' - 1;
int new_threshold = line.substring(7).toInt();
Serial.print("Setze den Schwellwert von Sensor S");
Serial.print(i_sensor+1);
Serial.print(" von ");
Serial.print(threshold[i_sensor]);
Serial.print(" auf ");
Serial.println(new_threshold);
threshold[i_sensor] = new_threshold;
write_threshold(i_sensor, new_threshold);
}
else if (line.startsWith("set ID=")) {
int new_id = line.substring(7).toInt();
Serial.print("Setze die Geraete-ID von ");
Serial.print(device_id);
Serial.print(" auf ");
Serial.println(new_id);
device_id = new_id;
eeprom_write_byte(13, new_id);
}
else Serial.println("Kommando \"" + line + "\" nicht erkannt.");
}