Example #1
0
class Channel:

    def __init__(self, name, output_pin, input_pin=None):
        self.name = name
        self.state = None
        self.output_pin = output_pin
        if input_pin is not None:
            self.input_pin = input_pin
        self.output_device = DigitalOutputDevice(output_pin)
        if input_pin:
            self.input_device = DigitalInputDevice(input_pin)

    def set(self, state):
        """Sets the channel output"""
        self.state = state
        if state == 'On':
            self.output_device.on()
        elif state == 'Off':
            self.output_device.off()
        else:
            raise NotImplementedError
        log.info('Channel %s set to %s', self.name, state)

    def valid(self):
        """
        Checks if the channel output is valid

        Returns: True, if the output and input pin states match.
                 False, if they don't match.
                 None, if no input pin is defined.

        """
        if self.input_pin is None:
            return None
        else:
            return self.output_device.value == self.input_device.value

    def status(self):
        return {
            'state': self.state,
            'valid': self.valid(),
        }
Example #2
0
class PCD8544(SPIDevice):
    """
    PCD8544 display implementation.

    This implementation uses software shiftOut implementation?

    @author SrMouraSilva
    Based in 2013 Giacomo Trudu - wicker25[at]gmail[dot]com
    Based in 2010 Limor Fried, Adafruit Industries
          https://github.com/adafruit/Adafruit_Nokia_LCD/blob/master/Adafruit_Nokia_LCD/PCD8544.py
    Based in CORTEX-M3 version by Le Dang Dung, 2011 [email protected] (tested on LPC1769)
    Based in Raspberry Pi version by Andre Wussow, 2012, [email protected]
    Based in Raspberry Pi Java version by Cleverson dos Santos Assis, 2013, [email protected]


    https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md

    The SPI master driver is disabled by default on Raspbian.
    To enable it, use raspi-config, or ensure the line
    dtparam=spi=on isn't commented out in /boot/config.txt, and reboot.

    :param int din: Serial data input
    :param int sclk: Serial clock input (clk)
    :param int dc: Data/Command mode select (d/c)
    :param int rst: External reset input (res)
    :param int cs: Chip Enable (CS/SS, sce)

    :param contrast
    :param inverse
    """
    def __init__(self, din, sclk, dc, rst, cs, contrast=60, inverse=False):
        super(PCD8544, self).__init__(clock_pin=sclk,
                                      mosi_pin=din,
                                      miso_pin=9,
                                      select_pin=cs)

        self.DC = DigitalOutputDevice(dc)
        self.RST = DigitalOutputDevice(rst)

        self._reset()
        self._init(contrast, inverse)

        self.drawer = DisplayGraphics(self)
        self.clear()
        self.dispose()

    def _reset(self):
        self.RST.off()
        time.sleep(0.100)
        self.RST.on()

    def _init(self, contrast, inverse):
        # H = 1
        self._send_command(SysCommand.FUNC | Setting.FUNC_H)
        self._send_command(SysCommand.BIAS | Setting.BIAS_BS2)
        self._send_command(SysCommand.VOP | contrast & 0x7f)
        # H = 0
        self._send_command(SysCommand.FUNC | Setting.FUNC_V)
        self._send_command(SysCommand.DISPLAY | Setting.DISPLAY_D
                           | Setting.DISPLAY_E * (1 if inverse else 0))

    def _send_command(self, data):
        self.DC.off()

        self._spi.write([data])

    def _send_data_byte(self, x, y, byte):
        self._set_cursor_x(x)
        self._set_cursor_y(y)

        self.DC.on()
        self._spi.write([byte])

    def set_contrast(self, value):
        self._send_command(SysCommand.FUNC | Setting.FUNC_H)
        self._send_command(SysCommand.VOP | value & 0x7f)
        self._send_command(SysCommand.FUNC | Setting.FUNC_V)

    def write_all(self, data):
        self._set_cursor_x(0)
        self._set_cursor_y(0)

        self.DC.on()
        self._spi.write(data)

    def _set_cursor_x(self, x):
        self._send_command(SysCommand.XADDR | x)

    def _set_cursor_y(self, y):
        self._send_command(SysCommand.YADDR | y)

    def clear(self):
        self._set_cursor_x(0)
        self._set_cursor_y(0)

        self.drawer.clear()

    @property
    def width(self):
        return DisplaySize.WIDTH

    @property
    def height(self):
        return DisplaySize.HEIGHT

    @property
    def value(self):
        return 0

    def close(self):
        super(PCD8544, self).close()

    @property
    def draw(self):
        return self.drawer.draw

    def dispose(self):
        self.drawer.dispose()
class KamigamiInterface():
    def __init__(self, do_calibrate=True):
        """
        Initialize Kamigami interface
        """

        # Setup ROS subscribers, publishers
        pwm_sub = rospy.Subscriber('kamigami/motor_cmd', PWMCommand,
                                   self.recieve_motor_cmd)
        step_sub = rospy.Subscriber('kamigami/step_cmd', StepCommand,
                                    self.recieve_step_cmd)
        self.imu_pub = rospy.Publisher('imu/data_raw', Imu, queue_size=10)

        # Setup action clients, servers
        # None as of now, should be using one for stepping but VREP only supports services/actions for ROS2

        # TODO: Add a debugging mode (multiple levels) or take advantage of ROS's own tools

        # Setup IMU
        i2c = busio.I2C(board.SCL, board.SDA)
        self.sensor = LSM6DS33(i2c)
        # TODO: Read in from config file
        # Running these at slightly above 100 Hz
        # These are currently the default values
        self.sensor.accelerometer_data_rate = Rate.RATE_104_HZ
        self.sensor.gyro_data_rate = Rate.RATE_104_HZ
        self.sensor.accelerometer_range = AccelRange.RANGE_4G
        self.sensor.gyro_range = GyroRange.RANGE_250_DPS

        # Setup Raspberry Pi Pins
        # TODO: Take pin definitions from a config file
        self.motor_standby = DigitalOutputDevice(17)
        self.motor_right_pwm = PWMOutputDevice(13)
        self.motor_left_pwm = PWMOutputDevice(18)
        self.motor_right_forward = DigitalOutputDevice(27)
        self.motor_right_backward = DigitalOutputDevice(22)
        self.motor_left_forward = DigitalOutputDevice(24)
        self.motor_left_backward = DigitalOutputDevice(23)
        self.pins_on()

        # TODO: Take in constants from some kind of config file
        self._loop_rate = 100
        self._step_pwm = .6
        self._step_rest_time = .35
        self._left_ang_desired = .09
        self._right_ang_desired = -.09
        self._threshold = .02
        self._filter_alpha = .98

        if do_calibrate:
            # Calibrate first
            print("\nCalibrating! Please keep robot still.")
            calibration_time = 3
            calibration_start = rospy.get_time()
            x_ang_vels = []
            x_tilt = []
            while (rospy.get_time() - calibration_start) < calibration_time:
                x_ang_vels.append(self.sensor.gyro[0])
                x_tilt.append(
                    self.acceleration_to_tilt(self.sensor.acceleration))
            # Estimate gyro bias in the roll direction by averaging the angular velocity over all samples
            self.x_ang_bias = sum(x_ang_vels) / len(x_ang_vels)
            # Estimate current tilt
            self.x_tilt_start = sum(x_tilt) / len(x_tilt)
            print("\nCalibration finished!")
            print(f"Gyro x bias: {self.x_ang_bias}")
            print(f"Starting tilt: {self.x_tilt_start}")

        # Instance variables
        self.roll_estimate = 0
        # TODO: Find a better way to represent step commands...
        self.queued_left_steps = 3
        self.queued_right_steps = 3

        # Custom shutdown function to stop all motors
        rospy.on_shutdown(self.shutdown)

    def recieve_motor_cmd(self, data):
        """
        Recieve KamigamiCommand message and control motors from that
        """

        self.motor_cmd(data.motor_left, data.motor_right)

    def motor_cmd(self, motor_left_speed, motor_right_speed):
        """
        Set both motors of Kamigami to input values
        """

        # Saturate max/min PWMs
        motor_left_speed = max(min(1, motor_left_speed), -1)
        motor_right_speed = max(min(1, motor_right_speed), -1)

        # Determine pins to set high and output PWM
        if motor_left_speed >= 0:
            self.motor_left_forward.on()
            self.motor_left_backward.off()
            self.motor_left_pwm.value = motor_left_speed
        else:
            self.motor_left_forward.off()
            self.motor_left_backward.on()
            self.motor_left_pwm.value = -motor_left_speed
        if motor_right_speed >= 0:
            self.motor_right_forward.on()
            self.motor_right_backward.off()
            self.motor_right_pwm.value = motor_right_speed
        else:
            self.motor_right_forward.off()
            self.motor_right_backward.on()
            self.motor_right_pwm.value = -motor_right_speed

        # print('Setting motor left to {}'.format(motor_left_speed))
        # print('Setting motor right to {}'.format(motor_right_speed))

    def recieve_step_cmd(self, data):
        # self.take_steps(data.left_steps, data.right_steps)
        self.queued_left_steps = data.left_steps
        self.queued_right_steps = data.right_steps

    # def take_steps(self, left_steps, right_steps):
    #     for i in range(left_steps):
    #         while(abs(self.roll_estimate - self._ang_desired) > self._threshold) and (not rospy.is_shutdown())
    #     return
    #   #  for i in range(n_steps):
    #   #      last = rospy.get_time()
    #   #      ang = 0
    #   #      for _ in range(left_steps):
    #   #          while (abs(ang - ang_desired) > threshold) and (not rospy.is_shutdown()):
    #   #              ang_desired = abs(ang_desired)
    #   #              send_cmd(pwm, 0)
    #   #              cur = rospy.get_time()
    #   #              gyro_estimate = ang + (cur - last) * (angular_velocity[0] - x_ang_bias)
    #   #              accel_estimate = get_tilt() - x_tilt_start
    #   #              last = cur
    #   #              # Complementary filter equation
    #   #              # TODO: Refine parameters based on cutoff frequencies, sampling times
    #   #              ang = self._filter_alpha*(gyro_estimate) + (1-self._filter_alpha)*accel_estimate
    #   #              # Only trust accelerometer if it is reasonable
    #   #              # if abs(gyro_estimate - accel_estimate) < .1:
    #   #              #     ang = .98 * (gyro_estimate) + .02 * accel_estimate
    #   #              # else:
    #   #              #     ang = gyro_estimate
    #   #              ang_pub.publish(ang)

    #   #      if rospy.is_shutdown():
    #   #          break

    def acceleration_to_tilt(self, linear_acceleration):
        return math.atan2(
            linear_acceleration[1],
            math.sqrt(linear_acceleration[1] * linear_acceleration[1] +
                      linear_acceleration[2] * linear_acceleration[2]))

    def update_state(self, last_time):
        """
        Updating state of the Kamigami by
        - polling sensors for new data
        - TODO: filtering
        - publishing new IMU data to imu/data_raw topic
        """

        # Poll IMU sensors
        angular_velocity = list(self.sensor.gyro)
        linear_acceleration = self.sensor.acceleration

        # print("Angular Velocity: {}".format(angular_velocity)
        # print("Linear Acceleration: {}".format(linear_acceleration))

        # Apply drift correction
        angular_velocity[0] = angular_velocity[0] - self.x_ang_bias

        # Update internal roll estimate
        cur_time = rospy.get_time()
        gyro_estimate = self.roll_estimate + angular_velocity[0] * (cur_time -
                                                                    last_time)
        accelerometer_estimate = math.atan2(
            linear_acceleration[1],
            math.sqrt(linear_acceleration[1] * linear_acceleration[1] +
                      linear_acceleration[2] * linear_acceleration[2]))
        # Simple complementary filter
        # TODO: Use a Kalman filter!
        self.roll_estimate = self._filter_alpha * gyro_estimate + (
            1 - self._filter_alpha) * accelerometer_estimate
        # print (f"Roll: {self.roll_estimate}")

        # Create and populate IMU message
        imu_data = Imu()
        imu_data.header.stamp = rospy.Time.now()
        imu_data.header.frame_id = 'imu_link'
        imu_data.angular_velocity.x, imu_data.angular_velocity.y, imu_data.angular_velocity.z = angular_velocity
        imu_data.linear_acceleration.x, imu_data.linear_acceleration.y, imu_data.linear_acceleration.z = linear_acceleration

        # Publish new state data
        self.imu_pub.publish(imu_data)

        return cur_time

    def shutdown(self):
        """
        Disable Kamigami by
        - shutting off motors
        - deactivating pins
        """

        self.motor_cmd(0, 0)
        self.pins_off()
        print("Kamigami interface shutdown.")

    def pins_on(self):
        """
        Enable Raspberry Pi pins
        """

        self.motor_standby.on()

    def pins_off(self):
        """
        Deactivate Raspberry Pi pins
        """

        self.motor_standby.off()
        self.motor_right_pwm.off()
        self.motor_left_pwm.off()
        self.motor_right_forward.off()
        self.motor_right_backward.off()
        self.motor_left_forward.off()
        self.motor_left_backward.off()

    def run(self):
        """
        Keep the Kamigami interface running and update state messages
        """

        rate = rospy.Rate(self._loop_rate)
        last_step = last_time = rospy.get_time()

        while not rospy.is_shutdown():
            # Update state
            last_time = self.update_state(last_time)
            # If we should be taking steps, do that
            if rospy.get_time() - last_step > self._step_rest_time:
                if self.queued_left_steps:
                    if (abs(self.roll_estimate - self._left_ang_desired) >
                            self._threshold):
                        self.motor_cmd(self._step_pwm, 0)
                        print(f"Roll: {self.roll_estimate}")
                        # print(f"Left desired: {self._left_ang_desired}")
                        # print(f"Threshold: {self._threshold}")
                    else:
                        print("Left step completed!")
                        self.motor_cmd(0, 0)
                        self.queued_left_steps = max(
                            self.queued_left_steps - 1, 0)
                        last_step = rospy.get_time()
                elif self.queued_right_steps:
                    if (abs(self.roll_estimate - self._right_ang_desired) >
                            self._threshold):
                        print(f"Roll: {self.roll_estimate}")
                        # print(f"Right desired: {self._right_ang_desired}")
                        # print(f"Threshold: {self._threshold}")
                        self.motor_cmd(0, self._step_pwm)
                    else:
                        print("Right step completed!")
                        self.motor_cmd(0, 0)
                        self.queued_right_steps = max(
                            self.queued_right_steps - 1, 0)
                        last_step = rospy.get_time()
            else:
                print("Waiting before next step...")
            rate.sleep()
        self.shutdown()
