Arduino OPC (st4makers) problem with floats

Hello i am using arduino opc from https://www.st4makers.com/.

At first i was using a serial connection from my pc to the arduino , connected the Reliance 4 scada with the opc server running , and the sensor data were appearing just fine.

However recently i purchased an arduino mega and an ethernet shield, i changed my arduino program to work with ethernet instead of serial, and now my float values appear as integers on the scada.

For example a sensor value of 25.35 degrees appear as 2535.

Does anyone know why this is happening?

here is my code i cut some pieces of code because it doesnt fit in the post.

#include <OPC.h>
#include <Bridge.h>
#include <Ethernet.h>
#include <SPI.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 9                                   //change was 11
#include <Wire.h>
#include "RTClib.h"
RTC_PCF8523 rtc;

#include <RS485_non_blocking.h>
#include <SoftwareSerial.h>
byte ENABLE_PIN = 4;
//const byte LED_PIN = 13;
static constexpr auto CONNECTION_LOSS_THRESHOLD_MS = 5000u;   //RS485 Timeout
static unsigned long last_message_received = millis();
int Distance;

SoftwareSerial mySerial(2, 3); // RX, TX

byte buf [20];
int fAvailable () {
  return mySerial.available ();
}

int fRead() {
  return mySerial.read ();
}

RS485 myChannel (fRead, fAvailable, NULL, 20);



OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress tempDeviceAddress = { 0x28, 0xCB, 0x30, 0x56, 0x05, 0x00, 0x00, 0x19 };
DeviceAddress tempDeviceAddress1 = { 0x28, 0xFF, 0x76, 0x1C, 0x3E, 0x04, 0x00, 0x82 };
DeviceAddress tempDeviceAddress2 = { 0x28, 0xFF, 0x29, 0x05, 0x3A, 0x04, 0x00, 0x4D };



int Hour;
int Minute;
int Second;
int distance = 0;
int  precision = 12;
int relayPin = 8;                 //change was 12
int lightvalue;
int timervalue;
int TemperatureValue;
int  idle = 0;
int timercheck = 0;
int  delayInMillis = 0;
float T1 = 0.0;
float T2Out = 0.0;
float TBoiler = 0.0;
bool TimedAutomate = 0;
bool PresetAutomate = 0;
bool InsideTempError = 0;
bool OutsideTempError = 0;
bool BoilerTempError = 0;
bool UltrasonicError = 0;
bool CommsError = 0;
bool relaystatus = 0;
unsigned long lastTempRequest = 0;
const int pResistor = A0; // Photoresistor at Arduino analog pin A0
long int timer;
const char servo1[] = "servo1";



OPCEthernet aOPCEthernet;

byte mac[] = { 0x90, 0xAA, 0xDA, 0xBE, 0xAD, 0x8D };

/*
 * Set your network configuration
 */
IPAddress ip(192, 168, 1, 20);
IPAddress gateway(192,168,1,1);
IPAddress dns_server(192,168,1,1);
IPAddress subnet(255,255,255,0);

/*
 * Server listen port
 */
const int listen_port = 80;


int Photoresistor1(const char *itemID, const opcOperation opcOP, const int value) {                               //Photoresistor OPC
  return analogRead(pResistor);
}

float t_1(const char *itemID, const opcOperation opcOP, const float value) {                                      //Temperature OPC
  
 
  
  return T1;
}

float t_2(const char *itemID, const opcOperation opcOP, const float value) {                                      //Temperature OPC

 
 
  return T2Out;
}

float t_3(const char *itemID, const opcOperation opcOP, const float value) {                                      //Temperature OPC
  return TBoiler;
}


int RTC_Hour(const char *itemID, const opcOperation opcOP, const int value) {                                     //OPC TIME HOUR
  return Hour;
}

int RTC_Minute(const char *itemID, const opcOperation opcOP, const int value) {                                   //OPC TIME MINUTE
  return Minute;
}

int RTC_Second(const char *itemID, const opcOperation opcOP, const int value) {                                   //OPC TIME SECOND
  return Second;
}

int Ultrasonic(const char *itemID, const opcOperation opcOP, const int value) {                                   //ULTRASONIC
  return Distance;
}


int Timerset(const char *itemID, const opcOperation opcOP, const int value) {                                     //Set Timer OPC
  if (opcOP == opc_opwrite) {
    timervalue = 60 * value;
  }
  return timervalue / 60;
}

int SetTemperature(const char *itemID, const opcOperation opcOP, const int value) {                                     //Set Timer OPC
  if (opcOP == opc_opwrite) {
    TemperatureValue = value;
  }
  return TemperatureValue;
}

