wake up zonder click

Arduino specifieke Software
Berichten: 132
Geregistreerd: 21 Feb 2013, 16:04

wake up zonder click

Berichtdoor René » 19 Mrt 2013, 00:08

Ik zit met het volgende 3 uitdagingen.
Probleem 1. Ik heb aan een drupknop mbv onebutton.h meerdere functies gehangen (enkel, dubbel en lang)
Nu wil ik echter ook energie besparen en mbv sleep.h gebruik ik SLEEP_MODE_PWR_DOWN waarna de rust wederkeert.
Het probleem ontstaat bij ontwaken. Daarvoor heb ik een interrupt "gehangen" aan mijn drukknop.
Zodra ik nu in PWR DOWN mode mijn drukknop aanraak gaat de wekker en komt alles weer tot leven. Helaas wordt dan ook "enkel" uitgevoerd van onebottun.h.
Wat ik wil is dat mijn applicatie weer wakker wordt maar zich verder niets aantrekt van de druk op de knop die daar voor nodig is.
Dit is een deel van de code (voor de overzichtelijkheid is die sterk aangepast maar de problemen doen zich in deze code voor)
Code: Alles selecteren
#include <OneButton.h>
#include <avr/sleep.h>

 
long sleeptime = millis();  // wordt gebruikt bij het bepalen sleep mode

// setting voor de werking van de drukknop uit OneButton.h
volatile boolean clicked = false;
volatile boolean enkel = false;
volatile boolean dubbel = false;
volatile boolean lang = false;
// einde setting voor de werking van de drukknop

// setting voor de drukknop. 
OneButton button(2, true);
// einde setting voor de drukknop. 
int backLight = 13;    // pin 13 will control the backlight

void setup() {
  Serial.begin(9600);
  button.attachClick(click);  // single click
  button.attachDoubleClick(doubleclick);
  button.attachPress(press);     // long click
  sleep_mode();            // here the device is actually put to sleep!!
                           // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
  sleep_disable();         // first thing after waking from sleep:
                            // disable sleep...
} // setup


// proces wake up
void wakeUpNow()       
{
    sleeptime = millis();
    sleep_disable();         // first thing after waking from sleep:
                             // disable sleep...
    detachInterrupt(0);      // disables interrupt 0 on pin 2 so the
                             // wakeUpNow code will not be executed
                             // during normal running time.
     
}
// einde proces wake up


// proces sleep now
void sleepNow()         
{
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   // sleep mode is set here
    sleep_enable();          // enables the sleep bit in the mcucr register
                             // so sleep is possible. just a safety pin
    attachInterrupt(0,wakeUpNow, LOW); // use interrupt 0 (pin 2) and run function
                                       // wakeUpNow when pin 2 gets LOW
    sleep_mode();            // here the device is actually put to sleep!!
                             // THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP

 }
// einde proces sleep now

// processen voor de drukknop
void click() {       
  clicked = true;
  enkel = true;
}
void doubleclick() {
  clicked = true;
  dubbel = true;
}
void press() {
  clicked = true;
  lang = true;
}
// einde processen voor de drukknop

void loop() 
{
   button.tick();          // voor de werking van Onebutton.h
  digitalWrite(backLight, HIGH);
  if (millis()-sleeptime >= 1000)
  {
          Serial.println("Ga slapen...");
          delay(10);
      digitalWrite(backLight, LOW);
    sleepNow();
               Serial.println("Ring wekker.");
          delay(10);
  }
     
     if (clicked)   
     {   
        clicked = false;
        if  (enkel)     
        {   enkel = false;
                  Serial.println("Enkel...");
                  delay(10);
        }   
        else if (dubbel)
        {   dubbel = false;
                  Serial.println("Dubbel...");
                  delay(10);
         }
        else if (lang)
        {   lang = false;
                  Serial.println("Lang....");
                  delay(10);
        }
        else
        {  // click event without type ?!  should not come here. set Error flag
        }
     }
}


Naast het bovenstaande probleem gaat er ook nog het volgende mis.:
Probleem 2. Regelmatig genereerd de code een "dubbel" bij een enkele klik.
Probleem 3. Als ik de knop enkele seconden ingedrukt houd loopt het hele zaakje vast.

Graag wat hulp. Groet
René

Advertisement

Berichten: 132
Geregistreerd: 21 Feb 2013, 16:04

Re: wake up zonder click

Berichtdoor René » 19 Mrt 2013, 18:04

Probleem 2 , het debounce effect waardoor ik af en toe "dubbel" clicks kreeg ipv "enkel" clicks, heb ik opgelost door een Schmitt trigger te bouwen van 2 transistortjes en een paar weerstanden. zie http://www.hobbyprojects.com/schmitt_tr ... ger_2.html
Blijft over probleem 1: de wake-up klik veroorzaakt ook een ongewilde button click voor mijn applicatie.
Probleem 3 is nog veel storender. Doordat ik gebruik maak van een button om wakker te worden en POWER-DWN als sleep-mode wil gebruiken, kan ik bij de interrupt alleen kiezen voor LOW als parameter (FALLING zou veel mooier zijn). Het drukken op de knop geeft daardoor een hele serie interrupts af waardoor de applicatie vastloopt bij lang indrukken van de button. Iemand een idee?

Gebruikers-avatar
Berichten: 229
Geregistreerd: 20 Jan 2013, 12:01

Re: wake up zonder click

Berichtdoor astrofrostbyte » 19 Mrt 2013, 19:18

