<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title><![CDATA[forum.technik-hobby.de - Nützliche Funktionen]]></title>
		<link>https://forum.technik-hobby.de/</link>
		<description><![CDATA[forum.technik-hobby.de - https://forum.technik-hobby.de]]></description>
		<pubDate>Tue, 07 Apr 2026 09:49:51 +0000</pubDate>
		<generator>MyBB</generator>
		<item>
			<title><![CDATA[Wemos D1 mini mit WPS-Pushbutton]]></title>
			<link>https://forum.technik-hobby.de/thread-97.html</link>
			<pubDate>Wed, 15 Jan 2020 14:15:54 +0100</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.technik-hobby.de/member.php?action=profile&uid=2">Gorathan</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.technik-hobby.de/thread-97.html</guid>
			<description><![CDATA[Um einen "Wemos D1 mini" (oder einen anderen ESP8266) mit dem WLAN zu verbinden, muss man nicht unbedingt SSID und PSK im Programm mitgeben.<br />
Das würde den Betrieb ja auch auf das eine WLAN beschränken.<br />
Es gibt auch die Möglichkeit, einen Taster (einfach von D3 bzw. GPIO 0 nach GND) als WPS-Pushbutton zu benutzen:<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://forum.technik-hobby.de/images/attachtypes/image.png" title=".gif" border="0" alt=".gif" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=144" target="_blank" title="">Wemos D1 mini WPS.GIF</a> (Größe: 11,8 KB / Downloads: 9)
<!-- end: postbit_attachments_attachment --><br />
<br />
Die Funktion "WiFi.beginWPSConfig()" in der "ESP8266WiFi.h"-Library übernimmt dann den Datenaustausch mit dem Router.<br />
<br />
Ich habe ein Programm geschrieben, das folgendes ermöglicht:<br />
1. Man startet die WPS-Pushbutton-Methode auf dem WLAN-Router.<br />
2. Man hält die WPS-Taste am Wemos min. 2 Sekuden gedrückt, bis die WLAN-LED schnell blinkt.<br />
3. Dann lässt man die Taste los und wartet etwas (maximal dauert das 2 Minuten).<br />
4. Der Wemos verbindet sich mit dem WLAN.<br />
Wenn die Verbindung erfolgreich war, dann leuchtet die WLAN-LED nun dauerhaft. Wenn nicht, dann blitzt die LED einmal pro Sekunde kurz auf und man muss die Prozedur wiederholen.<br />
<br />
Bei erfolgreicher WLAN-Verbindung holt sich das Programm dann das aktuelle Datum/Uhrzeit von einem NTP-Server aus dem Internet.<br />
Außerdem habe ich noch die Möglichkeit eines "OverTheAir"-Updates (OTA) eingebaut. So kann man weitere Firmware-Updates über das WLAN durchführen.<br />
<br />
Das Programm befindet sich im ZIP-Archiv (Anhang).<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://forum.technik-hobby.de/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=145" target="_blank" title="">Wemos_WPS_Pushbutton.zip</a> (Größe: 2,6 KB / Downloads: 16)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[Um einen "Wemos D1 mini" (oder einen anderen ESP8266) mit dem WLAN zu verbinden, muss man nicht unbedingt SSID und PSK im Programm mitgeben.<br />
Das würde den Betrieb ja auch auf das eine WLAN beschränken.<br />
Es gibt auch die Möglichkeit, einen Taster (einfach von D3 bzw. GPIO 0 nach GND) als WPS-Pushbutton zu benutzen:<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://forum.technik-hobby.de/images/attachtypes/image.png" title=".gif" border="0" alt=".gif" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=144" target="_blank" title="">Wemos D1 mini WPS.GIF</a> (Größe: 11,8 KB / Downloads: 9)
<!-- end: postbit_attachments_attachment --><br />
<br />
Die Funktion "WiFi.beginWPSConfig()" in der "ESP8266WiFi.h"-Library übernimmt dann den Datenaustausch mit dem Router.<br />
<br />
Ich habe ein Programm geschrieben, das folgendes ermöglicht:<br />
1. Man startet die WPS-Pushbutton-Methode auf dem WLAN-Router.<br />
2. Man hält die WPS-Taste am Wemos min. 2 Sekuden gedrückt, bis die WLAN-LED schnell blinkt.<br />
3. Dann lässt man die Taste los und wartet etwas (maximal dauert das 2 Minuten).<br />
4. Der Wemos verbindet sich mit dem WLAN.<br />
Wenn die Verbindung erfolgreich war, dann leuchtet die WLAN-LED nun dauerhaft. Wenn nicht, dann blitzt die LED einmal pro Sekunde kurz auf und man muss die Prozedur wiederholen.<br />
<br />
Bei erfolgreicher WLAN-Verbindung holt sich das Programm dann das aktuelle Datum/Uhrzeit von einem NTP-Server aus dem Internet.<br />
Außerdem habe ich noch die Möglichkeit eines "OverTheAir"-Updates (OTA) eingebaut. So kann man weitere Firmware-Updates über das WLAN durchführen.<br />
<br />
Das Programm befindet sich im ZIP-Archiv (Anhang).<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://forum.technik-hobby.de/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=145" target="_blank" title="">Wemos_WPS_Pushbutton.zip</a> (Größe: 2,6 KB / Downloads: 16)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Taster entprellen]]></title>
			<link>https://forum.technik-hobby.de/thread-54.html</link>
			<pubDate>Fri, 26 Apr 2019 18:08:21 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.technik-hobby.de/member.php?action=profile&uid=2">Gorathan</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.technik-hobby.de/thread-54.html</guid>
			<description><![CDATA[Da ich in meinen Projekten oftmals einen oder mehrere Taster verwende und ich zum entprellen nicht gleich eine "riesige" Library einbinden will, habe ich mal eine kleine PushButton-Klasse geschrieben. Die verbraucht nur wenig Speicher und hat doch alles, was ich so brauche (inkl. konfigurierbarer Tastenwiederholung).<br />
Diese Klasse verwendet <span style="font-weight: bold;" class="mycode_b">keine</span> Interrupts!<br />
Der Tastenzustand wird jedes Mal bei "Btn.pressed()" ausgelesen, was bedeutet, dass die Methode jedes Mal in der Loop-Funktion aufgerufen werden muss.<br />
Und die Loop-Funktion darf nicht blockierend programmiert sein (was sich sowieso von selbst verstehen sollte). Delays unbedingt vermeiden!<br />
<br />
<br />
<br />
<div class="spoiler">
		<div class="spoiler_title"><span class="spoiler_button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[1].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</span>PushButton.h:</div>
		<div class="spoiler_content" style="display: none;">
<br />
<br />
<br />
<br />
<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#ifndef PushButton_h<br />
#define PushButton_h 1<br />
#if (ARDUINO &gt;= 100)<br />
  #include "Arduino.h"<br />
#else<br />
  #include "WProgram.h"<br />
#endif<br />
/****************************************************************************************************************<br />
    PushButton-Klasse zum entprellen von Tastern<br />
    Version: 1.0.0.1 (26.04.2019)<br />
    Autor: Thomas Stephan (Gorathan)<br />
    Homepage: https://forum.technik-hobby.de<br />
    PushButton-Parameter: <br />
    Anschluss-Pin (0...255)<br />
    Pinmodus (0 = INPUT, 1 = INPUT_PULLUP, Standard = 1)<br />
    Reaktion (0 = LOW-aktiv, 1 = HIGH-aktiv, Standard = 0)<br />
    Entprellzeit (0...255 in ms, Standard = 30)<br />
    Wiederholzeit (0...65535 in ms, Standard = 0 / keine Tastenwiederholung)<br />
    Verzoegerungszeit (0...65535 in ms, Standard = 500) bis zur ersten Tastenwiederholung<br />
    <br />
    Beispiel: [] = optional<br />
      PushButton Btn(Anschluss-Pin[, Pinmodus][, Reaktion][, Entprellzeit][, Wiederholzeit][, Verzoegerungszeit]);<br />
    Abfrage: <br />
      if (Btn.pressed()) {...}<br />
    Wiederholzeit setzen:<br />
      Btn.setRepeatTime(repeatTime, delayTime);<br />
*****************************************************************************************************************/<br />
class PushButton {<br />
  private:<br />
    const uint8_t _pin, _dbTime;<br />
    const bool _edge;<br />
    uint16_t _RepeatTime, _DelayTime;<br />
    bool _newState, _oldState, _state, _1stClick;<br />
    uint32_t _dbMillis, _repMillis;<br />
  public:<br />
    // Konstruktor<br />
    PushButton(const uint8_t pin, const bool pullup = 1, const bool edge = 0, &#92;<br />
               const uint8_t dbTime = 30, const uint16_t repeatTime = 0, const uint16_t delayTime = 500);<br />
    // Methoden<br />
    bool pressed(void);<br />
    void setRepeatTime(const uint16_t repeatTime, const uint16_t delayTime = 500) {<br />
      _RepeatTime = repeatTime;<br />
      _DelayTime = delayTime;<br />
    };<br />
};<br />
#endif</code></div></div><br />
</div>
	</div>
<br />
<div class="spoiler">
		<div class="spoiler_title"><span class="spoiler_button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[1].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</span>PushButton.cpp:</div>
		<div class="spoiler_content" style="display: none;">
<br />
<br />
<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#include "PushButton.h"<br />
<br />
/***** Konstruktor *****/<br />
PushButton::PushButton(const uint8_t pin, const bool pullup, const bool edge, &#92;<br />
                       const uint8_t dbTime, const uint16_t repeatTime, const uint16_t delayTime):<br />
  _pin(pin), _edge(edge), _dbTime(dbTime), _RepeatTime(repeatTime), _DelayTime(delayTime)<br />
{<br />
  pinMode(pin, pullup ? INPUT_PULLUP : INPUT);<br />
}<br />
<br />
/***** Methode *****/<br />
bool PushButton::pressed(void) {<br />
  const uint32_t nowMillis = millis();<br />
  bool pressed = false;<br />
  _newState = digitalRead(_pin) == _edge;<br />
  if (_newState != _oldState) {<br />
    if (nowMillis - _dbMillis &gt; _dbTime) {<br />
      _repMillis = nowMillis;<br />
      _1stClick = true;<br />
      _oldState = _newState;<br />
      if (_newState) pressed = true;<br />
    }<br />
    _dbMillis = nowMillis;<br />
  } else if (_RepeatTime &amp;&amp; _newState &amp;&amp; nowMillis - _repMillis &gt; _RepeatTime + _1stClick * _DelayTime) {<br />
    _repMillis = nowMillis;<br />
    _state ^= 1;<br />
    _1stClick = false;<br />
    pressed = _state;<br />
  }<br />
  return pressed;<br />
}</code></div></div><br />
</div>
	</div>
<br />
Im Anhang befindet sich noch ein Beispiel-Sketch für einen Arduino-Nano.<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://forum.technik-hobby.de/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=130" target="_blank" title="">My_PushButton_Class.zip</a> (Größe: 2,33 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[Da ich in meinen Projekten oftmals einen oder mehrere Taster verwende und ich zum entprellen nicht gleich eine "riesige" Library einbinden will, habe ich mal eine kleine PushButton-Klasse geschrieben. Die verbraucht nur wenig Speicher und hat doch alles, was ich so brauche (inkl. konfigurierbarer Tastenwiederholung).<br />
Diese Klasse verwendet <span style="font-weight: bold;" class="mycode_b">keine</span> Interrupts!<br />
Der Tastenzustand wird jedes Mal bei "Btn.pressed()" ausgelesen, was bedeutet, dass die Methode jedes Mal in der Loop-Funktion aufgerufen werden muss.<br />
Und die Loop-Funktion darf nicht blockierend programmiert sein (was sich sowieso von selbst verstehen sollte). Delays unbedingt vermeiden!<br />
<br />
<br />
<br />
<div class="spoiler">
		<div class="spoiler_title"><span class="spoiler_button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[1].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</span>PushButton.h:</div>
		<div class="spoiler_content" style="display: none;">
<br />
<br />
<br />
<br />
<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#ifndef PushButton_h<br />
#define PushButton_h 1<br />
#if (ARDUINO &gt;= 100)<br />
  #include "Arduino.h"<br />
#else<br />
  #include "WProgram.h"<br />
#endif<br />
/****************************************************************************************************************<br />
    PushButton-Klasse zum entprellen von Tastern<br />
    Version: 1.0.0.1 (26.04.2019)<br />
    Autor: Thomas Stephan (Gorathan)<br />
    Homepage: https://forum.technik-hobby.de<br />
    PushButton-Parameter: <br />
    Anschluss-Pin (0...255)<br />
    Pinmodus (0 = INPUT, 1 = INPUT_PULLUP, Standard = 1)<br />
    Reaktion (0 = LOW-aktiv, 1 = HIGH-aktiv, Standard = 0)<br />
    Entprellzeit (0...255 in ms, Standard = 30)<br />
    Wiederholzeit (0...65535 in ms, Standard = 0 / keine Tastenwiederholung)<br />
    Verzoegerungszeit (0...65535 in ms, Standard = 500) bis zur ersten Tastenwiederholung<br />
    <br />
    Beispiel: [] = optional<br />
      PushButton Btn(Anschluss-Pin[, Pinmodus][, Reaktion][, Entprellzeit][, Wiederholzeit][, Verzoegerungszeit]);<br />
    Abfrage: <br />
      if (Btn.pressed()) {...}<br />
    Wiederholzeit setzen:<br />
      Btn.setRepeatTime(repeatTime, delayTime);<br />
*****************************************************************************************************************/<br />
class PushButton {<br />
  private:<br />
    const uint8_t _pin, _dbTime;<br />
    const bool _edge;<br />
    uint16_t _RepeatTime, _DelayTime;<br />
    bool _newState, _oldState, _state, _1stClick;<br />
    uint32_t _dbMillis, _repMillis;<br />
  public:<br />
    // Konstruktor<br />
    PushButton(const uint8_t pin, const bool pullup = 1, const bool edge = 0, &#92;<br />
               const uint8_t dbTime = 30, const uint16_t repeatTime = 0, const uint16_t delayTime = 500);<br />
    // Methoden<br />
    bool pressed(void);<br />
    void setRepeatTime(const uint16_t repeatTime, const uint16_t delayTime = 500) {<br />
      _RepeatTime = repeatTime;<br />
      _DelayTime = delayTime;<br />
    };<br />
};<br />
#endif</code></div></div><br />
</div>
	</div>
<br />
<div class="spoiler">
		<div class="spoiler_title"><span class="spoiler_button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[1].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</span>PushButton.cpp:</div>
		<div class="spoiler_content" style="display: none;">
<br />
<br />
<br />
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#include "PushButton.h"<br />
<br />
/***** Konstruktor *****/<br />
PushButton::PushButton(const uint8_t pin, const bool pullup, const bool edge, &#92;<br />
                       const uint8_t dbTime, const uint16_t repeatTime, const uint16_t delayTime):<br />
  _pin(pin), _edge(edge), _dbTime(dbTime), _RepeatTime(repeatTime), _DelayTime(delayTime)<br />
{<br />
  pinMode(pin, pullup ? INPUT_PULLUP : INPUT);<br />
}<br />
<br />
/***** Methode *****/<br />
bool PushButton::pressed(void) {<br />
  const uint32_t nowMillis = millis();<br />
  bool pressed = false;<br />
  _newState = digitalRead(_pin) == _edge;<br />
  if (_newState != _oldState) {<br />
    if (nowMillis - _dbMillis &gt; _dbTime) {<br />
      _repMillis = nowMillis;<br />
      _1stClick = true;<br />
      _oldState = _newState;<br />
      if (_newState) pressed = true;<br />
    }<br />
    _dbMillis = nowMillis;<br />
  } else if (_RepeatTime &amp;&amp; _newState &amp;&amp; nowMillis - _repMillis &gt; _RepeatTime + _1stClick * _DelayTime) {<br />
    _repMillis = nowMillis;<br />
    _state ^= 1;<br />
    _1stClick = false;<br />
    pressed = _state;<br />
  }<br />
  return pressed;<br />
}</code></div></div><br />
</div>
	</div>
<br />
Im Anhang befindet sich noch ein Beispiel-Sketch für einen Arduino-Nano.<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://forum.technik-hobby.de/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=130" target="_blank" title="">My_PushButton_Class.zip</a> (Größe: 2,33 KB / Downloads: 3)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Anfang der Jahreszeiten berechnen]]></title>
			<link>https://forum.technik-hobby.de/thread-53.html</link>
			<pubDate>Mon, 22 Apr 2019 17:39:58 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.technik-hobby.de/member.php?action=profile&uid=2">Gorathan</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.technik-hobby.de/thread-53.html</guid>
			<description><![CDATA[Um den Anfang der Jahreszeiten genau berechnen zu können, muss man schon einen 32-Bit-Mikroprozessor nehmen. Also einen ESP8266 zum Beispiel. <br />
Ein 8-Bit ATmega (z.B. Arduino UNO oder Nano) würde ein "falsches" Ergebnis liefern. Die Ungenauigkeit liegt dort bei bis zu 12 Stunden.<br />
<br />
Mit einem ESP8266 funktioniert das Programm aber recht genau (Abweichung liegt bei +-1 Minute).<br />
Ich habe das Programm auf Mitteleuropäische Zeit konfiguriert. Die Sommerzeit wird automatisch addiert. Es wird keine zusätzliche Bibliothek benötigt.<br />
Vielleicht könnt ihr so ein Programm ja gebrauchen...<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://forum.technik-hobby.de/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=128" target="_blank" title="">CalcSeason.zip</a> (Größe: 2,92 KB / Downloads: 8)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[Um den Anfang der Jahreszeiten genau berechnen zu können, muss man schon einen 32-Bit-Mikroprozessor nehmen. Also einen ESP8266 zum Beispiel. <br />
Ein 8-Bit ATmega (z.B. Arduino UNO oder Nano) würde ein "falsches" Ergebnis liefern. Die Ungenauigkeit liegt dort bei bis zu 12 Stunden.<br />
<br />
Mit einem ESP8266 funktioniert das Programm aber recht genau (Abweichung liegt bei +-1 Minute).<br />
Ich habe das Programm auf Mitteleuropäische Zeit konfiguriert. Die Sommerzeit wird automatisch addiert. Es wird keine zusätzliche Bibliothek benötigt.<br />
Vielleicht könnt ihr so ein Programm ja gebrauchen...<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://forum.technik-hobby.de/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=128" target="_blank" title="">CalcSeason.zip</a> (Größe: 2,92 KB / Downloads: 8)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Buzzer-ISR]]></title>
			<link>https://forum.technik-hobby.de/thread-51.html</link>
			<pubDate>Fri, 05 Apr 2019 15:36:18 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.technik-hobby.de/member.php?action=profile&uid=2">Gorathan</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.technik-hobby.de/thread-51.html</guid>
			<description><![CDATA[Hier ein kleines Beispiel, wie man einen aktiven Buzzer per Timer-Interrupt ansteuern kann.<br />
Das hat den Vorteil, dass man keine Delays und Schleifen benutzen muss. Man gibt einfach z.B. "Beep(3, 500, 200);" ein und schon werden drei Toene mit 500ms Puls- und 200ms Pausendauer abgespielt.<br />
Weil das interruptgesteuert ist, kann man danach einfach das eigene Programm weiterlaufen lassen.<br />
Man muss nur aufpassen, bei Programmen oder Bibliotheken, die ebenfalls den Timer1-Interrupt benutzen. Dann muss man auf einen anderen Timer-Interrupt ausweichen.<br />
<br />
Hier mal als Fritzing-Platine:<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://forum.technik-hobby.de/images/attachtypes/image.png" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=125" target="_blank" title="">Nano_Buzzer.png</a> (Größe: 194,77 KB / Downloads: 1)
<!-- end: postbit_attachments_attachment --><br />
<br />
<br />
<div class="spoiler">
		<div class="spoiler_title"><span class="spoiler_button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[1].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</span>Sourcecode:</div>
		<div class="spoiler_content" style="display: none;">
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#include &lt;TimerOne.h&gt;<br />
<br />
const byte BUZZER_PIN = 5;        // den aktiven Buzzer mit Plus an den Pin D5 vom Arduino Nano und Minus an GND <br />
<br />
// Struktur fuer den Buzzer<br />
struct tBuzzer {<br />
  bool state = 0;                 // Status des Buzzers (1 = ein, 0 = aus)<br />
  uint8_t tones = 0;              // Anzahl der abzuspielenden Toene<br />
  uint16_t times[2] = {0, 0};     // Array mit [0] = Pausenzeit, [1] = Pulszeit<br />
  uint32_t ticks = 0;             // zum merken der Millisekunden<br />
};<br />
<br />
volatile struct tBuzzer buzzer;   // Buzzer-Struktur als volatile, weil sie in einer Interrupt-Funktion verwendet wird<br />
<br />
<br />
// Interrupt-Routine zum reagieren auf die Anzahl und die Puls-/Pausenzeit des Buzzers<br />
void BeepISR() {<br />
  // wenn noch Toene abgespielt werden muessen und die Puls- bzw. Pausenzeit abgelaufen ist, dann...<br />
  if (buzzer.tones &amp;&amp; (millis() - buzzer.ticks &gt; buzzer.times[buzzer.state])) {<br />
    buzzer.state ^= 1;                      // den Status mit "XOR 1" invertieren<br />
    if (!buzzer.state) buzzer.tones--;      // wenn Status = 0, dann die Anzahl um eins verringern<br />
    digitalWrite(BUZZER_PIN, buzzer.state); // den Buzzer ein-/ausschalten (je nach Status)<br />
    buzzer.ticks = millis();                // die Millisekunden merken<br />
  }<br />
}<br />
<br />
// Funktion, um die Ausgabe der Toene zu starten<br />
// Parameter: Anzahl der Toene 0...255, Pulsdauer in ms 0...65535 [, Pausendauer in ms 0...65535]<br />
void Beep(const uint8_t tones, const uint16_t pulse, const uint16_t pause = 0) {<br />
  uint8_t oldSREG = SREG;        // Interrupt-Register merken<br />
  cli();                         // Interrupts verhindern<br />
  if (!buzzer.tones) {           // wenn die bisherigen Toene abgespielt wurden<br />
    buzzer.tones = tones;        // die Parameter in die Struktur uebernehmen<br />
    buzzer.times[0] = pause;<br />
    buzzer.times[1] = pulse;<br />
    buzzer.ticks = millis();     // die Millisekunden merken<br />
  }<br />
  SREG = oldSREG;                // Interrupt-Register wieder herstellen<br />
}<br />
<br />
void setup() {<br />
  digitalWrite(BUZZER_PIN, LOW);   // sicherstellen, dass der Pin auf LOW liegt<br />
  pinMode(BUZZER_PIN, OUTPUT);     // den Pin fuer den Buzzer als Ausgang schalten<br />
  Timer1.initialize(1000);         // Timer-Interrupt (alle 1000us = 1ms) initialisieren<br />
  Timer1.attachInterrupt(BeepISR); // zum steuern der Buzzerausgabe<br />
<br />
  // Beispiele:<br />
  Beep(5, 25, 500);                // fuenf Toene ausgeben (Puls: 25ms, Pause: 500ms)<br />
  delay(4000);                     // als Beispiel, dass der Nano gerade etwas anderes tut (die Beeps sind interruptgesteuert)<br />
<br />
  Beep(2, 300, 150);               // zwei Toene ausgeben (Puls: 300ms, Pause: 150ms)<br />
  delay(4000);                     // als Beispiel, dass der Nano gerade etwas anderes tut (die Beeps sind interruptgesteuert)<br />
<br />
  Beep(1, 1000);                   // ein Ton ausgeben (Puls: 1000ms, Pause: 0ms, kann weggelassen werden)<br />
  delay(4000);                     // als Beispiel, dass der Nano gerade etwas anderes tut (die Beeps sind interruptgesteuert)<br />
}<br />
<br />
void loop() {<br />
}</code></div></div><br />
</div>
	</div>
<br />
Im Anhang (ZIP-Archiv) befindet sich der Sourcecode als Arduino-Sketch.<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://forum.technik-hobby.de/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=126" target="_blank" title="">Buzzer-ISR.zip</a> (Größe: 1,38 KB / Downloads: 1)
<!-- end: postbit_attachments_attachment -->]]></description>
			<content:encoded><![CDATA[Hier ein kleines Beispiel, wie man einen aktiven Buzzer per Timer-Interrupt ansteuern kann.<br />
Das hat den Vorteil, dass man keine Delays und Schleifen benutzen muss. Man gibt einfach z.B. "Beep(3, 500, 200);" ein und schon werden drei Toene mit 500ms Puls- und 200ms Pausendauer abgespielt.<br />
Weil das interruptgesteuert ist, kann man danach einfach das eigene Programm weiterlaufen lassen.<br />
Man muss nur aufpassen, bei Programmen oder Bibliotheken, die ebenfalls den Timer1-Interrupt benutzen. Dann muss man auf einen anderen Timer-Interrupt ausweichen.<br />
<br />
Hier mal als Fritzing-Platine:<br />
<!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://forum.technik-hobby.de/images/attachtypes/image.png" title="PNG Image" border="0" alt=".png" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=125" target="_blank" title="">Nano_Buzzer.png</a> (Größe: 194,77 KB / Downloads: 1)
<!-- end: postbit_attachments_attachment --><br />
<br />
<br />
<div class="spoiler">
		<div class="spoiler_title"><span class="spoiler_button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[1].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</span>Sourcecode:</div>
		<div class="spoiler_content" style="display: none;">
<br />
<div class="codeblock"><div class="title">Code:</div><div class="body" dir="ltr"><code>#include &lt;TimerOne.h&gt;<br />
<br />
const byte BUZZER_PIN = 5;        // den aktiven Buzzer mit Plus an den Pin D5 vom Arduino Nano und Minus an GND <br />
<br />
// Struktur fuer den Buzzer<br />
struct tBuzzer {<br />
  bool state = 0;                 // Status des Buzzers (1 = ein, 0 = aus)<br />
  uint8_t tones = 0;              // Anzahl der abzuspielenden Toene<br />
  uint16_t times[2] = {0, 0};     // Array mit [0] = Pausenzeit, [1] = Pulszeit<br />
  uint32_t ticks = 0;             // zum merken der Millisekunden<br />
};<br />
<br />
volatile struct tBuzzer buzzer;   // Buzzer-Struktur als volatile, weil sie in einer Interrupt-Funktion verwendet wird<br />
<br />
<br />
// Interrupt-Routine zum reagieren auf die Anzahl und die Puls-/Pausenzeit des Buzzers<br />
void BeepISR() {<br />
  // wenn noch Toene abgespielt werden muessen und die Puls- bzw. Pausenzeit abgelaufen ist, dann...<br />
  if (buzzer.tones &amp;&amp; (millis() - buzzer.ticks &gt; buzzer.times[buzzer.state])) {<br />
    buzzer.state ^= 1;                      // den Status mit "XOR 1" invertieren<br />
    if (!buzzer.state) buzzer.tones--;      // wenn Status = 0, dann die Anzahl um eins verringern<br />
    digitalWrite(BUZZER_PIN, buzzer.state); // den Buzzer ein-/ausschalten (je nach Status)<br />
    buzzer.ticks = millis();                // die Millisekunden merken<br />
  }<br />
}<br />
<br />
// Funktion, um die Ausgabe der Toene zu starten<br />
// Parameter: Anzahl der Toene 0...255, Pulsdauer in ms 0...65535 [, Pausendauer in ms 0...65535]<br />
void Beep(const uint8_t tones, const uint16_t pulse, const uint16_t pause = 0) {<br />
  uint8_t oldSREG = SREG;        // Interrupt-Register merken<br />
  cli();                         // Interrupts verhindern<br />
  if (!buzzer.tones) {           // wenn die bisherigen Toene abgespielt wurden<br />
    buzzer.tones = tones;        // die Parameter in die Struktur uebernehmen<br />
    buzzer.times[0] = pause;<br />
    buzzer.times[1] = pulse;<br />
    buzzer.ticks = millis();     // die Millisekunden merken<br />
  }<br />
  SREG = oldSREG;                // Interrupt-Register wieder herstellen<br />
}<br />
<br />
void setup() {<br />
  digitalWrite(BUZZER_PIN, LOW);   // sicherstellen, dass der Pin auf LOW liegt<br />
  pinMode(BUZZER_PIN, OUTPUT);     // den Pin fuer den Buzzer als Ausgang schalten<br />
  Timer1.initialize(1000);         // Timer-Interrupt (alle 1000us = 1ms) initialisieren<br />
  Timer1.attachInterrupt(BeepISR); // zum steuern der Buzzerausgabe<br />
<br />
  // Beispiele:<br />
  Beep(5, 25, 500);                // fuenf Toene ausgeben (Puls: 25ms, Pause: 500ms)<br />
  delay(4000);                     // als Beispiel, dass der Nano gerade etwas anderes tut (die Beeps sind interruptgesteuert)<br />
<br />
  Beep(2, 300, 150);               // zwei Toene ausgeben (Puls: 300ms, Pause: 150ms)<br />
  delay(4000);                     // als Beispiel, dass der Nano gerade etwas anderes tut (die Beeps sind interruptgesteuert)<br />
<br />
  Beep(1, 1000);                   // ein Ton ausgeben (Puls: 1000ms, Pause: 0ms, kann weggelassen werden)<br />
  delay(4000);                     // als Beispiel, dass der Nano gerade etwas anderes tut (die Beeps sind interruptgesteuert)<br />
}<br />
<br />
void loop() {<br />
}</code></div></div><br />
</div>
	</div>
<br />
Im Anhang (ZIP-Archiv) befindet sich der Sourcecode als Arduino-Sketch.<br /><!-- start: postbit_attachments_attachment -->
<br /><!-- start: attachment_icon -->
<img src="https://forum.technik-hobby.de/images/attachtypes/zip.png" title="ZIP File" border="0" alt=".zip" />
<!-- end: attachment_icon -->&nbsp;&nbsp;<a href="attachment.php?aid=126" target="_blank" title="">Buzzer-ISR.zip</a> (Größe: 1,38 KB / Downloads: 1)
<!-- end: postbit_attachments_attachment -->]]></content:encoded>
		</item>
		<item>
			<title><![CDATA[Berechnung der Wochennummer]]></title>
			<link>https://forum.technik-hobby.de/thread-15.html</link>
			<pubDate>Tue, 09 May 2017 14:22:21 +0200</pubDate>
			<dc:creator><![CDATA[<a href="https://forum.technik-hobby.de/member.php?action=profile&uid=2">Gorathan</a>]]></dc:creator>
			<guid isPermaLink="false">https://forum.technik-hobby.de/thread-15.html</guid>
			<description><![CDATA[Um die Wochennummer zu berechnen, sind einige Funktionen nötig.<br />
Im Internet findet man zahlreiche Berechnungen, aber viele von denen liefern fehlerhafte Daten zurück und/oder berücksichtigen nicht die deutschen/europäischen Regeln zur Berechnung.<br />
Ich habe mal eine Berechnung auf Grundlage der ISO 8601 erstellt:<br />
<div class="spoiler">
		<div class="spoiler_title"><span class="spoiler_button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[1].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</span>Arduino-Quellcode:</div>
		<div class="spoiler_content" style="display: none;">
<br />
<br />
<br />
<pre class="line-numbers"><code class="language-cpp"><br />
<br />
/*  Daten mit Grenzwerten zum testen der Funktionen:<br />
 *  29.12.2014 = ist ein Montag und faellt bereits in die 1. Woche des naechsten Jahres<br />
 *  31.12.2015 = in dem Jahr gab es eine 53. Woche<br />
 *  31.12.2016 = Tag des Jahres wird mit 366 korrekt berechnet (Schaltjahr)<br />
 *  01.01.2017 = ist ein Sonntag und faellt noch in die 52. Woche des Vorjahres<br />
*/<br />
uint16_t year = 2014;<br />
uint8_t month = 12;<br />
uint8_t day = 29;<br />
const char WeekDays[][3] = {"Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"}; // Abkuerzungen der Wochentage<br />
<br />
void setup() {<br />
  Serial.begin(115200);<br />
  Serial.println(F("Berechnung nach ISO 8601"));<br />
  <br />
  Serial.print(F("Datum: "));<br />
  Serial.print(day);<br />
  Serial.print(".");<br />
  Serial.print(month);<br />
  Serial.print(".");<br />
  Serial.println(year);<br />
<br />
  uint8_t wd = GetWeekday(year, month, day);        // 1 = Mo, 2 = Di, 3 = Mi, 4 = Do, 5 = Fr, 6 = Sa, 7 = So<br />
  Serial.print(F("Wochentag: "));<br />
  Serial.println(WeekDays[wd - 1]);<br />
  <br />
  uint16_t doy = GetDayOfYear(year, month, day);    // den Tag des Jahres berechnen<br />
  Serial.print(F("Tag des Jahres: "));<br />
  Serial.println(doy);<br />
  <br />
  uint8_t WeekNr = GetWeekNumber(year, month, day); // die Wochennummer berechnen<br />
  Serial.print(F("Wochennummer: "));<br />
  Serial.println(WeekNr);<br />
<br />
  bool LeapYear = IsLeapYear(year);                 // berechnen, ob das Jahr ein Schaltjahr ist<br />
  Serial.print(F("Schaltjahr: "));<br />
  Serial.println(LeapYear ? F("Ja") : F("Nein"));<br />
}<br />
<br />
void loop() {<br />
<br />
}<br />
<br />
/***** Den Wochentag nach ISO 8601 (1 = Mo, 2 = Di, 3 = Mi, 4 = Do, 5 = Fr, 6 = Sa, 7 = So) berechnen *****/<br />
uint8_t GetWeekday(uint16_t y, uint8_t m, uint8_t d) {<br />
  static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};<br />
  y -= m &lt; 3;<br />
  uint8_t wd = (y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) % 7;<br />
  return (wd == 0 ? 7 : wd);<br />
}<br />
<br />
/***** Die Wochennummer nach ISO 8601 berechnen *****/<br />
uint8_t GetWeekNumber(uint16_t y, uint8_t m, uint8_t d) {<br />
  bool LeapYear;<br />
  uint16_t doy = GetDayOfYear(y, m, d);  // Anzahl der Tage im Jahr ermitteln<br />
  uint8_t wd = GetWeekday(y, m, d);      // Wochentag ermitteln<br />
  uint8_t wnr = (doy - wd + 7) / 7;      // die Wochennummer berechnen<br />
  switch (wnr) {<br />
    case 0:                              // wenn die Wochennummer Null ergibt, dann liegt der Tag am Anfang des Jahres (1. Sonderfall)<br />
      wd = GetWeekday(y - 1, 12, 31);    // den letzten Wochentag aus dem Vorjahr ermitteln<br />
      LeapYear = IsLeapYear(y - 1);      // ermitteln, ob es sich beim Vorjahr um ein Schaltjahr handelt<br />
      break;                             // und nach dem Switch weitermachen...<br />
    case 52:                             // wenn die Wochennummer 52 ergibt, dann liegt der Tag am Ende des Jahres (2. Sonderfall)<br />
      wd = GetWeekday(y, 12, 31);        // den letzten Wochentag aus diesem Jahr ermitteln<br />
      LeapYear = IsLeapYear(y);          // ermitteln, ob es sich bei diesem Jahr um ein Schaltjahr handelt<br />
      break;                             // und nach dem Switch weitermachen...<br />
    default:                             // in den anderen Faellen kann die Funktion<br />
      return wnr;                        // hier verlassen und die Wochennummer zurueckgegeben werden<br />
  }<br />
  if (wd &lt; 4) {                          // wenn der 31.12. vor dem Donnerstag liegt, dann...<br />
    wnr = 1;                             // ist das die erste Woche des Jahres<br />
  } else {                               // anderenfalls muss ermittelt werden, ob es eine 53. Woche gibt (3. Sonderfall)<br />
    /* wenn der letzte Wochentag auf einen Donnerstag oder,          */<br />
    /* in einem Schaltjahr, auf einen Donnerstag oder Freitag fällt, */<br />
    /* dann ist das die 53. Woche, ansonsten die 52. Woche.          */<br />
    wnr = ((wd == 4) || (LeapYear &amp;&amp; wd == 5)) ? 53 : 52;<br />
  }<br />
  return wnr;<br />
}<br />
<br />
/***** die Anzahl der Tage (Tag des Jahres) berechnen *****/<br />
uint16_t GetDayOfYear(uint16_t y, uint8_t m, uint8_t d) {<br />
  static const uint16_t mdays[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};<br />
  return d + mdays[m - 1] + (m &gt;= 2 &amp;&amp; IsLeapYear(y));<br />
}<br />
<br />
/***** Testen, ob das Jahr ein Schaltjahr ist *****/<br />
bool IsLeapYear(uint16_t y) {<br />
  return  !(y % 4) &amp;&amp; ((y % 100) || !(y % 400)); // Schaltjahrberechnung (true = Schaltjahr, false = kein Schaltjahr)<br />
}<br />
</code></pre>
<br />
<br />
<br />
</div>
	</div>
So funktioniert das auf dem Arduino problemlos.<br />
Ich habe das Programm umfangreich kommentiert, sodass die Funktionen verständlich sind.]]></description>
			<content:encoded><![CDATA[Um die Wochennummer zu berechnen, sind einige Funktionen nötig.<br />
Im Internet findet man zahlreiche Berechnungen, aber viele von denen liefern fehlerhafte Daten zurück und/oder berücksichtigen nicht die deutschen/europäischen Regeln zur Berechnung.<br />
Ich habe mal eine Berechnung auf Grundlage der ISO 8601 erstellt:<br />
<div class="spoiler">
		<div class="spoiler_title"><span class="spoiler_button float_right" onclick="javascript: if(parentNode.parentNode.getElementsByTagName('div')[1].style.display == 'block'){ parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'none'; this.innerHTML='Show Content'; } else { parentNode.parentNode.getElementsByTagName('div')[1].style.display = 'block'; this.innerHTML='Hide Content'; }">Show Content</span>Arduino-Quellcode:</div>
		<div class="spoiler_content" style="display: none;">
<br />
<br />
<br />
<pre class="line-numbers"><code class="language-cpp"><br />
<br />
/*  Daten mit Grenzwerten zum testen der Funktionen:<br />
 *  29.12.2014 = ist ein Montag und faellt bereits in die 1. Woche des naechsten Jahres<br />
 *  31.12.2015 = in dem Jahr gab es eine 53. Woche<br />
 *  31.12.2016 = Tag des Jahres wird mit 366 korrekt berechnet (Schaltjahr)<br />
 *  01.01.2017 = ist ein Sonntag und faellt noch in die 52. Woche des Vorjahres<br />
*/<br />
uint16_t year = 2014;<br />
uint8_t month = 12;<br />
uint8_t day = 29;<br />
const char WeekDays[][3] = {"Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"}; // Abkuerzungen der Wochentage<br />
<br />
void setup() {<br />
  Serial.begin(115200);<br />
  Serial.println(F("Berechnung nach ISO 8601"));<br />
  <br />
  Serial.print(F("Datum: "));<br />
  Serial.print(day);<br />
  Serial.print(".");<br />
  Serial.print(month);<br />
  Serial.print(".");<br />
  Serial.println(year);<br />
<br />
  uint8_t wd = GetWeekday(year, month, day);        // 1 = Mo, 2 = Di, 3 = Mi, 4 = Do, 5 = Fr, 6 = Sa, 7 = So<br />
  Serial.print(F("Wochentag: "));<br />
  Serial.println(WeekDays[wd - 1]);<br />
  <br />
  uint16_t doy = GetDayOfYear(year, month, day);    // den Tag des Jahres berechnen<br />
  Serial.print(F("Tag des Jahres: "));<br />
  Serial.println(doy);<br />
  <br />
  uint8_t WeekNr = GetWeekNumber(year, month, day); // die Wochennummer berechnen<br />
  Serial.print(F("Wochennummer: "));<br />
  Serial.println(WeekNr);<br />
<br />
  bool LeapYear = IsLeapYear(year);                 // berechnen, ob das Jahr ein Schaltjahr ist<br />
  Serial.print(F("Schaltjahr: "));<br />
  Serial.println(LeapYear ? F("Ja") : F("Nein"));<br />
}<br />
<br />
void loop() {<br />
<br />
}<br />
<br />
/***** Den Wochentag nach ISO 8601 (1 = Mo, 2 = Di, 3 = Mi, 4 = Do, 5 = Fr, 6 = Sa, 7 = So) berechnen *****/<br />
uint8_t GetWeekday(uint16_t y, uint8_t m, uint8_t d) {<br />
  static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};<br />
  y -= m &lt; 3;<br />
  uint8_t wd = (y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) % 7;<br />
  return (wd == 0 ? 7 : wd);<br />
}<br />
<br />
/***** Die Wochennummer nach ISO 8601 berechnen *****/<br />
uint8_t GetWeekNumber(uint16_t y, uint8_t m, uint8_t d) {<br />
  bool LeapYear;<br />
  uint16_t doy = GetDayOfYear(y, m, d);  // Anzahl der Tage im Jahr ermitteln<br />
  uint8_t wd = GetWeekday(y, m, d);      // Wochentag ermitteln<br />
  uint8_t wnr = (doy - wd + 7) / 7;      // die Wochennummer berechnen<br />
  switch (wnr) {<br />
    case 0:                              // wenn die Wochennummer Null ergibt, dann liegt der Tag am Anfang des Jahres (1. Sonderfall)<br />
      wd = GetWeekday(y - 1, 12, 31);    // den letzten Wochentag aus dem Vorjahr ermitteln<br />
      LeapYear = IsLeapYear(y - 1);      // ermitteln, ob es sich beim Vorjahr um ein Schaltjahr handelt<br />
      break;                             // und nach dem Switch weitermachen...<br />
    case 52:                             // wenn die Wochennummer 52 ergibt, dann liegt der Tag am Ende des Jahres (2. Sonderfall)<br />
      wd = GetWeekday(y, 12, 31);        // den letzten Wochentag aus diesem Jahr ermitteln<br />
      LeapYear = IsLeapYear(y);          // ermitteln, ob es sich bei diesem Jahr um ein Schaltjahr handelt<br />
      break;                             // und nach dem Switch weitermachen...<br />
    default:                             // in den anderen Faellen kann die Funktion<br />
      return wnr;                        // hier verlassen und die Wochennummer zurueckgegeben werden<br />
  }<br />
  if (wd &lt; 4) {                          // wenn der 31.12. vor dem Donnerstag liegt, dann...<br />
    wnr = 1;                             // ist das die erste Woche des Jahres<br />
  } else {                               // anderenfalls muss ermittelt werden, ob es eine 53. Woche gibt (3. Sonderfall)<br />
    /* wenn der letzte Wochentag auf einen Donnerstag oder,          */<br />
    /* in einem Schaltjahr, auf einen Donnerstag oder Freitag fällt, */<br />
    /* dann ist das die 53. Woche, ansonsten die 52. Woche.          */<br />
    wnr = ((wd == 4) || (LeapYear &amp;&amp; wd == 5)) ? 53 : 52;<br />
  }<br />
  return wnr;<br />
}<br />
<br />
/***** die Anzahl der Tage (Tag des Jahres) berechnen *****/<br />
uint16_t GetDayOfYear(uint16_t y, uint8_t m, uint8_t d) {<br />
  static const uint16_t mdays[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};<br />
  return d + mdays[m - 1] + (m &gt;= 2 &amp;&amp; IsLeapYear(y));<br />
}<br />
<br />
/***** Testen, ob das Jahr ein Schaltjahr ist *****/<br />
bool IsLeapYear(uint16_t y) {<br />
  return  !(y % 4) &amp;&amp; ((y % 100) || !(y % 400)); // Schaltjahrberechnung (true = Schaltjahr, false = kein Schaltjahr)<br />
}<br />
</code></pre>
<br />
<br />
<br />
</div>
	</div>
So funktioniert das auf dem Arduino problemlos.<br />
Ich habe das Programm umfangreich kommentiert, sodass die Funktionen verständlich sind.]]></content:encoded>
		</item>
	</channel>
</rss>