CC3200 Wi-Fi AC Voltage Switch Project


    I am going to embark on a new project - a Wi-Fi remote AC switch. A Wi-Fi switch to control an AC line with CC3200 development board. The onboard temperature sensor and accelerometer will be used to get temperature and vibration information from the switch. While I am working on the project with the development board I will also design custom hardware with the CC3200MOD SoC. All the updates on hardware and software will be published here. If you follow this project all you need is the TI's development board: SimpleLink Wi-Fi CC3200MOD module LaunchPad or SimpleLink Wi-Fi CC3200 LaunchPad.

For this project you will need to download and install CC3200 SDK. Also, for an additional information on how to set up and program the board refer to CC3200 page.


SimpleLink Wi-Fi CC3200 LaunchPad Schematics Diagram .pdf file.

On the hardware side for my custom board I am going to change the USB to UART converter, FT234XD-R, from the original FT2232D to lower the cost of my custom board. Since CC3200 can be programmed with UART I will be able to program CC3200 with FT234XD-R FTDI chip.

My custom preliminary circuit diagram for the MCU part:

For the project development I will be using CC3200 development board with the following pins connected (so far LED1, LED2, LED3):

To start with the wireless switch design, I need to develop the high voltage section of the circuit, the AC switch itself. Below is the preliminary circuit diagram for the AC switch. I will be making changes to the schematics and updating the web page.

Preliminary TRIAC AC switch Circuit Diagram

I have created a web-page on TRIAC circuits design for your reference.

The next step is to configure pins to match the schematics diagram, pins configuration is in pin_mux_config.c file. I have wrote this file with the help of the TI PinMAX tool. LED control signals has to be set as outputs. Also UART and ADC pins have to be configured for the project.

//*****************************************************************************
// pin_mux_config.c
//
// configure the device pins for different signals
//
// Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/
// All rights reserved.
// 
//  Redistribution and use in source and binary forms, with or without 
//  modification, are permitted provided that the following conditions 
//  are met:
//
//    Redistributions of source code must retain the above copyright 
//    notice, this list of conditions and the following disclaimer.
//
//    Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the 
//    documentation and/or other materials provided with the   
//    distribution.
//
//    Neither the name of Texas Instruments Incorporated nor the names of
//    its contributors may be used to endorse or promote products derived
//    from this software without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
//  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
//  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
//  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
//  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
//  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************

// This file was automatically generated on 12/20/2016 at 10:58:42 AM
// by TI PinMux version
//
//*****************************************************************************

#include "pinmux.h"
#include "hw_types.h"
#include "hw_memmap.h"
#include "hw_gpio.h"
#include "pin.h"
#include "gpio.h"
#include "prcm.h"

