Hey @all!
First at all I wanna say Gene thanks for his great program.
This is really the best HomeAutomation software I've seen yet!
But I am a very beginner regarding Homegenie and still learning a lot.
I want to hook up a PCF8574 expander to HomeGenie to control small relais cards with 4 inputs and outputs. I saw in the source of raspberry-sharp-io that there is already a class for it.
I changed the MCP23017 sample in HomeGenie to the following code:
var moduleDomain = "Components.PCF8475x";
var pinConfiguration = new List<dynamic>(){
new { Address = "1", Pin = Raspberry.IO.Components.Expanders.Pcf8574.Pcf8574Pin.P0, Direction = "Out" },
new { Address = "2", Pin = Raspberry.IO.Components.Expanders.Pcf8574.Pcf8574Pin.P1, Direction = "Out" },
new { Address = "3", Pin = Raspberry.IO.Components.Expanders.Pcf8574.Pcf8574Pin.P2, Direction = "Out" },
new { Address = "4", Pin = Raspberry.IO.Components.Expanders.Pcf8574.Pcf8574Pin.P3, Direction = "Out" },
new { Address = "5", Pin = Raspberry.IO.Components.Expanders.Pcf8574.Pcf8574Pin.P4, Direction = "In" },
new { Address = "6", Pin = Raspberry.IO.Components.Expanders.Pcf8574.Pcf8574Pin.P5, Direction = "In" },
new { Address = "7", Pin = Raspberry.IO.Components.Expanders.Pcf8574.Pcf8574Pin.P6, Direction = "In" },
new { Address = "8", Pin = Raspberry.IO.Components.Expanders.Pcf8574.Pcf8574Pin.P7, Direction = "In" }
//
};
bool[] pinStatus = new bool[8];
var sdaPin = ConnectorPin.P1Pin03.ToProcessor();
var sclPin = ConnectorPin.P1Pin05.ToProcessor();
var I2CTreiber = new I2cDriver(sdaPin, sclPin);
var I2CConnection = new Raspberry.IO.Components.Expanders.Pcf8574.Pcf8574I2cConnection(I2CTreiber.Connect(0x38));
When.WebServiceCallReceived(moduleDomain, ( args ) =>
{
string[] reqs = ((string)args).Split('/');
var errormessage = "";
try
{
string pinid = reqs[1];
string command = reqs[2];
//
var module = Modules.InDomain(moduleDomain).WithAddress(pinid).Get();
var pinname = "";
var i = int.Parse(pinid);
pinname = "P" + (i - 1).ToString();
//
var mcppin = (Raspberry.IO.Components.Expanders.Pcf8574.Pcf8574Pin)Enum.Parse(typeof(Raspberry.IO.Components.Expanders.Pcf8574.Pcf8574Pin), pinname);
switch(command)
{
// eg. http://hg_address/api/Expanders.MCP23017/1/Control.On
case "Control.On":
I2CConnection.SetPinStatus(mcppin, true);
break;
// eg. http://hg_address/api/Expanders.MCP23017/3/Control.Off
case "Control.Off":
I2CConnection.SetPinStatus(mcppin, false);
break;
// eg. http://hg_address/api/Expanders.MCP23017/9/Control.Toggle
case "Control.Toggle":
I2CConnection.Toogle(mcppin);
break;
}
Program.RaiseEvent(module, "Status.Level",
I2CConnection.GetPinStatus(mcppin) ? "1" : "0",
"PCF8574 " + pinname);
//
return "{ 'ResponseValue' : 'OK' }";
}
catch (Exception ex)
{
errormessage = ex.Message + " " + ex.StackTrace;
}
// unable to process request
return "{ 'ResponseValue' : 'ERROR " + errormessage + "' }";
});
for (int p = 0; p < pinConfiguration.Count; p++)
{
var pincfg = pinConfiguration[p];
if(pincfg.Direction == "In")
{
Raspberry.IO.Components.Expanders.Pcf8574.Pcf8574PinExtensionMethods.In(I2CConnection, pincfg.Pin);
Program.AddVirtualModule(moduleDomain, pincfg.Address, "Sensor", "homegenie/generic/sensor");
}
else
{
Raspberry.IO.Components.Expanders.Pcf8574.Pcf8574PinExtensionMethods.Out(I2CConnection, pincfg.Pin);
Program.AddVirtualModule(moduleDomain, pincfg.Address, "Switch", "");
}
// get the module associated to the pin and store current status
var module = Modules.InDomain(moduleDomain).WithAddress(pincfg.Address).Get();
module.Parameter("Status.Level").Value = (pinStatus[p] ? "1" : "0");
}
// status polling loop
while (Program.IsEnabled)
{
Pause(0.5); // 500 ms poll resolution
//
for (int p = 0; p < pinConfiguration.Count; p++)
{
var pincfg = pinConfiguration[p];
if (p>3)
{
bool status = I2CConnection.GetPinStatus(pincfg.Pin);
// check if the pin status changed
if (pinStatus[p] != status)
{
// get the module associated to the pin
var module = Modules.InDomain(moduleDomain).WithAddress(pincfg.Address).Get();
// raise the event and update the current pin status
Program.RaiseEvent(module, "Status.Level",
status ? "1" : "0",
"PCF8574 " + pincfg.Pin.ToString());
pinStatus[p] = status;
Pause(0.1);
}
}
}
}
When I add now the items to HomeGenie the outputs work all fine.
But the inputs are always on false.
I checked the voltage at the IC directly. When I boot up the pi, all inputs are on "high", that means the current source is activated and I have an internal pull-up.
When HomeGenie started, all inputs are on "low". So I have no chance to get a high level.
I checked the communication to the IC with the i2c-tools and everything seems to work. With i2cget command I can see every change at the inputs.
I know that there have to be written a "0" to activate the internal pull-up on high for the outputs. But I cannot find my mistake in the code.
Does somebody have a working code example so I can get this thing running?
And why is the SetInputPin method in PCF8574 class in raspberry-sharp-io only accessible by internal? So I have to use the PinExtensions method to set a pin as an input.
Thanks a lot!