Enviolo (Nuvinci) + Arduino für Rollstuhl

Ich spüre Verantwortung auf meinen Schultern :thinking:

  1. Bei analogWrite() nutzt Du einen Ausgang mit 490 Hz. Hast Du auch schon mal einen mit 980 Hz probiert?
  2. Bei analogWrite() verwendest Du 30 und 100 als Tastverhältnis. Gibt es da tatsächlich einen Geschwindigkeitsunterschied? Wenn ja, wäre ein Sanftanlauf eine sinnvolle Idee?

Kosmetik mit Typ- und Namensanpassungen:

const byte dataPin = 6;
const byte clockPin = 7;
//Motor
const byte sensorPin = 2;        // Interrupt Pin (nur 2 oder 3 @ Arduino Uno)
const byte brakePin = 8;         // Pinausgang Bremse, HIGH = Vollbremsung
const byte SCHLEICH_POWER = 30;  // Motor-Drehzahl-Schleichgang
const byte NORMAL_POWER = 100;   // Motor-Drehzahl-Normalbetrieb
const byte pwmPin = 9;           // Pinausgang für Drehzahl
const byte richtungsPin = 10;    // Pin Drehrichtungswechsel LOW/HIGH Drehrichtung

Wartungsfreundlichkeit:
In motorSetup() hast Du eine Schrittkette (=finite state machine; =endlicher Automat) verwendet, die man m. E. etwas deutlicher und damit servicefreundlicher schreiben kann.

  1. START initialisiert
  2. KRIECH schleicht sich an den mechanischen Anschlag, der durch Blockieren und damit wenigen Impulsen erkannt wird
  3. ANSCHLAG läßt sich die Bewegung am Anschlag beruhigen
  4. STARTPOSITION setzt die Startposition und schaltet in den Normalbetrieb
  5. BETRIEB sollte eigentlich nie erreicht werden. Hier könnte man die ganze Funktion motorMatik() unterbringen, muß aber auch nicht.

Da ich die Hardware nicht habe, ein gänzlich ungetesteter Vorschlag:

//Waage
#include "HX711.h"
HX711 scale;
uint8_t dataPin = 6;
uint8_t clockPin = 7;

//Motor
const uint8_t sensorPin = 2;        // Interrupt Pin (nur 2 oder 3 @ Arduino Uno)
const uint8_t brakePin = 8;         // Pinausgang Bremse, HIGH = Vollbremsung
const uint8_t KRIECH_POWER = 30;    // Motor-Drehzahl-Kriechgang
const uint8_t NORMAL_POWER = 100;   // Motor-Drehzahl-Normalbetrieb
const uint8_t pwmPin = 9;           // Pinausgang für Drehzahl
const uint8_t richtungsPin = 10;    // Pin Drehrichtungswechsel LOW/HIGH Drehrichtung
const uint32_t MESSINTERVALL = 500;
const uint32_t PAUSENINTERVALL = 1000;

volatile long Counter;
volatile bool dir;               // true: incr ; false: decr
bool normalbetrieb = false;
uint8_t P = 0;

void count() {
  Counter += dir ? +1 : -1;
}
void motor(bool Stop, bool Richtung, int pwmSignal) {
  digitalWrite (brakePin, Stop);
  digitalWrite (richtungsPin, Richtung);
  analogWrite (pwmPin, pwmSignal);
}
void M_Stop() {
  motor(HIGH, LOW, 0);
}
void M_Hoch() {
  motor(LOW, HIGH, NORMAL_POWER);
}
void M_Runter() {
  motor(LOW, LOW, NORMAL_POWER);
}
//**********************************************
void setup() {
  Serial.begin(9600);

  //Waage
  scale.begin(dataPin, clockPin);
  scale.set_scale(127.15);//es wird nur der Relativwert benötigt
  pinMode(dataPin, INPUT);
  pinMode(clockPin , OUTPUT);

  //Motor
  pinMode(sensorPin, INPUT);  // definiertes Potenzial (HIGH/LOW) von einem Hall-Sensor
  pinMode(brakePin , OUTPUT);
  pinMode(pwmPin , OUTPUT);
  pinMode(richtungsPin , OUTPUT);  // Drehrichtung

  attachInterrupt(digitalPinToInterrupt(sensorPin), count, CHANGE);
}
//**********************************************
void loop() {
  if (normalbetrieb) {
    motorMatik();
  } else {
    motorSetup();
  }
}

