jens-maus / RaspberryMatic

:house: A feature-rich but lightweight, buildroot-based Linux operating system alternative for your CloudFree CCU3/ELV-Charly 'homematicIP CCU' IoT smarthome central. Running as a pure virtual appliance (ProxmoxVE, Home Assistant, LXC, Docker/OCI, Kubernetes/K8s, etc.) on a dedicated embedded device (RaspberryPi, etc.) or generic x86/ARM hardware.
https://raspberrymatic.de
Apache License 2.0
1.52k stars 186 forks source link

Support PiModules UPS PIco HV3.0A Stack with 450mAh Battery #62

Closed renne closed 7 years ago

renne commented 7 years ago

The PiModules UPS PIco HV3.0A Stack with 450mAh Battery is a 30,- € Uninterruptable-Power-Supply-Hat for the Raspberry Pi.

It supports the following features:

Please support this RPi-Hat in RaspberryMatic! :-)

jens-maus commented 7 years ago

Thanks for this nice suggestion in supporting this UPS HAT for a RaspberryPi. So please feel free to donate this type of HAT and send it over to me so that I can work on integrating support for it :)

renne commented 7 years ago

What's the current state?

jens-maus commented 7 years ago

@renne The RTC clock should be supported in beta5. However, for the other UPS functions I am afraid, but the software for the software watchdog (FSSD) that is supplied with this HAT is largely based on python modules while python isn't supplied with RaspberryMatic. Thus this would require to create a dedicated CCU Addon which adds support for all the detailed UPS functions this HAT provides.

renne commented 7 years ago

@jens-maus Should the RTC work out of the box or do I need to configure something in RaspberryMatic?

If I understand correctly the Pi has to send pulse trains to GPIO 22 (watchdog function). On a power-down event the UPS switches GPIO 27 from high to low.

The UPS is available at Rasppishop, now.

jens-maus commented 7 years ago

@renne As you know, I have such a model here, but haven't had a lot of time to test it deeply. But indeed, the RTC should work out-of-the-box with beta5 and later. Have you tested it? However, for all the other support of the hardware including the watchdog function we would require more deep modifications of the system. For this, however, I would (as I said) prefer that someone (I simply lack the time) integrates the required changes in a dedicated CCU Addon package which users with this particular UPS system can install.

renne commented 7 years ago

The RTC works! I wrote a ASH-script which triggers the watchdog on the Pico UPS and queries for power-loss events via GPIO 22/27. It has no error-handling, yet and lacks all the I²C-features but works. It seems the Pico UPS activates the RTC when the watchdog-triggering/power-state querying starts. ;-)

jens-maus commented 7 years ago

@renne This sound great. Can you please provide your ash script so that I might investigate it and see if I can actually integrate something like this directly in RaspberryMatic or for reference for other Pico UPS users.

renne commented 7 years ago

@jens-maus I just created a fork of RaspberryMatic. In which directory do you want the script?

jens-maus commented 7 years ago

@renne You don't need to create a fork because I probably won't integrate it directly as said before. I just want to have a quick look over it to see what it actually does and how and then see what might be the next step to take.

renne commented 7 years ago
#!/bin/sh

# Source config file
CONFIG_FILE='/etc/filesafeshutdown.conf'
[ -r "$CONFIG_FILE" ] && . /etc/filesafeshutdown.conf

# Command run on power loss
: ${POWER_LOSS_CMD:='/sbin/shutdown -h now'}

# File descriptors
: ${GPIO_PULSE:=22}
: ${GPIO_CLOCK:=27}

# Debounce time in while loop
: ${DEBOUNCE_TIME:='0.3s'}

## Initialize GPIO file descriptor
# $1: File descriptor Value: decimal
# $2: Direction       Value: in|out
function initFD() {
    eval "[ -e /sys/class/gpio/gpio\$$1/direction ]" || {
        eval "echo \$$1 > /sys/class/gpio/export || exit 1"
        sleep 0.1s
    }
    eval "echo $2 > /sys/class/gpio/gpio\$$1/direction || exit 1"
}

## Set GPIO Value
# $1: File descriptor Value: decimal
# $2: Value           Value: 0|1
function setFDvalue() {
    eval "echo $2 > /sys/class/gpio/gpio\$$1/value || exit 1"
}

