Cheerlights client using WiFiDIPCortex and WS2801 RGB LED strip

Dependencies:   Adafruit_WS2801 HTTPClient cc3000_hostdriver_mbedsocket mbed

Files at this revision

API Documentation at this revision

Comitter:
SomeRandomBloke
Date:
Tue Feb 11 21:30:21 2014 +0000
Child:
1:40027344b249
Commit message:
Cheerlights using WiFiDIPCortex

Changed in this revision

Adafruit_WS2801.lib Show annotated file Show diff for this revision Revisions of this file
HTTPClient.lib Show annotated file Show diff for this revision Revisions of this file
cc3000_hostdriver_mbedsocket.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Adafruit_WS2801.lib	Tue Feb 11 21:30:21 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/SomeRandomBloke/code/Adafruit_WS2801/#6ff477690983
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPClient.lib	Tue Feb 11 21:30:21 2014 +0000
@@ -0,0 +1,1 @@
+https://mbed.org/users/donatien/code/HTTPClient/#1f743885e7de
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cc3000_hostdriver_mbedsocket.lib	Tue Feb 11 21:30:21 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/Kojto/code/cc3000_hostdriver_mbedsocket/#ca8c234997c0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Feb 11 21:30:21 2014 +0000
@@ -0,0 +1,337 @@
+/** WiFiDIPCortex Cheerlights
+ *
+ * @author Andrew Lindsay
+ *
+ * @section LICENSE
+ *
+ * Copyright (c) 2012 Andrew Lindsay (andrew [at] thiseldo [dot] co [dot] uk)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @section DESCRIPTION
+ *
+ * This is a basic cheerlights client, http://www.cheerlights.com/ It uses the
+ * API url http://api.thingspeak.com/channels/1417/field/1/last.txt to read the last
+ * colour selected.
+ *
+ * The hardware is the WiFiDIPCortex from SolderSplash Labs http://www.soldersplash.co.uk/products/wifi-dipcortex/
+ * This is a small, yet powerful LPC1347 Cortex M3 dev board with built in CC3000 WiFi module.
+ * The CC3000 uses the TI SmartConfig to setup the WiFi connection without having to update any code.
+ *
+ * The WiFiDIPCortex requires 2 pushbuttons connected between:
+ *     Reset:  Pin 1 (Reset) and GND, plus 10K resistor between Pin 1 and 3.3V, Pin 11
+ *     Config: Pin 6 (P1_31) and GND, plus 10K resistor between Pin 1 and 3.3V, Pin 11
+ *
+ * The LED strip used in this example is based on the WS2801 chips and requires a CLK and DATA to use it.
+ *     Pin 27 (P0_7)  LED strip Data
+ *     Pin 28 (P1_28) LED strip Clk.
+ * Ideally strip should be powered from a external 3.3V source and the GNDs connected between Power supply and
+ * WiFiDIPCortex.
+ *
+ * Debug output is sent to UART connected to pins 19 and 20.
+ *
+ * To use SmartConfig you'll need either the Android or iOS app from http://www.ti.com/tool/SmartConfig.
+ * The Java version hasnt worked so far, but could also be used.
+ * To enter SmartConfig mode, hold down the Config button, then press and release Reset, release Config.
+ * You then use the SmartConfig app to set your network parameters, when you get the notification that
+ * it was successful the WiFiDIPCortex is configured. The settings are saved and available next time it is powered up.
+ *
+ * If SmartConfig fails, try again.
+ *
+ * After starting the WiFiDIPCortex will connect to cheerlights.com and retrieve the latest colour and
+ * set the lights to the colour.
+ * Every minute the colour is retrieved and if its different to the last one the new colour is shown.
+ *
+ * The basic framework can be changed to use different LEDs to suit your available hardware.
+ *
+ */
+
+#include "mbed.h"
+#include "cc3000.h"
+#include "HTTPClient.h"
+// Library to drive the LED strip
+#include "Adafruit_WS2801.h"
+
+// Some local defines
+
+#define SERIAL_BAUD_RATE    115200
+
+#define WIGO           1
+#define WIFI_DIPCORTEX 2
+#define UNDEFINED      3
+
+#define MY_BOARD WIFI_DIPCORTEX
+
+using namespace mbed_cc3000;
+
+// LED to indicate smart config is running
+DigitalOut LedSC(P0_1);
+//
+DigitalIn SCButton(P1_31);
+
+PinName dataPin(P1_28);    // Yellow wire on Adafruit Pixels
+PinName clockPin(P0_7);    // Green wire on Adafruit Pixels
+
+/* cc3000 module declaration specific for user's board. Check also init() */
+#if (MY_BOARD == WIGO)
+cc3000 wifi(PTA16, PTA13, PTD0, SPI(PTD2, PTD3, PTC5), PORTA_IRQn);
+Serial uart(USBTX,USBRX);
+#elif (MY_BOARD == WIFI_DIPCORTEX)
+cc3000 wifi(p28, p27, p30, SPI(p21, p14, p37));
+Serial uart(p19, p20);
+#else
+
+#endif
+
+#ifndef CC3000_UNENCRYPTED_SMART_CONFIG
+const uint8_t smartconfigkey[] = {0x73,0x6d,0x61,0x72,0x74,0x63,0x6f,0x6e,0x66,0x69,0x67,0x41,0x45,0x53,0x31,0x36};
+#else
+const uint8_t smartconfigkey = 0;
+#endif
+
+tNetappIpconfigRetArgs ipinfo;
+extern char tmpBuffer[512];
+
+bool Connected = false;
+bool UsingSmartConfig = false;
+char _deviceName[] = "CC3000";
+
+HTTPClient http;
+//char str[128];
+uint32_t lastColour = 0;
+
+// Set the first variable to the number of rows, the second to number of pixels. 32 = 32 pixels in a row
+Adafruit_WS2801 strip = Adafruit_WS2801(1,32, dataPin, clockPin);
+
+// Setup the colour table and mappings
+#define NUM_COLOURS 12
+struct ColourTable {
+    char name[12];
+    uint32_t value;
+} colTable[NUM_COLOURS] = {
+    { "red",       0xFF0000 },
+    { "green",     0x008000 },
+    { "blue",      0x0000FF },
+    { "cyan",      0x00FFFF },
+    { "white",     0xFFFFFF },
+    { "warmwhite", 0xFDF5E6 },
+    { "purple",    0x800080 },
+    { "magenta",   0xFF00FF },
+    { "yellow",    0xFFFF00 },
+    { "orange",    0xFFA500 },
+    { "pink",      0xff69b4 },
+    { "oldlace",   0xfd5e56 }
+};
+
+
+
+/** Get status of WiFi connection
+ * displays and returns value
+ */
+int32_t getWiFiStatus(void)
+{
+    int32_t status = 0;
+    const char * WIFI_STATUS[] = {"Disconnected", "Scanning", "Connecting", "Connected"};
+
+    status = wifi._wlan.ioctl_statusget();
+    if (( status > -1 ) && ( status < 4 )) {
+        uart.printf(" Wifi Status    : %s\r\n", WIFI_STATUS[status]);
+    } else {
+        uart.printf(" Wifi Status    : %d\r\n", status);
+    }
+
+    return status;
+}
+
+/** Print info from CC3000
+ *
+ */
+void print_cc3000_info()
+{
+    uint8_t myMAC[8];
+    uint8_t buffer[2];
+    tNetappIpconfigRetArgs ipinfo2;
+    tUserFS cc_user_info;
+
+    wifi.get_user_file_info((uint8_t *)&cc_user_info, sizeof(cc_user_info));
+    wifi.get_mac_address(myMAC);
+    uart.printf(" MAC address : %02x:%02x:%02x:%02x:%02x:%02x\r\n", myMAC[0], myMAC[1], myMAC[2], myMAC[3], myMAC[4], myMAC[5]);
+
+    if (! wifi._nvmem.read_sp_version( (unsigned char*)&buffer ) ) {
+        uart.printf(" CC3000 Firmware Version : %u.%u \r\n", buffer[0], buffer[1]);
+    } else {
+        uart.printf(" CC3000 Read nvmem failed!");
+    }
+    getWiFiStatus();
+
+    if ( wifi.is_dhcp_configured() ) {
+        wifi.get_ip_config(&ipinfo2);
+        uart.printf(" Connected to   : %s \r\n", ipinfo2.uaSSID);
+        uart.printf(" IP             : %d.%d.%d.%d \r\n", ipinfo2.aucIP[3], ipinfo2.aucIP[2], ipinfo2.aucIP[1], ipinfo2.aucIP[0]);
+        uart.printf(" Gateway        : %d.%d.%d.%d \r\n", ipinfo2.aucDefaultGateway[3], ipinfo2.aucDefaultGateway[2], ipinfo2.aucDefaultGateway[1], ipinfo2.aucDefaultGateway[0]);
+        uart.printf(" Subnet         : %d.%d.%d.%d \r\n", ipinfo2.aucSubnetMask[3], ipinfo2.aucSubnetMask[2], ipinfo2.aucSubnetMask[1], ipinfo2.aucSubnetMask[0]);
+        uart.printf(" DNS            : %d.%d.%d.%d \r\n", ipinfo2.aucDNSServer[3], ipinfo2.aucDNSServer[2], ipinfo2.aucDNSServer[1], ipinfo2.aucDNSServer[0]);
+
+        uart.printf(" Cached IP      : %s \r\n", wifi.getIPAddress());
+        uart.printf(" Cached Gateway : %s \r\n", wifi.getGateway());
+        uart.printf(" Cached Subnet  : %s \r\n", wifi.getNetworkMask());
+
+    } else {
+        uart.printf(" Not connected \r\n");
+    }
+}
+
+
+/** Convert name to colour
+ * @param colStr Received colour name
+ */
+void setColour( char *colStr )
+{
+//    uart.printf("received %s\r\n",colStr);
+
+    for( int i=0; i < NUM_COLOURS; i++ ) {
+        if( strncmp( colTable[i].name, colStr, strlen(colTable[i].name) ) == 0 ) {
+            for (int n=0; n < strip.numPixels(); n++) {
+                strip.setPixelColor(n, colTable[i].value);
+                strip.show();
+                wait_ms(50);
+            }
+            return;
+        }
+    }
+    uart.printf("No colour found\r\n");
+
+}
+
+/** Read Cheerlights colour
+ * Use http call to get last Cheerlights colour
+ */
+void readCheerlight( void )
+{
+    char str[128];
+    //GET data
+    uart.printf("\r\nTrying to fetch page...\r\n");
+    int ret = http.get("http://api.thingspeak.com/channels/1417/field/1/last.txt", str, 128);
+    if (!ret) {
+        uart.printf("Page fetched successfully - read %d characters\r\n", strlen(str));
+        uart.printf("Result: %s\r\n", str);
+        setColour( str );
+    } else {
+        uart.printf("Error - ret = %d - HTTP return code = %d\r\n", ret, http.getHTTPResponseCode());
+    }
+
+}
+
+
+/** Initialisations
+ * Hardware initialisations and any other setup needed
+ */
+void init()
+{
+    LedSC = 0;
+    SCButton.mode(PullUp);
+    NVIC_SetPriority(SSP1_IRQn, 0x0);
+    NVIC_SetPriority(PIN_INT0_IRQn, 0x1);
+
+    // SysTick set to lower priority than Wi-Fi SPI bus interrupt
+    NVIC_SetPriority(SysTick_IRQn, 0x2);
+
+    // Enable RAM1
+    LPC_SYSCON->SYSAHBCLKCTRL |= (0x1 << 26);
+
+    uart.baud(SERIAL_BAUD_RATE);
+
+    strip.begin();
+
+    // Update LED contents, to start they are all 'off'
+    strip.show();
+}
+
+/** Main loop, handle WiFi connection, check for button press to start SmartConfig process
+ *
+ */
+int main( void )
+{
+    // Initalise the WiFi Module
+    init();
+
+    uart.printf("WiFiDIPCortex Smartconfig Cheerlights\r\n");
+    wifi.start(0);
+
+    // Check if button pressed during startup, if so then go into SmartConfig mode
+    // otherwise just start wifi
+    if(!SCButton) {
+        uart.printf("Smartconfig button pressed\r\n");
+
+        //SmartConfig();
+        uart.printf("\r\nStarting Smart config, waiting for message from smartphone app ....\r\n");
+        LedSC = 1;
+        // We dont want to auto reconnect to an access point
+        wifi._wlan.ioctl_set_connection_policy(0, 0, 0);
+
+        // start smart config will disconnect, set the prefix
+        // wait for a message via a SmartConfig app, store it to the profile list
+        // finally it will reenable auto connection, triggering the module to connect to the new access point
+        wifi.start_smart_config(0);
+        LedSC = 0;
+        UsingSmartConfig = true;
+
+        uart.printf("Back from SmartConfig\r\n");
+
+        wait(2);    // for dhcp to configure
+
+        if ( wifi.is_dhcp_configured() ) {
+            if (!Connected) {
+                // We have just connected
+                Connected = true;
+
+                // Start the mdns service, this tells any smart config apps listening we have succeeded
+                wifi._socket.mdns_advertiser(1, (uint8_t *)_deviceName, strlen(_deviceName));
+
+                UsingSmartConfig = false;
+            }
+        } else {
+            Connected = false;
+
+        }
+    } else {
+        uart.printf("Normal startup\r\n");
+    }
+
+    wait_ms(750);
+
+    LedSC = 0;
+    print_cc3000_info();
+    
+    // Check if we're connected to WiFi and have an IP address, if not then just flash LED
+    uint32_t status = getWiFiStatus();
+    if( status != 3 || !wifi.is_dhcp_configured() ) {
+        while( 1 ) {
+            LedSC = !LedSC;
+            wait_ms(500);
+        }    
+    }
+
+    while (1) {
+        getWiFiStatus();
+        readCheerlight();
+        // Pause for a minute before checking again
+        wait(60);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Feb 11 21:30:21 2014 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/824293ae5e43
\ No newline at end of file