Example #4
0
from gpiozero import PWMOutputDevice, DigitalOutputDevice
from time import sleep

enAPin = 12
enBPin = 13
in1Pin = 7
in2Pin = 8
in3Pin = 9
in4Pin = 10

enA = PWMOutputDevice(enAPin)
enB = PWMOutputDevice(enBPin)
in1 = DigitalOutputDevice(in1Pin)
in2 = DigitalOutputDevice(in2Pin)
in3 = DigitalOutputDevice(in3Pin)
in4 = DigitalOutputDevice(in4Pin)

enA.value = 1
enB.value = 1
in1.on()
in2.off()
in3.on()
in4.off()

sleep(5)
Example #5
0
from gpiozero import DigitalOutputDevice
from time import sleep

sleep_time = 5

test_pin = DigitalOutputDevice(17)

while True:
    test_pin.on()
    sleep(sleep_time)
    test_pin.off()
    sleep(sleep_time)
Example #6
0
DHT_MODEL = 11
HEAT_PIN = 17
COOL_PIN = 27
LIGHT_PIN = 18
lastUpdate = 0

print "Initializing grbl communication"
grbl = serial.Serial('/dev/serial0', 115200)
grbl.write("\r\n\r\n")

print "Creating heat/cool pins"
# https://gpiozero.readthedocs.io/en/stable/api_output.html
heatRelay = DigitalOutputDevice(HEAT_PIN)
coolRelay = DigitalOutputDevice(COOL_PIN)
lightRelay = DigitalOutputDevice(LIGHT_PIN)
lightRelay.on()
heatRelay.on()
coolRelay.on()

print "Authenticating with firebase..."
# Use a service account
cred = credentials.Certificate('/home/pi/Pycotronics/private_firebase_key.json')
firebase_admin.initialize_app(cred, {
    'databaseURL': 'https://mycotronics2.firebaseio.com/'
})

print "Fetching settings from firebase..."
settings = db.reference("settings/3")
print "Getting reference to logs"
doc = db.reference("logs/3")
print "Getting reference to image bucket"
Example #7
0
#!/usr/bin/env python


from gpiozero import DigitalOutputDevice
from time import sleep


rLight = DigitalOutputDevice(21,active_high=False)
rPump = DigitalOutputDevice(20,active_high=False)




rLight.on()
sleep(1)
rLight.off()
sleep(1)
rLight.on()
sleep(1)
rLight.off()
sleep(5)

rLight.on()
rPump.on()

sleep(30)
rPump.off()
sleep(10)
rLight.off()

Example #8
0
from gpiozero import DigitalInputDevice, DigitalOutputDevice
from time import sleep

led_pin = DigitalOutputDevice(7)
button_pin = DigitalInputDevice(14, pull_up=False)

while True:
    print(button_pin.value)

    if button_pin.value == 1:
        led_pin.on()
    else:
        led_pin.off()

    sleep(0.1)
Example #9
0
from gpiozero import DigitalOutputDevice
from time import sleep

pinAred = DigitalOutputDevice(17)
pinByellow = DigitalOutputDevice(27)
pinCgreen = DigitalOutputDevice(22)
pinDblack = DigitalOutputDevice(23)

pinEred = DigitalOutputDevice(13)
pinFyellow = DigitalOutputDevice(6)
pinGgreen = DigitalOutputDevice(5)
pinHblack = DigitalOutputDevice(12)

pinAred.off()
pinByellow.on()
pinCgreen.on()
pinDblack.off()
pinEred.off()
pinFyellow.off()
pinGgreen.on()
pinHblack.on()
sleep(1)

pinAred.close()
pinByellow.close()
pinCgreen.close()
pinDblack.close()
pinEred.close()
pinFyellow.close()
pinGgreen.close()
pinHblack.close()
Example #10
0
a = pin_a.is_pressed
b = pin_b.is_pressed

prev_a = not a
prev_b = not b
prev_z = True

counter = 0

loop = True

delay = .001

while(loop):
	device.on()
	sleep(delay)
	device.off()
	sleep(delay)
	if a != pin_a.is_pressed or b != pin_b.is_pressed:
		if pin_a.is_pressed == prev_a and pin_b.is_pressed == prev_b:
			counter -= 1
		else:
			counter += 1
		print(str(int(pin_a.is_pressed)) + " " + str(int(pin_b.is_pressed)) + " " + str(int(pin_z.is_pressed)) + " " + str(counter))
		#print(str(pin_a.is_pressed) + " " + str(pin_b.is_pressed) + " " + str(pin_z.is_pressed))
		a = pin_a.is_pressed
		prev_a = a
		b = pin_b.is_pressed
		prev_b = b
	loop = pin_z.is_pressed or prev_z
Example #11
0
from gpiozero import DigitalOutputDevice
from time import sleep
import random

d = DigitalOutputDevice(2, active_high=False)
d.on()
sleep(3)
d.off()
Example #12
0
class Printer(object):
    # Initialise objects and variables.
    def __init__(self):
        # HARDWARE INITIALISATION.

        # LIMIT SWITCHES
        self.xLim = Button(15, pull_up=False)
        self.yLim = Button(14, pull_up=False)

        # SOLENOID
        self.sol = DigitalOutputDevice(20)

        # STATUS LED
        self.sLED = DigitalOutputDevice(21)

        # MOTOR DRIVERS
        self.pins = [[
            DigitalOutputDevice(8),
            DigitalOutputDevice(7),
            DigitalOutputDevice(12),
            DigitalOutputDevice(16)
        ],
                     [
                         DigitalOutputDevice(18),
                         DigitalOutputDevice(23),
                         DigitalOutputDevice(24),
                         DigitalOutputDevice(25)
                     ]]

        # SOFTWARE INITIALISATION

        self.VERSION = "1.0"
        self.ARCHITECTURE = "DOT-MATRIX"

        # MOTOR STEP SEQUENCE
        self.seq = [[1, 0, 1, 0], [0, 1, 1, 0], [0, 1, 0, 1], [1, 0, 0, 1]]

        # POSITION
        self.pos = [200, 200]

        # STEP INDEX IN SEQUENCE
        self.step = 0

        # MAXIMUM ALLOWED STEPS
        self.maxSteps = 200

# Output current position to console.

    def printPos(self):
        print("Position: (%d, %d)" % (self.pos[0], self.pos[1]))

