Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions python/evolutek/lib/indicators/ws2812b.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,12 @@ def set_mode(self, mode=LightningMode.Loading):

self.mode = mode

self.leds.fill(Color.Black.value)
self.leds.fill(Color.Black.value.to_tupple())

if self.mode == LightningMode.Loading:
self.current_led = self.nb_leds - 1
for i in range(NB_LOADING_LED):
self.leds[i] = self.loading_color.value
self.leds[i] = self.loading_color.value.to_tupple()

elif self.mode == LightningMode.Disabled or self.mode == LightningMode.Error:
self.state = False
Expand All @@ -79,25 +79,25 @@ def run(self):
with self.lock:
if self.mode == LightningMode.Disabled:
for i in range(self.nb_leds):
self.leds[i] = Color.Orange.value if self.state ^ i % 2 == 0 else Color.Black.value
self.leds[i] = Color.Orange.value.to_tupple() if self.state ^ i % 2 == 0 else Color.Black.value.to_tupple()
self.state = not self.state

elif self.mode == LightningMode.Error:
self.leds.fill(Color.Red.value if self.state else Color.Black.value)
self.leds.fill(Color.Red.value.to_tupple() if self.state else Color.Black.value.to_tupple())
self.state = not self.state

elif self.mode == LightningMode.Loading:
self.leds[self.current_led] = Color.Black.value
self.leds[(self.current_led + NB_LOADING_LED) % self.nb_leds] = self.loading_color.value
self.leds[self.current_led] = Color.Black.value.to_tupple()
self.leds[(self.current_led + NB_LOADING_LED) % self.nb_leds] = self.loading_color.value.to_tupple()
self.current_led = (self.current_led + 1) % self.nb_leds

elif self.mode == LightningMode.Running:
self.leds.fill(Color.Green.value)
self.leds.fill(Color.Green.value.to_tupple())

self.leds.show()

sleep(refresh[self.mode])

self.leds.fill(Color.Black.value)
self.leds.fill(Color.Black.value.to_tupple())
self.leds.show()
print(f"[{self.name}] Stopped")
48 changes: 16 additions & 32 deletions python/evolutek/lib/sensors/rgb_sensors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,23 @@
import adafruit_tcs34725
import board
import busio
import time

from enum import Enum
from time import sleep

from evolutek.lib.component import Component, ComponentsHolder
from evolutek.lib.utils.color import Color
from evolutek.lib.utils.color import RGBColor, Color

TCA = None
CALIBRATE = 10

# Up -> More perturbations (more false positives)
# Down -> Better detection (more false negatives)
SENSITIVITY = 1.25
CALIBRATION_NB_VALUES = 10
DELTA_FOR_COLOR = 50

class TCS34725(Component):

def __init__(self, id, channel):
self.calibration = [0, 0, 0]
def __init__(self, id, channel, color_to_detect=None):
self.calibration = RGBColor(0, 0, 0)
self.sensor = None
self.channel = channel
self.color_to_detect = color_to_detect
super().__init__('TCS34725', id)

def _initialize(self):
Expand All @@ -38,32 +34,20 @@ def _initialize(self):
return True

def calibrate(self):
for i in range(CALIBRATE):
rgb = self.sensor.color_rgb_bytes
self.calibration[0] += rgb[0]
self.calibration[1] += rgb[1]
self.calibration[2] += rgb[2]
calibration = []
for i in range(CALIBRATION_NB_VALUES):
calibration.append(RGBColor.from_tupple(self.sensor.color_rgb_bytes))
sleep(0.1)
self.calibration[0] /= CALIBRATE
self.calibration[1] /= CALIBRATE
self.calibration[2] /= CALIBRATE
# print('Setup: R = %i - G = %i - B = %i' % (self.calibration[0],self.calibration[1],self.calibration[2]))
self.calibration = RGBColor.mean(calibration)
print(f"[{self.name}] Sensor {self.id} calibrated with {self.calibration}")

def read(self):
if not self.is_initialized:
print('[%s] %s %d not initialized' % (self.name, self.name, self.id))
return None

rgb = self.sensor.color_rgb_bytes
values = [rgb[0] - self.calibration[0], rgb[1] - self.calibration[1], rgb[2] - self.calibration[2]]
index = values.index(max(values))

