Advertisement
bradwood

LEDLight

Jun 10th, 2013
31
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.91 KB | None | 0 0
  1. /*
  2.     LEDLightFamily -- Parent Module
  3.     Created 2013-03-19 by Bradley Wood
  4.     $Id:: Parent.ino 1918 2013-06-03 22:59:21Z                              $:
  5.     $Date:: 2013-06-03 23:59:21 +0100 (Mon, 03 Jun 2013)                    $:
  6.  
  7. Copyright (c) 2013 Bradley Wood
  8. Released as Open Source under GNU GPL v3, see <http://www.gnu.org/licenses/>
  9.  
  10. This project is to design an LED-driven light cube family -- I am planning one
  11. parent and two kids, although, you could add more children.
  12.  
  13. The parent has the following:
  14. * Arduino Pro Mini 3V3 (8MHz)
  15. * MMA 8452 3-axix accelerometer breakout board
  16. * (a gyro would be nice too)
  17. * An RF transmitter
  18. * 3 super bright LEDs, one red, one green, one blue
  19. * a Pololu low voltage power switch
  20. * (a wake-on-shake breakout would also be cool)
  21. * Portable power pack (9V battery, for now)
  22.  
  23. The kid has exactly the same, but an RF receiver, rather than a transmitter.
  24.  
  25. All gear available from proto-pic.co.uk
  26.  
  27. Function: the parent light (mum) can have its colour/brightness changed by
  28. tilting, moving, shaking or twisting or "dropping". It transmits its RGB value
  29. over RF. The kids pick it up and fade their own lights into sync with mum.
  30. Kids can also operate as independent lights, similar to their mum.
  31.  
  32. */
  33.  
  34. //DEBUG code -- remove this compiler directive to turn of Serial debug msgs
  35. #define DEBUG
  36.  
  37. #define DEBUGPRINTING             \
  38.     Serial.print("S=");           \
  39.     Serial.print(sat,4);          \
  40.     Serial.print("\t");           \
  41.     Serial.print("H=");           \
  42.     Serial.print(hue,4);          \
  43.     Serial.print("\t");           \
  44.     Serial.print("V=");           \
  45.     Serial.println(brightness,4); \
  46.     Serial.print("R=");           \
  47.     Serial.print(red);            \
  48.     Serial.print("\t");           \
  49.     Serial.print("G=");           \
  50.     Serial.print(green);          \
  51.     Serial.print("\t");           \
  52.     Serial.print("B=");           \
  53.     Serial.println(blue);         \
  54.     Serial.print("R'=");          \
  55.     Serial.print(g_red);          \
  56.     Serial.print("\t");           \
  57.     Serial.print("G'=");          \
  58.     Serial.print(g_green);        \
  59.     Serial.print("\t");           \
  60.     Serial.print("B'=");          \
  61.     Serial.println(g_blue);
  62.  
  63.  
  64. //All common functions used by either Parent or Child (as well as some specific
  65. //to either the Child or the Parent)
  66. #include <LEDLightFamilyHelper.h>
  67.  
  68. //OPERATING MODES
  69.  
  70. //these are cycled through via trapping a tap in any dimention using the
  71. //tap handler capability of the accelerometer
  72.  
  73. #define NUM_MODES           4 // 3 modes for now
  74.  
  75. #define MODE_FREE_COLOR     0 // free hue & sat change by tilt
  76. #define MODE_FULL_LOCK      1 // hue, sat and value (intensity) locked
  77. #define MODE_COLORCYCLE     2 // gently cycle through the colour wheel (mood-light mode)
  78. #define MODE_AUDIO          3 // audio response mode
  79.  
  80. #define MODE_COLORCYCLE_SPEED   20 // no of milliseconds delay before moving to next degree of hue.
  81.  
  82. int mode = MODE_AUDIO; //start out in free colour mode
  83.  
  84. #define MODE_SWITCH_PIN     16 //Pin A2
  85.  
  86. //=== Debounce setup =====
  87. boolean LastButtonState = HIGH; //the state of the button last time we checked
  88. boolean CurrentButtonState = HIGH; //the current reading from the button pin
  89. #define Debounce_Delay  5 //milliseconds
  90.  
  91. //WAKE SLEEP states
  92. #define STATE_WAKE  0
  93. #define STATE_SLEEP 1
  94.  
  95. int state = STATE_WAKE; //start out awake
  96.  
  97. // PROGRAMMATIC TURN-OFF
  98. // if R, G & B go to zero and sleep has kicked in fo a specified
  99. //elapsed time, then turn off the device completely be send a signal to the
  100. // pololu switch.
  101.  
  102. #define OFFPin      4  //set high to turn the whole device off
  103. #define OFF_TIMEOUT 60000 // ~1 minute
  104. unsigned long offtime; //set to millis() when (R,G,B) = (0,0,0)
  105.  
  106. //LEDs
  107. #define RedLED      5
  108. #define GreenLED    6
  109. #define BlueLED     9
  110.  
  111. //AUDIO
  112. //===MSGEQ7 configs===
  113. //Set up variables for MSGEQ7 input
  114. const int EQAnalogPin = 15; // read from multiplexer using A1
  115. const int EQStrobePin = 10; // strobe is attached to 10
  116. const int EQResetPin = 14; // reset is attached to digital pin A0
  117. int EQSpectrumValue[7]; // to hold a2d values from MSGEQ7
  118. const int EQLowerMapBound = 150; // Set the lower threshold for map() to reduce noise when "silent"
  119. const int EQUpperMapBound = 1023; // Set the upper threshold for map() to reduce noise when "silent"
  120.  
  121.  
  122. // RF CONFIG
  123.  
  124.  /* Pins:
  125.  * Hardware SPI:
  126.  * MISO -> 12
  127.  * MOSI -> 11
  128.  * SCK -> 13
  129.  *
  130.  * Configurable:
  131.  * CE -> 8
  132.  * CSN -> 7
  133.  */
  134.  
  135. #include <SPI.h>
  136. #include <Mirf.h>
  137. #include <nRF24L01.h>
  138. #include <MirfHardwareSpiDriver.h>
  139.  
  140. #define TX_ON   0
  141. #define TX_OFF  1
  142. #define TXADDR "CHIL1" //the address we are sending to.
  143. //#define RXADDR "CHIL1"
  144.  
  145. int TX_state = TX_ON;
  146. byte buf[4];
  147.  
  148. //ACCELEROMETER
  149. /*
  150. Note: The MMA8452 is an I2C sensor, however this code does not make use of
  151. the Arduino Wire library. Because the sensor is not 5V tolerant, we can't use
  152. the internal pull-ups used by the Wire library. Instead use the included i2c.h
  153. file.
  154. */
  155.  
  156. #include <Accelerometer.h>
  157. #include <math.h>
  158. #include <i2c.h>
  159.  
  160. #define SA0 1  // Breakout board defaults to 1, set to 0 if SA0 jumper is set
  161. #if SA0
  162.     #define MMA8452_ADDRESS 0x1D  // SA0 is high, 0x1C if low
  163. #else
  164.     #define MMA8452_ADDRESS 0x1C
  165. #endif
  166. /* Set the scale below either 2, 4 or 8*/
  167. const byte AccelScale = 2;  // Sets full-scale range to +/-2, 4, or 8g. Used to calc real g values.
  168. /* Set the output data rate below. Value should be between 0 and 7*/
  169. const byte AccelDataRate = 6;  // 0=800Hz, 1=400, 2=200, 3=100, 4=50, 5=12.5, 6=6.25, 7=1.56
  170. // low sample rate to conserve battery.
  171. /* Pin definitions */
  172. const int AccelInt1Pin = 2;  // used for x, y, z accel data
  173. const int AccelInt2Pin = 3;  // used for all other interrupts (tap, wake/sleep, portrait/landscape, etc)
  174.  
  175. byte accelData[6];  // x/y/z accel register data store here
  176. int accelCount[3];  // Stores the 12-bit signed value
  177. float accelValue[3];  // Stores the real accel value in g's
  178.  
  179. //stores the real accel values in g's, but smoothed out using a LP
  180. //filter/moving average.
  181. float smoothedValue[3];
  182. const float LPF_RC = 0.6; // value between 0 and 1 used for LP filter. 0 = no filtering. 1 equals = no reading.
  183. const int TiltSensitivity = 300; // The higher the number, the less tilt required.
  184.  
  185. /*
  186. Color changes will work by tracking the object's "tilt" in 3D-space using
  187. the accelerometers x, y vectors. The tilt will be mapped to a 2D vector
  188. which will determine the hue and saturation.
  189. in HSB cyclindrical space with the vector's  x- and y-components determining the
  190. hue and the degree of tilt from the horizontal determining the saturation.
  191.  
  192. */
  193. byte red,g_red,green,g_green,blue,g_blue; // number to be sent to each LED to drive PWM setting. 0-1023
  194. float hue = 0.0; // will hold an angle --
  195. float sat, brightness = 0.0; //will hold saturation (0-254) and brightness (height)
  196.  
  197. unsigned int hi, si, bi; //integer versions of hue, saturation and brightness.
  198.  
  199. void setup ()
  200. {  
  201.     #if defined DEBUG
  202.         Serial.begin(115200);
  203.         Serial.println("PARENT");
  204.     #endif
  205.  
  206.     //set up mode Pin using internal pull
  207.     pinMode(MODE_SWITCH_PIN,INPUT);
  208.     digitalWrite(MODE_SWITCH_PIN,HIGH); //turn on pullup
  209.    
  210.     // make sure the off pin is low.
  211.     pinMode(OFFPin,OUTPUT);
  212.     digitalWrite(OFFPin,LOW);
  213.    
  214.     //initialise RF infrastucture
  215.     Mirf.spi = &MirfHardwareSpi;
  216.     Mirf.init();
  217.     Mirf.setTADDR((byte *)TXADDR);
  218.  
  219.     //set up LED pins
  220.     pinMode(RedLED, OUTPUT);
  221.     pinMode(GreenLED, OUTPUT);
  222.     pinMode(BlueLED, OUTPUT);
  223.  
  224.     /* Set up the interrupt pins, they're set as active high, push-pull */
  225.     pinMode(AccelInt1Pin, INPUT);
  226.     digitalWrite(AccelInt1Pin, LOW);
  227.     pinMode(AccelInt2Pin, INPUT);
  228.     digitalWrite(AccelInt2Pin, LOW);
  229.  
  230.     //initialise EQ chip
  231.     initMSGEQ7(EQAnalogPin, EQStrobePin, EQResetPin);
  232.    
  233.     //initialise and calibrate the accelerometer
  234.     initMMA8452(AccelScale, AccelDataRate);
  235.     CalibrateAccel();
  236. }
  237.  
  238. void loop()
  239. {
  240.     if(ModeButtonPressed(LastButtonState,CurrentButtonState,MODE_SWITCH_PIN,Debounce_Delay))
  241.     {
  242.         #if defined DEBUG
  243.             Serial.println("Mode changed (button press).");
  244.         #endif
  245.         //cycle the Mode variable to the next mode.
  246.         changeMode(mode, NUM_MODES);
  247.         //flash a number of times to ack the mode change...
  248.         FlashLights(1,RedLED, GreenLED, BlueLED, g_red,g_green,g_blue);    
  249.     }
  250.    
  251.     //read Int2 on the accelerometer and then set mode and wake/sleep accordingly
  252.     static byte accel_event_int_register;
  253.     /* If int2 goes high, a trappable event has occured */
  254.     //TODO: Sort out PortraitLandscape wake/sleep trigger
  255.     if (digitalRead(AccelInt2Pin))
  256.     {
  257.         accel_event_int_register = readRegister(INT_SOURCE_REG);  // Read the interrupt source reg.
  258.         if ((accel_event_int_register & SRC_PULSE_MASK)==SRC_PULSE_MASK)  // // tap event triggered
  259.         {
  260.             #if defined DEBUG
  261.                 Serial.println("--------------TAP TAP TAP TAP TAP --------------");
  262.             #endif
  263.             tapHandler();
  264.             //FlashLights(mode+1,RedLED, GreenLED, BlueLED, g_red,g_green,g_blue);     
  265.         }
  266.        
  267.         if ((accel_event_int_register & SRC_ASLP_MASK)==SRC_ASLP_MASK) // sleep/wake event triggered
  268.             #if defined DEBUG
  269.                 Serial.println("-------------WAKE SLEEP WAKE SLEEP----------------");
  270.             #endif
  271.            
  272.             wakesleepHandler(state); //set state accordingly.
  273.  
  274.         if((accel_event_int_register & SRC_FF_MT_1_MASK)==SRC_FF_MT_1_MASK) //motion detected
  275.         {
  276.             #if defined DEBUG
  277.                 Serial.println("-------------MOTION MOTION MOTION----------------");
  278.             #endif
  279.            
  280.             motionHandler(); //read the register to clear the latch, this should force WAKE mode.
  281.         }
  282.        
  283.         if((accel_event_int_register & SRC_LNDPRT_MASK)==SRC_LNDPRT_MASK) //portrait/landscape detected
  284.         {
  285.             #if defined DEBUG
  286.                 Serial.println("-------------PORTRAIT LANDSCAPE----------------");
  287.             #endif
  288.             portraitLandscapeHandler();
  289.         }
  290.     }  
  291.     // now handle the wake and sleep modes separately
  292.     switch (state)
  293.     {
  294.         case STATE_WAKE:
  295.            
  296.             //turn on RF TX infrastruture.
  297.             setTX(TX_ON);
  298.             #if defined DEBUG
  299.                 Serial.println("WAKE");
  300.             #endif
  301.  
  302.             switch (mode)
  303.             {
  304.                 case MODE_FREE_COLOR:
  305.                     #if defined DEBUG
  306.                         Serial.println("MODE_FREE_COLOR");
  307.                     #endif
  308.                     /* If int1 goes high, all data registers have new data */
  309.                     if (digitalRead(AccelInt1Pin))  // Interrupt pin, should probably attach to interrupt function
  310.                     {
  311.                         readRAWAccel(accelValue);
  312.  
  313.                         SmoothAccel(LPF_RC, accelValue, smoothedValue);
  314.  
  315.                         CalcSat_n_Hue(TiltSensitivity, smoothedValue[0], smoothedValue[1],  sat, hue);
  316.  
  317.                         //force full brightness in the this mode.
  318.                         brightness = 100.0;
  319.                        
  320.                         HSV_to_RGB(hue,sat,brightness,red,green,blue);
  321.  
  322.                         g_red = gamma_correction(red);
  323.                         g_green = gamma_correction(green);
  324.                         g_blue = gamma_correction(blue);
  325.  
  326.                         DEBUGPRINTING;
  327.  
  328.                         //turn on the LEDs
  329.                         ShowLight(RedLED, GreenLED, BlueLED, g_red,g_green,g_blue);
  330.  
  331.                         //transmit RGB codes -- 3 bytes for R,G,B
  332.                         buf[0] = g_red; buf[1] = g_green; buf[2] = g_blue;
  333.                         buf[3] = 0xAA; //TODO: use for command byte
  334.                         TXAccel(buf,state);
  335.                     }
  336.                 break;
  337.  
  338.                 case MODE_FULL_LOCK:
  339.                     #if defined DEBUG
  340.                         Serial.println("MODE_FULL_LOCK");
  341.                     #endif
  342.                    
  343.                     DEBUGPRINTING;
  344.                    
  345.                     //turn on the LEDs
  346.                     ShowLight(RedLED, GreenLED, BlueLED, g_red,g_green,g_blue);
  347.  
  348.                     //transmit RGB codes -- 3 bytes for R,G,B
  349.                     buf[0] = g_red; buf[1] = g_green; buf[2] = g_blue;
  350.                     buf[3] = 0xAA; //TODO: use for command byte
  351.                     TXAccel(buf,state);
  352.                    
  353.                 break;
  354.                                
  355.                 case MODE_COLORCYCLE:
  356.                     //gently cycle through colour where -- no accel in this mode.
  357.                    
  358.                     #if defined DEBUG
  359.                         Serial.println("MODE_COLORCYCLE");
  360.                     #endif
  361.  
  362.                     //force full brightness in the this mode.
  363.                     brightness = 100.0;
  364.                     sat = 100.0;
  365.                    
  366.                     cycleHue(hue,MODE_COLORCYCLE_SPEED);
  367.                     HSV_to_RGB(hue,sat,brightness,red,green,blue);
  368.  
  369.                     g_red = gamma_correction(red);
  370.                     g_green = gamma_correction(green);
  371.                     g_blue = gamma_correction(blue);
  372.  
  373.                     DEBUGPRINTING;
  374.  
  375.                     //turn on the LEDs
  376.                     ShowLight(RedLED, GreenLED, BlueLED, g_red,g_green,g_blue);
  377.  
  378.                     //transmit RGB codes -- 3 bytes for R,G,B
  379.                     buf[0] = g_red; buf[1] = g_green; buf[2] = g_blue;
  380.                     buf[3] = 0xAA; //TODO: use for command byte
  381.                     TXAccel(buf,state);
  382.                 break;
  383.  
  384.                 case MODE_AUDIO:
  385.                     //read the mic and display a color accordingly..
  386.                    
  387.                     #if defined DEBUG
  388.                         Serial.println("MODE_AUDIO");
  389.                     #endif
  390.                    
  391.                     readEQ(EQResetPin, EQStrobePin, EQAnalogPin, EQSpectrumValue);
  392.                                        
  393.                     EQ_to_RGB(EQSpectrumValue,EQLowerMapBound,EQUpperMapBound,red,green,blue);
  394.                    
  395.                     g_red = gamma_correction(red);
  396.                     g_green = gamma_correction(green);
  397.                     g_blue = gamma_correction(blue);
  398.  
  399.                     DEBUGPRINTING;
  400.  
  401.                     //turn on the LEDs
  402.                     ShowLight(RedLED, GreenLED, BlueLED, g_red,g_green,g_blue);
  403.  
  404.                     //transmit RGB codes -- 3 bytes for R,G,B
  405.                     buf[0] = g_red; buf[1] = g_green; buf[2] = g_blue;
  406.                     buf[3] = 0xAA; //TODO: use for command byte
  407.                     TXAccel(buf,state);
  408.                 break;
  409.             }
  410.  
  411.         break;
  412.        
  413.         case STATE_SLEEP:
  414.             #if defined DEBUG
  415.                 Serial.println("SLEEP");
  416.             #endif
  417.            
  418.             //turn on RX infrastructure.
  419.             setTX(TX_ON);
  420.            
  421.             switch (mode)
  422.             {
  423.                 case MODE_FREE_COLOR:
  424.                     #if defined DEBUG
  425.                         Serial.println("MODE_FREE_COLOR");
  426.                     #endif
  427.                     /* If int1 goes high, all data registers have new data */
  428.                     if (digitalRead(AccelInt1Pin))  // Interrupt pin, should probably attach to interrupt function
  429.                     {
  430.                         readRAWAccel(accelValue);
  431.  
  432.                         SmoothAccel(LPF_RC, accelValue, smoothedValue);
  433.  
  434.                         CalcSat_n_Hue(TiltSensitivity, smoothedValue[0], smoothedValue[1],  sat, hue);
  435.  
  436.                         //force full brightness in the this mode.
  437.                         brightness = 100.0;
  438.                        
  439.                         HSV_to_RGB(hue,sat,brightness,red,green,blue);
  440.  
  441.                         g_red = gamma_correction(red);
  442.                         g_green = gamma_correction(green);
  443.                         g_blue = gamma_correction(blue);
  444.  
  445.                         DEBUGPRINTING;
  446.  
  447.                         //turn on the LEDs
  448.                         ShowLight(RedLED, GreenLED, BlueLED, g_red,g_green,g_blue);
  449.  
  450.                         //transmit RGB codes -- 3 bytes for R,G,B
  451.                         buf[0] = g_red; buf[1] = g_green; buf[2] = g_blue;
  452.                         buf[3] = 0xAA; //TODO: use for command byte
  453.                         TXAccel(buf,state);
  454.                     }
  455.                 break;
  456.  
  457.                 case MODE_FULL_LOCK:
  458.                     #if defined DEBUG
  459.                         Serial.println("MODE_FULL_LOCK");
  460.                     #endif
  461.                     DEBUGPRINTING;
  462.                     //transmit RGB codes -- 3 bytes for R,G,B
  463.                     buf[0] = g_red; buf[1] = g_green; buf[2] = g_blue;
  464.                     buf[3] = 0xAA; //TODO: use for command byte
  465.                     TXAccel(buf,state);
  466.                 break;
  467.                            
  468.                 case MODE_COLORCYCLE:
  469.                     //gently cycle through colour where -- no accel in this mode.
  470.  
  471.                     #if defined DEBUG
  472.                         Serial.println("MODE_COLORCYCLE");
  473.                     #endif
  474.  
  475.                     //force full brightness in the this mode.
  476.                     brightness = 100.0;
  477.                     sat = 100.0;
  478.                
  479.                     cycleHue(hue,MODE_COLORCYCLE_SPEED);
  480.                     HSV_to_RGB(hue,sat,brightness,red,green,blue);
  481.  
  482.                     g_red = gamma_correction(red);
  483.                     g_green = gamma_correction(green);
  484.                     g_blue = gamma_correction(blue);
  485.  
  486.                     DEBUGPRINTING;
  487.  
  488.                     //turn on the LEDs
  489.                     ShowLight(RedLED, GreenLED, BlueLED, g_red,g_green,g_blue);
  490.  
  491.                     //transmit RGB codes -- 3 bytes for R,G,B
  492.                     buf[0] = g_red; buf[1] = g_green; buf[2] = g_blue;
  493.                     buf[3] = 0xAA; //TODO: use for command byte
  494.                     TXAccel(buf,state);
  495.                
  496.                 break;
  497.  
  498.                 case MODE_AUDIO:
  499.                     //read the mic and display a color accordingly..
  500.                    
  501.                     #if defined DEBUG
  502.                         Serial.println("MODE_AUDIO");
  503.                     #endif
  504.                    
  505.                     readEQ(EQResetPin, EQStrobePin, EQAnalogPin, EQSpectrumValue);
  506.                                        
  507.                     EQ_to_RGB(EQSpectrumValue,EQLowerMapBound,EQUpperMapBound,red,green,blue);
  508.                    
  509.                     g_red = gamma_correction(red);
  510.                     g_green = gamma_correction(green);
  511.                     g_blue = gamma_correction(blue);
  512.  
  513.                     DEBUGPRINTING;
  514.  
  515.                     //turn on the LEDs
  516.                     ShowLight(RedLED, GreenLED, BlueLED, g_red,g_green,g_blue);
  517.  
  518.                     //transmit RGB codes -- 3 bytes for R,G,B
  519.                     buf[0] = g_red; buf[1] = g_green; buf[2] = g_blue;
  520.                     buf[3] = 0xAA; //TODO: use for command byte
  521.                     TXAccel(buf,state);
  522.                 break;
  523.             }
  524.         break;
  525.     }
  526.    
  527. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement