Source code for automate.extensions.rpio.rpio_actuators

# -*- coding: utf-8 -*-
# (c) 2015 Tuomas Airaksinen
# This file is part of automate-rpio.
# automate-rpio is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# automate-rpio is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with automate-rpio.  If not, see <>.

from traits.api import CInt, CBool, Instance, Any, CFloat, Property
from automate.service import AbstractSystemService
from automate.statusobject import AbstractActuator

[docs]class RpioActuator(AbstractActuator): """ Boolean-valued actuator for setting Raspberry Pi GPIO port statuses (on/off). """ _status = CBool(transient=True) #: GPIO port id port = CInt #: Set to True to have inversed status value inverted = CBool(False) _hw_service = Instance(AbstractSystemService, transient=True) view = AbstractActuator.view + ["port"] def setup(self): self._hw_service = self.system.request_service('RpioService') self._hw_service.enable_output_port(self.port) def _port_changed(self, old, new): if not self._hw_service: return if old: self._hw_service.disable_output_port(old) self._hw_service.enable_output_port(new) def _status_changed(self): self.logger.debug("%s gpio actuator status changed %s",, repr(self._status)) self._hw_service.set_output_port_status(self.port, self._status if not self.inverted else not self._status)
[docs]class RpioPWMActuator(AbstractActuator): """ Actuator to control PWM (pulse-width-modulation) ports on Raspberry pi GPIO. Status range 0...1 This is not recommended to be used because RPIO PWM implementation is not very well behaving. I recommend to use ArduinoPWMActuator with an Arduino loaded with StandardFirmata. It's much more stable and robust solution. """ _status = CFloat(transient=True) #: GPIO port number port = CInt #: RPIO PWM DMA channel dma_channel = CInt(0) #: PWM frequency (Hz) frequency = CFloat(50.) _subcycle = Property(trait=CInt, transient=True) view = AbstractActuator.view + ["port"] _pwm = Any(transient=True) _hw_service = Instance(AbstractSystemService, transient=True) def _get__subcycle(self): return int(1. / self.frequency * 1e6) def setup(self): self._hw_service = self.system.request_service('RpioService') self._pwm = self._hw_service.get_pwm_module() self._port_changed(None, self.port) def _port_changed(self, old, new): if not self._hw_service: return if old: self._pwm.clear_channel_gpio(self.dma_channel, old) self._pwm.init_channel(self.dma_channel, self._subcycle) new = min(0.999, max(0., self._status)) self._pwm.add_channel_pulse(self.dma_channel, self.port, 0, int(round(new * self._subcycle / 10.))) def _frequency_changed(self): self._port_changed(self.port, self.port) def _status_changed(self): self.logger.debug("PWMActuator %s change %s", self, self._status) PWM = self._pwm PWM.clear_channel_gpio(self.dma_channel, self.port) new = min(0.999, max(0., self._status)) PWM.add_channel_pulse(self.dma_channel, self.port, 0, int(round(new * self._subcycle / 10.)))