ein projekt was leider nie ganz fertiggestellt wurde und gleichzeitig mein arduino erstlingsprojekt. so fing alles an. meine agentur führte mal einige zeit lang ein ladengeschäft auf der karli in leipzig, wir nannten das "kapitänsmesse". zum laden gehörte auch ein schaufenster richtung straße, dort haben wir einen monitor eingebaut um ein paar kunden zu fangen und allgemeine aufmerksamkeit zu haschen. doch irgendwie war alles was damit erzeugt wurde nur verwirung, deshalb hatte ich überlegt, wie man die leute von der straße besser ans schaufenster ranholen könnte und vielleicht einen richtigen hingucker erzeugen würde. ich dachte es müsste irgendetwas interaktives her, etwas womit man spielen kann, etwas dass auf die aktion der leute draußen eine reaktion zeigt und es musste sich leicht umsetzen lassen. das sollte quasi eine verbindung zwischen dem schaufenster und den leuten herstellen. und dabei dachte ich an eine art riesiges moodlight was irgendwie von draußen steuerbar sein sollte. dann könnten die passanten die farbe der schaufensterbeleuchtung bestimmen und dadurch mit dem schaufenster interagieren und dadurch würde dann eher interesse an der sache entstehen. dann bin ich auf ein adafruit tutorial gestoßen, bei dem per farbsensor die farbe von irgendwelchen gegenständen auf eine LED übertragen wird. perfekt! 😃 damit könnten die leute draußen ihre klamotte oder was auch immer als vorlage herhalten und das moodlight würde dessen farbe annehmen.
zuerst habe ich den rgb sensor getestet. im grunde ist es ganz einfach aufzubauen, ich hab mich einfach an die anleitung von adafruit gehalten und es hat super funktioniert.
#include <Wire.h>
#include "Adafruit_TCS34725.h"
/* Example code for the Adafruit TCS34725 breakout library */
/* Connect SCL to analog 5
Connect SDA to analog 4
Connect VDD to 3.3V DC
Connect GROUND to common ground */
/* Initialise with default values (int time = 2.4ms, gain = 1x) */
// Adafruit_TCS34725 tcs = Adafruit_TCS34725();
/* Initialise with specific int time and gain values */
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_700MS, TCS34725_GAIN_1X);
int freq = 1000;
void setup(void) {
Serial.begin(9600);
if (tcs.begin()) {
Serial.println("Found sensor");
} else {
Serial.println("No TCS34725 found ... check your connections");
while (1);
}
// Now we're ready to get readings!
}
void loop(void) {
uint16_t r, g, b, c, colorTemp, lux;
tcs.getRawData(&r, &g, &b, &c);
colorTemp = tcs.calculateColorTemperature(r, g, b);
lux = tcs.calculateLux(r, g, b);
//Serial.print("Color Temp: "); Serial.print(colorTemp, DEC); Serial.print(" K - ");
//Serial.print("Lux: "); Serial.print(lux, DEC); Serial.print(" - ");
//Serial.print("R: "); Serial.print(r, DEC); Serial.print(" ");
//Serial.print("G: "); Serial.print(g, DEC); Serial.print(" ");
//Serial.print("B: "); Serial.print(b, DEC); Serial.print(" ");
//Serial.print("C: "); Serial.print(c, DEC); Serial.print(" ");
r *= 0.1;
g *= 0.1;
b *= 0.1;
Serial.print(r, DEC);
Serial.print(", ");
Serial.print(g, DEC);
Serial.print(", ");
Serial.print(b, DEC);
Serial.println(" ");
delay(freq);
}
als nächstes teste ich den LED streifen. auch das ist eigentlich ganz easy, wenn man die anleitung befolgt. wichtig ist nur zu wissen, dass es analoge aber auch digitale streifen gibt! den unterschied erkennt man offenbar an den eingängen, analoge streifen haben drei pins. bei digitalen gibt es vier pins und bei denen erkennt man auch lauter kleine controller auf dem streifen. das ist auch so wie ich es verstanden habe der größte unterschied, analoge streifen können nur eine farbe gleichzeitig haben, während durch die controller bei den digitalen streifen alle LEDs jeweils einzeln angesteuert werden können.
// includes
#include "LPD8806.h"
#include "SPI.h"
#ifdef __AVR_ATtiny85__
#include <avr/power.h>
#endif
// strip definition
int nLEDs = 48;
int dataPin = 2;
int clockPin = 3;
LPD8806 strip = LPD8806(nLEDs, dataPin, clockPin);
// setup function
void setup() {
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000L)
clock_prescale_set(clock_div_1);
#endif
// initialize strip
strip.begin();
strip.show();
}
// pixel function
void pixel(int n, int r, int g, int b) {
//turn rbg into rgb
uint32_t color = strip.Color(r,b,g);
strip.setPixelColor(n, color);
}
// infinite loop
void loop() {
fullcolor(255,255,150);
}
// fill entire strip with
void fullcolor(int r, int g, int b) {
int i;
for (i=0; i < strip.numPixels(); i++) {
pixel(i,r,g,b);
}
strip.show();
}
okay super, bleibt also nur die beiden einzelnen tests miteinander zu verknüpfen. ich check nochmal ob alles richtig verkabelt ist und verbinde beide codeschnipsel miteinander. looft 😃 nur die farben sind noch ein wenig matschig. offenbar gibt es da noch abweichungen von gemessenen und wiedergegebenen werten. nach ein wenig recherchieren war es glasklar, hier braucht es eine gammakorrektur! ich finde es recht logisch wenn ich genauer drüber nachdenke, sowas hat jeder monitor, nur eben schon integriert, da bekommt man das nicht mit. ich baue also zwischen den gemessenen farbwertwert und den ausgegebenen farbwert eine gammakorrektur, ich richte mich nach dieser anleitung. zackbumm, geile farben 👍 den kompletten code gibts anbei. die farben habe ich dann trotzdem nochmal etwas verstärkt, damit die kontraste bei blassen farben auch ordentlich rauskommen. zusätzlich hatte ich mich noch entschieden einen kleinen pushbutton unterzubringen, der beim drücken den aktuellen farbwert festhält.
nano | GND | 5V | A0 | A3 | A4 | A5 | D2 | D3 |
---|---|---|---|---|---|---|---|---|
rgb sensor | GND | VIN | SDA | SCL | ||||
led streifen | GND | 5V | DI | CI | ||||
abstandssensor | - | + | S | |||||
pushbutton | - | + |
// include sensor
#include "Wire.h"
#include "Adafruit_TCS34725.h"
// include strip
#include "LPD8806.h"
#include "SPI.h"
#ifdef __AVR_ATtiny85__
#include "avr/power.h"
#endif
// basic config
int ledPin = 13;
// sensor definition
Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_4X);
// strip definition
int nLEDs = 48;
int dataPin = 2;
int clockPin = 3;
LPD8806 strip = LPD8806(nLEDs, dataPin, clockPin);
// global color values
int R,G,B;
float L;
// set button pin
int bPin = 5;
boolean hold = false;
int stat;
// proximity setup
int proxPin = 0;
int level = 300;
boolean near = false;
// setup function
void setup() {
// initialize sensor
if (tcs.begin()) {
Serial.println("Found sensor");
} else {
Serial.println("No TCS34725 found ... check your connections");
while (1);
}
// initialize strip
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000L)
clock_prescale_set(clock_div_1);
#endif
strip.begin();
strip.show();
// initialize serial monitor
Serial.begin(9600);
// set button
pinMode(bPin, INPUT_PULLUP);
// set onboard led
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, LOW);
// init
readcol();
fillstrip();
}
// infinite loop
void loop() {
// check button for hold
checkhold();
if (!hold){
// check proximity
checkproximity();
if (near){
// read sensor and set RGB
readcol();
// gamma correction
lvlgamma();
// amplify colors
amplify();
// set strip to color
// fillstrip();
shufflestrip();
}
}
}
// button logic
void checkhold(){
if (digitalRead(bPin) == LOW){
if (stat != digitalRead(bPin)){
switch (hold) {
case false:
digitalWrite(ledPin, HIGH);
break;
case true:
digitalWrite(ledPin, LOW);
break;
}
hold = !hold;
}
}
stat = digitalRead(bPin);
}
// read proximity sensor
void checkproximity(){
int readProx = analogRead(proxPin);
if(readProx > level){
near = true;
digitalWrite(ledPin, HIGH);
Serial.println('#');
}else{
near = false;
digitalWrite(ledPin, LOW);
Serial.println('-');
}
}
// gamma table
const uint8_t PROGMEM gamma[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255
};
// print color to serial monitor
void pr(int a, int b, int c) {
Serial.print(a, DEC);
Serial.print(", ");
Serial.print(b, DEC);
Serial.print(", ");
Serial.print(c, DEC);
Serial.println(" ");
}
// read sensor color
void readcol(){
uint16_t clear, red, green, blue, lux;
tcs.getRawData(&red, &green, &blue, &clear);
// some value conversions
uint32_t sum = clear;
float r, g, b;
r = red; r /= sum; r *= 255;
g = green; g /= sum; g *= 255;
b = blue; b /= sum; b *= 255;
// calc lux
lux = tcs.calculateLux(red, green, blue);
// set global
R = r;
G = g;
B = b;
L = lux;
}
void lvlgamma(){
// gamma correction
R = pgm_read_byte(&gamma[R]);
G = pgm_read_byte(&gamma[G]);
B = pgm_read_byte(&gamma[B]);
}
void amplify(){
// dim lowest value for more contrast
if ((R < G) && (R < B)){ R=R/2; }
if ((G < R) && (G < B)){ G=G/2; }
if ((B < R) && (B < G)){ B=B/2; }
}
// set one pixel
void pixel(int sn, int sr, int sg, int sb) {
//turn rbg into rgb
uint32_t color = strip.Color(sr,sb,sg);
strip.setPixelColor(sn, color);
}
// set entire strip to measured color
void fillstrip() {
int i;
for (i=0; i < strip.numPixels(); i++) {
pixel(i,R,G,B);
strip.show();
delay(10);
}
}
// set random dot to measured color (only on proximity)
void shufflestrip() {
int px = random(nLEDs);
pixel(px,R,G,B);
strip.show();
Serial.println(px);
}
okay, zeit löten zu lernen 😃 ich hab ein wenig auf youtube rumgeschaut und denke ich probiere das mal. dazu hab ich erstmal testweise ein paar lötstellen auf einer rasterplate gemacht. dabei bekommt man schon ein ganz gutes gefühl dafür, wie das lötzinn fließt und wie lange man die bauteile erhitzen muss.
der prototyp sieht schon ganz gut aus. ich habe zuerst alle steckbrücken und controller-pins einzeln au einer rasterplatte festgelötet, dann die steckbrücken zurechgebogen und letztendlich von unten auf der rasterplatte brücken zwischen die kontakte gelötet. ziemlich viel arbeit, aber dafür sehr ordentlich.
dann habe ich mich gefragt, was ich am besten als gehäuse verwenden sollte. ich hatte noch solche kleinen metalldosen da und war der meinung das könnte gut passen. allerdings habe ich festgestellt, dass metall sich schwer verarbeiten lässt, besonders wenn man öffnungen einschneiden muss und auch, weil metall ja leitend ist. also keine besonders kluge wahl. letztendlich habe ich ein universalgehäuse aus kunststoff besorgt, das geht wesentlich einfach zu bearbeiten. dazu hab ich mir ein gravierset mit allerhand fräsen usw gekauft, das geht wunderbar, gerade wenn man mal größere öffnungen fräsen muss. innen habe ich die rasterplatte an den befestigungslöchern mit kleinen schrauben am gehäuse verbunden.
ich dachte jetzt wäre es getan. soweit hat auch alles funktioniert, die farben werden korrekt erkannt und ausgegeben. nur hatte ich vergessen, dass es ja einen auslöser braucht, sonst misst das farbdingens ununterbrochen und wenn kein objekt vor dem sensor ist sind alle LEDs nur weiß. ich hatte dann probiert über den LUX messer des farbsensors anhand der vom objekt reflektierten lichtstrahlen herauszubekommen, ob gerade ein objekt vor dem sensor ist, oder nicht. das hat nur so halb funktioniert, der sensor lies sich so durch geschicktes bewegen des messobjektes austricksen. 😳 deshalb musste etwas anderes her.
ich bin dann auf infrarot abstandssensoren gestoßen. ich habe den dann einzeln nochmal getestet und damit war das ergebnis sehr viel eindeutiger. entweder es ist etwas davor, oder nicht.
//set pins
int proxPin = 0;
int ledPin = 13;
int level = 300;
void setup(){
pinMode(ledPin, OUTPUT); //led
digitalWrite(ledPin, LOW);
Serial.begin(9600);
}
void loop(){
delay(100);
int readProx = analogRead(proxPin);
if(readProx > level){
digitalWrite(ledPin, HIGH);
Serial.println('#');
}else{
digitalWrite(ledPin, LOW);
Serial.println('-');
}
}
das problem war nur, dass ich dazu den sensor noch zusätzlich ins gehäuse integrieren musste. mein gehäuse war aber zu klein 😳 also habe ich ein neues gehäuse organisiert und alles eingesetzt. aber nun der finale test. ich habe das fertige farbdingens mal an an der schaufensterscheibe der kapitänsmesse ausprobiert. geht nicht. 💩 okay offenbar bricht die glasscheibe die IR strahlen so doof dass der sensor denkt es sei permanent etwas davor. also bestelle ich nochmal einen enuen IR sensor mit einer anderen reichweite, vielleicht bringt das den optischen ausgleich, wenn die distanzen anders sind.
und dann kam das aus für die kapitänsmesse 😳 schade. mal sehen, ich denke ich werde das wieder auseinanderfriemeln und in anderen projekten wiederverwenden, wäre sonst schade um das material. ich hätte gerne das bunte schaufenster gesehen, aber ich weiß dass es als prototyp funktioniert hat, darum gilt die mission trotz allem als erfolgreich abgeschlossen 😃 letztendlich war das letzte problem die glasscheibe, das häte ich noch irgendwie ausgleichen können, aber wir nutzen den laden nicht mehr und machen platz für neue geschäfte.