Seite 9 von 31

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 3. Okt 2017, 21:52
von Fritzler
Deswegen nutzt man nicht son Mumpitz der alles wegabstrahiert, sondern ließt das Datenblatt.
Dort steht bei den AVRs, dass die Eingangsimpedanz zu einem ADC Pin nicht größer als 10k sein soll.
Sonst wird eben der S/H C nicht schnell genug geladen. 100k+100k sind bei weitem drüber.

Also eines der folgenden Dinge tun:
- nurnoch 10k als Vorwiderstand
- Opamp als Spannungsfolger
- 1nF an den ADC Pin, dann wird der pF große S/H C aus den 1nF geladen und nicht über die 100k

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 3. Okt 2017, 22:13
von xoexlepox
... zwischen den analogen Portpins den S/H-Kondensator (Sample and Hold) herumschaltet. Wenn dieser - so wie hier - aus einer hochohmigen Quelle gespeist wird, ist die erste Messung einfach Mist.
Das ist/war bei allen µCs, die ich bisher verwendet habe, so gelöst: Es gibt nur einen A/D-Wandler, und davor werkelt ein analoger Multiplexer. In den Datenblättern der Chips finden sich auch meist Formeln, mit denen sich die notwendige Wartezeit zwischen Selektierung der Portpins und Start der Wandlung berechnen lässt. Oftmals findet sich auch ein Hinweis, daß die Impedanz des zu messenden Analogsignals möglichst 10kOhm nicht überschreiten sollte. Ich vermute mal, daß in der Arduino-Lib diese Verzögerungen auch dementsprechend eingebaut sind. In meinen Programmen greife ich meist direkt auf die entsprechenden Register zu, wodurch die Selektierung des Portpins und die A/D-Wandlung zu getrennten Vorgängen werden. Und ich habe mir angewöhnt, sofort nach dem Start der A/D-Wandlung (die ja auch ein paar Takte benötigt, bis das Ergebnis vorliegt) den Analogmultiplexer auf den nächsten zu messenden Portpin umzuschalten.

Ok, Fritzler war schneller...

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mi 4. Okt 2017, 00:31
von berlinerbaer
Damit wäre das ja geklärt...

Wenn Du aus Deiner Anlage wieder ein paar Megas für andere Projekte verwenden möchtest, könntest Du auch I2C port extender verwenden oder ein Rudel nanos nehmen.

Kosten beim Chinesen einen bzw. anderthalb Euro.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mi 4. Okt 2017, 08:02
von Sir_Death
berlinerbaer hat geschrieben:Damit wäre das ja geklärt...

Wenn Du aus Deiner Anlage wieder ein paar Megas für andere Projekte verwenden möchtest, könntest Du auch I2C port extender verwenden oder ein Rudel nanos nehmen.

Kosten beim Chinesen einen bzw. anderthalb Euro.
Sorry - beides völlig Sinnlos.
Schau dir mal die Kosten für Portexpander an - PWM out, analog in, digital i/o. - Einen Mega bekommst du schon unter EUR 14,- inkl. Versand.
Dann kommt da noch die Programmlaufzeit dazu - je mehr Ports abzuarbeiten, desto mehr zu tun. Und nein, ich werde nicht anfangen in Plain C oder Assembler zu programmieren. Das mögen andere machen ich nicht.

Bezüglich Nanos: und wie vernetzt du die, ohne Kopfstände mit selbst abzuarbeitenden Interrupts? - Abgesehen davon, dass ich davon auch keinerlei Ahnung habe. Bei den Megas habe ich 4 serielle Schnittstellen mit Input-buffer. Den arbeite ich ab, wenn ich im Programm Zeit habe.

Meine Programmierkentnisse stammen aus der Zeit von Borland Pascal 6.0, und diese sind nur rudementär. Ich bin froh, überhaupt so weit gekommen zu sein.

@fritzler und xoexlepox: Danke für die Tips. Wenn es so wie jetzt gelöst dauerhaft funktioniert, bleibt es so, wenn nicht werden kleinere Vorwiderstände verbaut. Ursprünglich war ich am überlegen, die gesamte Anlage entweder mit Logikgatter oder mit PIC16F84 zu bauen. Vor dem PIC hat mir so gebraut, dass ich schon begonnen hatte, Logikgatter zu sammeln. Als ich dann durch den 3D-Druck Arduino in die Hände bekam, war ich begeistert, da sich mit dem Ding selbst von Halbidioten wie mich Programme zusammenstellen lassen, die sogar irgendwie laufen.
Den Anspruch auf Perfektionismus habe ich in anderen Bereichen, aber nicht beim Programmieren. Daher wäre ich euch sehr verbunden und dankbar, wenn ihr die Arduino-Umgebung nicht ständig verteufeln würdet. Jedem steht die Wahl seiner Mittel frei.

Danke.

P.S. Jetzt ist der Text doch etwas länger als geplant geworden. ;)

Edit: Sorry xoexlepotz - der Text mit dem Verteufeln ist nur für fritzler. :oops:

Re: Der AVR-/ARDUINO-Faden

Verfasst: Do 16. Nov 2017, 22:59
von Andreas_P
Ich habe folgende Schaltung aufgebaut.
Das funktioniert mit dem Arduino soweit. Leider kann ich die Uhrzeit nicht einstellen.
Um das zu anderen habe ich mir mal bei Pollin ein DCF-Empfangsmodul besorgt.
Dieses soll für eine Korrekte Uhrzeit sorgen.

Wie oder Was muss ich im Code ändern, damit die Uhrzeit vom dem DCF-Empfangsmodul
für die Anzeige der Zeit verwendet wird?

Bild->zoom

Code: Alles auswählen

#define A0 14 //ANALOG 0
#define A1 15
#define A2 16
#define INTERVAL 1000

//PINS SEKUNDEN MINUTEN STUNDEN
byte oneSecond[] = {0,1,2,3,4,5,6,7,8}; //No Serial on 0/1
byte tenSecond[] = {9,10,11,12,13};     //
byte theSwitch[] = {14,15,16};          //SEKUNDE MINUTE STUNDE
int s10=0,s1=0; //ONESECOND TENSECOND BAND
int m10=2,m1=9;
int h10=2,h1=2;

unsigned long t,t0; //TIMEINIT

void INTITIME(void){t0=millis();}
unsigned long TIMEREAD(void){return millis()-t0;}

void setup()
{int i;
 for(i=0; i<sizeof(oneSecond);i++)pinMode(oneSecond[i],OUTPUT);
 for(i=0; i<sizeof(tenSecond);i++)pinMode(tenSecond[i],OUTPUT);
 for(i=0; i<sizeof(theSwitch);i++)pinMode(theSwitch[i],OUTPUT);
 digitalWrite(A0, LOW);
 digitalWrite(A1, LOW);
 digitalWrite(A2, LOW);
}

