Johannes schrieb:> (DS1307) auf meinem LCD anzuzeigen, stellt sich jetzt das Problem, dass> ich nicht weiß wie ich beim Dimmen die delay Funktion umgehe weil dann> ja sonst meine Uhr während des Dimmens stehen bleibt.
Das hast du völlig richtig erkannt, dass dein delay das Problem ist.
Aber. Im Grunde ist das ja kein Problem. Du musst von deiner
for-Schleife weg!
Denn:
Du weisst, dass du um 7:00 einen Dimmgrad von 0 haben sollst.
Liegt die Uhrzeit zwischen 7:00 und 7:01 dann brauchst du einen Dimmgrad
von 1%.
Liegt die Uhrzeit zwischen 7:01 und 7:02, dann brauchst du einen
Dimmgrad von 2%
etc. etc.
D.h. anstelle dass du in einer for-schleife durchdimmst, machst du
(Programmskizze)
void loop()
{
if( Uhrzeit < 7 Uhr früh )
Dimmgrad = 0
else if( Urzeit < 7:01 früh )
Dimmgrad = 1
else if( Uhrzeit < 7:02 früh
Dimmgard = 2
...
}
d.h. du siehst dir einfach bei jedem Aufruf von loop die aktuelle
Uhrzeit an und leitest daraus her, wie der Dimmgrad zu dieser Uhrzeit
sein muss. Da loop immer wieder erneut aufgerufen wird, verändert sich
auch die dann jeweils festgestellte aktuelle Uhrzeit.
Hinweis: Du wirst natürlich nicht da jetzt 100 if-Abfragen machen,
sondern dir überlegen, wie du aus der Uhrzeit den Dimmgrad ERRECHNEN
kannst. Aber das Prinzip ist dasselbe: Die momentan aktuelle Uhrzeit
verrät dir, wie die LED genau zu diesem Zeitpunkt gedimmt sein muss. Du
musst dir nur überlegen, wie du das rechnen musst. Also: Papier und
Bleistift raus und mal ein wenig rumgerechnet. Wenn du die Vorgabe hast,
dass du einen Zahlenwert innerhalb von 30 Minuten von 0 auf 100 bringen
sollst und ich frage dich, welcher Wert 11 Minuten und 43 Sekunden nach
Beginn der ganzen Aktion dann vorliegt, wie berechnest du das?
> Das zweite ist dass ich nicht weiß wie ich den dann hochgedimmten> ausgang dann angeschalten lasse obwohl er ja jede sekunde den loop> wiederholt und die Zeit abruft.
Das Problem erledigt sich dann ganz von alleine :-)
(und ps: die delays schmeisst du alle raus. Versprochen?)
Karl Heinz Buchegger schrieb:> Hinweis: Du wirst natürlich nicht da jetzt 100 if-Abfragen machen,> sondern dir überlegen, wie du aus der Uhrzeit den Dimmgrad ERRECHNEN> kannst. Aber das Prinzip ist dasselbe: Die momentan aktuelle Uhrzeit> verrät dir, wie die LED genau zu diesem Zeitpunkt gedimmt sein muss. Du> musst dir nur überlegen, wie du das rechnen musst. Also: Papier und> Bleistift raus und mal ein wenig rumgerechnet. Wenn du die Vorgabe hast,> dass du einen Zahlenwert innerhalb von 30 Minuten von 0 auf 100 bringen> sollst und ich frage dich, welcher Wert 11 Minuten und 43 Sekunden nach> Beginn der ganzen Aktion dann vorliegt, wie berechnest du das?
Und noch ein Hinweis:
Die ganze Rechnung vereinfacht sich extrem, wenn du nicht mit einem
bunten Mix aus Minuten und Sekunden an die Sache rangehst, sondern
zuerst mal alles auf einen kleinsten gemeinsammen Nenner bringst. zb
Sekunden.
30 Minuten sind 1800 Sekunden und 11 Minuten 43 sind 703 Sekunden.
Wenn also nach 1800 Sekunden ein bei 0 beginnender Wert 1800 erreicht
haben soll, welchen Wert hast du dann nach 703 Sekunden?
-> Dreisatz.
OK super tipp. 100Stufen*703sek/1800sek = 39 Stufen
aber wie bekomm ich das ins programm weil das ja nur immer als uhrzeit
10sekunden ausgiebt dann wieder von vorne anfängt?
Johannes schrieb:> OK super tipp. 100Stufen*703sek/1800sek = 39 Stufen>> aber wie bekomm ich das ins programm weil das ja nur immer als uhrzeit> 10sekunden ausgiebt dann wieder von vorne anfängt?
Ja, macht ja nichts.
Du hast eine andere Uhrzeit. Dann macht eben der µC mit dieser neuen
Uhrzeit wieder dieselbe Berechnung, nur mit anderen Zahlenwerten. Dazu
hat man ja Variablen, in denen diese Zahlenwerte stehen. Damit man
a = b * 300 / c;
schreiben kann und je nachdem, welche WErte konkret in b bzw. c stehen,
kommt dann ein anderes Ergebnis raus.
1
voidloop(){
2
3
intdatum[7];
4
5
getDateDs1307(datum);// Datum und Uhrzeit aus DS1307 holen
Johannes schrieb:> Danke sehr für die geniale hilfe komm mir gerade vor wie ein depp aber> bei mir kommen nur Fehlermeldungen :(
Dann lies die Fehlermeldungen und behebe die Ursachen. Ein Fehler nach
dem anderen. Fang bei der ersten Fehlermeldung an.
Ich tippe hier die Programme direkt ein. D.h. das kann schon sein, dass
ich den einen oder anderen Tippfehler (und sei es nur eine
Gross/Kleinschreibung) drinnen habe.
Das Ziel ist ja auch nicht, dass ich dir ein fertiges Programm liefere,
dass du nur auf deinen µC brennen musst. Das Ziel ist, dass du verstehst
wie und warum ich bestimmte Dinge tue und da das Prinzip verstehen und
anwenden kannst. Und manchmal ist es nun mal einfacher, dieses Prinzip
mit Code zu verdeutlichen anstelle das ich mir da den Mund fusselig
rede.
(und deine Ausgabe war ja wirklich nicht sauber programmiert. Da gibt es
einfachere Methoden, auch wenn die ein wenig Resourcen verbrauchen. Aber
wer seinen µC 1 Sekunde lang Däumchen drehen lässt, kann es sich auch
leisten den Komfort von sprintf in Anspruch zu nehmen)
ja schon klar aber trotzdem danke für deine Hilfe. ja sauber
programmieren ist so ne sache :) Steh ja noch ganz am Anfang hab davor
noch nie einen Controller programmiert
So hab jetzt alles fast am laufen und auch die Formel. Allerdings
berechnet er die Lichtstufe falsch aber warum? Ich vermute das liegt
daran dass ich nur minuten berechne und da auch nachkommastellen
vorkommen
1
#include "LCD4Bit_mod.h"
2
#include "Wire.h"
3
4
int ledPin = 3; // LED Pin setzen
5
6
#define DS1307_I2C_ADDRESS 0x68 // I2C Adresse
7
8
char buffer[20] = ""; // Speicherbereich für Datenkonvertierung
Johannes schrieb:> So hab jetzt alles fast am laufen und auch die Formel. Allerdings> berechnet er die Lichtstufe falsch aber warum? Ich vermute
vermute nicht. Du hast ein LCD. Auf dem kann man sich Werte ausgeben
lassen, bzw. die Werte aus denen sie entstehen, wenn einem nicht klar
ist, wie ein Wert zustande kommt.
Was bedeutet 'falsch'? Kommt 384 raus oder -38. Oder was?
> das liegt> daran dass ich nur minuten berechne und da auch nachkommastellen> vorkommen
Nichts und niemand hindert dich daran, dass du hier
b = data[1] * 60;
auch noch die aktuellen Sekunden mit dazurechnest.
PS: Es ist immer gut, wenn man Variablen einen Namen gibt, der ihrer
Funktion entspricht, denn nur durch betrachten von
licht = a * b / c;
kann man nicht nachvollziehen, was du da eigentlich rechnest. Steht da
aber
licht = maximalLicht * DimmSekunde / GesamtDimmSekunden;
dann kann man das schon besser nachvollziehen. Und da im restlichen
Programm momenan sowieso die maximale Helligkeit mit 255 vorgegeben ist
und die Dauer der Dimmzeit mit 30 Minuten festgelegt ist, kannst du
gerne auch hier
licht = 255 * DimmSekunde / ( 60 * 30 );
schreiben, was das Lesen der Formel (momentan) vereinfacht.
PS:
Du wirst wohl hier
else if( datum[2] == 8 && datum[1] < 30 ) {
licht = a * b / c;
}
und hier
// von 6 bis halb 7 wird wieder eine Dimmstufe berechnet
// aber diesmal runterdimmen!
else if( datum[2] == 18 && datum[1] < 30 ) {
licht = a * b / c;
}
andere Formeln brauchen. Denn das eine mal wird das Licht ja heller
(dimmt also von dunkel nach hell), während es am Abend genau in die
andere Richtung dimmt: von hell nach dunkel. Das ist aber der genau
gegensätzliche Vorgang, daher kann das nicht dieselbe Formel sein.
Im übrigen ist es manchmal sehr erhellend, wenn man sich mal die
Berechnung rausgreift, Werte einsetzt und nachsieht, was da passiert
int b = datum[1]*60;
licht = 255 * b / 1800;
Sagen wir mal b sei ganz am Anfang. Die Minuten seien also noch 0.
0 mal 60 macht 0 255*0/1800 macht 0/1800 macht 0
Ein WErt in der Mitte. Sagen wir 15 MInuten
15 mal 60 macht 900 255*900/1800 macht 229500/1800
^
|
möööp, möööp, mööp
Overflow
Da ist ein Zwischenergebnis, welches den Bereich -32768 bis 32767
überschreitet.
Wenn du int rechnest, müssen auch alle Zwischenergebnisse im int Bereich
sein!
Ein long (32 Bit Ganzzahl) geht bis 2147483648. Da würden die 229500
nach reinpassen.
Was ist mit dem Extremwert von 30 Minuten?
30 mal 60 macht 1800. Das mal 255 macht 495000. Geht sich also auch noch
aus.
Also: macht man die Sekunden seit Beginn der Dimmung zu einem long
anstelle eines int, dann geht sich das aus
long SekundenSeitDimmstart = data[1] * 60 + data[0];
...
licht = 255 * SekundenSeitDimmstart / 1800;
Karl Heinz Buchegger schrieb:> licht = 255 * SekundenSeitDimmstart / 1800;
Dadurch dass SekundenSeitDimmstart ein long ist, erzwinge ich, dass die
Multiplikation mit 255 ebenfalls im Zahlenraum long gerechnet wird (also
als 32 Bit Multiplikation), und damit kann dann auch das Ergebnis keinen
Overflow mehr produzieren.
Johannes schrieb:> ja jetzt scheint es zu gehen :) Vielen Vielen Dank>> Mach mich jetzt noch ans runter dimmen.
Pst.
Runterdimmen ist im Prinzip der genau gleiche Vorgang gegengleich.
D.h. anstelle von 0 muss in deiner 'Formel' 255 rauskommen.
Anstelle von 1 muss 254 rauskommen
Anstelle von 2 muss 253 rauskommen
3 252
4 251
...
Merkst du was? Die erste und die zweite Zahl ergeben addiert wieder
die 255.
Wenn du also die Berechnung genau gleich wie im ersten Fall machst und
dieses Ergebnis dann von 255 abziehst, dann .....
Hallo habe auch ein problem mit meiner steuerung könnt ihr mir vll
helfen?
ich weis nicht wie ich meinem board den befehl geb das wenn es zb
8:00uhr ist das meine led auf pin 9 hochdimmt.
wäre voll nett wenn ihr mir helfen könnt.
MFG Andi
//
########################################################################
#####
// #
// # Scriptname : DS1307_Test.pde
// # Author : Peter Schmelzer, Oliver Kraus
// # Date : 2011-04-08
// # Editor : Lauren from DFRobot
// # Date : 30.12.2011
// # Description:
// # Test file for the DS1307new library. Assumes that you have a DS1307
// # connected to the I2C-Bus of your Arduino and that it has a battery
backup.
// # Update the library and sketch to compatible with IDE V1.0 and
earlier
// # Version : 1.0
//
########################################################################
#####
// *********************************************
// INCLUDE
// *********************************************
#include <Wire.h> // For some strange reasons,
Wire.h must be included here
#include <DS1307new.h>
// *********************************************
// DEFINE
// *********************************************
// *********************************************
// VARIABLES
// *********************************************
uint16_t startAddr = 0x0000; // Start address to store in the
NV-RAM
uint16_t lastAddr; // new address for storing in
NV-RAM
uint16_t TimeIsSet = 0xaa55; // Helper that time must not set
again
// *********************************************
// SETUP
// *********************************************
void setup()
{
pinMode(2, INPUT); // Test of the SQW pin, D2 =
INPUT
digitalWrite(2, HIGH); // Test of the SQW pin, D2 =
Pullup on
int ledPin = 9;
//INT-------------------------------------------------------------------
--------
pinMode(ledPin, OUTPUT);
//mode------------------------------------------------------------------
------
Serial.begin(9600);
/*
PLEASE NOTICE: WE HAVE MADE AN ADDRESS SHIFT FOR THE NV-RAM!!!
NV-RAM ADDRESS 0x08 HAS TO ADDRESSED WITH ADDRESS
0x00=0
TO AVOID OVERWRITING THE CLOCK REGISTERS IN CASE OF
ERRORS IN YOUR CODE. SO THE LAST ADDRESS IS 0x38=56!
*/
RTC.setRAM(0, (uint8_t *)&startAddr, sizeof(uint16_t));// Store
startAddr in NV-RAM address 0x08
/*
Uncomment the next 2 lines if you want to SET the clock
Comment them out if the clock is set.
DON'T ASK ME WHY: YOU MUST UPLOAD THE CODE TWICE TO LET HIM WORK
AFTER SETTING THE CLOCK ONCE.
*/
// TimeIsSet = 0xffff;
// RTC.setRAM(54, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
/*
Control the clock.
Clock will only be set if NV-RAM Address does not contain 0xaa.
DS1307 should have a battery backup.
*/
RTC.getRAM(54, (uint8_t *)&TimeIsSet, sizeof(uint16_t)); // 54
auf 55 stellen und datum + Zeiteinstellen
if (TimeIsSet != 0xaa55)
{
RTC.stopClock();
RTC.fillByYMD(2011,4,8);
RTC.fillByHMS(22,7,0);
RTC.setTime();
TimeIsSet = 0xaa55;
RTC.setRAM(54, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
RTC.startClock();
}
else
{
RTC.getTime();
}
/*
Control Register for SQW pin which can be used as an interrupt.
*/
RTC.ctrl = 0x00; // 0x00=disable SQW pin,
0x10=1Hz,
// 0x11=4096Hz, 0x12=8192Hz,
0x13=32768Hz
RTC.setCTRL();
Serial.println("DS1307 Testsketch");
Serial.println("Format is \"hh:mm:ss dd-mm-yyyy DDD\"");
uint8_t MESZ;
MESZ = RTC.isMEZSummerTime();
Serial.print("MEZ=0, MESZ=1 : ");
Serial.println(MESZ, DEC);
Serial.println();
}
// *********************************************
// MAIN (LOOP)
// *********************************************
void loop()
{
int ledPin = 9; // hier ist mein
Problem--------------------------------------------
pinMode(ledPin, OUTPUT);
RTC.getTime();
if (time)
{
digitalWrite(ledPin, HIGH);
}
if ( 20 > DN_H )
if (RTC.minute < 34)
{digitalWrite(ledPin, HIGH);
}
if (RTC.hour < 20)
{digitalWrite(ledPin, LOW);
}
//mode bis hier
------------------------------------------------------------------------
RTC.getTime();
if (RTC.hour < 10) // correct hour if necessary
{
Serial.print("0");
Serial.print(RTC.hour, DEC);
}
else
{
Serial.print(RTC.hour, DEC);
}
Serial.print(":");
if (RTC.minute < 10) // correct minute if necessary
{
Serial.print("0");
Serial.print(RTC.minute, DEC);
}
else
{
Serial.print(RTC.minute, DEC);
}
Serial.print(":");
if (RTC.second < 10) // correct second if necessary
{
Serial.print("0");
Serial.print(RTC.second, DEC);
}
else
{
Serial.print(RTC.second, DEC);
}
Serial.print(" ");
if (RTC.day < 10) // correct date if necessary
{
Serial.print("0");
Serial.print(RTC.day, DEC);
}
else
{
Serial.print(RTC.day, DEC);
}
Serial.print("-");
if (RTC.month < 10) // correct month if necessary
{
Serial.print("0");
Serial.print(RTC.month, DEC);
}
else
{
Serial.print(RTC.month, DEC);
}
Serial.print("-");
Serial.print(RTC.year, DEC); // Year need not to be changed
Serial.print(" ");
switch (RTC.dow) // Friendly printout the weekday
{
case 1:
Serial.print("MON");
break;
case 2:
Serial.print("TUE");
break;
case 3:
Serial.print("WED");
break;
case 4:
Serial.print("THU");
break;
case 5:
Serial.print("FRI");
break;
case 6:
Serial.print("SAT");
break;
case 7:
Serial.print("SUN");
break;
}
Serial.print(" seconds since 1.1.2000:");
Serial.print(RTC.time2000, DEC);
uint8_t MESZ = RTC.isMEZSummerTime();
Serial.print(" MEZ=0, MESZ=1 : ");
Serial.print(MESZ, DEC);
Serial.print(" - Address in NV-RAM is: ");
RTC.getRAM(0, (uint8_t *)&lastAddr, sizeof(uint16_t));
Serial.print(lastAddr, HEX);
lastAddr = lastAddr + 1; // we want to use it as
addresscounter for example
RTC.setRAM(0, (uint8_t *)&lastAddr, sizeof(uint16_t));
RTC.getRAM(54, (uint8_t *)&TimeIsSet, sizeof(uint16_t));
if (TimeIsSet == 0xaa55) // check if the clock was set or
not
{
Serial.println(" - Clock was set!");
}
else
{
Serial.println(" - Clock was NOT set!");
}
delay(1000); // wait a second
}