IP-Symcon auf Raspberry mit Nutzung der GPIOs

Hallo,

nachdem hier (IP-Symcon Community Forum) ausgesagt wurde, dass man sich selbst um die Anbindung der Raspberry I/O Schnittstellen kümmern muss, habe ich dies „als ersten Aufschlag“ getan.
Hierbei habe ich den Ansatz Befehle und Sollwerte über die SHELL direkt aus IPS zu setzen. Hierzu in einem normalen IPS-Script einfach z.B:

shell_exec("/usr/local/bin/gpio write 3 1");  //dies würde PIN3 auf High schalten.
//(WiringPI hierfür erforderlich: http://wiringpi.com/download-and-install/)

Die 1-Wire Temperaturen lese ich aus dem Dateiverzeichnis ebenfalls direkt aus IPS per Script z.B:

<?
//Adresse des Tempsensors muss im Info Feld stehen z.B.:
//28-000004aaf379
//Script muss unterhalb der TempVariablen stehen
//
$debug=false;
$Par_ID=IPS_GetParent($_IPS['SELF']);
$var_object_type=IPS_GetObject($Par_ID);
$ObjInfo=$var_object_type['ObjectInfo'];
if ($debug) echo $ObjInfo;
$dateiname="tail /sys/bus/w1/devices/".$ObjInfo."/w1_slave";
if ($debug) echo "
 $dateiname";
$meinstring=shell_exec($dateiname);
if ($debug) echo "
$meinstring
";
$pos1 = stripos($meinstring, "t=");
$value= substr($meinstring,$pos1+2);      //um das t= zu entfernen
$Temp=round(($value/1000),1);
if ($debug) echo "Temp= $value  $Temp";
If (GetValueFloat($Par_ID)!=$Temp)
    SetValueFloat($Par_ID,$Temp);
?>

Nun kann man ja die GPIO-Ports auch über ein Script auslesen, z.B.:

$Pin3=shell_exec("/usr/local/bin/gpio read 3");

, dies würde aber ein zyklischen Pollen erfordern.

Aus diesem Grund habe ich einen kleinen Dienst geschrieben, welcher die Werte (bei Änderung) per json an IP-Symcon schickt. Ich habe hier auch mehrere Tage schon erfolgreich I2C-Karten (von Horter&Kalb) in Betrieb, welche ich auch auf diesem Weg übertrage. Der Einfachheit halber ist das Beispiel (in der Anlage) aber nur für die GPIOs.

//Anleitung beschreibt nicht Installation von Raspbian,  IP-Symcon ...
//Dienst wird benötigt um Änderungen an den GPIOs sofort an den IPS zu übertragen
//IPS kann lokal (auf dem PI) oder auch Remote sein
//
//Voraussetzungen:
//Falls noch nicht erfolgt wiringPI installieren 
//http://wiringpi.com/download-and-install/
//Test mit: 
gpio readall    //liest alle Ports
gpio write 3 1    //schreibt Port3 HIGH 
//
//Falls I2C-Module vorhanden auch I2C-Tools installieren
//http://kampis-elektroecke.de/?page_id=2035
//
//
//Als Erstes lib für curl installieren:
sudo apt-get install libcurl4-openssl-dev
//Ordner "ips-pi" unter Home anlegen
sudo mkdir ips-pi
//ggf. Rechte anpassen
sudo chmod 777 ips-pi
//per WINSCP beide Dateien aus dem Anhang (makefile und ips-pi.c in dieses Verzeichnis kopieren
//zum Test sudo make (im Verzeichnis ips-pi) durchführen
sudo make  
//falls bei obigen ein Fehler kommt fehlt eine LIBRARY oder Fehler im Raspbian
//
//Anpassen der ips-pi.c im WINSCP
// IP und Port in nächster Zeile
// curl_easy_setopt(curl, CURLOPT_URL, "http://ip:port/api/");
// User und Password in nächster Zeile
// curl_easy_setopt(curl, CURLOPT_USERPWD, "user:password"); 
// Jeweilige Var_IDs z.B.:
// GPIO_PIN[0][0]=39331;    
// ggf. Zahl/Wert der überwachenden PINs einschränken
// for(i=0;i<=7;i++)
//
//Start durch:
sudo ./ips-pi                     //vorher nach ips-pi wechseln
//ggf.noch Autostart einrichten: http://www.raspberry-projects.com/pi/pi-operating-systems/raspbian/scripts
//

Viel Spaß

herbertf

ips-pi.rar (2.58 KB)

Hallo herbertf

danke für deine tolle Arbeit , das einlesen der GPIO’s funktioniert super, hätte aber auch interesse an deiner
i2c unterstützung.
Könntest du dieses auch veröffentlichen. Hab hier einige Sensoren wie Luftdruck / Temperatur /Helligkeit die ich als eigenstände Wetterstation einbinden will.

Gruß
MichelH

Tolle Arbeit :slight_smile:
Hätte auch großes Interesse an die i2c unterstütztung um zb die ds2413 auszulesen

