Längenmessgerät

Moin,
ich hoffe mir kann jemand bei meinem Problem helfen.
Ich möchte für ein Projekt das abrollen eines Kabels über einen induktiven Sensor erfassen.
Auf einer Rolle habe ich kleine Stahlplättchen aufgeklebt um damit den Sensor zu aktivieren.
Bei meinem Programm habe ich erkannt, dass ich beim erfassen des Signals aufpassen muss, dass er bei der Signalgebung nicht dauerhaft HIGH sendet, damit er nicht bei einem Signal mehrfach den Abstand zählt.
Hier zeigt sich aber mein Problem, wenn ich mit meinem Programm den sensorstate abfrage und dieser auf 1 also HIGH schaltet, dauert es zu lange bis das Programm diesen wieder auf LOW setzt, um den nächsten Schritt zu zählen.
Kann mir vielleicht jemand helfen, dies zu verbessern?

 #include <LiquidCrystal.h>

LiquidCrystal lcd(13, 12, 2, 3, 4, 5);

int taster_val;
int old_val;

byte sensorpin = 8;
int sensorstate;
int oldstate;
double Laenge;
double Laenge_neu;
double Laenge_alt;
float Abstand;

//LCD Belegung
int RS = 13;                                                                                                //RS - LCD
int E = 12;                                                                                                 //E - LCD
int DB4 = 2;                                                                                                //Bit0 - LCD
int DB5 = 3;                                                                                                //Bit1 - LCD
int DB6 = 4;                                                                                                //Bit2 - LCD
int DB7 = 5;                                                                                                //Bit3 - LCD

void setup() {
  Serial.begin(9600);

  pinMode(sensorpin, INPUT);
  pinMode(DB4, OUTPUT);                                                                                     //Definition der Variable DB4 als Output
  pinMode(DB5, OUTPUT);                                                                                     //Definition der Variable DB5 als Output
  pinMode(DB6, OUTPUT);                                                                                     //Definition der Variable DB6 als Output
  pinMode(DB7, OUTPUT);                                                                                     //Definition der Variable DB7 als Output

  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.write("Laenge = ");
  lcd.print(Laenge, 1);
  lcd.write(" m");
}

void loop() {
  SensorFunktion();
}

//***********************************************************************
void SensorFunktion() {
  sensorstate = digitalRead(sensorpin);
  if (sensorstate != oldstate) {
    Serial.print("Sensorstate");
    Serial.println(sensorstate);
    oldstate = sensorstate;
  }
  Abstand = 10;
  taster_val = digitalRead(sensorpin);
  if (taster_val == HIGH && taster_val != old_val) {
    Laenge = (Laenge + Abstand);
    Serial.print("Sensorstate");
    Serial.println(sensorstate);
    Serial.print("Laenge = ");
    Serial.print(Laenge * 0.01, 1);
    Serial.println("m");
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.write("Laenge = ");
    lcd.print(Laenge * 0.01, 1);
    lcd.write(" m");
    old_val = taster_val;
  } else {
    old_val = taster_val;
  }
}

Es scheint, du könntest einen Knopf library gebrauchen (zB OneButton von Matthias Hertel), was Ihr Leben einfacher machen würde, um Zustandsänderungen zu folgen

Danke für den Vorschlag. Allerdings ist mein Versuch es zu implementierennicht erfolgreich gewesen. Hast du einen Vorschlag, wie ich es machen könnte? Muss ich beim einfügen einer neuen Library den Sketch neu anfangen?

Sag mal...
Was ist das für ein Sensor?
Wie ist der Aufbau? (Zeichnung)

Das hört sich sehr danach an, als würde Dir ein PULLUP /PULLDOWN Widerstand fehlen.

Vielleicht würde so etwas funktionieren

#include <OneButton.h>    //  http://www.mathertel.de/Arduino/OneButtonLibrary.aspx
const byte sensorPin = 8;
OneButton sensor(sensorPin, false, false);  // Kein eingebauter PULLUP

#include <LiquidCrystal.h>
LiquidCrystal lcd(13, 12, 2, 3, 4, 5);

float Laenge = 0;
const float Abstand = 10;

void printLaenge() {
  lcd.setCursor(9, 0);
  lcd.print(F("       "));
  lcd.setCursor(9, 0);
  lcd.print(Laenge * 0.01, 1);
  lcd.write(" m");
}

void action() {
  Laenge += Abstand;
  printLaenge();
}

void setup() {
  pinMode(sensorPin, INPUT);
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.write("Laenge = ");
  printLaenge();
  sensor.attachClick(action);
}

void loop() {
  sensor.tick();
}

Hallo,
wie schnell kommen denn die Impulse?
das Programn mit allen if-bedingungen und Ausgaben auf lcd und seriellen-Monitor ist in 0,05 Sekunden abgearbeitet.
Also wie viele Impulse pro Sekunde müssen gezählt werden?

