ATTiny, Counting with interupts

Robin2:
Did you see Reply #25?

...R

No, you sneaked that one in while I was writing my reply. :slight_smile:

That's a good suggestion and I'll have a play with it, meantime I have been doing the user program code and I have come up with this...

Variables & init...(Note I am using same pin for output and led just for debugging as pin 1 is used for the serial debug)

#include <TinyDebugKnockBang.h>
#include <avr/eeprom.h>


const long debounce = 20;               // button debounce time

int outPin = 0;                         // output pin, set high when beep count meets target
int inPin = 2;                          // beep pulse input pin 
int progButtonPin = 3;                  // program button pin
int setButtonPin = 4;                   // set button pin
int LEDPin = 0;                         // status led pin
unsigned long onTimer = 0;              // used for timing output pin 
volatile int beepCount = 0;             // counter for number of beeps detected
volatile unsigned long beepTime = 0;    // used for timing beep count period
unsigned long lastBeepTime = 0;         // the time the last pin check happened
unsigned long currentTime = 0;          // stores current millis() count for comparison
unsigned int programMode = 0;           // program mode
bool LEDState = false;                  // status led state
bool longButtonPress = false;           // long button press flag
unsigned long buttonPressTimer = 0;     // timer for button press
uint8_t outTime = 5;                    // seconds the output will be high
uint8_t sensitivity = 3;                // no beeps needed during time period to turn on output

Setup function...

void setup()
{
  // get variables from eeprom
  ReadEepromVars();
  Debug.begin( 9600 );                  // for tiny_debug_serial
  // set registors
  MCUCR |= B00000010;                   //watch for falling edge
  GIMSK |= B01000000;                   //enable external interrupt
  SREG |= B10000000;                    //global interrupt enable 
  // set up pins
  pinMode(outPin,OUTPUT);
  pinMode(LEDPin, OUTPUT);
  pinMode(inPin, INPUT_PULLUP);
  pinMode(setButtonPin, INPUT_PULLUP);
  pinMode(progButtonPin, INPUT_PULLUP);
  //digitalWrite(outPin, LOW);
  // check if program button is pressed during power on
  if (!digitalRead(progButtonPin))
  {
    // set program mode
    programMode = 1;
    // turn on status led
    digitalWrite(LEDPin,HIGH);
    while (!digitalRead(progButtonPin))
    {
      // wait for program button to be released
    }
    // turn off status led
    digitalWrite(LEDPin,LOW);
    // delay to allow button to bounce
    delay(100);
  }
}

Main loop...

void loop()
{
  // check program mode
  if (programMode != 0)
  {
    // non zero so do programming function
    DoProgramming();
  }
  else
  {
    // do check beep function
    DoBeeps(); // (Beep code is the same as posted above for the time being)
  }
}

Programming function...

void DoProgramming()
{
  // check if program button pushed (active low)
  if (ReadButton(progButtonPin) == LOW)
  {
    // set current time & flag
    buttonPressTimer = millis();
    longButtonPress = true;
    // loop for 1 second
    while (millis() - buttonPressTimer < 1000)
    {
      // if button released reset flag & exit loop
      if (ReadButton(progButtonPin) == HIGH)
      {
        longButtonPress = false;
        break;
      }
    }    
    // check button press type
    if (longButtonPress)
    {
      // long press = save settings and exit programming mode
      //turn on led
      digitalWrite(LEDPin, HIGH);
      programMode = 0;
      // save values to eeprom
      WriteEeepromVars();
      // keep led on for 1 second to signal exit programming
      delay(1000);
      digitalWrite(LEDPin, LOW);
    }
    else
    {
      // short press = switch program mode
      programMode +=1;
      if (programMode > 2 )
      {
        programMode = 1; 
        
      }
      // signal current mode with led flashes
      flashLED(programMode);
    }
  }
  // check set button (active low)
  if (ReadButton(setButtonPin) == LOW)
  {
    // set current time & flag
    buttonPressTimer = millis();
    longButtonPress = true;
    // loop for 1 second
    while (millis() - buttonPressTimer < 1000)
    {
      // if button released reset flag & exit loop
      if (ReadButton(setButtonPin) == HIGH)
      {
        longButtonPress = false;
        break;
      }
    }
    // check program mode
    switch (programMode)
    {
      case 1:
        // check press type
        if (longButtonPress)
        {
          // long press = show current setting
          flashLED(sensitivity);
        }
        else
        {
          // short press = increment setting
          sensitivity +=1;
          if (sensitivity > 10)
          {
            sensitivity = 3;
          }
          Debug.print("Sensitivity: ");
          Debug.println(sensitivity);
          flashLED(sensitivity);          
        }
        break;
        
      case 2:
        // check press type
        if (longButtonPress)
        {
          // long press = show current setting
          flashLED(outTime);
        }
        else
        {
          // short press = increment setting
          outTime +=1;
          if (outTime > 10)
          {
            outTime = 5;
          }
          flashLED(outTime);
          Debug.print("On Time: ");
          Debug.println(outTime);         
        }
        break;        
    }
  }  
}

Misc Functions...

int ReadButton(int button)
{
  // read initial state of the button
  int buttonState = digitalRead(button);
  // if the button is pressed 
  if (buttonState == HIGH)
  {                
    currentTime = millis(); 
    while (millis() - currentTime < debounce)
    {    
      // wait the debounce time
    }
    // read button again after delay
    buttonState = digitalRead(button);   
    // return current button state   
    return buttonState;                     
  }
  else
  {
    return LOW;
  }
}

int flashLED(int count)
{
 digitalWrite(LEDPin,LOW);
 for (int i=0; i < count; i++)
 {
   digitalWrite(LEDPin,HIGH);
   delay(500);
   digitalWrite(LEDPin,LOW);
   delay(100);
 }
}

void ReadEepromVars()
{
  sensitivity = eeprom_read_byte((uint8_t*)0);
  outTime = eeprom_read_byte((uint8_t*)1);
  // if sensitivity not set then save default values in eeprom
  // 0xff is not a valid value and is the default eeprom value so I think this is a safe way to check
  if (sensitivity == 0xff)
  {
    sensitivity = 3;
    outTime = 5;
    WriteEeepromVars();
  }
}

void WriteEeepromVars()
{
  eeprom_write_byte((uint8_t*)0,sensitivity);
  eeprom_write_byte((uint8_t*)1,outTime);
  eeprom_write_byte((uint8_t*)2,1);
}

It's seems to be working really well but as always comments and suggestions are welcome.

Regards,

Les