This application shows an example of how to control the RGB LED over RPC. The app also contains an HTTP server and uses other components such as the LCD and Temperature Sensor to display additional information.

Dependencies:   C12832_lcd EthernetInterface HTTPServer LM75B MutexLocker mbed-rpc mbed-rtos mbed

main.cpp

Committer:
cabledev
Date:
2014-05-15
Revision:
0:452a42421de4
Child:
1:784afed9dbfe

File content as of revision 0:452a42421de4:

/**
 * Notice:
 * 
 * Neither CableLabs nor any member company is responsible to any party for any liability of any nature whatsoever
 * resulting from or arising out of use or reliance upon this software. This software is furnished on an "AS IS" basis
 * and neither CableLabs nor its members provides any representation or warranty, express or implied, regarding the
 * accuracy, completeness, or fitness for a particular purpose of this software.
 * 
 * (C)Copyright 2014 Cable Television Laboratories, Inc. All rights reserved.
 * -----------------------------------------------------------------------------
 * 
 * File: main.cpp
 * 
 */

#include "mbed.h"

// LCD
#include "C12832_lcd.h"
#include "Small_7.h"

// HTTPServer
#include "HTTPServer.h"
#include "FsHandler.h"
#include "LocalFileSystem.h"
#include "RpcHandler.h"
#include "mbed_rpc.h"

// Temperature sensor
#include "mutexlocker.h"
#include "LM75B.h"

#define ON 1
#define OFF 0
#define DIM 0.3
#define SERIAL_BAUD 115200 // 9600
#define HTTP_LISTEN_PORT 80

// blinks LED1 when the HTTP server is listening for connections
//#define LISTENING_LED

// for some reason, getting the return code causes the HTTP server to be unresponsive
#define ETH_CONNECTION_STATUS

// uncomment the following line for static IP address
//#define STATIC_IP
#define STATIC_IP_ADDRESS "192.168.1.177"
#define STATIC_IP_NETMASK "255.255.255.0"
#define STATIC_IP_GATEWAY "192.168.1.1"

#define TEMPERATURE_ACTIVE

// LCD
// LCD object
C12832_LCD lcd;

// the led's are connected to vcc, so a PwmOut of 100% will shut off the led and 0% will let it shine!
PwmOut r(p23);
PwmOut g(p24);
PwmOut b(p25);
RpcPwmOut rpc_r(p23,"r");
RpcPwmOut rpc_g(p24,"g");
RpcPwmOut rpc_b(p25,"b");
// used to restore the rgb value after turning LED off and back on 
bool powerOn = true;
float lastH = 0.0;
float lastS = 0.0;
float lastV = -1.0;

AnalogIn Pot1(p19);
AnalogIn Pot2(p20);

// Ethernet
EthernetInterface eth;
bool ethConnected;

// HTTPServer
#ifdef LISTENING_LED
// Use LED1 to indicate that the main loop is still executing
DigitalOut listeningLed(LED1);
#endif
// Use the serial connection 'pc' to dump debug information
Serial pc(USBTX, USBRX, "pc");
// Instantiate a HTTPServer to handle incoming requests
HTTPServer  svr;
// Instantiate a local file system handler named 'local' which will be used later to access files on the mbed.
LocalFileSystem local("local");

// Temperature sensor
Mutex mutex;
LM75B temperatureSensor(p28,p27);

// RPC Variables
/*
//First create the variables you wish to use
float f;
int i;
char c;
//Then attach them to an RPCVariable Object
RPCVariable<float> rpc_f(&f, "f");
RPCVariable<int> rpc_i(&i, "i");
RPCVariable<char> rpc_c(&c, "c");
*/

// RPC Functions
void setLight(Arguments* input, Reply* output);

// invoke with "http://<eth_ip>/RPC/setLightColor/run <H> <S> <V> <brightness> <powerOn>",
//  where 0 <= H <= 360, 0 <= S <= 1, 0 <= V <= 1
RPCFunction rpc_setLight(&setLight, "setLight");

