#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include <math.h>
#define RED_LED GPIO_NUM_4
#define GREEN_LED GPIO_NUM_2
#define LDR_PIN GPIO_NUM_32
#define AVG_WINDOW 10
#define SENSOR_THRESHOLD 500
const float GAMMA = 0.7;
const float RL10 = 50;
float ALA = 0; // Ambient Light Average -- name used to fit theme
float printLux = 0;
#define LDR_ADC_CHANNEL ADC1_CHANNEL_4
int Tstate;
int DCIstate;
// Task to blink an LED at 1 Hz (1000 ms period:500 ms ON, 500 ms OFF)
void blink_task(void *pvParameters)
{
Tstate = 0; // (TRANSMITTER STATE - 0 for not busy, 1 for busy)
DCIstate = 0; // DATA COLLECTION INDICATOR STATE
TickType_t currentTime = pdTICKS_TO_MS(xTaskGetTickCount());
while(1)
{
currentTime =pdTICKS_TO_MS(xTaskGetTickCount());
if(Tstate == 0)
{
gpio_set_level(RED_LED, 0);
DCIstate = !DCIstate;
gpio_set_level(GREEN_LED, DCIstate);
}
else if(Tstate == 1)
{
gpio_set_level(GREEN_LED, 0);
DCIstate = !DCIstate;
gpio_set_level(RED_LED, DCIstate);
}
// printf("LED Cycle %d @ %ld\n", DCIstate, currentTime); // used for testing
vTaskDelay(pdMS_TO_TICKS(500));
}
}
// Task to print a message every 1000 ms (1 seconds)
void print_task(void *pvParameters)
{
int counter = 0;
while (1)
{
if(counter < 10)
{
Tstate = 0;
printf("Scan in %d seconds... Current Lux : %.2f\n", (10 - counter), printLux);
counter++;
}
else if(counter >= 10)
{
Tstate = 1;
printf("Scanning...\n");
if(counter > 12)
{
printf("Scan Complete... ALA : %.2f\n\n", ALA);
counter = -1;
}
counter++;
}
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void sensor_task(void *pvParameters)
{
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(LDR_ADC_CHANNEL, ADC_ATTEN_DB_11);
int raw;
float vMeasured = 0.;
float rMeasured = 0.;
float lux = 0.;
int luxReadings[AVG_WINDOW] = {0};
int idx = 0;
float sum = 0;
for(int i = 0; i < AVG_WINDOW; ++i)
{
raw = adc1_get_raw(LDR_ADC_CHANNEL);
vMeasured = raw / 4096. * 3.3;
rMeasured = 10000 * vMeasured / (3.3 - vMeasured);
lux = pow(RL10 * 1e3 * pow(10, GAMMA) / rMeasured, (1 / GAMMA));
printLux = lux;
// printf("LUX : %.2f\n", lux); // removed, was being used for testing
luxReadings[i] = lux;
sum += luxReadings[i];
}
const TickType_t periodTicks = pdMS_TO_TICKS(500);
TickType_t lastWakeTime = xTaskGetTickCount();
while(1)
{
raw = adc1_get_raw(LDR_ADC_CHANNEL);
// printf("** raw ** : Sensor %d\n", raw);
vMeasured = raw / 4096. * 3.3;
rMeasured = 10000 * vMeasured / (3.3 - vMeasured);
lux = pow(RL10 * 1e3 * pow(10, GAMMA) / rMeasured, (1 / GAMMA));
printLux = lux;
// printf("LUX : %.2f\n", lux); // removed, was being used for testing
sum -= luxReadings[idx];
luxReadings[idx] = lux;
sum += lux;
idx = (idx + 1) % AVG_WINDOW;
float avg = sum / AVG_WINDOW;
ALA = avg;
if(avg > SENSOR_THRESHOLD)
{
printf("**ALERT** : Average ambient lighting exceeding optimal levels : %.2f\n", avg); // changed name of printed variable to fit theme
}
else
{
// printf("Ambient Light Average : %.2f\n", avg); // changed name of printed variable to fit theme
}
TickType_t currentTick = xTaskGetTickCount();
vTaskDelayUntil(&lastWakeTime, periodTicks); // remove for BONUS CODE
}
}
void app_main() {
// Initialize LED GPIO
gpio_reset_pin(RED_LED);
gpio_reset_pin(GREEN_LED);
gpio_reset_pin(LDR_PIN);
gpio_set_direction(RED_LED, GPIO_MODE_OUTPUT);
gpio_set_direction(GREEN_LED, GPIO_MODE_OUTPUT);
gpio_set_direction(LDR_PIN, GPIO_MODE_INPUT);
// Instantiate/ Create tasks:
// . pointer to task function,
// . descriptive name, [has a max length; located in the FREERTOS_CONFIG.H]
// . stack depth,
// . parameters [optional] = NULL
// . priority [0 = low],
// . pointer referencing this created task [optional] = NULL
// Learn more here https://www.freertos.org/Documentation/02-Kernel/04-API-references/01-Task-creation/01-xTaskCreate
xTaskCreatePinnedToCore(blink_task, "DCIOperation", 2048, NULL, 1, NULL, 1);
xTaskCreatePinnedToCore(print_task, "Print Task", 2048, NULL, 1, NULL, 1);
xTaskCreatePinnedToCore(sensor_task, "Sensor Task", 4096, NULL, 2, NULL, 1);
}