ATtiny85 (16MHz external) - IR Signale nach Sleep Mode

Hallo,

ich wollte alle System meiner TV Station via einer IR Diode und ATtiny85 mit externem 16Mhz Quarz auf einmal aus- bzw. einschalten. Soweit so gut, funzt auch TippiToppi!
Nur leider NICHT sobald ich den ATtiny85 in Sleep versetze. :frowning:
Nach dem aufwachen sendet die IR Diode scheinbar nur Grütze, der serielle Ausgang funktioniert komischerweise. Hat jemand einen Tipp woran das liegen könnte?

Verschaltung ATMEL ATTINY 85 / ARDUINO (Optiboot + Clock source 16MHz external):

              +-\/-+
RESET PB5    1|    |8  Vcc
Quarz 16MHz  2|    |7  TX SerialOut
Quarz 16MHz  3|    |6  IR DIODE
GND          4|    |5  TASTER
              +----+

Der Code hier funktioniert tadellos:

#define SERIAL_BAUDRATE 115200
#define DISABLE_CODE_FOR_RECEIVER // Disables restarting receiver after each send. Saves 450 bytes program memory and 269 bytes RAM if receiving functions are not used.

#include <Arduino.h>
#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.
#include <IRremote.hpp>
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/pgmspace.h>


//----------------------------- PIN DEFINITION -------------------------
 // pin 1 / PCINT5 - RESET mit 10kOhm an Vcc
 // pin 2 / PCINT3 - 16 MHz Quarz   
 // pin 3 / PCINT4 - 16 MHz Quarz 
 // pin 4 / GND
 #define I_TASTER_EINS   0  // pin 5
 // pin 6 / #define IR_SEND_PIN     PIN_PB1
 // pin 7 / TX SerialOut
 // pin 8 / Vcc


ISR(PCINT0_vect) {
    // This is called when the interrupt occurs, but I don't need to do anything in it
  }

//-----------Variablen für WAKEUP Modus --------------------------
#define AWAKETIME 5000
unsigned long AwakeMillis = 5000;
unsigned long CurrentMillis = 0;
 
// Tasterentprellung definieren
boolean StateTaster1_ON = false;               // Schalter wurde gedrückt
boolean StateTaster1_OFF = false;               // Schalter wurde gedrückt


//-----------Variablen für Fernbedienungen --------------------------
//Rohwert für VUsolo EINschalten
// Protocol=RC6 Address=0x10 Command=0xC Toggle=1 Raw-Data=0x8052900C 36 bits MSB first
const uint16_t VUsolo_ONRawData[61] = {2630,920, 430,420, 430,470, 430,870, 430,870, 1330,870, 430,420, 430,470, 430,420, 430,470, 430,420, 480,420, 430,470, 830,920, 830,920, 430,420, 880,870, 880,870, 430,470, 830,920, 430,420, 430,470, 430,420, 430,470, 430,420, 430,470, 430,420, 880,470, 430,870, 430,420, 430};  

//Rohwert für VUsolo AUSschalten
// Protocol=RC6 Address=0x10 Command=0xC Raw-Data=0x8052100C 36 bits MSB first
const uint16_t VUsolo_OFFRawData[63] = {2630,870, 430,470, 430,420, 430,920, 380,920, 1280,920, 380,470, 430,470, 430,420, 430,470, 430,420, 430,470, 430,420, 880,870, 880,870, 430,470, 830,920, 430,420, 430,470, 430,420, 880,870, 430,470, 430,420, 430,470, 430,420, 430,470, 430,420, 430,470, 880,420, 430,870, 430,470, 430};  

//Rohwert für Sharp EIN/AUSschalten
const unsigned int SharpTV_ONOFFRawData [31]   = {320,1680, 320,680, 320,680, 320,680, 320,680, 320,680, 320,1680, 320,1680, 320,680, 320,1680, 320,680, 320,680, 320,680, 320,1680, 320,680 ,320}; // Sharp 15Bit
const unsigned int SharpTV_ONOFFRawDataINV [31]= {320,1680, 320,680, 320,680, 320,680, 320,680, 320,1680, 320,680, 320,680, 320,1680, 320,680, 320,1680, 320,1680, 320,1680, 320,680, 320,1680, 320};  // Sharp 15Bit


//==============================================================================================================
//                          Zusatzfunktionen
//==============================================================================================================
void goToSleep ()
{
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); // choose power down mode
  sleep_enable();
  sleep_cpu();   

  /*+++++++++++++ The program will continue from here. +++++++++++++++++*/  
  sleep_disable();       // first thing after waking from sleep: disable sleep...
  power_all_enable();    // power everything back on

  delay(100);
  Serial.print("AWAKE!"); 
  AwakeMillis = millis();  //Sleep Timer neu aufziehen
  Serial.print("  Time:");
  Serial.println(AwakeMillis);
}  // end of goToSleep  


    
    
#define CLICKBTN_PULLUP HIGH

