The Bright Orange

I found this cute little sliced-orange night-light on the internet. In its original form it just has 3 internal LEDs that light the whole thing up. I can certainly do better! :-)

Original unit

Out with the old!

I dis-assembled the unit and stripped out all the original mains-rated stuff.

Dis-assembled device

Wedges

My intention was to light each segment of the orange individually. Part of this required a way to not light adjacent segments to the one being lit. To achieve this, I created 8 wedge-shaped light boxes from clear perspex:

Shaped perspex block

covering the sides and top of each wedge with aluminium foil, glued on with epoxy resin:

Glueing foil to perspex wedges

Finally the foiled wedges were glued back into a disk.

LED lighting.

Next, I carefully drilled 5mm holes out of the inside sloped edges of the wedges and inserted ultra-bright orange LEDs in each hole, with a dab of acrifix in each to hold them firm. I soldered the common leads of the LEDs together to a single lead (centre) with the other ends exiting the disk around it. A big glob of acrifix on top to set into solid acrylic overnight:

Building the light unit

Then, I sanded the transparent side of the light unit flat.

Sanded light unit

Finally, I soldered on 150 ohm resistors and a common wire, with another blob of acrifix (and some plastic shavings) to hold it all secure:

Completed light unit

Micro-control

An Arduino Pro-Micro (Leonardo compatible) was epoxy glued to a piece of scrap perspex which had been acrifixed over the resistors. Then I wired all the resistor-ends to the arduino digital pins 2 through 9:

Dis-assembled device

