Status LED ohne Delay, Sleep und Infrarot

Guten Abend zusammen,
ich habe ein bzw. mehrere Probleme bei meinem aktuellen Projekt.
Es geht dabei um einen batteriebetriebenen 3D Taster der bei kontakt mit dem Werkstück ein IR Signal an einen Empfänger, der mit der CNC Fräße verbunden ist, schickt und so Werkstücke Automatisch ausgerichtet werden können.

Mein Plan ist es das der Taster nach 10 min Inaktivität in einen Sleep Mode geht um die Knopfzelle zu schonen.
Um Ihn wieder zu Wecken ist ein physikalischer Butten verbaut.
Während der Taster bereit ist soll eine LED alle 1,5s blinken.
Als Controller ist ein ATtiny85 verbaut.

Nachdem ich mich lieber immer zuerst um ein Problem kümmere und nicht um alle gleichzeitig fange ich mal mit dem meiner Meinung nach einfachsten an.

Die Intervalle für die Status LED im Loop Regel ich über eine Rechnung basierend auf den millis(). Ein delay kommt hier nicht in Frage da der Taster jederzeit ein Signal senden können muss.
Nachdem ich leider noch keine Hardware habe (Tiny85 hat große Lieferprobleme) muss ich mich zum testen noch auf Tinker CAD berufen. zur Veranschaulichung habe ich dort die IR LED durch eine Rote normale LED ersetzt.
Eigentlich müsste die Grüne LED wenn der Rechte Button nicht gedrückt wird (dies ist später das eingangs Signal vom Taster und fungiert mechanisch als Öffner, in diesem Beispiel ist es ein Schließer, Logik wurde umgekehrt) 30sec lang im Intervall von 1,5sec blinken und dann in den void sleep springen.
In Tinkercad schaltet aber nach nach 5 maligem grünen blinken die Rote LED ein, dies wiederholt sich in Dauerschleife. Der rechte Button ist ohne Funktion.

Das 2. Problem ist das ich ich diesen Sleep Mode nicht zum laufen bekomme, habe schon viel ausprobiert, wie in den aus kommentierten Bereichen zu sehen ist.
und das Wecken würde ich über einen Interrupt lösen der über den linken Button ausgelöst wird klappt aber auch nicht so wirklich.

Anbei mein aktueller Code und ein Bild des Schaltplans.

#include <Arduino.h>
#include <IRremote.h>
#include <avr/io.h>
#include <avr/wdt.h> 
#include <avr/sleep.h>
#include <avr/interrupt.h>

//#define G_LED 0
//#define IR_LED 1


IRsend irsend;

const int b1  = 3;           //Weckbutton
const int b2  = 4;           //Auslöse Button Tasten
const int G_LED = 0;         //Grüne status LED
const int IR_LED = 1;        //IR LED


//unsigned long temps;
//int tempomin=10;                          // Tempo in min initialisiert auf 10min
//unsigned long tempo=600000;               // temp0 vor Standby in ms
//unsigned long tempsactuel=0;              // Schlafenszeit
int nb=0;                                   // anzahl der blink durchläufe
int t=0;                                    // time zwischen blinklicht 
int i=0;                                    // blink Zähler
//int n=0;                                    // Loop zähler 

//volatile bool statusLeuchten = false;
//bool statusSleep = true;

// ################## LED Blink Loop Rechner #########################################################

boolean value = LOW;                        // Startwert der LED
unsigned long previousMillis = 0;           // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
unsigned long interval = 1500;              // Interval zwischen zwei Änderungen

// ################# Sleep Timmer Rechner ############################################################

unsigned long timerMillis = 0;              // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
unsigned long timerinterval = 30000;        // Wartezeit bis zum Sleep Mode 30s später 10min=>600 000 ms 

//####################################################################################################

void blink(int nb,int t)                   // Start- und Stopp-LED blinkt
      {
 for (i=0; i <= nb; i++)
         {
         analogWrite(G_LED,128);
         delay(t);
         analogWrite(G_LED,0);
         delay(t);
         } 
  i=0;   
  t=0;
      } 
