Wyślij zapytanie Dołącz do Sii

Postępująca transformacja cyfrowa dotyka wiele dziedzin życia oraz gospodarki. Nie omija to również przemysłu poprzez realizację założeń czwartej rewolucji przemysłowej, opierającej się na głębokiej integracji systemów sterowania oraz nadzoru z zaawansowanymi systemami informatycznymi.

Mają one za zadanie podnosić wskaźniki wydajności, jakości oraz bezpieczeństwa prowadzonych procesów produkcyjnych. Pomimo sporych inwestycji przeznaczanych przez przedsiębiorstwa na modernizację aparatury sterująco-kontrolnej w obiegu nadal funkcjonują urządzenia nieprzystosowane do funkcjonowania w aktualnych systemach zarządzania obiektem sterowania. W związku z tym, częstym problemem podczas realizacji idei przemysłu 4.0 jest również starzejąca się infrastruktura sieciowa. Istnieje natomiast możliwość obniżenia kosztów takiej transformacji poprzez wykorzystanie zewnętrznych bibliotek wraz z REST API. W niniejszym przykładzie opisana zostanie implementacja REST API z wykorzystaniem sieci polowej MODBUS TCP. W przykładzie wykorzystano środowisko CoDeSys oraz REST API napisane z wykorzystaniem .NET WEB API w języku C#.

MODBUS TCP jest wersją otwartego protokołu MODBUS wykorzystującego ethernet jako medium komunikacyjne zarówno przewodowo jak i bezprzewodowo. Wykorzystuje on w komunikacji port 502. Działa on w architekturze klient-serwer (master-slave). W przeciwieństwie do MODBUS RTU daje to przewagę w możliwości zawarcia wielu klientów, aniżeli jednego w zakresie sieci.

PLC + MODBUS

Schemat obiektu wygląda następująco:

schemat obiektu: Soft PLC, Gateway, REST API

Na wstępie przygotowujemy strukturę projektu PLC wraz z przygotowaniem infrastruktury sieciowej dla MODBUS TCP. Device Ethernet konfigurujemy zgodnie z aktualną dla nas siecią Ethernet.

CoDeSys network config - Dane przemysłowe w Internecie – implementacja REST API z wykorzystaniem sieci polowej MODBUS

Kolejnym krokiem jest przygotowanie mapowania zmiennych sieciowych do wykorzystania w programie.

CoDeSys Modbus variables config - Dane przemysłowe w Internecie – implementacja REST API z wykorzystaniem sieci polowej MODBUS

Należy koniecznie pamiętać o ustawieniu odpowiedniego Taska dla działania naszej sieci polowej. W przykładzie jest to główny Task wywoływany cyklicznie.

CoDeSys task set - Dane przemysłowe w Internecie – implementacja REST API z wykorzystaniem sieci polowej MODBUS

Na tym etapie przygotowany projekt PLC jest gotowy do pracy w trybie slave (server), do którego będą przysyłane zapytania o dane.

REST API + NMODBUS

Kolejnym etapem jest przygotowanie REST API w środowisku .NET. W projekcie wykorzystano bibliotekę NModbus, która pozwala na dostęp do urządzeń wspierających sieć polową MODBUS zarówno w wersji RTU jak i TCP. Na wstępie wymagana jest konfiguracja klienta sieci MODBUS – w tym przypadku master’a.

public bool Connect()
{
   if (_client == null)
      return false;
   var retriesTimeSpan = Backoff.LinearBackoff(TimeSpan.FromSeconds(1), 5);
   var policy = Policy.Handle<SocketException>().WaitAndRetry(retriesTimeSpan);
   var connectionResult = policy.ExecuteAndCapture(() => _client.Connect(_hostname, _port));
   if (connectionResult.Outcome == OutcomeType.Failure)
   {
      var validationResult = new TcpClientValidationResult
      {
         HasErrors = true,
         ExceptionType = connectionResult.FinalException.InnerException
      };
   validationResult.ErrorMessage = validationResult.GetErrorMessageByExceptionType();
   ValidationResult = validationResult;
   }
   else
      ValidationResult = new TcpClientValidationResult();
   return _client.Connected;
}

Każdy endpoint wysyła zapytanie do service’ów, które to poprzez Gateway mają dostęp do sieci MODBUS.

[HttpGet("feedMotorSpeed")]
public async Task<IActionResult> GetFeddMotorSpeed()
{
   var serviceResponse = await _packagingCellService.GetFeedMotorSpeed();
   var actionResponse =_actionResponse.GetResponseFromService(serviceResponse);
   return serviceResponse.ValidationResult.HasErrors ? BadRequest(actionResponse) : Ok(actionResponse);
}
public async Task<IServiceResponse<ushort>> GetFeedMotorSpeed()
{
    var targetAddresses = _addressProvider.GetAddress(CompressorPackagingCellAddresses.FEED_MOTOR_SPEED);
    if (HasError(_addressProvider.ValidationResult))
    {
        SetResponseError(_addressProvider.ValidationResult);
        return GetResponse(_packagingCell.Model.FeedMotorSpeed);
    }
    _packagingCell.Model.FeedMotorSpeed = await _modbusGateway.Reader.ReadNumberValue(targetAddresses);
    if (HasError(_modbusGateway.Reader.ValidationResult))
        SetResponseError(_modbusGateway.Reader.ValidationResult);
     
    return GetResponse(_packagingCell.Model.FeedMotorSpeed);
}

Adresy poszczególnych rejestrów sieci MODBUS są przechowywane w stałych. Walidacja następuje przy każdym ich wykorzystaniu.

