Better folder structure, added a few ambient sensors
This commit is contained in:
		
							
								
								
									
										2
									
								
								clock/hardware/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								clock/hardware/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| # Placeholder | ||||
| from . import led, sensors | ||||
							
								
								
									
										17
									
								
								clock/hardware/led.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								clock/hardware/led.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| from . import unicorn as led | ||||
| # or neopixel soon: | ||||
| # from . import neopixel as led | ||||
|  | ||||
| def get_handler(): | ||||
|     OUT = led.ClockOut() | ||||
|     shape = OUT.shape | ||||
|  | ||||
|     if led.SETUP_FAIL: | ||||
|         # we use the sim | ||||
|         del OUT | ||||
|         from . import sim | ||||
|         OUT = sim.ClockOut(shape) | ||||
|  | ||||
|     return OUT | ||||
|  | ||||
|  | ||||
							
								
								
									
										51
									
								
								clock/hardware/neopixel.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								clock/hardware/neopixel.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| import time | ||||
| import numpy as np | ||||
| import colorsys | ||||
| import random | ||||
|  | ||||
| try: | ||||
|     import rpi_ws281x as ws | ||||
| except ImportError: | ||||
|     from unittest.mock import Mock | ||||
|     ws = Mock() | ||||
|     SETUP_FAIL = True | ||||
|  | ||||
|  | ||||
| class ClockOut: | ||||
|     def __init__(self): | ||||
|         self.shape = (45, 20) # H x W | ||||
|         num = self.shape[0] * self.shape[1] | ||||
|         pin = 18  | ||||
|         freq = 800000 # maybe higher | ||||
|         dma = 5 | ||||
|         invert = False | ||||
|         brightness = 100 | ||||
|         channel = 0 | ||||
|         led_type = None # ?? | ||||
|         self.strip = ws.PixelStrip(num, pin, freq, dma, invert, brightness, channel, led_type) | ||||
|         self.strip.begin() | ||||
|      | ||||
|  | ||||
|     def put(self, matrix): | ||||
|         self.render(matrix) | ||||
|  | ||||
|  | ||||
|     def render(self, matrix): | ||||
|         p = 0 | ||||
|         for i in range(matrix.shape[0]): | ||||
|             for j in range(matrix.shape[1]): | ||||
|                 col = int(ws.Color(*matrix[i,j])) | ||||
|  | ||||
|                 self.strip.setPixelColor(p, col) | ||||
|                 p += 1 | ||||
|         self.strip.show() | ||||
|  | ||||
|  | ||||
| # test = ClockOut() | ||||
| # z = np.zeros((30,30, 3), dtype=int) | ||||
| # for i in range(30): | ||||
| #     for j in range(30): | ||||
| #         z[i, j, ...] = [random.randint(0,255), random.randint(0,255), random.randint(0,255)] | ||||
| #         test.put(z) | ||||
| #         #time.sleep(0.1) | ||||
|  | ||||
							
								
								
									
										80
									
								
								clock/hardware/sensors.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								clock/hardware/sensors.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| import time | ||||