void loop()
{int i;
 t=TIMEREAD();
 do
 {for(i=0;i<sizeof(oneSecond);i++)digitalWrite(oneSecond[i],s1<=i?LOW:HIGH);  //EINERBAND SEKUNDEN
  for(i=0;i<sizeof(tenSecond);i++)digitalWrite(tenSecond[i],s10<=i?LOW:HIGH); //ZEHNERBAND SEKUNDEN 
  digitalWrite(A0, HIGH);//Masse an Sekunden
  delay(1);             //SHOWTIME SEKUNDEN
  digitalWrite(A0, LOW);
  for(i=0;i<sizeof(oneSecond);i++)digitalWrite(oneSecond[i],m1<=i?LOW:HIGH);  //EINERBAND MINUTEN
  for(i=0;i<sizeof(tenSecond);i++)digitalWrite(tenSecond[i],m10<=i?LOW:HIGH); //ZEHNERBAND MINUTEN 
  digitalWrite(A1, HIGH);//Masse an MINUTEN
  delay(1);             //SHOWTIME MINUTEN
  digitalWrite(A1, LOW);
  for(i=0;i<sizeof(oneSecond);i++)digitalWrite(oneSecond[i],h1<=i?LOW:HIGH);  //EINERBAND STUNDEN
  for(i=0;i<sizeof(tenSecond);i++)digitalWrite(tenSecond[i],h10<=i?LOW:HIGH); //ZEHNERBAND STUNDEN
  digitalWrite(A2, HIGH);//Masse an STUNDEN
  delay(1);             //SHOWTIME STUNDEN
  digitalWrite(A2, LOW);
 }while(TIMEREAD()<(t+INTERVAL));
 //---------------------------------
 s1++;                   //s++;
 if(s1>=10){s1=0;s10++;} 
 if(s10>=6){s10=0;m1++;} //m1++;
 if(m1>=10){m1=0;m10++;}
 if(m10>=6){m10=0;h1++;} //h1++;
 if(h1>=10){h1=0;h10++;}
 if(h10>=2 && h1>=4){h10=0;h1=0;}
}
Schom mal danke im Vorraus.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Do 16. Nov 2017, 23:10
von Sir_Death
Schon mal Tante Google mit den Worten "Arduino DCF77" befragt? - Spuckt jede Menge aus.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Sa 18. Nov 2017, 18:14
von Andreas_P
Ja das habe ich getan. Das hat mich nur noch mehr Verwirrt. :?
Ich weiß als Anfänger nur das ich ne Bibliothek DCF brauche.
Den Code zu der Schaltung habe ich mit aus dem Netz besorgt und per Copy and Paste
einfach eingefügt.

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 19. Nov 2017, 00:02
von Profipruckel
Andreas_P hat geschrieben:Ich weiß als Anfänger nur dass ich ne Bibliothek DCF brauche. Den Code zu der Schaltung habe ich mir aus dem Netz besorgt und per Copy and Paste einfach eingefügt.
Damit erfüllst Du leider das Klischeebild des "Arduinos": Irgendetwas kopieren und dann im Forum fragen, weshalb es nicht geht.

Zerlege Deine Aufgabe in kleine Teile und teste diese Stück für Stück einzeln. Erst, wenn Du diese kleinen Teile verstanden hast, füge sie zum Gesamtprojekt zusammen.

Hast Du nachgelesen, wie DCF77 funktioniert? Der Empfänger liefert jede Sekunde einen Impuls mit 100 oder 200 ms Länge, aus dem der Arduino die Uhrzeit errechnen muß - das dauert ab Einschalten mindestens zwei Minuten. In diversen Foren findet man, dass es garnicht funktioniert, Störungen durch Schaltnetzteile etc.! Die Anschaltung des Pollin-Modules ist auch nicht ganz problemfrei, es kann nur einen sehr geringen Strom treiben.

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 19. Nov 2017, 09:24
von sysconsol
Ist du die Bibliothek korrekt eingebunden worden?

Hast du ein Oszilloskop? -> Signal am entsprechenden Eingang des Arduino prüfen.

Das muss nicht nur pegelmäßig stimmen, das muss auch plausibel (= nicht gestört) sein.
Eventuell mitschreiben und händisch dekodieren.

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 19. Nov 2017, 09:56
von Andreas_P
Meine Frage war, an welcher Stelle in dem Oben geposteten
Programmcode muß ich den Code für dem DCF Empfang
einfügen.

Ich hatte das Projekt mit der Reinturm Uhr Anfang des
Jahres entnervt zuseite gelegt. Das Pollin DCF Modul
hatte ich auf einen Steckbrett mit ein paar externen Bauteilen
aufgebaut. Was gut funktioniert hat.

Ich suche heute mal alles dafür wieder zusammen.
In dem Chaos muss das noch wo sein.
Am lebenden Objekt kann man besser ausprobieren.

sysconsol
Oszilloskop habe ich da. Ich hatte dem korrekten Empfang des
DCF mit einem Testprogramm überprüft, das die Uhrzeit und
Datum über den Seriellen Monitor Ausgabe.

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 19. Nov 2017, 20:07
von Myvesdin
Jetzt mal was, wo ich wahrscheinlich einfach den Wald vor lauter Bäumen nicht seh...

Code: Alles auswählen


#include <Arduino.h>
#include <Wire.h>
#include "RTClib.h"
int SRCLK = 11;
int RCLK = 12;
int SER = 4;
int counter = 1;
int nowseconds = 0; 
int nowhours = 0;
int nowminutes = 0;
int numZero = 63;
int numOne = 6;
int numTwo = 91;
int numThree = 79;
int numFour  = 102;
int numFive  = 109;
int numSix   = 125;
int numSeven = 7;
int numEight = 127;
int numNine  = 111;

RTC_Millis rtc;

void setup() {
 pinMode(10, OUTPUT);
 pinMode(2, OUTPUT);
 pinMode(3, OUTPUT);
 pinMode(6, OUTPUT);
 pinMode(7, OUTPUT);
 pinMode(8, OUTPUT);
 pinMode(SRCLK, OUTPUT);
 pinMode(RCLK, OUTPUT);
 pinMode(SER, OUTPUT);
 rtc.begin(DateTime(F(__DATE__), F(__TIME__)));
 rtc.adjust(DateTime(2017, 11, 19, 19, 11, 22));
}
 
void loop () {
 DateTime now = rtc.now();
 if (counter = 1){
    nowhours = now.hour();
    int nowhours = nowhours / 10;
    if (nowhours = 0){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, 0);
        digitalWrite(RCLK, HIGH);    
    }
    if (nowhours = 1){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numOne);
        digitalWrite(RCLK, HIGH);
        }
    if (nowhours = 2){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numTwo);
        digitalWrite(RCLK, HIGH);    
    }    
    digitalWrite(10, HIGH);
    delay(1);
    digitalWrite(10, LOW);
 }

 
 if (counter = 2){
    nowhours = now.hour();
    int nowhours = nowhours % 10;
    if (nowhours = 0){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numZero);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 1){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numOne);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 2){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numTwo);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 3){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numThree);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 4){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numFour);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 5){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numFive);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 6){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numSix);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 7){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numSeven);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 8){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numEight);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 9){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numNine);
        digitalWrite(RCLK, HIGH);
    }
    digitalWrite(2, HIGH);
    delay(1);
    digitalWrite(2, LOW);
 }
 
if (counter = 6){
  counter = 1;
}
else{
  counter = counter + 1;
  }
}
Hab den restlichen Code erstmal weggekürzt.

Es soll eine Uhr werden, die aus VFD-Röhren besteht.
Problem ist jetzt aber erstmal, dass er mir bei der ersten Ziffer eine 2 rausgibt und bei der zweiten Ziffer eine 9.
Ich versteh nur einfach nicht wieso?

Grüße

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 19. Nov 2017, 20:38
von andreas6
Ohne jetzt das Umfeld genau zu kennen, fällt mir die ungewöhnliche Taktgebung auf. Normalerweise legt man Daten an, schaltet dann den Takt ein und aus und ändert dann die Daten. Ist das so gewollt?

MfG. Andreas

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 19. Nov 2017, 21:57
von Myvesdin
Oh verdammt, ganz vergessen zu kommentieren :oops: :?

Code: Alles auswählen

#include <Arduino.h>
#include <Wire.h>
#include "RTClib.h" 
int SRCLK = 11;
int RCLK = 12;
int SER = 4; //SRCLK,RCLK & SER sind die Pins für ein Shiftregister

int counter = 1;
int nowseconds = 0;
int nowhours = 0;
int nowminutes = 0;

int numZero = 63;
int numOne = 6;
int numTwo = 91;
int numThree = 79;
int numFour  = 102;
int numFive  = 109;
int numSix   = 125;
int numSeven = 7;
int numEight = 127;
int numNine  = 111; //Das sind die Daten entsprechend für die verschiedenen Zahlen

RTC_Millis rtc;

