Wo ist der Fehler ??

Hallo !

Ich beschäftige mich seit wenigen Monaten nebenbei mit Arduino und versuche grade eine PWM Dimmsteuerung richtig zu programmieren. Mit meinem aktuellen Code läuft alles ungefähr einen Tag gut, danach bleiben alle PWM Ausgänge konstant auf 255 ( analogWrite) . Liegt es evtl. an den unsigned long ? nach einem Tag ( 24h = 1440min = 86.400sek = 86.400.000millis ) können die doch eigentlich nicht überlaufen sein... vielleicht weiss jemand woran es liegen kann ...

Danke schonmal denjenigen die helfen wollen O:-)

Bewegungsmelder_Flur_Fade.ino (6.44 KB)

Nein, daran kann es eigentlich nicht liegen, ein unsigned long läuft nach 49,5 Tagen über.

Grüße Uwe

Hallo,

bei Deinem Code blick ich leider nicht ganz durch. Ist aber allgemein schwierig fremden Code zu lesen.
Eine altbewährte Methode ist, alle in Frage kommenden Variablen ständig zwischendurch seriell ausgeben zu lassen. Dann sieht man wenn was nicht so läuft wie geplant. Vielleicht siehst Du schon am Anfang was schief läuft und mußt keinen ganzen Tag warten.

hm das problem ist das ich das licht brauche, also 12V dran haben muss. Wenn ich zusätzlich noch die USB Schnittstelle ranstöpsel habe ich schon die erfahrung machen müssen, das der Arduino Uno dann gen Elektrohimmel fliegt ;-)... gibts dafür eigentlich auch einen Trick ? Also vielleicht galvanisch getrennte Schnittstellen ?

12V über den PowerJack oder VIN anzuschließen ist eine Sache, die zwar geht, aber nicht optimal ist!
Galvanisch trennen ist nicht nötig.