Wenn es wiklich seeehr viele Impulse pro Sekunde (10000 oder noch mehr) sind dann könnte man einen Interrupt verwenden.
Mit Interrupts programmieren hat aber auch seine Eigenheiten.

Danke für den Sketch. Allerdings habe ich beim ausprobieren gemerkt, dass er beim Auslösen des Pins nicht zählt bzw den Zustand nicht ändert. Er führt den Befehl einmal aus und gibt die Länge von 0,0 m an.

Die hohe Impulsrate war dazu gedacht, dass das Programm schneller aus dem Sensorstate 1 kommt. Das dauert sonst noch länger. Er bedient sich bei meinem Sketch anscheinend an einer festen Zeit, die ich nicht beeinflussen konnte.


Der induktive Sensor ist der IS 05 A1 S1 von Datalogic

Der Sensor hängt an 12V?
Mit dem Spannungsteiler 4,7k / 2,7k müsste passen.
Der schafft 2000Hz.

Hm.
Hast Du mal gemessen, wie lange Dir das HIGH am PIN stehen bleibt?

Ja er hängt an 12 V, da ich für den Arduino ein 12 V Netzteil habe. Als Versuche, kann ich die Spannung des Sensors aber auch auf 10V verringern.
Der Wert für High hängt von der Auslösedauer des Sensors ab. Wenn er zu lange auf High bleibt kann es bis zu 8 Sek dauern, bis er wieder auf LOW schaltet.
Selbst bei kurzer Auslösung braucht er min 1 Sek bis er auf Low schaltet

Der Teiler und die 12V sind schon ok. da kommen 4,3xx V raus - passt.

Wenn der 2kHz mitmachen soll, muss das schneller gehen.
Was passiert, wenn der Teiler mit 2,2k / 1,5k angesetzt wird?

Versuche es mit

OneButton-Sensor (sensorPin); // PULLUP
  pinMode(sensorPin, INPUT_PULLUP);

Welche "Impulsrate?"

Was meinst du mit Impulsrate? Ich verzichte jetzt aufs spekulieren.
Ich hätte es gerne ganz präzise. Wer hat da was für eine "Impulsrate?"
Oder was ist mit "Impulsrate" gemeint?

Welches "Sensortaste 1"?
In dem Programm das im post #1 gepostet wurde gibt es eine function
void SensorFunktion()

Also so viel Präzision muss in der Kommunikation schon sein.

Die function SensorFunktion() ist in 0,05 Sekunden abgearbeitet daran kann es also nicht liegen.

vgs

Entschuldigung, habe es mit einem vorher angelegten Sketch verwechselt bei dem ich noch einen Entprellungsbefehl über lastdebounce eingegeben habe. Mein Fehler.
Ich meinte in dem Fall also den delay bis er eine neue Eingabe entgegennimmt.

Das funktioniert leider auch nicht, da er dann das Signal am Eingang invertiert.

Wenn ich den Pullup rausnehme,, kann ich durch schnelles zuschalten des Sensors den Abstand nur manchmal dazuaddieren.

Bei Start des Programms ohne den Pullup scheint er auch ohne Einwirkung zwischen 0 und 1 zu wechseln.
14:36:34.091 -> Sensorstate0
14:36:34.183 -> Länge 0.00
14:36:34.276 -> Sensorstate0
14:36:34.369 -> Länge 0.00
14:36:34.509 -> Sensorstate0
14:36:34.603 -> Länge 0.00
14:36:34.697 -> Sensorstate0
14:36:34.791 -> Länge 0.00
14:36:34.886 -> Sensorstate0
14:36:34.981 -> Länge 0.00
14:36:35.077 -> Sensorstate1
14:36:35.168 -> Länge 0.00
14:36:35.307 -> Sensorstate0
14:36:35.401 -> Länge 0.00
14:36:35.496 -> Sensorstate1
14:36:35.591 -> Länge 0.00
14:36:35.684 -> Sensorstate0
14:36:35.777 -> Länge 0.00
14:36:35.918 -> Sensorstate1
14:36:36.013 -> Länge 0.00
14:36:36.106 -> Sensorstate0
14:36:36.201 -> Länge 0.00
14:36:36.293 -> Sensorstate1
14:36:36.387 -> Länge 10.00
14:36:36.479 -> Sensorstate1
14:36:36.620 -> Länge 10.00
14:36:36.712 -> Sensorstate1
14:36:36.805 -> Länge 10.00
14:36:36.897 -> Sensorstate1
14:36:36.990 -> Länge 10.00
14:36:37.082 -> Sensorstate1
14:36:37.217 -> Länge 10.00
14:36:37.308 -> Sensorstate1
14:36:37.400 -> Länge 10.00
14:36:37.492 -> Sensorstate1
14:36:37.585 -> Länge 10.00
14:36:37.725 -> Sensorstate1
14:36:37.819 -> Länge 10.00
14:36:37.911 -> Sensorstate1
14:36:38.005 -> Länge 10.00
14:36:38.098 -> Sensorstate1
14:36:38.192 -> Länge 10.00
14:36:38.330 -> Sensorstate1
14:36:38.422 -> Länge 10.00
14:36:38.514 -> Sensorstate0
14:36:38.606 -> Länge 10.00
14:36:38.698 -> Sensorstate0
14:36:38.791 -> Länge 10.00
14:36:38.929 -> Sensorstate0
14:36:39.021 -> Länge 10.00
14:36:39.113 -> Sensorstate1
14:36:39.204 -> Länge 10.00
14:36:39.295 -> Sensorstate1
14:36:39.433 -> Länge 10.00
14:36:39.526 -> Sensorstate1
14:36:39.620 -> Länge 20.00
14:36:39.715 -> Sensorstate1
14:36:39.808 -> Länge 20.00
14:36:39.901 -> Sensorstate1
14:36:40.041 -> Länge 20.00
14:36:40.133 -> Sensorstate1
14:36:40.227 -> Länge 20.00
14:36:40.320 -> Sensorstate1
14:36:40.411 -> Länge 20.00

