Hi! Im

Im trying to read a some 32-bit registers from a PLC and check if a bit is set. If e.g bit number 8 is set then i have an alarm. If bit 9 is set then it is acknowledged. If there is an alarm i would like to present this alarm with name and value in a list. The program should read through these registers continuously and always check the bits.
Can someone show me an example of this? Is it best to dedicate a own thread for this or what? Should i use windows forms or WPF?

The code below reads register 40-44 and writes the binary values to console.

try
                {
                    
                    //read register 40-44 and put the values into read array.
                    int[] read = connection.PcdRdRTC('R', 6000, 5);
                    int bin = 2;
                    
                    for (int i = 0; i < read.Length; i++)                        
                        Console.Write("Reg {0}: {1} ", i + 40, Convert.ToString(read[i], bin) + "\n");
                    Console.WriteLine();
                    

                }

Hope someone can help me in the right direction.
Best regards

Recommended Answers

All 5 Replies

You can get the same output using a bit-mask.

Console.WriteLine("Using bitmask");
for (int i = 0; i < read.Length; i++)
{
	int bitMask = 0x8000; // start from left most bit
	Console.Write(string.Format("Register {0}: ", i));
	for (int j = 0; j < 16; j++)
	{
		// test bit status and write 1 if set else 0
		Console.Write(((read[i] & bitMask) == bitMask) ? "1" : "0");
		bitMask >>= 1; // right shift mask one place
	}
	Console.WriteLine();
}

Or you could use a BitArray.

Console.WriteLine("Using 32bit BitArray");
for (int i = 0; i < read.Length; i++)
{
	// convert 32bit integer to bit array
	var bits = new System.Collections.BitArray(new[] { read[i] });
	Console.Write(string.Format("Register {0}: ", i));
	for (int j = 15; j >= 0; j--) // reverse loop as LSB is index 0
	{
		// test bit status and write 1 if set else 0
		Console.Write(bits[j] ? "1" : "0");
	}
	Console.WriteLine();
}

You could also put all the registers in to a single BitArray.
But remember that the LSB is index 0.

// put all bits in BitArray (remember LSB is index 0)
var allbits = new System.Collections.BitArray(read);
commented: Informative. +15

Regarding the reporting of the bit status as alarms:

I would have a system timer do the read operation and report any connection errors.
This would load the register values in to properties to allow external access.

Have another timer/event read the register bit status and report the alarm conditions.

Keeping the read/write as a separate operation makes debugging easier.
It also means that should you need UI then the read process is not hindered by UI thread operations and vice versa.

Thank you for very helpful answers nick. :)

I will try this.
So basically what you mean is that i should use different threads for reading and writing?

Do you have any thoughts about writing a realtime alarm handling application?
I was thinking about using MySQL as database for the system where alarm texts, attributes and logging of each alarm will be stored.

My advice is to have a single thread that read/writes any data to/from the PLC.
This is necessary to ensure the PLC connection is not shared between threads; otherwise you will have trouble with synchronisation.
This thread should put the data in to some common (shared) resource. This could be a database or an object instance of a custom class written for this purpose.

Other tasks can then also read/write the data values from the shared resource without interfering with the PLC communications. What those tasks do is down to your application.

Here is how I handle reading masked bits:

public static class BITS
  {
    public const byte BIT0 = 0x01;
    public const byte BIT1 = 0x02;
    public const byte BIT2 = 0x04;
    public const byte BIT3 = 0x08;
    public const byte BIT4 = 0x10;
    public const byte BIT5 = 0x20;
    public const byte BIT6 = 0x40;
    public const byte BIT7 = 0x80;
  }

Assigning properties to a bit-masked byte:

byte m_alarm;
    public bool HasAlarm
    {
      get { return m_alarm > 0; }
    }
    public bool LowAlarm1
    {
      get { return (m_alarm & BITS.BIT0) == BITS.BIT0; }
      set { m_alarm = (byte)((m_alarm & ~BITS.BIT0) | (value ? BITS.BIT0 : 0x00)); }
    }
    public bool HighAlarm1
    {
      get { return (m_alarm & BITS.BIT1) == BITS.BIT1; }
      set { m_alarm = (byte)((m_alarm & ~BITS.BIT1) | (value ? BITS.BIT1 : 0x00)); }
    }
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.