Welcome to our new forum
All users of the legacy CODESYS Forums, please create a new account at account.codesys.com. But make sure to use the same E-Mail address as in the old Forum. Then your posts will be matched. Close

Codesys and QT Communication

rsudecetin
2021-12-07
2022-01-09
  • rsudecetin - 2021-12-07

    I'm student for now and i want to p-simple project with qt and codesys. I want to do interface with qt and control system with codesys. How can i do that? I don't want to opc ua because of price. Please help me! Thank you everyone!

     
  • mondinmr

    mondinmr - 2021-12-10

    Shared Memory! Is very simple use it!!!
    In Qt Window you can use QSharedMemeory, running application as administrator and connecting CODESYS with key.
    In Qt Linux you must use system functions, Qt manage shared in a non compatible way to CODESYS, but is very easy.

    Here you have an example of our shared memory manager class. Working in Windows and Linux.
    Remember //Global/ in shm keys on windows systems.

    #ifndef ADVSAHREDMEMORYMANAGER_H
    #define ADVSAHREDMEMORYMANAGER_H
    
    #include "advabstractmemorymanager.h"
    #include "advmemorymanager_global.h"
    #include <QSharedMemory>
    #include <QDebug>
    #ifdef Q_OS_LINUX
    #include <fcntl.h>
    #include <sys/shm.h>
    #include <sys/stat.h>
    #include <sys/mman.h>
    #include <unistd.h>
    #endif
    
    template <class T>
    class ADVSahredMemoryManager : public ADVAbstractMemoryManager<T>
    {
    public:
        explicit ADVSahredMemoryManager(const QString &key) : ADVAbstractMemoryManager<T>(), m_key(key), shm(new QSharedMemory) { instantiateMemory(); }
        virtual ~ADVSahredMemoryManager() { freeMemory(); }
    
        bool isValid() {return m_valid;}
    
    protected:
        void instantiateMemory()
        {
            dataPtr = nullptr;
            shm->setNativeKey(m_key);
            if (attach()) {
                qWarning()<<QObject::tr("Shm exists, attached")<<m_key<<"!";
                m_valid = true;
            } else {
                if (create())
                {
    #ifndef Q_OS_LINUX
                    dataPtr = shm->data();
    #endif
                    memset(dataPtr, 0, sizeof(T));
    
                    qWarning()<<QObject::tr("Shm created")<<m_key;
                    m_valid = true;
                } else {
                    qWarning()<<QObject::tr("Cannot create shm")<<m_key<<"!!!";
                    m_valid = false;
                    return;
                }
            }
            ADVAbstractMemoryManager<T>::setDataPointer(reinterpret_cast<T *>(dataPtr));
        }
    
        void freeMemory()
        {
            if (isAttached()) {
                qDebug()<<"Detach"<<m_key;
                detach();
            }
            delete shm;
        }
    
    private:
        QString m_key;
        QSharedMemory *shm;
        void *dataPtr;
    
        bool m_valid;
    
        bool attach() {
    #ifndef Q_OS_LINUX
            if (shm->attach()) {
                dataPtr = shm->data();
                return true;
            }
            return false;
    #endif
    #ifdef Q_OS_LINUX
            int shm_fd = shm_open(shm->nativeKey().toUtf8().toStdString().c_str(), O_RDWR, 0666);
            if (shm_fd >= 0) {
                dataPtr = mmap(nullptr, sizeof(T), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
                if (dataPtr)
                    return true;
            }
            return false;
    #endif
        }
        void detach() {
    #ifndef Q_OS_LINUX
            shm->detach();
    #endif
    #ifdef Q_OS_LINUX
            shm_unlink(shm->nativeKey().toUtf8().toStdString().c_str());
    #endif
        }
        bool create() {
    #ifndef Q_OS_LINUX
            return shm->create(sizeof(T));
    #endif
    #ifdef Q_OS_LINUX
            int shm_fd = shm_open(shm->nativeKey().toUtf8().toStdString().c_str(), O_RDWR | O_CREAT | O_EXCL, 0666);
            if (shm_fd >= 0) {
                int ret = ftruncate(shm_fd, sizeof(T));
                if (ret == 0)
                    dataPtr = mmap(nullptr, sizeof(T), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
                else {
                    qDebug()<<"Error code ftruncate : "<<errno;
                    detach();
                }
                if (dataPtr)
                    return true;
                else
                    detach();
            }
            return false;
    #endif
        }
        bool isAttached() {
    #ifndef Q_OS_LINUX
            return shm->isAttached();
    #endif
    #ifdef Q_OS_LINUX
            return dataPtr != nullptr;
    #endif
        }
    };
    
    #endif // ADVSAHREDMEMORYMANAGER_H
    

    And here a sample of CODESYS side code:

    IF NOT shmOpened THEN
        IF shmHandler <> 0 THEN
            SysSharedMemoryClose(shmHandler);
        END_IF
        shmSize := SIZEOF(SharedArea);
        shmHandler := SysSharedMemoryOpen2(shmKey, 0, ADR(shmSize), ADR(shmOpenResult));
        IF shmOpenResult = 0 AND shmHandler > 0 THEN
            areaExchange := SysSharedMemoryGetPointer(shmHandler, ADR(shmPointerResult));
            ShmGlv.fieldArea REF= areaExchange^;
            IF shmPointerResult = 0 THEN
                shmOpened := TRUE;
            END_IF
        END_IF
    ELSE
        IF areaExchange^.watchDogPC = areaExchange^.watchDogPLC THEN
            areaExchange^.watchDogPLC := areaExchange^.watchDogPLC + 1;
            shmCounterWatchdog := 0;
            IF areaExchange^.watchDogPC > 0 THEN
                IF NOT shmConnected THEN
                    shmConnected := TRUE;
                END_IF;
            END_IF
        ELSE
            shmCounterWatchdog := shmCounterWatchdog + 1;
            IF shmCounterWatchdog >= MAX_WATCHDOG_COUNTER THEN
                IF shmConnected THEN
                    shmConnected := FALSE;
                END_IF
            END_IF
        END_IF;
    END_IF
    
     

    Last edit: mondinmr 2021-12-11

Log in to post a comment.