Skip to content

Набор функций, реализующих базовый функционал датчика пламени. Предназначен для обучения базовым принципам разработки пожарных и охранных датчиков.

License

Notifications You must be signed in to change notification settings

exatb/SimpleSensor

Repository files navigation

SimpleSensor

Набор функций, реализующих базовый функционал датчика пламени.

Этот проект предназначен для обучения базовым принципам разработки пожарных и охранных датчиков.

Работает на базе отладочных плат NUCLEO-L053R8 и NUCLEO-F072RB с подключенным модулем KY-026.

Включает общение по последовательному порту в режиме текстовых команд и протоколирование событий в энергонезависимой памяти.

Flame

Далее будет пошагово описано как сгенерировать проект в STM32CubeMX и добавить в него весь необходимый функционал.

Сборка пустого проекта в STM32CubeMX

Необходимо создать новый проект на базе отладочной платы NUCLEO-L053R8 или NUCLEO-F072RB.

Запускаем программу STM32CubeMX.

STM32CubeMX является визуальным графическим редактором для конфигурирования микроконтроллеров семейства STM32, позволяющим генерировать код на основе языка Си.

https://www.st.com/en/development-tools/stm32cubemx.html

Для создания проекта выбираем File→New Project, или воспользуемся горячей клавишей Ctr+N.

Выбираем Board Selector. В строке Commercial Part Number (находится в левой части окна раздела Board Selector) вводим название отладочной платы — NUCLEO-L053R8 или NUCLEO-F072RB. Из списка Boadrs List (располагается в центре окна) выбираем соотвествующую отладочную плату и нажимаем кнопку Start Project. Откроется окно Board Project Options. Нажимаем кнопку Yes (инициализируем всю периферию по умолчанию).

Для USART2 (вкладка Connectivity) в NVIC Settings включаем USART2 global interrupt. На вкладке Advanced Settings в разделе Driver Selector\USART выбираем «LL». Это означает подключение низкоуровневых библиотек для работы с последовательным портом.

На вкладке Clock Configuration для платы NUCLEO-L053R8 выбираем источник тактирования HSI в System Clock Mux. Для платы NUCLEO-F072RB он выбран по умолчанию.

На вкладке Pinout&Configuration для выводов контроллера PC0 и PC1 выбираем режимы работы и наименования:

  • PC0 режим GPIO mode выбираем Output Open Drain, имя User Label указываем OUT_OD.
  • PC1 режим GPIO mode выбираем External Interrupt Mode with Rising edge trigger detection, имя User Label указываем IN_RISING.

Включаем прерывание для соотвествующих ножек контроллера. Во вкладке NVIC Interrupt Table для GPIO включаем EXTI line 0 and 1 interrupts.

Для сторожевого таймера IWDG выбираем Activated.

Указываем наименование и путь к файлам проекта. Генерируем код кнопкой GENERATE CODE.

Сборка готового проекта

Открываем ранее созданный проект.

Файлы cmd.h, fifo.h, log.h, time.h, usart.h копируем в \Core\Inc.

Файлы cmd.c, fifo.c, log.c, time.c, usart.c копируем в \Core\Src.

Корректировка main.h

В файл main.h добавляем следующий код:

extern volatile uint8_t alarm_sensor;

Корректировка main.c

В main.c добавляем все заголовки:

#include "cmd.h"
#include "log.h"
#include "fifo.h"
#include "time.h"
#include "usart.h"

Добавляем определения:

#define IWDG_ENABLE

Добавляем переменные:

volatile uint8_t alarm_sensor;

В функцию MX_USART2_UART_Init() добавляем вызов USART_Init().

Добавляем следующие функции:

Простое преобразование из числа в строку

#define MAX_NUMBER_LEN 11

unsigned char * itoa(int32_t value, unsigned char base){
  static volatile unsigned char res[MAX_NUMBER_LEN+1] = {0};
  static unsigned char str[MAX_NUMBER_LEN] = {0};
  unsigned char resnum = 0;
  if (value<0)
  {
    res[resnum++] = '-';
    value=-value;
  }else
  if (value==0)
  {
    res[0]='0';
    res[1]=0;
    return (unsigned char*)res;
  }
  unsigned char ctr = MAX_NUMBER_LEN-1;
  str[ctr] = 0;
  while ((value != 0) && (ctr-1)){
    str[--ctr] = "0123456789abcdef"[value % base];
    value /= base;
  }
  while (ctr<MAX_NUMBER_LEN-1)
    res[resnum++]=str[ctr++];
  res[resnum] = 0;
  return (unsigned char*)res;
}

Вычитывание состояний из лога и отправка их в последованиельный порт

void ReadAndShowStates()
{
	for (int i=0;i<MAX_EVENTS;i++)
	{
		EVENT e = Read_Event();
		if (!e.time) continue;
		//Write state to terminal
		USART_Write_String((unsigned char*)"time=");
		USART_Write_String(itoa(e.time,10));
		USART_Write_String((unsigned char*)", event=");
		switch (e.data)
		{
		case CMD_LED_ON:
			USART_Write_String((unsigned char*)"LED ON");
			break;
		case CMD_LED_OFF:
			USART_Write_String((unsigned char*)"LED OFF");
			break;
		case CMD_OUT_ON:
			USART_Write_String((unsigned char*)"OUT ON");
			break;
		case CMD_OUT_OFF:
			USART_Write_String((unsigned char*)"OUT OFF");
			break;
		case CMD_BUTTON:
			USART_Write_String((unsigned char*)"BUTTON PRESSED");
			break;
		case CMD_ALARM:
			USART_Write_String((unsigned char*)"ALARM");
			break;
		case CMD_INFINITY:
			USART_Write_String((unsigned char*)"INFINITY CYCLE");
			break;
		default:
			USART_Write_String(itoa(e.data,10));
		}
		USART_Write_String((unsigned char*)"\r\n");
		USART_Send();
		HAL_Delay(10);

#ifdef IWDG_ENABLE
		HAL_IWDG_Refresh(&hiwdg);
#endif
	}
}

В функцию main() добавляем следующий код:

#ifdef IWDG_ENABLE
  MX_IWDG_Init();
#endif

alarm_sensor = 0;
LL_USART_EnableIT_RXNE(USART2);  
USART_Write_String((unsigned char*)"Ready\r\n");

В тело цикла while добавляем следующий код:

if (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin)==GPIO_PIN_RESET)
{
	USART_Write_String((unsigned char*)"Button pressed\r\n");
	Write_Event(CMD_BUTTON);
	USART_Send();
	HAL_Delay(100);
}

if (alarm_sensor)
{
	USART_Write_String((unsigned char*)"Alarm!!!\r\n");
	Write_Event(CMD_ALARM);
	USART_Send();
	alarm_sensor = 0;
	HAL_Delay(100);
}

uint16_t cmd = Cmd_Read();
if (cmd != CMD_NA)
{
	USART_Write_String((unsigned char*)"cmd=");
	USART_Write_String(itoa(cmd,10));
	USART_Write_String((unsigned char*)"\r\n");

	if (cmd!=CMD_READ_LOG)
			Write_Event(cmd);

	char OK = 1;
	switch (cmd)
	{
		case 	CMD_EEPROM_TEST:
			USART_Write_String((unsigned char*)"Start EEPROM test\r\n");
			USART_Send();

			HAL_StatusTypeDef status = HAL_OK;
			for (uint32_t adr = 0;adr<MAX_EVENTS;adr++)
			{
				status = Write_EEPROM(adr*4, (adr+10)<<16);
				#ifdef IWDG_ENABLE
					HAL_IWDG_Refresh(&hiwdg);
				#endif
				if (status!=HAL_OK) break;
			}

			uint32_t err = 0;
			if (status==HAL_OK){
				for (uint32_t adr = 0;adr<MAX_EVENTS;adr++)
				{
					if (Read_EEPROM(adr*4)!=((adr+10)<<16))
						{
							err = 1;
							break;
						}
				}
			}

			OK = (status==HAL_OK)&&(!err);

			break;
		case	CMD_LED_ON:
			HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
			break;
		case	CMD_LED_OFF:
			HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
			break;
		case	CMD_OUT_ON:
			HAL_GPIO_WritePin(OUT_OD_GPIO_Port, OUT_OD_Pin, GPIO_PIN_RESET);
			break;
		case	CMD_OUT_OFF:
			HAL_GPIO_WritePin(OUT_OD_GPIO_Port, OUT_OD_Pin, GPIO_PIN_SET);
			break;
		case	CMD_READ_LOG:
			ReadAndShowStates();
			break;
		case	CMD_BUTTON:
			break;
		case	CMD_ALARM:
			alarm_sensor = 1;
			break;
		case	CMD_INFINITY:
			while (1) {};
			break;
		default:
			OK = 0;
	}

	if (OK)
	{
		USART_Write_String((unsigned char*)"OK\r\n");
	}else
		USART_Write_String((unsigned char*)"FAILED\r\n");
}

USART_Send();
HAL_Delay(10);

#ifdef IWDG_ENABLE
HAL_IWDG_Refresh(&hiwdg);
#endif

Корректировка stm32f0xx_it.с

В файл stm32f0xx_it.с добавляем следующий код:

#include "time.h"
#include "usart.h"

В функцию SysTick_Handler добавляем вызов TimeShift1ms().

В функцию USART2_IRQHandler() добавляем вызов USART_IRQ().

В EXTI0_1_IRQHandler добавляем код:

alarm_sensor = 1;

Проверка

Компилируем код и запускаем на отладочной плате. Для взаимодействия с отладочной платой можно использовать программу ComTest.

https://github.com/exatb/ComTest

Должна быть корректная реакция на все команды.

image

Далее подключаем модуль KY-026 как показано на рисунке

Nucleo and KY-026

При возникновении пламени в зоне видимости фотодиода должно появляться сообщение Alarm!

Для ленивых

Собранные проекты для плат:

About

Набор функций, реализующих базовый функционал датчика пламени. Предназначен для обучения базовым принципам разработки пожарных и охранных датчиков.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages