Dezimalwert auf 8 Bit Variablen aufteilen (DEZ nach BIN)

Hallo,
ich lese einen PCF8574( 8-Bit I/O Expander für I2C-Bus) ein. Ich benutze 8 digitale Eingänge von dem PCF8574. Dieser ist an einer Pokeys Platine angeschlossen und liefert mir eine Variable mit den Werten 0-255, je nachdem welcher Eingang/Eingänge gesetzt sind.
Jeder der 8 Eingänge soll nun eine von 8 Variable auf 1 oder 0 setzen.

Beispiel:
Der Wert 0 soll alle 8 Variablen auf 0 setzen.
Der Wert 16 soll die Variable5 auf 1 setzten, alle Anderen auf 0.

Wie macht man das?

Gruß, Tobias

Hast Du vor den Wert in PoBlock zu verwenden oder in IP-Symcon?

Wenn in PoBlock poste mal das gezippte XML-File

Gruß Helmut

Poblock nehme ich nur um die Daten an ips zu schieben, dass geht sehr gut. Aber das zerlegen in ips macht mir zu schaffen

Mal quick&dirty


//Array mit variableids der 8 variablen ablegen, variable0 zuerst, ANPASSEN!
$varids=array(11111,12222,13333,14444,15555,16666,17777,18888);
$value=144; //Beispiel Bit7+Bit4 gesetzt
$bin=decbin($value);
echo $bin;
for ($i=0;$i<8; $i++) {
  $id=$varids[$i];
  $bit=$bin[7-$i];
  echo "Bit $i:$bit
";
  setvalue($id,$bit);
}

Tommi

Aus dem WWW geliehen:


<?
$PokeysWert= GetValueInteger(12345(VariablenID) der Modbusleseadr);
$bit = 3; // das vierte Bit
echo($PokeysWert&(1<<$bit))?'Yes, Bit gesetzt':'Leider nicht';
?>

Gruß Helmut
Edit Tommi gar nicht gesehen

Hallo Tommi, Hallo Helmut,

@Tommi: das Skript funktioniert bedingt. Damit es funktioniert, muss immer das 8te Bit gesetzt sein. Sobald dieses fehlt kommt eine Fehlermeldung, weil in der Variable „$bin“ die „0“ für das achte Bit (wenn es null ist) nicht angezeigt wird und dann auf eine Stelle(achtes Bit) zugegriffen wird, die es nicht gibt - bzw. eigendlich „0“ ist:

Wert: 127
BIN: 1111111 —>> hier ist der Fehler: es müsste 01111111 angezeigt werden

Notice: Uninitialized string offset: 7 in C:\IP-Symcon\scripts\39698.ips.php on line 11
Bit 0:

Warning: Cannot auto-convert to Boolean from Variant. Error: Invalid argument in C:\IP-Symcon\scripts\39698.ips.php on line 13
Bit 1:1
Bit 2:1
Bit 3:1
Bit 4:1
Bit 5:1
Bit 6:1
Bit 7:1


<?

//Array mit variableids der 8 variablen ablegen, variable0 zuerst, ANPASSEN!
$varids=array(17769 /*[TEST\Var1]*/,17954 /*[TEST\Var2]*/,26212 /*[TEST\Var3]*/,29221 /*[TEST\Var4]*/,30605 /*[TEST\Var5]*/,43628 /*[TEST\Var6]*/,48331 /*[TEST\Var7]*/,50273 /*[TEST\Var8]*/);
$value=GetValue(28594 /*[PoKey_EG214\SharedData1000\Value]*/); //Beispiel Bit7+Bit4 gesetzt
echo "Wert: $value 
";
$bin=decbin($value); //von Dezimal nach Binär
echo "BIN: $bin 
";
for ($i=0;$i<8; $i++) { //Schleife von 0 bis 7
  $id=$varids[$i]; //Variable aus Array auswählen
  $bit=$bin[7-$i]; //Bit aus Bin wählen
  echo "Bit $i:$bit
";
  setvalue($id,$bit);
}

echo "Helmut: 
";
$PokeysWert= GetValueInteger(28594 /*[PoKey_EG214\SharedData1000\Value]*/);
$bit = 7; // das achte Bit
echo($PokeysWert&(1<<$bit))?'Yes, Bit gesetzt':'Leider nicht';

?>

@Helmut dein Skript funktioniert, leider habe ich die Funktion nicht verstanden - genau genommen die letzte Zeile:


echo($PokeysWert&(1<<$bit))?'Yes, Bit gesetzt':'Leider nicht';

Vielleicht kannst du mir die Funktion erklären.
Für meinen Zweck müsste ich dann noch das Array von Oben übernehmen, damit die Werte in die 8 Variablen geschrieben werden.

Gruß, Tobias

Eigentlich sollte Dich mein aus dem Handgelenk geschriebenes Script nur auf den grundsätzlichen Lösungsweg hinweisen.
Du darfst auch selber nachdenken und das Script an Deine Bedürfnisse anpassen. Z.b. die für Dich problematische decbin() Funktion durch was passenderes ersetzen (schau mal nach sprintf() was Dich sofort ans Ziel bringt) oder Dich wie von Helmut vorgeschlagen an Bitschiebeoperationen in der for Schleife versuchen.

Tommi