//###################################################################################################

void setup() {
  //ACSR  |= _BV(ACD);                     //Deaktivierung analoger Komponenten   
  //ADCSRA &= ~_BV(ADEN);                  //Deaktivierung des Analog-Digital-Eingangswandlers
  pinMode(b1, INPUT);                      //Wecken
  pinMode(b2, INPUT_PULLUP);               //Tasten
  pinMode(IR_LED, OUTPUT);
  pinMode(G_LED, OUTPUT);
  Serial.begin(9600);

  //SREG &= 0x7F;                            //entspricht "cli();"   //Setzen der Register fuer Pin-Change-Interrupt Pin PB3
                                           //Loeschen des Global Interrupt Enable Bits (I) im Status Register (SREG)
  //GIMSK |= (1 << PCIE);                    //Setze des Pin Change Interrupt Enable Bit
  //PCMSK |= (1 << PCINT3);                  //Setzen des Pin Change Enable Mask Bit 3 (PCINT3)  ==> Pin PB3
  //SREG |= 0x80;                            //entspricht "sei();" //Setzen des Global Interrupt Enable Bits (I) im Status Register (SREG)


  blink(3,500);                           //Unterprogramm aufrufen LED blinkt 

}
//###################################################################################################
/*


 void wakeup(){                            // Chip-Wake-up bei PCINT3-Interrupt

    blink(3,500);                          //Unterprogramm aufrufen LED blinkt
  }
*/
//###################################################################################################
void sleep(){         
 /*
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);   //Konfiguration des Schlafmodus
    sleep_enable();                        // Schlafmodus aktivieren
    attachInterrupt(3, wakeup, LOW);       //Interrupt 3 (Pin PB3) für Alarm verwenden
     blink(30,500);                        //Warnsignal Schlafmodus an
     tempsactuel=millis();                 // Speicherung der Nutzungszeit
    sleep_mode();                          // slepp Mode an
    sleep_disable();                       // Nach dem Aufwachen, sleep Mode deaktivieren
    detachInterrupt(3);                    // deaktiviert Interrupton Pin 3, sodass der WakeUpNow-Code während der normalen Laufzeit nicht ausgeführt wird.
    blink(5,2000);                         //Wecksignal
 

  byte adcsra;

  adcsra = ADCSRA;                         //ADC Control and Status Register A sichern
  ADCSRA &= ~_BV(ADEN);                    //ADC ausschalten

  MCUCR |= (1 << SM1) & ~(1 << SM0);       //Sleep Modus = Power Down
  MCUCR |= _BV(SE);                        //Sleep Enable setzen
  sleep_cpu();                             //Schlafe ....
  MCUCR &= ~(1 << SE);                     //Sleep Disable setzen
 
  ADCSRA = adcsra;  
  */                       //ADCSRA-Register rückspeichern
  blink(3,5000);                            //Signal wieder wach

  }
//###################################################################################################