public int GetAddress(string address)
{
    var addressModel = _addressParser.Parse(address);
    var addressValidationResult = _validator.Validate(addressModel);
    if (!addressValidationResult.HasErrors)
        _address = addressModel.ByteAddress + addressModel.BitAddress;
     
    ValidationResult = addressValidationResult;
  
    return _address;
}

Biblioteka Polly zajmuje się realizacją podejmowania prób ponownego połączenia oraz ponownego odczytu danych z sieci polowej. Dzięki niej łatwo można skonfigurować politykę obsługi wyjątków oraz podejmowania ponownych prób wykonania akcji.

public async Task<ushort> ReadNumberValue(int address)
{
    var response =  0;
    using (var client = _client.GetClient())
    {
        var timeSpan = Backoff.LinearBackoff(TimeSpan.FromSeconds(1), 4);
        var modbusMasterPolicy = Policy.Handle<Exception>().WaitAndRetry(timeSpan);
        var policyExecutionResult = modbusMasterPolicy.ExecuteAndCapture(() => SetModbusMaster(client));
        if(policyExecutionResult.Outcome == OutcomeType.Failure)
        {
            var validationResult = new ModbusReadingValidationResult();
            validationResult.GetFromSlaveException(policyExecutionResult.FinalException, (int)EModbusTransportErrorCode.ConnectionError);
            ValidationResult = validationResult;
            return (ushort)response;
        }
        var modbusReadingPolicy = Policy.Handle<Exception>().WaitAndRetryAsync(timeSpan);
        var modbusReadingPolicyResult =  modbusReadingPolicy.ExecuteAndCaptureAsync(async () =>
            await _modbusMaster.ReadInputRegistersAsync(0, (ushort)address, 1).ConfigureAwait(false));
        if(modbusReadingPolicyResult.Result.Outcome == OutcomeType.Failure)
        {
            var validationResult = new ModbusReadingValidationResult();
            validationResult.GetFromSlaveException(modbusReadingPolicyResult.Result.FinalException,
                            (int)EModbusTransportErrorCode.ReadingError);
            ValidationResult = validationResult;
            return (ushort)response;
        }
        response = modbusReadingPolicyResult.Result.Result[0];
    }
    return (ushort)response;
}

Następnie przechwycona odpowiedź lub błąd wynikający z niepowodzenia operacji przekazywane są do metody formatującej odpowiedź końcową.

public ServiceResponseBase GetResponseFromService<T>(IServiceResponse<T> serviceResponse)
{
    var responseModel = new ModbusActionResponseModel
    {
        ResponseMessage = serviceResponse.ValidationResult.HasErrors ? 
            SetErrorMessage(serviceResponse.ValidationResult) : 
            SetPayloadMessage(serviceResponse.Payload),
    };
    responseModel.ResponseMessage.ResponseIssued = DateTime.Now;
    return responseModel.ResponseMessage;
}

Te same kroki odpowiadają również ustawianiu rejestrów MODBUS. W tym celu należy wykorzystać inne (podać jakie) metody przygotowane w ramach biblioteki NModbus. Metoda „WriteSingleRegister” wpisuje wartość do całego rejestru – jest nią najczęściej wartość liczbowa. Natomiast metoda „WriteSingleCoil” pozwala na zmianę stanu pojedynczego bitu w rejestrze.

void WriteSingleRegister(byte slaveAddress, ushort registerAddress, ushort value);
void WriteSingleCoil(byte slaveAddress, ushort coilAddress, bool value);

Jak widać, niewątpliwą zaletą takiego rozwiązania jest jego niski koszt implementacji. O ile sama sieć MODBUS nie jest przystosowana do transmisji dużych pakietów danych (253 bajty), o tyle przy wymianie niewielkich ilości informacji jest w stanie zaspokoić potrzeby monitorowania podstawowych lub wrażliwych danych o obiekcie. Otwiera to drogę do archiwizowania i wizualizowania danych z obiektu oraz możliwość zadawania sygnałów sterujących zdalnie. Możliwości opisanej wyżej konfiguracji mogą również służyć do prototypowania różnych rozwiązań przemysłowych – od niewielkich instalacji sterowania i nadzoru do systemów archiwizacji oraz agregacji i prezentacji danych w systemach informatycznych.  Istotnym elementem jest również zabezpieczanie takiej instalacji przed niepożądanym dostępem. W takim przypadku może on nie tylko narazić obiekt na utratę danych, ale również doprowadzić obiekt do stanu niebezpiecznego.

5/5 ( głos: 1)
Ocena:
5/5 ( głos: 1)
Autor
Avatar
Michał Kasperski

Programuję od 3 lat rozpoczynając swoją przygodę od sterowników przemysłowych. Obecnie pracuję w SII jako software developer w technologii ASP .NET. W wolnym czasie czytam książki historyczne, programuję oraz gram w badmintona.

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Może Cię również zainteresować

Pokaż więcej artykułów

Bądź na bieżąco

Zasubskrybuj naszego bloga i otrzymuj informacje o najnowszych wpisach.

Otrzymaj ofertę

Jeśli chcesz dowiedzieć się więcej na temat oferty Sii, skontaktuj się z nami.

Wyślij zapytanie Wyślij zapytanie

Natalia Competency Center Director

Get an offer

Dołącz do Sii

Znajdź idealną pracę – zapoznaj się z naszą ofertą rekrutacyjną i aplikuj.

Aplikuj Aplikuj

Paweł Process Owner

Join Sii

ZATWIERDŹ

This content is available only in one language version.
You will be redirected to home page.

Are you sure you want to leave this page?