Sensorwert auslesen und Aktion auslösen

Hallo Zusammen,

ich bin neu hier im Forum und habe erst vor kurzem mit der Programmierung von Arduino angefangen.
Folgendes Problem habe ich.

ich möchte ein Sensorwert aus ein Drehpoti überwachen, dass wenn der Wert steigt Aktion A auslöse, und wenn der Wert abfällt dann Aktion B auslöse.

bisher habe ich nur keine Idee wie ich "Wert steigt" und "Wert abfällt" in mein Code implementieren kann.

// Pin Definitionen
const int dirPin = 8;
const int stepPin = 9;
const int enPin = 7;
int speed = 100;

void setup() {
    // start Serial for Poti
Serial.begin(9600);
// Setze die Pin-Modi
  pinMode(dirPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(enPin, OUTPUT);
  // Aktiviere den Treiber
  digitalWrite(enPin, LOW);
}

void loop() {
  // put your main code here, to run repeatedly:

 while(true) {
           int Value = analogRead(0);
               Value = map(Value, 0, 1023, 0, 100);
               Serial.println(Value);
    if (Value<10) {
      digitalWrite(dirPin, HIGH); // HIGH = Vorwärts, LOW = Rückwärts
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(1000); // Pulsdauer
      digitalWrite(stepPin, LOW);
      delayMicroseconds(100); // Pause zwischen den Pulsen
    }
    if (Value>60) {
      digitalWrite(dirPin, LOW); // HIGH = Vorwärts, LOW = Rückwärts
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(1000); // Pulsdauer
      digitalWrite(stepPin, LOW);
      delayMicroseconds(100); // Pause zwischen den Pulsen

 }
}
}

Ihr Thema wurde in den deutschen Bereich des Forums verschoben. Bitte verwenden Sie die englische Sprache in den englischen Kategorien des Forums.

Original: UNO R4 Minima - Arduino Forum

Danke für es verschieben. Das war mein erster Beitrag und war mir so nicht bewusst :slight_smile:

Grundprinzip:

  • Miss den Wert
  • Vergleiche den Wert mit dem alten Wert - daraus ergibt sich niedriger, gleich oder höher
  • Merk dir den gemessenen Wert als alten Wert (fürs nächste mal)

Vielen dank für die schnelle Antwort
kannst du mir in einem kurzen Beispiel zeigen, wie das zu Implementieren ist ?

constexpr uint8_t adcPin = A0; // Input

void readADC() {
  static int previousADC = 0;
  int currentADC = analogRead(adcPin);
  Serial.print(currentADC);
  Serial.print('\t');
  Serial.print(previousADC);
  Serial.print('\t');
  if (currentADC < previousADC) {
    Serial.println("kleiner");
  }
  else if (currentADC > previousADC) {
    Serial.println("größer");
  }
  else {
    Serial.println("gleich");
  }
  previousADC = currentADC;
}

void setup() {
  Serial.begin(115200);
}

void loop() {
   readADC();
   delay(1000); // dirty delay to slow down for demo mode only
}

Potentiometer - Wokwi ESP32, STM32, Arduino Simulator

wie kann ich aber den momentanen Wert auf PreviousADC speichern ? in dein Beispiel ist es einfach auf 0 gesetzt.

Da der Analog-Digital-Converter (ADC) um ein Bit zappelt, und bei echten Sensoren evtl. ein noch größeres Rauschen nicht zu vermeiden ist, kann man das Beispiel etwas modifizieren:

constexpr byte h =1; // Hysterese 

  if (currentADC < previousADC-h) {
    Serial.println("kleiner");
    previousADC = currentADC;
}
  }
  else if (currentADC > previousADC+h) {
    Serial.println("größer");
    previousADC = currentADC;
}
  }
  else {
    Serial.println("gleich");
  }

Wo previousADC gesetzt wird, siehst du.

Der Trick ist, dass static bewirkt dass die Variable Ihren Wert behält,
und dass das = in der Definition kein normaler Zuweisungsoperator, sondern nur die Erst-Initialisierung ist.

Das macht bereits loop()

Grüße Uwe

Danke für die ausführliche Antwort.
bei mir handelt es sich um ein Drehprotentiometer und die Skalierung der Wert auf 0 bis 100 funktioniert ganz gut ohne eine Hysterese einzubauen.

wie kann ich den Wert "PreviusValue" speichern um mit dem momentanen "Value" zu vergleichen.

while(true) {
           int Value = analogRead(0);
               Value = map(Value, 0, 1023, 0, 100);
               Serial.println(Value);
    if (Value<10) {
      digitalWrite(dirPin, HIGH); // HIGH = Vorwärts, LOW = Rückwärts
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(1000); // Pulsdauer
      digitalWrite(stepPin, LOW);
      delayMicroseconds(100); // Pause zwischen den Pulsen
    }
    if (Value>60) {
      digitalWrite(dirPin, LOW); // HIGH = Vorwärts, LOW = Rückwärts
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(1000); // Pulsdauer
      digitalWrite(stepPin, LOW);
      delayMicroseconds(100); // Pause zwischen den Pulsen

 }
}
}

Warum ignorierst Du die Hinweise aus #8 und #9?

Gruß Tommy

Das hat dir @noiasca in #9 gezeigt

static int previousValue;
int Value = map(analogRead(A0),0,1024,0,100);  // auf 100 Werte ( 0 .. 99 ) normiert 
if ( Value != previousValue ) {
    previousValue = Value;
    // hier nur einmal bei einer Änderung 
}

