Forum: Mikrocontroller und Digitale Elektronik Arduino Nano initialisiert immer wieder auf Startwert


von Andi S. (laserandi)


Lesenswert?

Hallo Leute,
ich möchte mit einem Arduino Nano die Pulse von einem S0-Energiezähler 
erfassen und per USB an einen PC übertragen. Hier mein Porgramm:
1
#define  S0in 2
2
3
volatile unsigned long pulse_total = 0;
4
volatile unsigned long alteZeit = 0;
5
int crontimer = 0;
6
 
7
void setup(){
8
  Serial.begin(9600);
9
  pulse_total = 100.0*2000; //Startwert in kWh auf Display ablesen x 2000
10
  pinMode(S0in, INPUT_PULLUP);
11
  attachInterrupt(digitalPinToInterrupt(S0in), onPulse, RISING);
12
}
13
14
void loop() {
15
  if(millis()/1000 > crontimer + 3){ //alle 3s Daten senden via RS232
16
    crontimer = millis()/1000;
17
    Serial.println(pulse_total);
18
  }
19
}
20
21
void onPulse(){
22
  if((millis() - alteZeit) > 21) { // innerhalb der Entprellzeit 21ms nichts machen
23
    alteZeit = millis(); // letzte Schaltzeit merken
24
    pulse_total++;
25
  }
26
}

Solange ich mit einem Programm (z.B. Minicom) den USB Port des Nano 
auslese, sehe ich wie er hoch zählt:
200000
200003
200006
100010....

Problem: Sobald ich Minicom schließe und anschließend wieder öffne fängt 
er wieder bei 200000 an.
Meine erste Vermutung war, dass es sich um ein Problem mit der 
Stromversorgung handelt aber auch wenn man ein Netzteil an +5V oder Vin 
anschließt bleibt das Problem bestehen.

Was kann ich sonst noch testen? - Mir gehen langsam die Ideen aus.
VG Andi

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Andi S. schrieb:
> Problem: Sobald ich Minicom schließe und anschließend wieder öffne fängt
> er wieder bei 200000 an.

Das ist normal, weil minicom am DTR Pin zappelt.
Also Reset mit einem 10µC unterbinden, oder die Flusskontrolle 
abschalten (kann minicom das?)

von Christian (christiankpunkt)


Lesenswert?

Auf der Platine ist ein Schaltkreis, der den Controller resettet wenn 
eine Terminal-Verbindung aufgebaut wird.

Man kann es Verhindern, wenn man in seinem Terminal-Programm die 
Hardware-Flusskontrolle deaktiviert. Oder man Durchtrennt die Leiterban, 
DTR-Ausgang des UART-Controllers.

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Arduino F. schrieb:
> 10µC

Ähmmm...
Ein C mit 10µF

von Jens M. (schuchkleisser)


Lesenswert?

Den Reset zu unterbinden ist ja nichtmal die Hälfte der Miete.

Kurze Stromzappler? Irgendwann mal kurz ausmachen zum Putzen? Oder oder 
oder?
Irgendein Töffel vergisst vor dem Anstecken das Handshaking 
abzuschalten, benutzt einen doofen Adapter oder Treiber, bingo.
Jedesmal hoppelt das Ding auf Null zurück, das ist ja Quatsch und völlig 
instabil.

Was es da braucht ist ein nichtflüchtiger Speicher, in den zumindest ab 
und an mal der aktuelle Stand gesichert wird, so das man z.B. nur 5 
Minuten verliert oder so.
Da muss man aber aufpassen, denn die haben teilweise arg begrenzte 
Schreibzyklen...
Am besten geht's mit einem FRAM, das sollte selbst bei Sekundenzyklen 
Jahrzehnte schaffen, bleibt nur noch das Risiko, das man bei so einem 
Reset genau den Schreibzyklus unterbricht und der Speicher korrupt wird.

von Stefan F. (Gast)


Lesenswert?

Immer schön einen Schritt nach dem anderen. Der Andi ist nicht auf der 
Flucht.

von Manfred P. (pruckelfred)


Angehängte Dateien:

Lesenswert?

Arduino F. schrieb:
> Das ist normal, weil minicom am DTR Pin zappelt.
So ist das.

> Also Reset mit einem 10µC unterbinden,
Pfuschlösung, das geht auch ordentlich.

Christian schrieb:
> Oder man Durchtrennt die Leiterban, DTR-Ausgang des UART-Controllers.

Garnicht nötig, sowohl China als auch das Original haben dort einen 
Kondensator, den man rausnehmen kann.

Der Nebeneffekt ist, dass man dann zum Upload der Software manuell den 
Reset betätigen muß.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Manfred P. schrieb:
> Pfuschlösung, das geht auch ordentlich.
Pfusch?
Reversibel!

Manfred P. schrieb:
> haben dort einen
> Kondensator, den man rausnehmen kann.
Pfusch!

Siehe:
Manfred P. schrieb:
> dass man dann zum Upload der Software manuell den
> Reset betätigen muß.

von Joe L. (joelisa)


Lesenswert?