## get GPIO Value
# $1: File descriptor       Value: decimal
# $2: Target variable name  Value: 0|1
function getFDvalue() {
    eval "read $2 < /sys/class/gpio/gpio\$$1/value || exit 1"
}

# Initialize GPIO_CLOCK file descriptor
initFD GPIO_CLOCK in

# Initialize GPIO_PULSE file descriptor
initFD GPIO_PULSE out
setFDvalue GPIO_PULSE 1

# Listen for falling edge of GPIO_CLOCK
getFDvalue GPIO_CLOCK GPIO_CLOCK_VALUE

while getFDvalue GPIO_CLOCK GPIO_CLOCK_VALUE_NEW; do
    if [ $GPIO_CLOCK_VALUE_NEW -lt $GPIO_CLOCK_VALUE ];
    then

        # Debouncing in software
        sleep $DEBOUNCE_TIME

        # Save state of GPIO_PULSE
        getFDvalue GPIO_PULSE GPIO_PULSE_VALUE

        # Invert GPIO_PULSE_VALUE
        [ ${GPIO_PULSE_VALUE:-0} == 0 ] && GPIO_PULSE_VALUE=1 || GPIO_PULSE_VALUE=0

        # Set GPIO_PULSE_VALUE to low before switching to input mode
        setFDvalue GPIO_PULSE 0

        # Switch GPIO_PULSE to input
        initFD GPIO_PULSE in

        # Check for power loss (=0)
        getFDvalue GPIO_PULSE POWER_STATE
        [ 0 -eq $POWER_STATE ] && $POWER_LOSS_CMD &

        # Set GPIO_PULSE to flipped state
        initFD GPIO_PULSE out
        setFDvalue GPIO_PULSE $GPIO_PULSE_VALUE
    fi

    # Save new GPIO clock value for while loop comparison
    GPIO_CLOCK_VALUE=$GPIO_CLOCK_VALUE_NEW
done

# Remove GPIO file descriptors
echo $GPIO_PULSE > /sys/class/gpio/unexport
echo $GPIO_CLOCK > /sys/class/gpio/unexport
jens-maus commented 7 years ago

Thanks, I just inlined your script here instead providing it as an attachment so that it can be immediately be viewed. Also please provide information how and when are you starting this script during boot up.

renne commented 7 years ago

I haven't started it on boot, yet, but only manually. As it only depends on the Linux-kernel it should be possible to start it whenever you want if the Pico UPS is up and running. I suggest to start it at least before the RTC initialization an make sure only one instance is running at the same time.

jens-maus commented 7 years ago

Thanks, however, I am still not sure if we should really directly integrate it into RaspberryMatic for all users. 99% of the users won't have a Pico UPS and yet I don't see that the script tries to detect the UPS and just start its while loop if the UPS is installed. Thus, I currently think it wouldn't be wise to actually start this script for all users automatically.

renne commented 7 years ago

You can create an init-script which starts the script as a daemon. If the init-script is NOT enbabled by default users without a Pico UPS are not affected while users with a Pico UPS need only one command to activate it. ;-)

jens-maus commented 7 years ago

Of course this would be possible. However, I would actually prefer to automatically identify if a Pico UPS system is installed. There have to be a way to identify if a working Pico UPS system is installed on the GPIO of the RaspberryPi!?!?

renne commented 7 years ago

I haven't found a way, yet. But I just found https://github.com/ef-gy/rpi-ups-pico :-) :-)

jens-maus commented 7 years ago

This looks promising and I would really prefer to integrate such a C-like daemon instead of a simply shell script. So please evaluate this daemon and let me know if it is able to identify if a Pico UPS is installed or not.

renne commented 7 years ago

You can check for a UPS Pico with i2cget -y 1 0x69 0x26 b. It returns the current firmware version (exit status 0) or an error (exit status e.g. 2). The daemon seems to have a bug with firmware version 0x30. I already opened an issue.

jens-maus commented 7 years ago

Thanks for the hint and reference to the picod issue. So please let me know as soon as picod works fine for you so that I can start working on integration into a future RaspberryMatic version.

EffinMaggie commented 7 years ago

Heh, just saw the shoutout there for the daemon. I'll see about fixing those issues @renne opened against it - haven't quite seen most of them on my Pi, but I assume most of that is that I haven't updated the firmware on the pico in quite a bit :).

johnwlawrence88 commented 6 years ago

Hello, what is the purpose of the watchdog? could it be used to reset the pi if a python script fails ?