question

bigbadbob76 avatar image
bigbadbob76 asked

Inergrating Generator Running input to flow overview.

Hi Folks.

my system consists of a multiplus with a DSE333 generator control panel doing the input transfer switching between grid and generator and a raspberry pi running venus V2.66.

I'm looking to modify the flow overview gui page to show the AC input as "generator" (with generator icon) when genny is running and "Grid" when connected to grid.

I have set up my venus to see the generator running signal from the DES panel on GPIO2, this works and the device page shows generator state= running when I take GPIO2 low. :-)

I have tried Kevin's "GeneratorConnector" script but it's not designed to do what I want to do.

So I have modified /opt/victronenergy/gui/qml/overviewpage.qml to show generator text and icon manually. see below.

So far so good, but can anyone point me to where I can pick up the generator "running" state that shows on the device>generator page?

function getAcSourceIcon(type)
{
if (type === undefined)
return "";
if (type === 240)
return ""
//if (I need to put something here but not sure what)
return "overview-generator-power"  // this works but is not controlled by gpio
return acSourceIcon[type]
}

function getAcSourceName(type)
{
if (type === undefined)
return qsTr("AC Input")
if (type === 240)
return 
//if (I need to put something here but not sure what)
return qsTr("Generator") //this works too.
return acSourceName[type]
}
Generator
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

9 Answers
Kevin Windrem avatar image
Kevin Windrem answered ·

You use the state of the digital input as I do in startstop.py in GeneratorConnector

You need to discover which input is configured to indicate if the generator is running, then use the value of /State to modify you title for the AC input tile.

If you hard code the digital input to be used, you can bypass the discovery process I do in startstop.py.

Set the service path to that of your digital input service as shown in dbus-spy. (You must configure one of the digital inputs to something or there will not be a related service. I recommend Generator since it's more appropriate than other functions.)


How you get dbus parameters depends on how you use them in the qml code.

In one case, you set a property to a VBusItem, then test the value of the item.

In another case, you set up a VBusItem and have its onValueChanged event to call a function.

Here are some examples from another project:


    property VBusItem inverterModeItem: VBusItem { bind: Utils.path(inverterService, "/Mode" ) }

function someFunction ()
{
     var inverterMode = inverterModeItem.valid ? inverterModeItem.value : 0
}

or

TileText {
            text: inverterModeItem.valid ? inverterModeItem.value === 1 ? "true" " "false" : "not valid"
}


This can be used because the TileText text property is updated when there's a change to its value.

The other way is useful if a set of properties or other settings depend on many dbus parameters and it's too complicated to equate a property to them. In this case, you'd set one or more properties inside a function then call that function with onValueChanged.

    VBusItem
    {
        id: inverterContinuousPowerItem
        bind: Utils.path("com.victronenergy.settings", "/Settings/GuiMods/GaugeLimits/ContiuousPower")
        onValueChanged: setLimits ()
    }
    function setLimits ()
    {
        var inverterContinuousPower = inverterContinuousPowerItem.valid ? inverterContinuousPowerItem.value : 0
    }

These examples are pulled from PowerGauge.qml in GuiMods if you are interested.

2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

bigbadbob76 avatar image
bigbadbob76 answered ·

Many thanks for your detailed reply Kevin. :-)

I'll digest that and see how I get on, i like the idea of bypassing the discovery process.

dbus-spy will help me a lot I think.

I have tried pinching some of your code from startstop.py and overviewGenerator.qml to build my own startstop.py and overviewPage.qml but I must have missed something I think.

EDIT: I missed this step-

                  
  • function someFunction ()
  • {
  • var inverterMode = inverterModeItem.valid ? inverterModeItem.value : 0
  • }

That should get me going.

Thanks for the pointers. ;-)

Bob.

1 comment
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

Kevin Windrem avatar image Kevin Windrem commented ·

the VBusItem is the way dbus stuff is accessed. That's just the way Victron named things in qml to access their dbus services and parameters within them.

0 Likes 0 ·
bigbadbob76 avatar image
bigbadbob76 answered ·

@Kevin Windrem

Hi Kevin.

sorry to be a PITA but I'm still struggling...

