Programmare SlimLine Raspberry in “C”

  1. Home
  2. Knowledge Base
  3. Controllori SlimLine Raspberry
  4. Programmare SlimLine Raspberry in “C”

Il modulo SlimLine Raspberry oltre alla programmazione secondo la normativa IEC61131 in stile PLC, in ambiente LogicLab o CODESYS, può essere programmato in linguaggio "C". Questo permette di utilizzare le librerie disponibili su Internet e di poter gestire i moduli di estensione collegabili al modulo CPU grazie alla libreria libeS8CoreMng da noi fornita. Per lo sviluppo di applicazioni in "C" è possibile utilizzare qualsiasi compilatore, in questo articolo utilizzeremo il noto IDE Codelite. Per chi utilizza l'ambiente LogicLab e vuole aggiungere nuove funzioni ed FB scritte in linguaggio "C" può leggere questo articolo.

Installazione toolchain

Per poter compilare programmi eseguibili su Raspberry occorre scaricare la toolchain di cross-compilazione di Raspbian da GitHub, scompattare il file in una cartella di sistema esempio /home/elsist/dev. Ora aggiungere la cartella nel PATH di sistema, editare il file etc/profile inserendo in fondo il link alla toolchain nella cartella in cui è stata trasferita, di seguito il link per i sistemi a 32 bits sulla riga superiore e 64 bits sulla riga inferiore.

export PATH=/home/elsist/dev/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin:$PATH
export PATH=/home/elsist/dev/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin:$PATH

Dopo aver modificato il file per renderlo attivo occorre da un terminale eseguire il comando source /etc/profile, è possibile verificare che il PATH sia attivo con il comando printenv. Se tutto è corretto è possibile compilare un semplice programma HelloWorld ed eseguirlo. Con un editor di testo creare il file main.c con il seguente contenuto :

#include <stdio.h>
int main()
{
    printf("Hello World!\r\n");
    return 0;
}

Compilare il programma con il comando arm-linux-gnueabihf-gcc main.c -g -o hello, verrà creato il file eseguibile hello che trasferito sulla Raspberry potrà essere eseguito. Anche se ora abbiamo tutto quello che serve per compilare un programma è preferibile affidarsi ad un IDE che permetta di gestire in modo più semplice lo sviluppo di applicazioni complesse, nel prosieguo utilizzeremo Codelite.

Installazione IDE

Codelite è un IDE open source gratuito disponibile per Windows, Linux e MacOS per lavorare con il linguaggio C, il programma è scaricabile dal sito ufficiale. Tralascio tutte le istruzioni per l'installazione che oltre ad essere molto semplici sono disponibili su una infinità di guide reperibili su Internet. Anche se il programma è disponibile per Windows, ne consiglio l'installazione su di una macchina Linux in quanto dovendo sviluppare applicazioni per Raspberry ci si trova già con tutte le librerie di base disponibili.

Ora è possibile creare un nuovo Workspace a cui aggiungere un nuovo progetto, nel progetto settare il compilatore della toolchain Raspberry, tasto destro sul nome progetto, scegliere Settings -> General -> Compiler ed impostare Cross GCC (arm-linux-gnueabihf). Ora è possibile compilare il progetto e nella cartella Debug del progetto verrà generato il file eseguibile HelloWorld. Eseguendo il download del programma dimostrativo nella cartella HelloWorld si trova il progetto Codelite pronto per il test.

Trasferire programma su Raspberry

Con il comando build da Codelite viene compilato il programma che è salvato nella cartella Debug o Release (In base alla selezione di compilazione) creata all'interno della cartella di progetto. Ora utilizzando un SFTP occorre trasferirlo sul modulo Raspberry per l'esecuzione. Esistono molti client SFTP con interfaccia grafica adatti allo scopo il più noto è Filezilla, ma è più comodo agire semplicemente da una finestra terminale utilizzando il comando scp abbinandolo al comando sshpass per inviare anche la password di connessione.

Ora ipotizzando che il file eseguibile CPhrAccess compilato da Codelite sia nella cartella /home/CPhrAccess e che il modulo Raspberry abbia credenziali pi:raspberry ed indirizzo IP 192.168.0.180, volendo trasferire l'eseguibile nella cartella /home/pi occorre utilizzare il comando (Se il comando sshpass non è presente occorre installarlo):

sshpass -p 'raspberry' scp /home/CPhrAccess/CPhrAccess/Release/CPhrAccess [email protected]:/home/pi

Codelite può automaticamente al termine della compilazione eseguire il comando scp trasferendo il file sul modulo Raspberry, per impostarlo occorre nel menù Settings -> Pre/Post Build Commands -> Post Build inserire la riga di comando definita sopra.

Un esempio