void setup() {
 pinMode(10, OUTPUT);
 pinMode(2, OUTPUT);
 pinMode(3, OUTPUT);
 pinMode(6, OUTPUT);
 pinMode(7, OUTPUT);
 pinMode(8, OUTPUT);  //Die 6 VFD-Röhren 
 pinMode(SRCLK, OUTPUT);
 pinMode(RCLK, OUTPUT);
 pinMode(SER, OUTPUT); //Alle Datenpins als Output schalten
 rtc.begin(DateTime(F(__DATE__), F(__TIME__)));
 rtc.adjust(DateTime(2017, 11, 19, 19, 11, 22)); //Realtime Clock starten und testweise einstellen
}
 
void loop () {
 DateTime now = rtc.now(); //Uhrzeit abrufen
 if (counter = 1){
    nowhours = now.hour(); //RTC Stunden in ein Integer übertragen
    int nowhours = nowhours / 10; //int durch 10 teilen, um die erste Ziffer der Stunden zu bekommen

    if (nowhours = 0){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, 0);
        digitalWrite(RCLK, HIGH);   
    }
    if (nowhours = 1){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numOne);
        digitalWrite(RCLK, HIGH);
        }
    if (nowhours = 2){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numTwo);
        digitalWrite(RCLK, HIGH);                                //Herausfinden ob die erste Ziffer eine 0,1 oder 2 ist und dementsprechend die Daten in das Shiftregister übertragen
    }   
    digitalWrite(10, HIGH);
    delay(1);
    digitalWrite(10, LOW);        //1. VFD kurz einschalten, sodass die Ziffer angezeigt wird
 }

 
 if (counter = 2){
    nowhours = now.hour();        //Int "erneuern"
    int nowhours = nowhours % 10;   //2. Ziffer der Stunden erhalten
    if (nowhours = 0){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numZero);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 1){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numOne);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 2){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numTwo);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 3){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numThree);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 4){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numFour);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 5){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numFive);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 6){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numSix);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 7){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numSeven);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 8){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numEight);
        digitalWrite(RCLK, HIGH);
    }
    if (nowhours = 9){
        digitalWrite(RCLK, LOW);
        shiftOut(SER, SRCLK, MSBFIRST, numNine);
        digitalWrite(RCLK, HIGH);     //Herausfinden was die 2. Ziffer ist und die entsprechenden Daten ins Shiftregister schieben
    }
    digitalWrite(2, HIGH);
    delay(1);
    digitalWrite(2, LOW);    //2. VFD kurz einschalten
 }
 
if (counter = 6){
  counter = 1;
}
else{
  counter = counter + 1;
  }          //Da es 6 Röhren gibt soll es pro Durchlaufs des Loops eine Aktualisierung einer Röhre geben
}

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 19. Nov 2017, 22:45
von Andreas_P
Ich habe mir heute nen Wolf gesucht nach dem Pollin DCF Modul.
Etwas Doku habe ich auch noch gefunden.

Bild->zoom

Mit dieser Schaltung hatte ich Anfang des Jahres Erfolg gehabt das das Pollin DCF Modul funktionierte.

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 19. Nov 2017, 23:30
von xoexlepox
Etwas Doku habe ich auch noch gefunden.
Ach! Das braucht auch einen Vorwiderstand in der Zuleitung der Betriebsspannung? Bei einem Modul (von Reichelt) habe ich lange gebraucht, bis ich das herausgefunden hatte -> Diese Module sind m.E. oft echte "Mimosen" ;)

Re: Der AVR-/ARDUINO-Faden

Verfasst: So 19. Nov 2017, 23:54
von Andreas_P
Die Doku dazu hatte ich mir damals mit ausgedruckt.
Meine Doku Unterlagen habe ich heute auch wieder gefunden. :)
So war das gemeint.

xoexlepox
Doku gibt es zum dem Thema DCF im Netz mehr als genug.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mi 22. Nov 2017, 18:49
von Andreas_P
So meine Testschaltung die ich schon hier weiter oben gepostet habe, funktioniert.
Dieser Code gibt über den Seriellen Monitor Uhrzeit und Datum aus.