void loop() {
  /*
  if (digitalRead(b2) == HIGH) 
    {
    Serial.print("G_LED an");  
     
    //delay(50);
    digitalWrite(26, HIGH);
    delay(1000);
    digitalWrite(26, LOW);

    //irsend.sendNEC(0x0000, 32);             //Enter Remote Hex Value
    }
  */
//temps=millis()-tempsactuel;                // Zeit zurücksetzen beim Einschalten
//tempo=tempomin*60000;
//if (temps>=tempo){
                  //sleep();  
                 //} 


/*if (digitalRead(b2) == HIGH) 
    {
      irsend.sendNECMSB(0xC2A9FC0, 32); 
      //irsend.sendJVCMSB(0xC2A9FC0, 32); 
      Serial.print("Taster ausgelenkt "); 
      blink(1,200);    
    } 
    */
   
    /*for (n=0; n <= 100; n++)                //100 Loop durchläufe a 6sec => 10min           
         {
         analogWrite(G_LED,128);
         delay(3000);
         analogWrite(G_LED,0);
         delay(3000);
         } 
  n=0;   
  blink(30,500);   
  statusSleep = true;   

    if (statusSleep)
         {
          sleep();
          statusSleep = false;
         }
    */
    

    //+++++++++++Taster Abfrage+++++++++++++++
    if (digitalRead(b2) == HIGH) 
    {
      irsend.sendNECMSB(0xC2A9FC0, 32); 
      //irsend.sendJVCMSB(0xC2A9FC0, 32); 
      Serial.print("Taster ausgelenkt "); 
      timerMillis = millis();             //Timmer für Sleep Mode reset


      digitalWrite(IR_LED, HIGH);         // Nur zu Testzwecken
      delay(5000);
      digitalWrite(IR_LED, LOW);  


      blink(1,200);    
    }  




    //++++++++++LED Status Blinken++++++++++++
    if (millis() - previousMillis > interval) {
    previousMillis = millis();           // aktuelle Zeit abspeichern
 
    value = !value;                      // LED Zustand wecheln.
 
    digitalWrite(G_LED, value);         // Wert auf den Ausgang schreiben
  }
    //+++++++++Timer Sleep Mode zähler++++++++
    if (millis() - timerMillis > timerinterval) {
    timerMillis = millis();             // aktuelle Zeit abspeichern
    digitalWrite(G_LED, HIGH);         // Warnsignal Sleep Mode
    delay(5000);
    digitalWrite(G_LED, LOW);         
    sleep();
    }

}

Vielen lieben Dank schonmal
bin gespannt auf eure Antworten

Ein richtiges Schaltbild wäre schön, kein Gestrüpp mit irgendwelchen Bauteilen.

Im Code ist so viel auskommentiert, das liest sich ganz schwer.

Ich dachte, das Blinken soll ohne Blockierung funktionieren?

In meinem ersten Ansatz war es mit delay da ich da noch die Idee im Kopf hatte das Tast Signal auch über einen Interupt zu machen. Dies habe ich aber verworfen finde es ist mit einfachen if sätzen schöner. Mit dem Interupt kenn ich mich noch zu wenig aus.

Was ist denn der rechte Button.

Ich sehe:

const int b1  = 3;           //Weckbutton
[...]
  pinMode(b1, INPUT);                      //Wecken

Ist der Hardwareseitig irgendwie bestückt?
Wenn nicht, liegt der in der Luft.

Ansonsten Unmengen auskommentiert und delay(5000) drin.
Auch testweise macht man das nicht, wenn man zeitkritische Dinge lösen will.

4 LED ohne Vorwiderstand an 1 Ausgang? Das kann ja nicht gutgehen :frowning:

Das ist eine selbst entwickelte Platine, der Taskopf lieg gefedert mit 3 Passtiften auf 3 Kugelpaaren auf, wird dieser ausgelenkt wird die Verbindung unterbrochen.

b1 ist vorgesehen für die Weckfunktion aus dem Sleep aber an dieser Baustelle hänge ich noch komplett.

Nur der Loop darf nicht unterbrochen werden.
die vielen und langen delays habe ich oft eingebaut um in Tinkercad zu sehen wo er gerade steht.
zb. hier:

      digitalWrite(IR_LED, HIGH);         // Nur zu Testzwecken
      delay(5000);
      digitalWrite(IR_LED, LOW);  

beim Sleep aufruf leuchtet bewusst die LED 5sec um anzuzeigen das der Taster jetzt ausgeht.

    digitalWrite(G_LED, HIGH);         // Warnsignal Sleep Mode
    delay(5000);
    digitalWrite(G_LED, LOW);  

4 LED ohne Vorwiderstand an 1 Ausgang? Das kann ja nicht gutgehen :frowning:

davon wird eine wirklich verlötet es ging nur um die Pads für einen PCB Entwurf
je nachdem auf welcher Seite der Spindel der Empfänger montiert wird kann man die LED an die gewünschte stelle löten

Ach, sowas kenn ich doch noch aus der CNC-Bauteilprüfung.

Du schreibst

Was ist der rechte Button?

Wie vorhin beschrieben ist der rechte Button diese tast platine

