Hallo.
Ich habe nicht viel Ahnung wenn es um Arduino geht. Ich nutzte diesen Notgedrungen um Analoge werte Auszulesen da dies die SPS selber nicht kann.
Leider Friert der Arduino Leonardo (ETH) immer ein wenn ich das Programm hochlade sobald dieser Modbusbefehl aktiv ist.
// Mb.Req(MB_FC_WRITE_MULTIPLE_REGISTERS, 21,4,0); // 16
wenn ich diesen ausblende tut der Arduino seinen Dienst. Da ich Wasserwerte und druck an eine SPS senden möchte wäre es schon gut wenn der Modbus auch Funktioniert. Aber so geht das leider nicht. Hier noch der ganze Code .
#include "adcHelper.h"
#include <Wire.h>
#include <SPI.h>
#include <Ethernet2.h>
#include "MgsModbus.h"
#include "TimerOne.h"
#include <avr/wdt.h>
float ph;
float orp;
char sensordata[32]; //A 30 byte character array to hold incoming data from the sensors
byte sensor_bytes_received = 0; // We need to know how many characters bytes have been received
byte code = 0; //used to hold the I2C response code.
byte in_char = 0; //used as a 1 byte buffer to store in bound bytes from an I2C stamp.
unsigned int CalMod = 0x0000;
#define TOTAL_CIRCUITS 2 // <-- CHANGE THIS | set how many I2C circuits are attached to the Tentacle shield(s): 2
int channel_ids[] = {98, 99};// <-- CHANGE THIS.
// A list of I2C ids that you set your circuits to.
// This array should have 2 elements (2 circuits connected)
char const*channel_names[] = {"ORP", "PH"}; // <-- CHANGE THIS.
// A list of channel names (must be the same order as in channel_ids[])
// {"ORP","PH"}
/////#define DS_Pin 0x07, 0x08 // Pin wo die Drucksensoren angeschlossen sind
int DS_Pin[] = {0x07,0x08}; // A0, A4
MgsModbus Mb;
// Ethernet settings (depending on MAC and Local network)
byte mac[] = {0x90, 0xA2, 0xDA, 0x0E, 0x94, 0xB5 };
IPAddress ip(192, 168, 178, 13);
int pressure60,pressure5; // pressure60/60psi = A4, pressure5/5psi = A0
float Pbar;
void setup()
{
// slave address
Mb.remSlaveIP = (192,168,178,114);
// Serial.println(Mb.remSlaveIP);
Serial.begin(9600);
Wire.begin(); // enable I2C port.
Ethernet.begin(mac, ip); // start etehrnet interface
Timer1.initialize(10 * 1000); // zeit in microsekunden (1 / 1 000 000) s
Timer1.attachInterrupt(mb);
wdt_enable(WDTO_8S); // Watchdog timer alle 8 s ohne timerreset wird das gerät neu gestartet
// Mb.SetBit(0,false);
Mb.MbData[0] = ph *10.0;
Mb.MbData[1] = orp *10.0*2;
Mb.MbData[2] = pressure60 /100*4 -5;
Mb.MbData[3] = pressure5 *100 -6800;
Mb.MbData[4] = CalMod
}
// #define DRAW_DELAY 118
// #define D_NUM 47
int i;
void mb() {
// Mb.Req(MB_FC_READ_COILS, 0,1,0);
// Mb.Req(MB_FC_WRITE_MULTIPLE_REGISTERS, 21,4,0); // 16
Mb.MbmRun();
}
void writeCommand(int addr ,char *cmd) {
// Normalde Daten auslesen
Wire.beginTransmission(addr); // call the circuit by its ID number.
Wire.write(cmd); // request a reading by sending 'r'
Wire.endTransmission();
delay(1400); // AS circuits need a 1 second before the reading is ready
sensor_bytes_received = 0; // reset data counter
memset(sensordata, 0, sizeof(sensordata)); // clear sensordata array;
Wire.requestFrom(addr, 48, 1); // call the circuit and request 48 bytes (this is more then we need).
code = Wire.read();
while (Wire.available()) { // are there bytes to receive?
in_char = Wire.read(); // receive a byte.
if (in_char == 0) { // null character indicates end of command
Wire.endTransmission(); // end the I2C data transmission.
break; // exit the while loop, we're done here
}
else {
sensordata[sensor_bytes_received] = in_char; // append this byte to the sensor data array.
sensor_bytes_received++;
}
}
Serial.print(code,HEX);
Serial.print(" :=> ");
Serial.println(sensordata);
}
void loop() {
Mb.MbmRun();
if (CalMod != Mb.MbData[4]) {
CalMod = Mb.MbData[4];
switch (CalMod) {
case 1: // TODO Calibriere mit PH 7.00
Serial.println("Calibrierung Mittelwert PH: =7.00 ");
writeCommand(99,"Cal,mid,7.00");
break;
case2: // TODO Calibriere mit ORP 225mV
Serial.println("Calibrierung ORP: =475mV");
writeCommand(98,"Cal,475");
break;
}
}
//Serial.println("loop start");
for (int channel = 0; channel < TOTAL_CIRCUITS; channel++) { // loop through all the sensors
Wire.beginTransmission(channel_ids[channel]); // call the circuit by its ID number.
Wire.write('r'); // request a reading by sending 'r'
Wire.endTransmission(); // end the I2C data transmission.
delay(1000); // AS circuits need a 1 second before the reading is ready
sensor_bytes_received = 0; // reset data counter
memset(sensordata, 0, sizeof(sensordata)); // clear sensordata array;
Wire.requestFrom(channel_ids[channel], 48, 1); // call the circuit and request 48 bytes (this is more then we need).
code = Wire.read();
// Serial.print(":");
while (Wire.available()) { // are there bytes to receive?
in_char = Wire.read(); // receive a byte.
if (in_char == 0) { // null character indicates end of command
Wire.endTransmission(); // end the I2C data transmission.
break; // exit the while loop, we're done here
}
else {
sensordata[sensor_bytes_received] = in_char; // append this byte to the sensor data array.
sensor_bytes_received++;
}
}
switch (code) { // switch case based on what the response code is.
case 1: // decimal 1 means the command was successful.
if (channel == 1) {
ph = atof(sensordata);
} else {
orp = atof(sensordata);
}
Serial.println(sensordata); // print the actual reading
break; // exits the switch case.
case 2: // decimal 2 means the command has failed.
Serial.println("command failed"); // print the error
break; // exits the switch case.
case 254: // decimal 254 means the command has not yet been finished calculating.
Serial.println("circuit not ready"); // print the error
break; // exits the switch case.
case 255: // decimal 255 means there is no further data to send.
Serial.println("no data"); // print the error
break; // exits the switch case.
}
wdt_reset(); // Watchdog timer mit jeden loop durchlauf zurücksetzen, dauert der loop länger als 8s wird neu gestartet
} // for int
pressure60 = getPressure (0,60,20);
pressure5 = getPressure (1,5,20);
} //for loop
int getPressure (int channel, int type, int mittel) {
float vcc, vsensor, result=0,psi,bar;
for (int i = 0; i < mittel; i++) {
vcc = analogReadBG(0x1f); // dummy Read
vcc = 1.1 * 1024 /analogReadBG(0x1e) * 1000; // Bandgab Referenz bestimmen 1.1 V Default
vsensor = (float) analogReadBG(DS_Pin[channel]) * vcc/1024; // Messwert mit korrektem spannungsbeszug
result += vsensor;
}
psi = (float)(result / mittel);
if (psi < 500) { psi = 500; } // 0,5 mV => 0 PSi damit keine negativen drücke angezeigt werden
// Serial.print("Druck in mV: "); Serial.println(psi);
switch (type) {
case 60:
case 5:
psi = (type/4.0 * (psi/1000))*100;
break;
default: // Fehler bei den Parametern
return 0;
}
bar = psi * 0.0689;
Pbar=bar;
Serial.print("Druck Channel "); Serial.print(channel); Serial.print(" in Bar: "); Serial.println(bar/100);
return (int)psi;
}
kann mir da eventuell weiterhelfen um es zu verhindern das er den Durchlauf nur einmal macht und dann einfriert?