Grundsätzlich hat Tommi Recht, man muß die PHP Möglichkeiten selber herausfinden, dann bleibt es hängen.

Allerdings fällt es „nicht Programmierern“ extrem schwer überhaupt heraus zu finden nach was er suchen soll, wie der Lösungsweg aussehen könnte.

Dann kommt noch dazu, dass er das Pokeysmodul nutzt, dann muß ich hier was schreiben :wink:

Grundsätzlich findet in meinem Beispiel [QUOTE]$PokeysWert&(1<<$bit))? [ /QUOTE]eine Bitschieberei (da wo die Pfeile sind) statt, die Du in dem nachfolgenden Script „einzeln“ an der Verschiebung der „1“ im Vergleich siehst.

Dann schreibe ich in Abhängigkeit der UND Verknüpfung die Variablen, gebe das Ergebnis also nicht als Text aus.

Wenn Du es nutzen willst, Modbusinstanz ist klar, dazu mußt Du noch 8 Boolean/Bitvariablen anlegen, oder Du beschreibst in der entsprechenden Schleife Deine genutzten Variablen direkt.

 <?
$Wert= GetValueInteger(10494 /*ID Deiner Modbusvariable*/);
If ($Wert & 0b00000001)
{
SetValueBoolean(20240 /*[Test\Bit0]*/, true);
}
else
{
SetValueBoolean(20240 /*[Test\Bit0]*/, false);
}
If ($Wert & 0b00000010)
{
SetValueBoolean(26120 /*[Test\Bit1]*/, true);
}
else
{
SetValueBoolean(26120 /*[Test\Bit1]*/, false);
}
If ($Wert & 0b00000100)
{
SetValueBoolean(43003 /*[Test\Bit2]*/, true);
}
else
{
SetValueBoolean(43003 /*[Test\Bit2]*/, false);
}
If ($Wert & 0b00001000)
{
SetValueBoolean(40069 /*[Test\Bit3]*/, true);
}
else
{
SetValueBoolean(40069 /*[Test\Bit3]*/, false);
}

If ($Wert & 0b00010000)
{
SetValueBoolean(43155 /*[Test\Bit4]*/, true);
}
else
{
SetValueBoolean(43155 /*[Test\Bit4]*/, false);
}
If ($Wert & 0b00100000)
{
SetValueBoolean(47246 /*[Test\Bit5]*/, true);
}
else
{
SetValueBoolean(47246 /*[Test\Bit5]*/, false);
}
If ($Wert & 0b01000000)
{
SetValueBoolean(53187 /*[Test\Bit6]*/, true);
}
else
{
SetValueBoolean(53187 /*[Test\Bit6]*/, false);
}
If ($Wert & 0b100000000)
{
SetValueBoolean(34868 /*[Test\Bit7]*/, true);
}
else
{
SetValueBoolean(34868 /*[Test\Bit7]*/, false);
}
?>

Gruß Helmut

Hallo Tommi,
vielen Dank für den Hinweis und den tollen Link auf „sprintf()“. Aber wie Helmut schon schrieb, ist es für einen Nichtprogrammierer schwierig zu wissen, wonach man sucht. Da ich erst mit PHP anfange, begnüge ich mich damit vorhandene Skripte zu verstehen und zu verändern.
Das Skript von dir habe ich nun zum laufen bekommen - der Befehl heißt: $bin=sprintf("%’.08d
", $bin);
Dadurch wird die Variable mit Nullen aufgefüllt, bis die Variable 8 Stellen hat :slight_smile: Danke


 <?
//Array mit variableids der 8 variablen ablegen, variable0 zuerst, ANPASSEN!
$varids=array(17769 /*[TEST\Var1]*/,17954 /*[TEST\Var2]*/,26212 /*[TEST\Var3]*/,29221 /*[TEST\Var4]*/,30605 /*[TEST\Var5]*/,43628 /*[TEST\Var6]*/,48331 /*[TEST\Var7]*/,50273 /*[TEST\Var8]*/);
$value=GetValue(28594 /*[PoKey_EG214\SharedData1000\Value]*/); //Variable von PCF8574 auswählen
echo "Wert: $value 
";
$bin=decbin($value); //von Dezimal nach Binär
echo "BIN: $bin 
";
echo sprintf("%'.08d
", $bin);
$bin=sprintf("%'.08d
", $bin);
echo "BIN_neu: $bin 
";
for ($i=0;$i<8; $i++) { //Schleife von 0 bis 7
  $id=$varids[$i]; //Variable aus Array auswählen
  $bit=$bin[7-$i]; //Bit aus Bin wählen
  echo "Bit $i:$bit
";
  setvalue($id,$bit);
}

?>

Hallo Helmut,
ich habe mir die „BitSchieberei“ mal angesehen. Ich glaube ich habe es verstanden :smiley:
schön, dass du es so ausführlich geschrieben hast.
(in der letzten If-Bedingung ist eine 0 zu viel)

Nun kann ich den PCF8574 mit IPS verarbeiten - eine günstige Möglichkeit, um die PoKeysplatine über I²C mit Eingängen zu erweitern.

Gruß, Tobias

Du willst viele Eingänge, so um 43 und viele Ausgänge, so um 32, alle Optoentkoppelt und mit ULN Treibern?

Dann schau mal hier mit Hut 12 Gehäuse
Gruß Helmut