Code: Alles auswählen

 /**
     * Arduino DCF77 decoder v0.2
     * Copyright (C) 2006 Mathias Dalheimer (md@gonium.net)
     *
     * This program is free software; you can redistribute it and/or modify
     * it under the terms of the GNU General Public License as published by
     * the Free Software Foundation; either version 2 of the License, or
     * any later version.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License along
     * with this program; if not, write to the Free Software Foundation, Inc.,
     * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     */

    /**
     * Where is the DCF receiver connected?
     */
    #define DCF77PIN 2
    /**
     * Where is the LED connected?
     */
    #define BLINKPIN 13
    /**
     * Turn debugging on or off
     */
    #define DCF_DEBUG 1
    /**
     * Number of milliseconds to elapse before we assume a "1",
     * if we receive a falling flank before - its a 0.
     */
    #define DCF_split_millis 140
    /**
     * There is no signal in second 59 - detect the beginning of
     * a new minute.
     */
    #define DCF_sync_millis 1200
    /**
     * Definitions for the timer interrupt 2 handler:
     * The Arduino runs at 16 Mhz, we use a prescaler of 64 -> We need to
     * initialize the counter with 6. This way, we have 1000 interrupts per second.
     * We use tick_counter to count the interrupts.
     */
    #define INIT_TIMER_COUNT 6
    #define RESET_TIMER2 TCNT2 = INIT_TIMER_COUNT
    int tick_counter = 0;
    int TIMSK;
    int TCCR2;
    int OCIE2;
    /**
     * DCF time format struct
     */
    struct DCF77Buffer {
      unsigned long long prefix   :21;
      unsigned long long Min   :7;   // minutes
      unsigned long long P1      :1;   // parity minutes
      unsigned long long Hour   :6;   // hours
      unsigned long long P2      :1;   // parity hours
      unsigned long long Day   :6;   // day
      unsigned long long Weekday   :3;   // day of week
      unsigned long long Month   :5;   // month
      unsigned long long Year   :8;   // year (5 -> 2005)
      unsigned long long P3      :1;   // parity
    };
    struct {
       unsigned char parity_flag   :1;
       unsigned char parity_min      :1;
       unsigned char parity_hour   :1;
       unsigned char parity_date   :1;
    } flags;
    /**
     * Clock variables
     */
    volatile unsigned char DCFSignalState = 0;
    unsigned char previousSignalState;
    int previousFlankTime;
    int bufferPosition;
    unsigned long long dcf_rx_buffer;
    /**
     * time vars: the time is stored here!
     */
    volatile unsigned char ss;
    volatile unsigned char mm;
    volatile unsigned char hh;
    volatile unsigned char day;
    volatile unsigned char mon;
    volatile unsigned int year;
       

    /**
     * used in main loop: detect a new second...
     */
    unsigned char previousSecond;
       
    /**
     * Initialize the DCF77 routines: initialize the variables,
     * configure the interrupt behaviour.
     */
    void DCF77Init() {
      previousSignalState=0;
      previousFlankTime=0;
      bufferPosition=0;
      dcf_rx_buffer=0;
      ss=mm=hh=day=mon=year=0;
    #ifdef DCF_DEBUG
      Serial.println("Initializing DCF77 routines");
      Serial.print("Using DCF77 pin #");
      Serial.println(DCF77PIN);
      pinMode(BLINKPIN, OUTPUT);
      pinMode(DCF77PIN, INPUT);
    #endif
      pinMode(DCF77PIN, INPUT);
    #ifdef DCF_DEBUG
      Serial.println("Initializing timerinterrupt");
    #endif
      //Timer2 Settings: Timer Prescaler /64,
      TCCR2 |= (1<<CS22);    // turn on CS22 bit
      TCCR2 &= ~((1<<CS21) | (1<<CS20));    // turn off CS21 and CS20 bits   
      // Use normal mode
      TCCR2 &= ~((1<<WGM21) | (1<<WGM20));   // turn off WGM21 and WGM20 bits
      // Use internal clock - external clock not used in Arduino
      ASSR |= (0<<AS2);
      TIMSK |= (1<<TOIE2) | (0<<OCIE2);        //Timer2 Overflow Interrupt Enable
      RESET_TIMER2;
    #ifdef DCF_DEBUG
      Serial.println("Initializing DCF77 signal listener interrupt");
    #endif
      attachInterrupt(0, int0handler, CHANGE);
    }

    /**
     * Append a signal to the dcf_rx_buffer. Argument can be 1 or 0. An internal
     * counter shifts the writing position within the buffer. If position > 59,
     * a new minute begins -> time to call finalizeBuffer().
     */
    void appendSignal(unsigned char signal) {
    #ifdef DCF_DEBUG
      Serial.print(", appending value ");
      Serial.print(signal, DEC);
      Serial.print(" at position ");
      Serial.println(bufferPosition);
    #endif
      dcf_rx_buffer = dcf_rx_buffer | ((unsigned long long) signal << bufferPosition);
      // Update the parity bits. First: Reset when minute, hour or date starts.
      if (bufferPosition ==  21 || bufferPosition ==  29 || bufferPosition ==  36) {
       flags.parity_flag = 0;
      }
      // save the parity when the corresponding segment ends
      if (bufferPosition ==  28) {flags.parity_min = flags.parity_flag;};
      if (bufferPosition ==  35) {flags.parity_hour = flags.parity_flag;};
      if (bufferPosition ==  58) {flags.parity_date = flags.parity_flag;};
      // When we received a 1, toggle the parity flag
      if (signal == 1) {
        flags.parity_flag = flags.parity_flag ^ 1;
      }
      bufferPosition++;
      if (bufferPosition > 59) {
        finalizeBuffer();
      }
    }

    /**
     * Evaluates the information stored in the buffer. This is where the DCF77
     * signal is decoded and the internal clock is updated.
     */
    void finalizeBuffer(void) {
      if (bufferPosition == 59) {
    #ifdef DCF_DEBUG
        Serial.println("Finalizing Buffer");
    #endif
        struct DCF77Buffer *rx_buffer;
        rx_buffer = (struct DCF77Buffer *)(unsigned long long)&dcf_rx_buffer;
        if (flags.parity_min == rx_buffer->P1  &&
            flags.parity_hour == rx_buffer->P2  &&
            flags.parity_date == rx_buffer->P3)
        {
    #ifdef DCF_DEBUG
          Serial.println("Parity check OK - updating time.");
    #endif
          //convert the received bits from BCD
          mm = rx_buffer->Min-((rx_buffer->Min/16)*6);
          hh = rx_buffer->Hour-((rx_buffer->Hour/16)*6);
          day= rx_buffer->Day-((rx_buffer->Day/16)*6);
          mon= rx_buffer->Month-((rx_buffer->Month/16)*6);
          year= 2000 + rx_buffer->Year-((rx_buffer->Year/16)*6);
        }
    #ifdef DCF_DEBUG
          else {
            Serial.println("Parity check NOK - running on internal clock.");
        }
    #endif
      }
      // reset stuff
      ss = 0;
      bufferPosition = 0;
      dcf_rx_buffer=0;
    }

    /**
     * Dump the time to the serial line.
     */
    void serialDumpTime(void){
      Serial.print("Time: ");
      Serial.print(hh, DEC);
      Serial.print(":");
      Serial.print(mm, DEC);
      Serial.print(":");
      Serial.print(ss, DEC);
      Serial.print(" Date: ");
      Serial.print(day, DEC);
      Serial.print(".");
      Serial.print(mon, DEC);
      Serial.print(".");
      Serial.println(year, DEC);
    }


    /**
     * Evaluates the signal as it is received. Decides whether we received
     * a "1" or a "0" based on the
     */
    void scanSignal(void){
        if (DCFSignalState == 1) {
          int thisFlankTime=millis();
          if (thisFlankTime - previousFlankTime > DCF_sync_millis) {
    #ifdef DCF_DEBUG
            Serial.println("####");
            Serial.println("#### Begin of new Minute!!!");
            Serial.println("####");
    #endif
            finalizeBuffer();
            serialDumpTime();
          }
          previousFlankTime=thisFlankTime;
    #ifdef DCF_DEBUG
          Serial.print(previousFlankTime);
          Serial.print(": DCF77 Signal detected, ");
    #endif
        }
        else {
          /* or a falling flank */
          int difference=millis() - previousFlankTime;
    #ifdef DCF_DEBUG
          Serial.print("duration: ");
          Serial.print(difference);
    #endif
          if (difference < DCF_split_millis) {
            appendSignal(0);
          }
          else {
            appendSignal(1);
          }
        }
    }

    /**
     * The interrupt routine for counting seconds - increment hh:mm:ss.
     */
    ISR(TIMER2_OVF_vect) {
      RESET_TIMER2;
      tick_counter += 1;
      if (tick_counter == 1000) {
        ss++;
        if (ss==60) {
          ss=0;
          mm++;
          if (mm==60) {
            mm=0;
            hh++;
            if (hh==24)
              hh=0;
          }
        }
        tick_counter = 0;
      }
    };

    /**
     * Interrupthandler for INT0 - called when the signal on Pin 2 changes.
     */
    void int0handler() {
      // check the value again - since it takes some time to
      // activate the interrupt routine, we get a clear signal.
      DCFSignalState = digitalRead(DCF77PIN);
    }


    /**
     * Standard Arduino methods below.
     */

    void setup(void) {
      // We need to start serial here again,
      // for Arduino 007 (new serial code)
      Serial.begin(9600);
      DCF77Init();
    }

    void loop(void) {
      if (ss != previousSecond) {
        serialDumpTime();
        previousSecond = ss;
      }
      if (DCFSignalState != previousSignalState) {
        scanSignal();
        if (DCFSignalState) {
          digitalWrite(BLINKPIN, HIGH);
        } else {
          digitalWrite(BLINKPIN, LOW);
        }
        previousSignalState = DCFSignalState;
      }
        //delay(20);
    }
Das wird über den Seriellen Monitor ausgegeben:

-28402: DCF77 Signal detected, duration: 127, appending value 0 at position 55
-27411: DCF77 Signal detected, duration: 127, appending value 0 at position 56
-26419: DCF77 Signal detected, duration: 128, appending value 0 at position 57
-25427: DCF77 Signal detected, duration: 129, appending value 0 at position 58
####
#### Begin of new Minute!!!
####
Finalizing Buffer
Parity check OK - updating time.
Time: 17:46:0 Date: 22.11.2017
-23443: DCF77 Signal detected, duration: 129, appending value 0 at position 0
-22452: DCF77 Signal detected, duration: 129, appending value 0 at position 1
-21459: DCF77 Signal detected, duration: 232, appending value 1 at position 2

Re: Der AVR-/ARDUINO-Faden

Verfasst: Do 23. Nov 2017, 22:16
von Andreas_P

Re: Der AVR-/ARDUINO-Faden

Verfasst: Do 23. Nov 2017, 22:59
von Andreas_P
In meiner Verzweiflung ist mir eingefallen das
ich noch ein Meter Neopixel hier habe.
Mit einer Beschreibung aus dem Netz kann das wie oben
auf dem Bild heraus. Die Zeit wird per Bluetooth gestellt.
Das funktioniert noch nicht, ich habe die Zeit im Code
angepasst.
Die andere Schaltung werde ich auftrennen und sie mit
Schieberegistern ergänzen.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Fr 24. Nov 2017, 12:51
von atno
Myvesdin hat geschrieben:Oh verdammt, ganz vergessen zu kommentieren :oops: :?
Naja du hast deine Vergleiche in so ziemlich allen if Bedingungen falsch.

if (nowhours=9) weißt der Variablen nowhours den Integer 9 zu und das if prüft dann ob nowhours wahr ist.

