DRV8871 fährt nicht solange Analoginput abgefragt wird

Ich habe ein sehr interessantes Verhalten von meinem Arduino Nano feststellen können.

Zur Erklärung.

Ich habe ein 12 V Signal entweder an D6 oder D5 anliegen. Wenn dem so ist, soll nach der Abfrage die Variable "DacState" hoch bzw. runter gezählt werden.

Wenn sich "DacState" ändert soll ein 12 V Motor mit einem LMD298 gefahren werden. Der Motor verfügt einen Potentiometer anhand dessen ich die korrekte Stellung herausfinden kann.

Der DacState (welcher seinen Namen durch etwas anderes bekommen hat) gibt mir die Informationen, nach einer Berechnung, ob der Motor nach links oder rechts gefahren werden soll.

Alle Dinge funktionieren getrennt von einander jedoch nicht wenn 12V an Pin 5 oder 6 anliegen.
Der DacState wird hoch bzw. runter gezählt und die Logik stellt auch fest, dass der Motor nach rechts oder nach links gefahren wird. Direkt unter der Ausgabe kommen die Befehle für den LMD298 Motor treiber aber dieser fährt nicht.

Erst wenn an Pin 5 oder 6 keine Spannung mehr anliegt, fährt der Motor an die gewünschte Position.

Hat jemand ne Ahnung warum?

Hier eine gestrippte Version meines Codes:

#include <Arduino.h>
#include <MyMCP4725.h>

#define DIRA 6
#define DIRB 5

int EcuMdMinusPIN = A1;
int EcuMdPlusPIN = A0;
int ExupPotPIN = A2;

float dacState = 0.0f;

int ECUMDPlus;  //Signal-open
int ECUMDMinus; //Signal-close
float ExupPotVoltage = 0.0f;

float lowerTarget = 0.0f;
float higherTarget = 0.0f;

float DRVPower = 120; // DRV Power
float offsetExup = 10.0f;

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

  pinMode(DIRA, OUTPUT);
  pinMode(DIRB, OUTPUT);

  digitalWrite(DIRA, LOW);
  digitalWrite(DIRB, LOW);
}

void loop()
{

  ECUMDPlus = analogRead(EcuMdPlusPIN);
  ECUMDMinus = analogRead(EcuMdMinusPIN);
  ExupPotVoltage = analogReadToVoltage(analogRead(ExupPotPIN));

  float targetExupVoltage = cfg.maxDacVoltage - (dacState * cfg.dacStepsValue);
  lowerTarget = targetExupVoltage - (targetExupVoltage / offsetExup);
  higherTarget = targetExupVoltage + (targetExupVoltage / offsetExup);

  //Wenn Ziel unterhalb des max. Wertes der geschlossenen Klappe liegt
  if (lowerTarget < cfg.maxExupVoltageOpen)
  {
    higherTarget += lowerTarget;
  }

  //Wenn Ziel oberhalb des max. Wertes der offenen Klappe liegt
  if (higherTarget > cfg.maxExupVoltageClose)
  {
    lowerTarget -= abs(cfg.maxExupVoltageClose - higherTarget);
  }

  if (lowerTarget < ExupPotVoltage && ExupPotVoltage < higherTarget)
  {
#ifdef DEBUG
    Serial.println("Klappe ist genau richtig");
#endif
    digitalWrite(DIRA, LOW);
    digitalWrite(DIRB, LOW);
  }
  else if (ExupPotVoltage > higherTarget)
  {
#ifdef DEBUG
    Serial.println("Fahre klappe auf");
#endif
    digitalWrite(DIRA, LOW);
    digitalWrite(DIRB, DRVPower);
  }

  else if (lowerTarget > ExupPotVoltage)
  {
#ifdef DEBUG
    Serial.println("Fahre klappe zu");
#endif
    digitalWrite(DIRA, DRVPower);
    digitalWrite(DIRB, LOW);
  }

  if (ECUMDMinus > 100)
  {
    if (dacState < cfg.dacSteps)
    {
#ifdef DEBUG
      Serial.println("DACSTEP ++");
#endif
      dacState++;
    }
  }

  if (ECUMDPlus > 100)
  {
    if (dacState > 0)
    {
#ifdef DEBUG
      Serial.println("DACSTEP --");
#endif
      dacState--;
     
    }
  }
}