Hallo ihr beiden,

vielen Dank - dann versuche ich mal mein Glück, hoffentlich leicht verständlich (bin ja kein Pädagoge)):

Vorwort: Ich setzte I2C von Horter und Kalb ohne irgendwelche Pegelwandler direkt am PI (maximal 30cm Kabel) ein -ohne jegliche Ausfälle oder Probleme seit ca. 12 Monaten.

Die Outputkarten sind m.E. nicht für jede Anwendung geeignet, da sie nach dem Einschalten auf EIN gehen (chipbedingt) - wäre für die Eingangstür eher „schlecht“. Die Inputkarten haben m.E. den Vorteil des weiten Eingangsspannungsbereichs - für mich allerdings total flexibel.

So nun zur Idee „IPS-auf PI, am Beispiel Horter&Kalb I2C Inputkarte (Bausatz I2C-Input 5 - 24V 8 Bit für DIN-Schiene)“:

Zuerst Installation der I2C-Tools (http://kampis-elektroecke.de/?page_id=2035).

Ich lese den I2C-Bus in einem separaten Thread aus:

    if(pthread_create(&t2, NULL, (void *)&i2c_eingaenge1,NULL) != 0)
    {
      fprintf(stderr, "Fehler bei Thread 2  I2C-Eingaenge 1.....
");
      exit(0);
    }    

Dafür muss naürlich t2 als integer dekliniert sein.

In der „gpio_init“ folgendes hinzufügen:

    
    i2c_in_1[0][0]=26057;    //5-stellige Zahlen sind die Ziel-VariablenIDs (des lokalen IPS)
    i2c_in_1[1][0]=43699;
    i2c_in_1[2][0]=48692;
    i2c_in_1[3][0]=20600;
    i2c_in_1[4][0]=23055;
    i2c_in_1[5][0]=53358;
    i2c_in_1[6][0]=27936;
    i2c_in_1[7][0]=27534;

    if((fd1=wiringPiI2CSetup(dID1))<0){
        printf("error opening i2c channel Eingabekarte-1
\r");

Im Hauptprogramm definiere ich das Array:


int i2c_in_1[8][3]={{0},{0},{0}};        //I2C-Bus Array für Eingang 0=0-7  1=val_id    2=aktuellerWert    3=alterWert

und die jeweilige Adresse des I2C-Ports


int dID1 = 0x3d;                    //Hex-Adresse I2C-Eingabekarte1 ermittelt über "i2cdetect -y 1"

und den Thread:

void i2c_eingaenge1 (void)
{
    printf("I2C-Eingaenge1 Thread gestartet
");
    int i;
    for (;;)        //Endlosschleife
    {    
        int dezzahl1;
        dezzahl1=wiringPiI2CRead (fd1);
        //printf("READ:  %i 
", dezzahl1);
        if (dezzahl1>=128) i2c_in_1[7][1]=1; else i2c_in_1[7][1]=0;
        if (dezzahl1%128>=64) i2c_in_1[6][1]=1; else i2c_in_1[6][1]=0;
        if (dezzahl1%64>=32) i2c_in_1[5][1]=1; else i2c_in_1[5][1]=0;
        if (dezzahl1%32>=16) i2c_in_1[4][1]=1; else i2c_in_1[4][1]=0;        
        if (dezzahl1%16>=8) i2c_in_1[3][1]=1; else i2c_in_1[3][1]=0;            
        if (dezzahl1%8>=4) i2c_in_1[2][1]=1; else i2c_in_1[2][1]=0;            
        if (dezzahl1%4>=2) i2c_in_1[1][1]=1; else i2c_in_1[1][1]=0;
        if (dezzahl1%2>=1) i2c_in_1[0][1]=1; else i2c_in_1[0][1]=0;
        for(i=0;i<=7;i++)                                                //Input 3-7 mit EinzelMeldungen belegt (alle belegt)
        {
            if (i2c_in_1[i][2]!=i2c_in_1[i][1]) {
                if (i2c_in_1[i][1]==0) var_val="true";        //negative Logik
                else var_val="false";
                printf("
i2c_in_1-Pin hat sich geaendert i2c_in_1_%d=%d -> senden
",i,i2c_in_1[i][2]);
//                printf("
WerteGändert: %d %d %d 
",i2c_in_1[i][0],i2c_in_1[i][1],i2c_in_1[i][2]);
                curl_senden(i2c_in_1[i][0],var_val);
            }
            i2c_in_1[i][2]=i2c_in_1[i][1];        //alten Wert setzen
        }
        //Stabilität Delay
        delay(100);                                                   
    }
    printf("I2C-Eingaenge1 Thread beendet
");
    pthread_exit((void *) 0);
}

Zusätzlich zu diesem Dienst habe ich noch eine Generalabfrage im IPS auf dem PI eingerichtet (alle 10Minuten bzw. bei Neustart IPS), dieser liest die I2C-Eingänge praktisch ohne den Dienst aus:

<?
// GA ausfuehren fuer alle Variablen im Ordner
//
$I2C_Adresse=0x3d;      //ermittelt über i2cdetect -y 1
//
//
$Par_ID=IPS_GetParent($_IPS['SELF']);
//
//Auslesen I2C Bus und Umrechnung
$dezzahl= hexdec( shell_exec("i2cget -y 1 $I2C_Adresse"));
echo "
Dezzahl $dezzahl";
$i2c_arr=array();
if ($dezzahl>=128) $i2c_arr[7] =1; else $i2c_arr[7] =0;
if ($dezzahl%128>=64) $i2c_arr[6] =1; else $i2c_arr[6] =0;
if ($dezzahl%64>=32) $i2c_arr[5] =1; else $i2c_arr[5] =0;
if ($dezzahl%32>=16) $i2c_arr[4] =1; else $i2c_arr[4] =0;
if ($dezzahl%16>=8) $i2c_arr[3] =1; else $i2c_arr[3] =0;
if ($dezzahl%8>=4) $i2c_arr[2] =1; else $i2c_arr[2] =0;
if ($dezzahl%4>=2) $i2c_arr[1]  =1; else $i2c_arr[1]  =0;
if ($dezzahl%2>=1) $i2c_arr[0] =1; else $i2c_arr[0] =0;
//
//
$variablen_array=IPS_GetChildrenIDs($Par_ID);
$var_ids = array();
foreach ($variablen_array as $value)        //durchsucht alle Objekte unter PAR_ID
{
    $var_object_type=IPS_GetObject($value);
    $ObjTyp=$var_object_type['ObjectType'];
    $Name=IPS_GetName($value);
    // Ermittlung Variable
   If ($ObjTyp==2)     {  //Prüfung ob Objekt Variable
        //echo $Name;
        $Variable=IPS_GetVariable ($value);
        $ObjInfo=$var_object_type['ObjectInfo'];
        $Nummer= (int) substr($ObjInfo, -2);
        $wert=$i2c_arr[$Nummer];
        if ($wert==0) $wert=false;
           else $wert=true;
        echo "
$value $ObjInfo $Nummer $wert";
        If (GetValueBoolean($value)==$wert)    SetValueBoolean($value,!$wert);
    }
}
Ende_Script:
?>

Grundsätzlich ist es erforderlich, für die direkte Abfrage aus IPS, die I2C-Variablen mit dern INFO_Feld zu belegen !!!
Dies ist wichtig !!!
z.B. als Info-Feld:

I2C_IN_1_02

Das war „hoffentlich“ schon alles - Viel Spaß

Beste Grüße aus Thüringen

herbertf

hallo,

kann ich die GPIOs an einem Client abfragen bzw. setzen? Sprich nicht auf dem IPS-Server sondern einem im Heimnetz befindlichen RaspPi?

Gruß
Hardlog

Hallo Hardlog,

wenn Du KEINEN zusätzlichen IPS auf dem Raspberry einsetzen willst, funktioniert dies: http://www.ip-symcon.de/forum/threads/21088-Raspberry-PI-Modbus-TCP-IP-Server.

IP-Symcon auf dem Raspberry ist derzeit noch BETA, vor allem Abstürze in der Konsole „nerven“ etwas.

Trotzdem bist Du m.E. künftig flexibler wenn Du einen zusätzlichen IPS auf dem Raspberry installierst und die Daten wie in diesem Thread beschrieben mit Deinem aktuellen IPS austauschst … (direkt zwischen 2 IPS sollte JSON genutzt werden http://www.ip-symcon.de/service/dokumentation/entwicklerbereich/datenaustausch/)

Gruß

herbertf

Danke @herbertf,

das mit der Instabilität der beta hat mich erstmal zu nem Rückschritt verleitet. Hab momentan RaspPis nur zum visualisieren des WF und einen für XBMC im Einsatz. Deine Verschläge werde ich heute Nachmittag mal probieren.

Gruß
hardlog

Hi,

ich habe noch so einen PiFace drauf und damit funktioniert es nicht. Hättest Du da ne Lösung?

Hi UVoigi,

leider nein, ich habe -zwar ausschließlich- dafür aber mehrfach folgendes:

  • GPIOs als Ein- und Ausgänge (nachgeschaltete Relais-Boards)
  • GPIO mit 1-Wire-TempSensoren
  • I2C In- und Output von Horter & Kalb

als Türsprechstellen habe ich dann noch einen USB-Sound-Adapter für die Nutzung als PJSIP-VoIP Client.

Weiterhin nutze ich, bei 2 von 5 PIs, einen WLAN-Stick als zusätzlichen Access-Punkt. Funkt auch mit WPA/Radius problemlos.

Aber ein PiFace habe ich leider nicht …

HerbertF

Hm…

eigentlich funktioniert es fast, aber… ich muss vor jedem lese oder schreib Befehl ein -p setzen.
Weiß aber nicht wie oder wo ich es in deinem Skript vordefiniere. Hast Du vlt dafür eine Idee??

So funktioniert jetzt soweit alles.

Es gibt nur noch ein kleines Problem, wenn man mal ca 15 min. nichts am Rapberry macht,scheint es ein wenig
einzuschlafen. Drücke ich am Raspberry PiFace eine Taste dauert es ungefähr ca 15 sec. bis es aktualisiert…
Währe jetzt in diesem (meinem) Fall nicht so schlimm, und danach geht es dann wieder. Aber im Fall Port schalten ist es nicht so einfach, Da kommt dann die Fehlermeldung von IPS IP nicht erreichbar, dann dauert es ca 10 sec und er schaltet es mir 2 mal hintereinander.???

Gibt es da irgendeine Lösung das man den Raspberry, na wie soll ich sagen, Wachhalten? kann?

Also einschlafen soll und kann da nix.

Da hast Du bestimmt noch einen kleinen Fehler drin.

herbertf

@herbertf

hast recht gehabt. Der W-Lan Adapter ging in den Schlafmodus wenn er nicht benutzt wird.
Hier mal für jemanden der es braucht. In meinem Fall ist es der EDIMAX.

sudo nano /etc/modprobe.d/8192cu.conf

und dann der Eintrag.

# Disable power management
options 8192cu rtw_power_mgnt=0 rtw_enusbss=0

Hi,

weil ich nun nochmal per Mail angefragt wurde, hier nun mein aktives Beispiel auch für I2C Input und Output-Karten:

ips-pi.c

/*
Dieser Dienst sendet die lokalen Eingänge (GPIOs ..).... an den lokalen IP-Symcon-Dienst
//
// Garage
//
Ver: 2.6
- Übertragung binärer Zustände an IPS, bei deren Änderung
- I2C Unterstützung Inputkarte
- LifeBit
- I2C Unterstützung Outputkarte (Initialisierung auf Null)
- Prozessorlast durch Delay gesenkt
*/
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <curl/curl.h>
#include <pthread.h>
// Threads: http://pronix.linuxdelta.de/C/Linuxprogrammierung/Linuxsystemprogrammieren_C_Kurs_Kapitel8.shtml
pthread_t t1,t2,t3,t4,t5;
int var_id,j,e,fd1,fd2,fd3;
char* var_val;
int GPIO_PIN[17][3]={{0},{0},{0}};        //GPIO-PINs zweidimensionales Array 0=0-7 1=val_id 2=aktuellerWert 3=alterWert
int dID1 = 0x3d;                    //Hex-Adresse I2C-Eingabekarte1 ermittelt über "i2cdetect -y 1"
int dID2 = 0x3a;                    //Hex-Adresse I2C-Eingabekarte2 ermittelt über "i2cdetect -y 1"
int dID3 = 0x27;                    //Hex-Adresse I2C-Ausgabekarte ermittelt über "i2cdetect -y 1"
int i2c_in_1[8][3]={{0},{0},{0}};        //I2C-Bus zweidimensionales Array für Eingang 0=0-7 1=val_id 2=aktuellerWert 3=alterWert
int i2c_in_2[8][3]={{0},{0},{0}};        //I2C-Bus zweidimensionales Array für Eingang 0=0-7 1=val_id 2=aktuellerWert 3=alterWert
int i2c_out_1[8][3]={{0},{0},{0}};        //I2C-Bus zweidimensionales Array für Eingang 0=0-7 1=val_id 2=aktuellerWert 3=alterWert
//
void curl_senden (int var_id, char* var_val)
{
  CURL *curl;
  CURLcode res;
  curl_global_init(CURL_GLOBAL_ALL);
   /* get a curl handle */ 
  curl = curl_easy_init();
  //printf("
var_id= %d var_val= %s
",var_id,var_val);
  if(curl) {
    const int MAX_BUF =1000;
    char* jsonObj = malloc(MAX_BUF);
    sprintf(jsonObj,"{\"jsonrpc\": \"2.0\",\"method\":\"SetValue\",\"params\":[%i,%s],\"id\":1}",var_id,var_val); 
    printf("JSON-String= %s gesandt
",jsonObj);
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "Accept: application/json");
    headers = curl_slist_append(headers, "Content-Type: application/json");
    headers = curl_slist_append(headers, "charsets: utf-8");
    curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.4.57:3777/api/");    //hier IP-Adresse-Port
      curl_easy_setopt(curl, CURLOPT_USERPWD, "username:password");             //hier username+password
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonObj);    
    res = curl_easy_perform(curl);
     /* Check for errors */ 
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s
",
              curl_easy_strerror(res));
    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  curl_global_cleanup(); 
  printf("
");
  return;
}

int lifebit (void)    //
{
    printf("
Lifebit-Thread gestartet
");
    int x=1,LifeBit=30123;
    for(;;) 
    {
        x=abs(x-1);
        if (x==1) var_val="true";
        else var_val="false";
        curl_senden(LifeBit,var_val);
        delay(30000);    //alle 10 Sekunden
    }    
    return 0;
    printf("GPIO-Ueberwachung-Thread beendet
");
    pthread_exit((void *) 0);
}

int gpio_thread (void)    //
{
    printf("
GPIO-Ueberwachung-Thread gestartet
");
    int i;
    for(;;) 
    {
        for(i=0;i<=6;i++)                                //6Output-Ports GPIO 0-7  (7 wäre 1-Wire)
        {
            GPIO_PIN[i][1]=digitalRead(i);            //Liest GPIO-PINs in Array
            if (GPIO_PIN[i][2]!=GPIO_PIN[i][1]) {
                if (GPIO_PIN[i][1]==1) var_val="true";
                else var_val="false";
                printf("
GPIO-Pin hat sich geaendert GPIO_%d=%d -> senden
",i,GPIO_PIN[i][2]);
//                printf("
WerteGändert: %d %d %d 
",GPIO_PIN[i][0],GPIO_PIN[i][1],GPIO_PIN[i][2]);
                curl_senden(GPIO_PIN[i][0],var_val);
            }    
            GPIO_PIN[i][2]=GPIO_PIN[i][1];
//            printf("
Werte: %d %d %d 
",GPIO_PIN[i][0],GPIO_PIN[i][1],GPIO_PIN[i][2]);
        }
        for(i=11;i<=12;i++)                                //(MISO(13)) (7.Relais) und (MOSI(12)) (8.Relais)
        {
            GPIO_PIN[i][1]=digitalRead(i);            //Liest GPIO-PINs in Array
            if (GPIO_PIN[i][2]!=GPIO_PIN[i][1]) {
                if (GPIO_PIN[i][1]==1) var_val="true";
                else var_val="false";
                printf("
GPIO-Pin hat sich geaendert GPIO_%d=%d -> senden
",i,GPIO_PIN[i][2]);
//                printf("
WerteGändert: %d %d %d 
",GPIO_PIN[i][0],GPIO_PIN[i][1],GPIO_PIN[i][2]);
                curl_senden(GPIO_PIN[i][0],var_val);
                delay(20);
            }    
            GPIO_PIN[i][2]=GPIO_PIN[i][1];
//            printf("
Werte: %d %d %d 
",GPIO_PIN[i][0],GPIO_PIN[i][1],GPIO_PIN[i][2]);
        }        
    delay(100);    //zur Stabilität nötig (sonst Aufruf doppelt/dreifach)
    }    
    return 0;
    printf("GPIO-Ueberwachung-Thread beendet
");
    pthread_exit((void *) 0);
}
 
void i2c_eingaenge1 (void)
{
    printf("I2C-Eingaenge1 Thread gestartet
");
    int i;
    for (;;)        //Endlosschleife
    {    
        //printf("Eingaenge1 ist jetzt wieder wach!%d 
",j);
        int dezzahl1;
        dezzahl1=wiringPiI2CRead (fd1);
        //printf("READ:  %i 
", dezzahl1);
        if (dezzahl1>=128) i2c_in_1[7][1]=1; else i2c_in_1[7][1]=0;
        if (dezzahl1%128>=64) i2c_in_1[6][1]=1; else i2c_in_1[6][1]=0;
        if (dezzahl1%64>=32) i2c_in_1[5][1]=1; else i2c_in_1[5][1]=0;
        if (dezzahl1%32>=16) i2c_in_1[4][1]=1; else i2c_in_1[4][1]=0;        
        if (dezzahl1%16>=8) i2c_in_1[3][1]=1; else i2c_in_1[3][1]=0;            
        if (dezzahl1%8>=4) i2c_in_1[2][1]=1; else i2c_in_1[2][1]=0;            
        if (dezzahl1%4>=2) i2c_in_1[1][1]=1; else i2c_in_1[1][1]=0;
        if (dezzahl1%2>=1) i2c_in_1[0][1]=1; else i2c_in_1[0][1]=0;
        for(i=0;i<=7;i++)                                                
        {
            if (i2c_in_1[i][2]!=i2c_in_1[i][1]) {
                if (i2c_in_1[i][1]==0) var_val="true";        //negative Logik
                else var_val="false";
                printf("
i2c_in_1-Pin hat sich geaendert i2c_in_1_%d=%d -> senden
",i,i2c_in_1[i][2]);
//                printf("
WerteGändert: %d %d %d 
",i2c_in_1[i][0],i2c_in_1[i][1],i2c_in_1[i][2]);
                curl_senden(i2c_in_1[i][0],var_val);
                delay(20);
            }
            i2c_in_1[i][2]=i2c_in_1[i][1];        //alten Wert setzen
        }
        //Stabilität Delay
        delay(100);                                                    
    }
    printf("I2C-Eingaenge1 Thread beendet
");
    pthread_exit((void *) 0);
}

void i2c_eingaenge2 (void)
{
    printf("I2C-Eingaenge2 Thread gestartet
");
    int i;
    for (;;)        //Endlosschleife
    {    
        //printf("Eingaenge1 ist jetzt wieder wach!%d 
",j);
        int dezzahl2;
        dezzahl2=wiringPiI2CRead (fd2);
        //printf("READ:  %i 
", dezzahl1);
        if (dezzahl2>=128) i2c_in_2[7][1]=1; else i2c_in_2[7][1]=0;
        if (dezzahl2%128>=64) i2c_in_2[6][1]=1; else i2c_in_2[6][1]=0;
        if (dezzahl2%64>=32) i2c_in_2[5][1]=1; else i2c_in_2[5][1]=0;
        if (dezzahl2%32>=16) i2c_in_2[4][1]=1; else i2c_in_2[4][1]=0;        
        if (dezzahl2%16>=8) i2c_in_2[3][1]=1; else i2c_in_2[3][1]=0;            
        if (dezzahl2%8>=4) i2c_in_2[2][1]=1; else i2c_in_2[2][1]=0;            
        if (dezzahl2%4>=2) i2c_in_2[1][1]=1; else i2c_in_2[1][1]=0;
        if (dezzahl2%2>=1) i2c_in_2[0][1]=1; else i2c_in_2[0][1]=0;
        for(i=0;i<=7;i++)                                                
        {
            if (i2c_in_2[i][2]!=i2c_in_2[i][1]) {
                if (i2c_in_2[i][1]==0) var_val="true";        //negative Logik
                else var_val="false";
                printf("
i2c_in_1-Pin hat sich geaendert i2c_in_1_%d=%d -> senden
",i,i2c_in_2[i][2]);
//                printf("
WerteGändert: %d %d %d 
",i2c_in_2[i][0],i2c_in_2[i][1],i2c_in_2[i][2]);
                curl_senden(i2c_in_2[i][0],var_val);
                delay(20);    
            }
            i2c_in_2[i][2]=i2c_in_2[i][1];        //alten Wert setzen
        }
        //Stabilität Delay
        delay(100);                                                    //um Schreiben in Modbus zu ermöglichen
    }
    printf("I2C-Eingaenge2 Thread beendet
");
    pthread_exit((void *) 0);
}

void i2c_ausgaenge1 (void)
{
    printf("I2C-Ausgaenge1 Thread gestartet
");
    int i;
    for (;;)        //Endlosschleife
    {    
        //printf("Eingaenge1 ist jetzt wieder wach!%d 
",j);
        int dezzahl2;
        dezzahl2=wiringPiI2CRead (fd3);
        //printf("READ:  %i 
", dezzahl1);
        if (dezzahl2>=128) i2c_out_1[7][1]=1; else i2c_out_1[7][1]=0;
        if (dezzahl2%128>=64) i2c_out_1[6][1]=1; else i2c_out_1[6][1]=0;
        if (dezzahl2%64>=32) i2c_out_1[5][1]=1; else i2c_out_1[5][1]=0;
        if (dezzahl2%32>=16) i2c_out_1[4][1]=1; else i2c_out_1[4][1]=0;        
        if (dezzahl2%16>=8) i2c_out_1[3][1]=1; else i2c_out_1[3][1]=0;            
        if (dezzahl2%8>=4) i2c_out_1[2][1]=1; else i2c_out_1[2][1]=0;            
        if (dezzahl2%4>=2) i2c_out_1[1][1]=1; else i2c_out_1[1][1]=0;
        if (dezzahl2%2>=1) i2c_out_1[0][1]=1; else i2c_out_1[0][1]=0;
        for(i=0;i<=7;i++)                                                //Input 3-7 mit EinzelMeldungen belegt (alle belegt)
        {
            if (i2c_out_1[i][2]!=i2c_out_1[i][1]) {
                if (i2c_out_1[i][1]==0) var_val="true";        //negative Logik
                else var_val="false";
                printf("
i2c_out_1-Pin hat sich geaendert i2c_out_1%d=%d -> senden
",i,i2c_out_1[i][2]);
//                printf("
WerteGändert: %d %d %d 
",i2c_out_1[i][0],i2c_out_1[i][1],i2c_out_1[i][2]);
                curl_senden(i2c_out_1[i][0],var_val);
                delay(20);
            }
            i2c_out_1[i][2]=i2c_out_1[i][1];        //alten Wert setzen
        }
        //Stabilität Delay
        delay(100);                                                    //um Schreiben in Modbus zu ermöglichen
    }
    printf("I2C-Eingaenge2 Thread beendet
");
    pthread_exit((void *) 0);
}


int gpio_init(void)
{
    printf ("GPIO Init
") ;
    int n;
    if (wiringPiSetup () == -1)  //Startet Wiring API - wichtig
        return 1;                 //return von wiringPi
    //Initialisierung
    GPIO_PIN[0][0]=39331;    //
    GPIO_PIN[1][0]=50705;    //
    GPIO_PIN[2][0]=37099;    //n.B.
    GPIO_PIN[3][0]=55615;    //n.B.
    GPIO_PIN[4][0]=59727;    //n.B.
    GPIO_PIN[5][0]=36450;    //n.B.
    GPIO_PIN[6][0]=32653;    //
    GPIO_PIN[12][0]=26939;    //MOSI 
    GPIO_PIN[13][0]=44638;    //MISO
    for(n=0;n<=6;n++) pinMode(n, OUTPUT);    //PIN7 (entspricht auch GPIO7 ist für 1-Wire genutzt)
    pinMode(12,OUTPUT);       //entspricht in Konsole "gpio mode 12 out"
    pinMode(13,OUTPUT);       //entspricht in Konsole "gpio mode 13 out"    
    //
    i2c_in_1[0][0]=26057;    //00 
    i2c_in_1[1][0]=43699;
    i2c_in_1[2][0]=48692;
    i2c_in_1[3][0]=20600;
    i2c_in_1[4][0]=23055;
    i2c_in_1[5][0]=53358;
    i2c_in_1[6][0]=27936;
    i2c_in_1[7][0]=27534;    //70 
    //
    i2c_in_2[0][0]=12723;    //00 
    i2c_in_2[1][0]=47937;
    i2c_in_2[2][0]=33003;
    i2c_in_2[3][0]=13296;
    i2c_in_2[4][0]=41542;
    i2c_in_2[5][0]=56398;
    i2c_in_2[6][0]=42606;
    i2c_in_2[7][0]=36428;
    //
    //
    //
    if((fd1=wiringPiI2CSetup(dID1))<0){
        printf("error opening i2c channel Eingabekarte-1
\r");
    }
    if((fd2=wiringPiI2CSetup(dID2))<0){
        printf("error opening i2c channel Eingabekarte-1
\r");
    }    
    if((fd3=wiringPiI2CSetup(dID3))<0){
        printf("error opening i2c channel Ausgabekarte-1
\r");
    }    
    delay(100);
    if((e=wiringPiI2CWrite(fd3,0))<0)        {     //initial auf Null - wichtig
        printf("error writing to slave
\r");  
    }    //Ende I2C RELAISKARTE
    //
    i2c_out_1[0][0]=55868;
    i2c_out_1[1][0]=37960;
    i2c_out_1[2][0]=15286;
    i2c_out_1[3][0]=50020;
    i2c_out_1[4][0]=24998;
    i2c_out_1[5][0]=47589;
    i2c_out_1[6][0]=10178;
    i2c_out_1[7][0]=50968;    
    //
    return 1;
}    

int main(void)
{
    gpio_init();
    printf( "Raspi-Symcon-Dienst gestartet ....
");
//
    if(pthread_create(&t1, NULL, (void *)&gpio_thread,NULL) != 0)
    {
      fprintf(stderr, "Fehler bei gpio_thread 1....
");
      exit(0);
    }
    if(pthread_create(&t2, NULL, (void *)&i2c_eingaenge1,NULL) != 0)
    {
      fprintf(stderr, "Fehler bei Thread 2  I2C-Eingaenge 1.....
");
      exit(0);
    }    
    if(pthread_create(&t3, NULL, (void *)&i2c_eingaenge2,NULL) != 0)
    {
      fprintf(stderr, "Fehler bei Thread 3  I2C-Eingaenge 2.....
");
      exit(0);
    }
    if(pthread_create(&t4, NULL, (void *)&lifebit,NULL) != 0)
    {
      fprintf(stderr, "Fehler bei Thread 4  LifeBit.....
");
      exit(0);
    }    
    if(pthread_create(&t5, NULL, (void *)&i2c_ausgaenge1,NULL) != 0)
    {
      fprintf(stderr, "Fehler bei Thread 5  I2C-Ausgabekarte 1.....
");
      exit(0);
    }        
    for(;;) 
    {
        delay(1500);    //ohne delay Prozessorleistung 100%
    }
    return 0;
}

mehr quick & dirty - funktioniert aber ;-)))))

Hallo herbertf ,

das einlesen der GPIO’s funktioniert super, tolle arbeit.

Ich habe jedoch ein problem mit der Prozessorauslastung (100%) wenn das Programm läuft.
Hast du eine Idee woran das liegen könnte?

/*
Dieser Dienst sendet die lokalen Eingänge (GPIOs ..) an den lokalen IP-Symcon-Dienst
Ver: 2.1
- Übertragung binärer Zustände an IPS, bei deren Änderung
- I2C Unterstützung
*/

#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <curl/curl.h>
#include <pthread.h>

// Threads: http://pronix.linuxdelta.de/C/Linuxprogrammierung/Linuxsystemprogrammieren_C_Kurs_Kapitel8.shtml
pthread_t t1,t2,t3,t4;
int var_id,i;
char* var_val;
int GPIO_PIN[17][3]={{0},{0},{0}};		//GPIO-PIN  Array 0=0-7 1=val_id 2=aktuellerWert 3=alterWert

void curl_senden (int var_id, char* var_val)
{
  CURL *curl;
  CURLcode res;
  curl_global_init(CURL_GLOBAL_ALL);
   /* get a curl handle */ 
  curl = curl_easy_init();
  //printf("
var_id= %d var_val= %s
",var_id,var_val);
  if(curl) {
    const int MAX_BUF =1000;
	char* jsonObj = malloc(MAX_BUF);
    sprintf(jsonObj,"{\"jsonrpc\": \"2.0\",\"method\":\"SetValue\",\"params\":[%i,%s],\"id\":1}",var_id,var_val); 
	printf("JSON-String= %s gesandt
",jsonObj);
	struct curl_slist *headers = NULL;
	headers = curl_slist_append(headers, "Accept: application/json");
	headers = curl_slist_append(headers, "Content-Type: application/json");
	headers = curl_slist_append(headers, "charsets: utf-8");
    curl_easy_setopt(curl, CURLOPT_URL, "http://192.168.100.240:3777/api/");	
  	curl_easy_setopt(curl, CURLOPT_USERPWD, "User:Pass"); 	
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); 
	curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonObj);	
    res = curl_easy_perform(curl);
     /* Check for errors */ 
    if(res != CURLE_OK)
      fprintf(stderr, "curl_easy_perform() failed: %s
",
              curl_easy_strerror(res));
    /* always cleanup */
    curl_easy_cleanup(curl);
  }
  curl_global_cleanup();
  printf("
");
  return;
}

int gpio_thread (void)	//
{
	printf("
GPIO-Ueberwachung-Thread gestartet
");
	for(;;) 
	{
		for(i=0;i<=7;i++)								//7Output-Ports GPIO 0-6  (7 ist 1-Wire)
		{
			GPIO_PIN[i][1]=digitalRead(i);			//Liest GPIO-PINs in Array
			if (GPIO_PIN[i][2]!=GPIO_PIN[i][1]) {
				if (GPIO_PIN[i][1]==1) var_val="true";
				else var_val="false";
				printf("
GPIO-Pin hat sich geaendert GPIO_%d=%d -> senden
",i,GPIO_PIN[i][2]);
//				printf("
WerteGändert: %d %d %d 
",GPIO_PIN[i][0],GPIO_PIN[i][1],GPIO_PIN[i][2]);
				curl_senden(GPIO_PIN[i][0],var_val);
			}	
			GPIO_PIN[i][2]=GPIO_PIN[i][1];
//			printf("
Werte: %d %d %d 
",GPIO_PIN[i][0],GPIO_PIN[i][1],GPIO_PIN[i][2]);
		}
	sleep(1);
	}	
	return 0;
	printf("GPIO-Ueberwachung-Thread beendet
");
	pthread_exit((void *) 0);
}



int gpio_init(void)
{
	printf ("GPIO Init
") ;
	int n;
	if (wiringPiSetup () == -1)  //Startet Wiring API - wichtig
		return 1;				 //return von wiringPi
	//Initialisierung
	GPIO_PIN[0][0]=10468;
	GPIO_PIN[1][0]=14413;
	GPIO_PIN[2][0]=10402;
	GPIO_PIN[3][0]=58587;
	GPIO_PIN[4][0]=51601;
	GPIO_PIN[5][0]=38235;
	GPIO_PIN[6][0]=41525;
	GPIO_PIN[7][0]=38291;
	for(n=0;n<=7;n++) pinMode(n, OUTPUT);	
	return 1;
}	

int main(void)
{
	gpio_init();
	printf( "Raspi-Symcon-Dienst gestartet ....
");
	//

	if(pthread_create(&t1, NULL, (void *)&gpio_thread,NULL) != 0)
	{
	  fprintf(stderr, "Fehler bei gpio_thread 1....
");
	  exit(0);
	}
	for(;;);
  return 0;
}

Hi,

wie in meinem Beitrag vorher, ganz unten:

    
for(;;) 
    {
        delay(1500);    //ohne delay Prozessorleistung 100%
    }

herbertf

Hi,

hab mich heut mal an die Arbeit gemacht die GPIO´s zum leben zu erwecken…
Habe IPS auf einem Raspberry Pi installiert, muß man bei deinem erstem Skript irgend etwas anpassen?
Bei mir schaltet er den Ausgang nicht durch, wenn ich den Befehl direkt im Raspi eingebe dann funzt es.

Gruß Stefan

Hi Stefan,

hast Du folgendes schon getan?

//Voraussetzungen:
//Falls noch nicht erfolgt wiringPI installieren
//http://wiringpi.com/download-and-install/

herbertf

Hi,
ja das hab ich gemacht das funktioniert auch, hab das so geschrieben jetzt geht’s.

shell_exec("/usr/local/bin/gpio -g write 17 1");

Dann hätte ich aber doch noch eine Frage zu auslesen de Temperaturfühlers, da gibt er bei mir nen Fehler raus

Variable #19624 does not exist in /usr/share/symcon/scripts/16365.ips.php on line 20

kannst mir da sagen was ich da falsch gemacht habe?

Gruß Stefan

Hi,
ist der Anhang nicht mehr Online?
Danke

Gruß
Stefan