// Add analog channels modules
Program.AddVirtualModule("Components.MCP3008", "CH0", "Sensor", "homegenie/generic/sensor");
Program.AddVirtualModule("Components.MCP3008", "CH1", "Sensor", "homegenie/generic/sensor");
Program.AddVirtualModule("Components.MCP3008", "CH2", "Sensor", "homegenie/generic/sensor");
Program.AddVirtualModule("Components.MCP3008", "CH3", "Sensor", "homegenie/generic/sensor");
Program.AddVirtualModule("Components.MCP3008", "CH4", "Sensor", "homegenie/generic/sensor");
Program.AddVirtualModule("Components.MCP3008", "CH5", "Sensor", "homegenie/generic/sensor");
Program.AddVirtualModule("Components.MCP3008", "CH6", "Sensor", "homegenie/generic/sensor");
Program.AddVirtualModule("Components.MCP3008", "CH7", "Sensor", "homegenie/generic/sensor");
Program.AddFeature("Components.MCP3008", "Sensor", "AnalogInput.ParameterName", "1 - Parameter name to store computed value", "text");
Program.AddFeature("Components.MCP3008", "Sensor", "AnalogInput.ParameterRawAdjust", "2 - Raw value Offset", "text");
Program.AddFeature("Components.MCP3008", "Sensor", "AnalogInput.ParameterFactor", "3 - Multiplicative (M Factor)", "text");
Program.AddFeature("Components.MCP3008", "Sensor", "AnalogInput.ParameterAdjust", "4 - Additive (A Factor)", "text");
Program.AddFeature("Components.MCP3008", "Sensor", "AnalogInput.StabilizeValue", "5 - Soft stabilize value (yes/no)", "text");
// add program configuration parameters
Program.AddOption("PollFrequency", "10", "Pause between updates (seconds)", "text");
Program.Run();
const string MCP3008_DOMAIN = "Components.MCP3008";
const decimal voltage = 3.3m;
var valuesHistory = new Queue<decimal>[8];
// Initialize value history queue for Soft Stabilize feature
for (int q = 0; q < 8; q++) valuesHistory[q] = new Queue<decimal>();
// Setup MCP3008 SPI connection
var adcClock = ConnectorPin.P1Pin23.ToProcessor();
var adcMiso = ConnectorPin.P1Pin21.ToProcessor();
var adcMosi = ConnectorPin.P1Pin19.ToProcessor();
var adcCs = ConnectorPin.P1Pin24.ToProcessor();
var driver = GpioConnectionSettings.DefaultDriver;
driver.Allocate(adcClock, PinDirection.Output);
driver.Allocate(adcCs, PinDirection.Output);
driver.Allocate(adcMosi, PinDirection.Output);
driver.Allocate(adcMiso, PinDirection.Input);
var adcConnection = new Mcp3008SpiConnection(
driver.Out(adcClock),
driver.Out(adcCs),
driver.In(adcMiso),
driver.Out(adcMosi)
);
// Release allocated resource when program is stopping
When.ProgramStopping(()=>{
try
{
((IDisposable)adcConnection).Dispose();
} catch (Exception e) { Program.Notify("MCP3008 Error", e.Message); }
((IDisposable)driver).Dispose();
return true;
});
var ReadChannel = new Func<int, AnalogValue>((channel) => {
AnalogValue av = null;
lock (adcConnection)
{
av = adcConnection.Read((Mcp3008Channel)(channel));
}
return av;
});
// eg: GET /api/Components.MCP3008/CH2/ChannelValue.Get
When.WebServiceCallReceived(MCP3008_DOMAIN, ( args ) => {
object response = null;
var options = ((string)args).Split('/');
var channel = int.Parse(options[1].Replace("CH", ""));
var command = options[2];
if (command == "ChannelValue.Get")
{
response = ReadChannel(channel);
}
return response;
});
// Main program loop
while (Program.IsEnabled)
{
double pauseseconds = double.Parse(Program.Option("PollFrequency").Value);
if (pauseseconds < 1) pauseseconds = 1;
// read channel voltage values and map/normalize configured parameter names
for(int x = 0; x < 8; x++)
{
var channelPrefix = "CH" + x.ToString();
var channelModule = Modules.InDomain(MCP3008_DOMAIN).WithAddress(channelPrefix).Get();
var parameterName = channelModule.Parameter("AnalogInput.ParameterName").Value;
var parameterFactor = (decimal)channelModule.Parameter("AnalogInput.ParameterFactor").DecimalValue;
var parameterAdjust = (decimal)channelModule.Parameter("AnalogInput.ParameterAdjust").DecimalValue;
var parameterRawAdjust = (decimal)channelModule.Parameter("AnalogInput.ParameterRawAdjust").DecimalValue;
if (parameterFactor != 0)
{
var v = ReadChannel(x).Value;
valuesHistory[x].Enqueue(v);
// Software value stabilization
if (channelModule.Parameter("AnalogInput.StabilizeValue").Value.ToLower().StartsWith("y"))
{
decimal avg = 0;
foreach(decimal sv in valuesHistory[x]) avg += sv;
v = (decimal)Math.Round(avg / (decimal)valuesHistory[x].Count, 0);
// prefer smoothed value
valuesHistory[x].Dequeue();
valuesHistory[x].Enqueue(v);
}
if (valuesHistory[x].Count > 5) valuesHistory[x].Dequeue();
Program.RaiseEvent(channelModule,
"Sensor.RawValue",
v.ToString(),
":nopopup:Analog Channel");
if (parameterName != "")
{
var adjustedValue = ((v + parameterRawAdjust)* parameterFactor) + parameterAdjust;
adjustedValue = (Math.Round(adjustedValue * 10m / 5m, 0) * 5m / 10m); // 0.5 resolution
Program.RaiseEvent(channelModule,
parameterName,
adjustedValue.ToString(),
":nopopup:Analog Channel");
}
}
Pause(0.05);
}
Pause( pauseseconds );
}
HomeAutomation.HomeGenie.Automation
1037
MCP3008 - Analog Input Modules
MCP3008 8 channels ADC connected to SPI interface.
Infrastructure
text
Components.MCP3008
Sensor
AnalogInput.ParameterName
1 - Parameter name to store computed value
text
Components.MCP3008
Sensor
AnalogInput.ParameterRawAdjust
2 - Raw value Offset
text
Components.MCP3008
Sensor
AnalogInput.ParameterFactor
3 - Multiplicative (M Factor)
text
Components.MCP3008
Sensor
AnalogInput.ParameterAdjust
4 - Additive (A Factor)
text
Components.MCP3008
Sensor
AnalogInput.StabilizeValue
5 - Soft stabilize value (yes/no)
true
2022-08-16T10:00:42.277259Z
CSharp
true