| import logging | ||||
| logger = logging.getLogger(__name__) | ||||
|  | ||||
| class TempSim: | ||||
|     """Simulates a temperature for running on windows""" | ||||
|     temperature = 23 # return a celsius value | ||||
|     humidity = 0.3 | ||||
|  | ||||
|  | ||||
| class SensorModule: | ||||
|     def __init__(self): | ||||
|         logger.info("Using module " + self.__class__.__name__) | ||||
|      | ||||
| class LightSim: | ||||
|     def input(self, *args): | ||||
|         return 1 | ||||
|  | ||||
| try: | ||||
|     import board | ||||
|     import adafruit_dht  | ||||
|     dht11 = adafruit_dht.DHT11(board.D18) | ||||
|     import RPi.GPIO as GPIO | ||||
|     GPIO.setmode(GPIO.BCM) | ||||
|     GPIO.setup(4, GPIO.IN) | ||||
| except ImportError: | ||||
|     dht11 = TempSim() | ||||
|     GPIO = LightSim() | ||||
|  | ||||
|  | ||||
| class TemperatureModule(SensorModule): | ||||
|     """Takes readouts from the DHT 11 | ||||
|     Returns: temperature""" | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.device = dht11 | ||||
|          | ||||
|     def readout(self): | ||||
|         try: | ||||
|             temp = self.device.temperature | ||||
|         except: | ||||
|             time.sleep(1) | ||||
|             try: | ||||
|                 temp = self.device.temperature | ||||
|             except: | ||||
|                 temp = -1 | ||||
|          | ||||
|         return temp | ||||
|                          | ||||
| class HumidityModule(SensorModule): | ||||
|     """Takes readouts from the DHT 11 | ||||
|     Returns: humidity""" | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.device = self.device = dht11 | ||||
|          | ||||
|     def readout(self): | ||||
|         try: | ||||
|             hum = self.device.humidity | ||||
|         except: | ||||
|             time.sleep(1) | ||||
|             try: | ||||
|                 hum = self.device.humidity | ||||
|             except: | ||||
|                 hum = -1 | ||||
|          | ||||
|         return hum | ||||
|  | ||||
| class BrightnessModule(SensorModule): | ||||
|     """Returns one for HIGH and zero for LOW""" | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|  | ||||
|     def readout(self): | ||||
|         # The sensor is reversed: 0 when bright and 1 if dark | ||||
|         light = GPIO.input(4) | ||||
|         if light == 0: | ||||
|             return 1 | ||||
|         else: | ||||
|             return 0 | ||||
							
								
								
									
										52
									
								
								clock/hardware/sim.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								clock/hardware/sim.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| import sys | ||||
| import colorsys | ||||
| import pygame.gfxdraw | ||||
| import time | ||||
| import pygame | ||||
| import numpy | ||||
|  | ||||
| class ClockOut: | ||||
|     """Creates a drawable window in case the real hardware is not accessible. For development""" | ||||
|     def __init__(self, shape): | ||||
|         self.pixel_size = 20 | ||||
|  | ||||
|         self.shape = shape | ||||
|         self.pixels = numpy.zeros((*shape,3), dtype=int) | ||||
|         self.WIDTH = shape[1] | ||||
|         self.HEIGHT = shape[0] | ||||
|         self.window_width = self.WIDTH * self.pixel_size | ||||
|         self.window_height = self.HEIGHT * self.pixel_size | ||||
|  | ||||
|         pygame.init() | ||||
|         pygame.display.set_caption("Unicorn HAT simulator") | ||||
|         self.screen = pygame.display.set_mode([self.window_width, self.window_height]) | ||||
|  | ||||
|  | ||||
|     def put(self, matrix): | ||||
|         self.screen.fill((0, 0, 0)) | ||||
|         for event in pygame.event.get(): # User did something | ||||
|             if event.type == pygame.QUIT: | ||||
|                 print("Exiting...") | ||||
|                 pygame.quit() | ||||
|                 sys.exit() | ||||
|         self.pixels = matrix | ||||
|         self.draw_pixels() | ||||
|          | ||||
|         pygame.display.flip() | ||||
|         pygame.event.pump() | ||||
|  | ||||
|  | ||||
|     def draw_pixels(self): | ||||
|         p = self.pixel_size | ||||
|          | ||||
|         r = int(p / 4) | ||||
|         for i in range(self.HEIGHT): | ||||
|             for j in range(self.WIDTH): | ||||
|                 w_x = int(j * p + p / 2) | ||||
|                 #w_y = int((self.HEIGHT - 1 - y) * p + p / 2) | ||||
|                 w_y = int(i * p + p / 2) | ||||
|                 color = self.pixels[i,j,:] | ||||
|                 color = color.astype("int") | ||||
|  | ||||
|                 pygame.gfxdraw.aacircle(self.screen, w_x, w_y, r, color) | ||||
|                 pygame.gfxdraw.filled_circle(self.screen, w_x, w_y, r, color) | ||||
							
								
								
									
										94
									
								
								clock/hardware/unicorn.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								clock/hardware/unicorn.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| import colorsys | ||||