ich hoffe, du hast die platine noch nicht hergestellt, denn wenn Du sie nach dem dezeigten Schaltplan produzierst7produziert hast, wird das ganze, entweder gar nicht , oder nicht lange funktionieren.

  1. fehlen Vorwidrestände an den LED's
  2. fehlt der Ceramik-Kondensator am Attiny (möglichst nahe am ATtiny an VCC und GND
    Ob der ATtiny asu der CR2032-Zelle noch genügend Spannung bekommt, wenn die LED's eingeschaltet sind, bezweifle ich sehr. Das kann so in der Praxis m.M.n. nicht funktionieren. So belastest Du deine Knopfzelle damit extrem.

Nein die Platine ist noch nicht hergestellt. Ging in erster Line mal darum ein 3D Modell einer Möglichen Platine zu erstellen um die etwaigen Größenverhältnisse für das Gehäuse zu ermitteln.

Sind denn die Vorwiderstände bei 3v zwingend notwendig?

Der Kondensator wäre als Puffer gedacht wenn die LEDs an gehen, sehe ich das richtig? Reicht dann die CR2032 ?
Welchen Kondensator bräuchte ich denn dann genau?

im ersten Bild aus Tinkercad sieht man welcher Button links und Rechts liegt

Der Kondensator ist eher dafür, den ATTiny zu stützen und Spannungsschwankungen, welcher Art auch immer, zu glätten.

LEDs brauch immer einen Widerstand. LEDs werden mit Strom geregelt. Keine Begrenzung im Strom, stirbt die LED den Hitzetot. Natürlich begrenzt der Innenwiderstand der Knopfzelle den Strom. Aber da du ja eher Strom sparen willst, denn eine Knopfzelle stellt nicht viel bereit, solltest du den Widerstand so hoch wie möglich wählen. Wie hoch musst du testen und selber entscheiden. LED mit verschiedenen Widerständen an die KnopZelle nach optischer Helligkeit beurteilen. Anhand des Widerstandes kannst du dann auch den Stromfluss berechnen und abschätzen wie lange deine Knopfzelle hällt.

Gibt es den alternativen für eine Knopfzelle?
Die etwas mehr Spannung haben aber von der Bauart nicht recht viel größer sind?

Es gibt verschiedene Knopfzellen. Mit verschiedenen Kapazitäten. Spannung kannst du erhöhen, indem du mehrere Knopfzellen in Reihe betreibst. Kapazitäten kannst du erhöhen indem du Knopfzellen parallel betreibst.

Um Möglichst viel Kapazität auf engen Raum zu haben (kleine Batterie), braucht deine Batterie eine große Energiedichte. Am gebräuchlichsten ist in dem Fall eine Li-Ion Batterie.

Du musst erstmal ermitteln, wieviel Strom deine Schaltung braucht und wie Lange sie laufen soll. Anhand dessen kannst du ermitteln wieviel Kapazität deine Batterie braucht. Und anhand dieser Kapazität kannst du Bauformen der Batterien suchen.

Baue deine Schaltung auf und schaue wie lange sie läuft. Wenn es dir zu kurz hält, gehst du auf Suche nach Stromsparmaßnahmen oder größeren Kapazitäten.

Dazu empfehlen sich natürlich Steckbretter oder LochrasterPCB. Ein PCB fertigen lassen kommt erst später, da sich in diesem Stadium deines Projektes eh viel ändern wird.

also aus der Praxis kenne ich es in den großen Tastern mit diesen Batterien.
Dan wird das Gehäuse zwar etwas höher aber an sich sollten die doch reichen oder?

Wenn Max Continuous Discharge Current (Entladestrom) von 20mA ausreicht.

Das kann man doch nur beurteilen, wenn man den Strombedarf und die gewollte Laufzeit deiner Schaltung kennt. Dies musst du messen und benennen.

Also Sagen wir mal der Taster wird 1xam Tag benutz und blinkt dabei für 10 min bis er wieder in den Schlafmodus geht. Ruhestrom LED aus -> laut Tinkercad 4,5 mA , LED an 12,5mA im Takt von 1500ms. Welchen Stromverbrauch man im Sleep mode hat kann ich nicht sagen da das immer noch nicht funktioniert. Laut diesem Beitag: Wecken mit PCI sollte der Stromverbrauch im Sleep Mode bei weniger als 0,5 µA liegen.

Wenn ich die Batterie alle 2 Monate mal wechseln müsste wäre ich schon zufrieden.

also wenn das so stimmt dann reicht das vollkommen

Code Technisch bin ich aber noch nicht wirklich weiter gekommen.
hab den Code mal etwas aufgeräumt und alles aus kommentierte raus:


#include <Arduino.h>
#include <IRremote.h>
#include <avr/io.h>
#include <avr/wdt.h> 
#include <avr/sleep.h>
#include <avr/interrupt.h>

IRsend irsend;

const int b1  = 3;           //Weckbutton
const int b2  = 4;           //Auslöse Button Tasten
const int G_LED = 0;         //Grüne status LED
const int IR_LED = 1;        //IR LED

int nb=0;                                   // anzahl der blink durchläufe
int t=0;                                    // time zwischen blinklicht 
int i=0;                                    // blink Zähler

// ################## LED Blink Loop Rechner #########################################################

boolean value = LOW;                        // Startwert der LED
unsigned long previousMillis = 0;           // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
unsigned long interval = 1500;              // Interval zwischen zwei Änderungen

// ################# Sleep Timmer Rechner ############################################################

unsigned long timerMillis = 0;              // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
unsigned long timerinterval = 30000;        // Wartezeit bis zum Sleep Mode 30s später 10min=>600 000 ms 

//####################################################################################################

void blink(int nb,int t)                   // Start- und Stopp-LED blinkt
      {
 for (i=0; i <= nb; i++)
         {
         analogWrite(G_LED,128);
         delay(t);
         analogWrite(G_LED,0);
         delay(t);
         } 
  i=0;   
  t=0;
      } 
//###################################################################################################

void setup() {

  pinMode(b1, INPUT);                      //Wecken
  pinMode(b2, INPUT_PULLUP);               //Tasten
  pinMode(IR_LED, OUTPUT);
  pinMode(G_LED, OUTPUT);
  Serial.begin(9600);

  blink(3,500);                           //Unterprogramm aufrufen LED blinkt 
}

//###################################################################################################
void sleep(){         

  blink(3,5000);                            //Signal wieder wach

  }
//###################################################################################################

void loop() {
      //+++++++++++Taster Abfrage+++++++++++++++
    if (digitalRead(b2) == HIGH) 
    {
      irsend.sendNECMSB(0xC2A9FC0, 32); 
      //irsend.sendJVCMSB(0xC2A9FC0, 32); 
      Serial.print("Taster ausgelenkt "); 
      timerMillis = millis();             //Timmer für Sleep Mode reset


      digitalWrite(IR_LED, HIGH);         // Nur zu Testzwecken
      delay(5000);
      digitalWrite(IR_LED, LOW);  


      blink(1,200);    
    }  




    //++++++++++LED Status Blinken++++++++++++
    if (millis() - previousMillis > interval) {
    previousMillis = millis();           // aktuelle Zeit abspeichern
 
    value = !value;                      // LED Zustand wecheln.
 
    digitalWrite(G_LED, value);         // Wert auf den Ausgang schreiben
  }
    //+++++++++Timer Sleep Mode zähler++++++++
    if (millis() - timerMillis > timerinterval) {
    timerMillis = millis();             // aktuelle Zeit abspeichern
    digitalWrite(G_LED, HIGH);         // Warnsignal Sleep Mode
    delay(5000);
    digitalWrite(G_LED, LOW);         
    sleep();
    }
}

Ach den Aufbau habe ich neu gemacht mit den besagten Wiederständen und dem Kondensator

Das Problem bleibt bestehen das die Grüne LED brav vor sich hin blinkt aber nach jedem 4. blinken geht die Rote LED an was eigentlich erst passieren darf wenn der rechte Button betätigt wird. Dieser ist aber ohne Funktion.