Alles was nicht 0 ist, ist in c wahr. Damit sind alle deine if Abfragen wahr und die letzte wird für dich sichtbar.
Alle anderen davor sind aber genau so ausgeführt worden, nur eben direkt wieder überschrieben.

Was du schreiben wolltest ist if (nowhours==9).

Das betrifft übrigens auch alle deine counter Vergleiche.

Wenn du am Anfang sicherstellen möchtest dass der Kompiler dich dafür anmeckert kannst du den Vergleich umdrehen, also so etwas wie
if (9==nowhours) schreiben. Als Vergleich funktioniert das wunderbar, vergisst du das zweite = wird darauf (9=nowhours). Der Kompiler wird
dich dann darauf hinweisen das er einem Wert keine Variable zuweisen kann.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 6. Feb 2018, 14:45
von barclay66
Hi,

im Rahmen eines neuen Projektes taucht gerade eine Aufgabenstellung auf, zu der ich gerne fachlichen Rat hätte:

Ich will über einen Arduino Mega 2650 insgesamt vier Heimkino-Geräte (einen Video-Prozessor, einen AV-Receiver, einen Röhrenprojektor und einen Digitalprojektor) über RS232 steuern und zusätzlich ein paar Relais für deren Besaftung. Die Daten und Kommandos, die jeweils verstanden werden sind bekannt sowie auch evtl. Rückmeldungen. Ziel ist es, mit einem Tastendruck eine Sequenz von Einschalt- und Konfigurationsbefehlen loszutreten. Z.B.:

Taste "Analog TV" -> Saft an für Kabelreceiver, Blu Ray Player, Apple-TV, Video-Prozessor, AV-Receiver -> Saft an für Röhrenprojektor -> Pause bis Video-Prozessor hochgefahren ist -> Kommando "720p50 von Eingang 1 in 720p100 an Ausgang" an Video-Prozessor -> Pause bis Kabelreceiver hochgefahren ist -> Kommando "Aufwachen aus Standby" an Röhrenprojektor -> Kommando "Settings für 720p100 abrufen" an Röhrenprojektor -> Fertig

oder

Taste "Digital Blu Ray" -> Saft an für Kabelreceiver, Blu Ray Player, Apple-TV, Video-Prozessor, AV-Receiver -> Saft an für Digitalprojektor -> Pause bis Video-Prozessor hochgefahren ist -> Kommando "1080p24 von Eingang 1 in 1080p24 an Ausgang" an Video-Prozessor -> Kommando "Aufwachen aus Standby" an Digitalprojektor -> Fertig

oder

Taste "Ausschalten" -> Saft aus für Kabelreceiver, Blu Ray Player, Apple-TV, Video-Prozessor, AV-Receiver -> Wenn Röhrenprojektor an -> Saft aus für Röhrenprojektor -> Wenn Digitalprojektor an -> Kommando "Standby" an Digitalprojektor -> Warten bis Nachlaufzeit der Lüfter vorbei ist -> Saft aus für Digitalprojektor -> Fertig

Die Kommunikation muss dabei nicht gleichzeitig erfolgen sondern kann schrittweise eines der Geräte nach dem anderen abklappern.
Ich stehe jetzt vor der Frage, ob ich mit der entsprechenden Anzahl an I/O-Pins vier RS232-Schnittstellen mit jeweils z.B. einem MAX3232 aufbaue und für jede der Schnittstellen entsprechende Routinen vorsehe oder ob ich das nur einmal mache und die Ausgänge mittels bidirektionaler Mosfet-Schalter auf vier Sub-D Buchsen verteile. Dann könnte ich in die jeweilige Schleife zu einer Befehlskette einfach ein "Wähle Schnittstelle x" einbauen und bräuchte das ganze serielle Gedöns nur einmal im Code anzuwerfen.

Wie würdet Ihr das tun?

Gruß
barclay66

P.S.: Bitte keine alternativen Hardwarevorschläge ("der Super-Seriell-Kontrollör"), da ich die Arduinos schon rumliegen habe und mich auch nicht in die x-te IDE einarbeiten mag. Danke!

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 6. Feb 2018, 14:56
von sysconsol
Ich habe das so ähnlich mal an einer größeren Installation gemacht.
Alle RS232 auf RS485 bzw. RS422.
Und dann kommen alle Geräte an den Bus.
Voraussetzung: Jeder reagiert nur auf seine Kommandos.

Ansonsten würde ich vom Kontroller nur den Hardware-UART nutzen und per Logikgatter auf Schnittstellen-Treiber umschalten.
Oder hinter dem Schnittstellentreiber, wenn das sicher funktioniert.
Kommt auch drauf an, was man an Bauteilen so herumliegen hat ;)

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 6. Feb 2018, 16:31
von Matt
Meine Vorschlag: I2C und Watchdog ( Arduino hat I2C und Watchdog auch )



Grüss
Matt

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 6. Feb 2018, 16:54
von Christian Knüll
Hallo,

der Arduino mega hat praktischerweise exakt 4 UARTs eingebaut - einfach für jedes Gerät einen verwenden - fertig.

Christian

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 13. Feb 2018, 07:58
von Heaterman
Ich will einen Sekundenzähler in eine Uhrzeitanzeige (Breite 128 Pixel) einbinden, der mit fortlaufenden Punkten die Sekunden 1-60 zeigt.

Bisher geht das so:

if (s == 1)
{
display.setCursor(0, 15);
display.print(" . ");
}

if (s == 2)
{
display.setCursor(0, 15);
display.print(" . . ");
}

usw.

//alle 15 s einen Marker:

if (s == 15)
{
display.setCursor(32, 15);
display.print(" | ");
}

if (s == 30)
{
display.setCursor(64, 15);
display.print(" | ");
}

usw.

Die Sekundenzählung kann man doch sicher in einer Funktion abfertigen? Hat jemand eine Idee?

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 13. Feb 2018, 13:23
von xoexlepox
Die Sekundenzählung kann man doch sicher in einer Funktion abfertigen? Hat jemand eine Idee?
Hast du eine "left" oder "substr"-Funktion, die von einem String die linken N Zeichen abschneidet? Dann kannst du ein Array mit den kompletten 60 Zeichen füllen, und nur die Anzahl Zeichen ausgeben, die dein Sekundenzähler angibt. Eine andere Variante wäre eine Schleife, die bis zum Sekundenzähler läuft, und bei jedem Durchlauf ein Zeichen ausgibt. Ist der Schleifenzähler durch 5 teilbar (" i%5 == 0" ) wird ein "|" ausgegeben, sonst ein '.'.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 13. Feb 2018, 14:12
von Anse

Code: Alles auswählen



void draw_sec_bargraph(int S)
{

display.setCursor(0, 15);

   for(i=0;i<S;i++)
  {
       if(!(i%15))//Wen durch 15 teilbar dann Maker
       {
         Diplay.print("|");
       }
        else//Sonst Punkt
       {
         Diplay.print(".");
       }
    }
//ggf. den Bereich der noch leer bleibt "aufräumen"
    for(i=0;i<(128-S);i++)
   {
    Diplay.print(" ");
   }
}

//END



Es gäbe noch einen etwas komplexeren Ansatz, der nicht immer alles neu Zeichnet.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mi 14. Feb 2018, 05:42
von Heaterman
Vielen Dank für die Antworten. War der richtige Denkanstoß. Nach Anpassung hat Anses Code geklappt - vielen Dank!

Re: Der AVR-/ARDUINO-Faden

Verfasst: Do 22. Feb 2018, 07:45
von Heaterman
Nächste Hürde bei meiner Wortuhr, Zuweisung von festen Texten bei bestimmten Zeiten. Sorry, Gelegenheitsprogrammierer halt, aber ich partout eine deutsche Wortuhr auf einem Display statt LED-Matrix zusannenbauen.

Hab ich so versucht:

