summaryrefslogtreecommitdiff
path: root/app/light_sensor/light_sensor_task.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/light_sensor/light_sensor_task.c')
-rw-r--r--app/light_sensor/light_sensor_task.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/app/light_sensor/light_sensor_task.c b/app/light_sensor/light_sensor_task.c
new file mode 100644
index 0000000..d1a0f89
--- /dev/null
+++ b/app/light_sensor/light_sensor_task.c
@@ -0,0 +1,202 @@
+#include "light_sensor_task.h"
+#include "ltimers.h"
+
+// FreeRTOS includes
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+
+// Если используется фоторезистор:
+// - калибровка датчика освещенности ?
+// - добавить гистерезис
+// - плавное изменение яркости
+// - как будет реагировать фоторезистор на мерцание 50 Гц, 100 Гц на диодное и тд.
+
+// * Фоторезистор GL5516 стоит в нижнем плече делителя. В врехнем плече на питание
+// +3.3В подключен резистор 10К.
+// Фоторезистор в полной темноте дает сопротивление до 6МОм, на свету у окна
+// в пасмурную питерскую погоду около 200 Ом, а если на ярком солнце, то и еще
+// меньше.
+// В итоге, чем ярче освещение, тем ниже сопротивление, тем ниже напряжение
+// на АЦП.
+//
+// Порог переключения яркости ламп нужно в приложении настраивать под себя.
+// И сделать по умолчанию.
+//
+// - теперь нужно опытным путем определить порог, когда лампам нужно убавить яркость
+// Для начала сделать только два варианта - светло/темно.
+
+#define LIGHT_THREHSOLD 3300 // Значение АЦП, подобранное опытным путем
+#define LIGHT 0
+#define DARK 1
+
+#define TIME_LIGHT_SENSOR 3000 //ms
+
+static void ADC_Config(void);
+
+static uint16_t ADC_ConvertedValue = 0;//, ADC_ConvertedVoltage = 0;
+QueueHandle_t queue_light_sensor;
+
+// ----------------------------------------------------------------------------
+//
+// ----------------------------------------------------------------------------
+void LightSensorInit ( void )
+{
+ // - ADC init
+ ADC_Config ();
+ queue_light_sensor = xQueueCreate ( 1, sizeof (LightSensorState_t) );
+ configASSERT( queue_light_sensor );
+}
+
+
+// ----------------------------------------------------------------------------
+//
+// ----------------------------------------------------------------------------
+static void ADC_Config(void)
+{
+ ADC_InitTypeDef ADC_InitStructure;
+ GPIO_InitTypeDef GPIO_InitStructure;
+
+ /* GPIOC Periph clock enable */
+ RCC_AHBPeriphClockCmd(LIGHT_SENSOR_RCC_AHBPeriph_GPIOx, ENABLE);
+
+ /* ADC1 Periph clock enable */
+ LIGHT_SENSOR_RCC_APBxPeriphClockCmd(LIGHT_SENSOR_RCC_APBxPeriph_ADCx, ENABLE);
+
+ /* Configure ADC Channelx as analog input */
+ GPIO_InitStructure.GPIO_Pin = LIGHT_SENSOR_GPIO_PINx ;
+ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
+ GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
+ GPIO_Init(LIGHT_SENSOR_GPIOx, &GPIO_InitStructure);
+
+ /* ADCs DeInit */
+ ADC_DeInit(LIGHT_SENSOR_ADCx);
+
+ /* Initialize ADC structure */
+ ADC_StructInit(&ADC_InitStructure);
+
+ /* Configure the ADC1 in continuous mode with a resolution equal to 12 bits */
+ ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
+ ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
+ ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
+ ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
+ ADC_InitStructure.ADC_ScanDirection = ADC_ScanDirection_Upward;
+ ADC_Init(LIGHT_SENSOR_ADCx, &ADC_InitStructure);
+
+ /* Convert the ADC1 Channel 11 with 239.5 Cycles as sampling time */
+ ADC_ChannelConfig(LIGHT_SENSOR_ADCx, LIGHT_SENSOR_ADC_Channelx , ADC_SampleTime_239_5Cycles);
+
+ /* ADC Calibration */
+ ADC_GetCalibrationFactor(LIGHT_SENSOR_ADCx);
+
+ /* Enable the ADC peripheral */
+ ADC_Cmd(LIGHT_SENSOR_ADCx, ENABLE);
+
+ /* Wait the ADRDY flag */
+ while(!ADC_GetFlagStatus(LIGHT_SENSOR_ADCx, ADC_FLAG_ADRDY));
+
+ /* ADC1 regular Software Start Conv */
+ ADC_StartOfConversion(LIGHT_SENSOR_ADCx);
+
+}
+
+
+// ----------------------------------------------------------------------------
+//
+// ----------------------------------------------------------------------------
+void ProcessFSM_LightSensor ( void )
+{
+ static uint8_t process_light_state = 0;
+ LightSensorState_t light_sensor_state;
+ /* Test EOC flag */
+ // - заменить этот файл на проверку и выход
+ while(ADC_GetFlagStatus(LIGHT_SENSOR_ADCx, ADC_FLAG_EOC) == RESET);
+ /* Get ADC1 converted data */
+ ADC_ConvertedValue = ADC_GetConversionValue(LIGHT_SENSOR_ADCx);
+ switch ( process_light_state )
+ {
+ case 0: // ждем когда посветлеет
+ if (ADC_ConvertedValue < LIGHT_THREHSOLD) // если стало светло
+ {
+ // - запускаем таймер, в течение которого проверяем освещение
+ StartLTimer (LTIMER_LIGHT_SENSOR);
+ // - переходим в состояние проверки яркости в течение таймера
+ process_light_state = 2;
+ }
+ break;
+ case 1: // ждем когда потемнет
+ if (ADC_ConvertedValue > LIGHT_THREHSOLD) // если стало темно
+ {
+ // - запускаем таймер, в течение которого проверяем освещение
+ StartLTimer (LTIMER_LIGHT_SENSOR);
+ // - переходим в состояние проверки яркости в течение таймера
+ process_light_state = 3;
+ }
+ break;
+ case 2:
+ if ( GetLTimer (LTIMER_LIGHT_SENSOR) >= TIME_LIGHT_SENSOR )
+ {
+ // - если таймер вышел, значит подтверждается новое значение
+ // освещенности
+ // - отправляем сообщение на смену режима
+ light_sensor_state = LIGHT_SENSOR_STATE_LIGHT;
+ xQueueSend ( queue_light_sensor, &light_sensor_state, 0 );
+ // - а затем идем проверять когда потемнеет
+ process_light_state = 1;
+ }
+ else
+ {
+ // - если таймер еще тикает, то проверяем освещенность
+ // и, если она изменилась, то возвращаемся в состояние 0
+ // то есть в начало алгоритма проверки яркости (освещенности)
+ if (ADC_ConvertedValue < LIGHT_THREHSOLD)
+ {
+ // то ничего не меняем
+ }
+ else
+ {
+ process_light_state = 0;
+ }
+ }
+ break;
+ case 3:
+ if ( GetLTimer (LTIMER_LIGHT_SENSOR) >= TIME_LIGHT_SENSOR )
+ {
+ // - если таймер вышел, значит подтверждается новое значение
+ // освещенности
+ // - отправляем сообщение на смену режима
+ light_sensor_state = LIGHT_SENSOR_STATE_DARK;
+ xQueueSend ( queue_light_sensor, &light_sensor_state, 0 );
+ // - а затем идем проверять когда посветлеет
+ process_light_state = 0;
+ }
+ else
+ {
+ // - если таймер еще тикает, то проверяем освещенность
+ // и, если она изменилась, то возвращаемся в состояние 0
+ // то есть в начало алгоритма проверки яркости (освещенности)
+ if (ADC_ConvertedValue > LIGHT_THREHSOLD)
+ {
+ // то ничего не меняем
+ }
+ else
+ {
+ process_light_state = 1;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ vTaskDelay (100);
+}
+
+
+// ----------------------------------------------------------------------------
+// Задача ОС, реализующая головную задачу программы
+// ----------------------------------------------------------------------------
+void LightSensor_Task ( void *pvParameters )
+{
+ while(1)ProcessFSM_LightSensor ();
+}