if rgb[index] < self.calibration[index] * SENSITIVITY:
return Color.Unknown
rgb = RGBColor.from_tupple(self.sensor.color_rgb_bytes)
rgb -= self.calibration
color = Color.get_closest_color(rgb, self.color_to_detect if self.color_to_detect is not None else Color.__members__.values())

res = [Color.Red, Color.Green, Color.Blue][index]
if res == Color.Blue: return Color.Green
return res
print(f"[{self.name}] Sensor {self.id} detect color {color.name} with {color.value}")
return color

def __str__(self):
s = "----------\n"
Expand Down
115 changes: 105 additions & 10 deletions python/evolutek/lib/utils/color.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,115 @@
from enum import Enum
from math import sqrt

class RGBColor:

def __init__(self, r, g, b):
self.r = r
self.g = g
self.b = b

@staticmethod
def from_tupple(t):
return RGBColor(t[0], t[1], t[2])

def to_tupple(self):
return (self.r, self.g, self.b)

def __str__(self) -> str:
return f"(R, G, B): ({self.r}, {self.g}, {self.b})"

def __eq__(self, color) -> bool:
return (
self.r == color.r and
self.g == color.g and
self.b == color.b
)

def __add__(self, color):
return RGBColor(
self.r + color.r,
self.g + color.g,
self.b + color.b
)

def __sub__(self, color):
return RGBColor(
self.r - color.r,
self.g - color.g,
self.b - color.b
)

def __div__(self, div: int):
return RGBColor(
self.r / div,
self.g / div,
self.b / div
)

def __mul__(self, coef: float):
if coef < 0.0 or coef > 1.0:
return Color.Black.value

return RGBColor(self.r * coef, self.g * coef, self.b * coef)

def get_rgb_percentages(self):
sum = self.r + self.g + self.b
if sum == 0:
return (0, 0, 0)
return (self.r / sum, self.g / sum, self.b / sum)

@staticmethod
def mean(colors):
result = RGBColor(0, 0, 0)
for color in colors:
result += color
return result.__div__(len(colors))

@staticmethod
def compute_dist(a, b):
percentages_a = a.get_rgb_percentages()
percentages_b = b.get_rgb_percentages()

return ((
abs(percentages_a[0] - percentages_b[0]) +
abs(percentages_a[1] - percentages_b[1]) +
abs(percentages_a[2] - percentages_b[2])
) / 3)

class Color(Enum):
Black = (0, 0, 0)
Blue = (0, 0, 255)
Brown = (76, 43, 32)
Green = (0, 255, 0)
Orange = (255, 50, 0)
Purple = (115, 25, 115)
Red = (255, 0, 0)
Pink = (188, 64, 119)
Yellow = (247, 181, 0)
Unknown = (-1, -1, -1)
Black = RGBColor(0, 0, 0)
Blue = RGBColor(0, 0, 255)
Brown = RGBColor(76, 43, 32)
Green = RGBColor(0, 255, 0)
Orange = RGBColor(255, 50, 0)
Pink = RGBColor(188, 64, 119)
Purple = RGBColor(115, 25, 115)
Red = RGBColor(255, 0, 0)
Yellow = RGBColor(247, 181, 0)
Unknown = RGBColor(-1, -1, -1)

@staticmethod
def get_by_name(name):
try:
return Color.__members__[name.capitalize()]
except:
return Color.Unknown

@staticmethod
def get_by_rgb(rgb_color):
for color in Color.__members__.values():
if rgb_color == color.value:
return color
return Color.Unknown

@staticmethod
def get_closest_color(rgb_color, colors):
closest = None
min_dist = None
for color in colors:
dist = RGBColor.compute_dist(rgb_color, color.value)
if min_dist is None or dist < min_dist:
min_dist = dist
closest = color
return closest

3 changes: 1 addition & 2 deletions python/evolutek/tests/sensors/test_rgb_sensors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

from evolutek.lib.sensors.rgb_sensors import RGBSensors

rgb_sensors = RGBSensors([1, 2, 3, 4])
print(rgb_sensors.is_initialized())
rgb_sensors = RGBSensors([1])
print(rgb_sensors)

for sensor in rgb_sensors:
Expand Down