Code: Alles auswählen

if (m == 25 && h == 0 || h == 12) goto label1;


  if (m == 25 && h == 1) goto label2;

  {
label1:
    display.clearDisplay();
    display.setCursor(0, 0);
    display.print("Es ist  F \232 n f   vor");
    display.setCursor(3, 9);
    display.print("H a l b   E i n s" );
  }
  {
label2:
    display.clearDisplay();
    display.setCursor(0, 0);
    display.print("Es ist  F \232 n f   vor");
    display.setCursor(3, 9);
    display.print("H a l b   Z w e i" );
  }
}
Aber hier geht die Anzeige nach Start der Uhr genau auf die Anzeige von Label2 und bleibt da. Wo hab ich jetzt die Klammern falsch gesetzt?
Oder kann man da besser ein Array oder sogar eine lib bilden, was man abfragt? Aber wie geht sowas?

Die Alternative war, jede einzelne in Frage kommende Anzeige mit if...print... platt auszugeben, funktioniert, aber das übersteigt sofort den Speicher des AVRs. Die goto-Methode spart enorm Speicher, aber wo hab ich mich da verrannt?

Re: Der AVR-/ARDUINO-Faden

Verfasst: Do 22. Feb 2018, 07:57
von manuel
Der geht schon zu label 1, aber darunter ist label 2 und der part wird auch ausgeführt. Das heisst dein display zeigt ganz kurz fünf von halb ein an, uns dann fünf vor halb 2, so schnell das du es nicht siehst.

Aber mal im ernst willst du jede Permutation von Stunde und Minute einzeln behandeln ? Erstmal sind Stunde und Minute unabhängig, kann also anstatt mit quadrat nur mit Faktor 2 gebastelt programmiert werden, und noch einfacher wärs wenn du die stunden und minuten/5 direkt als look up index inner Tabelle nimmst.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Do 22. Feb 2018, 09:36
von ferdimh
Die goto-Methode spart enorm Speicher, aber wo hab ich mich da verrannt?
Die interessante Fragestellung ist eher, warum die Goto-Methode Speicher spart. Das sollte sie eigentlich nicht...
Durch Aufteilung des Ganzen in "es ist x vor/nach" und halbe Stunden sollte sich der Code aber ausreichend verkleinern lassen, dass das in den Speicher passt.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Do 22. Feb 2018, 16:21
von xoexlepox

Code: Alles auswählen

if (m == 25 && h == 0 || h == 12) ...
Uhhh.... Ich weiß, es gibt eine "operator precedence", ich hätte aber heftige Probleme nun zu sagen, wie diese Zeile wirkt ( was passiert z.b. bei m=24 und h=12 ?). Bei verschiedenen Operatoren in einer Zuweisung/Bedingung setze ich grundsätzlich entsprechende Klammern -> Es erleichtert zumindest das Lesen des Codes ;)

Re: Der AVR-/ARDUINO-Faden

Verfasst: Do 22. Feb 2018, 18:01
von Heaterman
:oops: :oops: Ja, ich bin so ein Spaghettiprogrammierer, man sieht auch immer wieder, dass ich aus der BASIC-Ecke komme, :mrgreen:

Ich werde das mal nach ferdis Vorschlag neu sortieren...

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mo 12. Mär 2018, 20:34
von sysconsol
Ich habe eine RTC Typ DS1302Z hier liegen.
Der Code vom User Krodal im Arduino-Playground funktioniert,
wenn er direkt in der Sketch liegt.

Nun wollte ich aus dem Code eine Bibliothek machen.
Die Definitionen samt Deklarationen in eine Header-Datei, die Funktionen in eine cpp-Datei.
Schrieb man im Roboternetz.
Aber was mache ich mit der Struktur?

Code: Alles auswählen

typedef struct ds1302_struct
Das Setzen der Zeit über

Code: Alles auswählen

memset ((char *) &rtc, 0, sizeof(rtc));
hätte ich in eine Funktion verbaut und mit in die cpp-Datei gelegt.

Ich denke, da fehlt mir etwas Wissen zu den C++-Gerüsten :oops:

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mo 12. Mär 2018, 20:49
von Heaterman
Warum nimmst Du keine fertige Bibliothek, z. B. die von Adafruit?

Ich fingere auch gerade an dem Problem mit dem Stellen rum. Momentan stelle ich den RTC durch einen ganz kurzen Sketch über das Terminal, da kann man die Verzögerung fürs Hochladen einrechnen. Danach kommt das normale Programm auf den AVR und ernährt sich vom zuvor gestellten RTC.
Normalerweise holt man ja per lib die Zeit zum Zeitpunkt des Compilierens vom Rechner, aber das ist eben ungenau, je nach Länge des Compilierens/Hochladens. Noch besser würde ich ein manuelles Stellen des RTC per Hardwaretasten finden, aber das hab ich noch nicht raus. Aber solange die Batterie für den RTC geht, reicht ja eigentlich das Stellen per Terminal.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mo 12. Mär 2018, 21:24
von sysconsol
Weil keine andere funktioniert.

Edit 20:56: Gerade noch etwas gefunden, was funktioniert: https://github.com/msparks/arduino-ds1302

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 13. Mär 2018, 00:09
von Sir_Death
naja. bei 1302 und 1307 kann man fast gleich weg lassen. - mehrere Minuten pro Tag sind keine Seltenheit. Nimm doch eine 3231

https://forum.arduino.cc/index.php?topic=377472.0
und die Lib geht jedenfalls: https://github.com/JChristensen/DS3232RTC

EdIt: Zahlendreher..

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 13. Mär 2018, 10:01
von sysconsol
Mit der bereits oben schon verlinken DS1302-Bibliothek von msparks habe ich noch ein Verständnisproblem.

Ich möchte die Zeit setzen - per Terminal.

Das Beispiel macht das in der Sketch wie folgt (ohne Terminal):

Code: Alles auswählen

// Make a new time object to set the date and time.
// Sunday, September 22, 2013 at 01:38:50.
   Time t(2013, 9, 22, 1, 38, 50, Time::kSunday);
   rtc.time(t); // setzt die Zeit
Im Headerfile steht dazu:

Code: Alles auswählen

// Class representing a particular time and date.
class Time {
 public:
  enum Day {
    kSunday    = 1,
    kMonday    = 2,
    kTuesday   = 3,
    kWednesday = 4,
    kThursday  = 5,
    kFriday    = 6,
    kSaturday  = 7
  };

  // Creates a Time object with a given time.
  //
  // Args:
  //   yr: year. Range: {2000, ..., 2099}.
  //   mon: month. Range: {1, ..., 12}.
  //   date: date (of the month). Range: {1, ..., 31}.
  //   hr: hour. Range: {0, ..., 23}.
  //   min: minutes. Range: {0, ..., 59}.
  //   sec: seconds. Range: {0, ..., 59}.
  //   day: day of the week. Sunday is 1. Range: {1, ..., 7}.
  Time(uint16_t yr, uint8_t mon, uint8_t date,
       uint8_t hr, uint8_t min, uint8_t sec,
       Day day);

  uint8_t sec;
  uint8_t min;
  uint8_t hr;
  uint8_t date;
  uint8_t mon;
  Day day;
  uint16_t yr;
};
Ich habe dann versrucht, per Terminal
- einen String einzulesen -> funktioniert
- in Teilstrings zu zerlegen -> funktioniert
- die Teilstrings in uint8_t zu konvertieren -> funktioniert

Nur mit dem Day komme ich nicht klar.
Folgende Codeschnipsel aus dem Sketch:

Die Eingabe am Terminal zum Setzen lautet (\n -> newline-character)

Code: Alles auswählen

set20180313090100Tuesday\n
Das kommt auch so im String temp an.

Es folgt

Code: Alles auswählen

