MQTT topic and message description :

Kit have two Capsense button. I used that as two switches.

Capsense 1 --> Topic : cap1 --> Message : TURNON/TURNOFF

Capsense 2 --> Topic : cap2 --> Message : TURNON/TURNOFF

Flow Chart:

 .

Our module code is designed to handle all user operations to control home electronics appliances using our smart home automation system. The system offers four modes of operation:

Our module code allows for seamless integration of these four modes, offering users flexibility and convenience in controlling their home electronics appliances.

CypressCode:

1. To import C libraries in your code, you need to include their header files using the #include preprocessor directive. This allows you to use functions and data types from the library in your program.

#include "project.h"
#include "stdlib.h"
#include "cyapicallbacks.h"

2. The code snippet you provided consists of four C function prototypes. These are:

void updateLoad(void);
void loadWrite(uint8,uint8);
void HandleError(void);
void i2cReceive(void);

These function prototypes define the function name, return type, and parameters (if any) that the function accepts. They are often used as a way to declare functions before they are implemented or used in a program, helping to ensure that the function is properly defined and its usage is correct.

3. The code snippet you provided defines two preprocessor directives using the #define keyword.

#define LightloadNumber 4
#define FanLoadNumber 1

These preprocessor directives help to make the code more readable and maintainable by defining values that are used in multiple places throughout the program in one central location. Anytime the program needs to refer to the number of light or fan loads, it can use these macros instead of hardcoding the values, which makes the code more flexible and easier to modify in the future.

4. These lines are declaring and initializing various arrays and variables that will be used in the program for controlling the smart home automation system.

uint8 state_switch[LightloadNumber];       //status of touch switch
uint8 pre_switch[LightloadNumber];         //previous status of touch switch
uint8 state_load[LightloadNumber];         //status of load
uint8 state[LightloadNumber + FanLoadNumber + 1];   //state for communication 
uint8 pre_state[LightloadNumber + FanLoadNumber + 1];   //state for communication 
uint8 state_Fswitch[FanLoadNumber];   //status of fan switch
uint8 pre_Fswitch[FanLoadNumber];    //previous status of fan switch
uint8 fan_state[2];uint8 state_Fan[FanLoadNumber];    //status of fan regulator

uint8 Switch[] = {0,1,2,3};   // touch swich for light load(cap sense button 0,1,2,3)
uint8 Load[] = {0,1,2,3};  //load connection for switch (L0,L1,L2,L3)(relay)
uint8 F_UP_DWN[2] = {5,4}; //fan up and down touch switch(cap sense button 5,6)
uint8 Fan[4] = {7,6,5,4};  //fan output connection(L4,L5,L6,L7)
uint8 Fan_led[5] = {12,11,10,9,8}; // fan speed indicator led(L8,L9,L10,L11,L12)
uint8 white_led_load[] = {13,14,15,16}; //white led for each load(L13,L14,L15,L16)
uint8 Fan_UDW[2] = {18,17};  //fan up down white led
uint8 Fan_UDB[2] = {22,21};  //fan up down blue led

//smd button down
/*
uint8 F_switch[] = {6}; //fan touch switch (cap sense button 4)
uint8 Fan_BW[2] = {20,19};   //fan blue and white led 
uint8 Scenebut = {7};  //touch switch for smd pad(cap sense button 7)
uint8 scene_BW[2] = {23,24};  
//smd switch up down blue led
*/
// smd button up
uint8 F_switch[] = {7}; //fan touch switch (cap sense button 4)
uint8 Fan_BW[2] = {24,23};   //fan blue and white led 
uint8 Scenebut = {6};  //touch switch for smd pad(cap sense button 7)
uint8 scene_BW[2] = {19,20};  //smd switch up down blue led
uint8 ScenebutStatus = 0;uint8 pre_ScenebutStatus = 0;
uint8 whiteLed = 1;      //status of activation of white led of all loads//i2c

uint8 i2cReadBuffer[(LightloadNumber + FanLoadNumber + 1)];
uint8 i2cWriteBuffer[(LightloadNumber + FanLoadNumber + 1)];
uint8 I2CFlag = 0u;
uint8 sceneled = 0;
uint8 speed = 0;
int onOffFlag = 0;
uint8 flag = 0; 

5. A callback function:

void I2C_I2C_ISR_ExitCallback()
{    I2CFlag = 1; }

A callback function that is executed when the I2C (Inter-Integrated Circuit) module finishes sending or receiving data. Specifically, it is called when the I2C interrupt is triggered and signals that the I2C communication has completed.

In this particular code, the function sets a flag variable called I2CFlag to 1, indicating that the I2C communication has finished. This flag can be used by other parts of the code to determine when to take further action based on the results of the I2C communication.

6. The code that controls loads (lights and fans) using CapSense touch sensors and an I2C interface.

int main(void)
{
    memset(state_switch,0,sizeof(state_switch));
    memset(pre_switch,0,sizeof(pre_switch));
    memset(state,0,sizeof(state));
    memset(state_load,0,sizeof(state_load));
    memset(pre_state,0,sizeof(pre_state));
    memset(state_Fswitch,0,sizeof(state_Fswitch));
    memset(pre_Fswitch,0,sizeof(pre_Fswitch));
    memset(fan_state,0,sizeof(fan_state));
    memset(i2cReadBuffer,0,sizeof(i2cReadBuffer));  
    
    L13_Write(whiteLed);
    L14_Write(whiteLed);
    L15_Write(whiteLed);
    L16_Write(whiteLed);
    L17_Write(whiteLed);
    L18_Write(whiteLed);
    L19_Write(whiteLed);
    L23_Write(whiteLed);
      
    I2C_I2CSlaveInitReadBuf(i2cReadBuffer, (LightloadNumber + FanLoadNumber + 1));
    I2C_I2CSlaveInitWriteBuf(i2cWriteBuffer, (LightloadNumber + FanLoadNumber + 1));
    
    I2C_I2C_ISR_ExitCallback();
    
    CyGlobalIntEnable; 
    
    CySysWdtWriteMode(CY_SYS_WDT_COUNTER1, CY_SYS_WDT_MODE_RESET);
    CySysWdtWriteMatch(CY_SYS_WDT_COUNTER1, 0xFA00);
      
    CySysWdtWriteClearOnMatch(CY_SYS_WDT_COUNTER1, 1u);
    
    CySysWdtEnable(CY_SYS_WDT_COUNTER1_MASK);
    
    CapSense_1_Start();
    CapSense_1_InitializeAllBaselines();
    I2C_Start();
    
    for(;;)
    {
        if(0u == CapSense_1_IsBusy()){
            /* Update all baselines */
            CapSense_1_ProcessAllWidgets();
           
            /* Start scanning all enabled sensors */
            CapSense_1_ScanAllWidgets();
        }
        
        ScenebutStatus = CapSense_1_IsWidgetActive(Scenebut);
        if(ScenebutStatus != pre_ScenebutStatus){
            if(ScenebutStatus != 0 && onOffFlag == 0){
                onOffFlag = 1;
                for(int i = 0; i < LightloadNumber+FanLoadNumber; i++){
                    if(i<LightloadNumber)
                        loadWrite(Load[i],0);
                    state[i] = 0;
                }
                loadWrite(Fan_BW[0],0);
                if(whiteLed == 1){
                    for(int i = 0; i < LightloadNumber; i++){
                        loadWrite(white_led_load[i],1);
                    }
                    loadWrite(Fan_BW[1],1);
                }
            }
            else if(ScenebutStatus != 0 && onOffFlag == 1){
                onOffFlag = 0;
                for(int i = 0; i < LightloadNumber+FanLoadNumber; i++){
                    if(i<LightloadNumber)
                        loadWrite(Load[i],1);
                    state[i] = 1;
                }
                loadWrite(Fan_BW[0],1);
                if(whiteLed == 1){
                    for(int i = 0; i < LightloadNumber; i++){
                        loadWrite(white_led_load[i],0);
                    }
                    loadWrite(Fan_BW[1],0);
                }
            }
            pre_ScenebutStatus = ScenebutStatus;
        }
        
        if(state[0] != 1 && state[1] != 1 && state[2] != 1 && state[3] != 1 && state[4] != 1){    
            onOffFlag = 1;
        }
        else {
            onOffFlag = 0;
        }
        if(state[0] == 1 && state[1] == 1 && state[2] == 1 && state[3] == 1 && state[4] == 1){
            if(whiteLed == 1)
                loadWrite(scene_BW[0],0);
            loadWrite(scene_BW[1],1);           
        }
        else {
            if(whiteLed == 1)
                loadWrite(scene_BW[0],1);
            loadWrite(scene_BW[1],0);
        }
        
        
        for(uint8 i = 0 ; i < LightloadNumber ; i++){                    
           state_switch[i] = CapSense_1_IsWidgetActive(Switch[i]);
            if(state_switch[i] != pre_switch[i]){                         
                if(state_switch[i] != 0){
                    if(state[i] != 0)
                        state_load[i] = 0;
                    else 
                        state_load[i] = 1;
                    loadWrite(Load[i],state_load[i]);  
                    state[i] = state_load[i] ? 1 : 0;
                    if(whiteLed == 1)
                        loadWrite(white_led_load[i],!(state_load[i])); 
                }
                pre_switch[i] = state_switch[i];
            }
        }
        
        state_Fswitch[0] = CapSense_1_IsWidgetActive(F_switch[0]);
        if(state_Fswitch[0] != pre_Fswitch[0]){                         
            if(state_Fswitch[0] != 0){
                if(state[4] != 0)
                    state_Fan[0] = 0;
                else 
                    state_Fan[0] = 1;
                loadWrite(Fan_BW[0],state_Fan[0]);  
                state[4] = state_Fan[0] ? 1 : 0;
                if(whiteLed == 1)
                    loadWrite(Fan_BW[1],!(state_Fan[0])); 
                for (uint8 i = 0; i < 4; i++)
                    loadWrite(Fan[i], 0);
                if(state[4] == 1){
                    if(speed == 1){
                        loadWrite(Fan[1], 1);
                    } 
                    else if(speed == 2){
                        loadWrite(Fan[2], 1);
                    }
                    else if(speed == 3){
                        loadWrite(Fan[0], 1);
                        loadWrite(Fan[2], 1);
                    }
                    else if(speed == 4){
                        loadWrite(Fan[1], 1);
                        loadWrite(Fan[2], 1);
                    }
                    else if (speed == 5){
                        loadWrite(Fan[3], 1);
                    }
                }
                else if(state[4] == 0){
                    for (uint8 i = 0; i < 4; i++)
                        loadWrite(Fan[i], 0);
                } 
            }
            pre_Fswitch[0] = state_Fswitch[0];
        }
        
        if(CapSense_1_IsWidgetActive(F_UP_DWN[0]) != fan_state[0]){
            if(CapSense_1_IsWidgetActive(F_UP_DWN[0]) != 0){
                if(speed != 5)
                    speed++;                                 //fan state[3] increase by 1
                else
                    speed = 0;
                fan_state[0] = !(fan_state[0]);
                loadWrite(Fan_UDW[0],0);              // fan up white led off
                loadWrite(Fan_UDB[0],1);              //fan up blue led on
            }
            else{
                loadWrite(Fan_UDB[0],0);              //fan up blue led off
                if(whiteLed == 1)
                    loadWrite(Fan_UDW[0],1);          //fan up white led off
            }
            fan_state[0] = (CapSense_1_IsWidgetActive(F_UP_DWN[0]));
        }
        if(CapSense_1_IsWidgetActive(F_UP_DWN[1]) != fan_state[1]){             //check if fan down touch pad is pressed
            if(CapSense_1_IsWidgetActive(F_UP_DWN[1]) != 0){
                if(speed != 0)
                    speed--;                             //fan state[3] decrease by 1
                else
                    speed = 5;
                fan_state[1] = !(fan_state[1]);
                loadWrite(Fan_UDW[1],0);
                loadWrite(Fan_UDB[1],1);
            }
            else{
                loadWrite(Fan_UDB[1],0);
                if(whiteLed == 1)
                    loadWrite(Fan_UDW[1],1);
            }
            fan_state[1] = (CapSense_1_IsWidgetActive(F_UP_DWN[1]));
        }
        
        if(speed == 0){
            state[5] = 0;
            for(int i = 0;i<5;i++){
                loadWrite(Fan_led[i],0);            
            }
        }
        else if(speed == 1){
            state[5] = 1;
            loadWrite(Fan_led[0],1);
            for(int i = 1;i<5;i++){
                loadWrite(Fan_led[i],0);            
            }
        }
        else if(speed == 2){
            state[5] = 2;
            for(int i = 0;i<2;i++){
                loadWrite(Fan_led[i],1);            
            }
            for(int i = 2;i<5;i++){
                loadWrite(Fan_led[i],0);            
            }
        }
        else if(speed == 3){
            state[5] = 3;
            for(int i = 0;i<3;i++){
                loadWrite(Fan_led[i],1);            
            }
            for(int i = 3;i<5;i++){
                loadWrite(Fan_led[i],0);            
            }
        }
        else if(speed == 4){
            state[5] = 4;
            for(int i = 0;i<4;i++){
                loadWrite(Fan_led[i],1);            
            }
            loadWrite(Fan_led[4],0);  
        }
        else if(speed == 5){
            state[5] = 5;
            for(int i = 0;i<5;i++){
                loadWrite(Fan_led[i],1);            
            }
        }
        
        if(state[5] != pre_state[5]){
            for (uint8 i = 0; i < 4; i++)
                loadWrite(Fan[i], 0);
            if(state[4] == 1){
                if(speed == 1){
                    loadWrite(Fan[1], 1);
                } 
                else if(speed == 2){
                    loadWrite(Fan[2], 1);
                }
                else if(speed == 3){
                    loadWrite(Fan[0], 1);
                    loadWrite(Fan[2], 1);
                }
                else if(speed == 4){
                    loadWrite(Fan[1], 1);
                    loadWrite(Fan[2], 1);
                }
                else if (speed == 5){
                    loadWrite(Fan[3], 1);
                }
            }
            //pre_state[5] = state[5];
        }
            
        
        if(I2CFlag != 0)
        {
            I2CFlag = 0;  
            if (0u != (I2C_I2C_SSTAT_WR_CMPLT & I2C_I2CSlaveStatus()))
            {
                i2cReceive();
                I2C_I2CSlaveClearWriteBuf();
                (void) I2C_I2CSlaveClearWriteStatus();
            }
            
            if(0u != (I2C_I2C_SSTAT_RD_CMPLT & I2C_I2CSlaveStatus()))
            {
                I2C_I2CSlaveClearReadBuf();
                (void) I2C_I2CSlaveClearReadStatus();
            }          
        }
        
        for(uint8 i = 0 ; i < LightloadNumber + FanLoadNumber + 1; i++){
            if(state[i] != pre_state[i]){
                if((I2C_I2C_SSTAT_RD_BUSY & I2C_I2CSlaveStatus()) == 0){
                    pre_state[i] = state[i];
                    i2cReadBuffer[i] = state[i];
                }
            }
        }
        CySysWatchdogFeed(CY_SYS_WDT_COUNTER1);
    }
}

