0

I am building a timer circuit using Arduino Pro Mini Atmega168p 5v 16MHz (which later supposed to be become to adjustable one).

Here is the current breadboard view.

enter image description here (I am supposed to use SS relay at place of that green thing. I am not sure if that item is correct SS relay in Fritzing)

Here is the program code I wrote.

#include <PinChangeInterrupt.h>
#include <PinChangeInterruptBoards.h>
#include <PinChangeInterruptPins.h>
#include <PinChangeInterruptSettings.h>

#include <avr/sleep.h>

// LED to indicate timer is active.
const int ON_LED = 5;
// It should be high when timer is active.
// Connect to relay.
const int PUMP_SWITCH = 6;

// Button to start timer running.
const int START_BUTTON = 8;
// Button to stop timer forcefully.
const int STOP_BUTTON = 9;

volatile boolean timer_running;
volatile int timer_start_time;

// TODO: Make it volatile once timer has mdified as configurable.
volatile unsigned long timer_time = 0;

void enter_sleep_mode() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sei();
  sleep_mode();
}

/**
 * Activate timer.
 */
void start_timer() {
  if (!timer_running) {
    // Time period in milliseconds.
    timer_time = 30000ul; // 30 seconds

    timer_running = true;
    timer_start_time = millis();
  }
}

/**
 * Stop timer.
 */
void stop_timer() {
  timer_running = false;
  timer_start_time = 0;
}

void setup() {
  timer_running = false;
  timer_start_time = 0;

  // Configure output pins.
  pinMode(ON_LED, OUTPUT);
  pinMode(PUMP_SWITCH, OUTPUT);

  // Configure pins for input push buttons.
  pinMode(START_BUTTON, INPUT_PULLUP);
  pinMode(STOP_BUTTON, INPUT_PULLUP);

  // Attach interrupt handlers
  // Buttons are with pull up resistors so listening for 'falling' (voltage).
  attachPCINT(digitalPinToPCINT(START_BUTTON), start_timer, FALLING);
  attachPCINT(digitalPinToPCINT(STOP_BUTTON), stop_timer, FALLING);
}

void loop() {
  if (timer_running) {
    digitalWrite(ON_LED, HIGH);
    digitalWrite(PUMP_SWITCH, HIGH);
    // TODO: Handle the case when return value of millis() goes back to start from zero
    if ( (millis() - timer_start_time) >= timer_time ) {
      // Timer elapsed the required time period.
      // So, stop the timer.
      stop_timer();
    }
  }
  else {
    digitalWrite(ON_LED, LOW);
    digitalWrite(PUMP_SWITCH, LOW);
    // Nothing to do If timer is not running.
    // Save power!!
    enter_sleep_mode();

    sleep_disable();
  }
}

The problem is timer does not work when pressing START button starting from third click. Two initial clicks works OK and timer functions as it should be. I think it does not wake up properly from sleep mode. However, wondering why it works for two initial clicks??

Please help me to identify the problem. I don't have much experience in writing Arduino code.

Thanks

2
  • Start by checking your calculation of time limits. I see you are mixing signed and unsigned arithmetics - not a very good idea. Check the blink-without-delay example for how to do that. Commented Oct 9, 2017 at 15:15
  • @MikaelPatel That is great! You are right. I found my mistake. I was wrongly declaring volatile int timer_start_time; where timer_start_time variable is supposed to hold return value from millis() Now I declared it as volatile unsigned long timer_start_time; and it worked! :) Could you please make it an answer so I can select? Thanks
    – Junaid
    Commented Oct 9, 2017 at 15:42

2 Answers 2

3

Start by checking your calculation of time limits. I see you are mixing signed and unsigned arithmetics - not a very good idea. Check the blink-without-delay example for how to do that.

The declaration of timer_start_time should be paid special attention.

Good luck with your project!

1
  • I could identify my problem and fixed it by declaring timer_start_time and as unsigned long. It should be wide enough to hold return values from millis(). Thanks!
    – Junaid
    Commented Oct 10, 2017 at 0:55
2

Please help me to identify the problem.

it is always very easy to solve this type of problems, if you just follow some common sense.

1) decompose your functionality into manageable blocks. for example, one is PCINT - can you blink an led with it - and another is going into sleep - can you put the mcu into sleep - and the next is to walk up from sleep - does your mcu support that? what has to be true for that to happen? ...

2) test individual blocks on their own.

3) integrate them into one functional program.

don't co-mingle them day 1. tackle only what you can manage. no more and no less.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.