class ClickButton
{
  public:
    ClickButton(uint8_t buttonPin);
    ClickButton(uint8_t buttonPin, boolean active);
    ClickButton(uint8_t buttonPin, boolean active, boolean internalPullup);
    void Update();
    int clicks;                   // button click counts to return
    boolean depressed;            // the currently debounced button (press) state (presumably it is not sad :)
    long debounceTime;
    long multiclickTime;
    long longClickTime;
  private:
    uint8_t _pin;                 // Arduino pin connected to the button
    boolean _activeHigh;          // Type of button: Active-low = 0 or active-high = 1
    boolean _btnState;            // Current appearant button state
    boolean _lastState;           // previous button reading
    int _clickCount;              // Number of button clicks within multiclickTime milliseconds
    long _lastBounceTime;         // the last time the button input pin was toggled, due to noise or a press
};

ClickButton::ClickButton(uint8_t buttonPin, boolean activeType, boolean internalPullup)
{
  _pin           = buttonPin;
  _activeHigh    = activeType;
  _btnState      = !_activeHigh;  // initial button state in active-high logic
  _lastState     = _btnState;
  _clickCount    = 0;
  clicks         = 0;
  depressed      = 0;
  _lastBounceTime= 0;
  debounceTime   = 20;            // Debounce timer in ms
  multiclickTime = 250;           // Time limit for multi clicks
  longClickTime  = 1000;          // time until "long" click register

  // Turn on internal pullup resistor if applicable
  if (_activeHigh == LOW && internalPullup == CLICKBTN_PULLUP)
    pinMode(_pin, INPUT_PULLUP);
  else
    pinMode(_pin, INPUT);
}


void ClickButton::Update()
{
  long now = (long)millis();      // get current time
  _btnState = digitalRead(_pin);  // current appearant button state

  // Make the button logic active-high in code
  if (!_activeHigh) _btnState = !_btnState;
  // If the switch changed, due to noise or a button press, reset the debounce timer
  if (_btnState != _lastState) _lastBounceTime = now;
  // debounce the button (Check if a stable, changed state has occured)
  if (now - _lastBounceTime > debounceTime && _btnState != depressed)
  {
    depressed = _btnState;
    if (depressed) _clickCount++;
  }
  // If the button released state is stable, report nr of clicks and start new cycle
  if (!depressed && (now - _lastBounceTime) > multiclickTime)
  {
    // positive count for released buttons
    clicks = _clickCount;
    _clickCount = 0;
  }
  // Check for "long click"
  if (depressed && (now - _lastBounceTime > longClickTime))
  {
    // negative count for long clicks
    clicks = 0 - _clickCount;
    _clickCount = 0;
  }
  _lastState = _btnState;
}

// the Button
ClickButton button1(I_TASTER_EINS, LOW, CLICKBTN_PULLUP);

// Button results
int function = 0;    


void LED_flash (byte O_LED_PIN, byte BLINKZYKLEN)
  {
  pinMode (O_LED_PIN, OUTPUT);
  for (byte i = 0; i < BLINKZYKLEN; i++)
    {
    digitalWrite(O_LED_PIN, !digitalRead(O_LED_PIN));   // Toggle led
    delay (50);   
    }
    digitalWrite(O_LED_PIN, HIGH);
  }  // end of flash


//==============================================================================================================
//                          Initialisieren
//==============================================================================================================
void setup() {
    pinMode (I_TASTER_EINS, INPUT_PULLUP);

    Serial.begin(SERIAL_BAUDRATE);
    delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!

    // Just to know which program is running on my Arduino
    Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRREMOTE));
    Serial.println(F("Send IR signals at pin " STR(IR_SEND_PIN)));
    Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_ATTINY_SERIAL_OUT));

   // pin change interrupt (example for D0/ pin 5)
    PCMSK  |= bit (PCINT0);  // want pin D0 / pin 5
    GIFR   |= bit (PCIF);    // clear any outstanding interrupts
    GIMSK  |= bit (PCIE);    // enable pin change interrupts 
    
    IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
    AwakeMillis = millis();
}


