Source code for the Curilights Controller. See http://www.saccade.com/writing/projects/CuriController/ for details.

Dependencies:   FatFileSystem mbed

This is the source code for the Curilights controller. This lets you interactively control a string of Curilights. It provides a simple click-wheel user interface for changing colors, brightness and behavior. It responds to movement and lighting.

Finished Controller

/media/uploads/isonno/nxp3872_controllerclose.jpg

System Block Diagram

/media/uploads/isonno/blockdiagram.png

Committer:
isonno
Date:
Thu Dec 29 01:59:53 2011 +0000
Revision:
0:6da5625a6946
Child:
1:d1da77023e6a
Contest submission version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
isonno 0:6da5625a6946 1 //
isonno 0:6da5625a6946 2 // CuriLights Controller firmware
isonno 0:6da5625a6946 3 //
isonno 0:6da5625a6946 4
isonno 0:6da5625a6946 5 #include "mbed.h" // Lives in http://mbed.org/projects/libraries/svn/mbed/trunk
isonno 0:6da5625a6946 6
isonno 0:6da5625a6946 7 #include "SerialConnect.h"
isonno 0:6da5625a6946 8 #include "ZMotionDetector.h"
isonno 0:6da5625a6946 9 #include "SDFileSystem.h"
isonno 0:6da5625a6946 10 #include "NokiaLCD.h"
isonno 0:6da5625a6946 11 #include "RotaryEncoder.h"
isonno 0:6da5625a6946 12 #include "HoldInterrupts.h"
isonno 0:6da5625a6946 13 #include "PinDetect.h"
isonno 0:6da5625a6946 14 #include "LightString.h"
isonno 0:6da5625a6946 15 #include "PushButton.h"
isonno 0:6da5625a6946 16 #include "SystemState.h"
isonno 0:6da5625a6946 17 #include "UserInterface.h"
isonno 0:6da5625a6946 18
isonno 0:6da5625a6946 19 #include "RGBLED.h"
isonno 0:6da5625a6946 20
isonno 0:6da5625a6946 21 #include <string>
isonno 0:6da5625a6946 22
isonno 0:6da5625a6946 23 // Blinking LEDs on the mbed board are used
isonno 0:6da5625a6946 24 // for light/motion sensor diagnostics
isonno 0:6da5625a6946 25
isonno 0:6da5625a6946 26 const int NumLEDs = 4;
isonno 0:6da5625a6946 27 DigitalOut leds[NumLEDs] = { DigitalOut(LED1),
isonno 0:6da5625a6946 28 DigitalOut(LED2),
isonno 0:6da5625a6946 29 DigitalOut(LED3),
isonno 0:6da5625a6946 30 DigitalOut(LED4) };
isonno 0:6da5625a6946 31
isonno 0:6da5625a6946 32 void cycleLEDs() {
isonno 0:6da5625a6946 33 static int curLED = 0;
isonno 0:6da5625a6946 34 leds[curLED] = 0;
isonno 0:6da5625a6946 35 curLED = (curLED + 1) % NumLEDs;
isonno 0:6da5625a6946 36 leds[curLED] = 1;
isonno 0:6da5625a6946 37 }
isonno 0:6da5625a6946 38
isonno 0:6da5625a6946 39 // Light sensor wrapper
isonno 0:6da5625a6946 40 class LightSensor
isonno 0:6da5625a6946 41 {
isonno 0:6da5625a6946 42 public:
isonno 0:6da5625a6946 43 LightSensor() : fLightPin( p19 ) {};
isonno 0:6da5625a6946 44
isonno 0:6da5625a6946 45 // int light() { return (int)(fLightPin.read() * 1000); }
isonno 0:6da5625a6946 46 int32_t light() {HoldInterrupts noirq; float a = fLightPin.read(); return (int)(a * 1000); }
isonno 0:6da5625a6946 47
isonno 0:6da5625a6946 48 private:
isonno 0:6da5625a6946 49 AnalogIn fLightPin;
isonno 0:6da5625a6946 50 };
isonno 0:6da5625a6946 51
isonno 0:6da5625a6946 52 // This is a version of Timeout that you simply
isonno 0:6da5625a6946 53 // poll to see if the timeout is still in effect
isonno 0:6da5625a6946 54 class MotionDelay : public Timeout
isonno 0:6da5625a6946 55 {
isonno 0:6da5625a6946 56 public:
isonno 0:6da5625a6946 57 MotionDelay() : Timeout()
isonno 0:6da5625a6946 58 { fWaiting = false; }
isonno 0:6da5625a6946 59
isonno 0:6da5625a6946 60 bool IsWaiting() { return fWaiting; }
isonno 0:6da5625a6946 61
isonno 0:6da5625a6946 62 void Start( int seconds )
isonno 0:6da5625a6946 63 {
isonno 0:6da5625a6946 64 detach(); // Reset the time
isonno 0:6da5625a6946 65 attach( this, &MotionDelay::Completed, seconds );
isonno 0:6da5625a6946 66 fWaiting = true;
isonno 0:6da5625a6946 67 }
isonno 0:6da5625a6946 68
isonno 0:6da5625a6946 69 private:
isonno 0:6da5625a6946 70 void Completed() { fWaiting = false; }
isonno 0:6da5625a6946 71
isonno 0:6da5625a6946 72 bool fWaiting;
isonno 0:6da5625a6946 73 };
isonno 0:6da5625a6946 74
isonno 0:6da5625a6946 75 // We want to be able to download files over USB, but only
isonno 0:6da5625a6946 76 // look for them on the SD Card. So at startup, we move
isonno 0:6da5625a6946 77 // any .CRI files found on the local drive to the SD card.
isonno 0:6da5625a6946 78 void CopyPatternFilesToSD()
isonno 0:6da5625a6946 79 {
isonno 0:6da5625a6946 80 SDFileSystem sdcard( p5, p6, p7, p8, "sdcard" );
isonno 0:6da5625a6946 81 LocalFileSystem local("local");
isonno 0:6da5625a6946 82
isonno 0:6da5625a6946 83 DIR * localDir = opendir("/local");
isonno 0:6da5625a6946 84
isonno 0:6da5625a6946 85 struct dirent *p;
isonno 0:6da5625a6946 86
isonno 0:6da5625a6946 87 while ((p = readdir( localDir )) != NULL)
isonno 0:6da5625a6946 88 {
isonno 0:6da5625a6946 89 string srcName = string("/local/") + string(p->d_name);
isonno 0:6da5625a6946 90 printf("Examining %s\r\n", srcName.c_str() );
isonno 0:6da5625a6946 91 if (srcName.rfind( ".CRI") != string::npos)
isonno 0:6da5625a6946 92 {
isonno 0:6da5625a6946 93 printf("Copying %s to SD Card\r\n", srcName.c_str());
isonno 0:6da5625a6946 94
isonno 0:6da5625a6946 95 string dstName = string("/sdcard/") + string(p->d_name);
isonno 0:6da5625a6946 96
isonno 0:6da5625a6946 97 FILE * src = fopen( srcName.c_str(), "rb" );
isonno 0:6da5625a6946 98 FILE * dst = fopen( dstName.c_str(), "wb" );
isonno 0:6da5625a6946 99
isonno 0:6da5625a6946 100 if (!src)
isonno 0:6da5625a6946 101 {
isonno 0:6da5625a6946 102 printf("Can't open: %s\r\n", srcName.c_str() );
isonno 0:6da5625a6946 103 continue;
isonno 0:6da5625a6946 104 }
isonno 0:6da5625a6946 105 if (!dst)
isonno 0:6da5625a6946 106 {
isonno 0:6da5625a6946 107 printf("Can't open %s\r\n", dstName.c_str() );
isonno 0:6da5625a6946 108 fclose( src );
isonno 0:6da5625a6946 109 continue;
isonno 0:6da5625a6946 110 }
isonno 0:6da5625a6946 111
isonno 0:6da5625a6946 112 // Copy the data
isonno 0:6da5625a6946 113 while (! feof(src))
isonno 0:6da5625a6946 114 {
isonno 0:6da5625a6946 115 char buffer[1024];
isonno 0:6da5625a6946 116 uint32_t numRead = fread( buffer, 1, sizeof( buffer ), src );
isonno 0:6da5625a6946 117 fwrite( buffer, 1, numRead, dst );
isonno 0:6da5625a6946 118 }
isonno 0:6da5625a6946 119 fclose(src);
isonno 0:6da5625a6946 120 fclose(dst);
isonno 0:6da5625a6946 121 remove(srcName.c_str()); // Wham! We only look for these on the sdcard
isonno 0:6da5625a6946 122 }
isonno 0:6da5625a6946 123 }
isonno 0:6da5625a6946 124 }
isonno 0:6da5625a6946 125
isonno 0:6da5625a6946 126 RGBLED gDebugLED( p22, p23, p24 );
isonno 0:6da5625a6946 127
isonno 0:6da5625a6946 128 void CheckDownloadedPattern( LightString& lightString )
isonno 0:6da5625a6946 129 {
isonno 0:6da5625a6946 130 static time_t activeTime;
isonno 0:6da5625a6946 131 static bool active = false;
isonno 0:6da5625a6946 132 bool nowActive = lightString.Snoop()->IsActive();
isonno 0:6da5625a6946 133 static bool saved = false;
isonno 0:6da5625a6946 134
isonno 0:6da5625a6946 135
isonno 0:6da5625a6946 136 int lightValue = 0;
isonno 0:6da5625a6946 137
isonno 0:6da5625a6946 138 if (active)
isonno 0:6da5625a6946 139 lightValue = 700;
isonno 0:6da5625a6946 140
isonno 0:6da5625a6946 141 if (saved)
isonno 0:6da5625a6946 142 lightValue += 70;
isonno 0:6da5625a6946 143
isonno 0:6da5625a6946 144 if (nowActive)
isonno 0:6da5625a6946 145 lightValue += 7;
isonno 0:6da5625a6946 146
isonno 0:6da5625a6946 147 gDebugLED.Set( lightValue );
isonno 0:6da5625a6946 148
isonno 0:6da5625a6946 149 if (!active && nowActive)
isonno 0:6da5625a6946 150 {
isonno 0:6da5625a6946 151 activeTime = time( NULL );
isonno 0:6da5625a6946 152 active = true;
isonno 0:6da5625a6946 153 }
isonno 0:6da5625a6946 154 else
isonno 0:6da5625a6946 155 if (active && nowActive)
isonno 0:6da5625a6946 156 {
isonno 0:6da5625a6946 157 activeTime = time( NULL );
isonno 0:6da5625a6946 158 }
isonno 0:6da5625a6946 159 else
isonno 0:6da5625a6946 160 if (active && !nowActive
isonno 0:6da5625a6946 161 && (time( NULL ) - activeTime > 2))
isonno 0:6da5625a6946 162 {
isonno 0:6da5625a6946 163 active = false;
isonno 0:6da5625a6946 164 lightString.Snoop()->SaveSnoop();
isonno 0:6da5625a6946 165 saved = true;
isonno 0:6da5625a6946 166 }
isonno 0:6da5625a6946 167 }
isonno 0:6da5625a6946 168
isonno 0:6da5625a6946 169 int main() {
isonno 0:6da5625a6946 170 printf("Welcome\r\n");
isonno 0:6da5625a6946 171 CopyPatternFilesToSD();
isonno 0:6da5625a6946 172
isonno 0:6da5625a6946 173 gSystemState.LoadState();
isonno 0:6da5625a6946 174
isonno 0:6da5625a6946 175 // Create hardware objects
isonno 0:6da5625a6946 176
isonno 0:6da5625a6946 177 CheapLCD lcd( p11, p13, p14, p12 ); // mosi, sclk, cs, rst
isonno 0:6da5625a6946 178
isonno 0:6da5625a6946 179 lcd.erase();
isonno 0:6da5625a6946 180 lcd.switch_backlight( true );
isonno 0:6da5625a6946 181
isonno 0:6da5625a6946 182 ZMotionDetector mdetect( p28, p27 );
isonno 0:6da5625a6946 183 mdetect.SetExtendedRange( true );
isonno 0:6da5625a6946 184
isonno 0:6da5625a6946 185 LightString curiLights( p9, 58 );
isonno 0:6da5625a6946 186 curiLights.InitLights();
isonno 0:6da5625a6946 187 curiLights.AttachUSBSerial();
isonno 0:6da5625a6946 188
isonno 0:6da5625a6946 189 RotaryEncoder knob( p17, p18 );
isonno 0:6da5625a6946 190 PushButton knobButton( p30, "Knob" );
isonno 0:6da5625a6946 191
isonno 0:6da5625a6946 192 LightSensor lightSensor;
isonno 0:6da5625a6946 193 MotionDelay motionDelay;
isonno 0:6da5625a6946 194
isonno 0:6da5625a6946 195 // Set up the User Interface
isonno 0:6da5625a6946 196 HomeMenu homeMenu( &lcd, &curiLights );
isonno 0:6da5625a6946 197 homeMenu.ConnectDevices( &knob, &knobButton );
isonno 0:6da5625a6946 198 homeMenu.Display( true );
isonno 0:6da5625a6946 199
isonno 0:6da5625a6946 200 // Infinite loop watches the light sensor and
isonno 0:6da5625a6946 201 // the motion detector. All other input is
isonno 0:6da5625a6946 202 // handled via interrupts.
isonno 0:6da5625a6946 203
isonno 0:6da5625a6946 204 leds[0] = leds[1] = leds[2] = leds[3] = 0;
isonno 0:6da5625a6946 205 gDebugLED.Set(0);
isonno 0:6da5625a6946 206
isonno 0:6da5625a6946 207 while(1) {
isonno 0:6da5625a6946 208 cycleLEDs();
isonno 0:6da5625a6946 209 wait(lightSensor.light() * 0.0004 );
isonno 0:6da5625a6946 210 // printf( "LightSensor: %d\r\n", lightSensor.light() );
isonno 0:6da5625a6946 211
isonno 0:6da5625a6946 212 // CheckDownloadedPattern( curiLights );
isonno 0:6da5625a6946 213
isonno 0:6da5625a6946 214 homeMenu.SetLightsOn( (lightSensor.light() < 800) || motionDelay.IsWaiting() );
isonno 0:6da5625a6946 215
isonno 0:6da5625a6946 216 if (mdetect.IsMotionDetected())
isonno 0:6da5625a6946 217 {
isonno 0:6da5625a6946 218 motionDelay.Start( 10 );
isonno 0:6da5625a6946 219 leds[0] = 1; leds[1] = 1; leds[2] = 1; leds[3] = 1;
isonno 0:6da5625a6946 220 wait(0.6);
isonno 0:6da5625a6946 221 }
isonno 0:6da5625a6946 222 }
isonno 0:6da5625a6946 223 }