rokito drehlicht

drehlicht

ich wollte eigentlich immer schon ein moodlight haben, aber die sind mir meist zu spießig und zu sehr so spa-chillout-mäßig 😃 deshalb hatte ich überlegt, dass man im prinzip ein analogeres licht mischen könnte, indem einfach drei lampen in den grundfarben entsprechend additiv geschaltet werden. das hat auch den nötigen rgb-retro-bezug... ich möchte auch, dass man die lampen sieht, also die glühbirnen, denn das typische moodlight ist ja eher so eine gleichmäßige langweilige farbwand... dann fehlt dazu nur noch der richtige schalter für die einzelnen lampen. am besten irgendwas, was in diesem zusammenhang möglichst ungewöhnlich ist und was man vielleicht nicht anfassen kann, aber was trotzdem intuitiv ist und zum rumspielen einlädt! 😳 ...ein kompass. genau. ich baue ein drehlicht, dass auf das erdmagnetfeld reagiert.

material

eigentlich habe ich wieder wie immer alles bei amazon bekommen – bis auf eine ausnahme – für das gehäuse nutze ich dieses mal glas. dazu nehme ich einfach was so rumliegt, glücklicherweise bin ich immer zu faul das altglas wegzuschaffen, insofern habe ich freie wahl bei der suche nach einem geeigneten schraubglas. 😃 insgesamt summiert siche der materialwert für das drehlicht dann auf ca. 50 EUR.

vorbereitung

zuerst teste ich wieder die einzelnen kernbestandteile. in diesem fall gibt es eigentlich bloß ein externes shield, nämlich den magnetometer, also den kompass. die verkabelung ist sehr einfach, wie bei allen digitalen signalen gibt es nur SCL und SDA sowie VCC und GND für die 5V stromversorgung. bei adafruit gibt es auch schon ein tutorial zu diesem sensor 👍 hier geht es um ein adafruit eigenes shield, dieses nutzt aber den gleichen magnetometer chip wie die günstigen shields auf amazon (hmc5883l). das codebeispiel kann man eigentlich 1:1 benutzen, ich habe nur sehr wenige veränderungen gemacht und hauptsächlich ausgemistet. ich teste schonmal mit ein paar bunten leds, die gradzahl vom sensor teile ich einfach in sechs teile und nutze eine switch anweisung um die jeweiligen lampen ensprechend des drehwinkels zu schalten, mehr dazu im finalen code... zum testen stecke ich die leds einfach ohne widerstand und schalte die entsprechenden pins auf HIGH.

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>

/* Assign a unique ID to this sensor at the same time */
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);

void displaySensorDetails(void)
{
  sensor_t sensor;
  mag.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" uT");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" uT");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" uT");
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
}

void setup(void)
{
  Serial.begin(9600);
  Serial.println("HMC5883 Magnetometer Test"); Serial.println("");

  /* Initialise the sensor */
  if(!mag.begin())
  {
    /* There was a problem detecting the HMC5883 ... check your connections */
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
    while(1);
  }

  /* Display some basic information on this sensor */
  displaySensorDetails();
}

void loop(void)
{
  /* Get a new sensor event */
  sensors_event_t event;
  mag.getEvent(&event);

  /* Display the results (magnetic vector values are in micro-Tesla (uT)) */
  Serial.print("X: "); Serial.print(event.magnetic.x); Serial.print("  ");
  Serial.print("Y: "); Serial.print(event.magnetic.y); Serial.print("  ");
  Serial.print("Z: "); Serial.print(event.magnetic.z); Serial.print("  ");Serial.print("uT");

  // Hold the module so that Z is pointing 'up' and you can measure the heading with x&y
  // Calculate heading when the magnetometer is level, then correct for signs of axis.
  float heading = atan2(event.magnetic.y, event.magnetic.x);
  float declinationAngle = 0.0523599;
  heading += declinationAngle;

  // Correct for when signs are reversed.
  if(heading < 0)
    heading += 2*PI;

  // Check for wrap due to addition of declination.
  if(heading > 2*PI)
    heading -= 2*PI;

  // Convert radians to degrees for readability.
  float headingDegrees = heading * 180/M_PI;

  Serial.print(" Heading (degrees): "); Serial.println(headingDegrees);

  delay(100);
}

drehlicht

nun geht es darum die leds durch richtige lampen zu ersetzen – das led licht ist mir zu kühl und ich mag es wenn man einen glimmdraht sieht, deswegen nehme ich kleine lämpchen wie sie bei vielen autos in den leuchten verbaut sind, die größe hier ist E10. die verbrauchen nicht allzu viel, aber immerhin zu viel für den arduino 😳 ich dachte eigentlich "naja, steckste wie die leds direkt an die pins ran", aber das zwingt den arduino sofort in die knie 💩 da ich die lampen also nicht direkt schalten kann, brauche ich etwas dazwischen, eine art schalter der mit einer kleinen spannung vom pin eine größere für die lampen schalten kann. zeit sich mal mit transistoren zu beschäftigen und das ordentlich zu machen!

drehlicht

also habe ich kurzerhand welche von denen bestellt und mal an einer lampenschaltung getestet. wichtig zu wissen ist, dass ein transistor offenbar prinzipiell die minus leistung unterbricht und nicht die plusleitung. der transistor kommt also an das schwarze ground kabel nach der lampe und bevor es wieder ins netz mündet 😳 dann gibt es noch zwei verschiedene versionen von transistoren, für meinen fall kommt NPN in frage. und anscheinend gibt es noch verschiedene stromstärken – ich hatte auch nach einigen versuchen noch andere transistroren bestellt und getestet, aber letztendlich fahre ich hier mit 0,1A ganz gut, warum auch immer... um das richtig zu testen habe ich dann die kabel schonmal an die lampensockel gelötet, das war ein riesen wirrwar. bis hierhin klappt alles ganz gut.

drehlicht

prototyp

für den prototypen bauen ich alles auf den adafruit trinket um. zum testen nehme ich immer den größeren arduino uno, denn damit hantiert sich leichter, für das drehlicht soll der microcontroller aber ja so klein wie möglich sein und den trinket kann ich voll ausreizen und er ist dabei noch superklein und hübsch. beim umbau ist eigenlich nur zu beachten, dass die pins beim trinket jeweils mehrere belegungen haben können, aber das erklärt das pinout diagramm ganz gut. wichtig dabei ist die verteilung von SDA und SCL, ich find das fast en bissel blöd dass die nicht nebeneinander liegen aber was solls. die restlichen pins gehen eigentlich fast alle für die lampenschaltung und den sensor drauf. auch der code muss leicht angepasst werden, insbesondere was die includes angeht, da der trinket anscheinend etwas anders tickt, aber den kompletten code gibts unten, hier gibts auch keine möglichkeit mit serial etwas zu loggen usw... der code nutzt letztendlich auch fast den ganzen trinket speicher aus 😃 damit habe ich auch wieder meine pintabelle um nachher alles richtig löten zu können.

trinket GND BAT 5V #0 #1 #2 #3 #4
kompass GND VCC SDA SCL
power GND PWR
transis B B B

drehlicht

#include <TinyWireM.h>
#include <USI_TWI_Master.h>

#include <Adafruit_HMC5883_U.h>
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);
#define r 1
#define g 3
#define b 4

void setup(void)
{
  mag.begin();
  pinMode(r,OUTPUT);
  pinMode(g,OUTPUT);
  pinMode(b,OUTPUT);
}

void loop(void)
{

  sensors_event_t event;
  mag.getEvent(&event);
  float heading = atan2(event.magnetic.y, event.magnetic.x);
  if(heading < 0) heading += 2*PI;
  if(heading > 2*PI) heading -= 2*PI;
  int degrees = heading*180/M_PI+1;

  switch (degrees/60) {
    case 1:
      digitalWrite(r,HIGH);
      digitalWrite(g,HIGH);
      digitalWrite(b,LOW);
      break;
    case 2:
      digitalWrite(r,LOW);
      digitalWrite(g,HIGH);
      digitalWrite(b,LOW);
      break;
    case 3:
      digitalWrite(r,LOW);
      digitalWrite(g,HIGH);
      digitalWrite(b,HIGH);
      break;
    case 4:
      digitalWrite(r,LOW);
      digitalWrite(g,LOW);
      digitalWrite(b,HIGH);
      break;
    case 5:
      digitalWrite(r,HIGH);
      digitalWrite(g,LOW);
      digitalWrite(b,HIGH);
      break;
    case 6:
      digitalWrite(r,HIGH);
      digitalWrite(g,LOW);
      digitalWrite(b,LOW);
      break;
    case 0:
      digitalWrite(r,HIGH);
      digitalWrite(g,LOW);
      digitalWrite(b,LOW);
      break;
  }

}

fertigung

drehlicht

jetzt fehlt nur noch alles zusammenzulöten und zu verkleben. die lampenfassungen und transistoren hatte ich beim testen schon verlötet. bleibt also nur noch alles an den trinket und den sensor zu löten und die lampensockel mit heißkleber auf den schraubdeckel zu kleben. ich war mir nicht ganz sicher – die unterseiten von solchen deckeln scheinen ja irgendeine art beschichtung zu haben aber ich habe dann doch vorsichtshalber erst einen heißkleber tropfen geklebt, den aushärten lassen und dann den sockel darauf festgeklebt, damit haben die sockel genug abstand vom metalldeckel. die ganzen kabel und der trinket sowie der sensor hängen dann alle frei im glas, ich mag das wenn man die kabel sieht 😃

