i want to control the charging of my EBike via energy measurement. The charging curve of a lipo battery changes from CC (constant current) to CV (constant voltage) at a SOC of 90%. Therefore also the power consumption of the charger is constant in the CC phase and tends towards zero in CV phase.
To increase the battery life, I want to switch of charging at a SOC of 90%. Therefore i measure the power of the charger in the CC phase. If the power drops below 80% of this value, the rule switches of the charger.
This is what i currently ended up with:
var Number EBikeLadecontrollerStart = 0
var Number EBikeLadecontrollerMaxPower= 0
var Number PowerTreshold = 0
var Boolean AutoAbschaltung = false
rule EBikeLadecontroller
when
Item EBikeLadecontrollerTotal changed or
Item EBikeLadecontrollerPower changed
then
var EBikeLadecontrollerTotal = (EBikeLadecontrollerTotal.state as Number) * 1000
if(EBikeLadecontrollerPower.state > EBikeLadecontrollerMaxPower) {
EBikeLadecontrollerMaxPower = EBikeLadecontrollerPower.state
PowerTreshold = (EBikeLadecontrollerTreshold.state as Number) / 100 * EBikeLadecontrollerMaxPower
logInfo("Ladecontroller", "Maximalwert {}", EBikeLadecontrollerMaxPower)
logInfo("Ladecontroller", "Abschaltschwelle {}", PowerTreshold)
}
if(EBikeLadecontrollerPower.state < PowerTreshold && AutoAbschaltung == true) {
EBikeLadecontroller.sendCommand(OFF)
logInfo("Ladecontroller", "Abschaltschwelle erreicht")
logInfo("Ladecontroller", "Abschaltschwelle {}", PowerTreshold)
logInfo("Ladecontroller", "Leistung {}", EBikeLadecontrollerPower.state)
}
EBikeLadecontrollercharged.postUpdate(EBikeLadecontrollerTotal - EBikeLadecontrollerStart )
end
rule Reset
when
Item EBikeLadecontroller changed from OFF to ON
then
EBikeLadecontrollerStart = EBikeLadecontrollerTotal
EBikeLadecontrollercharged.postUpdate(0)
EBikeLadecontrollerMaxPower = 0
AutoAbschaltung = false
createTimer(now.plusSeconds(60), [|
AutoAbschaltung = true
logInfo("Ladecontroller", "Autoabschaltung {}", AutoAbschaltung)
])
logInfo("Ladecontroller", "Ladevorgang gestartet, Startwert {}", EBikeLadecontrollerStart)
logInfo("Ladecontroller", "Maximalwert {}", EBikeLadecontrollerMaxPower)
logInfo("Ladecontroller", "Autoabschaltung {}", AutoAbschaltung)
end
The rule does the following:
Determines the max. power consumption of the charger.
Checks if the Power drops below the power treshold after 60 seconds from charging start.
Displays the charged energy in Wh.
The rule works already, but I’m getting the following error:
Rule 'EBikeLadecontroller': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.model.script.lib.NumberExtensions.operator_minus(java.lang.Number,java.lang.Number) on instance: null
I think it has to do with converting values from kWh to Wh.
I’m amazed that works at all without quotemarks rule "EBikeLadecontroller"
A word of warning on that subject, every rule must have a unique “name” there.
Okay, we can guess where that comes from as it involves ‘minus’.
(You can add temporary logInfo() messages to your rules to track progress when investigating error messages.)
This is a bit worrying though …
That’s not illegal, but it might not do what you expect.
You seem to have an Item named EBikeLadecontrollerTotal ?
But in the first line of your rule you declare a new variable also named EBikeLadecontrollerTotal
All references to name EBikeLadecontrollerTotal in your rule will now get that variable, not the “real” Item.
That includes the use of EBikeLadecontrollerTotal.state , which makes a circular definition of the variable by itself. I’m surprised that doesn’t throw an error, perhaps because it hasn’t yet finished making the “new” variable.
Yes, i have a item EBikeLadecontrollerTotal, which displays the total amount of energy.
The reason why i use the variable is, that i want to convert the value kWh to Wh. I’ve tried to convert it in the sitemap as described here. But i could not find out, why this wasn’t working.
I done some rework on my code:
var Number EBikeLadecontrollerStart = 0
var Number EBikeLadecontrollerMaxPower= 0
var Number PowerTreshold = 0
var Boolean AutoAbschaltung = false
rule "EBikeLadecontroller"
when
Item EBikeLadecontrollerTotal changed or
Item EBikeLadecontrollerPower changed
then
// var EBikeLadecontrollerTotal = (EBikeLadecontrollerTotal.state as Number) * 1000
if(EBikeLadecontrollerPower.state > EBikeLadecontrollerMaxPower) {
EBikeLadecontrollerMaxPower = EBikeLadecontrollerPower.state
PowerTreshold = (EBikeLadecontrollerTreshold.state as Number) / 100 * EBikeLadecontrollerMaxPower
logInfo("Ladecontroller", "Maximalwert {}", EBikeLadecontrollerMaxPower)
logInfo("Ladecontroller", "Abschaltschwelle {}", PowerTreshold)
}
if(EBikeLadecontrollerPower.state < PowerTreshold && AutoAbschaltung == true) {
EBikeLadecontroller.sendCommand(OFF)
logInfo("Ladecontroller", "Abschaltschwelle erreicht")
logInfo("Ladecontroller", "Abschaltschwelle {}", PowerTreshold)
logInfo("Ladecontroller", "Leistung {}", EBikeLadecontrollerPower.state)
}
logInfo("Ladecontroller", "Gesamtenergie {}", EBikeLadecontrollerTotal.state)
logInfo("Ladecontroller", "Startwert {}", EBikeLadecontrollerStart)
EBikeLadecontrollercharged.postUpdate((EBikeLadecontrollerTotal.state as Number - EBikeLadecontrollerStart)*1000)
end
rule "Reset"
when
Item EBikeLadecontroller changed from OFF to ON
then
EBikeLadecontrollerStart = EBikeLadecontrollerTotal.state
EBikeLadecontrollercharged.postUpdate(0)
EBikeLadecontrollerMaxPower = 0
AutoAbschaltung = false
createTimer(now.plusSeconds(60), [|
AutoAbschaltung = true
logInfo("Ladecontroller", "Autoabschaltung {}", AutoAbschaltung)
])
logInfo("Ladecontroller", "Ladevorgang gestartet, Startwert {}", EBikeLadecontrollerStart)
logInfo("Ladecontroller", "Maximalwert {}", EBikeLadecontrollerMaxPower)
logInfo("Ladecontroller", "Autoabschaltung {}", AutoAbschaltung)
end
Now, it is working… But i don’t know if the code is “clean”.