bool Relay(const char *itemID, const opcOperation opcOP, const bool value) {                                      //Relay on/off OPC
  if (opcOP == opc_opwrite) {
    relaystatus = value;

    if (relaystatus)

      digitalWrite(relayPin, HIGH);

    else
      digitalWrite(relayPin, LOW);
  }
  else
    return relaystatus;
}

bool TimedAutomation(const char *itemID, const opcOperation opcOP, const bool value) {                                 //Automation Timer OPC
  if (opcOP == opc_opwrite) {
    TimedAutomate = value;
  }
  return TimedAutomate;
}

bool PresetAutomation(const char *itemID, const opcOperation opcOP, const bool value) {                                 //Automation Timer OPC
  if (opcOP == opc_opwrite) {
    PresetAutomate = value;
  }
  return PresetAutomate;
}



void setup(void)                                                                                                  //SETUP
{

  Serial.begin(9600);
  mySerial.begin(9600);
  myChannel.begin();
  pinMode (ENABLE_PIN, OUTPUT);  // driver output enable
  //pinMode (LED_PIN, OUTPUT);  // built-in LED
  aOPCEthernet.setup(listen_port,mac,ip);  

  rtc.begin();



  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));






  pinMode(relayPin, OUTPUT);
  pinMode(pResistor, INPUT);// Set pResistor - A0 pin as an input (optional)


  sensors.begin();

  sensors.setResolution(tempDeviceAddress, precision);
  sensors.setResolution(tempDeviceAddress1, precision);
  sensors.setResolution(tempDeviceAddress2, precision);
  sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  delayInMillis = 1000 / (1 << (12 - precision));        //scary? :)


  lastTempRequest = millis();


  aOPCEthernet.addItem("InsideTemp", opc_read, opc_float, t_1);
  aOPCEthernet.addItem("OutsideTemp", opc_read, opc_float, t_2);
  aOPCEthernet.addItem("BoilerTemp", opc_read, opc_float, t_3);
 aOPCEthernet.addItem("TimedAutomation", opc_readwrite, opc_bool, TimedAutomation);
  aOPCEthernet.addItem("PresetAutomation", opc_readwrite, opc_bool, PresetAutomation);
  aOPCEthernet.addItem("SetPresetTemperature", opc_readwrite, opc_int, SetTemperature);
  aOPCEthernet.addItem("SetTimer", opc_readwrite, opc_int, Timerset);
  aOPCEthernet.addItem("RelayControl", opc_readwrite, opc_bool, Relay);
  aOPCEthernet.addItem("LightSensor", opc_read, opc_int, Photoresistor1);
  aOPCEthernet.addItem("SetTimer", opc_readwrite, opc_int, Timerset);
  aOPCEthernet.addItem("Ultrasonic", opc_read, opc_int, Ultrasonic);
  aOPCEthernet.addItem("RTCHour", opc_read, opc_int, RTC_Hour);
  aOPCEthernet.addItem("RTCMinute", opc_read, opc_int, RTC_Minute);
  aOPCEthernet.addItem("RTCSecond", opc_read, opc_int, RTC_Second);
}

void loop(void)

{
  aOPCEthernet.processOPCCommands();

  DateTime now = rtc.now();

  Hour = now.hour();
  Minute = now.minute();
  Second = now.second();

  lightvalue = analogRead(pResistor);








  if (TimedAutomate == 1 && PresetAutomate==0)
  {
    TimedAutomate = 1;
    if (timercheck == 0)
    {
      DateTime now = rtc.now();
      timer = now.unixtime() + timervalue;
      Serial.println(now.unixtime());
      timercheck = 1;                                                                           //Timed boiler
    }
    if ((now.unixtime() <= timer))
    {
      digitalWrite(relayPin, HIGH);
      relaystatus = 1;
    }

    if ((now.unixtime() >= timer) || TimedAutomate == 0) {

      digitalWrite (relayPin, LOW);
      relaystatus = 0;
      timercheck = 0;
      TimedAutomate = 0;
    }
  }



  if (TimedAutomate == 0 && timercheck == 1)
  {

    relaystatus = 0;
    digitalWrite (relayPin, LOW);
    timercheck = 0;

  }
  

 
    

    

    
  }



  if (millis() - lastTempRequest > delayInMillis) // waited long enough to read sample??
  {

    T1 = sensors.getTempC(tempDeviceAddress);
    T2Out = sensors.getTempC(tempDeviceAddress1);
    TBoiler = sensors.getTempC(tempDeviceAddress2);
    sensors.requestTemperatures();


    lastTempRequest = millis()



  }




}

Thank you!

Does anyone know why this is happening?

You are trying to run Yun code on a Mega. That won't work.

Hello,

I am using the opc library from st4makers.com.

At first i was using an arduino uno and connected it with the usb to a pc that had the opc server, then with a scada (reliance 4) i was able to get the tags and display them, no problems there.

However i decided to make an upgrade to arduino mega and ethernet shield.

After some changes to the code to work with ethernet everything was working ok, but the float value displayed as integers on the scada,

For example a value of 23.35 celcius appeared on the scada as 2335.

Can anyone explain to me what is going on, and why this is happening?

I have stripped some unnecessary parts of the code because its too big for the post:

/*
   PINOUT             ULTRASONIC      9 (TRIGGER)
                                      10 (ECHO)
                      TEMP SENSORS    PIN 11

                      RTC             A4
                                      A5

                                      2 rx
                                      3 tx
                                      4 driver (tr,rx)

*/

#include <OPC.h>
#include <Bridge.h>
#include <Ethernet.h>
#include <SPI.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define ONE_WIRE_BUS 9                                   //change was 11
#include <Wire.h>
#include "RTClib.h"
RTC_PCF8523 rtc;

#include <RS485_non_blocking.h>
#include <SoftwareSerial.h>
byte ENABLE_PIN = 4;
//const byte LED_PIN = 13;
static constexpr auto CONNECTION_LOSS_THRESHOLD_MS = 5000u;   //RS485 Timeout
static unsigned long last_message_received = millis();
int Distance;

SoftwareSerial mySerial(2, 3); // RX, TX

byte buf [20];
int fAvailable () {
  return mySerial.available ();
}

int fRead() {
  return mySerial.read ();
}

RS485 myChannel (fRead, fAvailable, NULL, 20);



OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress tempDeviceAddress = { 0x28, 0xCB, 0x30, 0x56, 0x05, 0x00, 0x00, 0x19 };
DeviceAddress tempDeviceAddress1 = { 0x28, 0xFF, 0x76, 0x1C, 0x3E, 0x04, 0x00, 0x82 };
DeviceAddress tempDeviceAddress2 = { 0x28, 0xFF, 0x29, 0x05, 0x3A, 0x04, 0x00, 0x4D };



int Hour;
int Minute;
int Second;
int distance = 0;
int  precision = 12;
int relayPin = 8;                 //change was 12
int lightvalue;
int timervalue;
int TemperatureValue;
int  idle = 0;
int timercheck = 0;
int  delayInMillis = 0;
float T1 = 0.0;
float T2Out = 0.0;
float TBoiler = 0.0;
bool TimedAutomate = 0;
bool PresetAutomate = 0;
bool InsideTempError = 0;
bool OutsideTempError = 0;
bool BoilerTempError = 0;
bool UltrasonicError = 0;
bool CommsError = 0;
bool relaystatus = 0;
unsigned long lastTempRequest = 0;
const int pResistor = A0; // Photoresistor at Arduino analog pin A0
long int timer;
const char servo1[] = "servo1";



OPCEthernet aOPCEthernet;

byte mac[] = { 0x90, 0xAA, 0xDA, 0xBE, 0xAD, 0x8D };

/*
 * Set your network configuration
 */
IPAddress ip(192, 168, 1, 20);
IPAddress gateway(192,168,1,1);
IPAddress dns_server(192,168,1,1);
IPAddress subnet(255,255,255,0);

/*
 * Server listen port
 */
const int listen_port = 80;


int Photoresistor1(const char *itemID, const opcOperation opcOP, const int value) {                               //Photoresistor OPC
  return analogRead(pResistor);
}

float t_1(const char *itemID, const opcOperation opcOP, const float value) {                                      //Temperature OPC
  
 
  
  return T1;
}

float t_2(const char *itemID, const opcOperation opcOP, const float value) {                                      //Temperature OPC

 
 
  return T2Out;
}

float t_3(const char *itemID, const opcOperation opcOP, const float value) {                                      //Temperature OPC
  return TBoiler;
}


}


void setup(void)                                                                                                  //SETUP
{

  Serial.begin(9600);


  aOPCEthernet.setup(listen_port,mac,ip);  

  rtc.begin();



  rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));






  pinMode(relayPin, OUTPUT);
  pinMode(pResistor, INPUT);// Set pResistor - A0 pin as an input (optional)


  sensors.begin();

  sensors.setResolution(tempDeviceAddress, precision);
  sensors.setResolution(tempDeviceAddress1, precision);
  sensors.setResolution(tempDeviceAddress2, precision);
  sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  delayInMillis = 1000 / (1 << (12 - precision));        //scary? :)


  lastTempRequest = millis();


  aOPCEthernet.addItem("InsideTemp", opc_read, opc_float, t_1);
  aOPCEthernet.addItem("OutsideTemp", opc_read, opc_float, t_2);
  aOPCEthernet.addItem("BoilerTemp", opc_read, opc_float, t_3);

}