if using your GeneratorConnector startstop.py (or my variant)....

Should this work as part of my QML file?

VBusItem
{
id: runningStateItem
bind: Utils.path(bindPrefix, "/GeneratorRunningState")//is this correct?
onValueChanged: runningState ()
}

function runningState ()
{
var runningState = runningStateItem.valid ? runningStateItem.value : 0
 }
function getAcSourceName(type)
{
if (type === undefined)
return qsTr("AC Input")
if (type === 240)
return ""
//if (runningState.value == "R") //this doesn't work
//if (runningState.valid) //neither does this
if (!runningState.valid) // this does work but means I've screwed up somewhere
return qsTr("Generator") //show "generator" text in tile 

return acSourceName[type]
}

I have managed to get the Generator Overview page tile to show stopped/running when I switch my gpio input, so my startstop.py is generating the dbus service ' /GeneratorRunningState'

I used your Tile text method for that. :-)


1 comment
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

Kevin Windrem avatar image Kevin Windrem commented ·

runningStateItem is the object that has .valid and .value parameters

You have already resolved this in runningState() so runningState will be the "R" value, e.g.,

if (runningState == "R")

You also can't use runningState outside the function runningState (). You need to declare it as a property of the root object:

property string runningState: ""

It's then available outside the function it's set in.

Also, you need to be consistent with your use of the variable/property runningState. RunningStateItem.value is a string so should not be set to an integer.

You can avoid the runningState () function like this:

property string runningState: runningStateItem.valid ? runningStateItem.value : ""




0 Likes 0 ·
bigbadbob76 avatar image
bigbadbob76 answered ·

Thanks again for your time @Kevin Windrem

so many languages...so little time to learn them all. haha.

I've avoided the runningState function by moving it into the function I use it in and tweaked a few things but still no joy.

Here's my latest attempt-