# Step pin set by number of steps

    def doSteps(self, pins, sDir, steps):
        # Step the requested number of steps.
        for x in range(steps):
            for x in range(4):
                if (self.seq[self.step][x]):
                    pins[x].on()
                else:
                    pins[x].off()
            if sDir:
                self.step += 1
            else:
                self.step -= 1
            sleep(0.005)  #GOOD SPEED 0.005
            if self.step >= 4:
                self.step = 0
            elif self.step < 0:
                self.step = 3

# Step axis by number of steps
# Direction 1 is towards limits.
# Axis X is 0.

    def stepAxis(self, axis, sDir, steps):
        # Modifier for adjusting position.
        mod = -1 if sDir else 1
        # DEBUG
        #print("Stepping axis %d by %d steps in direction %d" % (axis, steps, dir))
        # Check if step is valid from position.
        if (self.pos[axis] + mod * steps >=
                self.maxSteps) or (self.pos[axis] + mod * steps < 0):
            print(
                "Cannot perform command: \'Step %d steps from position (%d, %d)\'"
                % (steps, self.pos[0], self.pos[1]))
            print(self.pos[axis] + mod * steps)
            return 0
# Perform Steps
        self.doSteps(self.pins[axis], sDir, steps)
        self.pos[axis] = self.pos[axis] + mod * steps

# Step to position given.

    def stepToPos(self, pos):
        # Check bounds
        if (max(pos) > self.maxSteps) or (min(pos) < 0):
            print("Invalid Position (%d, %d)." % (pos[0], pos[1]))
            return 0

        # Calculate deltas in dimensions.
        dx = pos[0] - self.pos[0]
        dy = pos[1] - self.pos[1]

        # Step required amounts
        for axis, value in [[0, dx], [1, dy]]:
            sleep(0.1)
            sDir = 0 if (value >= 0) else 1
            self.stepAxis(axis, sDir, int(math.fabs(value)))

        return 1

    # Home Axes and reset position.
    def home(self):
        sleep(0.5)
        print("Homing Axes.")
        for axis, limit in ([[0, self.xLim], [1, self.yLim]]):
            while not (limit.is_pressed):
                self.stepAxis(axis, 1, 1)
                self.pos = [200, 200]
            print("Axis %d homed." % axis)
        self.pos = [0, 0]
        # Offset by 20 steps
        self.stepAxis(0, 0, 20)
        self.stepAxis(0, 0, 20)
        sleep(0.5)

# Draw a pixel at current position.

    def drawPixel(self):
        self.sol.on()
        sleep(0.15)
        self.sol.off()

# Print the matrix onto paper.

    def printMatrix(self, matrix):
        self.sol.off()
        # Home
        self.home()

        # Iterate over pixels.
        print("Printing...")
        for x in range(len(matrix) - 1):
            for y in range(len(matrix[0]) - 1):
                # If pixel is active.
                if (matrix[x][y] == "1"):

                    # Step to position.
                    #print("Moving to Position (%d, %d)" % (x, y))
                    r = self.stepToPos([x, y])
                    # Invalid position error. Something has broken.
                    if not (r):
                        print("Error Encountered. Cancelling print.")
                        self.sol.off()
                        self.home()
                        return
                    sleep(0.15)
                    self.drawPixel()

        # Done.
        self.sol.off()
        print("Complete.")

        # Home.
        self.home()
Example #13
0
    really_close_to_target = target - 5

    if not power:
        background = make_blank_background("black")
        relay.off()

    elif value == target:
        background = make_blank_background("green")
        relay.off()

    elif value >= target:
        background = make_blank_background("red")
        relay.off()

    elif value >= really_close_to_target:
        background = make_blank_background("turquoise")
        relay.blink(on_time=2, off_time=4, n=1, background=False)

    elif value >= close_to_target:
        background = make_blank_background("aqua")
        relay.blink(on_time=2, off_time=2, n=1, background=False)

    else:
        background = make_blank_background("blue")
        relay.on()

    image = write_white_text(background, (str(value)) + u"\u00B0", 0, big_font)
    image = write_gray_text(background, (str(target)) + u"\u00B0", 150,
                            small_font)
    lcd.display(image)
Example #14
0
class JoeSlot:
    def __init__(self,
                 mcp: MCP23017,
                 pwm_pin,
                 control_pins,
                 supply_voltage,
                 pwm=True):
        self.mcp = mcp
        self.supply_voltage = supply_voltage
        self.control_pins = control_pins
        self.pwm = pwm
        if self.pwm:
            self.pwm_pin = PWMOutputDevice(pwm_pin)
        else:
            self.pwm_pin = DigitalOutputDevice(pwm_pin)
            self.pwm_pin.on()
        self.mcp.setup(self.control_pins[0], 0)
        self.mcp.setup(self.control_pins[1], 0)
        self._scale_factor = 1
        self._speed = 1
        self._direction = 0

    @property
    def voltage(self):
        return self._scale_factor * self.supply_voltage

    @voltage.setter
    def voltage(self, value):
        if self.pwm:
            if value <= self.supply_voltage:
                self._scale_factor = round((value / self.supply_voltage), 3)
            else:
                print("Cannot set higher than supply!")
        else:
            print("Can't set speed for non-pwm pin.")

    @property
    def speed(self):
        '''Gets speed'''
        return self._speed

    @speed.setter
    def speed(self, value):
        '''Sets speed as pwm value.'''
        if self.pwm:
            if value <= 1 and value >= 0:
                self._speed = value
                self.pwm_pin.value = self._scale_factor * value
            else:
                print("Invalid speed.")
        else:
            print("Can't set speed for non-pwm pin.")

    @property
    def direction(self):
        '''Get direction'''
        return self._direction

    @direction.setter
    def direction(self, value):
        '''Sets the directional control pins.'''
        if value == 0:
            self.mcp.output(self.control_pins[0], 0)
            self.mcp.output(self.control_pins[1], 0)
            self._direction = 0
        elif value == 1:
            self.mcp.output(self.control_pins[0], 0)
            self.mcp.output(self.control_pins[1], 1)
            self._direction = 1
        elif value == -1:
            self.mcp.output(self.control_pins[0], 1)
            self.mcp.output(self.control_pins[1], 0)
            self._direction = -1
        else:
            print("Invalid direction")