Dann ist Dein Nano mit Sterben beschäftigt.

Gruß Tommy

Hi,

da hast du wohl Recht :smiley:

Ich habe vergessen zu erwähnen, dass die 12 vorher durch einen Spannungsteiler auf 5V runter geregelt werden

Wer oder was ist das?

Ausserdem sind Pin 5 und 6 OUTPUT Pins, die helfen dem Arduino auch beim Sterben, wenn du sie direkt mit GND oder Vcc verbindest.

Das passt nicht zusammen. 5 und 6 sind Ausgänge. Wo liegt also dein 12V-Signal an?

DRVPower ist als float mit Initialwert 120 definiert. Was willst Du damit in einem digitalWrite? Das macht keinen Sinn.

Wozu überhaupt so viele float? Auch analogRead gibt dir nur einen Integer zurück.

Oh da hab ich wohl paar Sachen durcheinander gebracht.

DIRA und DIRB sind OUTPUT Pins welchen den LMD298 ansteuern. Dieser gibt dann externe 12V die an den LMD angeschlossen sind an den Motor weiter.

an A1 und A0 habe ich die runtergeregelten 12V anliegen welche entscheiden ob der LMD linksrum oder rechtsrum fährt.

Das DRVPower ein Float ist, ist ein fehler von mir. Sollte ein int Wert sein.

cfg ist ein typedef struct welcher einfach paar Variablen beinhaltet die in den EEPROM gespeichert werden.

Also bitte weiter strippen, aber eventuell mit Testausgaben zeigen/sehen, was passiert.

Die Logausgabe ist wie folgt, wenn 5V an einem Inputtpin anliegen:

DACSTEP++
Fahre klappe auf
DACSTEP++
Fahre klappe auf
DACSTEP++
Fahre klappe auf
DACSTEP++
Fahre klappe auf
DACSTEP++
Fahre klappe auf
DACSTEP++
Fahre klappe auf
DACSTEP++
Fahre klappe auf
DACSTEP++
Fahre klappe auf
DACSTEP++
Fahre klappe auf
Fahre klappe auf
Fahre klappe auf
Fahre klappe auf
Fahre klappe auf
Fahre klappe auf
Klappe ist genau richtig
Klappe ist genau richtig
Klappe ist genau richtig
Klappe ist genau richtig
Klappe ist genau richtig
Klappe ist genau richtig

Und wie gesagt er fährt erst an den Motor zu fahren, wenn der Inputpin keine Spannung mehr anliegen hat

Also...
Für mich sprichst du in Rätseln...

Ich hab es mal weiter runter gebrochen:

if (ECUMDMinus > 100 )
  {
    if (dacState < cfg.dacSteps)
    {
      dacState++;
      digitalWrite(DIRA, HIGH);
      digitalWrite(DIRB, LOW);
    }
  }
  else
  {
    digitalWrite(DIRA, LOW);
    digitalWrite(DIRB, LOW);
  }

Bei dem Code würde solange auf ECUMDMinus Spannung anliegt der Motor laufen. Sobald die Spannung weg ist, wird der Motor gestoppt.