Oh Bugger! I had been testing the LEDs in the light-wedges with a button cell and forgot that + was the case side of the battery, so all my LEDs had the wrong terminal wired to common. Luckily, by wiring the common to VCC instead of GND, it still works (common anode), at the expense of having to remember to use HIGH for off and LOW for on in the arduino coding (the other way around is convention, but the arduino itself doesn't actually care).

Optional Extras

The Arduino Pro-Micro still has a few spare pads, so I am cramming extra functions in that I may-or-may-not use.

I de-soldered the LDR from the origional board and added it, along with a 1M ohm balance resistor to analog input A0. If I want to, I can now sense light levels around the device. I also put a small piece of black cardboard behind the LDR to keep stray internal light off it:

Dis-assembled device

I ordered a mobile phone earpiece speaker (tiny but loud) to connect up to digital output 10. I then programmed a startup sound (a few bars of Orange Crush by REM [Used under copyright fair-use academic provisions] - Thanks Mark R. for the transcription). Also added assorted appropriate beeps to the loop effects.

A micro-speaker glued on next to the Arduino

You can also see, above, that I painted some silver paint over the inside to try and reduce light-splash even further.

Finally, I drilled out the back with a circle-saw and glued in a perspex disk. This was both because the base had the ugly holes left over from removing the mains pins and also because, as a student demo project, I wanted to be able to see inside without always unscrewing the back.

The rear viewport on the device

 

Code

For the Arduino code, I programmed in a bunch of short subroutines that flash and cycle the LEDs in different patterns. The routine names are fairly self-explanatory. Some have extra variables, so far to determine the number of repeats to do, where it is appropriate :

//Leonardo/Pro-Micro // due to a brain-lapse, LEDS were wired backwards and // common had to be connected to VCC instead of GND // As a result LOW is ON and HIGH is OFF below #include "pitches.h" // from the Arduino digital-tone examples int count = 2; // loop counter int iterations; // repeat counter // the setup routine runs once when you press reset: void setup() { // initialize the digital pins as an output. for(count = 2; count <10; count++) pinMode(count, OUTPUT); playREM(0); // 0 = play the whole intro tune } // the loop routine runs over and over again forever: void loop() { all_off(); single_random(64); multi_random(64); all_off(); single_CCW(4); single_CW(4); single_CCW(1); single_CW(1); single_CCW(1); single_CW(1); dual_CW(8); all_off(); dual_CCW(8); all_off(); fill_CW(); empty_CW(); fill_CW(); empty_CW(); fill_CW(); empty_CW(); fill_CW(); empty_CW(); fill_CCW(); empty_CCW(); fill_CCW(); empty_CCW(); fill_CCW(); empty_CCW(); fill_CCW(); empty_CCW(); all_on(); all_off(); all_on(); all_off(); all_on(); all_off(); all_on(); all_off(); delay(500); playREM(1); // 1 = just the main bit this time } void single_CW(int loops) { for(iterations=0;iterations < loops;iterations++) { for(count=2;count<10;count++) { if(count==2) digitalWrite(9, HIGH); else digitalWrite(count-1, HIGH); // turn the previous LED off digitalWrite(count, LOW); // turn the next LED on tone(10,1000,10); delay(100); // wait for 1/10 second } } } void single_CCW(int loops) { for(iterations=0;iterations < loops;iterations++) { for(count=9;count>1;count--) { if(count==9) digitalWrite(2, HIGH); else digitalWrite(count+1, HIGH); digitalWrite(count, LOW); tone(10,1000,10); delay(100); } } } void dual_CW(int loops) { for(iterations=0;iterations < loops;iterations++) { for(count=2;count<6;count++) { if(count==2) { digitalWrite(9, HIGH); digitalWrite(5, HIGH); } else { digitalWrite(count-1, HIGH); digitalWrite(count+3, HIGH); } digitalWrite(count, LOW); digitalWrite(count+4, LOW); tone(10,count*100); delay(100); } } noTone(10); } void dual_CCW(int loops) { for(iterations=0;iterations < loops;iterations++) { for(count=5;count>1;count--) { if(count==5) { digitalWrite(2, HIGH); digitalWrite(6, HIGH); } else { digitalWrite(count+1, HIGH); digitalWrite(count+5, HIGH); } digitalWrite(count, LOW); digitalWrite(count+4, LOW); tone(10,count*100); delay(100); } } noTone(10); } void fill_CW() { for(count=2;count < 10;count++) { digitalWrite(count, LOW); delay(100); tone(10,count*500); } noTone(10); } void fill_CCW() { for(count=9;count > 1;count--) { digitalWrite(count, LOW); delay(100); tone(10,5500-count*500); } noTone(10); } void empty_CW() { for(count=2;count < 10;count++) { digitalWrite(count, HIGH); delay(100); tone(10,5500-count*500); } noTone(10); } void empty_CCW() { for(count=9;count > 1;count--) { digitalWrite(count, HIGH); delay(100); tone(10,count*500); } noTone(10); } void all_on() { for(count=9;count > 1;count--) { digitalWrite(count, LOW); } tone(10,2000); delay(400); noTone(10); } void all_off() { for(count=9;count > 1;count--) { digitalWrite(count, HIGH); } noTone(10); delay(400); } void single_random(int loops) { for(iterations=0;iterations < loops;iterations++) { int current = (int) random(2,9); digitalWrite(current, LOW); // turn it on delay(100); // wait for 1/10 second digitalWrite(current, HIGH); //turn it off tone(10, (int) random(1000,2000)); } noTone(10); } void multi_random(int loops) { for(iterations=0;iterations < loops;iterations++) { int current = (int) random(2,9); digitalWrite(current, LOW); // turn one on delay(50); // wait for 1/10 second current = (int) random(2,9); digitalWrite(current, HIGH); //turn one off delay(50); // wait for 1/10 second tone(10, (int) random(500,1000)); } noTone(10); } void playREM(int length) // 0 = full intro, 1 = second half only { // REM - Orange Crush :-P int melody[] = { NOTE_B3, NOTE_B3, NOTE_B3, NOTE_D4, NOTE_E4, NOTE_D4, NOTE_B3, NOTE_G3, NOTE_G3, NOTE_G3, NOTE_D3, NOTE_FS3, NOTE_FS3, NOTE_G3, NOTE_FS3, NOTE_E3}; // note durations: 4 = quarter note, 8 = eighth note, etc.: int noteDurations[] = {8, 4, 3, 4, 4, 8, 2, 4, 4, 4, 4, 4, 4, 6, 4, 4}; for (int thisNote = length*7; thisNote < 16; thisNote++) { // to calculate the note duration, take one second // divided by the note type. //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc. int noteDuration = 1000/noteDurations[thisNote]; tone(10, melody[thisNote],noteDuration); // to distinguish the notes, set a minimum time between them. // the note's duration + 30% seems to work well: int pauseBetweenNotes = noteDuration * 1.30; delay(pauseBetweenNotes); // stop the tone playing: noTone(10); } }

And here it is in action:

[REM "Orange Crush" used under copyright fair-use academic provisions]