The program initializes the various memory locations to zero and sets the state of the loads to zero. It then initializes and enables the Watchdog Timer, CapSense module, and I2C interface.

In the main loop, the program scans all enabled sensors and checks the status of the Scene button. If the Scene button is pressed, the program turns on/off all the loads depending on their previous state. If all loads are on, the program turns on the "All off" button and turns off the "All on" button, and vice versa.

The program then checks the status of the touch sensors for each load and sets the state of the loads accordingly. It also checks the status of the Fan switch and sets the state of the Fan load accordingly. If the white LED is on, the program sets the state of the white LED load accordingly.

The program also sets the various memory locations to their respective values in order to ensure proper functioning. The program then repeats this loop continuously.

7. This is a function that receives data over I2C communication and updates the states of various loads connected to the microcontroller accordingly.

void i2cReceive(void){
    for (uint8 i = 0; i < LightloadNumber; i++) {
        state[i] = i2cWriteBuffer[i];
        if (state[i] == 0) {
            loadWrite(Load[i],0);
            if(whiteLed == 1)
                loadWrite(white_led_load[i],1);
        }
        else if (state[i] == 1) {
            loadWrite(Load[i], 1);
            loadWrite(white_led_load[i],0);
        }
    }
    
    state[4] = i2cWriteBuffer[4];
    if(state[4] != 0)
        state_Fan[0] = 0;
    else 
        state_Fan[0] = 1;
    loadWrite(Fan_BW[0],!state_Fan[0]);  
    loadWrite(Fan_BW[1],(state_Fan[0])); 
    
    state[5] = i2cWriteBuffer[5];
    speed = i2cWriteBuffer[5];

    for (uint8 i = 0; i < 4; i++)
        loadWrite(Fan[i], 0);
    if(state[4] == 1){
        if(speed == 1){
            loadWrite(Fan[1], 1);
        } 
        else if(speed == 2){
            loadWrite(Fan[2], 1);
        }
        else if(speed == 3){
            loadWrite(Fan[0], 1);
            loadWrite(Fan[2], 1);
        }
        else if(speed == 4){
            loadWrite(Fan[1], 1);
            loadWrite(Fan[2], 1);
        }
        else if (speed == 5){
            loadWrite(Fan[3], 1);
        }
    }
}