Example #15
0
class Robot(object):
	SPEED_HIGH = int(config.get("robot.speed","speed_high"))
	SPEED_MEDIUM = int(config.get("robot.speed","speed_medium"))
	SPEED_LOW = int(config.get("robot.speed","speed_low"))

	##Define the arc of the turn process by a tuple wheels speed (left, right)
	LEFT_ARC_CLOSE = eval(config.get("robot.speed","left_arc_close"))
	LEFT_ARC_OPEN = eval(config.get("robot.speed","left_arc_open"))

	RIGHT_ARC_CLOSE = eval(config.get("robot.speed","right_arc_close"))
	RIGHT_ARC_OPEN = eval(config.get("robot.speed","right_arc_open"))

	#Pin pair left
	FORWARD_LEFT_PIN = int(config.get("robot.board.v1","forward_left_pin"))
	BACKWARD_LEFT_PIN = int(config.get("robot.board.v1","backward_left_pin"))

	#Pin pair right
	FORWARD_RIGHT_PIN = int(config.get("robot.board.v1","forward_right_pin"))
	BACKWARD_RIGHT_PIN = int(config.get("robot.board.v1","backward_right_pin"))

	#PWM PINS
	PWM_LEFT_PIN = int(config.get("robot.board.v1","pwm_left_pin"))
	PWM_RIGHT_PIN = int(config.get("robot.board.v1","pwm_right_pin"))

	#Frecuency by hertz
	FRECUENCY = int(config.get("robot.board.v1","frecuency"))

	# Cycles fits for pwm cycles
	LEFT_CYCLES_FIT = int(config.get("robot.board.v1","left_cycles_fit"))
	RIGHT_CYCLES_FIT = int(config.get("robot.board.v1","right_cycles_fit"))

	#Pin settings for head control
	HEAD_HORIZONTAL_PIN = int(config.get("robot.board.v1","head_pwm_pin_horizontal_axis"))
	HEAD_VERTICAL_PIN = int(config.get("robot.board.v1","head_pwm_pin_vertical_axis"))
	HEAD_HORIZONTAL_RANGE = config.get("robot.board.v1","head_horizontal_range").split(",")
	HEAD_VERTICAL_RANGE = config.get("robot.board.v1","head_vertical_range").split(",")

	RIGHT_WHEEL_SENSOR = int(config.get("robot.board.v1","right_wheel_sensor"))
	LEFT_WHEEL_SENSOR = int(config.get("robot.board.v1", "left_wheel_sensor"))

	CONTROLLER_BOARD = config.get("robot.controller", "board")

	#v2
	WHEEL_LEFT_ENABLED = int(config.get("robot.board.v2", "wheel_left_enabled"))
	WHEEL_LEFT_HEADING = int(config.get("robot.board.v2", "wheel_left_heading"))
	WHEEL_LEFT_STEP = int(config.get("robot.board.v2", "wheel_left_step"))

	WHEEL_RIGHT_ENABLED = int(config.get("robot.board.v2", "wheel_right_enabled"))
	WHEEL_RIGHT_HEADING = int(config.get("robot.board.v2", "wheel_right_heading"))
	WHEEL_RIGHT_STEP = int(config.get("robot.board.v2", "wheel_right_step"))


	SERVO_V = None
	SERVO_H = None

	head_vertical_current_position = None
	head_horizontal_current_position = None

	def __init__(self):
		if env == "prod":

			log.debug("Using %s configuration" % self.CONTROLLER_BOARD )

			self.SERVO_H = AngularServo(self.HEAD_HORIZONTAL_PIN, min_angle=-80, max_angle=80)
			self.SERVO_V = AngularServo(self.HEAD_VERTICAL_PIN, min_angle=-80, max_angle=80)

			##Digital devices
			self.forward_left_device = None
			self.forward_right_device = None
			self.backward_left_device = None
			self.backward_right_device = None

			self.wheel_right_step = None
			self.wheel_left_step = None
			self.wheel_right_heading = None
			self.wheel_left_heading = None
			self.wheel_right_enabled = None
			self.wheel_left_enabled = None

			self.pwm_left = None
			self.pwm_right = None

			if self.CONTROLLER_BOARD == "v1":
				self.forward_left_device = DigitalOutputDevice(self.FORWARD_LEFT_PIN, True, False)
				self.forward_right_device = DigitalOutputDevice(self.FORWARD_RIGHT_PIN, True, False)
				self.backward_left_device = DigitalOutputDevice(self.BACKWARD_LEFT_PIN, True, False)
				self.backward_right_device = DigitalOutputDevice(self.BACKWARD_RIGHT_PIN, True, False)
				self.pwm_left = PWMOutputDevice(self.PWM_LEFT_PIN, True, False, self.FRECUENCY)
				self.pwm_right = PWMOutputDevice(self.PWM_RIGHT_PIN, True, False, self.FRECUENCY)


			if self.CONTROLLER_BOARD == "v2":
				self.wheel_right_step = DigitalOutputDevice(self.WHEEL_RIGHT_STEP, True, False)
				self.wheel_left_step = DigitalOutputDevice(self.WHEEL_LEFT_STEP, True, False)
				self.wheel_right_heading = DigitalOutputDevice(self.WHEEL_RIGHT_HEADING, True, False)
				self.wheel_left_heading = DigitalOutputDevice(self.WHEEL_LEFT_HEADING, True, False)
				self.wheel_right_enabled = DigitalOutputDevice(self.WHEEL_RIGHT_ENABLED, True, False)
				self.wheel_left_enabled = DigitalOutputDevice(self.WHEEL_LEFT_ENABLED, True, False)


		self.current_horizontal_head_pos = 0
		self.current_vertical_head_pos = 0
		self.center_head()
		self._counting_steps = 0
		self._current_steps = 0
		self._stepper_current_step = 0

	def _set_left_forward(self):
		if self.CONTROLLER_BOARD == "v1":
			self.forward_left_device.on()
			self.backward_left_device.off()


	def _set_left_backward(self):
		if self.CONTROLLER_BOARD == "v1":
			self.forward_left_device.off()
			self.backward_left_device.on()

	def _set_left_stop(self):
		if self.CONTROLLER_BOARD == "v1":
			self.forward_left_device.on()
			self.backward_left_device.on()

	def _set_right_forward(self):
		if self.CONTROLLER_BOARD == "v1":
			self.forward_right_device.on()
			self.backward_right_device.off()

	def _set_right_backward(self):
		if self.CONTROLLER_BOARD == "v1":
			self.forward_right_device.off()
			self.backward_right_device.on()

	def _set_right_stop(self):
		if self.CONTROLLER_BOARD == "v1":
			self.forward_right_device.on()
			self.backward_right_device.on()

	def set_forward(self):
		log.debug("setting movement to forward")
		if env == "prod":
			self._set_left_forward()
			self._set_right_forward()


	def set_backward(self):
		log.debug("setting movement to backward")
		if env == "prod":
			self._set_left_backward()
			self._set_right_backward()


	def set_rotate_left(self):
		log.debug("setting movement to rotate left")
		if env == "prod":
			self._set_left_backward()
			self._set_right_forward()

	def set_rotate_right(self):
		log.debug("setting movement to rotate right")
		if env == "prod":
			self._set_right_backward()
			self._set_left_forward()

	def stop(self):
		log.debug("stopping")
		if env == "prod":
			if self.CONTROLLER_BOARD == "v1":
				self.pwm_left.off()
				self.pwm_right.off()

	def move(self, speed=None, arc=None, steps=100, delay=0.7, heading=1):
		if self.CONTROLLER_BOARD == "v1":
			self._move_dc(speed, arc)
		elif self.CONTROLLER_BOARD == "v2":
			self._move_steppers_bipolar(steps=steps, delay=delay, heading=heading)

	def _move_dc(self, speed, arc):
		log.debug("Moving using DC motors")
		if (speed and arc):
			print("Error: speed and arc could not be setted up at the same time")
			return

		if env == "prod":
			self.pwm_left.on()
			self.pwm_right.on()

		if (speed):
			log.debug("moving on " + str(speed))
			log.debug("aplying fit: left " + str(self.LEFT_CYCLES_FIT) + " right " + str(self.RIGHT_CYCLES_FIT))
			aditional_left_clycles = self.LEFT_CYCLES_FIT if ((speed + self.LEFT_CYCLES_FIT) <= 100.00) else 0.00
			aditional_right_clycles = self.RIGHT_CYCLES_FIT if ((speed + self.RIGHT_CYCLES_FIT) <= 100.00) else 0.00

			if env == "prod":
				self.pwm_left.value = (speed + aditional_left_clycles) / 100.00
				self.pwm_right.value = (speed + aditional_right_clycles) / 100.00

		if (arc):
			cycle_left, cycle_right = arc
			log.debug("turning -> left wheel: " + str(cycle_left) + " right wheel: " + str(cycle_right))
			if env == "prod":
				self.pwm_left.value = cycle_left / 100.00
				self.pwm_right.value = cycle_right / 100.00



	def _move_steppers_bipolar(self, steps, heading, delay):
		"""
		Currently it would take 4 steps to complete a whole wheel turn
		"""
		log.debug("Moving steppers bipolars . Steps " + str(steps) + " delay " + str(delay))
		steps_left = abs(steps)

		if env == "prod":
			self.wheel_left_enabled.off()
			self.wheel_right_enabled.off()

		while(steps_left!=0):
			log.debug("Current step: " + str(steps_left))
			if env == "prod":
				if heading:
					self.wheel_left_heading.on()
					self.wheel_right_heading.off()
				else:
					self.wheel_left_heading.off()
					self.wheel_right_heading.on()

				self.wheel_left_step.off()
				self.wheel_right_step.off()
				sleep(delay/1000.00)
				self.wheel_left_step.on()
				self.wheel_right_step.on()
				sleep(delay/1000.00)
			steps_left -= 1

		if env == "prod":
			self.wheel_left_enabled.on()
			self.wheel_right_enabled.on()


	def center_head(self):
		log.debug("centering head")
		self.head_horizontal_current_position = 0
		self.head_vertical_current_position = 0
		if env == "prod":
			self.SERVO_H.mid()
			self.SERVO_V.mid()
			sleep(0.2)
			self.SERVO_H.detach()
			self.SERVO_V.detach()


	def _angle_to_ms(self,angle):
		return 1520 + (int(angle)*400) / 45


	def move_head_horizontal(self, angle):
		log.debug("horizontal limits: " + self.HEAD_HORIZONTAL_RANGE[0] +" "+ self.HEAD_HORIZONTAL_RANGE[1])
		log.debug("new horizontal angle: " + str(angle))
		if angle > int(self.HEAD_HORIZONTAL_RANGE[0]) and angle < int(self.HEAD_HORIZONTAL_RANGE[1]):
			log.debug("moving head horizontal to angle: " + str(angle))
			self.head_horizontal_current_position = angle
			if env == "prod":
				self.SERVO_H.angle = angle
				sleep(0.2)
				self.SERVO_H.detach()

	def move_head_vertical(self, angle):
		log.debug("vertical limits: " + self.HEAD_VERTICAL_RANGE[0] +" "+ self.HEAD_VERTICAL_RANGE[1])
		log.debug("new vertical angle: " + str(angle))
		if angle > int(self.HEAD_VERTICAL_RANGE[0]) and angle < int(self.HEAD_VERTICAL_RANGE[1]):
			log.debug("moving head vertical to angle: " + str(angle))
			self.head_vertical_current_position = angle
			if env == "prod":
				self.SERVO_V.angle = angle
				sleep(0.2)
				self.SERVO_V.detach()

	#Used for encoders
	def steps(self, counting):
		self._current_steps = counting
		self.move(speed=self.SPEED_HIGH)
		self.move(speed=self.SPEED_MEDIUM)
		rpio.add_interrupt_callback(RIGHT_WHEEL_SENSOR, self._steps_callback, threaded_callback=True)
		rpio.add_interrupt_callback(LEFT_WHEEL_SENSOR, self._steps_callback, threaded_callback=True)
		rpio.wait_for_interrupts(threaded=True)

	def _steps_callback(self, gpio_id, value):
		self._counting_steps += 1
		if self._counting_steps > self._current_steps:
			self._counting_steps = 0
			self._current_steps = 0
			rpio.stop_waiting_for_interrupts()
Example #16
0
from gpiozero import Button, DigitalOutputDevice
from gpiozero.pins.rpigpio import RPiGPIOPin, RPiGPIOFactory
from time import sleep
from flask import Flask, request, jsonify

#Tried using the debounce option but it isn't working as expected
#This bug is confirmed by the interwebs...
greenButton = Button(4, pull_up=False)
redButton = Button(17, pull_up=False)

output1 = DigitalOutputDevice(27)
output2 = DigitalOutputDevice(14)
output1.on()


class Actuator():
    pin1 = 27
    pin2 = 14

    def __init__(self):
        output1 = DigitalOutputDevice(pin1)
        output2 = DigitalOutputDevice(pin2)

    def Work(self):
        output1.on()
        output2.off()

    def Home(self):
        output1.off()
        output2.on()
Example #17
0
class PCD8544(SPIDevice):
    """
    PCD8544 display implementation.

    This implementation uses software shiftOut implementation?

    @author SrMouraSilva
    Based in 2013 Giacomo Trudu - wicker25[at]gmail[dot]com
    Based in 2010 Limor Fried, Adafruit Industries
          https://github.com/adafruit/Adafruit_Nokia_LCD/blob/master/Adafruit_Nokia_LCD/PCD8544.py
    Based in CORTEX-M3 version by Le Dang Dung, 2011 [email protected] (tested on LPC1769)
    Based in Raspberry Pi version by Andre Wussow, 2012, [email protected]
    Based in Raspberry Pi Java version by Cleverson dos Santos Assis, 2013, [email protected]


    https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md

    The SPI master driver is disabled by default on Raspbian.
    To enable it, use raspi-config, or ensure the line
    dtparam=spi=on isn't commented out in /boot/config.txt, and reboot.

    :param int din: Serial data input
    :param int sclk: Serial clock input (clk)
    :param int dc: Data/Command mode select (d/c)
    :param int rst: External reset input (res)
    :param int cs: Chip Enable (CS/SS, sce)

    :param contrast
    :param inverse
    """
    def __init__(self, din, sclk, dc, rst, cs, contrast=60, inverse=False):
        super(PCD8544, self).__init__(clock_pin=sclk, mosi_pin=din, miso_pin=9, select_pin=cs)

        self.DC = DigitalOutputDevice(dc)
        self.RST = DigitalOutputDevice(rst)

        self._reset()
        self._init(contrast, inverse)

        self.drawer = DisplayGraphics(self)
        self.clear()
        self.dispose()

    def _reset(self):
        self.RST.off()
        time.sleep(0.100)
        self.RST.on()

    def _init(self, contrast, inverse):
        # H = 1
        self._send_command(SysCommand.FUNC | Setting.FUNC_H)
        self._send_command(SysCommand.BIAS | Setting.BIAS_BS2)
        self._send_command(SysCommand.VOP | contrast & 0x7f)
        # H = 0
        self._send_command(SysCommand.FUNC | Setting.FUNC_V)
        self._send_command(
            SysCommand.DISPLAY |
            Setting.DISPLAY_D |
            Setting.DISPLAY_E * (1 if inverse else 0)
        )

    def _send_command(self, data):
        self.DC.off()

        self._spi.write([data])

    def _send_data_byte(self, x, y, byte):
        self._set_cursor_x(x)
        self._set_cursor_y(y)

        self.DC.on()
        self._spi.write([byte])

    def set_contrast(self, value):
        self._send_command(SysCommand.FUNC | Setting.FUNC_H)
        self._send_command(SysCommand.VOP | value & 0x7f)
        self._send_command(SysCommand.FUNC | Setting.FUNC_V)

    def write_all(self, data):
        self._set_cursor_x(0)
        self._set_cursor_y(0)

        self.DC.on()
        self._spi.write(data)

    def _set_cursor_x(self, x):
        self._send_command(SysCommand.XADDR | x)

    def _set_cursor_y(self, y):
        self._send_command(SysCommand.YADDR | y)

    def clear(self):
        self._set_cursor_x(0)
        self._set_cursor_y(0)

        self.drawer.clear()

    @property
    def width(self):
        return DisplaySize.WIDTH

    @property
    def height(self):
        return DisplaySize.HEIGHT

    @property
    def value(self):
        return 0

    def close(self):
        super(PCD8544, self).close()

    @property
    def draw(self):
        return self.drawer.draw

    def dispose(self):
        self.drawer.dispose()