// function to convert hue , saturation and  value to RGB
// see http://en.wikipedia.org/wiki/HSL_and_HSV
void hsv2rgb(float H,float S, float V)
{
    float f,h,p,q,t;
    int i;
    if( S == 0.0) {
        r = 1.0 - V;  // invert pwm !
        g = 1.0 - V;
        b = 1.0 - V;
        return;
    }
    if(H > 360.0) H = 0.0;   // check values
    if(S > 1.0) S = 1.0; 
    if(S < 0.0) S = 0.0;
    if(V > 1.0) V = 1.0;
    if(V < 0.0) V = 0.0;
    h = H / 60.0;
    i = (int) h;
    f = h - i;
    p = V * (1.0 - S);
    q = V * (1.0 - (S * f));
    t = V * (1.0 - (S * (1.0 - f)));

    switch(i) {
        case 0:
            r = 1.0 - V;  // invert pwm !
            g = 1.0 - t;
            b = 1.0 - p;
            break;
        case 1:
            r = 1.0 - q;
            g = 1.0 - V;
            b = 1.0 - p;
            break;
        case 2:
            r = 1.0 - p;
            g = 1.0 - V;
            b = 1.0 - t;
            break;
        case 3:
            r = 1.0 - p;
            g = 1.0 - q;
            b = 1.0 - V;
            break;
        case 4:
            r = 1.0 - t;
            g = 1.0 - p;
            b = 1.0 - V;
            break;
        case 5:
        default:
            r = 1.0 - V;
            g = 1.0 - p;
            b = 1.0 - q;
            break;
    }
}

void setLight(Arguments* input, Reply* output)
{
    // Arguments are already parsed into argv array of char*
    printf("Object name = %s\n\r",input->obj_name);
    printf("Method name = %s\n\r",input->method_name);
    for (int i=0; i < input->argc; i++)
    {
        printf("argv[%1d] = %s \n\r",i,input->argv[i]);
    }
    
    if (input->argc > 4)
    {
        char* strH = input->argv[0];
        char* strS = input->argv[1];
        char* strV = input->argv[2];
        char* strBrightness = input->argv[3];
        char* strPower = input->argv[4];
        
        float h;
        float s;
        float v;
        float brightness;
        int power;
        
        if ((strH != NULL) && (strlen(strH) > 0) && (strcmp(strH, "null") != 0))
        {
            // assume that if we got an H, we also got an S & V
            sscanf(strH, "%f", &h);
            sscanf(strS, "%f", &s);
            sscanf(strV, "%f", &v);
            
            lastH = h;
            lastS = s;
            lastV = v;
printf("*** set lastV from color to %f\n\r", lastV);
        }
        
        if ((strBrightness != NULL) && (strlen(strBrightness) > 0) && (strcmp(strBrightness, "null") != 0))
        {
            sscanf(strBrightness, "%f", &brightness);
            brightness = brightness / 100.0;
            brightness = brightness*brightness; // normalization, because in general, the LED is too bright
            lastV = brightness;
printf("*** set lastV from brightness to %f\n\r", lastV);
        }
        
        if ((strPower != NULL) && (strlen(strPower) > 0) && (strcmp(strPower, "null") != 0))
        {
            sscanf(strPower, "%i", &power);
            
            powerOn = (power == ON);
        }
        
        printf("setLight: HSV = '(%s, %s, %s)', Brightness = '%s', Power = '%s'\n\r", strH, strS, strV, strBrightness, strPower);
        
        // recall that the power is inverted, so (0.0 == on) and (1.0 == off)
        if (powerOn)
        {
            hsv2rgb(lastH, lastS, lastV);
        }
        else
        {
            r = 1.0;
            g = 1.0;
            b = 1.0;
        }
    }
}

