Go Down

Topic: Code gets stuck (Read 403 times) previous topic - next topic

0mega5

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!

Code: [Select]
// 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);
}

bos1714

Hello there!

What is the micro controller doing when the code "freezes"?
Time line? Time isn't made out of lines. It is made out of circles. That is why clocks are round.

Go Up