Paso 5: Código fuente listado
//DIY Fake TV
//Keep burglars at bay while you are away
//Created by Jonathan Bush //Last Updated 3/24/2015 //Runnig on ATTiny 85
//Modified 8/4/2015 by Mark Werley for Trinket Pro //Rewritten to avoid the use of the delay() function //Initialized MAXBRIGHT to 255, the maximum //Added the use of the multiMAP function to convert a uniform distribution to something nonuniform //Added an auto-off feature so the LEDs go dark after a certain amount of time //Added a soft reboot feature after 24 hours, so the show starts up again every day at the same time //Added a blink on the builtin LED, so user can tell program is still running when neopixels are off
#include <Adafruit_NeoPixel.h>
#define PIN 3 //PIN 3 "runs" the NeoPixels. Works on Uno or Trinket Pro #define ledPin 13 //PIN 13 has built-in LED for Uno or Trinket Pro
#define buttonPin 4 //PIN 4 has a button attached through a 10k pullup resister
int ledState = LOW; //Keep track of the state of the built-in LED int buttonState = 0; //Keep tract of the state of the button int endShow = false; //True when the show is over
int POTPIN = A1; //1st analog pot pin, used for adjusting brightness int POTPIN2 = A2; //2nd analog pot pin, used for adjusting light show cut speed int POTPIN3 = A3; //3rd analog pot pin, used for adjust the runtime of the show
//Neopixel library provided by Adafruit, change 1st parameter to number of LEDs in your neopixels Adafruit_NeoPixel strip = Adafruit_NeoPixel(16, PIN, NEO_GRB + NEO_KHZ800);
int BRIGHTNESS = 0; int RED = 0; int BLUE = 0; int GREEN = 0; int TIMEDEL = 0; int mapTIMEDEL = 0; int MAXBRIGHT = 255; //set MAXBRIGHT to 255, the max, if no brightness pot int speedDivider = 1; //set speedDivider to 1, if no cut speed pot int potval = 0; int potval2 = 0; int potval3 = 0;
unsigned long runTimeMillis = 0; //How long the Fake TV light show will run in milliseconds int runTime = 120; //How long the Fake TV light show will run in minutes, 2 hours if no runTime pot unsigned long startMillis = 0; //The sampled starting time of the program, ususally just 0 or 1 milliseconds unsigned long previousMillis = 0; //Remember the number of milliseconds from the previous cut trigger unsigned long rebootTimeMillis = 0; //How long the program will run before a soft reset/reboot happens (24 hrs = 86,400,000 ms) unsigned long currentMillis = 0; //How long the program has run so far
int in[] = {200, 520, 840, 1160, 1480, 1800, 2120, 2440, 2760, 3080, 3400, 3720, 4040}; //This is just linear
// int out[] = {200,392,968,2120,3272,3848,4040,3848,3272,2120,968,392,200}; //normal distribution // int out[] = {200,392,2120,3848,4040,3848,3560,3272,2696,2120,968,392,200}; //LnNormal-ish // int out[] = {200,250,300,400,600,1200,4040,1200,600,400,300,250,200}; //made up int out[] = {200, 250, 300, 350, 400, 500, 600, 700, 800, 1200, 2000, 3000, 4040}; //made up #2
void setup() //Initialize everything { //Initialize the NeoPix strip.begin(); strip.show(); // Initialize all pixels to 'off' pinMode(PIN, OUTPUT); //set the neopixel control pin to output
pinMode(ledPin, OUTPUT); //set the onboard LED pin to output
pinMode(buttonPin, INPUT); //set the button pin to input
//Initialize the serial com, used for debugging on the Uno or Trinket Pro (w FTDI cable), comment out for production Serial.begin(9600); Serial.println("--- Start Serial Monitor SEND_RCVE ---"); Serial.println("Serial is active"); Serial.println(); rebootTimeMillis = 24ul * 60ul * 60ul * 1000ul; //hardcode reboot in 24 hours
startMillis = millis(); //sample the startup time of the program }
void loop() //Start the main loop { currentMillis = millis(); //sample milliseconds since startup
if (currentMillis > rebootTimeMillis) softReset(); //When rebootTimeMillis is reached, reboot // Let's read our sensors/controls
potval = analogRead(POTPIN); //Reads analog value from brightness Potentiometer/voltage divider, comment out if not using MAXBRIGHT = map(potval, 0, 1023, 11, 255); //Maps voltage divider reading to set max brightness btwn 11 and 255, comment out if not using
potval2 = analogRead(POTPIN2); //Reads analog value from cut speed Potentiometer, comment out if not using speedDivider = map(potval2, 0, 1020, 1, 8); //Maps the second pot reading to between 1 and 8, comment out if not using potval3 = analogRead(POTPIN3); //Reads analog valuse from show lenth Potentiometer, comment out if not using runTime = map(potval3, 0, 1020, 15, 480); //Maps the third pot to between 15 and 480 minutes (1/4 to 6 hours), comment out if not using runTimeMillis= long(runTime) * 60ul * 1000ul; Serial.print("potval3="); Serial.print(potval3); Serial.print(" runTime="); Serial.print(runTime); Serial.print(" runTimeMillis="); Serial.println(runTimeMillis); buttonState = digitalRead(buttonPin); //Sample the state of the button if (buttonState == HIGH) endShow = true; //Button was pressed, time to end tonight's show
if ((currentMillis - previousMillis) > long(mapTIMEDEL)) //Test to see if we're due for a cut (lighting change) { BRIGHTNESS = random (10, MAXBRIGHT); //Change display brightness from 20% to 100% randomly each cycle RED = random (150 , 256); //Set the red component value from 150 to 255 BLUE = random (150, 256); //Set the blue component value from 150 to 255 GREEN = random (150, 256); //Set the green component value from 150 to 255 TIMEDEL = random (200, 4040); //Change the time interval randomly between 0.2 of a second to 4.04 seconds
mapTIMEDEL = multiMap(TIMEDEL, in, out, 13); //use the multiMap function to remap the delay to something non-uniform mapTIMEDEL = mapTIMEDEL / speedDivider; //Divide by speedDivider to set rapidity of cuts
if ((currentMillis - startMillis) > runTimeMillis) endShow = true; //runTimeMillis has expired, time to end tonight's show
if (endShow) //Show's over for the night, aw... strip.setBrightness(0); else //The show is on! strip.setBrightness(BRIGHTNESS);
colorWipe(strip.Color(RED, GREEN, BLUE), 0); //Instantly change entire strip to new randomly generated color
if (ledState == HIGH) //toggle the ledState variable ledState = LOW; else ledState = HIGH;
digitalWrite(ledPin, ledState); //Flip the state of (blink) the built in LED
previousMillis = currentMillis; //update previousMillis and loop back around } }
// Fill the dots one after the other with a color void colorWipe(uint32_t c, uint8_t wait) { for (uint16_t i = 0; i < strip.numPixels(); i++) { strip.setPixelColor(i, c); strip.show(); } }
// Force a jump to address 0 to restart sketch. Does not reset hardware or registers void softReset() { asm volatile(" jmp 0"); }
//multiMap is used to map one distribution onto another using interpolation // note: the _in array should have increasing values //Code by rob.tillaart int multiMap(int val, int* _in, int* _out, uint8_t size) { // take care the value is within range // val = constrain(val, _in[0], _in[size-1]); if (val <= _in[0]) return _out[0]; if (val >= _in[size - 1]) return _out[size - 1];
// search right interval uint8_t pos = 1; // _in[0] allready tested while (val > _in[pos]) pos++;
// this will handle all exact "points" in the _in array if (val == _in[pos]) return _out[pos];
// interpolate in the right segment for the rest return (val - _in[pos - 1]) * (_out[pos] - _out[pos - 1]) / (_in[pos] - _in[pos - 1]) + _out[pos - 1]; }