| import time | ||||
| import numpy | ||||
| try: | ||||
|     import RPi.GPIO as GPIO | ||||
| except ImportError: | ||||
|     from unittest.mock import Mock | ||||
|     GPIO = Mock() | ||||
|     SETUP_FAIL = True | ||||
|  | ||||
|  | ||||
| class ClockOut: | ||||
|     def __init__(self): | ||||
|         self.PIN_CLK = 11 | ||||
|         ################################## | ||||
|         # Hardcoded vaules: | ||||
|         # GPIO Pins for the actual signal. The other ones are for signal clocks and resets. | ||||
|         self.PINS_DAT = [10, 22] | ||||
|         self.PIN_CS = 8 | ||||
|         # for data transmission | ||||
|         self.SOF = 0x72 | ||||
|         self.DELAY = 1.0/120 | ||||
|         # shape of 2 unicorn hats | ||||
|         self.shape = (16, 32) | ||||
|         ################################## | ||||
|          | ||||
|         GPIO.setmode(GPIO.BCM) | ||||
|         GPIO.setwarnings(False) | ||||
|         GPIO.setup(self.PIN_CS, GPIO.OUT, initial=GPIO.HIGH) | ||||
|         GPIO.setup(self.PIN_CLK, GPIO.OUT, initial=GPIO.LOW) | ||||
|         GPIO.setup(self.PINS_DAT, GPIO.OUT, initial=GPIO.LOW) | ||||
|          | ||||
|         self.HEIGHT = self.shape[0] #16 | ||||
|         self.WIDTH = self.shape[1] #32 | ||||
|  | ||||
|         self.reset_clock() | ||||
|  | ||||
|  | ||||
|     def reset_clock(self): | ||||
|         GPIO.output(self.PIN_CS, GPIO.LOW) | ||||
|         time.sleep(0.00001) | ||||
|         GPIO.output(self.PIN_CS, GPIO.HIGH) | ||||
|  | ||||
|  | ||||
|     def spi_write(self, buf1, buf2): | ||||
|         GPIO.output(self.PIN_CS, GPIO.LOW) | ||||
|  | ||||
|         self.spi_write_byte(self.SOF, self.SOF) | ||||
|  | ||||
|         for x in range(len(buf1)): | ||||
|             b1, b2= buf1[x], buf2[x] | ||||
|             self.spi_write_byte(b1, b2) | ||||
|  | ||||
|  | ||||
|         GPIO.output(self.PIN_CS, GPIO.HIGH) | ||||
|  | ||||
|  | ||||
|     def spi_write_byte(self, b1, b2): | ||||
|         for x in range(8): | ||||
|             GPIO.output(self.PINS_DAT[0], b1 & 0b10000000) | ||||
|             GPIO.output(self.PINS_DAT[1], b2 & 0b10000000) | ||||
|             GPIO.output(self.PIN_CLK, GPIO.HIGH) | ||||
|  | ||||
|             b1 <<= 1 | ||||
|             b2 <<= 1 | ||||
|             #time.sleep(0.00000001) | ||||
|             GPIO.output(self.PIN_CLK, GPIO.LOW) | ||||
|  | ||||
|  | ||||
|     def put(self, matrix): | ||||
|         """Sets a height x width matrix directly""" | ||||
|         self.reset_clock() | ||||
|         self.show(matrix) | ||||
|  | ||||
|  | ||||
|     def clear(self): | ||||
|         """Clear the buffer.""" | ||||
|         zero = np.zero((self.HEIGHT, self. WIDTH)) | ||||
|         self.put(zero) | ||||
|  | ||||
|  | ||||
|     def show(self, matrix): | ||||
|         """Output the contents of the buffer to Unicorn HAT HD.""" | ||||
|         ########################################################## | ||||
|         ## Change to desire | ||||
|         buff2 = numpy.rot90(matrix[:self.HEIGHT,:16],3) | ||||
|         buff1 = numpy.rot90(matrix[:self.HEIGHT,16:32],1) | ||||
|         ########################################################## | ||||
|         # separated these are: 16x16x3 arrays | ||||
|         buff1, buff2 = [(x.reshape(768)).astype(numpy.uint8).tolist() for x in (buff1, buff2)] | ||||
|  | ||||
|         self.spi_write(buff1, buff2) | ||||
|  | ||||
|         time.sleep(self.DELAY) | ||||
		Reference in New Issue
	
	Block a user
	 Remy Moll
					Remy Moll