The function starts by iterating through a for loop that goes up to a value defined by the macro LightloadNumber. For each iteration, the state of a particular load is updated with the corresponding value received over I2C communication. If the state is zero, the corresponding load is turned off, and if the whiteLed variable is set to one, the white LED load is turned on. If the state is one, the corresponding load is turned on, and the white LED load is turned off.

After the loop, the state of the Fan load is updated based on the value received over I2C communication at index 4 of the i2cWriteBuffer array. If this value is zero, then the Fan load is turned on, and if it is one, the Fan load is turned off. The state of the Fan is then used to set the state of two other loads (Fan_BW[0] and Fan_BW[1]) using bitwise NOT and bitwise AND operations.

Finally, the speed of the Fan load is updated based on the value received over I2C communication at index 5 of the i2cWriteBuffer array. Depending on the value of the speed, different combinations of loads (Fan[0] to Fan[3]) are turned on or off.

8. Function loadWrite

void loadWrite(uint8 loadpin,uint8 state){
    switch(loadpin){
        case 0:
            L0_Write(state);
            break;
        case 1:
            L1_Write(state);
            break;
        case 2:
            L2_Write(state);
            break;
        case 3:
            L3_Write(state);
            break;
        case 4:
            L4_Write(state);
            break;
        case 5:
            L5_Write(state);
            break;
        case 6:
            L6_Write(state);
            break;
        case 7:
            L7_Write(state);
            break;
        case 8:
            L8_Write(state);
            break;
        case 9:
            L9_Write(state);
            break;
        case 10:
            L10_Write(state);
            break;
        case 11:
            L11_Write(state);
            break;   
        case 12:
            L12_Write(state);
            break;
        case 13:
            L13_Write(state);
            break;
        case 14:
            L14_Write(state);
            break;
        case 15:
            L15_Write(state);
            break;
        case 16:
            L16_Write(state);
            break;
        case 17:
            L17_Write(state);
            break;
        case 18:
            L18_Write(state);
            break;
        case 19:
            L19_Write(state);
            break;
        case 20:
            L20_Write(state);
            break;
        case 21:
            L21_Write(state);
            break;
        case 22:
            L22_Write(state);
            break;
        case 23:
            L23_Write(state);
            break;
        case 24:
            L24_Write(state);
            break;
    }      
}

