Hi all!
I have a problem with one of my codes and after trying to solve it on many evenings, I've finally gave up. :smiley-confuse:
Hopefully someone here can help me! :)
The provided code is used for a night-/mobile light and in my point of view nothing special. It's running on an attiny85 with a lithium battery. And that is the reason, why I used the "power down" sleep mode in my code.
So what's my problem: With an attached pullup button, I can toggle within three modes. Off / On / PIR-Mode combined with an LDR. All these modes let the LEDs fade in and out.
The problem happens, when I toggle from the starting mode 0 (off), to mode 1 (on), mode 2 (PIR) and then back to mode 0. If I wait for a completely fade out, it stucks.
But when I enable the "Testcode" in my code, everything works smooth.
Thank you very much for your support!
// ATMEL ATTINY 25/45/85 / ARDUINO
//
// +-/-+
// Ain0 (D 5) PB5 1| |8 Vcc
// Ain3 (D 3) PB3 2| |7 PB2 (D 2) Ain1
// Ain2 (D 4) PB4 3| |6 PB1 (D 1) pwm1
// GND 4| |5 PB0 (D 0) pwm0
// +----+
//#define DEBUG
#define USEPIR
#define USELDR
#define AUTOADJUST
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
#ifndef DEBUG
const byte LED = 0;
#else
#include <SendOnlySoftwareSerial.h>
SendOnlySoftwareSerial Serial(0);
#endif
#ifdef USEPIR
const byte PIR = 2;
unsigned int pirTimeout = 30; // wait x times for watchdog to wake up (once a second per default)
unsigned int pirTrigger = pirTimeout;
#endif
#ifdef USELDR
const byte LUM = A2;
const byte LUMPOWER = 3;
unsigned int lumLimit = 768; // as darker as higher ;-) (take care of automatic adjustment function)
const int lumThreshold = 50;
#endif
const byte BUTTON = 1;
byte ledPWM = 0;
byte currentMode = 0;
unsigned long lastButtonPress = 0;
ISR (PCINT0_vect) {
wdt_disable();
}
#if defined USELDR || defined USEPIR
ISR (WDT_vect) {
wdt_disable();
}
#endif
void setup() {
#if defined USELDR || defined USEPIR
resetWatchdog();
#endif
#ifndef DEBUG
pinMode (LED, OUTPUT);
#else
Serial.begin(9600);
Serial.println("Startup...");
#endif
#ifdef USEPIR
pinMode (PIR, INPUT);
#endif
#ifdef USELDR
pinMode (LUM, INPUT);
pinMode (LUMPOWER, OUTPUT);
#endif
pinMode (BUTTON, INPUT_PULLUP);
for ( int flashCount = 0; flashCount < 3; flashCount++ ) {
while (ledPWM<255) {
#ifdef DEBUG
Serial.print("r");
#endif
rampUpDown(1,5);
}
while (ledPWM>0) {
#ifdef DEBUG
Serial.print("r");
#endif
rampUpDown(0,5);
}
#ifndef DEBUG
digitalWrite(LED, LOW);
#endif
delay(250);
}
#ifdef DEBUG
Serial.println();
#endif
PCMSK = 0b00000110;
GIFR |= bit (PCIF);
GIMSK |= bit (PCIE);
} // end of setup
void loop() {
if ( digitalRead(BUTTON) == LOW ) {
if ( millis() - lastButtonPress > 500 ) {
#if defined USELDR || defined USEPIR
if ( currentMode < 2 )
#else
if ( currentMode < 1 )
#endif
currentMode++;
else {
currentMode = 0;
#if defined USELDR || defined USEPIR
digitalWrite(LUMPOWER, LOW);
#endif
}
lastButtonPress = millis();
#ifdef DEBUG
Serial.print("nrMode: ");
Serial.println(currentMode);
#endif
}
/* Testcode
if ( currentMode == 0 ) {
while ( ledPWM > 0 ) {
rampUpDown(0,1);
}
while (ledPWM<255) {
rampUpDown(1,1);
}
while (ledPWM>0) {
rampUpDown(0,1);
}
}
else */ if ( currentMode == 2 ) {
digitalWrite(LUMPOWER, HIGH);
for ( byte counter = 0; counter < 3; counter++ ) {
while (ledPWM<255) {
#ifdef DEBUG
Serial.print("r");
#endif
rampUpDown(1,1);
}
while (ledPWM>0) {
#ifdef DEBUG
Serial.print("r");
#endif
rampUpDown(0,1);
}
}
#ifdef DEBUG
Serial.println();
#endif
}
}
if ( currentMode == 0 ) {
#ifdef DEBUG
Serial.print("rChecking PWM value... ");
#endif
if ( ledPWM > 0 ) {
rampUpDown(0,10);
}
else {
#ifdef DEBUG
Serial.println();
#endif
goToSleep(0);
}
}
else if ( currentMode == 1 ) {
#ifdef DEBUG
Serial.print("rChecking PWM value... ");
#endif
if ( ledPWM < 255 ) {
rampUpDown(1,10);
}
else {
#ifdef DEBUG
Serial.println();
#endif
goToSleep(0);
}
}
#if defined USEPIR || defined USELDR
else if ( currentMode == 2 ) {
int lumValue = analogRead(LUM);
#ifdef AUTOADJUST
if ( lumLimit < 1020 && lumValue > lumLimit ) {
lumLimit = lumValue < 1020 ? lumValue : 1020;
#endif
#ifdef DEBUG
Serial.print("LUM: ");
Serial.print(lumValue);
Serial.println();
#endif
}
bool pirValue = LOW;
if ( digitalRead(PIR) == HIGH && lumValue >= lumLimit ) {
pirTrigger = 0;
#ifdef DEBUG
Serial.print(" - Motion detected");
#endif
}
if ( pirTrigger < pirTimeout ) {
pirValue = HIGH;
#ifdef DEBUG
Serial.print(" - Checking PWM value... ");
Serial.println(ledPWM);
#endif
if ( ledPWM == 255 )
pirTrigger++;
}
#ifdef DEBUG
Serial.print("r");
Serial.print(millis());
Serial.print(" pirValue: ");
Serial.print(pirValue);
Serial.print(" ");
#endif
if ( pirValue == LOW && ledPWM == 0 ) {
digitalWrite(LUMPOWER, LOW);
pirTrigger = pirTimeout;
goToSleep(0);
digitalWrite(LUMPOWER, HIGH);
}
else if ( ( pirValue == LOW || lumValue < ( lumLimit - lumThreshold ) ) && ledPWM > 0 ) {
rampUpDown(0,10);
}
else if ( pirValue == HIGH && ledPWM == 255 ) {
goToSleep(1);
}
else if ( pirValue == HIGH && ( ( lumValue >= lumLimit && ledPWM < 255 ) || ( lumValue >= ( lumLimit - lumThreshold ) && ledPWM > 0 && ledPWM < 255 ) ) ) {
rampUpDown(1,5);
}
}
#endif
void goToSleep(bool useWDT) {
#ifdef DEBUG
Serial.print(millis());
Serial.print(" - Goto sleep mode: ");
Serial.println(useWDT);
#endif
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
byte keepADCSRA = ADCSRA;
ADCSRA = 0;
power_all_disable();
noInterrupts();
#if defined USEPIR || defined USELDR
if ( useWDT == 1 ) resetWatchdog();
#endif
sleep_enable();
interrupts();
sleep_cpu();
sleep_disable();
power_all_enable();
ADCSRA = keepADCSRA;
}
#if defined USEPIR || defined USELDR
void resetWatchdog() {
MCUSR = 0;
WDTCR = bit (WDCE) | bit (WDE) | bit (WDIF);
WDTCR = bit (WDIE) | bit (WDP2) | bit (WDP1);
wdt_reset();
}
#endif
void rampUpDown(bool upDown, byte speed) {
if ( upDown == 1 ) ledPWM++;
else ledPWM--;
#ifndef DEBUG
analogWrite(LED,ledPWM);
#else
Serial.print("Ramp... ");
Serial.print(ledPWM);
Serial.print(" ");
#endif
delay(speed);
}