Wenn du die Bedeutung von static nicht lernen willst, kannst du stattdessen auch eine globale Variable nehmen.

Sorry alle, aber das hat wirklich nichts mit wollen zu tun. Ich bin eher ein SPS Programmierer und hatte bis vor 3 Tage mit c++ nicht viel zu tun gehabt.

ich habe nun den Code angepasst. Folgendes sollte passieren.
wenn der Value steigt, dann fahre ich den Motor Vorwärts
wenn der Value abfällt, dann fahre ich Motor Rückwärts.

leider funktioniert das aber nicht wirklich.

// Pin Definitionen
const int dirPin = 8;
const int stepPin = 9;
const int enPin = 7;


static int previousValue;
int Value = map(analogRead(A0), 0, 1023, 0, 100);

void setup() {
    // start Serial for Poti
Serial.begin(9600);
// Setze die Pin-Modi
  pinMode(dirPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(enPin, OUTPUT);
  // Aktiviere den Treiber
  digitalWrite(enPin, LOW);
}

void loop() {
  // put your main code here, to run repeatedly:

 while(true) {

    if (Value<previousValue) {
      digitalWrite(dirPin, HIGH); // HIGH = Vorwärts, LOW = Rückwärts
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(1000); // Pulsdauer
      digitalWrite(stepPin, LOW);
      delayMicroseconds(100); // Pause zwischen den Pulsen
    }
    if (Value>previousValue) {
      digitalWrite(dirPin, LOW); // HIGH = Vorwärts, LOW = Rückwärts
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(1000); // Pulsdauer
      digitalWrite(stepPin, LOW);
      delayMicroseconds(100); // Pause zwischen den Pulsen

 }
}
}

Ist Dir klar, was Du da programmiert hast? Denk mal darüber nach. Dann kommt Dir vielleicht in den Sinn, warum das nicht funktionieren kann.

Googel mal nach C/C++ und Gültigkeitsbereich von Variablen. Was ist eine Zuweisung und was macht while(true) ?

Mal abgesehen davon, dass Dir schon gesagt wurde, der Ausdruck while(true) ist fehl am Platze weil schon void loop() wie eine Endlosschleife funktioniert.

Geh es schrittweise an.

  1. hab ich begonnen mit der Serial Debug Ausgaben einzubinden. Das ist ein guter Anfang um zu sehen was eigentlich passiert.
  2. Du vergleichst value mit previousValue ... nice.
    Was steht in den Variablen zum Zeitpunkt des Vergleiches?
  3. stell dir die Frage, was notwendig wäre damit in der nächsten Iteration vieleicht was anderes drinnen steht

Hier ist ein einfaches Beispiel, bei dem ein Schrittmotor entsprechend der Potentiometer Stellung bewegt wird. Eine volle Umdrehung ist möglich.

//
// Globale Konstanten definieren
//
constexpr byte DIR_PIN {4};
constexpr byte STEP_PIN {5};
constexpr byte ANALOG_PIN {A0};

constexpr unsigned int STEPS_PER_REVOLUTION {200};
constexpr unsigned int STEPPER_DELAY_US {2000};   // Mikroskunden!

// Struktur für die Daten, die zur Steuerung des Steppers erforderlich sind deklarieren
struct Steps {
  unsigned int analogValue;
  unsigned int prevAnalogValue;
  unsigned int position;
  unsigned int count;
};

//
// Feststellen ob eine Bewegung im Uhrzeigersinn (CW) oder Gegenuhrzeigersinn (CCW)
// erforderlich ist. Das Ergebnis ist abhängig von dem gemessenen Potentiometerwert
//
void prepareSteps(byte pin, Steps& st) {
  if (st.analogValue > st.prevAnalogValue) {
    digitalWrite(pin, HIGH);
    st.count = st.analogValue - st.position;
    st.position += st.count;
  } else {
    digitalWrite(pin, LOW);
    st.count = st.position - st.analogValue;
    st.position -= st.count;
  }
  st.prevAnalogValue = st.analogValue;
}

//
// Den Schrittmotor um die errechnete Anzahl an Schritten CW oder CCW bewegen.
//
void driveStepper(byte pin, unsigned int stepCount) {
  for (size_t x = 0; x < stepCount; ++x) {
    digitalWrite(pin, HIGH);
    delayMicroseconds(STEPPER_DELAY_US);
    digitalWrite(pin, LOW);
    delayMicroseconds(STEPPER_DELAY_US);
  }
}

void setup() {
  pinMode(STEP_PIN, OUTPUT);
  pinMode(DIR_PIN, OUTPUT);
}

void loop() {
  static Steps steps {0, 0, 0, 0};   // Strutur anlegen und Member mit 0 initialisieren.

  // Potentiometerwert lesen und auf die maximale Schrittzahl für eine Umdrehung des
  // Steppermotors umrechnen.
  steps.analogValue = map(analogRead(ANALOG_PIN), 0, 1023, 0, STEPS_PER_REVOLUTION);

  // Wenn sich der gelesenen Analogwert verändert hat den Stepper entsprechend bewegen.
  if (steps.analogValue != steps.prevAnalogValue) {
    prepareSteps(DIR_PIN, steps);
    driveStepper(STEP_PIN, steps.count);
  }
}

Zum Ausprobieren:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.