Per lo sviluppo di applicazioni in "C" viene fornita la libreria libeS8CoreMng che contiene definizioni e funzioni per gestire l'hardware del sistema oltre a numerose funzioni utili. Di seguito il sorgente del programma CPhrAccess che inizializza il bus di estensione attivando il watchdog (Vedi articolo) e gestisce un modulo di I/O digitali connesso al  bus di estensione.

CPhrAccess (Ptp168)
// *****************************************************************************
// PROGRAM "CPhrAccess"
// *****************************************************************************
// A simple programs that shows how to access to peripheral modules attached to
// the SlimLine extension BUS.
// -----------------------------------------------------------------------------

#include <stdio.h>
#include <PhrFcts.h>
#include <Library.h>
#include <WatchDog.h>
#include <PhrI2cBus.h>
#include <SystemTime.h>
#include <LastError.h>
using namespace Elsist; //Defines namespace

// -----------------------------------------------------------------------------
// MAIN PROGRAM
// -----------------------------------------------------------------------------

int main(int argc, char **argv)
{
    // Define variables.
    
    int8_t Result; //Function result
    uint8_t PModules; //Peripheral modules
    uint32_t DInputs; //Digital inputs
    static uint32_t DOutputs; //Digital outputs
    static uint32_t TimeBf; //Time buffer (uS)

    // -------------------------------------------------------------------------
    // SYSTEM INITIALIZATION
    // -------------------------------------------------------------------------
    // A welcome message is displayed.

    printf("Elsist PTP168A000, CPhrAccess, Library:%s\n", eGetLibVersion());

    // Initialize the library, this must be done before use any function.
    // Function returns 0 if Ok or the error code.

    if ((Result=eLibInit()) != 0) {printf("eLibInit error %d\n", Result); return(0);}

    // Defines wich I2C device has been to used to manage the extension bus,
    // and initializes it. Function returns 0 if Ok or the error code.
    
    Result=ePhrI2cBusInit((char_t*)"/dev/i2c-4");
    switch(Result)
    {
        // Error on bus initializing there's some hardware problem.

        case -1: printf("Bus init error: %d\n", Result); return(0);
        
        // System has been restarted by a watchdog intervention.
        // "Result" returns the number of subsequent watchdog interventions.

        default:
        if (Result == 0) printf("System power up\n");
        if (Result != 0) printf("System has been rebooted for %d times\n", Result);
        
        // After a defined number of system reboots by watchdog interventions,
        // a decision must be taken. In this example the program is stopped.
        
        if (Result > 2)
        {
            printf("Too wdog reboot\n");
            eResetWDog(); //Watchdog reset, it reinits the reboot counter
            return(0);
        }
    }

    // Set the peripheral bus ready, this activates all the attached modules.
    // Set also the wdog timeout to 2 seconds. Time range (1 to 60000 mS).
    
    while (!ePhrI2cBusReady(true, 2000)); //Set ready signal on peripheral bus

    // -------------------------------------------------------------------------
    // PROGRAM LOOP
    // -------------------------------------------------------------------------
    // This is the main program loop, here all the program tasks has to be done
    // in this example the 8 digital outputs of an extension module are managed.

    while(true)
    {
        // The watchdog control has been set so it must be refreshed. If it's
        // not refreshed in the time set the system is rebooted.
        
        eWDogRefresh(); //Refresh the watchdog circuit

        // Read how many modules are attached to the bus, if no modules ends.

        PModules=eGetModulesOnPhrI2cBus(); //Peripheral modules
        if (PModules == 0) return(0);

        // Supposing to have a logic I/O module (With address 0) attached to the bus
        // are reading the inputs and managed the outputs.

        if (!eIsPhrI2cBusExtModuleAv(0)) return(0); //Exit if module not present
        if (!eGetPhrDI(0, DI_MODE::DI_8_LL, &DInputs))
            {printf("eGetPhrDi error: %u\n", eGetLastError()); return(0);}

        // Copy Di00 input status on Do00 output.

        if (DInputs&eBITPATTERN(0)) eBITSET(DOutputs, 0); else eBITRESET(DOutputs, 0);

        // Blink the Do01 outputs.

        if (TimeBf == 0) TimeBf=eGetSysTime(); //Initialize the reference time
        if ((eGetSysTime()-TimeBf) > eSEC(1))
        {
            TimeBf=eGetSysTime(); //Time buffer (uS)
            if (DOutputs&eBITPATTERN(1)) eBITRESET(DOutputs, 1); else eBITSET(DOutputs, 1);
        }

        // Transfer the value on the extension module digital outputs.

        if (!eSetPhrDO(0, DO_MODE::DO_8_LL, &DOutputs))
            {printf("eSetPhrDO error: %u\n", eGetLastError()); return(0);}
    }
}

// [End of file]

Ti è stato utile questo articolo ?

Ultimo aggiornamento: 16 Aprile 2020