Modbus slave & DS18B20?

Projecten die niet passen in bovenstaande onderwerpen
Berichten: 22
Geregistreerd: 13 Aug 2018, 17:59
Woonplaats: Krimpen

Modbus slave & DS18B20?

Berichtdoor swets » 28 Apr 2020, 15:54

Ik heb de onderstaande code...

Ik wil een Arduino mega laten praten via modbus tcp/ip met een Schneider PLC...

en eigenlijk heb ik het al heel ver aan de gang....

als je in het programma kijk zie je staan : celsius=300;

dit getal krijg ik via modbus binnen op mijn PLC.... temperatuur is dan 300/16=18.75....

en als ik via de serial monitor kijk zie ik dat me DS18B20 het ook doet... maar zodra ik ze aan elkaar hang, krijg ik geen data meer binnen in me PLC...
(dus als ik van celsius=300; commentaar maakt, en die ReadTemp() aanzet )

zal wel iets te maken hebben dat hij te lang in die DS18B20 lus blijf hangen ofzo?

maar hoe los ik zo iets op?

Code: Alles selecteren

#include <SPI.h>
#include <Ethernet.h>
#include "MgsModbus.h"
#include <OneWire.h>

MgsModbus Mb;
int inByte = 0; // incoming serial byte

// Ethernet settings (depending on MAC and Local network)
byte mac[] = {0x90, 0xA2, 0xDA, 0x0E, 0x94, 0xB5 };
IPAddress ip(192, 168, 3, 175);
IPAddress gateway(192, 168, 3, 100);
IPAddress subnet(255, 255, 255, 0);

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)

byte j;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
int celsius;
byte HighByte;
byte LowByte;

void setup()
{
  // serial setup
  Serial.begin(9600);
  Serial.println("Serial interface started");

  // initialize the ethernet device
  Ethernet.begin(mac, ip, gateway, subnet);   // start etehrnet interface
  Serial.println("Ethernet interface started");

  // print your local IP address:
  Serial.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    // print the value of each byte of the IP address:
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print(".");
  }
  Serial.println();

  // Fill MbData
  //  Mb.SetBit(0,false);
  Mb.MbData[0] = 0;
  Mb.MbData[1] = 0;
  Mb.MbData[2] = 0;
  Mb.MbData[3] = 0;
  Mb.MbData[4] = 0;
  Mb.MbData[5] = 0;
  Mb.MbData[6] = 0;
  Mb.MbData[7] = 0;
  Mb.MbData[8] = 0;
  Mb.MbData[9] = 0;
  Mb.MbData[10] = 0;
  Mb.MbData[11] = 0;

  // print MbData
  for (int i = 0; i < 12; i++) {
    Serial.print("address: "); Serial.print(i); Serial.print("Data: "); Serial.println(Mb.MbData[i]);
  }
  // print menu
  Serial.println("0 - print the first 12 words of the MbData space");
  Serial.println("1 - fill MbData with 0x0000 hex");
  Serial.println("2 - fill MbData with 0xFFFF hex");
  Serial.println("3 - fill MbData with 0x5555 hex");
  Serial.println("4 - fill MbData with 0xAAAA hex");
}

void loop()
{

  if (Serial.available() > 0) {
    // get incoming byte:
    inByte = Serial.read();
    if (inByte == '0') {                                          // print MbData
      for (int i = 0; i < 12; i++) {
        Serial.print("address: "); Serial.print(i); Serial.print("Data: "); Serial.println(Mb.MbData[i]);
      }
    }
    if (inByte == '1') {
      for (int i = 0; i < 12; i++) {
        Mb.MbData[i] = 0x0000;
      }
    }
    if (inByte == '2') {
      for (int i = 0; i < 12; i++) {
        Mb.MbData[i] = 0xFFFF;
      }
    }
    if (inByte == '3') {
      for (int i = 0; i < 12; i++) {
        Mb.MbData[i] = 0x5555;
      }
    }
    if (inByte == '4') {
      for (int i = 0; i < 12; i++) {
        Mb.MbData[i] = 0xAAAA;
      }
    }
  }

  //ReadTemp();
celsius=300;

Serial.println(celsius);

  LowByte = celsius / 256;
  HighByte = celsius % 256;

  Mb.MbData[0] = LowByte;
  Mb.MbData[1] = HighByte;
  Mb.MbsRun();
}