This function loadWrite is used to write a digital state (high or low) to a specific load pin. The function takes two arguments: the first argument loadpin is an integer that specifies the load pin number (ranging from 0 to 24), and the second argument state is an integer that specifies the state of the load pin (0 or 1, low or high).

The function uses a switch-case statement to determine which load pin to write to based on the value of loadpin. Each case corresponds to a specific load pin number and calls the appropriate function (e.g. L0_WriteL1_Write, etc.) to write the specified state to that load pin.

9. Function HandleError:

void HandleError(void)
{   

     /* Disable all interrupts. */
    __disable_irq();

    /* Infinite loop. */
    while(1u) {}
}

 The HandleError() function is used to handle errors in the firmware. It disables all interrupts and enters an infinite loop, effectively stopping the execution of the program. This function is typically called when a serious error is detected that cannot be recovered from, such as a hardware fault or a critical software error. By entering an infinite loop, the program is effectively halted, preventing any further damage or malfunction from occurring. This function is commonly used in safety-critical systems where the failure of the system could result in harm to people or damage to property.

 Alexa and Google Home Development:

RequiredAccount:

1. AWS account (https://aws.amazon.com/)

2. Alexa Developer (https://developer.amazon.com/en-US/alexa)

3. Google Cloud Developer (https://console.cloud.google.com)

To develop an Amazon Alexa smart home skill, you can follow the steps provided in the video. Be sure to set up a rule that enables the Lambda function to read data from DynamoDB, which will give you the ability to display real-time switch statuses in both the Amazon Alexa and Google Home applications.

Schematics: