// Deklarationen
// Timer DS3231 einrichten
#include "Wire.h"
#define DS3231_ADDRESSE 0x68
// LCD Display I2C 4 Zeilen je 20 Zeichen einrichten
#include <LiquidCrystal_I2C.h> // LCD Display
// Displayadresse ist 0x27 oder 0x3F
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
// Baudrate fuer Serial Schnittstelle
const int baudSerial = 9600;
//-----------------------Taster01----------------------------------------
// const byte ist im Programm Constant und byte ist fuer Werte 0-255
const byte Taster01 = 15; // Pin 15 wird Constant als Taster01 bezeichnet
byte Tasterstatus01 = 0; // Zum Abfragen des Tatsenpins
byte Tastenmerker01 = 0; // Zum Merken des aktuellen Tatsenstatus
unsigned long Sekundenablauf01 = 0; // Tastenabfrage von Taster02 300ms aussetzen
const unsigned long Pausezeit01 = 200;
//-----------------------Taster02---------------------------------------
const byte Taster02 = 16; // Pin16 wird Constant als Taster02 bezeichnet
byte Tasterstatus02 = 0;
byte Tastenmerker02 = 0;
unsigned long Sekundenablauf02 = 0; // Tastenabfrage von Taster02 300ms aussetzen
const unsigned long Pausezeit02 = 200;
//-----------------------Analoger Eingang A0------------------------------
const byte ANALOG_PIN = A0; // Hier wird der Name fuer den Steuereingang festgelegt
int a0 = 0; // Der Speicher fuer den Analogwert
int a0alt = 0; // Der Speicher fuer den alten Analogwert
//-----------------------PWM Pins festlegen am Mega-----------------------
/* Timer und zugehörige Pinns:
timer 0 (controls pin 13, 4);
timer 1 (controls pin 12, 11);
timer 2 (controls pin 10, 9);
timer 3 (controls pin 5, 3, 2);
timer 4 (controls pin 8, 7, 6);
Wenn ich den Pin10 als PWM_PIN3 deklariere, dann bekomme ich Probleme bei der Tonausgabe
auf Pin 17. Also wenn ich Pin 10 anstelle von Pin 9 als PWM Ausgang benutze, dann wird
die Tonfrequenz von Pin17 liniar mit dem eingestellten PWM Signal verändert. Wenn ich
wie jetzt im Programm für Pin10 den Pin9 verwende ist da kein Problem mehr. Der Pin10
ist genauso wie Pin9 nicht beschalten. Was ja bei einem OUTPUT Pin kein Problem ist.
*/
int PWM_PIN2 = 13; // PWM Ausgabepin 13 festlegen auf 490Hz, Timer0
int PWM_PIN1 = 11; // PWM Ausgabepin 11 festlegen auf 31300Hz, Timer1
int PWM_PIN3 = 9; // PWM Ausgabepin 9 festlegen auf 980Hz, Timer2
//-----------------------AusgangPIN31-------------------------------------
const byte Ausgang01 = 6; // Pin 31 ist für das Relais01
byte Ausgangsstatus01 = 0;
unsigned long Sekundenablauf03 = 0; // Ausgang Schaltzeit auf 3000ms 3 Sekunden einrichten
const unsigned long Pausezeit03 = 3000;
//-----------------------AusgangPIN32-------------------------------------
const byte Ausgang02 = 7; // Pin 32 ist für das Relais02
byte Ausgangsstatus02 = 0;
unsigned long Sekundenablauf04 = 0; // Ausgang Schaltzeit auf 1000ms 1 Sekunde einrichten
const unsigned long Pausezeit04 = 1000;
//-------------------------Tonausgabe PIN 17-----------------------------
const byte tonPin = 17;
const int frequenz = 1000;
unsigned long tonZeit = 100;
//-------------------------Programmdurchlauf in Millis messen------------
unsigned long Startzeit = 0;
unsigned long Stoppzeit = 0;
//-------------------------Kontrolle ob eine Minute abgelaufen-----------
unsigned long minutenablauf = 0;
unsigned long eineminute = 60000;
//=============================================================================================================
void setup() {
//I2C für DS3231 aktivieren
Wire.begin();
// Wenn die I2C Leitung länger ist, kann man den Tackt für den I2C Bus langsammer machen!!
Wire.setClock(32000);
// Serial Schnittstelle starten
Serial.begin(baudSerial);
// Wenn die Zeit gestellt werden muß
// aktuelle Zeit sek min std wt tag monat jahr
// einstellenDS3231zeit(00, 22, 22, 2, 16, 06, 20);
// ----------PWM Tackt für Pin 11&12 auf 31300Hz ändern---------------
TCCR1B = TCCR1B & 0b11111000 | 0x01;
//-----------LCD Display Start----------------------------------------
lcd.begin(20, 4);
lcd.backlight();
lcd.clear();
//-----------Display Maske erstellen----------------------------------
zeigeZeit(); // Zeit ausgeben // Zeile 1
lcd.setCursor (0, 3); // Zeile 4
lcd.print (F("PWM Wert "));
lcd.setCursor (0, 1); // Zeile 2
lcd.print (F("Taste 01 0"));
lcd.setCursor (15, 1);
lcd.print (F("02 0"));
lcd.setCursor (0, 2); // Zeile 3
lcd.print (F("Ausg. 01 0"));
lcd.setCursor (15, 2);
lcd.print (F("02 0"));
//-----------Taster einrichten----------------------------------------
pinMode(Taster01, INPUT_PULLUP); // Pin 15 fuer Taster01 wird intern auf plus gelegt. Mit GND ueber Taste aktivieren
pinMode(Taster02, INPUT_PULLUP); // Pin 16 fuer Taster02
//-----------Ausgang einrichten---------------------------------------
pinMode(Ausgang01, OUTPUT); // Pin 6 (Ausgang01) ist als Ausgang aktiviert
pinMode(Ausgang02, OUTPUT); // Pin 7 (Ausgang02) ist als Ausgang aktiviert
//-----------Input und Output Pin für PWM bestimmen-------------------
pinMode(ANALOG_PIN, INPUT); // Eingang für Poti A0
pinMode(PWM_PIN1, OUTPUT); // Pin 11
pinMode(PWM_PIN2, OUTPUT); // Pin 13
pinMode(PWM_PIN3, OUTPUT); // Pin 9
//--------------Ton Ausgabepin einrichten----------------------------
pinMode(tonPin, OUTPUT); // Pin 17
//--------------Startzeit für Zeitausgabe----------------------------
minutenablauf = millis();
}
//=============================================================================================================
void loop() {
Startzeit = micros();
//-----------Zeit ausgeben von DS3231-----------------------------------
if (millis() - minutenablauf >= eineminute) { // Eine Minute abgelaufen?
zeigeZeit(); // Zeit ausgeben
}
//----------Analogen Eingang auslesen-----------------------------------
a0 = analogRead (ANALOG_PIN);
a0 = map(a0, 0, 1023, 25, 254);
if (a0 != a0alt) {
//------Potiwert auf PWM Ausgang ausgeben-----------------------------
analogWrite (PWM_PIN1, a0); // Analogwert Ausgabe an PWM Pin.11
analogWrite (PWM_PIN2, a0); // Analogwert Ausgabe an PWM Pin.13
analogWrite (PWM_PIN3, a0); // Analogwert Ausgabe an PWM Pin.9
lcd.setCursor (11, 3); // Zeile 4
lcd.print (F(" "));
lcd.setCursor (11, 3);
lcd.print (a0);
a0alt = a0;
}
//-----------Taster01 abfragen--------------------------------------------
if (millis() - Sekundenablauf01 >= Pausezeit01) { // 200msec abgelaufen?
Tasterstatus01 = digitalRead(Taster01); // Pin von Taster01 abfragen
if (Tasterstatus01 == LOW) { // Ist Taster01 gedrueckt?
Tastenmerker01 = !Tastenmerker01; // Merken dass Taster01 gedrueckt wurde
lcd.setCursor (10, 1); // Zeile 2
lcd.print (Tastenmerker01);
Sekundenablauf01 = millis();
tone(tonPin, frequenz, tonZeit);
}
}
//-----------Taster02 abfragen--------------------------------------------
if (millis() - Sekundenablauf02 >= Pausezeit02) { // 200msec abgelaufen?
Tasterstatus02 = digitalRead(Taster02); // Pin von Taster02 abfragen
if (Tasterstatus02 == LOW) { // Ist Taster02 gedrueckt?
Tastenmerker02 = !Tastenmerker02; // Merken dass Taster02 gedrueckt wurde
lcd.setCursor (19, 1); // Zeile 2
lcd.print (Tastenmerker02);
Sekundenablauf02 = millis();
tone(tonPin, frequenz, tonZeit);
}
}
//-------------Ausgang01 schalten-------------------------------------------
// Alle 3 Sekunden 2100 Microsekunden
if (millis() - Sekundenablauf03 >= Pausezeit03) { // 3000msec abgelaufen?
Ausgangsstatus01 = ! Ausgangsstatus01; // Status wechseln
digitalWrite (Ausgang01, Ausgangsstatus01); // Ausgang01 Relais umschalten
lcd.setCursor (10, 2); // Zeile 3
lcd.print (Ausgangsstatus01);
Sekundenablauf03 = millis();
}
//-------------Ausgang02 schalten-------------------------------------------
// Jede Sekunde 2100 Microsekunden
if (millis() - Sekundenablauf04 >= Pausezeit04) { // 1000msec abgelaufen?
Ausgangsstatus02 = ! Ausgangsstatus02; // Status wechseln
digitalWrite (Ausgang02, Ausgangsstatus02); // Ausgang02 Relais umschalten
lcd.setCursor (19, 2); // Zeile 3
lcd.print (Ausgangsstatus02);
Sekundenablauf04 = millis();
}
// Zeitmessung für einen Programm Durchlauf und Ausgabe des Wertes
// Mit Serial.print() sieht man die Laufzeiten des Programmes in MicroSekunden
Stoppzeit = micros();
//Serial.print("Laufzeit= ");
//Serial.println(Stoppzeit - Startzeit);
}
//=======================Loop Ende==============================================================================
//---------------Erweiterung für die DS3132---------------------------------------------------------------------
void einstellenDS3231zeit(byte sekunde, byte minute, byte stunde, byte wochentag, byte tag, byte monat, byte jahr)
{
// Datum und Uhrzeit einstellen
Wire.beginTransmission(DS3231_ADDRESSE);
Wire.write(0);
Wire.write(decToBcd(sekunde)); // Sekunden einstellen
Wire.write(decToBcd(minute)); // Minuten einstellen
Wire.write(decToBcd(stunde));
Wire.write(decToBcd(wochentag)); // 1=Sonntag ... 7=Samstag
Wire.write(decToBcd(tag));
Wire.write(decToBcd(monat));
Wire.write(decToBcd(jahr)); // 0...99
Wire.endTransmission();
}
//--------------------------Die Zeit auslesen------------------------------------------------------------------
// jede Minute etwa 5000 Microsekunden
void leseDS3231zeit(byte *sekunde, byte *minute, byte *stunde, byte *wochentag, byte *tag, byte *monat, byte *jahr)
{
Wire.beginTransmission(DS3231_ADDRESSE);
Wire.write(0); // DS3231 Register zu 00h
Wire.endTransmission();
Wire.requestFrom(DS3231_ADDRESSE, 7); // 7 Byte Daten vom DS3231 holen
*sekunde = bcdToDec(Wire.read() & 0x7f);
*minute = bcdToDec(Wire.read());
*stunde = bcdToDec(Wire.read() & 0x3f);
*wochentag = bcdToDec(Wire.read());
*tag = bcdToDec(Wire.read());
*monat = bcdToDec(Wire.read());
*jahr = bcdToDec(Wire.read());
}
//---------------------------Die Zeit anzeigen----------------------------------------------------------------
// jede Minute etwa 15000 Microsekunden
void zeigeZeit() {
byte sekunde, minute, stunde, wochentag, tag, monat, jahr, minuteAlt;
leseDS3231zeit(&sekunde, &minute, &stunde, &wochentag, &tag, &monat, &jahr); // Daten vom DS3231 holen
if ((minute > minuteAlt) || (minute == 0)) {
switch (wochentag) {
case 1:
lcd.setCursor(0, 0);
lcd.print(F("Mo "));
break;
case 2:
lcd.setCursor(0, 0);
lcd.print(F("Di "));
break;
case 3:
lcd.setCursor(0, 0);
lcd.print(F("Mi "));
break;
case 4:
lcd.setCursor(0, 0);
lcd.print(F("Do "));
break;
case 5:
lcd.setCursor(0, 0);
lcd.print(F("Fr "));
break;
case 6:
lcd.setCursor(0, 0);
lcd.print(F("Sa "));
break;
case 7:
lcd.setCursor(0, 0);
lcd.print(F("So "));
break;
default:
break;
}
if (tag < 10) {
lcd.print(F("0"));
}
lcd.print(tag); // ausgeben T.M.J H:M:S
lcd.print(F("."));
if (monat < 10) {
lcd.print(F("0"));
}
lcd.print(monat);
lcd.print(F("."));
lcd.print(jahr);
lcd.print(F(" um "));
if (stunde < 10) {
lcd.print(F("0"));
}
lcd.print(stunde, DEC); // byte in Dezimal zur Ausgabe
lcd.print(F(":"));
if (minute < 10) {
lcd.print("0");
}
lcd.print(minute, DEC);
minuteAlt = minute;
// Bestimmen wann wieder eine Minute um
minutenablauf = millis();
eineminute = (60 - sekunde) * 1000UL;
}
}
byte decToBcd(byte val) {
// Dezimal Zahl zu binary coded decimal (BCD) umwandeln
return ((val / 10 * 16) + (val % 10));
}
byte bcdToDec(byte val) {
// BCD (binary coded decimal) in Dezimal Zahl umwandeln
return ((val / 16 * 10) + (val % 16));
}