void motorSetup() {
  uint32_t jetzt = millis();
  static uint32_t setupMillis = jetzt;
  enum {START, KRIECH, ANSCHLAG, STARTPOSITION, BETRIEB};
  static byte schritt = KRIECH;

  switch (schritt) {
    case START:
      Counter = 0;
      dir = 1;
      setupMillis = jetzt;
      motor(LOW, LOW, KRIECH_POWER); //Kriechgang zum Anfahren der Endposition (Anschlag)
      schritt = KRIECH;
      break;
    case KRIECH:
      if (jetzt - setupMillis >= MESSINTERVALL) {
        setupMillis = jetzt;
        if (Counter < 10) {
          M_Stop (); // Drehzahl sinkt am Anschlag unter (10) , der Motor stoppt
          schritt = ANSCHLAG;
        } else {
          Counter = 0;
        }
      }
      break;
    case ANSCHLAG:
      if (jetzt - setupMillis >= PAUSENINTERVALL) {
        Counter = 1000;  // Counter wir auf 1000 gesetzt um ein "Überfahren" in den negativen Bereich zu verhindern
        motor (LOW, HIGH, NORMAL_POWER);  // Richtungswechsel nach Anschlag
        schritt = STARTPOSITION;
      }
      break;
    case STARTPOSITION:
      if (Counter >= 1010) {//Fahrt auf Ausgangsposition (z.B X + 10)
        M_Stop ();//Setup-Phase ist beendet, Motor steht in Ausgangsposition
        normalbetrieb = true;
        schritt = BETRIEB;
      }
      break;
    case BETRIEB:
      break;
    default:
      schritt = START;
      break;
  }
}

void motorMatik () {
  static unsigned long m_Millis;
  static unsigned long m_MillisH;
  uint16_t wz = analogRead(A0);
  long positionM[] = {1040, 1600};
  long druckPosition = map (wz, 0, 1023, 1000, 1600);

  if (druckPosition > (Counter + 1) && Counter < positionM[1]) {
    P = 1;
    if (millis() - m_Millis >= 1000) {//Pause, um M_Hoch auslaufen zu lassen
      dir = 1;
      M_Runter();//Druck läßt nach
      m_MillisH = millis();
    } else {
      M_Stop();
    }
  }
  else if (druckPosition < (Counter - 1) && Counter > positionM[0] ) {
    P = 2;
    if (millis() - m_MillisH >= 1000) {//Pause, um M_Runter auslaufen zu lassen
      dir = 0;
      M_Hoch();//Druck steigt
      m_Millis = millis();
    } else {
      M_Stop();
    }
  }
  else {
    m_Millis = millis();
    m_MillisH = millis();
    M_Stop();
    P = 3;
  }
  Serial.print("druckPosition: "); Serial.print(druckPosition);
  Serial.print("\t Counter: "); Serial.print(Counter);
  Serial.print("\t P_Position: "); Serial.print(P);
  Serial.print("\t m_MillisH: "); Serial.print(m_MillisH);
  /*
    Serial.print("\t millis: ");
    Serial.print(millis());
    Serial.print("\t m_Millis: ");
    Serial.print(m_Millis);
    // */
  Serial.println();
}

Du wirst sicherlich den bisherigen Ablauf wiedererkennen und kleine Fehler von mir korrigieren können.

Interessiert Dich mein Vorschlag?