Lecture 18: May 15, 2013
Assignment:
Develop the final project and
Develop a plan for dissemination of your final project
Using Arduino Duemillanuove
and This shield:
// TCS3414 receiver code rev 5
// Developed by Tiuri de Jong, with contributions by Max
Pierson
// This software is released under WTFPL, although credit and
share-alike are appreciated.
// 18 November 2012
//include the library for i2c
#include
unsigned int TCS3414values[4]; // [Clear,Red,Green,Blue]
float TCS3414medium[4]; // [Clear,Red,Green,Blue]
float TCS3414mediate[4]; // [Clear,Red,Green,Blue]
float ColorTemperature = 0;
// SET the integration time here. Higher times allow for
higher values with better precicion.
int integrationtime = 400; //12 == 12ms, 100 = 100ms, 400 =
400ms. Other values are note accepted
int loopdelay = integrationtime; //loop delay depends on the
integration time
boolean debug = false; //change to true if you want to see the
various debug serial output bits
boolean percentageEnabled = false; //enable/disable the
percentage mode
boolean compensateEnabled = false; //enable/disable color
compensation of the sensor sensitivity per color
void setup(){
Wire.begin();// join i2c bus (address optional for master)
Serial.begin(9600);//115200
while (!Serial) {
; // wait for serial port to connect. This while loop is
needed for the Arduino Leonardo only
}
CMD(0);
TCS3414Start(14,2000);
}
//The main function.. This repeats itself forever!
void loop() {
getSerialCommands(); //to be able to receive commands
//gets the raw values from the sensors and writes it to
TCS3414values[]
TSC3414All(TCS3414values);
//compensate based on the filter characteristics of the
TCS3414
if(compensateEnabled)
colorCompensator(TCS3414values);
//keeps a running average from the last 4 values per color.
calculateMedium(TCS3414mediate,TCS3414values,4.0);
//calculates the color temperature, using the algorithm in the
TCS3414 datasheet
ColorTemperature = CCTCalc(TCS3414values);
//displays percentage values, if enabled.
if(percentageEnabled){
makePercentage(TCS3414values, TCS3414medium);
}
Serial.print(“Clear: “);
Serial.print(TCS3414values[0]);
if(percentageEnabled)
Serial.print(“%”);
Serial.print(“\tRed: “);
Serial.print(TCS3414values[1]);
if(percentageEnabled)
Serial.print(“%”);
Serial.print(” \tGreen: “);
Serial.print(TCS3414values[2]);
if(percentageEnabled)
Serial.print(“%”);
Serial.print(“\tBlue: “);
if(percentageEnabled){
Serial.print(TCS3414values[3]);
Serial.println(“%”);
}else{
Serial.println(TCS3414values[3]);
}
delay(loopdelay); //delays by the integration time between
measurements
}//end loop()
/*
* ======================================================
* Calculation functions
* ======================================================
*/
/*** takes the raw values from the sensors and converts them
to
Correlated Color Temperature. Returns a float with CCT ***/
float CCTCalc(unsigned int allcolors[]){
float TCS3414tristimulus[3]; // [tri X, tri Y, tri Z]
float TCS3414chromaticityCoordinates[2]; //chromaticity
coordinates // [x, y]
//calculate tristimulus values (chromaticity coordinates)
//The tristimulus Y value represents the illuminance of our
source
TCS3414tristimulus[0] = (-0.14282 * allcolors[1]) + (1.54924 *
allcolors[2]) + (-0.95641 * allcolors[3]); //X
TCS3414tristimulus[1] = (-0.32466 * allcolors[1]) + (1.57837 *
allcolors[2]) + (-0.73191 * allcolors[3]); //Y // =
Illuminance
TCS3414tristimulus[2] = (-0.68202 * allcolors[1]) + (0.77073 *
allcolors[2]) + (0.56332 * allcolors[3]); //Z
float XYZ = TCS3414tristimulus[0] + TCS3414tristimulus[1] +
TCS3414tristimulus[2];
//calculate the chromaticiy coordinates
TCS3414chromaticityCoordinates[0] = TCS3414tristimulus[0] /
XYZ; //x
TCS3414chromaticityCoordinates[1] = TCS3414tristimulus[1] /
XYZ; //y
float n = (TCS3414chromaticityCoordinates[0] – 0.3320) /
(0.1858 – TCS3414chromaticityCoordinates[1]);
float CCT = ( (449*pow(n,3)) + (3525*pow(n,2)) + (6823.3 * n)
+ 5520.33 );
Serial.print(“Illuminance: “);
Serial.print(TCS3414tristimulus[1]);
Serial.print(“\tx: “);
Serial.print(TCS3414chromaticityCoordinates[0]);
Serial.print(” \ty: “);
Serial.print(TCS3414chromaticityCoordinates[1]);
Serial.print(” \tCCT: “);
Serial.print(CCT);
Serial.print(“K\t — \t”);
return CCT;
}
/*** Keeps a running average of 4 values per color. ***/
void calculateMedium(float med[], unsigned int value[], float
divider){
for(int i = 0; i < 4; i++){
med[i] = ( (med[i]*(divider-1.0)) + value[i] ) / divider;
}
}
/*** calculates percentages for R,G,B channels, if enabled.
***/
void makePercentage(unsigned int allcolors[], float
allmedium[]){ //makes every color a percentage, 100% is the
average of the previous 4 values before this is entered.
for(int i=0; i 0){
int receive_command = Serial.read();
if(receive_command == 49){//49 == 1
Serial.println(“Percentage enabled, max value (100%) set to
current medium”);
percentageEnabled = true;//enables/disables percentage mode.
for(int o = 0; o < 4; o++){
TCS3414medium[o] = TCS3414mediate[o];
}
}else if(receive_command == 48){//48 == 0
Serial.println(“Percentage disabled”);
percentageEnabled = false;//enables/disables percentage mode.
}else if(receive_command == 63){//63 == ?
CMD(2000);
}else if(receive_command == 112){//112 == p
Serial.println(“pausing for 5 seconds (stackable)…”);
delay(5000);
getSerialCommands();
}else if(receive_command == 99){//99 == c
Serial.println(“Color compensation enabled”);
compensateEnabled = true;
}else if(receive_command == 110){//110 == n
Serial.println(“Color compensation disabled”);
compensateEnabled = false;
}else{
Serial.print(“The command entered ( “);
Serial.print(receive_command);
Serial.println(” ) was NOT found in the command list”);
}
}
}
void CMD(int delayTime){
Serial.println(“=========== Command list ===========”);
Serial.println(“\’ \’”);
Serial.println(” ? == Show this command list”);
Serial.println(“”);
Serial.println(” p == pause for 5 seconds (stackable)”);
Serial.println(“”);
Serial.println(” 1 == Enable Percentage mode”);
Serial.println(” 0 == Disable Percentage mode”);
Serial.print(” Percentage mode is currently: “);
if(percentageEnabled){
Serial.println(“ON”);
}else{
Serial.println(“OFF”);
}
Serial.println(“”);
Serial.println(” c == Enable Color compensation mode”);
Serial.println(” n == Disable Color compensation mode”);
Serial.print(” Color compensation mode is currently: “);
if(compensateEnabled){
Serial.println(“ON”);
}else{
Serial.println(“OFF”);
}
Serial.println(“\’ \’”);
Serial.println(“====================================”);
delay(delayTime);
}
Since the code is released under the "wtfpl" licence -
we will use that as a starting point (and we won't fully
translate what wtfpl licence stands for but its something with
"do what the f you want to publice licence"...). #ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#if defined(__AVR_ATmega168__) ||
defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__)
// deactivate internal pull-ups for twi
// as per note from atmega8 manual pg167
cbi(PORTC, 4);
cbi(PORTC, 5);
#else
// deactivate internal pull-ups for twi
// as per note from atmega128 manual pg204
cbi(PORTD, 0);
cbi(PORTD, 1);
#endif
Note this:The TTL levelshifter ended up looking like this:
static volatile uint8_t *dmxPort;
static uint8_t dmxBit = 0;
static uint8_t dmxPin = 3; // Defaults to output on pin 3 to
support Tinker.it! DMX shield
<TO THIS>
static volatile uint8_t *dmxPort;
static uint8_t dmxBit = 0;
static uint8_t dmxPin = 0; // Defaults to output on pin 0 to
support CuteDigi's MaxwellRossPierson's DMX shield
/*
Based on sample code from Tinker.it - the creator of DmxSimple
Arduino Library
Modified and adapted by Michael Hviid Nielsen, 2013
for a Fab Academy project
*/
/******************************* Pin
Outs*****************************/
// Digital Pin0 on Arduino = Pin1 of MAX485 alias Receiver
Output
// Digital Pin1 on Arduino = Pin4 of MAX485 alias Driver Input
// Digital Pin2 on Arduino = Pin2 of MAX485 alias Receive
Enable
// Digital Pin3 on Arduino = Pin3 of MAX485 alias Drive Enable
/* NB! The state on pin 0 can prevent a new sketch to upload
on the Arduino*/
/* So disconnect shield while updating firmware*/
#include <DmxSimple.h>
#define RED_CHANNEL 1
#define GRN_CHANNEL 2
#define BLU_CHANNEL 3
#define WHI_CHANNEL 4
int DMX_RE = 2;
int DMX_DE = 3;
void setup() {
pinMode(DMX_RE, OUTPUT);
pinMode(DMX_DE, OUTPUT);
digitalWrite(DMX_RE, LOW); // Set direction pin
of transceiver to Rx.
digitalWrite(DMX_DE, HIGH); // Set direction pin
of transceiver to Tx.
/* The pin used for DMX output. Depends on the shield
used. If you need to change that, do it here. */
DmxSimple.usePin(1);
/* DMX devices typically need to receive a complete set
of channels
** even if you only need to adjust the first channel.
You can
** easily change the number of channels sent here. If
you don't
** do this, DmxSimple will set the maximum channel
number to the
** highest channel you DmxSimple.write() to. */
// DmxSimple.maxChannel(4);
}
void loop() {
int brightness;
/* Simple loop to ramp up brightness RED */
for (brightness = 0; brightness <= 255;
brightness++) {
/* Update DMX channel to new brightness */
DmxSimple.write(RED_CHANNEL, brightness);
/* Small delay to slow down the ramping */
delay(5);
}
for (brightness = 255; brightness >= 0;
brightness--) {
/* Update DMX channel to new brightness */
DmxSimple.write(RED_CHANNEL, brightness);
/* Small delay to slow down the ramping */
delay(5);
}
/* Simple loop to ramp up brightness GREEN */
for (brightness = 0; brightness <= 255;
brightness++) {
/* Update DMX channel to new brightness */
DmxSimple.write(GRN_CHANNEL, brightness);
/* Small delay to slow down the ramping */
delay(5);
}
for (brightness = 255; brightness >= 0;
brightness--) {
/* Update DMX channel to new brightness */
DmxSimple.write(GRN_CHANNEL, brightness);
/* Small delay to slow down the ramping */
delay(5);
}
/* Simple loop to ramp up brightness BLUE */
for (brightness = 0; brightness <= 255;
brightness++) {
/* Update DMX channel to new brightness */
DmxSimple.write(BLU_CHANNEL, brightness);
/* Small delay to slow down the ramping */
delay(5);
}
for (brightness = 255; brightness >= 0;
brightness--) {
/* Update DMX channel to new brightness */
DmxSimple.write(BLU_CHANNEL, brightness);
/* Small delay to slow down the ramping */
delay(5);
}
/* Simple loop to ramp up brightness WHI */
for (brightness = 0; brightness <= 255;
brightness++) {
/* Update DMX channel to new brightness */
DmxSimple.write(WHI_CHANNEL, brightness);
/* Small delay to slow down the ramping */
delay(5);
}
for (brightness = 255; brightness >= 0;
brightness--) {
/* Update DMX channel to new brightness */
DmxSimple.write(WHI_CHANNEL, brightness);
/* Small delay to slow down the ramping */
delay(5);
}
}
Carefull reading of the datasheet for the chip reveals
its inner workings and the gist of it can be condensed to this: