Pages: [1]   Go Down
Author Topic: Warum funktionieren meine Interrupts nicht?  (Read 947 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 1
Posts: 24
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

ich möchte gerne einfach meinen Controller nach dem Setup in den Powerdown schicken und bei jedem Pinchange am Pin3 Interrupt Pin 1 wieder aufwecken und die Nachricht ("SEND") ausgeben lassen. Das klappt aber gar nicht und er meldet immer nur beim ersten Tastendruck SEND und mehr nicht.

Vielleicht hat ja einer einen Tipp woran es liegen kann. Vielen Dank.

Gruß kami83

Code:
#include <avr/sleep.h>
 
volatile int old_millis = millis();

void count(){
   int m_delta = millis() - old_millis;
  if(m_delta > 200 ){
   Serial.println("Send");
    old_millis = millis();

  }
 sleepNow();

 }
 
void setup()   {
Serial.begin(57600);
Serial.println("Logger");

attachInterrupt(1, count, FALLING);
sleepNow();
  }
  void loop() {
  }
 
void sleepNow()       
{
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   
    sleep_enable();         
    sleep_mode();           
    sleep_disable();       
   
}

Logged

0
Offline Offline
Faraday Member
**
Karma: 24
Posts: 3495
20 LEDs are enough
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

1) Du solltest an Deinen Einrückungen arbeiten, das ist so kaum zu lesen.

2) Du schickst den Controller in der ISR schlafen. Danach wird er nicht wieder aufwachen, denn in der ISR ist der auslösende Interrupt erst einmal gesperrt. Selbst wenn er aufwachen würde (z.B. weil Du die Interrupts explizit wieder erlaubst) würde das mit der Zeit den Stack zumüllen.

Besser wäre es die ISR leer zu lassen und stattdessen die Arbeit in loop() zu erledigen.

Udo

Logged

Check out my experiments http://blog.blinkenlight.net

0
Offline Offline
Newbie
*
Karma: 1
Posts: 24
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

okay mit dem Code kann man besser machen. Aber ich habe das Problem das ich nur mit dem externen Interrupt den Controller aufwecken will. Kannst du mir nicht den Quellcode anpassen?

Vielen dAnk.

Cu kami
Logged

0
Offline Offline
Faraday Member
**
Karma: 24
Posts: 3495
20 LEDs are enough
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Du wolltest einen Tipp haben. Den hast Du bekommen. In meiner Antwort steht drin wie es geht. Wenn Du es versuchst und dann nicht weiter kommst, dann frag nochmal.

Udo
Logged

Check out my experiments http://blog.blinkenlight.net

0
Offline Offline
Newbie
*
Karma: 1
Posts: 24
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

ich habe nochmal etwas am den Code rumgespielt.

Sieht jetz so aus:

Code:
#include <Ports.h>
#include <RF12.h>
#include <avr/sleep.h>

#define LOGGERNUM   56
#define TESTSEC 5
 
volatile int flag=0;
static byte radioIsOn,testval = 1;
volatile long cnt = 0;
volatile long cnt_old = cnt;
volatile int old_millis = millis();


typedef struct {
    unsigned int device;
    unsigned int error;
    unsigned int lobat;
    unsigned int status1;
} msgstruct;


void count(){
   sleep_disable();
   flag=1;

}
 
void setup()   {

      Serial.begin(57600);
      Serial.println("Logger");
      rf12_initialize(8, RF12_868MHZ, 5);
      rf12_easyInit(0);
     
      rf12_sleep(0); // turn the radio off
      radioIsOn = 0;

      attachInterrupt(1, count, FALLING);
      sleepNow();
}
 
void loop() {
   
    if (flag==1)
    {
     flag=2;
    Serial.println("Sending starts");

    domessage();
   
    }
    if (radioIsOn && rf12_easyPoll() == 0 && flag==0) {
        Serial.println("Sending done");
       
        rf12_sleep(0); // turn the radio off
        radioIsOn = 0;
       
        Serial.println("Sleep");
       
        sleepNow();
    }
 
}
 
void sleepNow()       
{
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   
    sleep_enable();         
    sleep_mode();           
}


void domessage()
{   
  Serial.println("Msg starts");
 
  int m_delta = millis() - old_millis;
 
  if(m_delta > 200 ){
 
    if (testval==1) testval=0; else testval=1;
   
    msgstruct msgfile;
    msgfile.device = LOGGERNUM;
    msgfile.error = 123;
    msgfile.lobat = rf12_lowbat();
    msgfile.status1 = testval;
    wakeupToSend(&msgfile, sizeof msgfile);
   
    old_millis = millis();

  }
   
}

static void wakeupToSend (const void* ptr, byte len) {
    char sending = rf12_easySend(ptr, len);
    if (sending) {
            // make sure the radio is on again
            if (!radioIsOn)
                rf12_sleep(-1); // turn the radio back on
            radioIsOn = 1;
            flag=0;
        }   
}

Vielen Dank.

Gruß kami
Logged

0
Offline Offline
Faraday Member
**
Karma: 24
Posts: 3495
20 LEDs are enough
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Genau so funktioniert das. Tipp kriegen, selber lösen, was dabei lernen und dann das Ergebnis posten. Vorbildlich smiley-wink
Du kannst das sleep_disable aus der ISR weglassen. Der Controller ist ja schon wach. Von selber schläft der nicht wieder ein.

Gruß, Udo
Logged

Check out my experiments http://blog.blinkenlight.net

0
Offline Offline
Newbie
*
Karma: 1
Posts: 24
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

so ich habe nun ein erweiterungsproblem. Mit dem Interrupt kriege ich es ja hin, das er mir beim Tastendruck wechselt. Nun möchte ich aber gerne dadurch einen Timer für 15min starten, den Controller bis zum nächsten Interrupt in den Schlaf schicken und nach 15min soll er aufwachen und einen Serielle Ausgabe machen. Geht das? Wenn ja wie?

Gruß kami
Logged

0
Offline Offline
Faraday Member
**
Karma: 24
Posts: 3495
20 LEDs are enough
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Der Arduino hat keinen Timer der so ohne weiteres auf 15 Minuten kommt. Die übliche Lösung ist einen Timer so einzustellen, daß der Arduino alle paar Sekunden kurz aufwacht und dabei mitzuzählen wie oft das schon passiert ist. Daraus ermittelt man die abgelaufene Zeit. Wenn die 15 Minuten voll sind dann kann man reagieren.

Du könntest auch versuchen den Takt abzusenken, die Prescaler hochzudrehen und die Timer zu verketten, d.h. einen Timer benutzen als PWM, den entsprechenden Pin auf den Eingang eines anderen Timer. Damit bekommt man nochmal 8bit mehr muß aber 2Pins dafür opfern.

Das ist allerdings schon etwas fortgeschrittener. Nachdem Du das mit dem Interrupt hingekriegt hast ist das aber schon in Deiner Reichweite.
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Die_Timer_und_Z%C3%A4hler_des_AVR
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
Logged

Check out my experiments http://blog.blinkenlight.net

0
Offline Offline
Newbie
*
Karma: 1
Posts: 24
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

also ich würde da Variante 1 bevorzugen. Zur Zeit habe ich das andere SKetch angepasst und fülle damit ein Struct alle paar Sekunden. Nun möchte ich aber immer in der Zeit in den Sleep-Mode gehen, wo kein Interrupt kommt und alle 3 min wieder aufwachen um im Struct eine Zelle weiterzuspringen. Vielleicht hat ja jemand einen Tipp? Wäre dankbar für ein Timer Interrupt Sketch. Gruß kami smiley
Logged

0
Offline Offline
Faraday Member
**
Karma: 24
Posts: 3495
20 LEDs are enough
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Das Standardbeispiel ist das hier: http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
Logged

Check out my experiments http://blog.blinkenlight.net

Pages: [1]   Go Up
Jump to: