-
When Hardware Guys Write Code…
10/31/2014 at 06:36 • 0 commentsWith parts on the way my next step was to start working on the software side of the project. Now I am a hardware guy, I know that you can do amazing things with software, and if it means less mucking around with 'Hard Logic' and greater flexibility then I am all for it. However, I often have no idea where to start when it comes to the actual code. That is one of the main reasons why I have chosen the Arduino platform for this project, for the simplicity of coding, the number of code examples available and because I don't have the facilities to spin my own PCBs at the Højskole a ready made development board simplifies the situation considerably. Another advantage with this is that I had some of the code from a previous project that I could reuse.
A couple of years back I was asked by a family member if we could do some 'Fancy Lighting' with the glass splash-back behind his stove in the kitchen of the new house that he was building, the 'fancy' solution ended up being an RGB LED strip lighting through the glass, the effect was pretty cool and has become a talking point at parties.
I wrote the original code with help from a friend and while it wasn't the most elegant it was functional and fit for purpose. I planned to reuse elements of this code, making it more elegant where possible.
The controller would have eight push buttons, four power transistors, one PIR sensor and one microphone. The intention was to build it in stages, first the pushbuttons and power transistors to provide basic control, then adding code to allow the LEDs to cross fade, next a PIR would be added and finally the microphone, other coding elements, for example a tap tempo button to control the crossfade rate, could be explored after that. The code would have to grow along with the hardware, and after many long nights, countless uploads and lots of debugging I think I have ended up with a pretty robust foundation. At this stage only the first and second stages have been implemented; basic control and crossfading, and it functions really well. The following snippet is the code in its current iteration.
/*===================[ RGBW LED CONTROLLER ]=============================================================================================
*
*RGBW_LED_Controller.ino
*
*Created: 14/09/2014
*Author: D. Blackler
*
*The code is designed for the Arduino Uno, it takes inputs from eight(8) momentery push buttons, one(1) microphone and one(1) PIR sensor and outputs a
* PWM signal to a length of RGBW LED strip via three(4) power transistors. The input push buttons
* are as follows:
*
* Button Momentery Hold
* Red Red 100% Length determines % of red in mix
* Green Green 100% Length determines % of green in mix
* Blue Blue 100% Length determines % of blue in mix
* White White 100% Length determines intensity of white
* Fade Starts cross fade cycle
* Reset Resets colour mix to all off
*
*
*==================================================================================================================================*/
/*===================[ REVISION HISTORY ]===========================================================================================
*
* Revision 1: 14/09/2014
*-First created and formatted
* Revision 2: 17/10/2014
*-First generation functional code
*
*
*
*
*
*
*
*
*
*
*==================================================================================================================================*/
/*===================[ PIN DEFINITIONS ]===========================================================================================*/
#define REDPB 2
#define GREENPB 3
#define BLUEPB 4
#define WHITEPB 5
#define FADEPB 7
#define RESETPB 8
#define REDPIN 6
#define GREENPIN 9
#define BLUEPIN 10
#define FADESPEED 15 // The higher this number, the slower the cross fade speed will be
// Initialize global variables
int FADE = 0; //Crossfade indicator initialised to 0
/*===================[ SETUP ]=====================================================================================================*/
void setup()
{
pinMode(REDPB, INPUT);
pinMode(GREENPB, INPUT);
pinMode(BLUEPB, INPUT);
pinMode(WHITEPB, INPUT);
pinMode(FADEPB, INPUT);
pinMode(RESETPB, INPUT);
pinMode(REDPIN, OUTPUT);
pinMode(GREENPIN, OUTPUT);
pinMode(BLUEPIN, OUTPUT);
// Initialize serial communications at 9600 bps:
Serial.begin(9600);
}
/*===================[ MAIN FUNCTION ]=============================================================================================*/
void loop()
{
int x = 0;
int R = 0; //Red intensity variable initialised to 0
int G = 0; //Green intensity variable initialised to 0
int B = 0; //Blue intensity variable initialised to 0
x = Button();
{
switch(x)
{
case 1: //If called sets red intensity to 100%, if button is held down, red
R = 255; //intensity dims
analogWrite(REDPIN, R);
while (Button() == 1)
{
R --;
analogWrite(REDPIN, R);
delay(10);
}
break;
case 2: //If called sets green intensity to 100%, if button is held down, green
G = 255; //intensity dims
analogWrite(GREENPIN, G);
while (Button() == 2)
{
G --;
analogWrite(GREENPIN, G);
delay(10);
}
break;
case 3: //If called sets blue intensity to 100%, if button is held down, blue
B = 255; //intensity dims
analogWrite(BLUEPIN, B);
while (Button() == 3)
{
B --;
analogWrite(BLUEPIN, B);
delay(10);
}
break;
case 4: //If called sets white intensity to 100%, if button is held down, white
R = 255; //intensity dims. R,G & B are used to create 'white'
G = 255;
B = 255;
analogWrite(REDPIN, R);
analogWrite(GREENPIN, G);
analogWrite(BLUEPIN, B);
while (Button() == 4)
{
R --;
G --;
B --;
analogWrite(REDPIN, R);
analogWrite(GREENPIN, G);
analogWrite(BLUEPIN, B);
delay(10);
}
break;
case 5: //If called sets crossfade indicatorred to 1 and then calls Crossfade
FADE = 1; //subroutine
Crossfade();
break;
case 6: //If called sets all intensities and crossfade indicator to 0
R = 0;
G = 0;
B = 0;
FADE = 0;
analogWrite(REDPIN, R);
analogWrite(GREENPIN, G);
analogWrite(BLUEPIN, B);
break;
}
}
}
/*===================[ FUNCTIONS ]=================================================================================================*/
/* The following function returns a number depending on which button or combination of buttons is pressed it also includes simple
* delay and recheck debouncing. The returns are as follows:
*
* Button Return
* Red '1'
* Green '2'
* Blue '3'
* White '4'
* Crossfade '5'
* Reset '6'
*
*/
int Button()
{
// Checking 'RED' Push button, includes software debouncing
if ((digitalRead(REDPB) == HIGH)&&(digitalRead(GREENPB) == LOW)&&(digitalRead(BLUEPB) == LOW)&&(digitalRead(WHITEPB) == LOW)&&
(digitalRead(FADEPB) == LOW)&&(digitalRead(RESETPB) == LOW))
{
delay (10);
if ((digitalRead(REDPB) == HIGH)&&(digitalRead(GREENPB) == LOW)&&(digitalRead(BLUEPB) == LOW)&&(digitalRead(WHITEPB) == LOW)&&
(digitalRead(FADEPB) == LOW)&&(digitalRead(RESETPB) == LOW))
{
Serial.print("B1 = " );
Serial.println(HIGH);
return 1;
}
}
// Checking 'GREEN' Push button, includes software debouncing
if ((digitalRead(REDPB) == LOW)&&(digitalRead(GREENPB) == HIGH)&&(digitalRead(BLUEPB) == LOW)&&(digitalRead(WHITEPB) == LOW)&&
(digitalRead(FADEPB) == LOW)&&(digitalRead(RESETPB) == LOW))
{
delay (10);
if ((digitalRead(REDPB) == LOW)&&(digitalRead(GREENPB) == HIGH)&&(digitalRead(BLUEPB) == LOW)&&(digitalRead(WHITEPB) == LOW)&&
(digitalRead(FADEPB) == LOW)&&(digitalRead(RESETPB) == LOW))
{
Serial.print("B2 = " );
Serial.println(HIGH);
return 2;
}
}
// Checking 'BLUE' Push button, includes software debouncing
if ((digitalRead(REDPB) == LOW)&&(digitalRead(GREENPB) == LOW)&&(digitalRead(BLUEPB) == HIGH)&&(digitalRead(WHITEPB) == LOW)&&
(digitalRead(FADEPB) == LOW)&&(digitalRead(RESETPB) == LOW))
{
delay (10);
if ((digitalRead(REDPB) == LOW)&&(digitalRead(GREENPB) == LOW)&&(digitalRead(BLUEPB) == HIGH)&&(digitalRead(WHITEPB) == LOW)&&
(digitalRead(FADEPB) == LOW)&&(digitalRead(RESETPB) == LOW))
{
Serial.print("B3 = " );
Serial.println(HIGH);
return 3;
}
}
// Checking 'WHITE' Push button, includes software debouncing
if ((digitalRead(REDPB) == LOW)&&(digitalRead(GREENPB) == LOW)&&(digitalRead(BLUEPB) == LOW)&&(digitalRead(WHITEPB) == HIGH)&&
(digitalRead(FADEPB) == LOW)&&(digitalRead(RESETPB) == LOW))
{
delay (10);
if ((digitalRead(REDPB) == LOW)&&(digitalRead(GREENPB) == LOW)&&(digitalRead(BLUEPB) == LOW)&&(digitalRead(WHITEPB) == HIGH)&&
(digitalRead(FADEPB) == LOW)&&(digitalRead(RESETPB) == LOW))
{
Serial.print("B4 = " );
Serial.println(HIGH);
return 4;
}
}
// Checking 'FADE' Push button, includes software debouncing
if ((digitalRead(REDPB) == LOW)&&(digitalRead(GREENPB) == LOW)&&(digitalRead(BLUEPB) == LOW)&&(digitalRead(WHITEPB) == LOW)&&
(digitalRead(FADEPB) == HIGH)&&(digitalRead(RESETPB) == LOW))
{
delay (10);
if ((digitalRead(REDPB) == LOW)&&(digitalRead(GREENPB) == LOW)&&(digitalRead(BLUEPB) == LOW)&&(digitalRead(WHITEPB) == LOW)&&
(digitalRead(FADEPB) == HIGH)&&(digitalRead(RESETPB) == LOW))
{
Serial.print("B5 = " );
Serial.println(HIGH);
return 5;
}
}
// Checking 'RESET' Push button, includes software debouncing
if ((digitalRead(REDPB) == LOW)&&(digitalRead(GREENPB) == LOW)&&(digitalRead(BLUEPB) == LOW)&&(digitalRead(WHITEPB) == LOW)&&
(digitalRead(FADEPB) == LOW)&&(digitalRead(RESETPB) == HIGH))
{
delay (10);
if ((digitalRead(REDPB) == LOW)&&(digitalRead(GREENPB) == LOW)&&(digitalRead(BLUEPB) == LOW)&&(digitalRead(WHITEPB) == LOW)&&
(digitalRead(FADEPB) == LOW)&&(digitalRead(RESETPB) == HIGH))
{
Serial.print("B6 = " );
Serial.println(HIGH);
return 6;
}
}
return 0;
}
//Crossfade subroutine
void Crossfade()
{
while(FADE == 1)
{
unsigned int rgbColour[3];
// Start off with red.
rgbColour[0] = 255;
rgbColour[1] = 0;
rgbColour[2] = 0;
// Choose the colours to increment and decrement.
for (int decColour = 0; decColour < 3; decColour += 1)
{
int incColour = decColour == 2 ? 0 : decColour + 1;
// cross-fade the two colours.
for(int i = 0; i < 255; i += 1)
{
rgbColour[decColour] -= 1;
rgbColour[incColour] += 1;
setColourRgb(rgbColour[0], rgbColour[1], rgbColour[2]);
delay(FADESPEED);
if (digitalRead(RESETPB) == HIGH)
{
delay (10);
if (digitalRead(RESETPB) == HIGH)
{
FADE = 0;
break; //Breaks out of crossfade if RESETPB is pressed - includes software debouncing
}
}
}
}
}
}
//Writing RGB PWM output values
void setColourRgb(unsigned int red, unsigned int green, unsigned int blue)
{
analogWrite(REDPIN, red);
analogWrite(GREENPIN, green);
analogWrite(BLUEPIN, blue);
}
As always, my work is open for critique so if you think I could have done something better please let me know in the comments.
-
Ordering Parts
10/19/2014 at 20:10 • 0 commentsHaving sketched up the basics of the design in one of my many 'FIELD NOTES' notebooks, I always seem to have a pile of active ones, I was able to write up a list of the parts that I thought I would need for the project. Bearing in mind that I had no parts on hand and would have to get anything that I needed and I didn't want to have excess leftover that I would have to deal with when I leave Denmark at the end of the year. So at the very least I needed:
- Arduino Uno;
- Breadboard;
- Breadboard Jumper Wires;
- Tactile Push Buttons;
- TIP31 Power Transistors;
- 100Ω Resistors;
- 10KΩ Resistors;
- Hookup Wire;
- 12V 5A Power Suppy;
- RGBW LED Strip – About five meters worth;
With this list inhand I turned to my old friends 'ebay', 'Deal Extreme' and 'Banggood' (Which despite its questionable name is a very useful DX type supplier) in search of economically priced parts for my project. Having researched the import requirements for New Zealand in the past I had developed a 'safe figure' of $200 (US$160), and knew that anything under that had no customs requirements. I had no such 'safe figure' for Denmark, after some digging on the internet I discovered that in order to avoid 23% VAT being charged at the border I needed to keep my orders below 80kr. That's about USD $13, so not a lot to play with, especially given that I needed a five meter roll of RGBW LED strip.
After some clever splitting and staggering of orders I had parts on the way and I could focus on developing the code, and some hardware schematics while I waited. Shipping from china was meant to take less the 30 days, so I had some time.