Jens M. schrieb:
> Was es da braucht ist ein nichtflüchtiger Speicher, in den zumindest ab
> und an mal der aktuelle Stand gesichert wird, so das man z.B. nur 5
> Minuten verliert oder so.
> Da muss man aber aufpassen, denn die haben teilweise arg begrenzte
> Schreibzyklen...

Man müsste sich da was ausdenken, dass man den nichtflüchtigen Speicher 
auf viele Speicherzellen verteilen kann. "Wear Leveling" nennt sich das 
auf Fach-Chinesisch - und selbst Tante Google kann was dazu sagen.

Aber nun ist genug gespoilert ...

: Bearbeitet durch User
von Andi S. (laserandi)


Lesenswert?

Nachdem ihr mich darauf hingewiesen habt, sah ich auch das die Reset-LED 
immer aufblinkt wenn man minicom starte oder beendet.
Ich habe jetzt den Kondensator an DTR ausgelötet. So funktioniert alles 
wie gewollt.

Zum Thema Datensicherheit:
Ich hatte auch erst vor in gewissen Intervallen die Werte in den EEPROM 
zu schreiben. Da ich die Daten aber sowieso regelmäßig per USB auslese 
und speichere habe ich das wieder verworfen.

Vielen Dank für Eure Hilfe!!!

: Bearbeitet durch User
von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Andi S. schrieb:
> Reset-LED

Ich kenne keinen Nano mit einer Reset Led

von Steve van de Grens (roehrmond)


Lesenswert?

Andi S. schrieb:
> Ich habe jetzt den Kondensator an DTR ausgelötet. So funktioniert alles
> wie gewollt.

Jetzt musst du zum Flashen den Reset-Knopf manuell drücken (falls das 
nicht klar war). Oder du nimmst einen ISP Adapter.

: Bearbeitet durch User
von Εrnst B. (ernst)


Lesenswert?

Generell ein paar Verbesserungs-Vorschläge:
1
volatile unsigned long alteZeit = 0;

ist unnötig. Schöner:
1
void onPulse(){
2
  static uint32_t alteZeit;
3
  if((millis() - alteZeit) > 21) { // innerhalb der Entprellzeit 21ms nichts machen
4
    alteZeit = millis(); // letzte Schaltzeit merken
5
...

Und:
1
void loop() {
2
  if(millis()/1000 > crontimer + 3){ //alle 3s Daten senden via RS232

Überleg dir, was passiert sobald millis() seinen 32-bit-Rollover hat.

Schöner:
1
  if ((millis() - crontimer)>3000) {
2
    crontimer=millis();
(Also ananlog zu "alteZeit" im onPulse)

von Jens M. (schuchkleisser)


Lesenswert?

Andi S. schrieb:
> Da ich die Daten aber sowieso regelmäßig per USB auslese
> und speichere habe ich das wieder verworfen.

Dann solltest du die Übertragung einfach auf die Anzahl der Pulse seit 
dem letzten Auslesen ausführen und den Stand am Auslesegerät festhalten.
Da kannst du dann auch bequemer den aktuellen Stand nachhalten, falls 
dein Adapter mal was vergessen hat.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Εrnst B. schrieb:
> Überleg dir, was passiert sobald millis() seinen 32-bit-Rollover hat.
Es passiert viel öfter Seltsames. Nämlich schon, wenn "geschickt" 
zwischen
*if(millis()/1000 > crontimer + 3){*  und  *crontimer = millis()/1000;*
der millis-Zähler einen der allsekündlichen Tausender-Überläufe hat. 
Dann wird nämlich eine "Schaltsekunde" eingelegt, wenn z.B. zum 
Zeitpunkt der if-Abfrage millis() noch 12999 hatte, beim Berechnen des 
neuen crontimer Werts aber schon auf 13000 weitergezählt hat.

Εrnst B. schrieb:
> Schöner:
>   if ((millis() - crontimer)>3000) {
>     crontimer=millis();
Und noch viel viel schöner ist es, wenn man am Anfang der Mainloop ein 
einziges Mal den millis()-Zeitstempel abholt und den Rest im Zyklus mit 
derselben Zeit rechnet:
1
unsigned long jetzt, crontimer = 0, t5s = 0;
2
3
void loop() {
4
  jetzt = millis(); // einmalig Zeitstempel für diesen Schleifendurchlauf abholen
5
6
  if (jetzt - crontimer > 3000) { // alle 3s ...
7
    crontimer = jetzt;
8
    Serial.println(pulse_total);
9
  }
10
11
  if (jetzt - t5s > 5000) { // alle 5 s
12
    t5s = jetzt;
13
    :
14
  }
15
}
Und so richtig schön wäre es dann, wenn man am Anfang der Schleife die 
Eingänge ebenfalls auf ein Prozessabbild einlesen und alle berechneten 
Änderungen erst am Schluss der Schleife auf die Ausgänge schreiben 
würde. Dann hat man nämlich die vielmillionenfach erprobte 
Vorgehensweise einer SPS. Da kann zwar die Zykluszeit der SPS insgesamt 
zu langsam sein, es gibt aber kein seltsames Timingverhalten wegen einer 
zum Programmablauf hinzugefügten Funktion.

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
Noch kein Account? Hier anmelden.