Tx and Rx communication for mega 2560

I am working on a project using Arduino Mega 2560. I have an oxygen monitor module. I have successfully been able to receive data from analog outputs. Now i want to get data digitally but it uses tx and rx for communication. Can someone help me with this? I've not been able to write a code for this. Which library do i use?

OCS-3F 2.1data sheet.pdf (598 KB)

You don't need a library as serial communications is part of the Arduino core functionality

Connect the device to the Serial1 pins on the Mega (18 and 19) with Tx from the device going to Rx on the Mega and vice versa

Then

void setup()
{
  Serial.begin(115200);
  Serial1.begin(9600);
}

void loop()
{
  if (Serial1.available())
  {
    Serial.println(Serial1.read());
  }
}

should display the incoming data on the Serial monitor. Don't forget to set the Serial monitor baud rate to 115200

The code in Reply #1 will show the bytes in the data on the Serial Monitor. However it seems the data is sent in binary form so the raw byte values may not make sense.

The following code is a small adaptation of a suggestion I made in another Post a few days ago. By copying the received data to a struct it gets "parsed" automatically.

      // define the stuct at the top pf the program
struct MyDataStruct {
    byte ack;
    byte lb;
    byte cmd;
    int concent;
    int flow;
    int temp; // I don't know the correct name
    byte st1;
    byte st2;
    byte crc;
};

MyDataStruct myData;
byte myDataLen = sizeof(myData);
byte* mdata = reinterpret_cast<byte*>(&myData); 


         // this code to transfer the data to the struct goes into loop
if (Serial1.available() >= myDataLen) {
    for (byte n = 0; n < myDataLen; n++) {
        *(mdata + n) = Serial1.read();
    }
        // make sure the serial buffer is empty
    while (Serial1.available() > 0) {
        byte dumpByte = Serial1.read();
    }
}

        // example of how to view a value on the Serial Monitor
Serial.println(myData.concent);

...R

EDIT 29 Oct 2020 to insert "byte" before "myDataLen = sizeof(myData);"

Hi robin2. I was actually getting garbage values. Can you help me with this- "// define the stuct at the top pf the program"
I got one doubt. The RXD pin on the module goes to RX1 and TXD pin goes to TX1. Is that correct?

The RXD pin on the module goes to RX1 and TXD pin goes to TX1. Is that correct?

Sounds like the wrong way round

A byte transmitted by the device need to be received by the Arduino and vice versa hence my suggested use of pins in reply #1

Connect the device to the Serial1 pins on the Mega (18 and 19) with Tx from the device going to Rx on the Mega and vice versa

bonyl:
Can you help me with this- "// define the stuct at the top pf the program"
[/quote]
It will be much easier to help if you post the program that represents your best attempt and tell us in detail what it actually does and what you want it to do that is different. That way we can focus on the parts you need help with rather than wasting time on things that you can do.

...R

When i compile, it says myDataLen was not declared in this scope. What goes in the void setup() ?
I have attached the error photo.

PFA

Please follow the advice on posting a programming question given in Read this before posting a programming question

In particular note the advice to Auto format code in the IDE and to use code tags when posting code here as it prevents some combinations of characters in code being interpreted as HTML commands such as italics, bold or a smiley character, all of which render the code useless

My mistake. It should be

byte myDataLen = sizeof(myData);

I will correct the earlier Reply.

...R

PS ... please don't post pictures of programs. Just post the program as text.

Hi Robin, this code is giving me random values.
Let me just explain what I'm trying to do here. I am working on building an oxygen concentrator. The compressed air is passed through a molecular sieve and the nitrogen in the air is trapped and only oxygen is allowed to pass. Now i want to check the purity of the oxygen in real time with the help of this oxygen monitor module. I have attached the datasheet in previous reply. This sensor measures both flow (Litres per minute) and oxygen (Percentage). I tested these values in analog form and they are proper. Now i want to get it digitally.
Can i get both flow and oxygen level with TX1 and RX1 pins.
If yes, how do i do it?
I am a PLC programmer and a noob in scripting and communication :cold_sweat: Please help.

