#include "light_sensor_task.h" #include "ltimers/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 ) { (void)pvParameters; while(1)ProcessFSM_LightSensor (); }