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

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);

Edited 5 Years Ago by nick.crane: n/a

Comments
Informative.

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.

Edited 5 Years Ago by nick.crane: n/a

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)); }
    }
This question has already been answered. Start a new discussion instead.