a) ein selbst gebautes USB Kabel zu nutzten, bei dem nur die 2 Datenleitung sowie Ground aufgelegt sind.
b) orginal AVRISP von Atmel kaufen (http://www.reichelt.de/Programmer-Entwicklungstools/AT-AVR-ISP/3//index.html?ACTION=3&GROUPID=5100&ARTICLE=45040&SEARCH=atmel%20avr&OFFSET=500&WKID=0&SID=13VFEcIn8AAAIAAD3bDUg929eb7b533f5ef9470fe94bb45d2887e&CTYPE=0&MWSTFREE=0)
Dieser versorgt den Arduino nicht über den 5V Anschluss.
Alternativ einen Diamex AVRISP o.ä. bei dem man 5V/3V3 abschalten kann

Es gibt noch weit aus mehr möglichkeiten. Möglichkeit a sollte aber relativ einfach zu realisieren sein. Ich hab immer ein aufgeschnittenes USB Kabel rumliegen. Aussen herum ist an einer Stelle die Isolierung komplett entfernt. Denn Schirm habe ich zur Seite gelegt, sodass immer noch Verbindung steht. Die rote Leitung dann auftrennen und einen Schalter o.ä. zwischenbasteln.

Programmiere selbst nur über den Atmel mkii oder Diamex. Ich habe den aufgetrennt zum Messen der Stromaufnahme.

d3rm4rt3n:
vielleicht weiss jemand woran es liegen kann ...

Bei Fehlfunktionen kommen zwei Themenbereiche als Ursache in Frage:

  • Hardware-/Schaltungsfehler
  • Softwarefehler

Kannst Du das näher eingrenzen und zum Beispiel nach dem Auftreten des Fehlers feststellen, ob die Bewegungsmelder noch ihre Ausgänge schalten? Oder ob zwar die Bewegungsmelder ihre Ausgänge schalten, und nur das Licht nicht mehr angeht?

Zu Hardware-/Schaltungsfehler:
Was für Bewegungsmelder verwendest Du und weshalb initialisierst Du diese mit INPUT_PULLUP? Die billigen chinesischen PIR-Bewegungsmelder, die ich kenne, haben ganz schwache Push-Pull-Ausgänge - und die Ausgänge arbeiten mit 3.3V! Korrekterweise würde man diese an einem Arduino-Eingang anschließen, der als INPUT betrieben wird.

Zu Softwarefehler:
Ich mag mir Dein Programm gar nicht näher ansehen, so unstrukturiert wie das ist. Normalerweise würde man die Variablen in der benötigten Zimmeranzahl als Array oder struct-Array anlegen und die gesamte Programmlogik dann in einer for-Schleife so oft durchlaufen lassen wie man Zimmer hat. Also z.B. bei drei Zimmern dreimal eine Funktion mit der Zimmernummer als Parameter aufrufen.

Beim groben Überfliegen kann ich keine Fehler entdecken, die sich nach einem Tag bemerkbar machen könnten. Fehler durch einen falschen Umgang mit dem millis()-Timer treten normalerweise erst nach entweder knapp 25 Tagen (Überlauf in negatives Vorzeichen) oder nach knapp 50 Tagen (Überlauf des Zählers) auf.

Ja was du über die Programmstruktur sagst hört sich sehr gut an, wenn ich mal zeit finde werde ich mich auch mal mit sauberer programmierung beschäftigen.

-also ich kann schonmal ausschliessen das alle bewegungsmelder gleichzeitig,oder in kurzem zeitabstand, eine schaltfehlfunktion haben, da ich, sobald alle lichter gleichzeitig leuchten, auf den arduino reset knopf drücken kann und damit die lichter
wieder ausschalte. die spannung liegt dabei ja konstant an den bewegungsmeldern an.

-mit dem input pullup hast du wohl recht !! ich habe es bis jetzt so gelassen weil es, ehrlich gesagt, so funktioniert hat... werde ich heut abend mal ändern. aber merkwürdig das es so funktioniert hat, sobald die bewegungsmelder geschaltet haben, hatte ich eine 1 anliegen. einen abend war auch das phänomen das das licht wieder überall an war, und sobald ich in einen raum gegangen bin ging das licht aus :smiley: .

ja vielleicht ist es so das die PIR Bewegungsmelder im abgeschalteten zustand den eingang LEICHT gegen 0V ziehen aber nicht immer 100%ig und dadurch fehlsignale vom eingang gemessen werden. und über die zeit verliert dieses ziehen gegen 0v seine wirkung und die dinger sind konstant an. wenn das im zusammenspiel mit den eingängen wirkt und ich dann den arduino resette legt sich dieses phänomen wieder, obwohl VCC und GND noch angeschlossen sind. Vielleicht ist es so.... nur aber natürlich eine ganz grobe theorie. ich werde es weiter beobachten und die ergebnisse nochmal posten.

Beim groben Überfliegen kann ich keine Fehler entdecken, die sich nach einem Tag bemerkbar machen könnten

Dem muss ich mich leider zustimmen.

Allerdings denke ich, dass du nie zum Runterdimmen kommst:

 //FLUR LAUFZEIT & FREIGABE
  if(digitalRead(pinflurbm) == 1){ 
    eszflur = sekunden;
    flurbm = 1;
   
  }
 if(eszflur < (sekunden - flurlaufzeit)){ // Wenn Zeit abgelaufen ist, wird wieder runtergedimmt.
 flurbm = 0;
 
  }

Wenn eszflur erstmal auf einen sekunden-Wert gesetzt wurde, wird es nie mehr kleiner als
sekunden - flurlaufzeit

Evtl. solltest du dir angewöhnen, die Abfragen generell andersrum zu machen:

statt

if (zpeflur > (millis() + flurdimmzeit)) ( so evtl. gedacht ??? )

besser

if (millis() - zpeflur > flurdimmzeit)

Wenn die Differenz aus 2 Zeiten genommen wird als Vergleichswert, geht selbst während des Überlaufs alle 49 Tagen alles problemlos.

Da kann auch der Vergleichswert meist ein int sein, und eventuell gar eine Konstante.
const unsigned int flurdimmzeit = 500;

ja doch die praxis zeigt das das runterdimmen schon funktioniert bei allen dreien.
die werte werden ja alle im sekunden system benutzt, also keine sekunden werte mit millis vermixt.

die variante

if (millis() - zpeflur > flurdimmzeit)

gefällt mir auch viel besser, ist auch leichter zu verstehen ! Danke für den Tipp :slight_smile:

Hallo,

sschultewolter:
a) ein selbst gebautes USB Kabel zu nutzten, bei dem nur die 2 Datenleitung sowie Ground aufgelegt sind.