void ReadTemp()
{
  addr[0] = 0x28;
  addr[1] = 0xFF;
  addr[2] = 0x57;
  addr[3] = 0x9A;
  addr[4] = 0x21;
  addr[5] = 0x17;
  addr[6] = 0x03;
  addr[7] = 0x29;

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end

  //delay(750);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE);         // Read Scratchpad

  for ( j = 0; j < 9; j++) {           // we need 9 bytes
    data[j] = ds.read();
  }

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = raw ;
}

Advertisement

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Modbus slave & DS18B20?

Berichtdoor Koepel » 28 Apr 2020, 16:35

Wanneer ik jouw sketch vergelijk met dit voorbeeld: https://github.com/PaulStoffregen/OneWire/blob/master/examples/DS18x20_Temperature/DS18x20_Temperature.pde.
dan ontbreekt er een delay van 1 seconde.

Berichten: 22
Geregistreerd: 13 Aug 2018, 17:59
Woonplaats: Krimpen

Re: Modbus slave & DS18B20?

Berichtdoor swets » 28 Apr 2020, 20:17

ja... die had ik er ff uitgehaald.... maar ook met die er in werkt het niet....

het uitlezen van de ds18B20 werkt wel.....

en ook de modbus communicatie werkt...

alleen niet tegelijk....

misschien moet ik dat modbus verhaaltje via een tijd interrupt ofzo aan roepen....

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: Modbus slave & DS18B20?

Berichtdoor Koepel » 28 Apr 2020, 20:39

Die delay van 1 seconde hoort er in. Het is niet iets dat je zomaar weg kunt halen.

De OneWire library zet de interrupts uit om het timing protocol te kunnen doen.

Ik weet niet welke ModBus library je gebruikt.
Misschien stuurt die vaak en snel gegevens heen en weer.

Een Ethernet Shield heeft meestal een W5100, W5200 of W5500. Die hebben een grote buffer in de chip. Voor een webpagina is dat handig.
Als de OneWire bezig is (en zelfs nog de interrupts uit zet) en dan nog de delay van 1 seconde, dan reageert de Arduino even niet.

Waarom pin 10 voor de 1-Wire bus ? Dat is de ChipSelect voor de SPI bus op een Uno board. Misschien is die verbonden met je Ethernet Shield op de een of andere vage manier. Probeer eens pin 2 of A0 of zo iets.

Ik zie verder op het eerste gezicht geen bug in de sketch.

Als niemand het probleem ziet, dan kun je deze weg verlaten en een andere weg inslaan. Bijvoorbeeld rigoureus de DS18B20 er uit gooien. Weg er mee. Er zijn I2C sensors die ook nauwkeurig de temperatuur kunnen meten. Dan kan er niet een lange draad aan en de module moet geschikt zijn voor een 5V I2C bus. De Arduino Mega 2560 is het enige board dat 10k pullup resistors op de SDA en SCL heeft naar 5V. Dat voldoende om een sensor van 3.3V stuk te maken.

Berichten: 22
Geregistreerd: 13 Aug 2018, 17:59
Woonplaats: Krimpen

Re: Modbus slave & DS18B20?

Berichtdoor swets » 29 Apr 2020, 08:38

hij werkt nu...
ja snap ik dat die delay er in moet.... maar ik wilde kijken of de modbus dan wel ging praten....

maar nu roep ik de modus aan met een timer interrupt, en nu gaat het wel goed....

die modbus moet wel om de zoveel tijd ff antwoord geven aan de plc....
dus nu roep ik om de halve sec die MODbus routine aan.... en nu gaat het dus goed....

ik zie temperatuur in me PLC...

en waarom deze componenten.... ja die had ik liggen... :-) en ik heb weinig te doen... dus ik dacht zal een gaan spelen met modbus....
Ik ben PLC programmeur... dus veel bezig met allerlei bussen en communicatie... en dacht ga eens kijken of ik dit aan de gang krijg...

we gaan dit toch nooit in het echt gebruiken.... mij baas is niet zo op dat zelfbouwspul....
wilde alleen kijken of het ging.... en dat je dan klaar ben voor een paar euro, waar je in de industrie vele euro's voor betaal....

code zou nog een stuk korter kennen.... zit nog veel test spul in.... main loop is eigenlijk de DS18B20, en via de timer intterupt het modbus verhaaltje... en ik verzent nu nog 12 bytes, maar dat zounder er 2 kunnen worden... maar het werkt....

Toch bedankt !!!!


Code: Alles selecteren

#include <SPI.h>
#include <Ethernet.h>
#include "MgsModbus.h"
#include <OneWire.h>
#include <TimerOne.h>

