Fighting Germs

Enter Your Project for a Chance to Win a Thermal Imaging Camera, Germicidal UV Lamp, and a Shopping Cart with Matching Charity Donation!

Submit an EntrySubmit an Entry  Back to homepage
Project14 Home
Monthly Themes
Monthly Theme Poll

 

1 Skip and Work with CubeMX

TouchGFX works fine if only with GUI, since most of the generated GUI codes and not open for revised. Normal revise shall break the simulation. So, work with CubeMX means say goodbye to TouchGFX normally.

Configurate pin and UART5 for ESP-01 connection can enrich the IoT but, there have been bugs, since the HAL_UART can not be added into the project automatically. Manually import the files or it can not pass.

 

2 FreeRTOS and CMSIS_RTOS_2

2.1 The whole project is based on FreeRTOS, but wrapped by CMSIS_RTOS. If one want to play both, that is fine. In this case , CMSIS RTOS is much easy to use.

Only create thread , then start the thread.

Best part of CMSIS is timer management, use osDelay(), can get expected delay without mix with other thread.

2.2 In this project , three thread is created. One for TouchGFX, one for UV lamp/ Hand_spray_santilizer, and one for wifi connect to get online data from covid cases.

The last one need bunches of code to parsing the HTML code.  Not enough time to build the whole backend web site

/* USER CODE BEGIN 0 */


int wifi_cccnt;
int hw_hs_onoff;
int hw_ruvc_onoff;
fgm fgm_status;
char *rec_data;
int WIFI_CONNECTED_OK;
void  HsRuvcTask(void *argument);
void  CCwifiTasky(void *argument);
void HsRuvcTask(void *argument)
{
// Room UVC on or off,
HAL_GPIO_WritePin(RU_onoff_GPIO_Port, RU_onoff_Pin, hw_ruvc_onoff);
// Hand Spray Part
hw_hs_onoff=HAL_GPIO_ReadPin(HS_hand_spray_GPIO_Port,HS_hand_spray_Pin) + hw_hs_onoff;
if (hw_hs_onoff >0)
{
HAL_GPIO_WritePin(HS_press_spray_GPIO_Port, HS_press_spray_Pin, GPIO_PIN_SET);
hw_hs_onoff=0;
osDelay(1000);
}
HAL_GPIO_WritePin(HS_press_spray_GPIO_Port, HS_press_spray_Pin, GPIO_PIN_RESET);
osDelay(100);
}
void  CCwifiTask(void *argument)
{


// Enter STA mode
if ( !WIFI_CONNECTED_OK )
{
strcpy(rec_data, "AT+CWMODE=1");
  if ( HAL_UART_Transmit(&huart5,&rec_data, 48, 60) != HAL_OK)
  {
    Error_Handler();
  }
  // Access Wifi with ssid and passwd
    if ( HAL_UART_Transmit(&huart5,"AT+CWJAP_DEF=\"ssid\",\"passwd.\"", 31, 60) != HAL_OK)
    {
      Error_Handler();
    }
  // Enter STA mode
    if ( HAL_UART_Transmit(&huart5,"AT+CWMODE=1", 11, 60) != HAL_OK)
      {
        Error_Handler();
      }
  WIFI_CONNECTED_OK=1;
}
else
{
  // GET CC_CNT data from local server,
    if ( HAL_UART_Transmit(&huart5,"AT+CIPSEND=8,\"192.168.1.1\",1000", 42, 60) != HAL_OK)
    {
      Error_Handler();
    }
  if ( HAL_UART_Transmit(&huart5,"GETCCCNT", 8, 60) != HAL_OK)
      {
        Error_Handler();
      }
  if ( HAL_UART_Receive(&huart5,*rec_data, 10, 60) != HAL_OK)
      {
        Error_Handler();
      }
  wifi_cccnt=atoi(rec_data);
}
}
 /* Init scheduler */
  osKernelInitialize();
  TouchGFXTaskHandle = osThreadNew(TouchGFX_Task, NULL, &TouchGFXTask_attributes);
/* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  HsRuvcTaskHandle = osThreadNew(HsRuvcTask, NULL, &HsRuvc_Task_attributes);
  CCwifiTaskHandle = osThreadNew(CCwifiTask, NULL, &CCwifi_Task_attributes);
  /* USER CODE END RTOS_THREADS */

 /* Start scheduler */
  osKernelStart();

 

3 The interface with GFX

3.1 Come back to main.c, the code flow is simple. Most of the hardware shall be controlled here.

int main(void)
{
  /* USER CODE BEGIN 1 */




  /* USER CODE END 1 */


  /* MPU Configuration--------------------------------------------------------*/
  MPU_Config();


  /* Enable I-Cache---------------------------------------------------------*/
  SCB_EnableICache();


  /* Enable D-Cache---------------------------------------------------------*/
  SCB_EnableDCache();


  /* MCU Configuration--------------------------------------------------------*/


  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();


  /* USER CODE BEGIN Init */
  wifi_cccnt=100;
  hw_hs_onoff=0;
  hw_ruvc_onoff=0;
  WIFI_CONNECTED_OK=0;


  //fgm_status.ruvconoff=9;


  /* USER CODE END Init */


  /* Configure the system clock */
  SystemClock_Config();


  /* USER CODE BEGIN SysInit */


  /* USER CODE END SysInit */


  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CRC_Init();
  MX_DSIHOST_DSI_Init();
  MX_LTDC_Init();
  MX_FMC_Init();
  MX_QUADSPI_Init();
  MX_DMA2D_Init();
  MX_I2C4_Init();
  MX_UART5_Init();
  MX_TouchGFX_Init();
  /* USER CODE BEGIN 2 */


  /* USER CODE END 2 */


  /* Init scheduler */
  osKernelInitialize();




  TouchGFXTaskHandle = osThreadNew(TouchGFX_Task, NULL, &TouchGFXTask_attributes);


  /* USER CODE BEGIN RTOS_THREADS */
  /* add threads, ... */
  HsRuvcTaskHandle = osThreadNew(HsRuvcTask, NULL, &HsRuvc_Task_attributes);
  CCwifiTaskHandle = osThreadNew(CCwifiTask, NULL, &CCwifi_Task_attributes);
  /* USER CODE END RTOS_THREADS */


  /* Start scheduler */
  osKernelStart();

  /* We should never get here as control is now taken by the scheduler */
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */


    /* USER CODE BEGIN 3 */


  }
  /* USER CODE END 3 */
}

3.2 The Interface with GFX is fairly close. It would be better leave as it is. There are three places for interface, the OsWrapper.c,  Model.cpp, and TouchGFXConfiguration.cpp. Other solution includes osMessage() between thread.Since this is not too complicated . simply use three global variables can make is.

In main.c, the

int wifi_cccnt;
int hw_hs_onoff;
int hw_ruvc_onoff;

and in different view  screen, data shall be updated as on/off control,

In covid cases views,

#include <gui/c_cases_screen/c_casesView.hpp>


c_casesView::c_casesView()
{


}


void c_casesView::setupScreen()
{
    c_casesViewBase::setupScreen();
}


void c_casesView::tearDownScreen()
{
    c_casesViewBase::tearDownScreen();
}


void c_casesView::cc_update_function()
{
    //touchgfx_printf("Enter into Case Covid19 pages.\n");
    cc_counter=presenter->get_cc_count();
    //cc_counter=1234;
    Unicode::snprintf(covidCaseBuffer, COVIDCASE_SIZE, "%d", cc_counter);
    covidCase.invalidate();


}

In hand santilizer view,

#include <gui/hand_santinizer_screen/hand_santinizerView.hpp>


hand_santinizerView::hand_santinizerView()
{


}


void hand_santinizerView::setupScreen()
{
    hand_santinizerViewBase::setupScreen();
    //hs_onoff=presenter->sget_hs_onoff(hs_onoff);
}


void hand_santinizerView::tearDownScreen()
{
    hand_santinizerViewBase::tearDownScreen();
}


void hand_santinizerView::handleTickEvent()
{
    //personblock_in= presenter->get_ruvc_personblock_in(); 
    //presenter->save_hs_onoff(personblock_in);
}


