[gelöst] was mache falsch beim Übertragen von MULTIPLE_REGISTERS

Hallo,

ich versuche Werte aus einzelnen Variablen an die Mb.Data[0]- [2] zu übergeben so das sie als MULTIPLE_REGISTERS in eine SPS geschrieben werden. Dazu nutze ich die MgsModbus.h als Client. Die SPS ist der Sklave.

  Mb.MbData[0] = ph_wert; 
  Mb.MbData[1] = orp_wert;

sobald ich den Variablen Namen eintrage überträgt er nur 0
aber wenn ich schreibe

  Mb.MbData[0] = 1; 
  Mb.MbData[1] = 2;

dann schreibt er den richtigen wert.
Wie stelle ich es an damit er den Inhalt des Variablen Namen übertragen tut? Ich habe ja schon die Adresse und die Anzahl angegeben.

  Mb.Req(MB_FC_WRITE_MULTIPLE_REGISTERS, 21, 2, 0); // 16

ich bin da derzeit noch ein bischen überfragt. habe mir auch andere Beispiele angeschaut aber aus denen werde ich auch nicht schlau da es sich meistens auf den Sklaven bezieht.

Und wir sollen uns jetzt auswürfweln, wie Deine Variablen deklariert sind aund was da drin steht?

Zeige den ganzen Sketch, nimm serielle Ausgaben rein, die Dir den Inhalt Deiner Variablen anzeigen und gib uns Links zu den verwendeten Libs.

Gruß Tommy

Hallo
lasse dir den Inhalt der Variablen mit
Serial.println(ph_wert);
und mit
Serial.println(orp_wert);
zur Kontrolle ausgeben.

hi,
Für alle, die vielleicht den Hintergrund nicht wissen, es gab einen Ursprungsthread, bei dem es ums Grundsätzlcihe mit dem MB ging...
https://forum.arduino.cc/index.php?topic=729727.0
da auch ursprünglicher Code.

später hier:
https://forum.arduino.cc/index.php?topic=729727.msg4909789#msg4909789

luzie:
ich versuche Werte aus einzelnen Variablen an die Mb.Data[0]- [2] zu übergeben so das sie als

Mb.MbData[0] = ph_wert; 

Mb.MbData[1] = orp_wert;



sobald ich den Variablen Namen eintrage überträgt er nur 0
aber wenn ich schreibe


Mb.MbData[0] = 1;
  Mb.MbData[1] = 2;



dann schreibt er den richtigen wert.

Wo übergibst Du die Werte?
Wenn Du die nur im setup eintackerst, sind die var's ph und orp noch nicht belegt - also 0.

Du musst in der switch case

    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);
        }

oder vor dem schreiben der Daten das array befüllen.

          ph = atof(sensordata);
          MbData[0]=ph*10;

HINWEIS: MbData kann nur word aufnehmen. dein ph ist ein float. Darum steht da oben auch *10 im setup, ich habs mit übernommen, dann bekommst Du die Nachkommastelle mit übergeben.

Ich würde mir erstmal auf dem SerMon ausgeben lassen, was in dem Array steht.
Unzwar bei jeder Übergabe an den Bus ein

for (int i = 0; i < 4; i++)
{ 
  Serial.print (Mb.data[i]);
  Serial.println();
}

Hat wer andere Ideen?

die lib habe ich von hier MgsModbus.h

die werte werden im Monitor so ausgegeben


der wert 325.4 steht für orp und 6.561 für ph
diese sind hier deklariert

float ph;
float orp;
int ph_wert = (ph *10.0);
int orp_wert = (orp *10.0);
   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.
    }

ich hoffe das geht so

luzie:
ich hoffe das geht so

Nein.
gib mal Deinen ganzen Sketch.
Ich sehe nicht, wo Du ph ins Mb.data-Array schreibst.

#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;
int ph_wert = (ph *10.0);
int orp_wert = (orp *10.0);
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()
{
  Serial.begin(115220);
  //  Timer1.initialize(100 * 1000); // zeit in microsekunden (1 / 1 000 000) s
  //  Timer1.attachInterrupt(mb);
  Wire.begin();                 // enable I2C port.
  Ethernet.begin(mac, ip);      // start etehrnet interface
  //  slave address
  Mb.remSlaveIP = (192, 168, 178, 114);

  //  Mb.SetBit(0,false);
  Mb.MbData[0] = 1; 
  Mb.MbData[1] = 2;
 // Mb.MbData[2] = 3; // pressure60 /100*4 -5;
 // Mb.MbData[3] = 4; // pressure5 *100 -6800;

  wdt_enable(WDTO_8S); // Watchdog timer alle 8 s ohne timerreset wird das gerät neu gestartet

}
// #define DRAW_DELAY 118
// #define D_NUM 47

int i;