//==============================================================================================================
//                           Arbeitsschleife
//==============================================================================================================
void loop() {
 // Update button state
 button1.Update();

// Save click codes in LEDfunction, as click codes are reset at next Update()
 if (button1.clicks != 0) function = button1.clicks;

//Ausgabe erfolgt nur EINMAL
 if(button1.clicks == 1) StateTaster1_ON=true;
 if(button1.clicks == 2) StateTaster1_OFF=true;


// ---------------------- System AUSschalten ------------------------------------
 if (StateTaster1_ON){
  delay(200); 
  AwakeMillis = millis();  //Sleep Timer neu aufziehen
  Serial.println(F("Button 1x"));
  //Rohwert für VUsolo AUSschalten
  IrSender.sendRaw(VUsolo_OFFRawData, sizeof(VUsolo_OFFRawData) / sizeof(VUsolo_OFFRawData[0]), 38); // Note the approach used to automatically calculate the size of the array.
  delay(100); 
  
  //Rohwert für Sharp EIN/AUSschalten
  IrSender.sendRaw(SharpTV_ONOFFRawData, sizeof(SharpTV_ONOFFRawData) / sizeof(SharpTV_ONOFFRawData[0]), 38); // Note the approach used to automatically calculate the size of the array.
  delay(40);
  IrSender.sendRaw(SharpTV_ONOFFRawDataINV, sizeof(SharpTV_ONOFFRawDataINV) / sizeof(SharpTV_ONOFFRawDataINV[0]), 38); // Note the approach used to automatically calculate the size of the array.
  
  delay(100);
  IrSender.sendNEC(0x4FB50AF,32);

  StateTaster1_ON =false;
  StateTaster1_OFF=false;  
 }

// ------------------------ System EINschalten ---------------------------------------
 if (StateTaster1_OFF){
  delay(200); 
  AwakeMillis = millis();  //Sleep Timer neu aufziehen
  Serial.println(F("Button 2x"));
  //Rohwert für VUsolo AUSschalten
  IrSender.sendRaw(VUsolo_ONRawData, sizeof(VUsolo_ONRawData) / sizeof(VUsolo_ONRawData[0]), 38); // Note the approach used to automatically calculate the size of the array.
  delay(100); 
  
  //Rohwert für Sharp EIN/AUSschalten
  IrSender.sendRaw(SharpTV_ONOFFRawData, sizeof(SharpTV_ONOFFRawData) / sizeof(SharpTV_ONOFFRawData[0]), 38); // Note the approach used to automatically calculate the size of the array.
  delay(40);
  IrSender.sendRaw(SharpTV_ONOFFRawDataINV, sizeof(SharpTV_ONOFFRawDataINV) / sizeof(SharpTV_ONOFFRawDataINV[0]), 38); // Note the approach used to automatically calculate the size of the array.
  
  delay(100);
  IrSender.sendNEC(0x4FB50AF,32);

  StateTaster1_ON =false;
  StateTaster1_OFF=false;  
 }

//// ----------- ATTiny in Sleep Modus setzten -----------------
// CurrentMillis=millis();
// if((CurrentMillis-AwakeMillis) > AWAKETIME)  {
//  Serial.println(F("ATtiny in sleep mode"));
//  delay(100);
//  goToSleep ();
// }
} // End of Programm 

Sobald ich den Sleep Bereich aktiviere, der ATtiny85 einschläft und nach dem Aufwachen die gleiche IR Sequenzen schicken soll, kommt scheinbar nur Grütze raus...

// ----------- ATTiny in Sleep Modus setzten -----------------
 CurrentMillis=millis();
 if((CurrentMillis-AwakeMillis) > AWAKETIME)  {
  Serial.println(F("ATtiny in sleep mode"));
  delay(100);
  goToSleep ();
 }
} // End of Programm 

IRremote Lib von hier: https://github.com/Arduino-IRremote/Arduino-IRremote

mache

nach jedem Aufwachen

Das IrSender.begin(); mit in die Aufwachsequenz zu nehmen, war auch meine erste Idee. Funktioniert aber leider NICHT, kommt weiterhin nur Grütze raus...

 /*+++++++++++++ The program will continue from here. +++++++++++++++++*/  
  sleep_disable();       // first thing after waking from sleep: disable sleep...
  power_all_enable();    // power everything back on

  delay(100);
  IrSender.begin(); // Start with IR_SEND_PIN as send pin and enable feedback LED at default feedback LED pin
  Serial.print("AWAKE!"); 

Versuch mal: IrSender.enableIROut(38);

Leider auch nicht die Lösung! :frowning:

Deshalb habe mal etwas weiter rumgespielt und scheinbar liegt es am

Wenig Arbeitsspeicher verfügbar, es können Stabilitätsprobleme auftreten.

Denn wenn ich Serial.print ect. auskommentiere und den benötigten Speicher von

Der Sketch verwendet 4320 Bytes (56%) des Programmspeicherplatzes. Das Maximum sind 7616 Bytes.
Globale Variablen verwenden 441 Bytes (86%) des dynamischen Speichers, 71 Bytes für lokale Variablen verbleiben. Das Maximum sind 512 Bytes.

auf:

Der Sketch verwendet 3026 Bytes (39%) des Programmspeicherplatzes. Das Maximum sind 7616 Bytes.
Globale Variablen verwenden 422 Bytes (82%) des dynamischen Speichers, 90 Bytes für lokale Variablen verbleiben. Das Maximum sind 512 Bytes.
Wenig Arbeitsspeicher verfügbar, es können Stabilitätsprobleme auftreten.

reduziere. Scheint keine Grütze mehr nach dem Aufwachen versendet zu werden! :grinning:

Nutze für konstante Texte das F-Macro:

// alt
Serial.print("Text");
// neu
Serial.print(F("Text"));

Gruß Tommy

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.