Orac - The Wrap-up
Here is a short video of my ORAC in action: SEE ORAC RUN.mkv 2.9MiB, h264, vorbis.
Here is a nice silent loop snipped from the middle of the above:
Well, I made it! Both figuratively and literally. Below is the complete code of the Arduino program. You will notice some variations to the sample snippets which were stripped to the minimum to enhance their value as examples. The below code needs a bit more of a clean-up which I hope to get to in the next few weeks, but it works fine.
int redChanValue = 0; // we randomly walk up and down the red channel brightness
int bluChanValue = 0; // we randomly walk up and down the blue channel brightness
int tickerValue = 0; // count the loops and switch the circumfrence LEDs every 8 loops
int count = 0; // throw-away variable to count loops in
int on = 0; // track if we are on (on-off state will lag the switch somewhat)
void setup()
{ pinMode(2, OUTPUT); // Red Ball Channel - "Analog" PCM output
pinMode(3, OUTPUT); // Blue Ball Channel - "Analog" PCM output
pinMode(4, OUTPUT); // Circumfrence LED Channel 1 - Digital output
pinMode(5, OUTPUT); // Circumfrence LED Channel 2 - Digital output
pinMode(6, OUTPUT); // Tick Channel - pulse this pin to advance lights
pinMode(7, OUTPUT); // Power Chanel - "HIGH" to have lights on. "Analog" PCM output is an option.
pinMode(8, INPUT); // Key inserted input
for(count=22; count <53; count+=2)
pinMode(count, OUTPUT); // set up all the even-numbered board-end outputs
}
void lightShow()
{ redChanValue += random(-16,16); // increase or decrease the output brightness by up to 16/256ths each cycle
if(redChanValue > 255) redChanValue = 255; // don't overflow the maximum permissible value
if(redChanValue <0 ) redChanValue = 0; // don't underflow the minimum permissible value
analogWrite(2, redChanValue);
bluChanValue += random(-16,16); // remember, adding a negative value is subtracting
if(bluChanValue > 255) bluChanValue = 255;
if(bluChanValue <0 ) bluChanValue = 0;
analogWrite(3, bluChanValue);
if(tickerValue == 0 ) // as tickerValue crosses 0, change the circumfrence LEDs
{ digitalWrite(4,HIGH);
digitalWrite(5,LOW);
}
if(tickerValue == -25 ) // as tickerValue is reset to -7, change the circumfrence LEDs
{ digitalWrite(4,LOW);
digitalWrite(5,HIGH);
}
tickerValue++; // Tick value will count from -25 to 25
if(tickerValue == 26 ) // when we overflow
tickerValue = -25; // go back to start
analogWrite(7, 255); // full brightness
digitalWrite(6,HIGH);
delay(50); // pause so the pulse exists long enough to register
digitalWrite(6,LOW);
digitalWrite(random(11,27)*2, random(2) ); // turn on or off a random tarriel cell LED state
tone(9,100+random(20)); // make the slightly-varying low-level buzzing noise characteristic to Orac
}
void powerUp()
{ on = 1;
tone(9, 2000); // start-tone - higher pitch pulse
delay(100);
for(count=1500; count >100; count-=100)
{ tone(9, count); // drop pitch to running hum
delay(10);
}
}
void killShow()
{ digitalWrite(4, 0); // turn off the circumfrence lights
digitalWrite(5, 0); // turn off the circumfrence lights
analogWrite(7, 0); // turn off the ring
for(count=22; count <53; count+=2)
digitalWrite(count, 0); // turn off all the tarriel cells
for(count=230; count >30; count-=5)
{ if(redChanValue > count-30)
{ redChanValue = count-30;
analogWrite(2, redChanValue); // fade out the ball red channel
}
if(bluChanValue > count-30)
{ bluChanValue = count-30;
analogWrite(3, bluChanValue); // fade out the ball red channel
}
if(count % 30 > 15)
tone(9, count); // kill-tone-low - pitch drops
else
tone(9, count*2); // kill-tone-high - modulate the dropping pitch up periodically
delay((250-count)/5); //taper out the timing too
}
noTone(9); // turn off sound completely
analogWrite(2, 0); // turn off the ball red channel
analogWrite(3, 0); // turn off the ball red channel
on = 0;
}
void loop()
{ if( digitalRead(8) == HIGH && on == 0) // key in unit off = startup
powerUp();
else if( digitalRead(8) == HIGH && on == 1) // key in unit on = keep running
lightShow();
else if( digitalRead(8) == LOW && on == 1) // key removed, unit on = shut down
killShow();
else
delay(100); // if we are all off, wait 1/10th of a second and check the switch again
}
Orac will likely never be entirely finished, as I will no-doubt find extra bits to glue into it, and will probably keep tweaking-away at the code from time to time as I learn new tricks in other projects. I will update these pages as appropriate in this case.
Hope you enjoyed sharing the creation and hope you can take away some useful ideas for your own projects.