StackPage {
property variant acSourceIcon: ["overview-ac-power", "overview-grid-power", "overview-generator-power", "overview-shore-power"]
property string runningState: "" // i'll need it again later if it works

 VBusItem
{
id: genRunningStateItem
bind: Utils.path(bindPrefix, "/GeneratorRunningState")
onValueChanged: getAcSourceIcon(type) 
}

 function getAcSourceIcon(type)
{
var runningState = genRunningStateItem.valid ? genRunningStateItem.value : 0

if (runningState == "R") {return "overview-generator-power"}

if (runningState == "S") {return "overview-grid-power"}

else {return "overview-ac-power"} //it shows this icon 

/*so still not reading "/GenaratorRunningState" (or it's not valid) 
but OverviewGenerator.qml uses it just fine)/*

}

}

Oooft!! it's 3 am, better get some kip.



2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

Kevin Windrem avatar image
Kevin Windrem answered ·

errors are logged in /var/log/gui/current. These may help figure out what's going on.

The call to getAcSourcIcon is returning a value that's not used (onValuChanged does not expect a return value). You probably need to set acSourceIcon in our function.

If you want to retain runningState, do not use a local variable in getAcSourceIcon. You can set the property from there, or better yet:

property string runningState: genRunningStateItem.valid ? genRunningStateItem.value : 0



1 comment
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

bigbadbob76 avatar image bigbadbob76 commented ·

Well spotted @Kevin Windrem :-)

getAcSourceIcon is called by other scripts. OverviewGridParrallel.qml and OverviewHub.qml and maybe more I havn't found yet.

so I probably don't need the onValueChanged call

therefore... script below should work but doesn't.

Dbus-spy tells me that GeneratorRunningState = S

OverviewGenerator.qml works and it uses the same dbus service.

aaaaggghhh!!! where's the rum? I'm going crazy.

StackPage {
                      
id: root
property variant acSourceIcon: ["overview-ac-power", "overview-grid-power", "overview-generator-power", "overview-shore-power"]
property string bindPrefix
property VBusItem runningStateItem: VBusItem {
                        bind: Utils.path(bindPrefix, "/GeneratorRunningState") }
property string runningState: runningStateItem.valid ? runningStateItem.value : 0

//some unrelated functions here

function getAcSourceIcon(type)
	{
                        
	if (runningState == "R") {
                         return "overview-generator-power"}
	if (runningState == "S") {
                          return "overview-grid-power"}
	else {
                           return "overview-ac-power"} 
 }

//another function here that uses "runningState"

}
0 Likes 0 ·
bigbadbob76 avatar image
bigbadbob76 answered ·

hmmm..... /var/log/gui/current shows "unknown service com.victronenergy.generator.startstop0"

but dbus-spy shows com.victronenergy.generator.startstop0.generator0/GeneratorRunningState=S

I can only assume the service is being called before it is running which flags up the error but by the time I get in there with PuTTY it is running. so maybe that's a red herring.

I need to find what's calling getAcSourceIcon() and when it's getting called.

6 comments
2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

Kevin Windrem avatar image Kevin Windrem commented ·
I don't see the error on my system when it boots. But to eliminate the condition where the service might not be up yet:
killall gui

Then check the log again to see if the error occurs after the system is up.

grep is your friend. Use to find where getAcSourceIcon is being called:

cd /opt/victronenergy/gui/qml
grep getAcSouerceIcon *.qml


0 Likes 0 ·
bigbadbob76 avatar image bigbadbob76 Kevin Windrem commented ·

Lol, i did it a slightly different way..... grep would have been easier but I bulk searched all the qml files for "getAcSourceIcon" with notepad++.

OverviewHub.qml is the one that does the business.

lightbulb moment.....

The icon doesn't get updated regularly.

I think I'm going about this the wrong way, I need a script to change AcInput1 in settings when /GeneratorRunningState changes so that OverviewHub.qml will call getAcSourceIcon() to update it.

Possibly by making my startstop.py set "/Settings/SystemSetup/AcInput1" as well as "/GeneratorRunningState"

Using dbus-spy to change "com.victronenergy/Settings/SystemSetup/AcInput1" value from 1 (grid) to 2 (genarator) does the trick.

so I'll see if I can get startstop.py to do it.



0 Likes 0 ·
Kevin Windrem avatar image Kevin Windrem bigbadbob76 commented ·

You can change the input type as you suggested but other things like input current limit don't change along with it. You should be changing that also.

I don't think you want to make this change based on the running state of the generator. The generator could be running and not supplying the power to the Multi. Rather, you should use another digital input to notify Venus of the state of the external transfer switch and use that to switch the input type and other parameters between grid and generator.

0 Likes 0 ·
bigbadbob76 avatar image bigbadbob76 Kevin Windrem commented ·
Good thinking Kevin.

My current setup has the transfer switch controller tell the pi that the generator is running and connected to Acinput1 but yes, maybe I should configure a different input so as not to confuse things.

but I need to get the software working first, having startstop.py set the /settings/systemsetup/AcInput1 service doesnt work, it gets in an argument with whatever else (another.py script) controlls it.

I'm not sure why it works if I set it manually in dbus-spy but not in startstop.py

timings maybe. hmmmm.....


0 Likes 0 ·
Kevin Windrem avatar image Kevin Windrem bigbadbob76 commented ·
It's possible startstop.py is running before the settings service is up. In this case, the attempt to set the value will fail. You can wrap your dbus calls in

try: / except dbus.DBusException:

to avoid the script crashing, then come back later.

Check out my TankRepeater. I do this in a couple of places.

0 Likes 0 ·
bigbadbob76 avatar image bigbadbob76 Kevin Windrem commented ·

Thanks for the pointers Kevin, dbus-spy and killall gui have saved me a lot of hassle.

I'll have a look into try: and your tank repeater. :-)

..................

Ok... I've had a look and it's allready wrapped in a try: except: as you suggest (it's part of your script anyway, haha)

I've tidied up my setting of the "/Settings/SystemSetup/AcInput1" value

and it's now stable until I close the gennerator running switch, then it fights with another (as yet unknown) script and jumps back and forth between AcInput1 settings.

I still think my original method should have worked, maybe something to do with "property string bindprefix:"

0 Likes 0 ·
bigbadbob76 avatar image
bigbadbob76 answered ·

Yay, I finally got it working, my problem was "bindPrefix related.

My flow page now shows "Generator", and the generator icon, in the ac input tile when whichever digital i/o pin is set to generator input is switched to ground.

and otherwise shows whatever you set it to in settings>system setup menu of the gui.

Thanks again Kevin, you kept me going with this.

If anyone else wants to do something similar, here's my complete OverviewPage.qml code.

it relies on having either Kevin's (or my slightly different) version of-

/opt/victronenergy/dbus-generator-starter/startstop.py

and also removes the toolbar at the bottom of the flow page as it was annoying me.

import QtQuick 1.1
import "utils.js" as Utils
import Qt.labs.components.native 1.0

StackPage {
id: root
property variant acSourceName: [qsTr("Not available"), qsTr("Grid"), qsTr("Generator"), qsTr("Shore")]
property variant acSourceIcon: ["overview-ac-power", "overview-grid-power", "overview-generator-power", "overview-shore-power"]
property string bindPrefix: "com.victronenergy.generator.startstop0"//RB
property VBusItem runningStateItem: VBusItem { bind: Utils.path(bindPrefix, "/Generator0/GeneratorRunningState") }//RB
property string runningState: runningStateItem.valid ? runningStateItem.value : 0//RB
focus: active
width: Screen.width
height: Screen.height
showToolBar: false

/*
 * Determine direction of power flow, but ignore some noise
 * Typically used for directions of the arrows, 1W @ 230V -> 4mA RMS.
 * Since you don't want to overreact with the visual indication, only
 * some arbritary significant power is shown as power flow. A less
 * arbitrare choise would be to base it one the maximum or nominal power
 * flow of the connection... This function ignores some low power values
 * around zero, the flow function below returns the sign of it.
 */
function noNoise(power)
{
if (power === undefined || !power.valid)
return 0;

if (power.value < -30)
return power.value
if (power.value > 30)
return power.value

return 0;
}


function flow(power)
{
return Utils.sign(noNoise(power))
}

/* show "Generator" and generator icon when genny is running */


function getAcSourceIcon(type)
{
if (runningState == "R")//RB check if genny running
return "overview-generator-power"//RB
if (type === undefined)
return ""
if (type === 240)
return ""
return acSourceIcon[type]//  else get ac input device from settings
}


function getAcSourceName(type)
{
if (runningState == "R")//RB 
return "Generator"/RB
if (type === undefined)
return qsTr("AC Input")
if (type === 240)
return ""

return acSourceName[type]
}
}


2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

bigbadbob76 avatar image
bigbadbob76 answered ·

I've discovered a strange bug in my system, I think I know where it's coming from but.... when I reboot my pi the generator runs for about 5 seconds during reboot. and if I shutdown (halt) the pi then the gen runs continuously until I remove power from the pi, not something I can live with obviously.

I have gpio 3 configured as the start/stop relay signal and this drives an opto-isolator which in turn switches a power transistor to switch the relay drives.

I suspect this is to do with hardware pullup resistors on the gpio lines.

from another furum- "When a Pi first boots, all Gpios are set to input, and GPIOs 0 to 8 have pull-ups enabled, the rest have pull-downs enabled."

So my solution should be to either use another gpio or add a 10k pull down resistor to my gpio output.

I'll try the 10k and see if it is enough of a pulldown......

Edit: fitted 10k pulldown and removed 1k8 pullup R23 from the pi board. gpio 3 is also used for I2c so has hardware pullups in gpio 2 and3 that are needed for that. but i'm not using I2C.

I thought I'd stick this in here as it will effect anyone using non standard gpios as digital outputs as a gen-start relay drive. the standard gpio21 relay output is not effected.

2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.

bigbadbob76 avatar image
bigbadbob76 answered ·

I also made modifications to startstop.py and TileManualStart.qml which replaces the manual generator run-time timer with "until charged".

This runs the gen by manual start until SOC>90% or until manually stopped.

This is allready available as an auto start function but I don't like auto starts.

I might change this so it just replaces the 1 minute timer with "until charged" and leave the timers available for >= 2 mins.

2 |3000

Up to 8 attachments (including images) can be used with a maximum of 190.8 MiB each and 286.6 MiB total.