Cheerlights client using WiFiDIPCortex and WS2801 RGB LED strip
Dependencies: Adafruit_WS2801 HTTPClient cc3000_hostdriver_mbedsocket mbed
main.cpp
00001 /** WiFiDIPCortex Cheerlights 00002 * 00003 * @author Andrew Lindsay 00004 * 00005 * @section LICENSE 00006 * 00007 * Copyright (c) 2012 Andrew Lindsay (andrew [at] thiseldo [dot] co [dot] uk) 00008 * 00009 * Permission is hereby granted, free of charge, to any person obtaining a copy 00010 * of this software and associated documentation files (the "Software"), to deal 00011 * in the Software without restriction, including without limitation the rights 00012 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00013 * copies of the Software, and to permit persons to whom the Software is 00014 * furnished to do so, subject to the following conditions: 00015 00016 * The above copyright notice and this permission notice shall be included in 00017 * all copies or substantial portions of the Software. 00018 * 00019 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00020 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00021 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00022 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00023 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00024 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00025 * THE SOFTWARE. 00026 * 00027 * @section DESCRIPTION 00028 * 00029 * This is a basic cheerlights client, http://www.cheerlights.com/ It uses the 00030 * API url http://api.thingspeak.com/channels/1417/field/1/last.txt to read the last 00031 * colour selected. 00032 * 00033 * The hardware is the WiFiDIPCortex from SolderSplash Labs http://www.soldersplash.co.uk/products/wifi-dipcortex/ 00034 * This is a small, yet powerful LPC1347 Cortex M3 dev board with built in CC3000 WiFi module. 00035 * The CC3000 uses the TI SmartConfig to setup the WiFi connection without having to update any code. 00036 * 00037 * The WiFiDIPCortex requires 2 pushbuttons connected between: 00038 * Reset: Pin 1 (Reset) and GND, plus 10K resistor between Pin 1 and 3.3V, Pin 11 00039 * Config: Pin 6 (P1_31) and GND, plus 10K resistor between Pin 1 and 3.3V, Pin 11 00040 * 00041 * The LED strip used in this example is based on the WS2801 chips and requires a CLK and DATA to use it. 00042 * Pin 27 (P0_7) LED strip Data 00043 * Pin 28 (P1_28) LED strip Clk. 00044 * Ideally strip should be powered from a external 3.3V source and the GNDs connected between Power supply and 00045 * WiFiDIPCortex. 00046 * 00047 * Debug output is sent to UART connected to pins 19 and 20. 00048 * 00049 * To use SmartConfig you'll need either the Android or iOS app from http://www.ti.com/tool/SmartConfig. 00050 * The Java version hasnt worked so far, but could also be used. 00051 * To enter SmartConfig mode, hold down the Config button, then press and release Reset, release Config. 00052 * You then use the SmartConfig app to set your network parameters, when you get the notification that 00053 * it was successful the WiFiDIPCortex is configured. The settings are saved and available next time it is powered up. 00054 * 00055 * If SmartConfig fails, try again. 00056 * 00057 * After starting the WiFiDIPCortex will connect to cheerlights.com and retrieve the latest colour and 00058 * set the lights to the colour. 00059 * Every minute the colour is retrieved and if its different to the last one the new colour is shown. 00060 * 00061 * The basic framework can be changed to use different LEDs to suit your available hardware. 00062 * 00063 */ 00064 00065 #include "mbed.h" 00066 #include "cc3000.h" 00067 #include "HTTPClient.h" 00068 // Library to drive the LED strip 00069 #include "Adafruit_WS2801.h" 00070 00071 00072 // Some local defines 00073 #define SERIAL_BAUD_RATE 115200 00074 00075 #define NUM_PIXELS 50 00076 #define NUM_COL_HISTORY 5 00077 00078 #define WIGO 1 00079 #define WIFI_DIPCORTEX 2 00080 #define UNDEFINED 3 00081 00082 #define MY_BOARD WIFI_DIPCORTEX 00083 00084 using namespace mbed_cc3000; 00085 00086 // LED to indicate SmartConfig is running 00087 DigitalOut LedSC(P0_1); 00088 // Button to hold down during reset to enter SmartConfig mode 00089 DigitalIn SCButton(P1_31); 00090 00091 // For Bit-Banging SPI use Pins 40 and 39 00092 PinName dataPin(p40); // PIN 40 - Yellow wire on Adafruit Pixels 00093 PinName clockPin(p39); // PIN 39 - Green wire on Adafruit Pixels 00094 00095 // For hardware SPI use Pin 16 for Data and pin 13 for Clk 00096 00097 /* cc3000 module declaration specific for user's board. Check also init() */ 00098 #if (MY_BOARD == WIGO) 00099 cc3000 wifi(PTA16, PTA13, PTD0, SPI(PTD2, PTD3, PTC5), PORTA_IRQn); 00100 Serial uart(USBTX,USBRX); 00101 #elif (MY_BOARD == WIFI_DIPCORTEX) 00102 cc3000 wifi(p28, p27, p30, SPI(p21, p14, p37)); 00103 Serial uart(p19, p20); 00104 #else 00105 00106 #endif 00107 00108 #ifndef CC3000_UNENCRYPTED_SMART_CONFIG 00109 //const uint8_t smartconfigkey[] = {0x73,0x6d,0x61,0x72,0x74,0x63,0x6f,0x6e,0x66,0x69,0x67,0x41,0x45,0x53,0x31,0x36}; 00110 #else 00111 //const uint8_t smartconfigkey = 0; 00112 #endif 00113 00114 tNetappIpconfigRetArgs ipinfo; 00115 extern char tmpBuffer[512]; 00116 00117 bool Connected = false; 00118 bool UsingSmartConfig = false; 00119 char _deviceName[] = "CC3000"; 00120 00121 HTTPClient http; 00122 00123 // Set the first variable to the number of rows, the second to number of pixels. 32 = 32 pixels in a row 00124 Adafruit_WS2801 strip = Adafruit_WS2801(NUM_PIXELS, dataPin, clockPin); 00125 00126 // Setup the colour table and mappings 00127 #define NUM_COLOURS 13 00128 struct ColourTable { 00129 char name[12]; 00130 uint32_t value; 00131 } colTable[NUM_COLOURS] = { 00132 { "red", 0xff0000 }, 00133 { "green", 0x008000 }, 00134 { "blue", 0x0000ff }, 00135 { "cyan", 0x00ffff }, 00136 { "white", 0xffffff }, 00137 { "warmwhite", 0xfdf5e6 }, 00138 { "purple", 0x800080 }, 00139 { "magenta", 0xff00ff }, 00140 { "yellow", 0xffff00 }, 00141 { "orange", 0xffa500 }, 00142 { "pink", 0xff69b4 }, 00143 { "oldlace", 0xfd5e56 }, 00144 { "black", 0x000000 } 00145 }; 00146 00147 /** Get status of WiFi connection 00148 * displays and returns value 00149 */ 00150 int32_t getWiFiStatus(void) 00151 { 00152 int32_t status = 0; 00153 const char * WIFI_STATUS[] = {"Disconnected", "Scanning", "Connecting", "Connected"}; 00154 00155 status = wifi._wlan.ioctl_statusget(); 00156 if (( status > -1 ) && ( status < 4 )) { 00157 uart.printf(" Wifi Status : %s\r\n", WIFI_STATUS[status]); 00158 } else { 00159 uart.printf(" Wifi Status : %d\r\n", status); 00160 } 00161 00162 return status; 00163 } 00164 00165 /** Print info from CC3000 00166 * 00167 */ 00168 void print_cc3000_info() 00169 { 00170 uint8_t myMAC[8]; 00171 uint8_t buffer[2]; 00172 tNetappIpconfigRetArgs ipinfo2; 00173 tUserFS cc_user_info; 00174 00175 wifi.get_user_file_info((uint8_t *)&cc_user_info, sizeof(cc_user_info)); 00176 wifi.get_mac_address(myMAC); 00177 uart.printf(" MAC address : %02x:%02x:%02x:%02x:%02x:%02x\r\n", myMAC[0], myMAC[1], myMAC[2], myMAC[3], myMAC[4], myMAC[5]); 00178 00179 if (! wifi._nvmem.read_sp_version( (unsigned char*)&buffer ) ) { 00180 uart.printf(" CC3000 Firmware Version : %u.%u \r\n", buffer[0], buffer[1]); 00181 } else { 00182 uart.printf(" CC3000 Read nvmem failed!"); 00183 } 00184 getWiFiStatus(); 00185 00186 if ( wifi.is_dhcp_configured() ) { 00187 wifi.get_ip_config(&ipinfo2); 00188 uart.printf(" Connected to : %s \r\n", ipinfo2.uaSSID); 00189 uart.printf(" IP : %d.%d.%d.%d \r\n", ipinfo2.aucIP[3], ipinfo2.aucIP[2], ipinfo2.aucIP[1], ipinfo2.aucIP[0]); 00190 uart.printf(" Gateway : %d.%d.%d.%d \r\n", ipinfo2.aucDefaultGateway[3], ipinfo2.aucDefaultGateway[2], ipinfo2.aucDefaultGateway[1], ipinfo2.aucDefaultGateway[0]); 00191 uart.printf(" Subnet : %d.%d.%d.%d \r\n", ipinfo2.aucSubnetMask[3], ipinfo2.aucSubnetMask[2], ipinfo2.aucSubnetMask[1], ipinfo2.aucSubnetMask[0]); 00192 uart.printf(" DNS : %d.%d.%d.%d \r\n", ipinfo2.aucDNSServer[3], ipinfo2.aucDNSServer[2], ipinfo2.aucDNSServer[1], ipinfo2.aucDNSServer[0]); 00193 00194 uart.printf(" Cached IP : %s \r\n", wifi.getIPAddress()); 00195 uart.printf(" Cached Gateway : %s \r\n", wifi.getGateway()); 00196 uart.printf(" Cached Subnet : %s \r\n", wifi.getNetworkMask()); 00197 00198 } else { 00199 uart.printf(" Not connected \r\n"); 00200 } 00201 } 00202 00203 00204 /** Convert name to colour and set it on LEDs. With colour history, strip will be 00205 * changing colour for every new colour detected producing an almost random effect 00206 * @param colNum Number of the received colour, starts 0 to NUM_COL_HISTORY with highest being latest colour 00207 * @param colStr Received colour name 00208 */ 00209 void setColour( int colNum, char *colStr ) 00210 { 00211 // uart.printf("received %s\r\n",colStr); 00212 00213 for( int i=0; i < NUM_COLOURS; i++ ) { 00214 if( strncmp( colTable[i].name, colStr, strlen(colTable[i].name) ) == 0 ) { 00215 for (int n=colNum; n < strip.numPixels()+NUM_COL_HISTORY; n += NUM_COL_HISTORY) { 00216 strip.setPixelColor(n, colTable[i].value); 00217 } 00218 // Update strip after colour has been set 00219 strip.show(); 00220 // Slight pause 00221 wait_ms(250); 00222 return; 00223 } 00224 } 00225 uart.printf("No colour found\r\n"); 00226 00227 } 00228 00229 #define CL_BUFFSIZE 1024 00230 /** Read Cheerlights colour 00231 * Use http call to get last Cheerlights colour 00232 */ 00233 void readCheerlight( void ) 00234 { 00235 char responseStr[CL_BUFFSIZE]; 00236 //GET data 00237 uart.printf("\r\nTrying to fetch page...\r\n"); 00238 int ret = http.get("http://api.thingspeak.com/channels/1417/feed.csv?results=5", responseStr, CL_BUFFSIZE); 00239 if (!ret) { 00240 uart.printf("Page fetched successfully - read %d characters\r\n", strlen(responseStr)); 00241 //uart.printf("Result: %s\r\n", responseStr); 00242 // Parse CSV and set colours 00243 // Get a line 00244 char *ptr = responseStr; 00245 // Skip header line 00246 while(*ptr++ != 0x0a ); // Header 00247 // 5 colours 00248 for( int i=0; i<5; i++ ) { 00249 while(*ptr++ != ','); // Column 1 - Date, Skip 00250 while(*ptr++ != ','); // Column 2 - ID, Skip 00251 char col[10]; 00252 char *cPtr = col; 00253 while( *ptr != 0x0a ) { // Column 3 - colour 00254 *cPtr++ = *ptr++; 00255 } 00256 *cPtr = '\0'; 00257 uart.printf("%d %s\r\n",i,col); 00258 setColour( i, col ); 00259 } 00260 } else { 00261 uart.printf("Error - ret = %d - HTTP return code = %d\r\n", ret, http.getHTTPResponseCode()); 00262 } 00263 00264 uart.printf("End of readCheerlights\n\r"); 00265 } 00266 00267 00268 /** Initialisations 00269 * Hardware initialisations and any other setup needed 00270 */ 00271 void init() 00272 { 00273 LedSC = 0; 00274 SCButton.mode(PullUp); 00275 NVIC_SetPriority(SSP1_IRQn, 0x0); 00276 NVIC_SetPriority(PIN_INT0_IRQn, 0x1); 00277 00278 // SysTick set to lower priority than Wi-Fi SPI bus interrupt 00279 NVIC_SetPriority(SysTick_IRQn, 0x2); 00280 00281 // Enable RAM1 00282 LPC_SYSCON->SYSAHBCLKCTRL |= (0x1 << 26); 00283 00284 uart.baud(SERIAL_BAUD_RATE); 00285 00286 strip.updatePins(); // Switch to Hardware SPI 00287 strip.begin(); 00288 00289 // Update LED contents, to start they are all 'off' 00290 strip.show(); 00291 } 00292 00293 /** Main loop, handle WiFi connection, check for button press to start SmartConfig process 00294 * 00295 */ 00296 int main( void ) 00297 { 00298 // Initalise the WiFi Module 00299 init(); 00300 00301 uart.printf("WiFiDIPCortex Smartconfig Cheerlights\r\n"); 00302 wifi.start(0); 00303 00304 // Check if button pressed during startup, if so then go into SmartConfig mode 00305 // otherwise just start wifi 00306 if(!SCButton) { 00307 uart.printf("Smartconfig button pressed\r\n"); 00308 00309 //SmartConfig(); 00310 uart.printf("\r\nStarting Smart config, waiting for message from smartphone app ....\r\n"); 00311 LedSC = 1; 00312 // We dont want to auto reconnect to an access point 00313 wifi._wlan.ioctl_set_connection_policy(0, 0, 0); 00314 00315 // start smart config will disconnect, set the prefix 00316 // wait for a message via a SmartConfig app, store it to the profile list 00317 // finally it will reenable auto connection, triggering the module to connect to the new access point 00318 wifi.start_smart_config(0); 00319 LedSC = 0; 00320 UsingSmartConfig = true; 00321 00322 uart.printf("Back from SmartConfig\r\n"); 00323 00324 wait(2); // for dhcp to configure 00325 // TODO: Add this into start_smart_config 00326 if ( wifi.is_dhcp_configured() ) { 00327 if (!Connected) { 00328 // We have just connected 00329 Connected = true; 00330 // This might need calling for mdsn advertiser to work. 00331 // uint32_t ip_addr[4] = {0,0,0,0}; 00332 // wifi._socket.gethostbyname((uint8_t *)_deviceName, strlen(_deviceName), uint32_t *ip_addr); 00333 00334 // Start the mdns service, this tells any smart config apps listening we have succeeded 00335 wifi._socket.mdns_advertiser(1, (uint8_t *)_deviceName, strlen(_deviceName)); 00336 00337 UsingSmartConfig = false; 00338 } 00339 } else { 00340 Connected = false; 00341 00342 } 00343 } else { 00344 uart.printf("Normal startup\r\n"); 00345 } 00346 00347 wait_ms(750); 00348 00349 LedSC = 0; 00350 print_cc3000_info(); 00351 00352 // Check if we're connected to WiFi and have an IP address, if not then just flash LED until reset 00353 uint32_t status = getWiFiStatus(); 00354 if( status != 3 || !wifi.is_dhcp_configured() ) { 00355 while( 1 ) { 00356 LedSC = !LedSC; 00357 wait_ms(500); 00358 } 00359 } 00360 00361 while (1) { 00362 if( getWiFiStatus() == 0 ) { 00363 // Not connected, attempt reconnect 00364 ; 00365 } 00366 readCheerlight(); 00367 // Pause for a minute before checking again 00368 wait(60); 00369 } 00370 }
Generated on Sat Jul 16 2022 13:59:27 by 1.7.2