void loop(void)

{
  aOPCEthernet.processOPCCommands();



 
    
  }



  if (millis() - lastTempRequest > delayInMillis) // waited long enough to read sample??
  {

    T1 = sensors.getTempC(tempDeviceAddress);
    T2Out = sensors.getTempC(tempDeviceAddress1);
    TBoiler = sensors.getTempC(tempDeviceAddress2);
    sensors.requestTemperatures();


    lastTempRequest = millis();






}

I have stripped some unnecessary parts of the code because its too big for the post:

But you have left in unnecessary bits of code. Bridge is a useless library for anything but a Yun. Get rid of it.

DeviceAddress tempDeviceAddress = { 0x28, 0xCB, 0x30, 0x56, 0x05, 0x00, 0x00, 0x19 };
DeviceAddress tempDeviceAddress1 = { 0x28, 0xFF, 0x76, 0x1C, 0x3E, 0x04, 0x00, 0x82 };
DeviceAddress tempDeviceAddress2 = { 0x28, 0xFF, 0x29, 0x05, 0x3A, 0x04, 0x00, 0x4D };

Do you count that way? Number ALL "related" variables.

  aOPCEthernet.addItem("InsideTemp", opc_read, opc_float, t_1);

That looks like a suspect where the decimal point is being stripped. Post a link to that library.

void loop(void)

{
  aOPCEthernet.processOPCCommands();



 
   
  }



  if (millis() - lastTempRequest > delayInMillis) // waited long enough to read sample??
  {

    T1 = sensors.getTempC(tempDeviceAddress);
    T2Out = sensors.getTempC(tempDeviceAddress1);
    TBoiler = sensors.getTempC(tempDeviceAddress2);

Deal with old data. Then, get new data to deal with. I'll never understand that "logic".

Thanks for your time,

The link below goes to the github of the library, all information are there if you want to look for something specific.

In the examples for the ethernet it used a bridge.h library, so i thought i would use it, i have no problem getting rid of it.

PaulS:

DeviceAddress tempDeviceAddress = { 0x28, 0xCB, 0x30, 0x56, 0x05, 0x00, 0x00, 0x19 };

DeviceAddress tempDeviceAddress1 = { 0x28, 0xFF, 0x76, 0x1C, 0x3E, 0x04, 0x00, 0x82 };
DeviceAddress tempDeviceAddress2 = { 0x28, 0xFF, 0x29, 0x05, 0x3A, 0x04, 0x00, 0x4D };



Do you count that way? Number ALL "related" variables.

Im not sure about what you are asking me here sorry !

PaulS:

void loop(void)

{
  aOPCEthernet.processOPCCommands();

}

if (millis() - lastTempRequest > delayInMillis) // waited long enough to read sample??
  {

T1 = sensors.getTempC(tempDeviceAddress);
    T2Out = sensors.getTempC(tempDeviceAddress1);
    TBoiler = sensors.getTempC(tempDeviceAddress2);



Deal with old data. Then, get new data to deal with. I'll never understand that "logic".

Yes , you are right i might move it at the end

I think I would start with an Ethernet scanner (like WireShark or netcat) to see if the decimal point appears in the Ethernet messages or not. If not, the problem is probably in the OPC library.

FYI:

  delayInMillis = 1000 / (1 << (12 - precision));        //scary? :)

Less scary:

  delayInMillis = sensors.millisToWaitForConversion(precision);

PaulS:
You are trying to run Yun code on a Mega. That won't work.

What do you mean? How do i declare what board do i use? Mind sharing your information please?

theomv:
What do you mean? How do i declare what board do i use? Mind sharing your information please?

The "Bridge" library is for the Yün.
The OPC library puts code for a bunch of platforms (Serial, Ethernet, Yün WiFi and ESP8266 WiFi) all in the same file. I suspect that without some of those unused include files there will be some "file not found" errors or link errors.

Yes this is correct i do get some files not found warning, i didnt know that was from the includes, i am new to this, thanks for the info.

An update for my problem:

I installed reliance 4 scada and opc server on another pc and the values are displayed correctly, with decimal points.

Because the version i downloaded was newer from the pc i originally used, i downloaded the same version to the original pc, but the values still diplayed without decimal points.

So with same opc server version and reliance it still doesnt work.

Any clues?