Hallo, Ich lese mit meinen Arduino die Led Impulse vom Stromzähler, klappt soweit alles auch. Da ich für eine weiteres Gerät die Signale auf ein S0 konformes Signal (30ms High, 30ms LOW haben muss stellt sich folgendes Problem. Der Zähler gibt pro kWh 10.000 Impulse aus. Nach der S0 Normung sind maximal 16,67 Hz erlaubt, was mit 6000W schon erreicht ist. Jetzt wollte ich in der Arduino Software einen Zähler verbauen, der nur jedes 10te Signal durchlässt, also aus 10.000 1.000 macht. Es folgt nun das Problem, dass er bei Beachtung der S0 Normung Nicht alle Impulse erfassen kann. (Outputsignal wird mit Delay 30ms definiert) Interruptionen sind leider nicht möglich, da die Auswertung über ein Analogeingang erfolgt. Könnt ihr mir weiterhelfen. Code folgt noch.
Rugby schrieb: > Es folgt nun das Problem, dass er bei Beachtung der S0 Normung Nicht > alle Impulse erfassen kann. (Outputsignal wird mit Delay 30ms definiert) > Interruptionen sind leider nicht möglich, da die Auswertung über ein > Analogeingang erfolgt. > Könnt ihr mir weiterhelfen. Code folgt noch. Was hat das Eine mit dem Anderem zutun? Ein Timerinterupt nach 30 ms geht nicht, wenn man den ADC verwendet? Das wäre mir neu. Bei 16 Hz geht das sogar one Timer. Ließ einfach mal "Blink without delay"!
Hier erstnochmal der Code:
1 | |
2 | const int ledPin13 = 13; |
3 | |
4 | int analog0; |
5 | |
6 | void setup() { |
7 | |
8 | pinMode(ledPin13, OUTPUT); |
9 | |
10 | |
11 | } |
12 | |
13 | void loop() { |
14 | |
15 | analog0 = analogRead(0); |
16 | |
17 | if (analog0 > 300){ |
18 | digitalWrite(ledPin13, HIGH); |
19 | delay(30); |
20 | } |
21 | else { |
22 | digitalWrite(ledPin13, LOW); |
23 | //delay(30); |
24 | }; |
25 | |
26 | } |
ja mein Problem ist es, dass er nicht jedes Signal erfasst, da er dann noch bei delay hängt. Und außerdem soll das Signal trotzdem noch S0 konform sein. Jemand eine Idee?
Rugby schrieb: > ja mein Problem ist es, dass er nicht jedes Signal erfasst, da er dann > noch bei delay hängt. Und außerdem soll das Signal trotzdem noch S0 > konform sein. Jemand eine Idee? Du beschreibst deinen Fehler schon selbst. Das delay() muss raus. Ersetze es durch millis oder wie es en "BlinWithoutDelay" beschrieben ist.
Hallo, ich habe da mal eben was zusammen geschrieben.
1 | const int ledPin13 = 13; |
2 | |
3 | unsigned int subS0Pulses = 0; |
4 | unsigned int lastAnalogValue = 0; |
5 | boolean generateOutput = false; |
6 | int outputPulseDuration = 0; |
7 | |
8 | const unsigned int s0PulsesRef = 10; // [sub S0 pulses] |
9 | // Make sure s0PulseOnTime/tickDuration has no remainder. |
10 | // Same is true for s0PulseOffTime/tickDuration. |
11 | const unsigned int tickDuration = 1; // [ms] |
12 | const unsigned int s0PulseOnTime = 30; // [ms] |
13 | const unsigned int s0PulseOffTime = 30; // [ms] |
14 | |
15 | void setup() |
16 | { |
17 | pinMode(ledPin13, OUTPUT); |
18 | } |
19 | |
20 | void loop() |
21 | { |
22 | // Detect rising edge |
23 | int analogValue = analogRead(0); |
24 | if((analogValue > 300) && |
25 | (lastAnalogValue <= 300)) |
26 | { |
27 | // Remember analog value for the next time. |
28 | subS0Pulses++; |
29 | } |
30 | lastAnalogValue = analogValue; |
31 | // Only every tenth pulse should generate an output impulse |
32 | if(subS0Pulses >= s0PulsesRef && generateOutput == false) |
33 | { |
34 | generateOutput = true; |
35 | outputPulseDuration = 0; |
36 | subS0Pulses -= s0PulsesRef; |
37 | } |
38 | // Generate output impulse |
39 | if(generateOutput == true) |
40 | { |
41 | if(outputPulseDuration < (s0PulseOnTime / tickDuration)) |
42 | { |
43 | digitalWrite(ledPin13, HIGH); |
44 | outputPulseDuration++; |
45 | } |
46 | else if((outputPulseDuration >= (s0PulseOnTime / tickDuration)) && |
47 | (outputPulseDuration < (s0PulseOffTime / tickDuration))) |
48 | { |
49 | digitalWrite(ledPin13, LOW); |
50 | outputPulseDuration++; |
51 | } |
52 | else |
53 | { |
54 | generateOutput = false; |
55 | } |
56 | } |
57 | delay(tickDuration); |
58 | } |
Ich habe weder eine IDE oder gar Hardware. Soll heissen: Da sind bestimmt noch einige Unstimmigkeiten - oder gar richtige Fehler - enthalten. Die Idee ist, dass du nicht darauf wartest, dass die Befehle nach einander abgearbeitet werden und das Programm erst danach erst einen erneuten Durchlauf der Schleife beginnt. Stattdessen wird die die Schleife alle <tickDuration>/1ms durchlaufen. Siehe ganz unten das delay(). Ein Durchlauf beginnt damit, dass der ADC ausgelesen wird. Anschliessend wird der aktuelle und der alte Wert verglichen ob es eine steigende Flanke gibt(die LED vom Zähler angeht). Wenn das der Fall ist, wird subS0Pulses um 1 erhöht. Danach wird überprüft ob schon genug Impulse gezählt wurden und gerade kein Impuls ausgegeben wird. Falls ja wird ein neuer Impuls angestossen. Dies geschieht im letzten IF-Block. Mit <outputPulseDuration> wird dabei gezählt, der wievielte Durchlauf von loop() es gerade ist und somit auch was gerade passieren soll. Es wird nur kurz der Ausgabe-Pin gesetzt und die Zählervariable erhöht - viel mehr passiert in diesem IF-Block nicht und das Programm läuft direkt in den delay(). CU, Jay
Danke Jay für den Code. Habe diesen Code ausgetestet. Nun habe ich das Problem, das nach dem 10ten Zählimpuls die LED leuchtet, dann aber nicht wieder ausgeht. Habe versucht im Code was zu ändern, leider ohne erfolg. Kanst du mir da bitte weiterhelfen? Mfg Rugby
Dazu sei gesagt, dass der Zähler immer wieder von 0 bis 10 hochzählt. Zählen klappt also.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.