Example #18
0
class PhotoBox:
    """My PhotoBox"""

    # Configuration
    config = None

    FBI = "/usr/bin/sudo /usr/bin/fbi"
    FBI_KILL = "/usr/bin/sudo /usr/bin/killall fbi"
    GPHOTO = "/usr/bin/gphoto2"
    OMX = "/usr/bin/omxplayer"

    # class variables
    button_instant = None
    button_delayed = None
    switch_light_A = None
    switch_light_B = None

    last_picture = None

    standby_timer = None
    review_timer = None
    error_timer = None

    def __init__(self):
        logger.info("Initializing PhotoBox")
        self.config = configparser.ConfigParser()
        if os.path.isfile("photobox.ini"):
            self.config.read("photobox.ini")
        else:
            raise Exception("photobox.ini not found")

#    import pdb; pdb.set_trace()

        gpio = int(self.config['GPIO']['button_instant'])
        self.button_instant = Button(gpio, hold_time=3)

        gpio = int(self.config['GPIO']['button_delayed'])
        self.button_delayed = Button(gpio)

        gpio = int(self.config['GPIO']['button_shutdown'])
        self.button_shutdown = Button(gpio)
        self.button_shutdown.when_pressed = self.shutdownRaspi

        gpio = int(self.config['GPIO']['switch_light_A'])
        self.switch_light_A = DigitalOutputDevice(gpio, active_high=False)

        gpio = int(self.config['GPIO']['switch_light_B'])
        self.switch_light_B = DigitalOutputDevice(gpio, active_high=False)

        # Prepare Standby Timer
        t = int(self.config['TIMES']['standby'])
        self.standby_timer = Timer(t * 60.0, self.standby)

        t = int(self.config['TIMES']['review'])
        self.review_timer = Timer(t * 1.0, self.active)

        t = 5  # also change _dtb ## fixed: 5sec error screen
        self.error_timer = Timer(t * 1.0, self.active)

        # set camera settings
        os.system("%s --set-config-value capturetarget=1" % self.GPHOTO)

        # setting config value does not seem to stick with all cameras. So just modifying gphoto2 settings here. Need to exist...
        # Yes, sorry, this does expect Linux, for now. Well, as do file/dir separators later on :)
        os.system(
            '/bin/grep "ptp2=capturetarget=card" ~/.gphoto/settings || /bin/echo "ptp2=capturetarget=card" >>~/.gphoto/settings'
        )

        # go into Active after init
        self.active()

    def shutdownRaspi(self):
        self._switch_lights(to=True)
        sleep(2)
        self._switch_lights(to=False)
        sleep(2)
        self._switch_lights(to=True)
        sleep(2)
        self._switch_lights(to=False)
        sleep(2)
        self._switch_lights(to=True)
        sleep(2)
        self._switch_lights(to=False)
        sleep(2)
        os.system("sudo shutdown -r now")

    def _remove_state(self, state):
        f = self.config['PATHS']['state'] + "/" + state
        if os.path.isfile(f):
            os.remove(f)

    def _set_state(self, state):
        if not self.config['PATHS']['state']:
            return
        # remove all possible files - do not care about old state
        self._remove_state("active")
        self._remove_state("standby")
        self._remove_state("error")
        self._remove_state("maintenance")

        f = open(self.config['PATHS']['state'] + "/" + state, "w+")
        f.write(state)
        f.close()

    ## disable timers and buttons
    def _dtb(self):
        dtbdebug = False

        dtbdebug and logger.debug(
            "_dtb: Disabling all Timers and Button activities")
        # Disable Timers and Buttons

        dtbdebug and logger.debug("_dtb: cancel standby")
        self.standby_timer.cancel()
        t = int(self.config['TIMES']['standby'])
        self.standby_timer = Timer(t * 60.0, self.standby)

        dtbdebug and logger.debug("_dtb: cancel review")
        self.review_timer.cancel()
        t = int(self.config['TIMES']['review'])
        self.review_timer = Timer(t * 1.0, self.active)

        dtbdebug and logger.debug("_dtb: cancel error")
        self.error_timer.cancel()
        t = 5  # also change __init__ ## fixed: 5sec error screen
        self.error_timer = Timer(t * 1.0, self.active)

        dtbdebug and logger.debug("_dtb: unset instant when_held")
        self.button_instant.when_held = None

        dtbdebug and logger.debug("_dtb: unset instant when_pressed")
        self.button_instant.when_pressed = None

        dtbdebug and logger.debug("_dtb: unset delayed when_pressed")
        self.button_delayed.when_pressed = None

    def _switch_lights(self, to=False):
        logger.debug("_switch_lights: Switching Lights state")
        if to is None:  # toggle
            self.switch_light_A.value = not self.switch_light_A.value
            self.switch_light_B.value = not self.switch_light_B.value
        elif to == True:  # turn on
            self.switch_light_A.on()
            self.switch_light_B.on()
        else:  # secure state = off
            self.switch_light_A.off()
            self.switch_light_B.off()

    def _fbi(self, file=None, folder=None, delay=15, random=0):
        logger.debug("_fbi: Displaying image")
        # remove all old images
        os.system(self.FBI_KILL)

        # show new image
        fbi = self.FBI + " --noverbose -a -T 1"

        if random:
            fbi += " -u "

        if folder is None:
            fbi += " %s " % file
        else:
            fbi += " -t %d -u %s/*" % (delay, folder)

        os.system(fbi)

    def _get_battery_level(self):
        logger.debug("_get_battery_level")

        call = "LANG=en %s --get-config /main/status/batterylevel" % self.GPHOTO
        out = subprocess.Popen(call,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT,
                               shell=True).communicate()[0]

        # analyze lines returned
        power = 0
        cameraerror = False

        if out:
            # analyze lines returned

            for o in out.splitlines():
                logger.debug("LINE: %s" % o)

                # look for battery current state
                mtch = re.search('Current: (\d+)%', o)
                if mtch:
                    power = int(mtch.group(1))
                    logger.info("---- Found Battery level %i" % power)

                # look for error state
                mtch = re.search('Error: No camera found', o)
                if mtch:
                    cameraerror = True
                    logger.critical("---- Found No Camera found error")

        # camera error - unrecoverable: Go to maintenance
        if cameraerror:
            self.maintenance()
            return

        # battery power low? show notice for 5 seconds
        if power <= 15:
            self._fbi(file="fbi/battery.png")
            sleep(3)
            return

        # and do whatever was planned to do next :)
        return power

    def _take_photo(self, delay=None, rnd=0):
        logger.debug("_take_photo")
        self._dtb()  # disable Timer and Buttons

        # tried to take a photo 3 times - something is wrong, going to error mode
        if (rnd == 3):
            logger.warn("Encountered multiple errors, stopping at 3 retries")
            self.error(file="fbi/error-retry.png")
            return

        # delayed picture: show countdown video
        if delay is None:
            # No countdown, just turn on lights
            if self.config['LIGHTS']['flash_lights']:
                self._switch_lights(True)
                # and give it a second to be sure it's on
                sleep(1)
        elif delay == 3:
            if self.config['LIGHTS']['flash_lights']:
                self._switch_lights(True)
            subprocess.Popen([self.OMX, "countdown/countdown3.mp4"])
            sleep(3)
        else:
            subprocess.Popen([self.OMX, "countdown/countdown.mp4"])
            sleep(5)  # time delayed display, so that it will take a photo at 0
            if self.config['LIGHTS']['flash_lights']:
                self._switch_lights(True)
            sleep(4)

        self.last_picture = self.config['PATHS']['storage'] + "/current.png"

        call = "LANG=en %s --filename %s --force-overwrite --keep-raw --capture-image-and-download --get-config /main/status/batterylevel" % (
            self.GPHOTO, self.last_picture)
        logger.debug("starting: " + call)

        prc = subprocess.Popen(call,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.STDOUT,
                               shell=True)

        self._fbi(file="fbi/transfer.png")

        # blocking, await gphoto2 finish
        out = prc.communicate()[0]

        if self.config['LIGHTS']['flash_lights']:
            self._switch_lights(False)

        # analyze lines returned
        power = 0
        filename = ""
        focuserror = False
        cameraerror = None

        if out:
            # analyze lines returned

            for o in out.splitlines():
                logger.debug("LINE: %s" % o)

                # look for filename
                mtch = re.search('Deleting file .*/(DSC.*\.JPG) on the camera',
                                 o)
                if mtch:
                    filename = mtch.group(1)
                    logger.debug("---- Found filename %s" % filename)

            # look if camera is set to RAW
                mtch = re.search('Keeping file .*/(DSC.*\.NEF) on the camera',
                                 o)
                if mtch:
                    logger.error("---- Camera uses RAW/NEF")
                    cameraerror = "fbi/error-raw.png"

                # look for battery level
                mtch = re.search('Current: (\d+)%', o)
                if mtch:
                    power = int(mtch.group(1))
                    logger.debug("---- Found Battery level %i" % power)

                # look for error state
                # no camera
                mtch = re.search('Error: No camera found', o)
                if mtch:
                    cameraerror = "fbi/error-nocam.png"
                    logger.error("---- Found No Camera error")

                # sd card problems (most likely full)
                mtch = re.search('PTP Store Not Available', o)
                if mtch:
                    cameraerror = "fbi/storage-ptp.png"
                    logger.error("---- Found PTP (SD Card) error")

                # camera does not store to SD
                mtch = re.search(
                    'New file is in location /capt0000.jpg on the camera', o)
                if mtch:
                    cameraerror = "fbi/storage-sd.png"
                    logger.error(
                        "---- Found file location error, not storing to SD card"
                    )

                # local pi storage full
                mtch = re.search('write: No space left on device', o)
                if mtch:
                    cameraerror = "fbi/storage-pi.png"
                    logger.error("---- Found Storage (main or backup) error")

                mtch = re.search('Out of Focus', o)
                if mtch:
                    focuserror = True
                    logger.debug("---- Found Focus error")

        # camera error - unrecoverable: Go to maintenance
        if cameraerror:
            self._fbi(file=cameraerror)
            sleep(30)
            self.maintenance()
            return

        # focus error - try again, up to 3 times
        if focuserror:
            self._take_photo(rnd=rnd + 1)
            return

        # battery power low? show notice for 5 seconds
        if power <= 15:
            logger.warn("Low battery level: %i %" % power)
            self._fbi(file="fbi/battery.png")
            sleep(3)
            return

        if filename:

            # review pic
            # note: will not activate buttons
            self.review(activateButtons=False)

            splfile = filename.split('.')
            splfile.insert(len(splfile) - 1, str(uuid.uuid4()))
            filenameuuid = '.'.join(splfile)

            # copy to storage dir
            new_target = self.config['PATHS']['storage'] + "/" + filenameuuid
            try:
                copyfile(self.last_picture, new_target)
            except (OSError, IOError) as e:
                # if an error occurs, assume storage problem and move to maintenance
                logger.critical(e)
                self._fbi(file="fbi/storage-file.png")
                sleep(30)
                self.maintenance()
                return

            # copy to backup dir, if exists
            if self.config['PATHS']['backup']:
                new_target = self.config['PATHS']['backup'] + "/" + filenameuuid
                try:
                    copyfile(self.last_picture, new_target)
                except (OSError, IOError) as e:
                    # if an error occurs, assume storage problem and move to maintenance
                    logger.critical(e)
                    self._fbi(file="fbi/storage-backup.png")
                    sleep(30)
                    self.maintenance()
                    return

            # copy to web last dir, if exists
            if self.config['PATHS']['lastweb']:
                new_target = self.config['PATHS'][
                    'lastweb'] + "/" + filenameuuid
                try:
                    copyfile(self.last_picture, new_target)
                    # Create HTML file
                    lw = open(self.config['PATHS']['lastweb'] + "/index.html",
                              "w+")
                    lw.write(
                        '<html><body><img width="640" src="%s" /></body></html>'
                        % filenameuuid)
                    lw.close()

                except (OSError, IOError) as e:
                    # if an error occurs, ignore.
                    logger.critical(e)
                    logger.critical("ignored for web")
                    return

            # activate buttons in review mode
            self.review(buttonsOnly=True)
            return

        else:
            # no filename found - most likely not downloaded from camera?
            logger.error("no filename found in camera output")
            self.error(file="fbi/error-file.png")
            return

    def _take_photo_delayed(self):
        logger.debug("_take_photo_delayed")
        return self._take_photo(delay=1)

    def _take_photo_delayedshort(self):
        logger.debug("_take_photo_delayedshort")
        return self._take_photo(delay=3)

    def _delete_photo(self):
        logger.debug("_delete_photo")
        self._dtb()  # disable Timer and Buttons

        # Sorry, never delete anything :)
        # But I'll mark it deleted, by moving it to another folder

        # TODO file handling - move to deleted folder

        # Display DELETED message

        # wait for 2 seconds so the users will notice it
        sleep(2)

        # become active afterwards
        self.active()

    def standby(self):
        logger.debug("standby")
        self._dtb()  # disable Timer and Buttons
        self._set_state("standby")

        # Turn off Lights
        if not self.config['LIGHTS']['flash_lights']:
            self._switch_lights(False)

        # FBI slideshow "standby" folder
        self._fbi(folder="fbi/standby", random=1)

        # Wait for any key press to become active
        self.button_instant.when_pressed = self.active
        self.button_delayed.when_pressed = self.active

    def active(self):
        logger.debug("active")
        self._dtb()  # disable Timer and Buttons
        self._set_state("active")

        # looks for battery level, will display warning, and go to maintenance if camera not found
        self._get_battery_level()

        # Turn on Lights
        if not self.config['LIGHTS']['flash_lights']:
            self._switch_lights(True)

        # FBI main screen
        self._fbi(file="fbi/active.png")

        # Wait for key press to init countdown / directly snap
        self.button_instant.when_pressed = self._take_photo_delayedshort
        self.button_delayed.when_pressed = self._take_photo_delayed

        # after self.standby minutes without state change, go to standby
        self.standby_timer.start()

    def review(self, activateButtons=True, buttonsOnly=False):
        logger.debug("review")

        if buttonsOnly == False:
            self._dtb()  # disable Timer and Buttons

            # Keep lights are they were
            # Show picture
            self._fbi(file=self.last_picture)

        if buttonsOnly == True or activateButtons == True:
            # at "long?" Instant keypress, move Image to Deleted
            self.button_instant.when_held = self._delete_photo

            # at Delayede keypress or after 15sec, restart active
            self.button_delayed.when_pressed = self.active
            self.button_instant.when_pressed = self.active

        if buttonsOnly == False:
            # go to active after review time
            self.review_timer.start()

    def error(self):
        logger.debug("error")
        self._dtb()  # disable Timer and Buttons
        self._set_state("error")

        # Keep lights are they were

        # FBI error screen
        self._fbi(file="fbi/error.png")

        # at Delay keypress or after 15sec, restart active
        self.button_delayed.when_pressed = self.active
        self.button_instant.when_pressed = self.active

        # go to active after review time
        self.error_timer.start()

    def maintenance(self):
        logger.debug("maintenance")
        self._dtb()  # disable Timer and Buttons
        self._set_state("maintenance")

        # Turn off lights
        if not self.config['LIGHTS']['flash_lights']:
            self._switch_lights(False)

        # FBI slideshow "maintenance" folder
        self._fbi(folder="fbi/maintenance", random=1)

        # On DUAL keypress, output error information
        while 1:
            if self.button_instant.is_pressed and self.button_delayed.is_pressed:
                # TODO output error messages
                break
            sleep(0.5)

        # output log to console 1
        os.system(self.FBI_KILL)
        os.system("/usr/bin/sudo /bin/cat ~pi/photobox.log >/dev/tty1")

        sleep(5)  # to avoid instant triggering

        # get active on keypress
        self.button_instant.when_pressed = self.active
        self.button_delayed.when_pressed = self.active