drehlicht

okay das wäre es soweit zum gehäuse, an sich ist es jetzt fertig. funktioniert aber nur so halb 😳 ich habe dann ein wenig rumprobiert und mal die kühlschrankmagneten drangehalten, aber irgendwie scheint der kompass falsche signale zu geben, die lampen schalten beim drehen nicht so wie sie sollten. ich kann mir das nur durch störende magnetfelder durch die ganze kabelei erklären. ich hab dann den sensor mal nach unten ins glas verlegt wo es keine kabel gibt. siehe da – looft 👍

drehlicht

zuletzt schraube ich noch die bunten birnen rein. mal sehen ob die ohne vorwiderstand ne weile halten, ansonsten muss ich da nochmal etwas feintunen. ich denke auch, dass es gut so ist, dass das drehlicht nur auf 6 farben schaltet. das unterstreicht zum einen den analogen charakter den ich so mag und andererseits könnte man theortisch die lampen noch mit PWM dimmen um fließende farbübergänge zu erzielen, aber ob die lampen das auf dauer mitmachen würde ich bezweifeln und ich denke auch dass dabei das haptische feedback geringer wäre als mit festen abstufungen... 😃 jetzt beim ersten richtigen test stellt sich auch heraus, dass das licht ganz anders gestreut wird als ich erwartet hatte, durch die form vom glas enstehen interessante lichtbrechungen. die waren in keinster weise beabsichtigt, aber ich mag sie!

drehlicht

dummerweise fängt dort irgendwas an zu schmoren, ich glaub ich hab da was falsch gemacht 💩 und eh mir noch die hütte abbrennt... 😳 das is mit zu blöd ich stelle jetzt um auf LED, da brauch ich mir kein kopp mehr machen welche bauteile wie zusammenpassen. zum glück hab ich noch von meinem farbdingens einen digitalen LED streifen über muhahahah 😃 den trinket muss ich aber leider wieder rausschneiden und durch einen normalen nano ersetzen, denn der trinket ist zu klein für die zusätzliche library für den LED streifen 😳

#include "LPD8806.h"
#include "SPI.h"
int nLEDs = 48;
int clockPin = 2;
int dataPin  = 3;
LPD8806 strip = LPD8806(nLEDs, dataPin, clockPin);

#include <Adafruit_HMC5883_U.h>
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);

// 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
};

void setup(void)
{
  mag.begin();
  strip.begin();
  strip.show();
  Serial.begin(9600);
}

void loop(void)
{

  sensors_event_t event;
  mag.getEvent(&event);
  float heading = atan2(event.magnetic.y, event.magnetic.x);
  if(heading < 0) heading += 2*PI;
  if(heading > 2*PI) heading -= 2*PI;
  int degrees = heading*180/M_PI+1;

  Serial.println(degrees/30);
  switch (degrees/30) {
    case 1:  fullcolor(255,0,0); break;
    case 2:  fullcolor(255,128,0); break;
    case 3:  fullcolor(255,255,0); break;
    case 4:  fullcolor(150,255,0); break;
    case 5:  fullcolor(0,255,0); break;
    case 6:  fullcolor(0,255,128); break;
    case 7:  fullcolor(0,255,255); break;
    case 8:  fullcolor(0,128,255); break;
    case 9:  fullcolor(0,0,255); break;
    case 10: fullcolor(128,0,255); break;
    case 11: fullcolor(255,0,255); break;
    case 12: fullcolor(255,0,128); break;
    case 0:  fullcolor(255,0,128); break;
  }

  delay(100);

}

// fill entire strip with
void fullcolor(int r, int g, int b) {

  //gamma
  r = pgm_read_byte(&gamma[r]);
  g = pgm_read_byte(&gamma[g]);
  b = pgm_read_byte(&gamma[b]);

  int i;
  for (i=0; i < nLEDs; i++) {
    uint32_t color = strip.Color(r,b,g);
    strip.setPixelColor(i, color);
  }
  strip.show();

}

den code stelle ich lediglich in sofern um, dass nun keine drei einzelnen pins zusammengeschalten werden, sondern ein rgb signal an den streifen geschickt wird. dadurch kann ich auch mehr zwischentöne mischen und die farben werden sauberer. apropos farben, hier braucht es noch eine gammakorrektur sonst werden die farben beim mischen matschig, aber auch da ist schnell implementiert. endlich fertig 👍 der effekt lohnt das gemehre 😃