struct MyDataStruct {
    byte ack;
    byte lb;
    byte cmd;
    int concent;
    int flow;
    int temp; // I don't know the correct name
    byte st1;
    byte st2;
    byte crc;
};
MyDataStruct myData;
byte myDataLen = sizeof(myData);
byte* mdata = reinterpret_cast<byte*>(&myData);

void setup(){  // define the stuct at the top pf the program
Serial.begin(9600);
Serial1.begin(9600);
}

void loop(){
         // this code to transfer the data to the struct goes into loop
if (Serial1.available() >= myDataLen) {
    for (byte n = 0; n < myDataLen; n++) {
        *(mdata + n) = Serial1.read();
    }
        // make sure the serial buffer is empty
    while (Serial1.available() > 0) {
        byte dumpByte = Serial1.read();
    }
}
        // example of how to view a value on the Serial Monitor
Serial.println(myData.concent);
}

bonyl:
Hi Robin, this code is giving me random values.

You are printing values to the Serial monitor without any regard for whether a new message has been received from the oxygen module. When I suggested the code in Reply #2 I had assumed you would adapt the idea into a program of your own.

Try this version.

struct MyDataStruct {
    byte ack;
    byte lb;
    byte cmd;
    int concent;
    int flow;
    int temp; // I don't know the correct name
    byte st1;
    byte st2;
    byte crc;
};
MyDataStruct myData;
byte myDataLen = sizeof(myData);
byte* mdata = reinterpret_cast<byte*>(&myData);

bool newData = false;

void setup(){  // define the stuct at the top pf the program
Serial.begin(9600);
Serial1.begin(9600);
}

void loop(){
         // this code to transfer the data to the struct goes into loop
if (Serial1.available() >= myDataLen) {
    for (byte n = 0; n < myDataLen; n++) {
        *(mdata + n) = Serial1.read();
    }
        // make sure the serial buffer is empty
    while (Serial1.available() > 0) {
        byte dumpByte = Serial1.read();
    }
    newData = true;
}

  if (newData == true) {
        // example of how to view a value on the Serial Monitor
    Serial.println(myData.concent);
    newData = false;
  }
    
}

...R

Thank you Robin. I tried the new version. But i'm getting the values as attached. What can be the problem? Will both the values (flow and O2) be shown together?

bonyl:
But i'm getting the values as attached. What can be the problem?

I don't know and as I don't have your equipment I can't carry out tests.

Maybe my struct design is not correct.

...R

Can you still help me? Maybe if you go through the datasheet, you could direct me... or anyone else?
Thanks in advance

Robin2:
Maybe my struct design is not correct.

struct MyDataStruct {
    byte ack;
    byte lb;
    byte cmd;
    int concent;
    int flow;
    int temp; // I don't know the correct name
    byte st1;
    byte st2;
    byte crc;
};

An AVR processor is Little Little Endian. Data from the sensor comes in Big Endian:

gfvalvo:
An AVR processor is Little Little Endian. Data from the sensor comes in Big Endian:

Then it would be better to receive the complete message as a series of bytes and subsequently reconstruct the ints the correct way round.

Or maybe receive the message into my struct and subsequently swap the bytes at the int positions.

...R

Robin2:
Then it would be better to receive the complete message as a series of bytes and subsequently reconstruct the ints the correct way round.

Or maybe receive the message into my struct and subsequently swap the bytes at the int positions.

I'd go with the former method. Given that there's a defined packet rate (once every 500ms), framing bytes, and a checksum, it's a simple matter to determine that you've captured a valid, properly-aligned packet.

Then, use bitwise operations to correctly place the high/low bytes into the variables.

Also, use a proper data type (i.e. uint16_t) instead of plane old 'int'. I always worry there will be some implementation-dependent funniness when doing bit shifts on signed data types.

The above technique ensure that the code is processor and implementation independent.

gfvalvo:
Then, use bitwise operations to correctly place the high/low bytes into the variables.

AFAIK the bits are the correct order - it's only the two bytes that need to be swapped.

...R

Robin2:
AFAIK the bits are the correct order - it's only the two bytes that need to be swapped.

By "bitwise operations" I meant:

uint16_t var = ((uint16_t) highByte) << 8 | lowByte;