void hand_santinizerView::hs_function()
{
    //
    hs_onoff=(hs_onoff+1) %2;
    presenter->save_hs_onoff(hs_onoff);
    //touchgfx_printf("hs_onoff.");
}

In room uvc views,

#include <gui/room_uvc_screen/room_uvcView.hpp>


room_uvcView::room_uvcView()
{


}


void room_uvcView::setupScreen()
{
    room_uvcViewBase::setupScreen();
    ruvc_duration=60;
    ruvc_onoff=0;
    //ruvc_hour=presenter->get_ruvc_hour();
    //ruvc_minute=presenter->get_ruvc_minute();
}


void room_uvcView::tearDownScreen()
{
    room_uvcViewBase::tearDownScreen();
    //presenter->save_ruvc_hour(ruvc_hour);   
    //presenter->save_ruvc_minute(ruvc_minute);
}


void room_uvcView::handleTickEvent()
{
    tickCount=ruvc_onoff+tickCount;
    //personblock_in= presenter->get_ruvc_personblock_in(); //tickCount+btn_onoff;
    if (tickCount == 6000)
    {
        ruvc_minute++;
        ruvc_hour = (ruvc_hour - (ruvc_minute / 60)) % 24;
        ruvc_minute %= 60;
    }
    tickCount=tickCount %6000;
    ruvc_digitalClock1.setTime24Hour(ruvc_hour, 60-ruvc_minute-1, 59-tickCount/100);
    //presenter->save_ruvc_hour(ruvc_hour); //presenter->save_ruvc_minute(ruvc_minute);


}


void room_uvcView::ruvc_function()
{
    ruvc_onoff=(ruvc_onoff+1) %2;    
    presenter->save_ruvc_onoff(ruvc_onoff);
}


void room_uvcView::slider_function(int value)
{
    ruvc_onoff=1;   
    ruvc_hour= value /60; 
    ruvc_minute = value% 60;
    tickCount =0;
    //presenter->save_ruvc_onoff(ruvc_onoff);
}

Most important part in model.c, each view share data in model.c,

#include <gui/model/Model.hpp>
#include <gui/model/ModelListener.hpp>


extern int hw_hs_onoff;
extern int hw_ruvc_onoff;


Model::Model() : modelListener(0),
                cc_count(0),
                hs_onoff(0),
                ruvc_onoff(0),
                ruvc_hour(0),
                ruvc_minute(0)
{}

void Model::tick()
{

hw_hs_onoff=hs_onoff;
hw_ruvc_onoff=ruvc_onoff;

}

 

 

4 The How to use this smart home hub,

4.1 Welcome page, pause 5 seconds until next dash board main view appears.

Then the Covid cases view, now the data is 0, it can be updated when running. But the data has to be processed backend on AWS or Azure, in this case, I use local server "192.168.1.1". It shall be replaced.

 

The real part for hand santilizer, press the button, the motor shall rorary to punch the 75% alcohol sprayer, another part is from proximate sensor near the sprayer. Make it touch free sprayer.

 

The last part is Room UVC, I update the time control , press the button to make the UV lamp toggle on/off status. Use slider to change the setting time from 0 to 120 minutes.

 

4 Hardware control and demo

That part is not difficult. Like we used normally , one relay controlled 220V UV lamp  and one sprayer.

4.1 The UV lamp and the relay.

Wiring the hs_onoff_pin with the relay to control the on/off state of UVC lamp. The person shall be out of the room to keep from the harm to eyes.

The UV lamp go off when time count to zero.

 

4.2 The hand santinizer with alcohol spray.That is pushbutton hand spray of 75% medical spray for sanitizer. The free-run span of the button is 5mm, I could place one order for a screw rod and accessary for my 5-12V servo, to change the movement from spiral to linear. That is not difficult part. Just need some robust frame.  Since I have delayed in some Azure Configuration, the order is not arrived yet. But , anyone can make the design with all the parts easily.

 

5 Further to Go

This design is elastic and Can add more useful function freely. I hope this fighting germ idea can be of some help for all.

The whole touchGFX project  is attached in rar as reference.