_measure something: add a sensor to a microcontroller board that you’ve designed and read it
For this activity, I will try to design a sensor for my final project, the bacteria artefact.
The first step we made in our laboratory, we seek the largest possible number of sensors, in the picture below I share the sensors we have now:
1- Height Sensor/Pressure – MPL3115A2
2 – Accelerometer, three Axis – MMA8452Q
3 – Humidity Sensor HTU21D
4 – IR Receiver
5 – Magnetometer, three Axis – HMC5883L
6 – Gyroscope with digital outputs, three axes ITG-3200
7 – Ultrasonic Rangefinder – Maxbotix LV-EZ1
8 – PIR Motion Sensor
9 – Large Piezo Vibration Sensor
10, Reed Switch
11- Imam Square 0.25 ”
12 – Resistance Force-sensitive 0.5 ”
13 – SoftPot
14 – Cell Fotoeléctricia
15 – Optical Detector / Phototransistor
16 – Flexible Sensor
17 – Sound Sensor
18 – Color Sensor
As a starting point I will use the color sensor TCS34725, shared by Adafruit:
https://github.com/adafruit/Adafruit_TCS34725
To test the operation of the sensor, I used an Arduino Mega and the original sensor Adafruit, here we see sensor operating:
Here is the example code to control the sensor from the Arduino:
#include
#include "Adafruit_TCS34725.h"
#define redpin 3
#define greenpin 5
#define bluepin 6
#define commonAnode true
byte gammatable[256];
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);
void setup() {
Serial.begin(9600);
Serial.println("Color View Test!");
if (tcs.begin()) {
Serial.println("Found sensor");
} else {
Serial.println("No TCS34725 found ... check your connections");
while (1); // halt!
}
pinMode(redpin, OUTPUT);
pinMode(greenpin, OUTPUT);
pinMode(bluepin, OUTPUT);
for (int i=0; i<256; i++) {
float x = i;
x /= 255;
x = pow(x, 2.5);
x *= 255;
if (commonAnode) {
gammatable[i] = 255 - x;
} else {
gammatable[i] = x;
}
}
}
void loop() {
uint16_t clear, red, green, blue;
tcs.setInterrupt(false);
delay(60);
tcs.getRawData(&red, &green, &blue, &clear);
tcs.setInterrupt(true);
Serial.print("C:\t"); Serial.print(clear);
Serial.print("\tR:\t"); Serial.print(red);
Serial.print("\tG:\t"); Serial.print(green);
Serial.print("\tB:\t"); Serial.print(blue);
uint32_t sum = clear;
float r, g, b;
r = red; r /= sum;
g = green; g /= sum;
b = blue; b /= sum;
r *= 256; g *= 256; b *= 256;
Serial.print("\t");
Serial.print((int)r, HEX); Serial.print((int)g, HEX); Serial.print((int)b, HEX);
Serial.println();
analogWrite(redpin, gammatable[(int)r]);
analogWrite(greenpin, gammatable[(int)g]);
analogWrite(bluepin, gammatable[(int)b]);
}
and here the code for viewing from Processing:
import processing.serial.*;
import java.awt.datatransfer.*;
import java.awt.Toolkit;
Serial port;
void setup(){
size(200,200);
port = new Serial(this, "/dev/cu.usbmodem1411", 9600);
}
String buff = "";
int wRed, wGreen, wBlue, wClear;
String hexColor = "ffffff";
void draw(){
background(wRed,wGreen,wBlue);
while (port.available() > 0) {
serialEvent(port.read());
}
}
void serialEvent(int serial) {
if(serial != '\n') {
buff += char(serial);
} else {
int cRed = buff.indexOf("R");
int cGreen = buff.indexOf("G");
int cBlue = buff.indexOf("B");
int clear = buff.indexOf("C");
if(clear >=0){
String val = buff.substring(clear+3);
val = val.split("\t")[0];
wClear = Integer.parseInt(val.trim());
} else { return; }
if(cRed >=0){
String val = buff.substring(cRed+3);
val = val.split("\t")[0];
wRed = Integer.parseInt(val.trim());
} else { return; }
if(cGreen >=0) {
String val = buff.substring(cGreen+3);
val = val.split("\t")[0];
wGreen = Integer.parseInt(val.trim());
} else { return; }
if(cBlue >=0) {
String val = buff.substring(cBlue+3);
val = val.split("\t")[0];
wBlue = Integer.parseInt(val.trim());
} else { return; }
print("Red: "); print(wRed);
print("\tGrn: "); print(wGreen);
print("\tBlue: "); print(wBlue);
print("\tClr: "); println(wClear);
wRed *= 255; wRed /= wClear;
wGreen *= 255; wGreen /= wClear;
wBlue *= 255; wBlue /= wClear;
hexColor = hex(color(wRed, wGreen, wBlue), 6);
println(hexColor);
buff = "";
}
}
You need to have a little careful with external light, but the sensor works perfectly.
The plate was Designed by Adafruit Industries. licensed Creative Commons Attribution, Here we can download the libraries:
https://github.com/adafruit/Adafruit-Eagle-Library
And here we see TCS34725 files in Eagle:
After this, generates a library model for bacteria, and I designed the sensor for the bacteria recognizer.
in process….
Now I’m waiting for the components, the plan is to make a FabKit (http://fabacademy.org/archives/2015/doc/fabkit-0.4.html) to control color sensors. At the moment I am advancing on python code for TCS34725:
https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code/tree/master/Adafruit_TCS34725
+#!/usr/bin/python
+
+import time
+from Adafruit_I2C import Adafruit_I2C
+
+# ===========================================================================
+# TCS3472 Class
+# ===========================================================================
+
+
+class TCS34725:
+ i2c = None
+
+ __TCS34725_ADDRESS = 0x29
+ __TCS34725_ID = 0x12 # 0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727
+
+ __TCS34725_COMMAND_BIT = 0x80
+
+ __TCS34725_ENABLE = 0x00
+ __TCS34725_ENABLE_AIEN = 0x10 # RGBC Interrupt Enable
+ __TCS34725_ENABLE_WEN = 0x08 # Wait enable - Writing 1 activates the wait timer
+ __TCS34725_ENABLE_AEN = 0x02 # RGBC Enable - Writing 1 actives the ADC, 0 disables it
+ __TCS34725_ENABLE_PON = 0x01 # Power on - Writing 1 activates the internal oscillator, 0 disables it
+ __TCS34725_ATIME = 0x01 # Integration time
+ __TCS34725_WTIME = 0x03 # Wait time (if TCS34725_ENABLE_WEN is asserted)
+ __TCS34725_WTIME_2_4MS = 0xFF # WLONG0 = 2.4ms WLONG1 = 0.029s
+ __TCS34725_WTIME_204MS = 0xAB # WLONG0 = 204ms WLONG1 = 2.45s
+ __TCS34725_WTIME_614MS = 0x00 # WLONG0 = 614ms WLONG1 = 7.4s
+ __TCS34725_AILTL = 0x04 # Clear channel lower interrupt threshold
+ __TCS34725_AILTH = 0x05
+ __TCS34725_AIHTL = 0x06 # Clear channel upper interrupt threshold
+ __TCS34725_AIHTH = 0x07
+ __TCS34725_PERS = 0x0C # Persistence register - basic SW filtering mechanism for interrupts
+ __TCS34725_PERS_NONE = 0b0000 # Every RGBC cycle generates an interrupt
+ __TCS34725_PERS_1_CYCLE = 0b0001 # 1 clean channel value outside threshold range generates an interrupt
+ __TCS34725_PERS_2_CYCLE = 0b0010 # 2 clean channel values outside threshold range generates an interrupt
+ __TCS34725_PERS_3_CYCLE = 0b0011 # 3 clean channel values outside threshold range generates an interrupt
+ __TCS34725_PERS_5_CYCLE = 0b0100 # 5 clean channel values outside threshold range generates an interrupt
+ __TCS34725_PERS_10_CYCLE = 0b0101 # 10 clean channel values outside threshold range generates an interrupt
+ __TCS34725_PERS_15_CYCLE = 0b0110 # 15 clean channel values outside threshold range generates an interrupt
+ __TCS34725_PERS_20_CYCLE = 0b0111 # 20 clean channel values outside threshold range generates an interrupt
+ __TCS34725_PERS_25_CYCLE = 0b1000 # 25 clean channel values outside threshold range generates an interrupt
+ __TCS34725_PERS_30_CYCLE = 0b1001 # 30 clean channel values outside threshold range generates an interrupt
+ __TCS34725_PERS_35_CYCLE = 0b1010 # 35 clean channel values outside threshold range generates an interrupt
+ __TCS34725_PERS_40_CYCLE = 0b1011 # 40 clean channel values outside threshold range generates an interrupt
+ __TCS34725_PERS_45_CYCLE = 0b1100 # 45 clean channel values outside threshold range generates an interrupt
+ __TCS34725_PERS_50_CYCLE = 0b1101 # 50 clean channel values outside threshold range generates an interrupt
+ __TCS34725_PERS_55_CYCLE = 0b1110 # 55 clean channel values outside threshold range generates an interrupt
+ __TCS34725_PERS_60_CYCLE = 0b1111 # 60 clean channel values outside threshold range generates an interrupt
+ __TCS34725_CONFIG = 0x0D
+ __TCS34725_CONFIG_WLONG = 0x02 # Choose between short and long (12x) wait times via TCS34725_WTIME
+ __TCS34725_CONTROL = 0x0F # Set the gain level for the sensor
+ __TCS34725_ID = 0x12 # 0x44 = TCS34721/TCS34725, 0x4D = TCS34723/TCS34727
+ __TCS34725_STATUS = 0x13
+ __TCS34725_STATUS_AINT = 0x10 # RGBC Clean channel interrupt
+ __TCS34725_STATUS_AVALID = 0x01 # Indicates that the RGBC channels have completed an integration cycle
+
+ __TCS34725_CDATAL = 0x14 # Clear channel data
+ __TCS34725_CDATAH = 0x15
+ __TCS34725_RDATAL = 0x16 # Red channel data
+ __TCS34725_RDATAH = 0x17
+ __TCS34725_GDATAL = 0x18 # Green channel data
+ __TCS34725_GDATAH = 0x19
+ __TCS34725_BDATAL = 0x1A # Blue channel data
+ __TCS34725_BDATAH = 0x1B
+
+ __TCS34725_INTEGRATIONTIME_2_4MS = 0xFF # 2.4ms - 1 cycle - Max Count: 1024
+ __TCS34725_INTEGRATIONTIME_24MS = 0xF6 # 24ms - 10 cycles - Max Count: 10240
+ __TCS34725_INTEGRATIONTIME_50MS = 0xEB # 50ms - 20 cycles - Max Count: 20480
+ __TCS34725_INTEGRATIONTIME_101MS = 0xD5 # 101ms - 42 cycles - Max Count: 43008
+ __TCS34725_INTEGRATIONTIME_154MS = 0xC0 # 154ms - 64 cycles - Max Count: 65535
+ __TCS34725_INTEGRATIONTIME_700MS = 0x00 # 700ms - 256 cycles - Max Count: 65535
+
+ __TCS34725_GAIN_1X = 0x00 # No gain
+ __TCS34725_GAIN_4X = 0x01 # 2x gain
+ __TCS34725_GAIN_16X = 0x02 # 16x gain
+ __TCS34725_GAIN_60X = 0x03 # 60x gain
+
+ __integrationTimeDelay = {
+ 0xFF: 0.0024, # 2.4ms - 1 cycle - Max Count: 1024
+ 0xF6: 0.024, # 24ms - 10 cycles - Max Count: 10240
+ 0xEB: 0.050, # 50ms - 20 cycles - Max Count: 20480
+ 0xD5: 0.101, # 101ms - 42 cycles - Max Count: 43008
+ 0xC0: 0.154, # 154ms - 64 cycles - Max Count: 65535
+ 0x00: 0.700 # 700ms - 256 cycles - Max Count: 65535
+ }
+
+ # Private Methods
+ def __readU8(self, reg):
+ return self.i2c.readU8(self.__TCS34725_COMMAND_BIT | reg)
+
+ def __readU16Rev(self, reg):
+ return self.i2c.readU16Rev(self.__TCS34725_COMMAND_BIT | reg)
+
+ def __write8(self, reg, value):
+ self.i2c.write8(self.__TCS34725_COMMAND_BIT | reg, value & 0xff)
+
+ # Constructor
+ def __init__(self, address=0x29, debug=False, integrationTime=0xFF, gain=0x01):
+ self.i2c = Adafruit_I2C(address)
+
+ self.address = address
+ self.debug = debug
+ self.integrationTime = integrationTime
+ self.initialize(integrationTime, gain)
+
+ def initialize(self, integrationTime, gain):
+ "Initializes I2C and configures the sensor (call this function before \
+ doing anything else)"
+ # Make sure we're actually connected
+ result = self.__readU8(self.__TCS34725_ID)
+ if (result != 0x44):
+ return -1
+
+ # Set default integration time and gain
+ self.setIntegrationTime(integrationTime)
+ self.setGain(gain)
+
+ # Note: by default, the device is in power down mode on bootup
+ self.enable()
+
+ def enable(self):
+ self.__write8(self.__TCS34725_ENABLE, self.__TCS34725_ENABLE_PON)
+ time.sleep(0.01)
+ self.__write8(self.__TCS34725_ENABLE, (self.__TCS34725_ENABLE_PON | self.__TCS34725_ENABLE_AEN))
+
+ def disable(self):
+ reg = 0
+ reg = self.__readU8(self.__TCS34725_ENABLE)
+ self.__write8(self.__TCS34725_ENABLE, (reg & ~(self.__TCS34725_ENABLE_PON | self.__TCS34725_ENABLE_AEN)))
+
+ def setIntegrationTime(self, integrationTime):
+ "Sets the integration time for the TC34725"
+ self.integrationTime = integrationTime
+
+ self.__write8(self.__TCS34725_ATIME, integrationTime)
+
+ def getIntegrationTime(self):
+ return self.__readU8(self.__TCS34725_ATIME)
+
+ def setGain(self, gain):
+ "Adjusts the gain on the TCS34725 (adjusts the sensitivity to light)"
+ self.__write8(self.__TCS34725_CONTROL, gain)
+
+ def getGain(self):
+ return self.__readU8(self.__TCS34725_CONTROL)
+
+ def getRawData(self):
+ "Reads the raw red, green, blue and clear channel values"
+
+ color = {}
+
+ color["r"] = self.__readU16Rev(self.__TCS34725_RDATAL)
+ color["b"] = self.__readU16Rev(self.__TCS34725_BDATAL)
+ color["g"] = self.__readU16Rev(self.__TCS34725_GDATAL)
+ color["c"] = self.__readU16Rev(self.__TCS34725_CDATAL)
+
+ # Set a delay for the integration time
+ delay = self.__integrationTimeDelay.get(self.integrationTime)
+ time.sleep(delay)
+
+ return color
+
+ def setInterrupt(self, int):
+ r = self.__readU8(self.__TCS34725_ENABLE)
+
+ if (int):
+ r |= self.__TCS34725_ENABLE_AIEN
+ else:
+ r &= ~self.__TCS34725_ENABLE_AIEN
+
+ self.__write8(self.__TCS34725_ENABLE, r)
+
+ def clearInterrupt(self):
+ self.i2c.write8(0x66 & 0xff)
+
+ def setIntLimits(self, low, high):
+ self.i2c.write8(0x04, low & 0xFF)
+ self.i2c.write8(0x05, low >> 8)
+ self.i2c.write8(0x06, high & 0xFF)
+ self.i2c.write8(0x07, high >> 8)
+
+ #Static Utility Methods
+ @staticmethod
+ def calculateColorTemperature(rgb):
+ "Converts the raw R/G/B values to color temperature in degrees Kelvin"
+
+ if not isinstance(rgb, dict):
+ raise ValueError('calculateColorTemperature expects dict as parameter')
+
+ # 1. Map RGB values to their XYZ counterparts.
+ # Based on 6500K fluorescent, 3000K fluorescent
+ # and 60W incandescent values for a wide range.
+ # Note: Y = Illuminance or lux
+ X = (-0.14282 * rgb['r']) + (1.54924 * rgb['g']) + (-0.95641 * rgb['b'])
+ Y = (-0.32466 * rgb['r']) + (1.57837 * rgb['g']) + (-0.73191 * rgb['b'])
+ Z = (-0.68202 * rgb['r']) + (0.77073 * rgb['g']) + ( 0.56332 * rgb['b'])
+
+ # 2. Calculate the chromaticity co-ordinates
+ xc = (X) / (X + Y + Z)
+ yc = (Y) / (X + Y + Z)
+
+ # 3. Use McCamy's formula to determine the CCT
+ n = (xc - 0.3320) / (0.1858 - yc)
+
+ # Calculate the final CCT
+ cct = (449.0 * (n ** 3.0)) + (3525.0 *(n ** 2.0)) + (6823.3 * n) + 5520.33
+
+ return int(cct)
+
+ @staticmethod
+ def calculateLux(rgb):
+ "Converts the raw R/G/B values to color temperature in degrees Kelvin"
+
+ if not isinstance(rgb, dict):
+ raise ValueError('calculateLux expects dict as parameter')
+
+ illuminance = (-0.32466 * rgb['r']) + (1.57837 * rgb['g']) + (-0.73191 * rgb['b'])
+
+ return int(illuminance)
Primary source: http://academy.cba.mit.edu/classes/input_devices/index.html
Contact: fernando.meneses@udem.edu / fernandomeneses@nodolab.com / f / in / g+ / w / v / mx































