#define TCNT2_US_PERIOD 125
#define TCNT2_PRESCALER 8
void initADC()
{
noInterrupts();
ADCSRA = 0;
// Setting the ADC
// Set ADC prescaler to 8 - 125KHz sample rate @ 16MHz
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
ADMUX = 0;
// Set voltage reference
// REFS1 REFS0 Voltage Reference Selection
// 0 0 AREF, Internal Vref turned off
// 0 1 AVCC with external capacitor at AREF pin
// 1 0 Reserved
// 1 1 Internal 1.1V Voltage Reference with external capacitor at AREF pin
ADMUX |= (1 << REFS0);
// Enable ADC and ADC interrupt
ADCSRA |= (1 << ADEN) | (1 << ADIE);
// Start first conversion which takes 25 cycles
ADCSRA |= (1 << ADSC); // Start conversion
// Wait for the first conversion to complete
while (!(ADCSRA & ADIF));
interrupts();
}
uint16_t adc_value[6] = {0};
volatile double light_filtered = 0;
#define IDF_LENGTH 40
//Low Pass Filter ****************************
double lp_filter_value = 0.0;
double dT = 500e-6 * IDF_LENGTH; //Sekunden
double Tau = 60; //Sekunden, Zeitkonstante Tau
double alpha = dT / Tau;
//*********************************************
ISR(ADC_vect)
{
static uint8_t adc_sample_table[] = {0, 1, 0, 3, 0, 1, 0, 5};
static uint8_t adc_index = 0;
static uint16_t light_filter_sum = 0;
static uint16_t lf_index = 0;
adc_value[adc_sample_table[adc_index]] = ADC;
if (adc_index == 0 || adc_index == 4)
{
light_filter_sum += ADC;
//IDF Filter
if (++lf_index == IDF_LENGTH)
{
light_filtered = light_filter_sum;
light_filtered /= IDF_LENGTH;
light_filter_sum = 0;
lf_index = 0;
//Low Pass Filter ******************************************************
lp_filter_value = alpha * light_filtered + (1 - alpha) * lp_filter_value;
//**********************************************************************
}
}
adc_index++;
if (adc_index == 8) adc_index = 0;
ADMUX = (ADMUX & 0xF0) | adc_sample_table[adc_index];
}
void initUltimateTimer()
{
noInterrupts();
TCCR2A = (1 << WGM21);
TCCR2B = (1 << CS21);
OCR2A = TCNT2_US_PERIOD * F_CPU / 1e6 / TCNT2_PRESCALER - 1;
TIMSK2 = (1 << OCIE2A);
interrupts();
}
volatile unsigned int tcnt2_count = 0;
volatile unsigned long timer2_counter = 0;
volatile unsigned long timer3_counter = 0;
ISR(TIMER2_COMPA_vect)
{
ADCSRA |= (1 << ADSC); // Start conversion
timer2_counter++;
timer3_counter++;
}
#define SIZE 250
//static float art_light[SIZE];
#define LED_ORANGE 11
void setup()
{
Serial.begin(115200);
//AVCC with external capacitor at AREF pin
initADC();
initUltimateTimer();
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(LED_ORANGE, OUTPUT);
}
#define ON 1
#define OFF 0
void loop()
{
Serial.print("1023,");
Serial.print(adc_value[0]);
Serial.print(",");
Serial.print(light_filtered);
Serial.print(",");
Serial.print(lp_filter_value);
Serial.println(",0");
static double lux_value = 4.0/3 * lp_filter_value - 550.0/3;
static uint8_t light_state = OFF;
//State Machine 1
switch (light_state)
{
case OFF: if (lux_value < 500)
{
digitalWrite(8, HIGH);
light_state = ON;
}
break;
case ON: if (lux_value > 520)
{
digitalWrite(8, LOW);
light_state = OFF;
}
break;
}
static uint8_t cloud_state = OFF;
//State Machine 2
switch (cloud_state)
{
case OFF: if (light_filtered < 300)
{
digitalWrite(9, HIGH);
cloud_state = ON;
}
break;
case ON: if (light_filtered > 320)
{
digitalWrite(9, LOW);
cloud_state = OFF;
}
break;
}
static uint8_t LED_cyan_state = OFF;
switch(LED_cyan_state)
{
case OFF: if(timer2_counter > 4000)
{
digitalWrite(10, HIGH);
timer2_counter = 0;
LED_cyan_state = ON;
}
break;
case ON: if(timer2_counter > 4000)
{
digitalWrite(10, LOW);
timer2_counter = 0;
LED_cyan_state = OFF;
}
break;
}
#define PAUSE 2
static uint8_t LED_orange_state = OFF;
static uint8_t LED_orange_state_change_counter = 0;
switch(LED_orange_state)
{
case OFF: if(timer3_counter > 2000)
{
if(LED_orange_state_change_counter == 3)
{
timer3_counter = 0;
LED_orange_state = PAUSE;
}
else
{
digitalWrite(LED_ORANGE, HIGH);
timer3_counter = 0;
LED_orange_state = ON;
}
}
break;
case ON: if(timer3_counter > 2000)
{
digitalWrite(LED_ORANGE, LOW);
timer3_counter = 0;
LED_orange_state_change_counter++;
LED_orange_state = OFF;
}
break;
case PAUSE: if(timer3_counter > 6000)
{
digitalWrite(LED_ORANGE, HIGH);
timer3_counter = 0;
LED_orange_state = ON;
}
}
}