Die Realität zeigt, dass der Motor nicht fährt, außer ich gebe ganz kurze Impulse auf die Leitung. Dann fährt der Motor immer nur ein Stück (Weil der else Block den Motor wieder stoppt.

Wieso läuft der Motor nicht dauerhaft?

Offensichtlich ist die Bedingung (ECUMDMinus > 100 ) doch nicht so Wahr, wie du glaubst. Denn sonst könnte das else ja nicht greifen.

Doch die Bedingung ist so wahr wie ich mir das vorstelle.

Ich habe beim else ebenfalls ein Serial.println hinzugefügt welcher nur dann ausgibt, wenn keine Spannung anliegt.

Nunja....

Da if und else IMMER zuverlässig funktionieren.....
Ist der Fehler an anderer Stelle.

Klarer:
Du schaltest den Motor an anderer Stelle ab.

Das If und Else funktioniert auch zuverlässig.

Denk dir den Else Block mal komplett weg. Dann wäre das Verhalten so, dass solange ECUMDMinus > 100 ist er den Motor nicht fährt. Erst wenn er da raus ist, würde der Motor anfangen zu fahren

Wäre, hätte, hätte, Fahrradkette.

Viel wichtiger ist ja:
Was soll es tun?
Was tut es stattdessen?

Und natürlich funktioniert das if-else korrekt!

Nachtrag:
Jetzt mal im Ernst...

Du möchtest offensichtlich eine Ablaufsteuerung bauen, einen endlichen Automaten.

Mein Tipp:
Dann tue das auch!

Benenne und definiere alle Zustände, auch die Bedingungen, denn bis jetzt ist für mich nicht zu erkennen, was es tun soll, und warum.

Hab den Code noch mehr ausgedünnt, hoffe dann wird klar was mein Problem ist und was passieren soll

In der Loop funktion habe ich folgenden Code


ECUMDMinus = analogRead(EcuMdMinusPIN);
if (ECUMDMinus > 100)
  {
      if (!tst)
      {
        tst = true;
        Serial.println("Motor soll fahren");
        digitalWrite(DIRA, LOW);
        digitalWrite(DIRB, HIGH);
      }
  }

tst ist ein bool welcher einmalig auf true gesetzt wird. Damit sorge ich dafür, das alles nach "if (!tst) nur einmal ausgeführt wird.

Ich führe den Code aus und gebe dann 5V auf ECUMDMinus und ich springe in die Bedinung. Das Log gibt "Motor soll fahren" aus und digitalWrite wird an DIRA und DIRB gesetzt.

Das Problem ist nun, solange auf ECUMDMinus eine Spannung anliegt fährt der Motor nicht. Erst wenn ECUMDMINUS keine Spannung mehr hat, fährt der Motor immer weiter nach links.

Der Motor soll aber schon in dem Moment anfangen zu drehen wo auf ECUMDMinus eine Spannung anliegt.

Mehr Code ist im Loop nicht enthalten

OK ....

Dann sollte der Motor auch laufen!

Das ist unlogisch!

Er hat zu fahren, wenn die Pins richtig gesetzt sind.

Also hast du einen Fehler.
Einen Fehler außerhalb des bisher gezeigten Code.

Mein kompletter Code ist:

#include <Arduino.h>

#define DIRA 6
#define DIRB 5

uint8_t tst = 0;
int EcuMdMinusPIN = A1;
int ECUMDMinus; //Signal-close

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

  pinMode(DIRA, OUTPUT);
  pinMode(DIRB, OUTPUT);

  digitalWrite(DIRA, LOW);
  digitalWrite(DIRB, LOW);

  digitalWrite(DIRA, HIGH);
  digitalWrite(DIRB, LOW);

  delay(1000);
  digitalWrite(DIRA, LOW);
  digitalWrite(DIRB, HIGH);
  delay(1000);

  digitalWrite(DIRA, LOW);
  digitalWrite(DIRB, LOW);
}

void loop()
{
  ECUMDMinus = analogRead(EcuMdMinusPIN);
  if (ECUMDMinus > 100)
  {
    if (!tst)
    {
      tst = true;
      Serial.println("Motor soll fahren");
      digitalWrite(DIRA, HIGH);
      digitalWrite(DIRB, LOW);
    }
  }
}

Im Setup lasse ich den Motor einmal nach links und nach rechts laufen was auch funktioniert. Das restliche Verhalten ist wie beschrieben.

Spannnug auf den Pin -> Es passiert nichts bis auf das setzen
Spannung weg -> Motor fängt an zu fahren

Dann muss der Fehler außerhalb des Programms zu suchen sein.

#define DIRA 6
#define DIRB 5
void setup() {
  Serial.begin(9600);

  pinMode(DIRA, OUTPUT);
  pinMode(DIRB, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  digitalWrite(DIRA, LOW);
  digitalWrite(DIRB, LOW);
  delay(500);
  Serial.println("Los");
  digitalWrite(DIRA, HIGH);
  digitalWrite(DIRB, LOW);
  delay(1000);

  Serial.println("Zurueck");
  digitalWrite(DIRA, LOW);
  digitalWrite(DIRB, HIGH);
  delay(1000);
  Serial.println("Stop");
  digitalWrite(LED_BUILTIN, HIGH);
  digitalWrite(DIRA, LOW);
  digitalWrite(DIRB, LOW);
}

void loop() {
}

Und dieser Sketch macht, was er soll?
Synchron zu Text und LED?