danke, das war jetzt die Lösung für eines meiner Probleme.
Manchmal sieht man den Parkplatz vor lauter Autos nicht (aktualisiertes Sprichwort).
Ich bastel hier immer noch an meiner LED-Beleuchtung. Der Arduino (mittlerweile Mega wegen Speicherproblemen) wird über +5V aus dem LED-Netzteil versorgt. Manchmal vergesse ich, vor dem Abschalten des Netzteils, das USB-Kabel zu ziehen. Die LEDs glimmen dann in rot. Bis jetzt hat es die USB-Schnittstelle am Rechner überlebt, aber das ist sicher nicht dauerhaft.
Ich habe einfach nie in Frage gestellt, ob die +5V via USB zum übertragen der Programme überhaupt nötig sind. Habe mir jetzt auch solch ein Kabel gebaut und es funktioniert.

Gruß
Christoph

edit wegen falschem Anschluss

Ja ein sehr guter Tipp der meinen im moment 4 Arduino Uno´s hohen Scheiterhaufen hoffentlich ab jetzt staub sammeln lässt :cold_sweat:

so ich habe den fehler gefunden es lag daran das ich esz... (z.b. eszflur ) zwar in sekunden rechnen lassen habe, dieser sekundentimer aber trotzdem über die 32000 kommt und damit den zähler wieder rücksetzt oder was auch immer, jedenfalls habe ich den esz... jetzt nicht in int sonder unsigned long deklariert und jetzt ist alles absolut super !!

habe mittlerweile noch eine echtzeituhr rangehängt, um morgends die lichter langsamer angehen zu lassen damit man nicht gleich so geflasht wird wenn man aus dem bett steigt und in den flur geht :smiley: . funzt perfekt !!

dazu aber eine frage :

wenn ich sagen will das ich von 0 - 8:00 Uhr funktion x ausführen will, habe ich es jetzt so gemacht das ich die aktuelle zeit in sekunden aufaddiere, also stunden3600 + minuten60 + sekunden und damit dann die zeit vergleiche.

also z.b. wenn "uhrzeit in sekunden" <= 28800( 8 uhr) ist , dann funktion x .

ich wollte vorher die einzelnen stellen vergleichen, da man ja stunden minuten und sekunden einzeln von dem echtzeitmodul bekommt, aber das ging nicht.

kennt da jemand eine leichtere methode die er schon angewendet hat, und die funktioniert ?

schöne grüße !

Da hast du dein Problem doch schön eingegrenzt, genau das sollte dir beim nächsten auch helfen. Die Herangehensweise über die gesamten Sekunden ist schon die richtige, allerdings bist du immer noch im Integer-Bereich. Für spätere Schaltzeiten brauchst du Variablen, die größere Werte aufnehemn können, hier bietet sich ein unsigned long an, das reicht schon über den gesamten Tag. :wink:

...aber das ging nicht.

kennt da jemand eine leichtere methode die er schon angewendet hat, und die funktioniert ?

  1. Das geht

  2. Ist aber nicht "leichter"

  3. Du könntest dir eine Klasse bauen, die -- wenn sie richtig verwendet wird -- leicht aussieht, die aber viel Arbeit kostet, bis sie funktioniert. Sehr lehrreich !

Verwendung z.B.

#include <Zeit.h> // definiert  class Zeit,um folgende Syntax zu ermöglichen

const Zeit STARTZEIT(8,0); // 8:00 
void loop()  {
   Zeit now(); // liest die aktuelle Zeit aus der Echtzeituhr
   if (now > STARTZEIT) func();
   delay(1000);
}

Man spart evtl. das Multiplizieren mit 60 und 3600, weil in ein long passen locker auch 3 byte für hh:mm:ss.
Aber ausser dem Lerneffekt in C++ Programmierung bringt es nicht viel.