(Puntje 1)
In de Onebutton lib zie ik de volgende twee functies.

// explicitely set the number of millisec that have to pass by before a click is detected.
void OneButton::setClickTicks(int ticks) {
_clickTicks = ticks;
} // setClickTicks

// explicitely set the number of millisec that have to pass by before a lonn button press is detected.
void OneButton::setPressTicks(int ticks) {
_pressTicks = ticks;
} // setPressTicks

Je zou voor het slapen gaan deze op een erg hoge waarde kunnen zetten en als je en weer uit komt, weer terug zetten op de default waarde.
Defaults zijn:
_clickTicks = 600; // number of millisec that have to pass by before a click is detected.
_pressTicks = 1000; // number of millisec that have to pass by before a lonn button press is detected.

-----

of wat mischien wat mooier is, dat na het wakkerworden zelf checken en wachten tot de button losgelaten wordt.
iets in de richting van while ( ! digitalRead(2) ) ;
Laatst gewijzigd door astrofrostbyte op 19 Mrt 2013, 19:50, in totaal 3 keer gewijzigd.
Gear: Arduino- Uno,Due,Ethernet,Mega2560 , OLS LogicAnalyser, TDS1002, Rigol DG1022, J-Link EDU, BusPirate

Gebruikers-avatar
Berichten: 229
Geregistreerd: 20 Jan 2013, 12:01

Re: wake up zonder click

Berichtdoor astrofrostbyte » 19 Mrt 2013, 19:25

Wat opmerkingetjes, vraagjes, tips:

- In de loop() wordt digitalWrite(backLight, HIGH) heel vaak aangeroepen.

- Als er een button gedrukt (key event)is moet dan de variabele 'sleeptime' niet geupdate worden ?.

- in setup wordt na een sleep_mode() bij wakkerworden de functie sleep_disable() aangeroepen, ik zie dat bij andere aanroepen van sleep_mode() niet.
het is ook veiliger om maar op 1 plek die sleep_mode() aanroep te hebben

Voor probleempje 3 zou je toch eens in die OnButton.h library moeten kijken , heb je het vermoeden dat hij daar ergens blijft hangen ?.
Gear: Arduino- Uno,Due,Ethernet,Mega2560 , OLS LogicAnalyser, TDS1002, Rigol DG1022, J-Link EDU, BusPirate

Berichten: 132
Geregistreerd: 21 Feb 2013, 16:04

Re: wake up zonder click

Berichtdoor René » 19 Mrt 2013, 20:15

Dank je astrofrostbyte:)

Het vastlopen is opgelost met de volgende code.


Code: Alles selecteren
void sleepNow()
{
sleep_enable();
attachInterrupt(0, pin2_isr, LOW);
// 0, 1, or many lines of code here
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
cli();
// sleep_bod_disable();
sei();
sleep_cpu();
// wake up here
sleep_disable();
}


void pin2_isr()
{
  sleeptime = millis();
  sleep_disable();
  detachInterrupt(0);
  pin2_interrupt_flag = 1;
}


Nu nog mijn "fouten/slordigheden" uit de code halen.
En dan jou suggestie van
_clickTicks = 600; en _pressTicks = 1000; in sleepmode verlengen. Hoe kan dat trouwens als die variabelen in "een library" zitten ? Ook eens kijken of ik iets met de door astrofrostbyte genoemde "mooiere" oplossing kan.

Berichten: 132
Geregistreerd: 21 Feb 2013, 16:04

Re: wake up zonder click

Berichtdoor René » 19 Mrt 2013, 21:06

Opgelost!
De onderstaande code voorkomt dat na het wakker worden ook de OneButton click wordt uitgevoerd.
Code: Alles selecteren
void pin2_isr()
{
while ( ! digitalRead(2) )
{ delay(1);}
  sleeptime = millis();
  sleep_disable();
  detachInterrupt(0);
  pin2_interrupt_flag = 1;
}


tnx

Gebruikers-avatar
Berichten: 229
Geregistreerd: 20 Jan 2013, 12:01

Re: wake up zonder click

Berichtdoor astrofrostbyte » 20 Mrt 2013, 21:11

rené> _clickTicks = 600; en _pressTicks = 1000; in sleepmode verlengen. Hoe kan dat trouwens als die variabelen in "een library" zitten ?

De variabelen _clickTicks kan je niet direct benaderen omdat ze 'private' zijn , de _ voor de variabele zorgt daarvoor.

// explicitely set the number of millisec that have to pass by before a click is detected.
void OneButton::setClickTicks(int ticks) {
_clickTicks = ticks;
} // setClickTicks


je moet de variabelen benaderen via de geleverde 'methods' :
button.setPressTicks(2000);
button.setClickTicks(3000);

details in http://arduino.cc/en/Hacking/LibraryTutorial

grtz..
Gear: Arduino- Uno,Due,Ethernet,Mega2560 , OLS LogicAnalyser, TDS1002, Rigol DG1022, J-Link EDU, BusPirate

Berichten: 132
Geregistreerd: 21 Feb 2013, 16:04

Re: wake up zonder click

Berichtdoor René » 22 Mrt 2013, 00:44

Dank je astrofrostbyte:)
Ik merk dat als ik een vraag stel, ik een onderbouwd antwoord krijg. Ik vind dat heel plezierig. De aangedragen oplossingen gebruik ik met succes.
Ik mis alleen wel de achterliggende kennis, moet toch eens op zoek naar een goede uitleg/handleiding.
Groet
René

Terug naar Arduino software

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 13 gasten