We have created a desktop app on .Net Framework using LattePanda to read sensor data from PCB using RS485 Communication Protocol. In c# part, we have used EasyModbus Library to read data. The app working well to some extent, but coming to some point it is throwing the following error:
Object reference not set to an instance of an object.
at System.IO.Ports.SerialStream.EventLoopRunner.CallReceiveEvents(Object state)
at System.Threading.QueueUserWorkItemCallback.Execute()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
In the follwing you can see thec# code to create ModbusClient object and ReadInputRegisters() method. We couldn't find the cause of this termination.
private readonly SemaphoreSlim _lock = new (1, 1);
private static ModbusClient CreateAndConnectClient(string comPort, int baudrate, byte unitIdentifier)
{
try
{
ModbusClient modbusClient = new(comPort)
{
UnitIdentifier = unitIdentifier,
Baudrate = baudrate,
Parity = Parity.None,
StopBits = StopBits.One,
ConnectionTimeout = 1000
};
modbusClient.Connect();
return modbusClient;
}
catch (ModbusException ex) {
Trace.WriteLine("ModbusException: " + ex.Message);
throw;
}
catch (Exception ex)
{
Trace.WriteLine("Unhandled Exception: " + ex.Message);
throw;
}
}
public async Task<int[]> ReadInputRegistersAsync(string comPort, int baudrate, byte unitIdentifier, int startAddress, int quantity)
{
await _lock.WaitAsync();
ModbusClient? modbusClient = null;
try
{
// Attempt to create and connect the Modbus client
modbusClient = CreateAndConnectClient(comPort, baudrate, unitIdentifier);
// Check if the client was successfully created and connected
// to avoid Exception --> "Object reference not set to an instance of an object"
if (modbusClient == null)
{
Trace.WriteLine("ModbusClient is null.");
return new int[quantity];
}
var data = modbusClient.ReadInputRegisters(startAddress, quantity) ?? new int[quantity];
return data;
}
catch (ModbusException ex)
{
Trace.WriteLine("ModbusException in ReadInputRegistersAsync: " + ex.Message);
// Return a new empty integer array
return new int[quantity];
}
catch (Exception ex)
{
Trace.WriteLine("Unhandled Exception in ReadInputRegistersAsync: " + ex.Message);
return new int[quantity];
}
finally
{
if (modbusClient!=null && modbusClient.Connected)
{
modbusClient.Disconnect();
}
_lock.Release();
}
}
Then in the following class, we have called ReadInputRegistersAsync()
public List<RawInput> GetData(DateTime date)
{
var data = new List<RawInput>();
var items = GetSensors();
var groupeItems = items.GroupBy(i => i.SlaveID).ToList();
foreach (var itemGroup in groupeItems)
{
var sensors = itemGroup.ToList();
var sensor = sensors.OrderBy(i => i.InputCh).LastOrDefault();
if (sensor == null) continue;
var readTask = modbusManager.ReadInputRegistersAsync(
$"COM{sensor.SerPort}", 9600, (byte)itemGroup.Key, 0, sensor.InputCh);
Trace.WriteLine("^^^^^^^^^^^^^^^^^^^ READ TASK SlaveID: " + (byte)itemGroup.Key);
readTask.ContinueWith(task =>
{
if (task.IsCompletedSuccessfully)
{
var list = task.Result.ToList();
data.AddRange(sensors.ConvertAll(s =>
new RawInput()
{
ItemId = s.Id,
RawValue = list[s.InputCh - 1]
}
));
}
else
{
Trace.WriteLine("^^^^^^^^^^^^^^^^^^^ READ TASK IS NOT COMPLETED SUCCESSFULLY");
data.AddRange(sensors.ConvertAll(s => new RawInput()
{
ItemId = s.Id,
RawValue = 0
}));
}
}).Wait();
}
return data;
}