Serial.println(temp); // Eingabe anzeigen zwecks Kontrolle, zum Jahr hin muss eine freie Zeile sein!!
// Eingabe zerschneiden in einzele Strings und diese zu uint8_t konvertieren
jahr = temp.substring(3, 7).toInt();
monat = temp.substring(7, 9).toInt();
tag = temp.substring(9, 11).toInt();
stunde = temp.substring(11, 13).toInt();
minute = temp.substring(13, 15).toInt();
sekunde = temp.substring(15, 17).toInt();

temp = temp.substring(17); // Tagesname mit newline in temporären String ablegen
// Länge Tagesname mit newline ermitteln    
// newline brauchen wir nicht mehr 
// newline abschneiden, nur den Tagesnamen behalten    
temp.remove((temp.substring(17).length()) - 1); 
wochentag = String("k" + temp); // dem Tagesnamen ein "k" voranstellen (siehe enum Day in Headerfile)

// so war das gedacht, funktioniert jedoch nicht:
// Time t(jahr, monat, tag, stunde, minute, sekunde, wochentag);
// no matching function for call to 'Time::Time(uint16_t&, uint8_t&, uint8_t&, uint8_t&, uint8_t&, uint8_t&, String&)'

// so geht es auch nicht:
// Time t(jahr, monat, tag, stunde, minute, sekunde, Time::wochentag);
// 'wochentag' is not a member of 'Time' --> logisch, nur: wie drücke ich aus, dass der Inhalt von "wochentag" eingesetzt werden soll?
    
// so funktioniert das prinzipiell, nur der Wochentag lässt sich nicht setzen:
Time t(jahr, monat, tag, stunde, minute, sekunde, Time::kTuesday);
rtc.time(t);
    
// auch folgendes funktioniert nicht:
// rtc.time(jahr, monat, tag, stunde, minute, sekunde, Time::kTuesday);
    
rtc.halt(false); // RTC wieder laufen lassen
halten = false; // ein Merker für den Zustand, unkritisch
Serial.println(jahr);
Serial.println(monat);
Serial.println(tag);
Serial.println(stunde);
Serial.println(minute);
Serial.println(sekunde);
Serial.println(wochentag);
Sketch (in .ino umbenennen)
RTC_V00.txt
(4.5 KiB) 61-mal heruntergeladen
Das dürfte wieder auf ein C++-Verständnisproblem hinauslaufen :oops: - Was mache ich falsch?

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 13. Mär 2018, 16:50
von Anse
Funktioniert die Wandlung von Day String zu int?
Warum kann man den Tag nicht auch einfach mit einer Zahl setzen?

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 13. Mär 2018, 18:31
von sysconsol
Eben nicht.
Wenn ich den Tag als String einsetze, dann funktioniert es ja nicht mehr.

Oder verstehe ich deine Frage falsch?

Warum kann man den Tag nicht auch einfach mit einer Zahl setzen?
Du meinst, die Time-Funktion nicht ein enum erwarten lassen, sondern ein uint8_t?
Muss ich mal probieren.

Edit 18:11: Die Ausgabe funktionier schon, nur die Eingabe (setzen) funktioniert nicht mehr. Muss mir etwas mehr Verständnis besorgen.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 13. Mär 2018, 19:42
von Anse
sysconsol hat geschrieben:Du meinst, die Time-Funktion nicht ein enum erwarten lassen, sondern ein uint8_t?
Muss ich mal probieren.
In den String

Code: Alles auswählen

set20180313090100 2 \n
Statt Tuesday einfach eine 2 einfügen wie gezeigt, natürlich ohne Leerzeichen. Dann wie der Rest auslesen und umwandeln.

Alternativ kannst Du auch eine eigenen Funktion schreiben die aus "Tuesday" eine 2 macht und mit den anderen Tagen natürlich auch.
Geht auch mit Ersetzen im String.

Ich hätte das ganze mehr in dem Format gemacht:

Code: Alles auswählen

SetDate: 13.3.2018
SetWeekDay: 2
SetTime: 18:45:00
Vorteil:
-einzelne Datensätze können getrennt geschrieben werden. Z.B. wenn man nur die Zeit ändern will.
-Schön übersichtlich
-Leicht zu implementieren aber nur wenn es um noch mehr ähnliche Datensätze gibt damit es sich lohnt.

Beim Interpretieren wird nach den jeweiligen Schlüsselwörtern gesucht. Die Schlüsselwörter geben dann auch gleich an wie der folgende Stringabschnitt zu verstehen ist. Die Trennzeichen sind auch hilfreich beim interpretieren.
Nur mal so als Anregung.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Di 13. Mär 2018, 21:02
von sysconsol
So einfach (statt Tagesnamen die Ziffer schreiben) geht das nicht.
Da müsste man irgendwie umwandeln, was ich aber nicht hinbekommen habe.

Ich habe jetzt die Bibliothek abgeändert.
Damit funktioniert das ohne die Tage beim Namen zu kennen.
Die Umwandelei ist mir persönlich zu verkompliziert worden.
Wenn ich das Chaos bereinigt habe, kann ich das gerne hier einstellen.

Die Formatierung der Ausgabe (Reihenfolge von Jahr, Monat,...) ist ein geringeres Problem und bereits gelöst.

Danke!

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mi 14. Mär 2018, 09:13
von sysconsol
Hier die modifizierte Bibliothek.
Im Beispiel-Ordner ist die Sketch zum Setzen der Zeit enhalten.

(ich hoffe, ich verstoße mit dem Einstellen nicht gegen irgendwelche Rechte)

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mo 21. Mai 2018, 00:06
von Sir_Death
Jungs, ich brauch mal eure Hilfe - meine C-Kenntnisse sind schon seit 20 Jahren verrostet.

Gegeben: 2 Stück 3D-Drucker und eine Käsefräse, alle 3 mit Arduino Mega 2560 und RAMPS.
Unterschied: der USB-Chip 1 x der 16U2 und 2 x der CH340

Plan: Es soll eine Handsteuerung für die 3 Geräte her, die ich einfach anstecken (bzw. zwischen PC und Maschinensteuerung rein stecke)
Lösung: Noch ein Arduino Mega mit dem USB-Host-Shield.
Kommunikation mit allen 3en klappt schon mal, aber: es müssen unterschiedliche Treiber für den 16U2 und die CH340 geladen werden.
Nachdem ich die Handsteuerung einfach umstecken können will, fällt jedes mal neu compilieren aus.

Frage: Kann mir irgendjemand helfen, diesen Sourcecode so umzustricken, dass der Arduino beim Start entscheiden kann, welchen Treiber er lädt? - gerne spendiere ich einen Schalter an einem Eingang, mit dem ich den gewünschten Treiber signalisiere.
Hauptproblem: Die Programmierer der beiden Libraries (cdcacm.h und cdc_ch34x.h) haben teilweise die gleichen Variablennamen verwendet - spießt sich also auch schon mal dort.

