Alright!
Arduino IS a great thing indeed!
My project changed a bit with some limitations, but still, in less than a month I went from "What's Arduino?" to getting the job done... I was able to upgrade it to 3 channels (3 doors, 3 lights/led strips) to only one chip; and shrunk it down to an ATTiny45 instead of my original plan of putting as much 555 timers as needed first...
I achieved it with this config:
ATTiny 45/85: (fused at 8mhz for software PWM)
| (note pins numbers are Arduino pins and not package pins)
|--Pin 0-- Vref
|--Pin 1-- Led chan1 output
|--Pin 2-- Led chan2 output
|--Pin 3-- Analog input with 3 switches (and resistors as voltage dividers: 18k pulldown to GND, ch1:22k ch2:47k ch3:94k to Vref)
|--Pin 4-- Led chan3 output
And wrote this from scratch: (I know... ain't optimized, some parts are bit messy, but truly works well and smooth)
// NOTE: FOR ATTiny25/45/84, you MUST "Burn bootloader" and set fuses to 8 Mhz with Arduino as ISP for optimal performances...
// Even though ATTiny doesn't have an official bootloader, It will set the speed to higher, better value.
// otherwise, you might see a lot of LED flickering
// More infos on setting the fuses: http://forum.arduino.cc/index.php?topic=83623.0
//
// Original code: Pierre-Olivier Bisson, March 2014
// Version: 1.0.0.1
// Open Source, but please leave original credit and add you own. Thank you!
#define onState HIGH //Change to LOW if LED is Common -
#define offState LOW //Change to HIGH if LED is Common -
#define mcuRes 32 //Defines CPU micros() resolution... 1mhz = 64, 2mhz = 32, 4mhz = 16, 8mhz = 8... etc
#define pwmRes 192 // Defines adjustables "Levels"; namely duty cycle resolution... higher level, slower speed... (MAX 255)
#define slewRate 5 //defines "slowing" factor for the fade time... "1" is the fastest, if you want to be faster, lower the pwmRes.
// to calculate aprox fade time with original code: mcuRes * pwmRes * slewRate = total time in uSeconds
#define AInputPin 3 //will be the Analog Input pin (3-4 for ATTiny 25/45/85)
#define falseReadTreshold 5 //to avoid false detection of a switch, and leds flashing without any reason...
#define redPin 1
#define greenPin 2
#define bluePin 4
unsigned long calendar1 = 0L;
unsigned long duty1 = 0L;
boolean rStatus = 0;
boolean gStatus = 0;
boolean bStatus = 0;
int redDim = 0;
int greenDim = 0;
int blueDim = 0;
/////////////////////////////////////////////////////////////////////////SETUP////////////////////////////////////////////////////////////////
void setup() {
analogReference(EXTERNAL); //On attiny 25/45/85 Will use Digital Pin 0 as Vref to compare voltage of the input pin
// pinMode(AInputPin, INPUT);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
//Nice "Boot sequence" :) ...
digitalWrite(redPin, onState);
delay(1000);
digitalWrite(greenPin, onState);
delay(1000);
digitalWrite(bluePin, onState);
delay(2000);
digitalWrite(redPin, offState);
digitalWrite(greenPin, offState);
digitalWrite(bluePin, offState);
}
/////////////////////////////////////////////////////////////////////END SETUP////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////LOOOOOOP////////////////////////////////////////////////////////////////
void loop()
{
//code here to execute once every calendar...
calendar1 = (micros() + ((mcuRes * pwmRes) * slewRate) );
//insert/change switch check function here
//insert/change Dimming increments and/or function calls here
byte inValue = (inputSwitchesState(AInputPin)); //Calls fuction to read 3 switches pulled on voltage dividers (high or low) and returns binary (00001111) values... 8 to 15=error
setDim(inValue); //Adjust Global Dimming variables...
while (calendar1 > micros()) {
duty1 = (micros() + (mcuRes * pwmRes));
while (duty1 > micros()){
unsigned long currentMicros = micros();
////Since micros() fuction reset after 71 hours, we want to avoid a complete crash every 71 hours with this condition:
if ( duty1 >= (4284967295)) {
calendar1=0;
duty1=0;
}
if ( calendar1 >= (4284967295)) {
calendar1=0;
duty1=0;
}
//and reset flags if micros() reseted
//Note: improvement could be made, since this one causes a 10 seconds freeze (or so with std parameters) every 3 days...
///////////////////////////////////////////////////////////////////////////////////////////
//////////////////////RED/////////////////////////
if ((currentMicros+(mcuRes * redDim)) <= duty1 ){
if (rStatus == 0){
digitalWrite(redPin, offState);
rStatus =1;
}
}
else{
if ((rStatus == 1)&&(redDim>falseReadTreshold)){
digitalWrite(redPin, onState);
rStatus =0;
}
}
//////////////////////END RED/////////////////////
//////////////////////GREEN/////////////////////////
if ((currentMicros + (mcuRes * greenDim)) <= duty1 ){
if (gStatus == 0){
digitalWrite(greenPin, offState);
gStatus =1;
}
}
else{
if ((gStatus == 1)&&(greenDim>falseReadTreshold)){
digitalWrite(greenPin, onState);
gStatus =0;
}
}
//////////////////////END GREEN/////////////////////
//////////////////////BLUE/////////////////////////
if ((currentMicros+(mcuRes * blueDim)) <= duty1 ){
if (bStatus == 0){
digitalWrite(bluePin, offState);
bStatus =1;
}
}
else{
if ((bStatus == 1)&&(blueDim>falseReadTreshold)){
digitalWrite(bluePin, onState);
bStatus =0;
}
}
//////////////////////END Blue/////////////////////
}//End of duty1
}//end of calendar1
}
///////////////////////////////////////////////////////END LOOP///////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////SUB ROUTINES///////////////////////////////////////////////////////////
void setDim(byte inValue)
{
if (bitRead (inValue, 0)) //red channel switch flag at binary position 0
{
if (redDim <= pwmRes) {
redDim++;
}
}
else
{
if (redDim >=1) {
redDim--;
}
};
if (bitRead (inValue, 1)) //green channel switch flag at binary position 1
{
if (greenDim <= pwmRes) {
greenDim++;
}
}
else
{
if (greenDim >=1) {
greenDim--;
}
}
if (bitRead (inValue, 2)) //blue channel switch flag at binary position 2
{
if (blueDim <= pwmRes) {
blueDim++;
}
}
else
{
if (blueDim >=1) {
blueDim--;
}
}
}
/* inputSwitchesState
// Based on custom project, returns values on 3 voltage dividers based switches and possible combinations. Returns 0 to 7 (or 0000 to 0111)
// Resistor values are: Pulldown: 18k, Switch 1: 22k, Switch 2: 47k, Switch 3: 94k (or x2 47k)
// NOTE: USE PRECISION RESISTORS, AS 5% Tolerance may give unstable results!! 1% tolerance recommended.
// Or, at least, measure the resistors you are installing to take the ones with SPOT ON the values...
//
// ALSO, use EXTERNAL Vref on your chip, instead of the internal one, otherwise results will vary.
//
// Here, ELSE IF is used to accelerate the function, that will end as soon as the correct value was found...
*/
byte inputSwitchesState(byte pin)
{
int sensorValue = analogRead(pin);
byte retValue = 0;
if (sensorValue < 82) {
retValue = 0;
} //0= no switch pulled high whatsoever
else if ((sensorValue >=82) && (sensorValue < 223)) {
retValue = 4;
} //0100 SW 3 pulled high CHECK
else if ((sensorValue >=223) && (sensorValue < 327)) {
retValue = 2; //CHECK
} //0010 SW 2 pulled high
else if ((sensorValue >=327) && (sensorValue < 415)) {
retValue = 6; //CHECK
} //0110 SW 2+3 pulled high
else if ((sensorValue >=415) && (sensorValue < 486)) {
retValue = 1; //CHECK
} //0001 SW 1 pulled high
else if ((sensorValue >=486) && (sensorValue < 534)) {
retValue = 5; //CHECK
} //0101 SW 1+3 pulled high
else if ((sensorValue >=534) && (sensorValue < 575)) {
retValue = 3; //CHECK
} //0011 SW 1+2 pulled high
else if ((sensorValue >=575) && (sensorValue < 640)) {
retValue = 7; //CHECK
} //0111 SW 1+2+3 pulled high
else if (sensorValue >=640) {
retValue = 15; //CHECK
} //1111 ErrorCode, actual resistor values don't permit higher values that 640...
return(retValue);
};
The whole thing should in theory run with a ATTiny 25 @ 8mhz as it only takes 1.8k once compiled, but I don't know about Ram and other specs.. (If anyone wants to try... ;D I only have 85's here at the moment)
Gotta be addicted to Arduinos now... I can't wait to install that!
**Edit: 2014-03-19 Updated code, Major bug 1.0.0.0 crashed