void startHttpServer(void const* arg)
{
    // Ethernet
#ifdef STATIC_IP
    pc.printf("Configuring Ethernet with Static IP Address.\n\r");
    //eth.init("192.168.1.177", "255.255.255.0", "192.168.1.1");
    eth.init(STATIC_IP_ADDRESS, STATIC_IP_NETMASK, STATIC_IP_GATEWAY);
#else
    pc.printf("Configuring Ethernet with DHCP IP Address.\n\r");
    eth.init(); //Use DHCP
#endif
    
#ifdef ETH_CONNECTION_STATUS
//pc.printf("*** eth.connect()!\n\r");
    int connected = eth.connect(); // success == 0
//pc.printf("*** Eth.connect returned %i\n\r", connected);
    if (connected != 0)
    {
        lcd.printf("Ethernet not connected");
    }
    else
    {
#else
//pc.printf("*** eth.connect()!\n\r");
    eth.connect();
#endif
        char* ipAddr = eth.getIPAddress();
//pc.printf("*** ipAddr: %s\n\r", ipAddr);
        ethConnected = ((ipAddr != NULL) && (strlen(ipAddr) > 0));

        if (ethConnected)
        {
            mutex.lock();
            lcd.locate(10,0);
            lcd.printf("IP Address: %s", eth.getIPAddress());
            mutex.unlock();
            
#ifndef TEMPERATURE_ACTIVE
            mutex.lock();
            lcd.locate(10,10);
            lcd.printf("WebServer started");
            mutex.unlock();
#endif
        }
        else
        {
            lcd.printf("No IP Address");
        }
#ifdef ETH_CONNECTION_STATUS
    }
#endif
    
    svr.addHandler<HTTPFsRequestHandler>("/");
    svr.addHandler<HTTPRpcRequestHandler>("/RPC");
    
    svr.setPort(HTTP_LISTEN_PORT);
    svr.setEthernetInterface(&eth);
    svr.start();
}

void startTemperatureMonitor(void const* arg)
{
    float tempC = 0;
    float tempF = 0;
    while(true)
    {
        tempC = temperatureSensor.read();
        tempF = (tempC * 1.8f) + 32.0f;
        
        mutex.lock();
        lcd.locate(10,10);        
        lcd.printf("Temp: %.3f F\n", tempF);
        mutex.unlock();
        wait(1.0);
    }
}

int main()
{
    // LED
    float h; //  hue 
    float s,v; // saturation and  value;
    unsigned short temp;
    
    lcd.cls();
    lcd.set_font((unsigned char*) Small_7);
    
    r.period(0.001); // set pwm period
    s = 1.0;
    
    // initialize the LED from the Pots
    // get Poti 1 for color
    temp = Pot1.read_u16();
    temp = temp >> 6;        // truncate to 10 Bit
    h = temp * 0.3515625;  // scale to 0 - 360;
    //lcd.locate(0,13);
    //lcd.printf("Colour = %3.2f degree",h);
    // get Poti 2 fo value
    temp = Pot2.read_u16();
    temp = temp >> 6;
    v = temp * 0.0009765624;  // scale to 0 - 1;
    //lcd.locate(0,23);
    //lcd.printf("Val = %01.3f ",v);
    hsv2rgb(h,s,v);
    
    lastH = h;
    lastS = s;
    lastV = v;
    
    //HTTPServer
    pc.baud(SERIAL_BAUD);
    
    // add the interfaces that can be created dynamically
    RPC::add_rpc_class<RpcDigitalOut>();
    RPC::add_rpc_class<RpcPwmOut>();
    
    HTTPFsRequestHandler::mount("/local/", "/");
    
    ethConnected = false;
    Thread httpsvr( &startHttpServer );
    
#ifdef TEMPERATURE_ACTIVE
    Thread tempMonitor(&startTemperatureMonitor );
#endif
    
    while (true)
    {
#ifdef LISTENING_LED
        if (ethConnected)
        {
            listeningLed = ON;
            wait(0.2);
            listeningLed = OFF;
            wait(0.2);
        }
#endif
    }
}