June 7, 2016

Работа с CANopen из C# программы

Большинство модулей расширения на шине EtherCAT внутри себя работают через собственную шину: CANopen, SERCOS, и т. п. Чтобы напрямую обратиться к внутренним регистрам модуля, необходимо выполнить ряд подготовительных операций, а точнее, правильно сформировать AmsNetId, индекс группы и смещение в функциях чтения через протокол ADS. Включать ADS-сервер шины EtherCAT при этом не требуется.
Про работу с SERCOS можно прочитать в статье S и P параметры сервоусилителей.

Адрес модуля, к регистрам которого мы будем обращаться, можно подсмотреть в зеленой ветке InfoData.



Передать адрес модуля в программу на C# можно через ПЛК-программу и выделенную переменную с заранее известным именем, либо извлечь через TwinCAT Automation Interface. Первый вариант — проще, второй — универсальный.

Для демонстрации я взял модуль инкрементального энкодера EL5151. Просто потому, что у него красивый артикул и внутри шина CANopen.

Индекс группы сервиса ADS, отвечающего за работу с CANopen SDO:
EC_ADS_IGRP_CANOPEN_SDO = 0xF302;
Индекс смещения формируется как двойное слово (32-разряда), состоящее из индекса и субиндекса адреса CANopen:
SHLWORD_TO_DWORD(nIndex), 16 ) OR BYTE_TO_WORD( nSubIndex )

В качестве примера я хочу прочитать 1018:02 (Identity : Product code), т. е. я хочу прочитать из модуля его артикул:

using System;
using TwinCAT.Ads;

class Program
{
    static long EC_ADS_IGRP_CANOPEN_SDO = 0xF302;

    static void Main(string[] args)
    {
        const string ETHERCAT_BUS_AMSNETID = "192.168.1.18.2.1";
        const int EL5151_AMSPORT = 1002;

        TcAdsClient client = new TcAdsClient();
        client.Connect(
            ETHERCAT_BUS_AMSNETID,
            EL5151_AMSPORT);

        // CANopen SDO Identity:Product code = 1018:02
        uint cansdo_Index = 0x1018;
        uint cansdo_SubIndex = 0x02;

        long CanSdoOffset = cansdo_Index << 16 | cansdo_SubIndex;

        uint Identity_ProductCode =
            (uint)client.ReadAny(
                EC_ADS_IGRP_CANOPEN_SDO, 
                CanSdoOffset,
                typeof(uint));

        Console.WriteLine(
             string.Format(
                "1018:02 = 0x{0} ({1})",
                Identity_ProductCode.ToString("X2"),
                Identity_ProductCode));

        Console.ReadKey();
    } // Main
} // class


Сравниваем полученный результат:



Аналогично можно записывать параметры, при условии, что они доступны для записи. На картинке выше колонка Flags отображает доступность регистров: RO — только для чтения, RW — чтение/запись.

No comments

Post a Comment

Note: Only a member of this blog may post a comment.