033 - MicroPython TechNotes: TCS34725 RGB Color Sensor
Introduction
In this article, we will learn how to use the TCS34725 RGB Color Sensor with ESP32 using MicroPython programming language.
Bill Of Materials
- ESP32 development board.
- Gorillacell ESP32 shield.
- 4-pin female-female dupont wires.
- TCS34725 RGB color sensor module.
Pinout
- GND – for the ground pin.
- VCC – for the supply voltage.
- SDA – for the I2C serial data pin.
- SCL – for the I2C serial clock pin.
Hardware Instruction
- First, attach the ESP32 board on top of the ESP32 shield and make sure that both USB ports are on the same side.
- Next, attach the dupont wires to the RGB Color Sensor by following the color coding which is black for the ground, red for the VCC, yellow for the SDA pin, and white for the SCL pin.
- Next, attach the other end of the dupont wires to the ESP32 shield by matching the colors of the wires to the colors of the pin headers such as black to black, red to red, and yellow and the following colors to yellow pin headers. For this experiment, I choose GPIO 21 for the SDA pin and GPIO 22 for the SCL pin.
- Next, power the ESP32 shield with an external power supply with a type-C USB connector and make sure that the power switch is set to ON state.
- Lastly, connect the ESP32 to the computer.
Software Instruction
- Copy the tcs34725.py below and paste it to Thonny IDE and save it to ESP32 MicroPython root directory by clicking the File menu and select Save As. Click the MicroPython Device and save it as tcs34725.py.
- Copy the example source codes and play with it.
Video Demonstration
Call To Action
For any concern, write your message in the comment section.
You might also like to support my journey on Youtube by Subscribing. Click this to Subscribe to TechToTinker.
Thank you and have a good days ahead.
See you,
– George Bantique | tech.to.tinker@gmail.com
Source Code
Example # 1, exploring the basics of TCS34725 RGB Color Sensor:
1# More details can be found in TechToTinker.blogspot.com
2# George Bantique | tech.to.tinker@gmail.com
3
4from machine import Pin
5from machine import I2C
6from tcs34725 import TCS34725
7from time import sleep_ms
8
9i2c_bus = I2C(0, sda=Pin(21), scl=Pin(22))
10tcs = TCS34725(i2c_bus)
11
12# # The following lines of code should be tested in the REPL:
13# #
14# # 1. To print the raw data:
15# print('raw: {}'.format(tcs.read('raw')))
16# #
17# # 2. To print the RGB data:
18# print('rgb: {}'.format(tcs.read('rgb')))
19# #
20# # 3. To print the RGB data in decimal form:
21# print('dec: {}'.format(tcs.read('dec')))
22# #
23# # 4. To print the RGB data in hex form:
24# print('hex: {}'.format(tcs.read('hex')))
25# #
26# # 5. To print the color temperature in ^Kelvin and
27# # the luminosity in lux
28# print('lux: {}'.format(tcs.read('lux')))
py
Example # 2, simple application of TCS34725:
1# More details can be found in TechToTinker.blogspot.com
2# George Bantique | tech.to.tinker@gmail.com
3
4from machine import Pin
5from machine import I2C
6from machine import PWM
7from time import sleep_ms
8from tcs34725 import TCS34725
9from gorillacell_rgb import GORILLACELL_RGB
10
11i2c_bus = I2C(0, sda=Pin(21), scl=Pin(22))
12tcs = TCS34725(i2c_bus)
13rgb = GORILLACELL_RGB(25, 26, 27)
14
15while True:
16 red, grn, blu = tcs.read('dec')
17 rgb.set_rgb(red, grn, blu)
py
3. tcs34725.py modified driver library for TCS34725:
1import time
2 import ustruct
3 #const = lambda x:x
4 _COMMAND_BIT = const(0x80)
5 _REGISTER_ENABLE = const(0x00)
6 _REGISTER_ATIME = const(0x01)
7 _REGISTER_AILT = const(0x04)
8 _REGISTER_AIHT = const(0x06)
9 _REGISTER_ID = const(0x12)
10 _REGISTER_APERS = const(0x0c)
11 _REGISTER_CONTROL = const(0x0f)
12 _REGISTER_SENSORID = const(0x12)
13 _REGISTER_STATUS = const(0x13)
14 _REGISTER_CDATA = const(0x14)
15 _REGISTER_RDATA = const(0x16)
16 _REGISTER_GDATA = const(0x18)
17 _REGISTER_BDATA = const(0x1a)
18 _ENABLE_AIEN = const(0x10)
19 _ENABLE_WEN = const(0x08)
20 _ENABLE_AEN = const(0x02)
21 _ENABLE_PON = const(0x01)
22 _GAINS = (1, 4, 16, 60)
23 _CYCLES = (0, 1, 2, 3, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60)
24 class TCS34725:
25 def __init__(self, i2c, address=0x29):
26 self.i2c = i2c
27 self.address = address
28 self._active = False
29 self.integration_time(2.4)
30 sensor_id = self.sensor_id()
31 if sensor_id not in (0x44, 0x10):
32 raise RuntimeError("wrong sensor id 0x{:x}".format(sensor_id))
33 def _register8(self, register, value=None):
34 register |= _COMMAND_BIT
35 if value is None:
36 return self.i2c.readfrom_mem(self.address, register, 1)[0]
37 data = ustruct.pack('<B', value)
38 self.i2c.writeto_mem(self.address, register, data)
39 def _register16(self, register, value=None):
40 register |= _COMMAND_BIT
41 if value is None:
42 data = self.i2c.readfrom_mem(self.address, register, 2)
43 return ustruct.unpack('<H', data)[0]
44 data = ustruct.pack('<H', value)
45 self.i2c.writeto_mem(self.address, register, data)
46 def active(self, value=None):
47 if value is None:
48 return self._active
49 value = bool(value)
50 if self._active == value:
51 return
52 self._active = value
53 enable = self._register8(_REGISTER_ENABLE)
54 if value:
55 self._register8(_REGISTER_ENABLE, enable | _ENABLE_PON)
56 time.sleep_ms(3)
57 self._register8(_REGISTER_ENABLE,
58 enable | _ENABLE_PON | _ENABLE_AEN)
59 else:
60 self._register8(_REGISTER_ENABLE,
61 enable & ~(_ENABLE_PON | _ENABLE_AEN))
62 def sensor_id(self):
63 return self._register8(_REGISTER_SENSORID)
64 def integration_time(self, value=None):
65 if value is None:
66 return self._integration_time
67 value = min(614.4, max(2.4, value))
68 cycles = int(value / 2.4)
69 self._integration_time = cycles * 2.4
70 return self._register8(_REGISTER_ATIME, 256 - cycles)
71 def gain(self, value):
72 if value is None:
73 return _GAINS[self._register8(_REGISTER_CONTROL)]
74 if value not in _GAINS:
75 raise ValueError("gain must be 1, 4, 16 or 60")
76 return self._register8(_REGISTER_CONTROL, _GAINS.index(value))
77 def _valid(self):
78 return bool(self._register8(_REGISTER_STATUS) & 0x01)
79 def read(self, raw=False):
80 was_active = self.active()
81 self.active(True)
82 while not self._valid():
83 time.sleep_ms(int(self._integration_time + 0.9))
84 data = tuple(self._register16(register) for register in (
85 _REGISTER_RDATA,
86 _REGISTER_GDATA,
87 _REGISTER_BDATA,
88 _REGISTER_CDATA,
89 ))
90 self.active(was_active)
91 if raw:
92 return data
93 return self._temperature_and_lux(data)
94 def _temperature_and_lux(self, data):
95 r, g, b, c = data
96 x = -0.14282 * r + 1.54924 * g + -0.95641 * b
97 y = -0.32466 * r + 1.57837 * g + -0.73191 * b
98 z = -0.68202 * r + 0.77073 * g + 0.56332 * b
99 d = x + y + z
100 n = (x / d - 0.3320) / (0.1858 - y / d)
101 cct = 449.0 * n**3 + 3525.0 * n**2 + 6823.3 * n + 5520.33
102 return cct, y
103 def threshold(self, cycles=None, min_value=None, max_value=None):
104 if cycles is None and min_value is None and max_value is None:
105 min_value = self._register16(_REGISTER_AILT)
106 max_value = self._register16(_REGISTER_AILT)
107 if self._register8(_REGISTER_ENABLE) & _ENABLE_AIEN:
108 cycles = _CYCLES[self._register8(_REGISTER_APERS) & 0x0f]
109 else:
110 cycles = -1
111 return cycles, min_value, max_value
112 if min_value is not None:
113 self._register16(_REGISTER_AILT, min_value)
114 if max_value is not None:
115 self._register16(_REGISTER_AIHT, max_value)
116 if cycles is not None:
117 enable = self._register8(_REGISTER_ENABLE)
118 if cycles == -1:
119 self._register8(_REGISTER_ENABLE, enable & ~(_ENABLE_AIEN))
120 else:
121 self._register8(_REGISTER_ENABLE, enable | _ENABLE_AIEN)
122 if cycles not in _CYCLES:
123 raise ValueError("invalid persistence cycles")
124 self._register8(_REGISTER_APERS, _CYCLES.index(cycles))
125 def interrupt(self, value=None):
126 if value is None:
127 return bool(self._register8(_REGISTER_STATUS) & _ENABLE_AIEN)
128 if value:
129 raise ValueError("interrupt can only be cleared")
130 self.i2c.writeto(self.address, b'xe6')
131 def html_rgb(data):
132 r, g, b, c = data
133 red = pow((int((r/c) * 256) / 255), 2.5) * 255
134 green = pow((int((g/c) * 256) / 255), 2.5) * 255
135 blue = pow((int((b/c) * 256) / 255), 2.5) * 255
136 return red, green, blue
137 def html_hex(data):
138 r, g, b = html_rgb(data)
139 return "{0:02x}{1:02x}{2:02x}".format(int(r),
140 int(g),
141 int(b))
py
4. gorillacell_rgb driver library for the RGB LED:
1# This is a class helper for the RGB module
2# George Bantique | tech.to.tinker@gmail.com
3
4from machine import Pin
5from machine import PWM
6
7class GORILLACELL_RGB:
8 def __init__(self, r_pin, g_pin, b_pin):
9 self.r = PWM(Pin(r_pin))
10 self.g = PWM(Pin(g_pin))
11 self.b = PWM(Pin(b_pin))
12
13 # Initialize the PWM frequency to 60Hz
14 self.r.freq(60)
15 self.g.freq(60)
16 self.b.freq(60)
17 # and Initialize with pulse turned OFF
18 self.r.duty(0)
19 self.g.duty(0)
20 self.b.duty(0)
21
22 def map(self, x, in_min, in_max, out_min, out_max):
23 # This will not handle x value greater than in_max or
24 # x value less than in_min
25 return int((x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min)
26 def set_rgb(self, x, y, z):
27 # Maximum duty cycle is 1023
28 # RGB values is usually 0 to 255
29 # By using ratio and proportion
30 self.r.duty(self.map(x, 0, 255, 0, 1023))
31 self.g.duty(self.map(y, 0, 255, 0, 1023))
32 self.b.duty(self.map(z, 0, 255, 0, 1023))
33
34 def rst_rgb(self):
35 # Turn off all pwm pulse
36 self.r.duty(0)
37 self.g.duty(0)
38 self.b.duty(0)
py
References And Credits
-
Purchase your Gorillacell ESP32 development kit at: https://gorillacell.kr
-
TCS34725 Driver Library: https://github.com/adafruit/micropython-adafruit-tcs34725
Posts in this series
- 049 - MicroPython TechNotes: MP3 Player
- 048 - MicroPython TechNotes: Analog Touch Sensor
- 047 - MicroPython TechNotes: E108 GPS
- 046 - MicroPython TechNotes: RF433 Transceivers
- 045 - MicroPython TechNotes: Infrared Transmitter
- 044 - MicroPython TechNotes: Infrared Receiver
- 043 - MicroPython TechNotes: ESP12E WiFi | External WiFi module
- 042 - MicroPython TechNotes: JDY-32 | Bluetooth Low Energy BLE
- 041 - MicroPython TechNotes: Bluetooth HC-06
- 040 - MicroPython TechNotes: Relay
- 039 - MicroPython TechNotes: Electromagnet
- 038 - MicroPython TechNotes: Buzzer
- 037 - MicroPython TechNotes: Servo Motor
- 036 - MicroPython TechNotes: Stepper Motor
- 035 - MicroPython TechNotes: Dual Motor Driver
- 034 - MicroPython TechNotes: DC Motors | Gear Motor and Fan Motor
- 032 - MicroPython TechNotes: BMP280 Sensor
- 031 - MicroPython TechNotes: TOF Distance Sensor
- 030 - MicroPython TechNotes: DS3231 RTC
- 029 - MicroPython TechNotes: HC-SR04 Ultrasonic Sensor
- 028 - MicroPython TechNotes: DHT11 Temperature and Humidity Sensor
- 027 - MicroPython TechNotes: Rotary Encoder
- 026 - MicroPython TechNotes: Light Dependent Resistor (LDR)
- 025 - MicroPython TechNotes: Joystick
- 024 - MicroPython TechNotes: Slider Switch
- 023 - MicroPython TechNotes: Continuous Rotation Potentiometer
- 022 - MicroPython TechNotes: Potentiometer | Reading an Analog Input
- 021 - MicroPython TechNotes: Color Touch Sensor
- 020 - MicroPython TechNotes: Touch Sensor
- 019 - MicroPython TechNotes: Switch Module
- 018 - MicroPython TechNotes: Button | Reading an Input
- 017 - MicroPython TechNotes: LASER Module
- 016 - MicroPython TechNotes: RGB LED Matrix
- 015 - MicroPython TechNotes: Neopixel 16
- 014 - MicroPython TechNotes: 8x8 Dot Matrix Display (I2C)
- 013 - MicroPython TechNotes: 8x16 Dot Matrix Display (SPI)
- 012 - MicroPython TechNotes: 8x8 Dot Matrix Display (SPI)
- 011 - MicroPython TechNotes: 1.3 OLED Display
- 010 - MicroPython TechNotes: 0.96 OLED Display
- 009 - MicroPython TechNotes: 7 Segment Display
- 008 - MicroPython TechNotes: 16x2 LCD
- 007 - MicroPython TechNotes: RGB LED
- 006 - MicroPython TechNotes: Traffic Light LED Module
- 005 - MicroPython TechNotes: Gorilla Cell LED | MicroPython Hello World
- 004 - MicroPython TechNotes: Gorilla Cell I/O Devices
- 003 - MicroPython TechNotes: Gorillacell ESP32 Shield
- 002 - MicroPython TechNotes: Introduction for Gorillacell ESP32 Dev Kit
- 001 - MicroPython TechNotes: Get Started with MicroPython
- 000 - MicroPython TechNotes: Unboxing Gorillacell ESP32 Development Kit
No comments yet!