Hallo,
Ich möchte Daten von Sensoren(Temperatur, Luftfeuchtigkeit und CO2 Gehalt) an einer Scada Software schicken(konkret: ExoMachine Scada Expert). Dafür habe ich schon einen Webserver aufgesetzt um mich mit dem Ethernetshield vertraut zu machen. Das hat alles wunderbar funktioniert.
Jetzt nimmt das Scada Programm am liebsten TCP/IP als Datenverbindung. Es wird jede Sekunde vom Client eine Anfrage geschickt um die 3 Messwerte zu bekommen. Dort kann ich auch die IP-Adresse einfach angeben.
Meine Fragen: Wie kann ich eine TCP/IP Server aufsetzten? Ist das ähnlich zum Webserver? Brauche ich nur den Befehl Ethernet.write()?
Momentan kann der Client keine Verbindung aufbauen.
Hier mein Code(ohne Webserver):
Für den Webserver habe ich einfach die drei Zeilen von Ethernet.write(Messwert) geändert.
#include <Adafruit_Sensor.h> //hum
#include <DHT.h> //hum
#include <DHT_U.h> //hum
#include <Wire.h> //temp
#include <LiquidCrystal_I2C.h> //lc
#include <SPI.h> //Webserver
#include <Ethernet.h> //Webserver
#define address 0x4F //temp
#define DHTPIN 2 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT11 //sensor type
DHT_Unified dht(DHTPIN, DHTTYPE);
int SensorPin = 6; // Der PWM-Pin des Sensors wird an Pin6 des Mikrocontrollers angeschlossen
int Messbereich = 5000; // Der voreingestellte Messbereich (0-5000ppm)
unsigned long ZeitMikrosekunden; // Variable für die Dauer des PWM-Signalpegels in Mikrosenkunden
unsigned long ZeitMillisekunden; // Variable für die Dauer des PWM-Signalpegels in Millisekunden
int PPM = 0; // Variable für den CO2-Messwert in ppm (parts per million - Anteile pro Million)
float Prozent=0; // Variable für den prozentuale Länge des PWM-Signals
int ppmmitte[5];
int ppmmittelwert = 0;
float tempmitte[5];
float tempmittelwert = 0;
float hummitte[5];
float hummittelwert = 0;
float humwert = 0;
int cmitte;
uint32_t delayMS;
int ampelRotPin = 9;
int ampelGelbPin = 8;
int ampelGruenPin = 7;
LiquidCrystal_I2C lcd(0x27, 16, 2); //16 Zeichen in 2 Zeilen und der HEX-Adresse 0x27
byte mac[] = {
0xA8, 0x61, 0x0A, 0xAE, 0x76, 0x76
};
IPAddress ip(172, 30, 254, 5 );
IPAddress gateway(172, 30, 254, 1);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
//einmalig ausgeführte SetUp Befehle
void setup()
{
//Starten der seriellen Übertragung
Serial.begin(9600);
Serial.println("Starting...");
dht.begin();
Wire.begin();
lcd.init(); //Im Setup wird der LCD gestartet
lcd.backlight(); //Hintergrundbeleuchtung einschalten (lcd.noBacklight(); schaltet die Beleuchtung aus)
byte Celsius[8] = {B11100,B10100,B11100,B0000,B00000,B00000,B00000,B00000}; //Grad Anzeige selber erstellt
lcd.createChar(0, Celsius);
lcd.setCursor(0, 0);
lcd.print("Hum ");
lcd.setCursor(4, 0);
lcd.print("Temp ");
lcd.setCursor(12, 0);
lcd.print("CO2");
pinMode(SensorPin, INPUT); //Der Pin für die Sensorwerte (6) wird als Eingang definiert.
pinMode(ampelRotPin, OUTPUT);
pinMode(ampelGelbPin, OUTPUT);
pinMode(ampelGruenPin, OUTPUT);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
Serial.println("Ethernet WebServer Example");
// start the Ethernet connection and the server:
Ethernet.setGatewayIP(gateway);
Ethernet.begin(mac, ip);
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware) {
Serial.println("Ethernet shield was not found. Sorry, can't run without hardware. :(");
while (true) {
delay(1); // do nothing, no point running without Ethernet hardware
}
}
if (Ethernet.linkStatus() == LinkOFF) {
Serial.println("Ethernet cable is not connected.");
}
// start the server
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop(){
delay(1000); //pause
sensors_event_t event; //Auslesen der Luftfeuchtigkeit
dht.humidity().getEvent(&event); // Get humidity event and print its value.
if (isnan(event.relative_humidity)) {
Serial.println(F("Error reading humidity!"));
} else {
humwert = event.relative_humidity;
humwert += 17;
}
ZeitMikrosekunden = pulseIn(SensorPin, HIGH, 2000000); // Der pulseIn Befehl misst die Zeit, ab der ein Signal am angegebenen Pin auf HIGH wechselt und in diesem Zustand verbleibt. Standartmäßig endet diese Messung nach maximal 1.000.000 Mikrosekunden (1000ms). Durch das Ahängen des letzten Wertes kann man diesen sogenannten "Timeout" verlängern. Da das Signal des CO2 Sensors bis zu 1004ms lang sein kann, müssen wir den Wert entsprechend hoch ansetzen.
ZeitMillisekunden = ZeitMikrosekunden/1000; // Umwandeln der Zeiteinheit von Mikrosekunden in Millisekunden.
float Prozent = ZeitMillisekunden / 1004.0; // Die maximale Länge des PWM-Signals ist laut Datenblatt des MH-Z19B 1004ms (Millisekunden) lang. Daher berechnen wir hier die gemessene PWM-Signaldauer durch die maximal mögliche Signaldauer und erhalten einen Prozentwert des aktiven (5V) Pegels im PWM-Signal. Dieser Prozentwert spiegelt einen PPM-Wert zwischen 0PPM und 5000PPM wieder.
PPM = Messbereich * Prozent; // PPM-Wert berechnen aus der prozentualen Signaldauer und dem maximalen Messbereich.
Wire.beginTransmission(address);
Wire.write(0x00);
Wire.requestFrom(address, 2);
float temperature = 0;
if (Wire.available()) {
int a = Wire.read();
int b = Wire.read();
float temp = a;
temp=temp+((float)b/1024.0);
temperature = temp;
}
Wire.endTransmission();
mittelwert(PPM, humwert, temperature); //Mittelwertberechnung siehe unten
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
Ethernet.write(ppmmittelwert);
Ethernet.write(hummittelwert);
Ethernet.write(tempmittelwert);
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(5);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
//Von 5 Werten wird der Durchschnitt berechnet und erst nach 5 Sekunden ausgegeben
//Sinn: Ausschläge von Messwerten werden abgeflacht
void mittelwert(int ppm, float hum, float temp){
cmitte += 1;
switch (cmitte){ //Auch mit einem if-else realisierbar
case 1:
ppmmitte[0] = ppm;
tempmitte[0] = temp;
hummitte[0] = hum;
break;
case 2:
ppmmitte[1] = ppm;
tempmitte[1] = temp;
hummitte[1] = hum;
break;
case 3:
ppmmitte[2] = ppm;
tempmitte[2] = temp;
hummitte[2] = hum;
break;
case 4:
ppmmitte[3] = ppm;
tempmitte[3] = temp;
hummitte[3] = hum;
break;
case 5:
ppmmittelwert = 0;
tempmittelwert = 0;
hummittelwert = 0;
ppmmitte[4] = ppm;
tempmitte[4] = temp;
hummitte[4] = hum;
for(int i = 0; i<5; i++){
ppmmittelwert += ppmmitte[i];
tempmittelwert += tempmitte[i];
hummittelwert += hummitte[i];
}
ppmmittelwert /= (cmitte);
tempmittelwert /= (cmitte);
hummittelwert /= (cmitte);
cmitte=0;
display(ppmmittelwert, hummittelwert, tempmittelwert);
break;
}
}
void display(int ppmw, float humw, float tempw){
Serial.print("CO2 PPM: "); // Ausgabe der Werte über den Seriellen Monitor
Serial.println(ppmw);
lcd.setCursor(12, 1); //Ausgabe der Werte über das LCD Display
lcd.print(ppmw);
Serial.print(F("Humidity: "));
Serial.print(humw, 0);
Serial.println(F("%"));
lcd.setCursor(0, 1);
lcd.print(humw, 0);
lcd.setCursor(2, 1);
lcd.print("%");
Serial.print("Temp: ");
Serial.print(tempw);
Serial.print('\n');
lcd.setCursor(4, 1);
lcd.print(tempw);
lcd.setCursor(9, 1);
lcd.write((uint8_t)0);
lcd.setCursor(10, 1);
lcd.print(F("C "));
if(ppmw<700 && ppmw>0){ //Ampelphasen 1
digitalWrite(ampelRotPin, LOW);
digitalWrite(ampelGelbPin, LOW);
digitalWrite(ampelGruenPin, HIGH);
lcd.setCursor(15, 1);
lcd.print(" "); //Damit die Null von den TausendernPPM nicht stehen bleibt
} else if(ppmw>701 && ppmw<1000){ //Ampelphasen 2
digitalWrite(ampelRotPin, LOW);
digitalWrite(ampelGelbPin, HIGH);
digitalWrite(ampelGruenPin, HIGH);
lcd.setCursor(15, 1);
lcd.print(" "); //Damit die Null von den TausendernPPM nicht stehen bleibt
}else if(ppmw>1001 && ppmw<1400){ //Ampelphasen 3
digitalWrite(ampelRotPin, LOW);
digitalWrite(ampelGelbPin, HIGH);
digitalWrite(ampelGruenPin, LOW);
} else if(ppmw>1401){ //Ampelphasen 4
digitalWrite(ampelRotPin, HIGH);
digitalWrite(ampelGelbPin, LOW);
digitalWrite(ampelGruenPin, LOW);
}
}
Falls jemand noch mehr Infos haben möchte: Es ist eine CO2 Ampel mit lcd Display zur Aufzeichnung der Luftqualität im Büro. Jetzt soll es auf einen Großbildschirm noch schöner dargestellt werden
Schonmal danke im vorraus. Ich bin für jede Hilfe offen