Skip to content

Commit

Permalink
Update rgb sensors
Browse files Browse the repository at this point in the history
  • Loading branch information
kmikaz51 committed Apr 12, 2023
1 parent 03ce522 commit fd05f08
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 47 deletions.
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")
52 changes: 22 additions & 30 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,28 @@ 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 = 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__)

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 color == Color.Unknown:
print(f"[{self.name}] Sensor {self.id} didn't see any color")

if rgb[index] < self.calibration[index] * SENSITIVITY:
return Color.Unknown
dist = rgb.compute_dist(color.value)
if dist >= DELTA_FOR_COLOR:
print(f"[{self.name}] Sensor {self.id} detect a bad color (dist={dist})")


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 with {color.value} with dist {dist}")
return color

def __str__(self):
s = "----------\n"
Expand Down
99 changes: 91 additions & 8 deletions python/evolutek/lib/utils/color.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,101 @@
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(r, g, b)

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)

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

def compute_dist(self, color):
tmp = self.__sub__(color)
return sqrt(
tmp.r ** 2 + tmp.g **2 + tmp.b **2
)

class Color(Enum):
Black = (0, 0, 0)
Blue = (0, 0, 255)
Green = (0, 255, 0)
Orange = (255, 50, 0)
Red = (255, 0, 0)
Yellow = (255, 255, 0)
Purple = (115, 25, 115)
Unknown = (-1, -1, -1)
Black = RGBColor(0, 0, 0)
Blue = RGBColor(0, 0, 255)
Green = RGBColor(0, 255, 0)
Orange = RGBColor(255, 50, 0)
Red = RGBColor(255, 0, 0)
Yellow = RGBColor(255, 255, 0)
Purple = RGBColor(115, 25, 115)
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__:
if rgb_color == color.value:
return color
return Color.Unknown

@staticmethod
def get_closest_color(rgb_color, colors):
closest = Color.Unknow
min_dist = rgb_color.compute_dist(Color.Unknow.value)
for color in colors:
dist = rgb_color.compute_dist(color.value)
if dist < min_dist:
min_dist = dist
closest = color
return closest
2 changes: 1 addition & 1 deletion python/evolutek/tests/sensors/test_rgb_sensors.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from evolutek.lib.sensors.rgb_sensors import RGBSensors

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

Expand Down

0 comments on commit fd05f08

Please sign in to comment.