hallo my_mx_projekt
ich habe einnmal nur den Code von dem DFRobot Teil herrausgenommen so das es übersichtlicher ist.
#include <Wire.h>
#include <SPI.h>
#include <EEPROM.h>
#include "DFRobot_EC.h"
void EC();
int EC_PIN {4}; // Analopin Arduino Lepnardo ETH
float voltage, ecValue, temperature = 21; // fiktiver Wert da kein onewire sensor angeschliossen ist
DFRobot_EC ec;
void setup() {
Wire.begin(); // enable I2C port.
Serial.begin(115200);
}
void loop() {
EC(); // Auslesen TDS Sensor ppm Wert
Serial.print(salzGehalt(100.0,20.0));
Serial.println(" :g/L");
Serial.print(ecValue);
Serial.println(" mS/cm");
}
void EC() // ermitteln des ec wertes
{
static unsigned long timepoint = millis();
if (millis() - timepoint > 1000U) //time interval: 1s
{
timepoint = millis();
voltage = analogRead(EC_PIN) / 1024.0 * 5000; // read the voltage
//temperature = readTemperature(); // read your temperature sensor to execute temperature compensation
ecValue = ec.readEC(voltage, temperature); // convert voltage to EC with temperature compensation
#ifdef DEBUG1 // Ausgabe im Serialen Monitor deaktiviert
Serial.print("temperature:");
Serial.print(temperature, 1);
Serial.print("^C EC:");
Serial.print(ecValue, 2); // ermittelter wert ms/cm
Serial.println("ms/cm");
#endif
}
ec.calibration(voltage, temperature); // calibration process by Serail CMD
}
float salzGehalt(float ecValue, float temperature) {
const float SF = 553;
float r_salzgehalt = 0;
float A1, A2, A3;
if (temperature <= 10) {
A1 = -0.044532198;
A2 = -0.013174538;
A3 = 1.085694313;
} else {
A1 = -0.073894632;
A2 = -0.010947644;
A3 = 1.09173096;
}
float r_Leitwert = ecValue/(10.0);
float base = 10;
float exponent = (A1 + temperature * A2 + A3 * log10 ( abs(r_Leitwert)));
r_salzgehalt = pow(base, exponent);
r_salzgehalt = r_salzgehalt * SF/1000.0;
return r_salzgehalt;
}
float readTemperature() {
//add your code here to get the temperature from your temperature sensor
}
dazu noch die h und cpp datei von DFRobot.
cpp
/*
* file DFRobot_EC.cpp
* @ https://github.com/DFRobot/DFRobot_EC
*
* Arduino library for Gravity: Analog Electrical Conductivity Sensor / Meter Kit V2 (K=1), SKU: DFR0300
*
* Copyright [DFRobot](http://www.dfrobot.com), 2018
* Copyright GNU Lesser General Public License
*
* version V1.01
* date 2018-06
*/
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "DFRobot_EC.h"
#include <EEPROM.h>
#define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
#define EEPROM_read(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}
#define KVALUEADDR 0x0A //the start address of the K value stored in the EEPROM
#define RES2 820.0
#define ECREF 200.0
char* DFRobot_EC::strupr(char* str) {
if (str == NULL) return NULL;
char *ptr = str;
while (*ptr != ' ') {
*ptr = toupper((unsigned char)*ptr);
ptr++;
}
return str;
}
DFRobot_EC::DFRobot_EC()
{
this->_ecvalue = 0.0;
this->_kvalue = 1.0;
this->_kvalueLow = 1.0;
this->_kvalueHigh = 1.0;
this->_cmdReceivedBufferIndex = 0;
this->_voltage = 0.0;
this->_temperature = 25.0;
}
DFRobot_EC::~DFRobot_EC()
{
}
void DFRobot_EC::begin()
{
EEPROM_read(KVALUEADDR, this->_kvalueLow); //read the calibrated K value from EEPROM
if(EEPROM.read(KVALUEADDR)==0xFF && EEPROM.read(KVALUEADDR+1)==0xFF && EEPROM.read(KVALUEADDR+2)==0xFF && EEPROM.read(KVALUEADDR+3)==0xFF){
this->_kvalueLow = 1.0; // For new EEPROM, write default value( K = 1.0) to EEPROM
EEPROM_write(KVALUEADDR, this->_kvalueLow);
}
EEPROM_read(KVALUEADDR+4, this->_kvalueHigh); //read the calibrated K value from EEPRM
if(EEPROM.read(KVALUEADDR+4)==0xFF && EEPROM.read(KVALUEADDR+5)==0xFF && EEPROM.read(KVALUEADDR+6)==0xFF && EEPROM.read(KVALUEADDR+7)==0xFF){
this->_kvalueHigh = 1.0; // For new EEPROM, write default value( K = 1.0) to EEPROM
EEPROM_write(KVALUEADDR+4, this->_kvalueHigh);
}
this->_kvalue = this->_kvalueLow; // set default K value: K = kvalueLow
}
float DFRobot_EC::readEC(float voltage, float temperature)
{
float value = 0,valueTemp = 0;
this->_rawEC = 1000*voltage/RES2/ECREF;
valueTemp = this->_rawEC * this->_kvalue;
//automatic shift process
//First Range:(0,2); Second Range:(2,20)
if(valueTemp > 2.5){
this->_kvalue = this->_kvalueHigh;
}else if(valueTemp < 2.0){
this->_kvalue = this->_kvalueLow;
}
value = this->_rawEC * this->_kvalue; //calculate the EC value after automatic shift
value = value / (1.0+0.0185*(temperature-25.0)); //temperature compensation
this->_ecvalue = value; //store the EC value for Serial CMD calibration
return value;
}
void DFRobot_EC::calibration(float voltage, float temperature,char* cmd)
{
this->_voltage = voltage;
this->_temperature = temperature;
strupr(cmd);
ecCalibration(cmdParse(cmd)); //if received Serial CMD from the serial monitor, enter into the calibration mode
}
void DFRobot_EC::calibration(float voltage, float temperature)
{
this->_voltage = voltage;
this->_temperature = temperature;
if(cmdSerialDataAvailable() > 0)
{
ecCalibration(cmdParse()); // if received Serial CMD from the serial monitor, enter into the calibration mode
}
}
boolean DFRobot_EC::cmdSerialDataAvailable()
{
char cmdReceivedChar;
static unsigned long cmdReceivedTimeOut = millis();
while (Serial.available()>0)
{
if(millis() - cmdReceivedTimeOut > 500U){
this->_cmdReceivedBufferIndex = 0;
memset(this->_cmdReceivedBuffer,0,(ReceivedBufferLength));
}
cmdReceivedTimeOut = millis();
cmdReceivedChar = Serial.read();
if(cmdReceivedChar == '\n' || this->_cmdReceivedBufferIndex==ReceivedBufferLength-1){
this->_cmdReceivedBufferIndex = 0;
strupr(this->_cmdReceivedBuffer);
return true;
}else{
this->_cmdReceivedBuffer[this->_cmdReceivedBufferIndex] = cmdReceivedChar;
this->_cmdReceivedBufferIndex++;
}
}
return false;
}
byte DFRobot_EC::cmdParse(const char* cmd)
{
byte modeIndex = 0;
if(strstr(cmd, "ENTEREC") != NULL){
modeIndex = 1;
}else if(strstr(cmd, "EXITEC") != NULL){
modeIndex = 3;
}else if(strstr(cmd, "CALEC") != NULL){
modeIndex = 2;
}
return modeIndex;
}
byte DFRobot_EC::cmdParse()
{
byte modeIndex = 0;
if(strstr(this->_cmdReceivedBuffer, "ENTEREC") != NULL)
modeIndex = 1;
else if(strstr(this->_cmdReceivedBuffer, "EXITEC") != NULL)
modeIndex = 3;
else if(strstr(this->_cmdReceivedBuffer, "CALEC") != NULL)
modeIndex = 2;
return modeIndex;
}
void DFRobot_EC::ecCalibration(byte mode)
{
char *receivedBufferPtr;
static boolean ecCalibrationFinish = 0;
static boolean enterCalibrationFlag = 0;
static float compECsolution;
float KValueTemp;
switch(mode){
case 0:
if(enterCalibrationFlag){
Serial.println(F(">>>Command Error<<<"));
}
break;
case 1:
enterCalibrationFlag = 1;
ecCalibrationFinish = 0;
Serial.println();
Serial.println(F(">>>Enter EC Calibration Mode<<<"));
Serial.println(F(">>>Please put the probe into the 1413us/cm or 12.88ms/cm buffer solution<<<"));
Serial.println();
break;
case 2:
if(enterCalibrationFlag){
if((this->_rawEC>0.9)&&(this->_rawEC<1.9)){ //recognize 1.413us/cm buffer solution
compECsolution = 1.413*(1.0+0.0185*(this->_temperature-25.0)); //temperature compensation
}else if((this->_rawEC>9)&&(this->_rawEC<16.8)){ //recognize 12.88ms/cm buffer solution
compECsolution = 12.88*(1.0+0.0185*(this->_temperature-25.0)); //temperature compensation
}else{
Serial.print(F(">>>Buffer Solution Error Try Again<<< "));
ecCalibrationFinish = 0;
}
KValueTemp = RES2*ECREF*compECsolution/1000.0/this->_voltage; //calibrate the k value
if((KValueTemp>0.5) && (KValueTemp<1.5)){
Serial.println();
Serial.print(F(">>>Successful,K:"));
Serial.print(KValueTemp);
Serial.println(F(", Send EXITEC to Save and Exit<<<"));
if((this->_rawEC>0.9)&&(this->_rawEC<1.9)){
this->_kvalueLow = KValueTemp;
}else if((this->_rawEC>9)&&(this->_rawEC<16.8)){
this->_kvalueHigh = KValueTemp;
}
ecCalibrationFinish = 1;
}
else{
Serial.println();
Serial.println(F(">>>Failed,Try Again<<<"));
Serial.println();
ecCalibrationFinish = 0;
}
}
break;
case 3:
if(enterCalibrationFlag){
Serial.println();
if(ecCalibrationFinish){
if((this->_rawEC>0.9)&&(this->_rawEC<1.9)){
EEPROM_write(KVALUEADDR, this->_kvalueLow);
}else if((this->_rawEC>9)&&(this->_rawEC<16.8)){
EEPROM_write(KVALUEADDR+4, this->_kvalueHigh);
}
Serial.print(F(">>>Calibration Successful"));
}else{
Serial.print(F(">>>Calibration Failed"));
}
Serial.println(F(",Exit EC Calibration Mode<<<"));
Serial.println();
ecCalibrationFinish = 0;
enterCalibrationFlag = 0;
}
break;
}
}
header datei
/*
* file DFRobot_EC.h * @ https://github.com/DFRobot/DFRobot_EC
*
* Arduino library for Gravity: Analog Electrical Conductivity Sensor / Meter Kit V2 (K=1), SKU: DFR0300
*
* Copyright [DFRobot](http://www.dfrobot.com), 2018
* Copyright GNU Lesser General Public License
*
* version V1.01
* date 2018-06
*/
#ifndef _DFROBOT_EC_H_
#define _DFROBOT_EC_H_
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#define ReceivedBufferLength 10 //length of the Serial CMD buffer
class DFRobot_EC
{
public:
DFRobot_EC();
~DFRobot_EC();
void calibration(float voltage, float temperature,char* cmd); //calibration by Serial CMD
void calibration(float voltage, float temperature); //calibration by Serial CMD
float readEC(float voltage, float temperature); // voltage to EC value, with temperature compensation
void begin(); //initialization
private:
float _ecvalue;
float _kvalue;
float _kvalueLow;
float _kvalueHigh;
float _voltage;
float _temperature;
float _rawEC;
char _cmdReceivedBuffer[ReceivedBufferLength]; //store the Serial CMD
byte _cmdReceivedBufferIndex;
private:
boolean cmdSerialDataAvailable();
void ecCalibration(byte mode); // calibration process, wirte key parameters to EEPROM
byte cmdParse(const char* cmd);
byte cmdParse();
char* strupr(char* str);
};
#endif
wenn ich das ganze über modbus sende
Mb.MbData[5] = ecValue * 10; // EC Wert
bekomme ich auf der SPS den Rohwert wo er dann weiter bearbeitet wird und als ist Wert an die Visualisirung gesendet wird.
nun noch der gesammte Baustein wie es in der SPS verarbeitet wird.
FUNCTION_BLOCK EC { altName := "Salzmenge"; vNameAlignment := "top"; width := 400; bgColor := "green"; }
VAR_INPUT
Leitwert : Word := 0; //ms/cm Leitwert / cm
BeckenTemp : REAL := 0; // Becken ist Temperatur
Z_EN : BOOL := FALSE; // Elektrolyse Zelle enable/false
END_VAR
VAR_OUTPUT
salzgehalt : WORD := 0; // Salzgehalt was an den RPI gesendet wird
salz_high : BOOL:= FALSE; // Salzgehalt überschritten, Zelle abschalten
salz_low : BOOL:= FALSE; // Salzgehalt unterschritten Zelle abschalten
zelle_EN : BOOL:= FALSE; // Zelle auschalten
Leitwert_EC : WORD:= 0; // Leitwert an den RPI senden
END_VAR
VAR_EXTERNAL
Mout_Elektrolyse : BOOL; // externe Variable ob Zelle ein oder ausgeschaltet ist
END_VAR
VAR
r_salzgehalt : REAL:=0;
r_Leitwert : REAL:=0;
A1 : REAL;
A2 : REAL;
A3 : REAL;
SF : REAL := 553;
END_VAR
salzgehalt := TO_WORD (r_salzgehalt*10.0);
r_Leitwert := TO_REAL (Leitwert)/10.0;
Leitwert_EC := TO_WORD (r_Leitwert*10.0);
zelle_EN := Z_EN; // noch nicht berücksichtigt
if (BeckenTemp <= 10)then // Angabe in °C
A1:= -0.044532198;
A2:= -0.013174538;
A3:= 1.085694313;
else
A1:= -0.073894632;
A2:= -0.010947644;
A3:= 1.09173096;
end_if;
r_salzgehalt := expt( IN1 := 10, IN2:= (A1 + BeckenTemp * A2 + A3 * log( in:= ABS( in:= r_Leitwert) ) ));
r_salzgehalt := r_salzgehalt * SF/1000;
IF (r_salzgehalt >= 4.9)THEN
salz_high:= TRUE;
ELSE
salz_high:= FALSE;
END_IF;
IF (r_salzgehalt<=2.1)THEN
salz_low:=TRUE;
ELSE
salz_low:= FALSE;
END_IF;
END_FUNCTION_BLOCK
ich hoffe du kannst dir damit ein bild machen
wie gesagt ich sende den EC wert was auch bei der SPS ankommt, auch der Arduino zeigt diesen Wert richtig an, nur der Arduino weigert sich den Salzgehalt anzuzeigen.