Kannst Du mal bitte die Bilder rausnehmen und dafür im Seriellen Monitor einmal reinklicken, STRG-A, STRG-C, und hier in Codetags mit STRG-V einfügen.... Ggfls. kürzen.

Kannst Du mal folgenden Sketch draufspielen:

const byte sensorpin = 8;
void setup() {
  Serial.begin(115200);
  Serial.println(F("Start..."));
  pinMode(sensorpin, INPUT);
  //pinMode(sensorpin, INPUT_PULLUP);
}

void loop() {
  SensorFunktion();
}

void SensorFunktion()
{
  static bool sensorstate = false;
  static unsigned long lastmicros = 0;
  double Laenge = 0;
  float Abstand = 10.0;

  if (digitalRead(sensorpin)) // PIN HIGH?
  {
    if (!sensorstate)         // noch LOW?
    {
      Serial.print(F("Errechnete µs1: "));
      Serial.println(micros() - lastmicros);
      Laenge = (Laenge + Abstand);
      Serial.print("Laenge = ");
      Serial.print(Laenge * 0.01, 1);
      Serial.println("m");
      sensorstate = !sensorstate; // toggle
      lastmicros = micros();
    }
  }
  else if (sensorstate)       // PIN LOW && state HIGH?
  {
    Serial.print(F("Errechnete µs2: "));
    Serial.println(micros() - lastmicros);
    sensorstate = !sensorstate; // toggle
    lastmicros=micros();
  }
}

Das sieht dann auf dem SerMon so aus:

14:39:45.508 -> Errechnete µs1: 7307228
14:39:45.508 -> Laenge = 0.1m
14:39:45.508 -> Errechnete µs2: 436
14:39:45.508 -> Errechnete µs1: 2188
14:39:45.508 -> Laenge = 0.1m
14:39:45.508 -> Errechnete µs2: 1444
14:39:45.607 -> Errechnete µs1: 101452
14:39:45.607 -> Laenge = 0.1m
14:39:45.607 -> Errechnete µs2: 128
14:39:45.607 -> Errechnete µs1: 616
14:39:45.607 -> Laenge = 0.1m
14:39:45.740 -> Errechnete µs2: 136768

Warum variiert die Zeit bis zur Timestamp Errechnete µs2: so stark?

15:03:57.924 -> Start...
15:03:57.924 -> Errechnete µs1: 208
15:03:57.924 -> Laenge = 0.1m
15:03:57.924 -> Errechnete µs2: 8536
15:03:57.924 -> Errechnete µs1: 9008
15:03:57.924 -> Laenge = 0.1m
15:03:57.971 -> Errechnete µs2: 10216
15:03:57.971 -> Errechnete µs1: 9028
15:03:57.971 -> Laenge = 0.1m
15:03:57.971 -> Errechnete µs2: 10208
15:03:57.971 -> Errechnete µs1: 9076
15:03:57.971 -> Laenge = 0.1m
15:03:58.016 -> Errechnete µs2: 10140
15:03:58.016 -> Errechnete µs1: 9112
15:03:58.016 -> Laenge = 0.1m
15:03:58.016 -> Errechnete µs2: 10132
15:03:58.016 -> Errechnete µs1: 9084
15:03:58.016 -> Laenge = 0.1m
15:03:58.016 -> Errechnete µs2: 10128
15:03:58.063 -> Errechnete µs1: 9100
15:03:58.063 -> Laenge = 0.1m
Ich kann dann bei Signal High vom Sensor den Zustand halten, aber er zählt nicht. Er gibt immer 0,1m aus.
Er fängt auch nicht bei 0 an.