This project simulates a thermostat with Wi-Fi connectivity. The IOT device used as the embedded system for this project is a CC3220S-LAUNCHXL microcontroller. This device was purchased the SNHU Bookstore as part of the SimpleLink™ Wi-Fi® CC3220S wireless microconontroller LaunchPad™ development kit.
-
- SIMPLELINK-CC32XX-SDK (Installed through CCS)
-
Visual Studio Code (Mainly for the extensions and integrated version control)
-
Visual Studio Code Extensions:
- C/C++ (Extension ID: ms-vscode.cpptools)
- Doxygen Documentation Generator (Extension ID: cschlosser.doxdocgen)
Documentation for the CC3220S-LAUNCHXL
This module provides an implementation for simulating a thermostat using various peripherals and callback functions. The code is designed to meet the following specifications:
The thermostat utilizes a task scheduler algorithm to manage different tasks at specific intervals. The algorithm performs three main tasks:
- Checking button flags every 200ms
- Reading the temperature and updating the LED every 500ms
- Outputting data to the UART every second
The timer interrupt flag (TimerFlag
) is used to synchronize and control the execution of these tasks. The timer period is configured appropriately to achieve the desired task intervals.
The lab guide provides the following code as an example for the task scheduler:
// Loop Forever
while (1)
{
// Every 200ms check the button flags
// Every 500ms read the temperature and update the LED
// Every second output the following to the UART
// "<02%d,%02d,%d,%04d>", temperature, setpoint, heat, seconds
DISPLAY( snprintf(output, 64, "<02%d,%02d,%d,%04d>\n\r", temperature, setpoint, heat, seconds))
// Wait for timer period
while (!TimerFlag){}
TimerFlag = 0;
++timer;
}
The below algorithm accomplishes all tasks in the intervals they need to be performed:
To summarize the above flowchart, the algorithm performs four basic steps:
- Iterate through a list of tasks
- Update how long the task has been waiting
- Check if the task has waited long enough
- Execute the task and then set it to wait the scheduled amount of time
- UART (Universal Asynchronous Receiver-Transmitter): The UART is used to establish communication with external devices. The thermostat initializes the UART with
initUART()
before callinginitI2C()
andinitTimer()
. - I2C (Inter-Integrated Circuit): The thermostat uses I2C communication to interface with temperature sensors. The initialization function
initI2C()
configures the I2C driver with the desired parameters, such as the bit rate (e.g., 400kHz). It then scans for the presence of temperature sensors by checking their addresses. - Timer The timer is utilized to generate periodic interrupts for task scheduling. The
initTimer()
function initializes and starts the timer with the appropriate configuration, including the desired timer period.
The Wi-Fi connection is first set up through the SimpleLink™ Wi-Fi® Start Pro app. Once the profile is provisioned, the device's default setting is to connect to the WLAN automatically on startup. From here, the device may perform cloud operations based on the needs of the device. There are several modules that can be configured for the developer to use the included networking drivers that come with the SimpleLink CC32XX SDK.
The CC3220 has 256 KB of RAM and 1 MB of flash memory. The first indication that the project is designed within the memory limitations of the device is that it runs on board. The compiler will not be able to load the compiled .out file if there is not enough flash memory. The .out file is 374 KB, which within the 1 MB limit. The project is also within the RAM limitations because there are no memory address issues. I learned this earlier when certain variables caused ISR faults due to inaccessible memory addresses.
This header file contains the implementation of tasks and task scheduling for the thermostat project.
Tasks are defined using the Task_Object
and Task_Params
structures and task functions. The Task_Object
structure contains the necessary information for a task, including the task function pointer, period, elapsed time, and state. The parameters of a Task_Object
should not be initialized directly and should be set using a Task_Params
with `void Task_init(Task_Object *task, Task_Params *params)'.
typedef struct {
int state;
uint32_t period;
Task_stateMachineFxn callBack;
} Task_Params;
typedef struct {
int state;
uint32_t period;
uint32_t elapsedTime;
Task_stateMachineFxn callBack;
} Task_Object;
The task function should have the following signature:
int callBack(int state);
The state
parameter represents the current state of the task, and the function should return the success status.
- Include the
task.h
header in your source file:
#include "header/task.h"
- Define the states, state machine, and any necessary functions or macros for your task.
#define SM_SUCCESS 0
#define SM_FAIL -1
static enum {
DM_SMStart,
DM_WAIT,
DM_TIME_REACHED,
DM_DISPLAY_MESSAGE
} DM_State;
int displayMessageMachine(int state) {
// Transitions
switch (state) {
case (DM_SMStart):
state = DM_WAIT;
break;
case (DM_WAIT):
state = DM_DISPLAY_MESSAGE;
break;
case (DM_DISPLAY_MESSAGE):
default:
state = DM_WAIT;
break;
}
// Actions
switch (state) {
case (DM_DISPLAY_MESSAGE):
updateThermostatUptime();
DISPLAY(snprintf(output, 64, "<%02d,%02d,%d,%04d>\n\r",
thermostatData.temperature,
thermostatData.setpoint,
thermostatData.heat,
thermostatData.seconds))
break;
case (DM_WAIT):
break;
case (DM_SMStart):
default:
return SM_FAIL;
}
return SM_SUCCESS;
}
- Define the required task using the
Task_Object
structure and initialize the parameters.
Task_Object displayMessageTask;
Task_Params params;
Task_Params_init(*params);
params.state = DM_SMStart;
params.period = MESSAGE_PERIOD_US;
params.callBack = displayMessageMachine;
- Initialize the task using the
Task_init()
function.
Task_init(&displayMessageTask, ¶ms);