//*****************************************************************************
void PinMuxConfig(void)
{


    //
    // Set unused pins to PIN_MODE_0 with the exception of JTAG pins 16,17,19,20
    //

    //
    // Enable Peripheral Clocks 
    //
    PRCMPeripheralClkEnable(PRCM_ADC, PRCM_RUN_MODE_CLK);
    PRCMPeripheralClkEnable(PRCM_TIMERA2, PRCM_RUN_MODE_CLK);
    PRCMPeripheralClkEnable(PRCM_TIMERA3, PRCM_RUN_MODE_CLK);
    PRCMPeripheralClkEnable(PRCM_GPIOA0, PRCM_RUN_MODE_CLK);
    PRCMPeripheralClkEnable(PRCM_GPIOA1, PRCM_RUN_MODE_CLK);
    PRCMPeripheralClkEnable(PRCM_GPIOA2, PRCM_RUN_MODE_CLK);
    PRCMPeripheralClkEnable(PRCM_GPIOA3, PRCM_RUN_MODE_CLK);
    PRCMPeripheralClkEnable(PRCM_GSPI, PRCM_RUN_MODE_CLK);
    PRCMPeripheralClkEnable(PRCM_UARTA0, PRCM_RUN_MODE_CLK);
    PRCMPeripheralClkEnable(PRCM_I2CA0, PRCM_RUN_MODE_CLK);

    //
    // Configure PIN_59 for ADC0 ADC_CH2
    //
    PinTypeADC(PIN_59, PIN_MODE_255);

    //
    // Configure PIN_04 for TimerCP4 GT_CCP04
    //
    PinTypeTimer(PIN_04, PIN_MODE_12);

    //
    // Configure PIN_63 for TimerCP6 GT_CCP06
    //
    PinTypeTimer(PIN_63, PIN_MODE_12);

    //
    // Configure PIN_50 for GPIO Output
    //
    PinTypeGPIO(PIN_50, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA0_BASE, 0x1, GPIO_DIR_MODE_OUT);

    //
    // Configure PIN_58 for GPIO Input
    //
    PinTypeGPIO(PIN_58, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA0_BASE, 0x8, GPIO_DIR_MODE_IN);

    //
    // Configure PIN_60 for GPIO Output
    //
    PinTypeGPIO(PIN_60, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA0_BASE, 0x20, GPIO_DIR_MODE_OUT);

    //
    // Configure PIN_61 for GPIO Output
    //
    PinTypeGPIO(PIN_61, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA0_BASE, 0x40, GPIO_DIR_MODE_OUT);

    //
    // Configure PIN_62 for GPIO Output
    //
    PinTypeGPIO(PIN_62, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA0_BASE, 0x80, GPIO_DIR_MODE_OUT);

    //
    // Configure PIN_64 for GPIO Input
    //
    PinTypeGPIO(PIN_64, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA1_BASE, 0x2, GPIO_DIR_MODE_IN);

    //
    // Configure PIN_03 for GPIO Input
    //
    PinTypeGPIO(PIN_03, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA1_BASE, 0x10, GPIO_DIR_MODE_IN);

    //
    // Configure PIN_15 for GPIO Output
    //
    PinTypeGPIO(PIN_15, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA2_BASE, 0x40, GPIO_DIR_MODE_OUT);

    //
    // Configure PIN_16 for GPIO Output
    //
    PinTypeGPIO(PIN_16, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA2_BASE, 0x80, GPIO_DIR_MODE_OUT);

    //
    // Configure PIN_17 for GPIO Input
    //
    PinTypeGPIO(PIN_17, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA3_BASE, 0x1, GPIO_DIR_MODE_IN);

    //
    // Configure PIN_18 for GPIO Output
    //
    PinTypeGPIO(PIN_18, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA3_BASE, 0x10, GPIO_DIR_MODE_OUT);

    //
    // Configure PIN_20 for GPIO Input
    //
    PinTypeGPIO(PIN_20, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA3_BASE, 0x20, GPIO_DIR_MODE_IN);

    //
    // Configure PIN_21 for GPIO Input
    //
    PinTypeGPIO(PIN_21, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA3_BASE, 0x2, GPIO_DIR_MODE_IN);

    //
    // Configure PIN_53 for GPIO Output
    //
    PinTypeGPIO(PIN_53, PIN_MODE_0, false);
    GPIODirModeSet(GPIOA3_BASE, 0x40, GPIO_DIR_MODE_OUT);

    //
    // Configure PIN_08 for SPI0 GSPI_CS
    //
    PinTypeSPI(PIN_08, PIN_MODE_7);

    //
    // Configure PIN_05 for SPI0 GSPI_CLK
    //
    PinTypeSPI(PIN_05, PIN_MODE_7);

    //
    // Configure PIN_06 for SPI0 GSPI_MISO
    //
    PinTypeSPI(PIN_06, PIN_MODE_7);

    //
    // Configure PIN_07 for SPI0 GSPI_MOSI
    //
    PinTypeSPI(PIN_07, PIN_MODE_7);

    //
    // Configure PIN_55 for UART0 UART0_TX
    //
    PinTypeUART(PIN_55, PIN_MODE_3);

    //
    // Configure PIN_57 for UART0 UART0_RX
    //
    PinTypeUART(PIN_57, PIN_MODE_3);

    //
    // Configure PIN_01 for I2C0 I2C_SCL
    //
    PinTypeI2C(PIN_01, PIN_MODE_1);

    //
    // Configure PIN_02 for I2C0 I2C_SDA
    //
    PinTypeI2C(PIN_02, PIN_MODE_1);
}


I am going to start with 3200ExositeDemo firmware example then make all the necessary changes to the original code. You will find the updated code here: Source code.

CC3200 WLAN code examples web page is here for your reference.

There are three tasks that will be executed by the program

Each task will be executed according to a task priority:
#define EXOSITE_TASK_PRIORITY    3
#define LOW_TASK_PRIORITY           1
#define HIGH_TASK_PRIORITY          4
#define SPAWN_TASK_PRIORITY       9
#define OSI_STACK_SIZE    2048 and will be executed by the OS.

Low priority numbers denote low priority tasks. The idle task has priority zero.


//
// Create Exosite Task
//
lRetVal = osi_TaskCreate(ExositeTask, (signed char*)"ExositeTask", \
	OSI_STACK_SIZE, NULL, \
	EXOSITE_TASK_PRIORITY, NULL );
if(lRetVal < 0)
{
	ERR_PRINT(lRetVal);
	LOOP_FOREVER();
} 		
		

Inside the ExositeTask the program determines if the board is in AP or STA mode: ReadDeviceConfiguration();. Then if board in STA mode (jumper on P58 is not placed for the original code, SW2 is pressed for the updated code) it will try to connect to a network.


Below is the original example code with the pin58 jumper:

//****************************************************************************
//
//!    \brief Read Force AP GPIO and Configure Mode - 1(Access Point Mode)
//!                                                  - 0 (Station Mode)
//!
//! \return                        None
//
//****************************************************************************
static void ReadDeviceConfiguration()
{
    unsigned int uiGPIOPort;
    unsigned char pucGPIOPin;
    unsigned char ucPinValue;
        
    //Read GPIO PIN_58 to verify the pull-up jumper.
    GPIO_IF_GetPortNPin(SH_GPIO_3,&uiGPIOPort,&pucGPIOPin);
    ucPinValue = GPIO_IF_Get(SH_GPIO_3,uiGPIOPort,pucGPIOPin);
        
    //If Connected to VCC, Mode is AP
    if(ucPinValue == 1)
    {
        //AP Mode
        g_uiDeviceModeConfig = ROLE_AP;
    }
    else
    {
        //STA Mode
        g_uiDeviceModeConfig = ROLE_STA;
    }

}		
		

I have changed the above shown function to read GPIO22 (SW2). This allows me to switch to AP mode at any time and enter the network settings.

static void ReadDeviceConfiguration()
{
    unsigned int uiGPIOPort;
    unsigned char pucGPIOPin;
    unsigned char ucPinValue;
        
    //Read GPIO 22
    GPIO_IF_GetPortNPin(SH_GPIO_22,&uiGPIOPort,&pucGPIOPin);
    ucPinValue = GPIO_IF_Get(SH_GPIO_22,uiGPIOPort,pucGPIOPin);
        
    //If Connected to VCC, Mode is AP
    if(ucPinValue == 1)
    {
        //AP Mode
        g_uiDeviceModeConfig = ROLE_AP;
    }
    else
    {
        //STA Mode
        g_uiDeviceModeConfig = ROLE_STA;
    }

}

The next step is a decision to either switch to AP mode or connect to a network. This is determined inside the ConnectToNetwork() function:

//Connect to Network
ret = ConnectToNetwork();
if(ret < 0)
{
	ERR_PRINT(ret);
	LOOP_FOREVER();
}
		

Inside ConnectToNetwork() function program determines if the board is in AP or STA mode.

