Quantcast
Channel: Arduino Forum - Latest topics
Viewing all articles
Browse latest Browse all 15374

One button library - isIdle not triggering after sleep

$
0
0

Hello,
I've built myself an electrified coffee grinder. The intended operation is as follows -
No on/off switch, just sleep. Wake up with one button click, another one click for grinding a predetermined time, go back to sleep. Triple click while awake - enter "programming" mode where you hold button for long enough to grind double (for increased accuracy) the intended amount of coffe, after releasing the button new grind time is saved to EEPROM. I got everything to work, but... If I wake up the arduino and don't do anything else, it'll never go back to sleep. I tried btn.reset at wakeup, but that resulted in going back to sleep immediately.
Will also take suggestions as to how to unkludge the grind(); function - the workaround for lag caused by I2C transmission to display (progress bar) is pretty ugly. And of course any other comments about the quality of the code are most welcome.
Thank you!

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include <avr/sleep.h>
#include <OneButton.h>
#include <EEPROM.h>

Adafruit_SSD1306 display(4); //default: sda - A4 scl - a5

// 'coffee2253', 32x32px
const unsigned char epd_bitmap_coffee [] PROGMEM = {
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x40, 0x00, 
 0x00, 0x12, 0x40, 0x00, 0x00, 0x12, 0x40, 0x00, 0x00, 0x12, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x04, 0x00, 0x03, 0x30, 0x04, 0x00, 0x02, 0x10, 
 0x04, 0x00, 0x02, 0x10, 0x04, 0x00, 0x02, 0x10, 0x02, 0x00, 0x02, 0x60, 0x03, 0xff, 0xff, 0xc0, 
 0x01, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x00, 0x7f, 0xf0, 0x00, 
 0x00, 0x3f, 0xe0, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

OneButton btn = OneButton(
 2, // Input pin for the button
 true, // Button is active LOW
 true // Enable internal pull-up resistor
);

volatile long grindT=8000;
int eeAddress = 0;

void setup() {

 Serial.begin(9600);
 Wire.setClock(400000L);

 pinMode(2, INPUT); //button pin
 digitalWrite(2, HIGH); //button pullup
 pinMode(3, OUTPUT); //mosfet out
 digitalWrite(3, LOW); //out reset to 0

 EEPROM.get(eeAddress, grindT);  

 display.begin(SSD1306_SWITCHCAPVCC,0x3C);
 display.setRotation(1);
 display.setTextColor(WHITE);
 display.setTextSize(1);
 display.setTextWrap(true);
 display.clearDisplay();

 display.drawBitmap(0, 48, epd_bitmap_coffee, 32, 32, WHITE);
 display.display();
 delay(1000);

 attachInterrupt(digitalPinToInterrupt(2), checkTics, FALLING); 

 btn.setClickMs(400); // def400 msec  Timeout used to distinguish single clicks from double clicks.
 btn.setPressMs(500); // def800 msec  Duration to hold a button to trigger a long press.
 btn.setIdleMs(15000);

 btn.attachClick(grind);
 btn.attachMultiClick(program);
 btn.attachIdle(sleep); 

}

void loop() {

 btn.tick();

}

void null() {
}

void checkTics() {
 btn.tick();
}

void grind() {

 btn.attachClick(null);
 display.clearDisplay();
 display.drawBitmap(0, 0, epd_bitmap_coffee, 32, 32, WHITE);
 display.drawRect(0, 33, 32, 95, WHITE);
 display.display();

 int d=12; //n of steps of the progress bar
 int i=0;
 int grindTfraction=grindT/d;
 unsigned long timerT = 0UL;
 unsigned long timerTmax = 0UL; 
 
 digitalWrite(3, HIGH);
 timerT = millis ();
 timerTmax = timerT+grindT;

 for (i=0; i<=d; i++) {
 display.fillRect(0, 32, 32, i*(96/d), WHITE);
 delay(grindTfraction-50); //arbitrary delay reduction to amount for display transmission time
 display.display();
    if (timerT >= timerTmax) { //turning it off if we still exceed the time too far
    digitalWrite(3, LOW);
    }
  }

 digitalWrite(3, LOW);
 
 delay(3000);
 display.clearDisplay();
 display.drawBitmap(0, 48, epd_bitmap_coffee, 32, 32, WHITE);
 display.display();
 btn.attachClick(grind);
}

void program() {

 display.clearDisplay();
 display.display();
 display.setCursor(2,2);
 display.println("Long press to grind 2x dose of coffe");
 display.display();

 btn.reset();
 btn.attachLongPressStart(startGrind);
 display.println("Current time:");
 display.println(grindT);
 display.display();

}

void startGrind() {
 digitalWrite(3, HIGH);
 btn.attachLongPressStop(endGrind);
}

void endGrind() {

 digitalWrite(3, LOW);
 unsigned long doublegrindT = btn.getPressedMs();
 grindT = doublegrindT >> 1; // binary divide by 2

 EEPROM.put(eeAddress, grindT);
 
 display.clearDisplay();
 display.println("New time:");
 display.println(grindT);
 display.display();
 delay(3000);

 btn.attachLongPressStart(null);
 display.clearDisplay();
 display.drawBitmap(0, 48, epd_bitmap_coffee, 32, 32, WHITE);
 display.display();

}

void sleep() {
 
 display.clearDisplay();
 display.setCursor(0,0);
 display.println("falling asleep");
 display.display();
 delay(3000);
 display.clearDisplay();
 display.display();

 pinMode(3, INPUT); //mosfet out switch off

 noInterrupts ();
 ADCSRA = 0; // disable ADC
 attachInterrupt(0, wake, LOW); 
 EIFR = bit (INTF0);  // clear flag for interrupt 0
  // turn off brown-out enable in software
  // BODS must be set to one and BODSE must be set to zero within four clock cycles
 MCUCR = bit (BODS) | bit (BODSE);
  // The BODS bit is automatically cleared after three clock cycles
 MCUCR = bit (BODS); 
  // We are guaranteed that the sleep_cpu call will be done
  // as the processor executes the next instruction after
  // interrupts are turned on.
 interrupts ();
 sleep_mode();

}

void wake() {

 sleep_disable();
 noInterrupts();
 attachInterrupt(digitalPinToInterrupt(2), checkTics, FALLING);
 interrupts();
 
 display.clearDisplay();
 display.setCursor(0,0);
 display.println("waking up");
 display.display();
 delay(2000);

 display.clearDisplay();
 display.drawBitmap(0, 48, epd_bitmap_coffee, 32, 32, WHITE);
 display.display();

 pinMode(3, OUTPUT); //mosfet out reactivate
}

3 posts - 2 participants

Read full topic


Viewing all articles
Browse latest Browse all 15374

Trending Articles