I have a sketch for an ATtiny85 that compiles but does not perform as expected and I am at a loss for why. I am posting both schematic and sketch here. My circuit is battery powered and uses a ATtiny85 to light an LED array in dark conditions controlled by an LDR. LED brightness is controlled by PWM that is adjustable by a pot. PWM is increased as battery voltage decreases. To save power the sketch uses ATtiny85 sleep modes and drives the brightness pot. Problem the circuit only lights the LED array if booted in dark conditions, and then will turn off the LEDs in ambient light. However if booted in ambient light it will not turn on LEDs after transitioning to dark. I know that the sketch detects the dark condition because quiescent current changes from 65 microA to 35 microA when shifting from light to dark conditions. I cannot find the logical error that prevents lighting the LEDs when transitioning from light to dark. I have ruled out reaching LDR threshold values by measuring voltage in light and dark. I am a newbie and have used a variety of LLMs to help with the code and to sort this out but they are not up to the task. Any help is greatly appreciated`Use code tags to format code for the forum
```cpp
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#include <math.h>
// --- Light Thresholds ---
const uint16_t DARK_THRESHOLD_ON = 740;
const uint16_t DARK_THRESHOLD_OFF = 700;
const uint16_t DAYLIGHT_THRESHOLD_ON = 600;
const uint16_t DAYLIGHT_THRESHOLD_OFF = 700;
// --- Pin Assignments ---
const uint8_t LDR_ADC_PIN = A1; // PB2 (Pin 7)
const uint8_t LDR_COMP_PIN = 1; // PB1 (Pin 6)
const uint8_t BRIGHTNESS_PIN = A3; // PB3 (Pin 2)
const uint8_t PWM_OUTPUT_PIN = 4; // PB4 (Pin 3)
const uint8_t RV2_POWER_PIN = 0; // PB0 (Pin 5)
bool isLedOn = false;
volatile bool wokeFromComparator = false;
// --- PWM Compensation Constants ---
const float REG_SLOPE = 1104.8f;
const float REG_INTERCEPT = -1849.7f;
const float VCC_NOMINAL_VOLTS = 2.94f;
const float I_MAX_AT_VNOMINAL = REG_SLOPE * VCC_NOMINAL_VOLTS + REG_INTERCEPT;
const float MIN_MULTIPLIER = 0.5f;
const float MAX_MULTIPLIER = 7.0f;
// --- Interrupt Handlers ---
ISR(WDT_vect) {}
ISR(ANA_COMP_vect) {
wokeFromComparator = true;
}
// --- Utility Functions ---
float getCompensatedMultiplier(uint16_t vcc_mv_actual) {
float vcc_volts = vcc_mv_actual / 1000.0f;
float i_actual = REG_SLOPE * vcc_volts + REG_INTERCEPT;
if (i_actual <= 1.0f) return MAX_MULTIPLIER;
float multiplier = I_MAX_AT_VNOMINAL / i_actual;
return fmaxf(MIN_MULTIPLIER, fminf(MAX_MULTIPLIER, multiplier));
}
void setupWatchdog() {
MCUSR &= ~(1 << WDRF);
WDTCR |= (1 << WDCE) | (1 << WDE);
WDTCR = (1 << WDIE) | (1 << WDP3) | (1 << WDP0); // ~8s
}
void disableWatchdog() {
MCUSR &= ~(1 << WDRF);
WDTCR &= ~((1 << WDIE) | (1 << WDE));
}
uint16_t readVcc() {
uint8_t oldADMUX = ADMUX;
ADMUX = 0x0C; // Internal 1.1V reference to measure Vcc
delay(10);
ADCSRA |= (1 << ADSC);
while (ADCSRA & (1 << ADSC))
;
uint16_t adcResult = ADC;
ADMUX = oldADMUX;
return adcResult == 0 ? 3000 : (uint16_t)(1126400L / adcResult);
}
uint16_t readVcc_stable() {
uint32_t sum = 0;
for (uint8_t i = 0; i < 4; i++) {
sum += readVcc();
if (i < 3) delayMicroseconds(100);
}
return sum / 4;
}
uint16_t readLDR() {
ADMUX = (0 << REFS0) | (LDR_ADC_PIN & 0x07);
delay(10);
ADCSRA |= (1 << ADSC);
while (ADCSRA & (1 << ADSC))
;
return ADC;
}
uint16_t readBrightnessPotWithPowerControl_stable() {
uint32_t sum = 0;
for (uint8_t i = 0; i < 4; i++) {
pinMode(RV2_POWER_PIN, OUTPUT);
digitalWrite(RV2_POWER_PIN, HIGH);
delayMicroseconds(150);
sum += analogRead(BRIGHTNESS_PIN);
digitalWrite(RV2_POWER_PIN, LOW);
pinMode(RV2_POWER_PIN, INPUT); // High impedance to reduce leakage
if (i < 3) delayMicroseconds(100);
}
return sum / 4;
}
void enterSleepWithLDRComparator() {
ADCSRA &= ~(1 << ADEN); // Disable ADC
ACSR &= ~(1 << ACIE); // Disable comparator interrupt
ACSR |= (1 << ACI); // Clear interrupt flag
// Enable comparator: AIN1 vs 1.1V bandgap, rising edge
ACSR = (1 << ACIE) | (1 << ACBG) | (1 << ACIS1); // rising edge only
wokeFromComparator = false;
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_bod_disable();
sei();
sleep_cpu();
sleep_disable();
ACSR &= ~(1 << ACIE); // Disable comparator interrupt
ADCSRA |= (1 << ADEN); // Re-enable ADC
delay(10000); // 10-second delay after wake-up to ensure LDR settles
}
void setupADC() {
ADMUX = (0 << REFS0);
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
}
void setupPWM() {
pinMode(PWM_OUTPUT_PIN, OUTPUT);
analogWrite(PWM_OUTPUT_PIN, 0);
}
void setup() {
power_timer0_disable();
pinMode(RV2_POWER_PIN, OUTPUT);
digitalWrite(RV2_POWER_PIN, LOW);
pinMode(LDR_ADC_PIN, INPUT);
pinMode(LDR_COMP_PIN, INPUT);
pinMode(BRIGHTNESS_PIN, INPUT);
setupADC();
setupPWM();
for (int i = 0; i < 3; i++) {
readLDR();
delay(10);
}
disableWatchdog();
sei();
uint16_t light = readLDR();
if (light >= DARK_THRESHOLD_ON) {
uint16_t brightnessRaw = readBrightnessPotWithPowerControl_stable();
uint16_t pwmRaw = brightnessRaw >> 2;
uint16_t vcc = readVcc_stable();
float multiplier = getCompensatedMultiplier(vcc);
uint16_t scaledPwm = (uint16_t)(pwmRaw * multiplier);
if (scaledPwm == 0 && brightnessRaw > 4) scaledPwm = 1;
if (scaledPwm > 255) scaledPwm = 255;
analogWrite(PWM_OUTPUT_PIN, (uint8_t)scaledPwm);
isLedOn = true;
setupWatchdog();
} else {
analogWrite(PWM_OUTPUT_PIN, 0);
isLedOn = false;
disableWatchdog();
enterSleepWithLDRComparator();
}
}
void loop() {
uint16_t light = readLDR();
uint16_t brightnessRaw = readBrightnessPotWithPowerControl_stable();
uint16_t pwmRaw = brightnessRaw >> 2;
uint16_t vcc = readVcc_stable();
float multiplier = getCompensatedMultiplier(vcc);
uint16_t scaledPwm = (uint16_t)(pwmRaw * multiplier);
if (scaledPwm == 0 && brightnessRaw > 4) scaledPwm = 1;
if (scaledPwm > 255) scaledPwm = 255;
uint8_t pwmValue = (uint8_t)scaledPwm;
if (!isLedOn) {
if (light >= DARK_THRESHOLD_ON) {
analogWrite(PWM_OUTPUT_PIN, pwmValue);
isLedOn = true;
setupWatchdog();
} else {
analogWrite(PWM_OUTPUT_PIN, 0);
isLedOn = false;
disableWatchdog();
enterSleepWithLDRComparator();
return;
}
} else {
if (light <= DAYLIGHT_THRESHOLD_ON || (light <= DARK_THRESHOLD_OFF && light > DAYLIGHT_THRESHOLD_ON)) {
analogWrite(PWM_OUTPUT_PIN, 0);
isLedOn = false;
disableWatchdog();
enterSleepWithLDRComparator();
return;
} else {
analogWrite(PWM_OUTPUT_PIN, pwmValue);
}
}
if (isLedOn) {
ADCSRA &= ~(1 << ADEN);
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_enable();
sleep_cpu();
sleep_disable();
ADCSRA |= (1 << ADEN);
}
}