//****************************************************************************
//
//!    \brief Connects to the Network in AP or STA Mode - If ForceAP Jumper is
//!                                             Placed, Force it to AP mode
//!
//! \return  0 - Success
//!            -1 - Failure
//
//****************************************************************************
long ConnectToNetwork()
{
    long lRetVal = -1;                  // Link return value
    unsigned int uiConnectTimeoutCnt = 0;

    // staring simplelink
    lRetVal =  sl_Start(NULL,NULL,NULL); // Initializing the Wi-Fi subsystem as a WLAN station
    ASSERT_ON_ERROR( lRetVal);	// Prints error code if lRetVal < 0

    //UART_PRINT("[EXO] We connected, but timed-out waiting for a response. Try again.\r\n");

    // Device is in AP Mode and Force AP Jumper is not Connected
    if(ROLE_STA != lRetVal && g_uiDeviceModeConfig == ROLE_STA )
    {
        if (ROLE_AP == lRetVal)
        {
            UART_PRINT("\r\nConnectToNetwork: Current AP mode, the jumper is not connected\r\n");
            // If the device is in AP mode, we need to wait for this event
            // before doing anything 
            while(!IS_IP_ACQUIRED(g_ulStatus))
            {
            #ifndef SL_PLATFORM_MULTI_THREADED
              _SlNonOsMainLoopTask(); 
            #endif
            }
        }
        //Switch to STA Mode
        lRetVal = ConfigureMode(ROLE_STA);
        UART_PRINT("\r\nConnectToNetwork: Switch to STA mode\r\n");
        ASSERT_ON_ERROR( lRetVal);
    }

    //Device is in STA Mode and Force AP Jumper is Connected
    if(ROLE_AP != lRetVal && g_uiDeviceModeConfig == ROLE_AP )
    {
         UART_PRINT("\r\nConnectToNetwork: Current ST mode, the jumper is connected\r\n");
         //Switch to AP Mode
         lRetVal = ConfigureMode(ROLE_AP);
         //UART_PRINT("\r\nConnectToNetwork: Switch to AP mode\r\n");
         ASSERT_ON_ERROR( lRetVal);

    }

    //No Mode Change Required
    if(lRetVal == ROLE_AP)
    {
         UART_PRINT("\r\nConnectToNetwork: Current AP mode\r\n");
        //waiting for the AP to acquire IP address from Internal DHCP Server
        // If the device is in AP mode, we need to wait for this event 
        // before doing anything 
        while(!IS_IP_ACQUIRED(g_ulStatus))
        {
        #ifndef SL_PLATFORM_MULTI_THREADED
            _SlNonOsMainLoopTask(); 
        #endif
        }
        //Stop Internal HTTP Server
        lRetVal = sl_NetAppStop(SL_NET_APP_HTTP_SERVER_ID);
        ASSERT_ON_ERROR( lRetVal);

        //Start Internal HTTP Server
        lRetVal = sl_NetAppStart(SL_NET_APP_HTTP_SERVER_ID);
        ASSERT_ON_ERROR( lRetVal);

       char cCount=0;
       
       //Blink LED 3 times to Indicate AP Mode
       for(cCount=0;cCount<3;cCount++)
       {
           //Turn RED LED On
           GPIO_IF_LedOn(MCU_RED_LED_GPIO);
           osi_Sleep(400);
           
           //Turn RED LED Off
           GPIO_IF_LedOff(MCU_RED_LED_GPIO);
           osi_Sleep(400);
       }

       char ssid[32];
       unsigned short len = 32;
       unsigned short config_opt = WLAN_AP_OPT_SSID; //AP Mode
       sl_WlanGet(SL_WLAN_CFG_AP_ID, &config_opt , &len, (unsigned char* )ssid);
       UART_PRINT("\n\r Connect to : \'%s\'\n\r\n\r",ssid);
    }
    else
    {
        UART_PRINT("\r\nConnectToNetwork: Current STA mode\r\n");
        //Stop Internal HTTP Server
        lRetVal = sl_NetAppStop(SL_NET_APP_HTTP_SERVER_ID);
        ASSERT_ON_ERROR( lRetVal);

        //Start Internal HTTP Server
        lRetVal = sl_NetAppStart(SL_NET_APP_HTTP_SERVER_ID);
        ASSERT_ON_ERROR( lRetVal);

        //waiting for the device to Auto Connect
        while(uiConnectTimeoutCnt<AUTO_CONNECTION_TIMEOUT_COUNT &&
            ((!IS_CONNECTED(g_ulStatus)) || (!IS_IP_ACQUIRED(g_ulStatus)))) 
        {
            //Turn RED LED On
            GPIO_IF_LedOn(MCU_RED_LED_GPIO);
            osi_Sleep(50);
            
            //Turn RED LED Off
            GPIO_IF_LedOff(MCU_RED_LED_GPIO);
            osi_Sleep(50);
            
            uiConnectTimeoutCnt++;
        }
        //Couldn't connect Using Auto Profile
        if(uiConnectTimeoutCnt == AUTO_CONNECTION_TIMEOUT_COUNT)
        {
            UART_PRINT("\r\nConnectToNetwork: Couldn't connect Using Auto Profile\r\n");
            //Blink Red LED to Indicate Connection Error
            GPIO_IF_LedOn(MCU_RED_LED_GPIO);    //Turn On red LED
            
            CLR_STATUS_BIT_ALL(g_ulStatus);

            //Connect Using Smart Config
            UART_PRINT("\r\nConnectToNetwork: Connecting Using Smart Config\r\n");
            lRetVal = SmartConfigConnect();
            ASSERT_ON_ERROR(lRetVal);

            //Waiting for the device to Auto Connect
            while((!IS_CONNECTED(g_ulStatus)) || (!IS_IP_ACQUIRED(g_ulStatus)))
            {
                MAP_UtilsDelay(500);              
            }
    }
    //Turn RED LED Off
    GPIO_IF_LedOff(MCU_RED_LED_GPIO);

    g_iInternetAccess = ConnectionTest();

    }
    return SUCCESS;
}			
			

To make it a little more convenient to switch to AP mode, I have made SW2 to have the same function as the pullup jumper on PIN_58. With the SW2 push button you can switch to AP mode at any time without restarting the board.
The updated code for the UptimeTask is:


static void UptimeTask( void *pvParameters )
{
    while(1)
    {

    	long   lRetVal = -1;
    	//GPIO_IF_LedOff(MCU_ORANGE_LED_GPIO);
        g_uptimeSec++;


        ReadDeviceConfiguration();
        //Device is in STA Mode and Force AP Jumper is Connected
        if(ROLE_AP != lRetVal && g_uiDeviceModeConfig == ROLE_AP )
        {
        	UART_PRINT("\r\nConnectToNetwork: Current ST mode, the SW2 is pressed\r\n");
           //Switch to AP Mode
           lRetVal = ConfigureMode(ROLE_AP);
           //UART_PRINT("\r\nConnectToNetwork: Switch to AP mode\r\n");
           ASSERT_ON_ERROR( lRetVal);

        }
        // Wait here if we're in AP Mode
        while(g_uiDeviceModeConfig != ROLE_STA){
        	osi_Sleep(1000);
        }


        UART_PRINT("\n\r\rExecuting UptimeTask\n\r\r");        
        osi_Sleep(1000);
    }
}