Announcement

REXYGEN forum has been moved. This one is closed.
Head over to the new REXYGEN Community Forum at https://forum.rexygen.com.

Looking forward to meeting you there!
 

#1 2016-05-04 01:47:30

coldh2odvr
Member
Registered: 2016-04-18
Posts: 17

BCD data

Now that I've got my RPi reading values from my PLC (awesome) I need to convert them into something useful. The values in the PLC are stored in a mix of HEX and BCD values (common to most HMIs).

Example - I'm reading line pressure via the MTM block from the Modbus Slave as a 16 bit register. The value received is decimal 4633 = binary 0001 0010 0001 1001. In BCD this converts to the actual line pressure of 1219 (each digit is represented by its respective 4 bits).

Is there any easy way to specify or convert bases in Rex? I've been digging but not found anything yet.

Thanks!

Offline

#2 2016-05-04 06:37:38

scoobsalamander
Member
From: Belgium - Hulshout
Registered: 2015-10-27
Posts: 217

Re: BCD data

In a REXLANG block you can do something like this by shifting/masking the bits.

pressure = ((input & 0x0F) + ((input>>4 & 0x0F)*10) + ((input>>8 & 0x0F)*100) + ((input>>12 & 0x0F)*1000));

I did not test the code but I guess you got the idea...

Last edited by scoobsalamander (2016-05-04 07:35:29)

Offline

#3 2016-05-04 07:04:16

jaroslav_sobota
Administrator
Registered: 2015-10-27
Posts: 535

Re: BCD data

Thumbs up scoobsalamander! And here is how to do it using function blocks.
bcd_example.png

The principle is the same: Take the four bits, convert it to decimal numbers and multiply it by 1, 10, 100 and 1000 respectively.

There are two approaches to obtaining the binary form of a Modbus register. The first one is faster but a bit tricky for the first use, that's why I included both of them.

Here is the mdl file.

Offline

#4 2016-05-04 07:27:47

scoobsalamander
Member
From: Belgium - Hulshout
Registered: 2015-10-27
Posts: 217

Re: BCD data

Here a tested example for four signals..... smile 

/************************************************************
*
* REXLANG - BCD to INT
*
*************************************************************/

long input(0) input_u0;
long input(1) input_u1;
long input(2) input_u2;
long input(3) input_u3;

double output(0) output_y0;
double output(1) output_y1;
double output(2) output_y2;
double output(3) output_y3;

long init(void)
{
    return 0;
}


long main(void)
{
        output_y0 = ((input_u0 & 0x0F) + ((input_u0>>4 & 0x0F)*10) + ((input_u0>>8 & 0x0F)*100) + ((input_u0>>12 & 0x0F)*1000));
	output_y1 = ((input_u1 & 0x0F) + ((input_u1>>4 & 0x0F)*10) + ((input_u1>>8 & 0x0F)*100) + ((input_u1>>12 & 0x0F)*1000));
	output_y2 = ((input_u2 & 0x0F) + ((input_u2>>4 & 0x0F)*10) + ((input_u2>>8 & 0x0F)*100) + ((input_u2>>12 & 0x0F)*1000));
	output_y3 = ((input_u3 & 0x0F) + ((input_u3>>4 & 0x0F)*10) + ((input_u3>>8 & 0x0F)*100) + ((input_u3>>12 & 0x0F)*1000));

    return 0;
}

long exit(void)
{
  return 0;
}

Offline

#5 2016-05-04 12:00:59

josar
Member
From: Czech Rep.
Registered: 2015-11-03
Posts: 17

Re: BCD data

scoobsalamander wrote:
long main(void)
{
        output_y0 = ((input_u0 & 0x0F) + ((input_u0>>4 & 0x0F)*10) + ((input_u0>>8 & 0x0F)*100) + ((input_u0>>12 & 0x0F)*1000));
	output_y1 = ((input_u1 & 0x0F) + ((input_u1>>4 & 0x0F)*10) + ((input_u1>>8 & 0x0F)*100) + ((input_u1>>12 & 0x0F)*1000));
	output_y2 = ((input_u2 & 0x0F) + ((input_u2>>4 & 0x0F)*10) + ((input_u2>>8 & 0x0F)*100) + ((input_u2>>12 & 0x0F)*1000));
	output_y3 = ((input_u3 & 0x0F) + ((input_u3>>4 & 0x0F)*10) + ((input_u3>>8 & 0x0F)*100) + ((input_u3>>12 & 0x0F)*1000));

    return 0;
}

Isn't it possible to implement a function for that?

Offline

#6 2016-05-04 13:05:15

scoobsalamander
Member
From: Belgium - Hulshout
Registered: 2015-10-27
Posts: 217

Re: BCD data

Should be possible, maybe you can put your inputs in an array and iterate over it.

Offline

#7 2016-05-04 15:59:39

jaroslav_sobota
Administrator
Registered: 2015-10-27
Posts: 535

Re: BCD data

josar wrote:

Isn't it possible to implement a function for that?

Yes it is possible (and recommended!). Find the code below:

/************************************************************
*
* REXLANG - BCD to DOUBLE
*
*************************************************************/

long input(0) input_u0;
long input(1) input_u1;
long input(2) input_u2;
long input(3) input_u3;

double output(0) output_y0;
double output(1) output_y1;
double output(2) output_y2;
double output(3) output_y3;

double bcd2double(long bcd)
{
    return ((bcd & 0x0F) + ((bcd>>4 & 0x0F)*10) + ((bcd>>8 & 0x0F)*100) + ((bcd>>12 & 0x0F)*1000)); 
}

long init(void)
{
    return 0;
}

long main(void)
{
        output_y0 = bcd2double(input_u0);
        output_y1 = bcd2double(input_u1);
        output_y2 = bcd2double(input_u2);
        output_y3 = bcd2double(input_u3);

    return 0;
}

long exit(void)
{
  return 0;
}

Offline

#8 2016-05-04 17:31:33

scoobsalamander
Member
From: Belgium - Hulshout
Registered: 2015-10-27
Posts: 217

Re: BCD data

@jaroslav_sobota : is it possible to put all the values from the inputs in one 'long' array? I tried but it didn't want to compile....maybe I used the wrong syntax.....

Last edited by scoobsalamander (2016-05-04 17:34:20)

Offline

#9 2016-05-04 19:02:47

coldh2odvr
Member
Registered: 2016-04-18
Posts: 17

Re: BCD data

Tried all three methods, didn't get the INHEXD block working but BDHEXD worked and scoobsalamander/ jaroslav code/function work great!

Offline

Board footer

Powered by FluxBB