Library: https://github.com/felis/USB_Host_Shield_2.0
Zusätzlich sind noch die beiden angehängten Dateien für den CH340 notwendig (habe ich in einem japanischen Forum gefunden - Google Translate macht es lesbar: http://www.suke-blog.com/arduino_usb_ho ... ith_ch340/

Code: Alles auswählen

// General definitions
#include <SPI.h>
uint16_t rcvd = 0;
byte data = 0;
byte i = 0;
byte buf[64];

// Arduino with 16U2 Interface-Chip
#include <cdcacm.h>

class MyAsyncOper : public CDCAsyncOper {
  public: byte OnInit(ACM *pacm) {
    LINE_CODING  lc;
    lc.dwDTERate  = 250000;
    lc.bCharFormat  = 0;
    lc.bParityType  = 0;
    lc.bDataBits  = 8;
    pacm->SetLineCoding(&lc);
  }
};

USB           Usb;
MyAsyncOper   AsyncOper;
ACM           Acm(&Usb, &AsyncOper);

//Arduino with CH340 Interface-Chip
/*#include <cdc_ch34x.h>
 
class MyAsyncOper : public CDCAsyncOper {
  public: byte OnInit(CH34X *pch34x) {
    LINE_CODING lc;
    lc.dwDTERate = 250000;
    lc.bCharFormat = 0;
    lc.bParityType = 0;
    lc.bDataBits = 8;
    lc.bFlowControl = 0;
    pch34x->SetLineCoding(&lc);
  }
};

USB         Usb;
MyAsyncOper AsyncOper;
CH34X       Acm(&Usb, &AsyncOper);*/

void setup()
{
  Serial.begin(250000);
  Usb.Init();
}

void loop()
{
  Usb.Task();

  // Arduino with 16U2 Interface-Chip
  rcvd = 64;
  //Arduino with CH340 Interface-Chip
  //rcvd = 32;

  if( Acm.isReady()) {
    if(Serial.available()) {
      data= Serial.read();
      Acm.SndData(1, &data);
    }
    Acm.RcvData(&rcvd, buf);
    if( rcvd ) for(i=0; i < rcvd; i++ ) Serial.print((char)buf[i]);
  }
}
Ich wäre für Hilfe sehr dankbar, denn das ist jedenfalls jenseits meiner Grenzen. - Bin froh, dass ich den Sourcecode so weit vereinfachen konnte.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mi 23. Mai 2018, 22:24
von gafu
Ich hab mal eine Frage:

Ich hab eine steuerung mit einem Atmega2560 prozessor.
Der hat ja 1000 beinchen, und eben auch welche, die beim "arduino mega" nicht auf buchsenleisten herausgeführt sind, und deshalb beim pin-mapping auch keine nummer in den üblichen übersichten haben.
z.B. Pin 69 "Port J bit 6"

Wie steuere ich den denn an mit den üblichen mitteln in der arduino ide?

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mi 23. Mai 2018, 22:27
von Sir_Death
Ich vermute mal, auf Fußpilzbasis (Assembler) wird es schon gehen, wenn du die Register direkt ansprichst - frag mich aber bloß nicht wie.

Auf meine Frage (1 weiter oben) gibt es scheinbar noch keine Antwort. Schade :-(

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mi 23. Mai 2018, 23:20
von Anse
Sir_Death hat geschrieben:Auf meine Frage (1 weiter oben) gibt es scheinbar noch keine Antwort. Schade
Ich hab von dem arduino-C keine Plan aber vielleicht bring es Dir was:

Code: Alles auswählen

// General definitions
#include <SPI.h>
uint16_t rcvd = 0;
byte data = 0;
byte i = 0;
byte buf[64];

// Arduino with 16U2 Interface-Chip
#include <cdcacm.h>

class MyAsyncOper : public CDCAsyncOper {
  public: byte OnInit(ACM *pacm) {
    LINE_CODING  lc;
    lc.dwDTERate  = 250000;
    lc.bCharFormat  = 0;
    lc.bParityType  = 0;
    lc.bDataBits  = 8;
    pacm->SetLineCoding(&lc);
  }
};

USB           Usb;
MyAsyncOper   AsyncOper;
ACM           Acm(&Usb, &AsyncOper);

//Arduino with CH340 Interface-Chip
/*#include <cdc_ch34x.h>
 
class MyAsyncOper : public CDCAsyncOper {
  public: byte OnInit(CH34X *pch34x) {
    LINE_CODING lc;
    lc.dwDTERate = 250000;
    lc.bCharFormat = 0;
    lc.bParityType = 0;
    lc.bDataBits = 8;
    lc.bFlowControl = 0;
    pch34x->SetLineCoding(&lc);
  }
};

USB         Usb;
MyAsyncOper AsyncOper;
CH34X       Acm(&Usb, &AsyncOper);*/

void setup()
{
  Serial.begin(250000);
  Usb.Init();
 pinMode([Pin mit Schalter], INPUT);//Hier muss ein Pull-up zu Vcc und ein Schalter zu Gnd dran
}

void loop()
{
  Usb.Task();
if (LOW==DigitalReade([Pin mit Schalter]))
{
	// Arduino with 16U2 Interface-Chip
	rcvd = 64;
} 
else
{
	//Arduino with CH340 Interface-Chip
	rcvd = 32;
}
  
  

  if( Acm.isReady()) {
    if(Serial.available()) {
      data= Serial.read();
      Acm.SndData(1, &data);
    }
    Acm.RcvData(&rcvd, buf);
    if( rcvd ) for(i=0; i < rcvd; i++ ) Serial.print((char)buf[i]);
  }
}
An einem Pin muss ein Schalter angeschlossen werden. Wie siehe Kommentar.
gafu hat geschrieben:Ich hab mal eine Frage:

Ich hab eine steuerung mit einem Atmega2560 prozessor.
Der hat ja 1000 beinchen, und eben auch welche, die beim "arduino mega" nicht auf buchsenleisten herausgeführt sind, und deshalb beim pin-mapping auch keine nummer in den üblichen übersichten haben.
z.B. Pin 69 "Port J bit 6"

Wie steuere ich den denn an mit den üblichen mitteln in der arduino ide?
Habs nicht geprüft aber da sie mit C verwand ist könnte das hier gehen:

Code: Alles auswählen

DDRJ|=(1<<6);//Vergleichbar mit PinMode();
PORTJ|=(1<<6);//Setzen
PORTJ&=~(1<<6);//Zurück setzen
Wenn die Konstanten DDRJ usw. nicht bekannt sein sollten müssen an ihrer Stelle die Adressen aus dem Dabla. verwendet werden.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mi 23. Mai 2018, 23:28
von Sir_Death
Servus Anse

Danke - aber das ist leider nicht des Rätsels Lösung - soweit komme ich zum Glück selbst.
Mein Problem ist, dass die beiden USB-Librarys für den CH340 und den 16U2 die selben public Variablen verwenden, und sich das deswegen beim compilieren beißt...
Und eine Library ändern, damit das geht, übersteigt noch bei weitem meine Fähigkeiten.

Ich versuche mehr oder weniger ein Plug and Play mit Autodetect zu programmieren, wo der Arduino selbst entscheidet, welchen Treiber er lädt.

Inzwischen habe ich (bei 3D-Drucker Firmware abgeschaut) zumindest geschafft, dass ich nicht jedes mal die gesamten Kommentarmarker ändern muss, sondern eine Config-Variable am Anfang, die den Compiler beeinflusst.

EDIT: Und externer Pullup braucht man nicht - einfach INPUT gegen INPUT_PULLUP tauschen ;)

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mi 23. Mai 2018, 23:30
von berlinerbaer
Ohne jetzt den code gelesen zu haben, würde ich bei den sich überschneidenden Variablennamen einfach bei einem der beiden Treiber alle mit einem einheitlichen, kurzen Präfix versorgen, damit nix mehr durcheinander kommt.

Dann per Schalter zwischen beiden hin- und herschalten. Oder, noch simpler, die Buchsen in den zu steuernden Geräten direkt mit der passenden Brücke versehen, dann gehts ganz ohne Nachdenken und Platz genug wäre selbst bei einem DB9-Stecker...

Beim 2560 ist wohl wirklich Datenblattlektüre und eventuell auch inline-Assembler erforderlich.

Re: Der AVR-/ARDUINO-Faden

Verfasst: Mi 23. Mai 2018, 23:33
von gafu
bei den üblichen 3d-drucker-firmwares gibts ne zweite serielle schnittstelle, z.b. für die steuerrung per bluetooth-modul.

Dort kannst du mit einem beliebigen geräts einfach per seriellem Uart Gcode-befehle reinsenden.
Du musst nur verhindern, das die handsteuerung etwas sendet während auf dem usb auch gcode reinkommt, weil das ineinanedrgewürfelt werden könnte (also auch innerhalb einer zeile)

weiss jetzt gerade nicht welchen entwicklungsstand die cnc-option von repetier firmware haben, aber das mal so als idee was man machen könnte.