/*
  void mb()
  {

  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.Req(MB_FC_WRITE_MULTIPLE_REGISTERS, 21, 2, 0); // 16

  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;
        case 2: // TODO Calibriere mit ORP 475mV
          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
  }

  pressure60 = getPressure (0, 60, 20);
  pressure5  = getPressure (1, 5, 20);

}


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;
    //  Serial.print("Messung: channel - ");
    //  Serial.print(channel);
    //  Serial.print(" Wert: ");
    //  Serial.println(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;
}

bitte ich habe schon graue haare *g

my_xy_projekt:
hi,
Für alle, die vielleicht den Hintergrund nicht wissen, es gab einen Ursprungsthread, bei dem es ums Grundsätzlcihe mit dem MB ging...

Grundlegend ist ein neuer Thread ein neuer Thread. Wenn der TO nicht zu seinen vorherigen Threads verlinkt (warum fängt er neu an?) muss er eben alle Infos nochmal schicken.
Es kann doch nicht sein, dass wie das Forum durchsuchen, ob es dazu schon mal was gab. Da ist der TO in meinen Augen in der Bringepflicht.

Gruß Tommy

sorry,
ich hatte den letzten schon als gelöst markiert und wusste nicht das ich verlinken kann/muss/sollte.
Wird sicherlich nicht wieder passieren.

aber nun es ist passiert.

luzie:

int ph_wert = (ph *10.0);

int orp_wert = (orp *10.0);

]
Das ist immer 0 und vermenden tusts auch nicht. Also egal.

void setup()
{
  //  Mb.SetBit(0,false);
  Mb.MbData[0] = 1; 
  Mb.MbData[1] = 2;
 // Mb.MbData[2] = 3; // pressure60 /100*4 -5;
 // Mb.MbData[3] = 4; // pressure5 *100 -6800;
}

das ist das, was ich meinte. Wenn Du Hier die Werte setzt ist das nur einmal - danach nie wieder.

Ich habs mal angepappt wie ich meine, das irgendein Sensorwert übergeben wird.

Da diese kack forensoftware mich hier heute nicht mag und nun auch noch meint die Nachricht ist leider zu gross - als Anhang.

luzzi_01.ino (8.06 KB)

Tommy56:
Wenn der TO nicht zu seinen vorherigen Threads verlinkt (warum fängt er neu an?) muss er eben alle Infos nochmal schicken.

Ich leiste Abbitte.
Die Empfehlung kam von mir, weil das Problem als solches (im Ursprungsthema) gelöst war.
Das Timing ist nicht das Problem. Jetzt ist der Inhalt dran.
Und beim nächsten Mal, wenn ich das nicht per PM lösen möchte, werde ich dazu schreiben, das der TO seine Ausgangslage schildert.

Ok werde ich machen. Aber wie kann ich im allgemeinen float oder int werte als word übergeben? So wie bei der SPS funktioniert das hier ja leider nicht.

my_xy_projekt:
Und beim nächsten Mal, wenn ich das nicht per PM lösen möchte, werde ich dazu schreiben, das der TO seine Ausgangslage schildert.

Lösungen per PM widersprechen eigentlich dem Sinn eines Forums, da dann die Allgemeinheit nichts davon hat.

Gruß Tommy

luzie:
Ok werde ich machen. Aber wie kann ich im allgemeinen float oder int werte als word übergeben? So wie bei der SPS funktioniert das hier ja leider nicht.

So wie ich im case das gemacht habe, ist float ph 6,5 als word 65.
Wieviele Nachkommastellen brauchst Du denn?

@Tommy56 - na sind wir uns doch einig.

bisher scheint es nicht zu funktionieren er gibt immer einen wert von 65 bei beiden aus


@tommy56, nein hatter ja auch nicht, solle anfrage im Forum stellen. alles gut

eine nachkomma reicht

luzie:
bisher scheint es nicht zu funktionieren er gibt immer einen wert von 65 bei beiden aus
eine nachkomma reicht

Ich sehe Deine Bilder nicht - häng die bitte hier ran nicht auf externen Bilderhostern - die verschwinden da und keiner weiss, was Du wolltest.

Der 65 er ist ok.
Meine Zeile 171 musst ändern in

Mb.data[1]=orp*10;

das mit dem Bild kann ich nicht anhängen. er fragt immer nach ein URL. :frowning:

das mit dem Mb.data[1] muss ich ändern in Mb.MbData[1].

      case 1:                               // decimal 1  means the command was successful.
        if (channel == 1)
        {
          ph = atof(sensordata);
          Mb.MbData[0]=ph*10.0;
          Serial.print(F("Sensordata / Mb.MbData[0] ist: "));
          Serial.print(sensordata);
          Serial.print("\t");
          Serial.println(Mb.MbData[0]);
          delay(500); // hier macht er 500ms Pause
        } else
        {
          orp = atof(sensordata);
          Mb.MbData[1]=orp*10.0;
          Serial.print(F("Sensordata / Mb.MbData[1] ist: "));
          Serial.print(sensordata);
          Serial.print("\t");
          Serial.println(Mb.MbData[1]);
          delay(500); // hier macht er 500ms Pause

aber nun klappt es auch mit der Übertagung

luzie:
das mit dem Bild kann ich nicht anhängen. er fragt immer nach ein URL. :frowning:

Ja, Du willst oben im editor ein img einfügen.
Mach es mal unten als attachment :wink:

aber nun klappt es auch mit der Übertagung

Hehe...
Also: Jetzt kannst die seriellen Ausgaben da rausnehmen und die delays.
Dann in der SPS nur noch sagen, wieviele Stellen des empfangenen das Nachkomma sind - in diesem Fall eine NK.
Wenn Du mehr brauchst, dann musst *100 machen oder so...

...war ich ja doch auf dem richtigen Dampfer.

ja warste.
Danke für deine Hilfe, nun kommen Sie auch so wie sollen auf der SPS an

sps.PNG

der Umweg war etwas komplieziert gewesen, da ich ein Slave auf einem Raspberry habe einen Slave in der SPS sowie 2 Master in der SPS und einen auf dem Raspberry. Dazu kommt nun noch der Master auf dem Leonardo. Aber zum Glück funktioniert nun das Zusammenspiel von allem.

sps.PNG

luzie:
Danke für deine Hilfe, nun kommen Sie auch so wie sollen auf der SPS an

gerne. war zum Glück nur eine reine Logikfrage...

Aber zum Glück funktioniert nun das Zusammenspiel von allem.

... und gelöst ists auch.
Geht doch...