MgsModbus Mb;
int inByte = 0; // incoming serial byte

// Ethernet settings (depending on MAC and Local network)
byte mac[] = {0x90, 0xA2, 0xDA, 0x0E, 0x94, 0xB5 };
IPAddress ip(192, 168, 3, 175);
IPAddress gateway(192, 168, 3, 100);
IPAddress subnet(255, 255, 255, 0);

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)

byte j;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
int celsius;
byte HighByte;
byte LowByte;

void timerIsr()
{
 
    Mb.MbData[0] = LowByte;
  Mb.MbData[1] = HighByte;
  Mb.MbsRun();
}

void setup()
{
  // serial setup
  Serial.begin(9600);
  Serial.println("Serial interface started");

  Timer1.initialize(500000); // set a timer of length 100000 microseconds (or 0.1 sec - or 10Hz => the led will blink 5 times, 5 cycles of on-and-off, per second)
  Timer1.attachInterrupt( timerIsr ); // attach the service routine here

  // initialize the ethernet device
  Ethernet.begin(mac, ip, gateway, subnet);   // start etehrnet interface
  Serial.println("Ethernet interface started");

  // print your local IP address:
  Serial.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    // print the value of each byte of the IP address:
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print(".");
  }
  Serial.println();

  // Fill MbData
  Mb.MbData[0] = 0;
  Mb.MbData[1] = 0;
  Mb.MbData[2] = 0;
  Mb.MbData[3] = 0;
  Mb.MbData[4] = 0;
  Mb.MbData[5] = 0;
  Mb.MbData[6] = 0;
  Mb.MbData[7] = 0;
  Mb.MbData[8] = 0;
  Mb.MbData[9] = 0;
  Mb.MbData[10] = 0;
  Mb.MbData[11] = 0;

  // print MbData
  for (int i = 0; i < 12; i++) {
    Serial.print("address: "); Serial.print(i); Serial.print("Data: "); Serial.println(Mb.MbData[i]);
  }
  // print menu
  Serial.println("0 - print the first 12 words of the MbData space");
  Serial.println("1 - fill MbData with 0x0000 hex");
  Serial.println("2 - fill MbData with 0xFFFF hex");
  Serial.println("3 - fill MbData with 0x5555 hex");
  Serial.println("4 - fill MbData with 0xAAAA hex");
}

void loop()
{
  if (Serial.available() > 0) {
    // get incoming byte:
    inByte = Serial.read();
    if (inByte == '0') {                                          // print MbData
      for (int i = 0; i < 12; i++) {
        Serial.print("address: "); Serial.print(i); Serial.print("Data: "); Serial.println(Mb.MbData[i]);
      }
    }
    if (inByte == '1') {
      for (int i = 0; i < 12; i++) {
        Mb.MbData[i] = 0x0000;
      }
    }
    if (inByte == '2') {
      for (int i = 0; i < 12; i++) {
        Mb.MbData[i] = 0xFFFF;
      }
    }
    if (inByte == '3') {
      for (int i = 0; i < 12; i++) {
        Mb.MbData[i] = 0x5555;
      }
    }
    if (inByte == '4') {
      for (int i = 0; i < 12; i++) {
        Mb.MbData[i] = 0xAAAA;
      }
    }
  }

  addr[0] = 0x28;
  addr[1] = 0xFF;
  addr[2] = 0x57;
  addr[3] = 0x9A;
  addr[4] = 0x21;
  addr[5] = 0x17;
  addr[6] = 0x03;
  addr[7] = 0x29;

  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end

  delay(750);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE);         // Read Scratchpad

  for ( j = 0; j < 9; j++) {           // we need 9 bytes
    data[j] = ds.read();
  }

  // Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = raw ;
  LowByte = celsius / 256;
  HighByte = celsius % 256;


}

Berichten: 22
Geregistreerd: 13 Aug 2018, 17:59
Woonplaats: Krimpen

Re: Modbus slave & DS18B20?

Berichtdoor swets » 06 Mei 2020, 15:59

zomaar nog een modbus vraag.....

ik stuur vrij veel informatie tussen mijn plc en HMI heen en weer...

als ik nu een arduino met een ethernet module op het zelfde netwerk zet.... moet ik toch ook gewoon die modus variabele kunnen lezen...

Ik heb nog een tft schermpje....
dan moet ik toch zo waarde op het schermpje kunnen laten zien?

iemand daar wel eens mee gespeeld?

Terug naar Overige projecten

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 17 gasten