Example #19
0
#!/usr/bin/env python
print("Loading...")\

from gpiozero import DigitalOutputDevice
from time import sleep

pin = DigitalOutputDevice(21)

print("Turning fan on for 20 seconds, turn potentiometer to test.")
pin.on()
sleep(20)
print("Turning fan off")
pin.off()

print("Exiting")
pin.close()
exit()
from gpiozero import DigitalOutputDevice
from time import sleep

sol = DigitalOutputDevice(20)
sLED = DigitalOutputDevice(21)

for i in range(10):
    sol.on()
    sLED.on()
    sleep(0.5)
    sol.off()
    sLED.off()
    sleep(0.5)

sol.close()
Example #21
0
class MotorControl:
    def __init__(self):

        #Define a winch carabiner height variable (meters)
        self.z_winch = 0

        #Define winch to to climber margin of error (meters)
        self.WINCH_OFFSET = .05

        #Define winch speed CONSTANT (meters/s)
        self.WINCH_SPEED = 0.1

        #Define winch_in timer
        self.winch_in_timer = 0

        #Define winch_out timer
        self.winch_out_timer = 0

        #Define winch out switch variable (meters/s)
        self.winch_out = DigitalOutputDevice(23)

        #Define a lowering flag
        self.lower_flag = 0

        #Define winch in switch variable (meters/s)
        self.winch_in = DigitalOutputDevice(25)

        #Deine a fall flag
        self.fall_flag = 0

        #Define fall timer for seeing how long after a fall
        self.fall_timer = 0

        # stop motor if above threshold
        self.threshhold = .5

    def rotate(self, z_climber, acc):
        #Update the winch position
        if (self.winch_in.value == 1):
            self.z_winch = self.z_winch + self.WINCH_SPEED * (
                time.time() - self.winch_in_timer)
        elif (self.winch_out.value == 1):
            self.z_winch = self.z_winch - self.WINCH_SPEED * (
                time.time() - self.winch_out_timer)
        else:
            self.z_winch = self.z_winch

        #check if a fall has occurred
        if (self.fall_flag == 1):
            #Check the timer to see if 2 seconds has elapsed and lower climber
            if ((time.time() - self.fall_timer) >= 5):
                self.lower_flag = 1
                self.fall_flag = 0

        #check if lowering
        elif (self.lower_flag == 1):

            #Check if climber to winch distance is greater than 5 cm
            #             if((z_climber - self.z_winch) > self.WINCH_OFFSET):
            #                 #turn off motor_out
            #                 self.winch_out.off();
            #                 #Reset motor_out_timer
            #                 self.winch_out_timer = 0;
            #                 #turn on motor_in
            #                 self.winch_in.on();
            #                 #Record motor_in_timer start time
            #                 self.winch_in_timer = time.time();
            #
            #If at the bottom, stop the winch
            if (self.z_winch < self.WINCH_OFFSET):
                #Turn off motor_in and motor_out
                self.winch_in.off()
                #Reset motor_in_timer
                self.winch_in_timer = 0
                self.winch_out.off()
                #Reset motor_out_timer
                self.winch_out_timer = 0

            #Otherwise continue lowering
            else:
                self.winch_out.on()
                #Record motor_out_timer start time
                self.winch_out_timer = time.time()
                self.winch_in.off()
                #Reset motor_in_timer
                self.winch_in_timer = 0

        #Normal climbing mode
        else:
            if (self.z_winch >= self.threshhold):
                self.winch_out.off()
                self.winch_out_timer = 0
                self.winch_in.off()
                self.winch_in_timer = 0

            #Check if climber is higher than winch carabiner
            elif ((z_climber - self.z_winch) > self.WINCH_OFFSET):

                #Check if motor in and out are both on
                if (self.winch_in.value == 1 and self.winch_out.value == 1):
                    #Turn off winch_out
                    self.winch_out.off()
                    #Reset motor_out_timer
                    self.winch_out_timer = 0
                    #Turn on winch_in
                    self.winch_in.on()
                    #Record motor_in_timer start time
                    self.winch_out_timer = time.time()

                #Check if winch_in is off and motor_out is 1
                elif (self.winch_in.value == 0 and self.winch_out.value == 1):
                    #Turn off motor_out
                    self.winch_out.off()
                    #Reset motor_out_timer
                    self.winch_out_timer = 0
                    #Turn on winch_in
                    self.winch_in.on()
                    #Record motor_in_timer start time
                    self.winch_in_timer = time.time()

                #Check if motor in and out are off
                elif (self.winch_in.value == 0 and self.winch_out.value == 0):
                    #Turn off motor_out
                    self.winch_out.off()
                    #Reset motor_out_timer
                    self.winch_out_timer = 0
                    #Turn on motor_in
                    self.winch_in.on()
                    #Record motor_in_timer start time
                    self.winch_in_timer = time.time()

                #Check if motor_in is on and motor_out is off
                elif (self.winch_in.value == 1 and self.winch_out.value == 0):
                    #Turn off motor_out
                    self.winch_out.off()
                    #Reset motor_out_timer
                    self.winch_out_timer = 0
                    #Turn on motor_in
                    self.winch_in.on()
                    #Record motor_in_timer start time
                    self.winch_in_timer = time.time()

                #motor_in == 1 must always be true in this condition
                else:
                    self.winch_out.off()
                    #Reset motor_out_timer
                    self.winch_out_timer = 0
                    self.winch_in.on()
                    #Record motor_in_timer start time
                    self.winch_in_timer = time.time()

            #Check if climber and winch positions are equal
            elif (np.abs(z_climber - self.z_winch) < self.WINCH_OFFSET):
                #Turn off motor_in and motor_out
                self.winch_in.off()
                #Reset winch_in_timer
                self.winch_in_timer = 0
                self.winch_out.off()
                #Reset winch_out_timer
                self.winch_in_timer = 0

            #Check if climber position is less than carabiner
            if (acc < -8.5
                ):  #((z_climber - self.z_winch) < (-1*self.WINCH_OFFSET)):
                #This is a fall condition we need to accomodate
                self.fall_flag = 1
                #start fall timer
                self.fall_timer = time.time()
                #Turn off motor_in
                self.winch_in.off()
                #Record motor_in_timer start time
                self.winch_in_timer = 0
                #Turn on motor_out
                self.winch_out.off()
                #Set winch_out_timer start time
                self.winch_out_timer = 0
Example #22
0
#!/usr/bin/env python


from gpiozero import DigitalOutputDevice
from time import sleep


rLight = DigitalOutputDevice(21,active_high=False)

rLight.on()
#sleep(10)
#rLight.off()




Example #23
0
from gpiozero import DigitalOutputDevice
from time import sleep

print("blink.py start")

led_pin = DigitalOutputDevice(7)

print(type(led_pin))

while True:
    led_pin.on()  # HIGH
    print(led_pin.value)  # Gets the state of the pin
    sleep(3)

    led_pin.off()  # LOW
    print(led_pin.value)
    sleep(1)
Example #24
0
from gpiozero import DigitalOutputDevice
import time
#import sys

signal = DigitalOutputDevice(14)

print("Running")
#print(sys.argv[1])
#if(sys.argv[1] == '0'):
#	print("Turn off")
#	signal.on()
#elif(sys.argv[1] == '1'):
#	print("Turn on")
#	signal.off()

while True:
    now = time.localtime()
    time.sleep(60)
    if (now.tm_hour >= 19 or now.tm_hour < 1):
        signal.off()
    else:
        signal.on()
Example #25
0
from gpiozero import DigitalOutputDevice
import time

winch_in = DigitalOutputDevice(25)
winch_out = DigitalOutputDevice(23)

winch_in.off()
winch_out.off()
for i in range(1):
    winch_out.on()

    time.sleep(1)

winch_in.off()
winch_out.off()
Example #26
0
class PM25:
    def __init__(self, channel, tca, pwr_pin, num_iterations=3, precision=3):
        if pwr_pin is None:
            raise ValueError(f"must supply pwr_pin")
        # TODO: I'm not doing anything with the units here
        self.pwr_pin = DigitalOutputDevice(pwr_pin)
        # TODO: improve logic
        self.device = self._create_device(channel, tca)

        self.num_iterations = num_iterations
        self.precision = precision
        self.accepted_units = ["ug/m^3", "um/0.1L"]

    def _parse_sensor(self):
        self.pwr_pin.on()
        # NOTE: the device needs to run for 30+ seconds to initialize
        time.sleep(40)
        try:
            aqdata = self.device.read()
        except (OSError, RuntimeError) as e:
            print(f"ERROR!: {e}")
            aqdata = None

        vals, units = {}, {}
        if aqdata:
            # keys
            # reading key, unit, new_name
            # Particle Matter concentrations of different size particles in micro-gram per cubic meter
            sensor_keys = [
                ("particles 03um", "03um/0.1L", "particle_03um"),
                ("particles 05um", "05um/0.1L", "particle_05um"),
                ("particles 10um", "10um/0.1L", "particle_10um"),
                ("particles 25um", "25um/0.1L", "particle_25um"),
                ("particles 50um", "50um/0.1L", "particle_50um"),
                ("particles 100um", "100um/0.1L", "particle_100um"),
                ("pm10 standard", "ug/m^3", "standard_pm10"),
                ("pm10 env", "ug/m^3", "env_pm10"),
                ("pm25 standard", "ug/m^3", "standard_pm25"),
                ("pm25 env", "ug/m^3", "env_pm25"),
                ("pm100 standard", "ug/m^3", "standard_pm100"),
                ("pm100 env", "ug/m^3", "env_pm100"),
            ]

            for skt in sensor_keys:
                vals[skt[2]] = aqdata[skt[0]]
                units[skt[2]] = skt[1]
        return vals, units

    def _create_device(self, channel, tca):
        self.pwr_pin.on()
        # NOTE: must allow device to be on for initialization
        time.sleep(2)
        try:
            device = PM25_I2C(tca[channel])
        except OSError:
            # Try one more time
            self.pwr_pin.off()
            time.sleep(1)
            self.pwr_pin.on()
            time.sleep(2)
            try:
                device = PM25_I2C(tca[channel])
            except Exception:
                raise OSError(
                    f"Unable to initialize PM25 device. please double check {self.pwr_pin} is correct on/off pin"
                )
        return device

    def return_value(self, **kwargs):
        # TODO: this is a pretty rough first cut
        # the units will need to be addressed more elegantly
        try:
            unit = kwargs["unit"]
        except KeyError:
            raise ValueError(f"unit not in {kwargs}")
        if unit:
            if not isinstance(unit, str):
                raise ValueError(
                    f"unit ({unit}) is expected to be type {str}, not {type(unit)}"
                )
            if unit not in self.accepted_units:
                raise ValueError(
                    f"unit {unit} not currently supported. Please select from {self.accepted_units}"
                )
        else:
            raise ValueError(f"`unit` is expected to exist")

        raw_vals = {}
        cur_u = {}
        for i in range(self.num_iterations):
            cur_v, cur_u = self._parse_sensor()
            # sleep betweek events
            time.sleep(10)
            raw_vals[f"{i}"] = cur_v
        self.pwr_pin.off()
        val_dict = average_dict(raw_vals)

        # format output
        if self.precision:
            for k, v in val_dict.items():
                val_dict[k] = round(v, self.precision)

        additional_vals = {
            "particle_num_unit": "um/0.1L",
            "particle_concentration_unit": "ug/m^3",
            "num_iterations": self.num_iterations,
        }
        out = {**val_dict, **additional_vals}

        return out
Example #27
0
from gpiozero import DigitalOutputDevice
from time import sleep

pinAred = DigitalOutputDevice(17)
pinByellow = DigitalOutputDevice(27)
pinCgreen = DigitalOutputDevice(22)
pinDblack = DigitalOutputDevice(23)

pinEred = DigitalOutputDevice(13)
pinFyellow = DigitalOutputDevice(6)
pinGgreen = DigitalOutputDevice(5)
pinHblack = DigitalOutputDevice(12)

pinAred.on()
pinByellow.on()
pinCgreen.off()
pinDblack.off()
pinEred.off()
pinFyellow.off()
pinGgreen.off()
pinHblack.on()
sleep(1)

pinAred.close()
pinByellow.close()
pinCgreen.close()
pinDblack.close()
pinEred.close()
pinFyellow.close()
pinGgreen.close()
pinHblack.close()
Example #28
0
class Bot:
    def __init__(self):
        self.leftMotorEnable = PWMOutputDevice(LEFT_MOTOR_ENABLE_PIN)
        self.leftMotorDirection1 = DigitalOutputDevice(LEFT_MOTOR_IN1_PIN)
        self.leftMotorDirection2 = DigitalOutputDevice(LEFT_MOTOR_IN2_PIN)
        self.rightMotorEnable = PWMOutputDevice(RIGHT_MOTOR_ENABLE_PIN)
        self.rightMotorDirection1 = DigitalOutputDevice(RIGHT_MOTOR_IN1_PIN)
        self.rightMotorDirection2 = DigitalOutputDevice(RIGHT_MOTOR_IN2_PIN)

        self.speed = 0
        self.speedLeft = 0
        self.speedRight = 0
        self.direction = 0

    def processCommand(self, command):
        speed, direction = struct.unpack('>Hh', command)

        print(speed, direction)

        self.updateBot(speed, direction)

    def updateBot(self, speed, direction):
        self.speed = speed
        self.direction = direction

        if speed == 0: self.stop()
        else:
            self.speedLeft = DIRECTIONS[str(direction)][0] * (self.speed / 100)
            self.speedRight = DIRECTIONS[str(direction)][1] * (self.speed /
                                                               100)

            self.setLeftMotorSpeed(self.speedLeft)
            self.setRightMotorSpeed(self.speedRight)

    def setLeftMotorSpeed(self, speed):
        print('leftForwardSpeed' + str(speed))
        self.leftMotorEnable.value = abs(speed)
        if speed > 0:
            self.leftMotorDirection1.on()
            self.leftMotorDirection2.off()
        else:
            self.leftMotorDirection1.off()
            self.leftMotorDirection2.on()

    def setRightMotorSpeed(self, speed):
        print('rightForwardSpeed' + str(speed))
        self.rightMotorEnable.value = abs(speed)
        if speed > 0:
            self.rightMotorDirection1.on()
            self.rightMotorDirection2.off()
        else:
            self.rightMotorDirection1.off()
            self.rightMotorDirection2.on()

    def leftMotorStop(self):
        self.leftMotorEnable.off()

    def rightMotorStop(self):
        self.rightMotorEnable.off()

    def stop(self):
        self.leftMotorStop()
        self.rightMotorStop()
Example #29
0
# Version: 1.0

# Library Import
from gpiozero import DigitalOutputDevice  # DIGITALOUTPUTDEVICE is for RELAIS
from gpiozero import Button
from gpiozero.pins.pigpio import PiGPIOFactory
import time

# IPADRES CHANGE THE GREEN TEXT TO CHANGE IP ADRES
factory = PiGPIOFactory('192.168.0.112')

# Setup Outputs
# Relais
CH1 = DigitalOutputDevice(17, True, False, pin_factory=factory)

# LED's
LED1 = DigitalOutputDevice(26, pin_factory=factory)

# Setup Inputs
# Buttons
BTN1 = Button(pin=14, pull_up=False, bounce_time=0.25, pin_factory=factory)

if BTN1.value == 1 and CH1.value == 0:
    CH1.on()
    LED1.on()
    time.sleep(0.25)
if BTN1.value == 1 and CH1.value == 1:
    CH1.off()
    LED1.off()
    time.sleep(0.25)
Example #30
0
    class Control:
        controls = []   # array of all sensor instances (in order of creation for status printout)
        by_name = {}    # dict of all controls by name
        by_pin = {}     # dict of all controls by pin
        names = []      # array of control names (in order of creation for status printout)

        def __init__(self, pin, name, active_high=True, initial_value=False, toggle_delay=0.5):
            # TODO throw exception if pin not set
            self.name = name
            self.isControl = True
            self.device = DigitalOutputDevice(pin=pin, active_high=active_high, initial_value=initial_value)
            self.toggle_delay = toggle_delay
            Gpio.Control.controls.append(self)
            Gpio.Control.by_name[name] = self
            Gpio.Control.by_pin[pin] = self
            Gpio.Control.names.append(name)

            # Fob control magic
            if (name == 'fob'):
                self.fob_wait = self.toggle_delay + 3.0    # Delay after toggle to check for roof motion
                self.fob_tries = 3                         # How many times we try toggling before we give up
                self.togglingFob = 0                       # Flag to track when we're toggling


        def turnOn(self):
            self.device.on()
            browser.browser.updateBrowser()
            logging.info(printStatus())

        def turnOff(self):
            self.device.off()
            browser.browser.updateBrowser()
            logging.info(printStatus())

        def is_active(self):
            return(self.device.value == 1)

        def isOn(self):
            return(self.device.value == 1)

        def isOff(self):
            return(self.device.value == 0)

        def toggle(self, step=0):
            """Toggle the control ouput on then off"""
            if (step == 0):
                logging.info("Toggle {}".format(self.name))
                self.turnOn();
                threading.Timer(self.toggle_delay, self.toggle, [1]).start()
            elif (step == 1):
                self.turnOff();
            else:
                logging.error("WTF? toggle() called with step %".format(step))

        # Fob has speical toggle magic to ensure the roof starts moving
        def toggleFob(self, step=0):
            """Toggle fob and check for roof movement, retrying up to fob_tries times"""
            if (self.name != 'fob'):
                logging.error("toggleFob() called for {}".format(self.name))
                return(-1)
            if (step == 0 and self.togglingFob):
                logging.error("toggleFob() called while toggling already in progress")
                return(-1)
            # If roof is middle just revert to toggle
            if (step == 0 and Gpio.open.roofPosition() == roof.MIDWAY):
                self.togglingFob = 0
                self.toggle()
                return(0)

            # If we're a scheduled callback check for status
            if (step > 0 and Gpio.open.roofPosition() == roof.MIDWAY):
                browser.browser.sendNotice("Roof is midway")
                logging.info("toggleFob() detected roof movement")
                self.togglingFob = 0
                return(0)

            # Bail after x tries
            if (step >= self.fob_tries):
                browser.browser.sendNotice("No roof movement; giving up")
                logging.error("toggleFob() failed to detect movement after {} tries; giving up".format(step))
                self.togglingFob = 0
                return(1)

            # Toggle and schedule a callback to check for movement
            if (step > 0):
                browser.browser.sendNotice("Retrying fob ({}/{})".format(step+1, self.fob_tries))
            self.togglingFob = 1  # Should we use a timestamp so we can "expire" just in case?
            self.toggle()
            logging.info("toggleFob({}) waiting {} seconds".format(step, self.fob_wait))
            threading.Timer(self.fob_wait, self.toggleFob, [step+1]).start()
            return(0)
    Setup GPIO 17 as digital output
    """
    fan_switch = DigitalOutputDevice(17, True, False)


def fan_on():
    print("turning fan on")
    fan_switch.on()


def fan_off():
    print("turning fan off")
    fan_switch.off()


from gpiozero import CPUTemperature
from time import sleep

fan = DigitalOutputDevice(17)

TEMP_TH = 40.0  # CPU Temp threshold (C))

cpu = CPUTemperature()
if (cpu.temperature > TEMP_TH):
    print("turning fan on")
    fan.on()
    sleep(5)
else:
    print("turning fan off")
    fan.off()
Example #32
0
def motor_jog(current_step, velocity = 3200, acceleration = 2000, steps = 1600, absolute = False): # velocity in steps/s, acceleration in steps/s^2
    # defines pin numbers
    pulse_pin     = DigitalOutputDevice(24)
    direction_pin = DigitalOutputDevice(25)
    enable_pin    = DigitalOutputDevice(22)

    # sets correct direction pin voltage and enables the enable pin
    enable_pin.on()
    if absolute:
        target_step = steps
        multiplier = np.sign(steps - current_step)
    else:
        target_step = current_step + steps
        multiplier = np.sign(steps)
        steps = np.abs(steps)
    if multiplier   == 1:
        direction_pin.off()
    elif multiplier == -1:
        direction_pin.on()

    # creates loop variables
    jog_steps = []
    jog_times = []
    current_velocity = 100
    initial_step = current_step
    acceleration_steps = velocity**2/(2*acceleration) # approx. num. of steps taken during acceleration
    current_time = time.perf_counter()

    try:
        #steps forward at the appropriate time
        while current_step != target_step:
            #turn pulse pin on and get current time
            last_time = current_time
            current_time = time.perf_counter()
            pulse_pin.on()
            dt = current_time - last_time

            ## calculate delay time to next step
            half_over = np.absolute(current_step - initial_step) > np.absolute(target_step - current_step) # are we more than half done travelling?
            # if we are still accelerating, increase current_velocity
            if (current_velocity != velocity and not half_over):
                current_velocity = min(velocity, current_velocity + acceleration * max(dt,1E-7))
            # if we are decelerating, decrease current_velocity
            elif (np.absolute(target_step - current_step) < acceleration_steps != velocity and half_over):
                current_velocity = max(100, current_velocity - acceleration * dt)

            # each step takes 1/current_velocity time (in s)
            delay = 1/current_velocity

            # save values
            jog_times.append(current_time) # save current time
            current_step = current_step + multiplier # calculate current step
            jog_steps.append(current_step) # save current step

            # WAIT to turn pulse pin off, then wait again
            better_sleep(delay/2, current_time)
            # turn pulse pin off, WAIT
            pulse_pin.off()
            better_sleep(delay, current_time)

        # done with movement, so we turn the enable pin off
        enable_pin.off()

    except KeyboardInterrupt:
        print("\nUser exit during motor usage. Powering down.\n")

        pulse_pin.off()
        enable_pin.off()

        sys.exit(0)

    return jog_steps, jog_times, current_step
Example #33
0
time.sleep(.1)
state = 0
latitude = 0.0
longitude = 0.0
while(1):
    try:
        blynk.run()
        print(sensor.readThermistor())
        if sensor.readThermistor() > 40.0 and mq_sensor.value == 1 and state == 0:
            print("Fire Alert")
            blynk.virtual_write(0, 1, latitude, longitude, "Fire_location")
            blynk.virtual_write(1, latitude)
            blynk.virtual_write(2, longitude)
            blynk.notify("Fire Alert")
            sprinkler.on()
            state = 1
        elif sensor.readThermistor() < 40.0 and mq_sensor.value == 0 :
            sprinkler.off()
            state = 0
        data = gps.readline()
        data_str = data.decode('ascii')
        message = data[0:6]
        if (message == "$GPRMC"):
            parts = data.split(",")
            if parts[2] == "V":
                print("GPS receiver warning")
            else:
                longitude = float(formatDegreesMinutes(parts[5], 3))
                latitude = float(formatDegreesMinutes(parts[3], 2))
                print("Your position: lon = " + str(longitude) + ", lat = " + str(latitude))
Example #34
0
class Motor:
    def __init__(self, ain1=None, ain2=None, bin1=None, bin2=None, pwma=None, pwmb=None):
        print("init")
        self.ain1 = DigitalOutputDevice(ain1, initial_value=False)
        self.ain2 = DigitalOutputDevice(ain2, initial_value=False)
        self.bin1 = DigitalOutputDevice(bin1, initial_value=False)
        self.bin2 = DigitalOutputDevice(bin2, initial_value=False)
        self.pwma = PWMOutputDevice(pwma, initial_value=.5)
        self.pwmb = PWMOutputDevice(pwmb, initial_value=.5)

    def stop(self):
        print("stop")
        self.ain1.off()
        self.ain2.off()
        self.bin1.off()
        self.bin2.off()

    def forward():
        print("forward")
        self.ain1.on()
        self.ain2.off()
        self.bin1.on()
        self.bin2.off()

    def backward():
        print("backward")
        self.ain1.off()
        self.ain2.on()
        self.bin1.off()
        self.bin2.on()

    def turn_left():
        print("turn_left")
        self.ain1.off()
        self.ain2.on()
        self.bin1.on()
        self.bin2.off()

    def turn_right():
        print("turn_right")
        self.ain1.on()
        self.ain2.off()
        self.bin1.off()
        self.bin2.on()