Servo spinnt und Programmstürzt ab

Hallo Freunde des Arduino,
ich möchte gerne ein Servo über den Arduino Nano (atmega328 nano) steuern. Dazu habe ich noch eine Zeitsteuerung, die läuft und ein paar Schalter, die das Servo und die Zeit im Display steuern sollen.
Nun habe ich das Problem, dass ich das ungeordnete Bewegungen macht und dann das Programm stillsteht. manchmal passiert das gleich wenn ich das Programm starte, manchmal nach ein paar mal Servo + und -. Beim UNO hatte ich das Problem nur, wenn ich für das Servo eine seperate Stromquelle hatte, über die PINs lief es fehlerfrei. Kann das etwas mit dem Timer (millis()) zu tun haben.
Hier mein Code, vielleicht weiß jemand eine Lösung:

#include <LiquidCrystal_I2C.h>
#include <Servo.h>

LiquidCrystal_I2C lcd(0x27, 20, 4); // I2C address 0x27, 20 column and 4 rows
String empfangBT;
int servoPos = 160;
int servoPosMax = 150;
int servoPosMin = 20;
int servoDelta = 10;
int timeCode = 0;
long zeit;
Servo myservo;
const byte buttonPinA = 4; //Speed
const byte buttonPinB = 5; //Ergo+
const byte buttonPinC = 6; //Ergo-
const byte buttonPinD = 3; //resetTime
const byte buttonPinE = 7; //Pause-Time
unsigned long lastPressedTime = 0;
long millsD=0;
double deltaT=0;
double deltaT1=0;
//alle 5 Durchläufe wird Geschwindigkeit und Puls gesendet
int sending = 0;
int sendingCount = 5;
double diffsumme =0 ;
double strecke = 0;

float Quellspannung=5.0;
int AnalogPin=3;
int R1=1500.0; //Wert des bekannten Widerstands (der mitgelieferte 1,5k-Widerstand)
long MesswertHf;
float SpannungR2; //Spannung über dem zu messenden Widerstand
float WiderstandHf;

long myTimer = 0;
long myTimeout = 1000;
boolean pause = false;


 
void setup(){
 Serial.begin(9600);  //serieller Monitor wird gestartet, Baudrate auf 9600 festgelegt
  pinMode(buttonPinA, INPUT_PULLUP);
  pinMode(buttonPinB, INPUT_PULLUP);
  pinMode(buttonPinC, INPUT_PULLUP);
  pinMode(buttonPinD, INPUT_PULLUP);
  pinMode(buttonPinE, INPUT_PULLUP);
  lcd.init(); // initialize the lcd
  lcd.backlight();
  myservo.attach(9);
   
  myservo.write(servoPos);
  Serial.println("s170#");
  dPrint(0,0,"**** Ergometer *****");
  dPrint(0,1,"Stufe:");
  dPrint(0,2,"Speed:");
  dPrint(0,3,"Time:");
}
 
void loop(){

  //Serielle Daten empfangen

  while(Serial.available() > 0) {
    empfangBT=Serial.readStringUntil('\n');
  }
 
  

if (millies() > myTimeout + myTimer ) {

  int sekunde = (millies()/1000) % 60; // Das Zeichen: "%" ist der Modulo-Operator
  int minute  = (millies()/60000) % 60;
  int stunde  = (millies()/3600000) % 24;
  //Stunde
  if (stunde<10)
  {
    dPrint(7,3, "0");
    dPrint(8,3, String(stunde));
  } 
  else
  {
      dPrint(7,3, String(stunde));
  }
      dPrint(9,3, ":");
  //Minute
  if (minute<10)
  {
    dPrint(10,3, "0");
    dPrint(11,3, String(minute));
  } 
  else
  {
      dPrint(10,3, String(minute));
  }
      dPrint(12,3, ":");
  //Sekunde
  if (sekunde<10)
  {
    dPrint(13,3, "0");
    dPrint(14,3, String(sekunde));
  } 
  else
  {
      dPrint(13,3, String(sekunde));
  }


//    dPrint(7,3, "             ");
//    dPrint(7,3, String(myTimer/1000));
    myTimer = millies();

  }

  
  //Servosteuerung
  if(empfangBT.indexOf("x")!=-1){
     int posX = empfangBT.indexOf("x");
     int posH = empfangBT.indexOf("#");    
     String out = empfangBT.substring(posX+1,posH);
      servoPos = out.toInt();
      //myservo.write(servoPos); 
      String sb = "s";
      String sPos = String(servoPos);
      String hash = "#";
      String zuSenden = sb+sPos+hash;
      dPrint(7, 1, "           ");
      dPrint(7, 1, String(servoPos));
      myservo.write(servoPos);
      Serial.println(zuSenden);

      empfangBT="";
}
  //Geschwindigkeit ermitteln
  if (buttonPressedA()){
    if (lastPressedTime > 0){
      unsigned long difference = millies()-lastPressedTime;
     // Serial.print("Time difference: ");
     // Serial.println(difference);
      diffsumme=diffsumme+difference;   
    if(sending>=sendingCount){
     
      float sendeSpeed = (diffsumme/sending)/1000;
      dSendFloat("v", "#", sendeSpeed);

      double umfang = 2 * 0.2 * 3.141;
      double speed = (umfang / sendeSpeed) * 3.6;

      String s1 = String(speed);
      String s2 = " km/h";
      String sx = s1+s2;
    

      sending=0;
      diffsumme=0;
      dPrint(7, 2, "         ");
      dPrint(7, 2, sx);

      //in sec
      deltaT1= (millies()-deltaT)/1000;
      strecke = (((deltaT1)/3600)*speed)+strecke; 

    dPrint(11, 1, "       ");
    dPrint(12, 1, String(strecke));
    dPrint(17, 1, "km");


    deltaT=millies();
    }
    sending++;

    }
    lastPressedTime = millies();
  }


  if (buttonPressedB()){
   if(servoPos<servoPosMax){
      servoPos+=10;
      //myservo.write(servoPos); 
      String sb = "s";
      String sPos = String(servoPos);
      String hash = "#";
      String zuSenden = sb+sPos+hash;
      myservo.write(servoPos);
      Serial.println(zuSenden);
      dPrint(7, 1, "   ");
      dPrint(7, 1, String(servoPos));
   }
  }

  if (buttonPressedC()){
   if(servoPos>servoPosMin){
      servoPos-=10;
      //myservo.write(servoPos); 
      String sb = "s";
      String sPos = String(servoPos);
      String hash = "#";
      String zuSenden = sb+sPos+hash;
      myservo.write(servoPos);
      Serial.println(zuSenden);
      dPrint(7, 1, "   ");
      dPrint(7, 1, String(servoPos));
   }

  }
    //Time-Reset
  if (buttonPressedD()){
    millsD=millis();
    strecke=0;
    dPrint(11, 1, "          ");
    dPrint(12, 1, String(strecke));
    dPrint(17, 1, "km");
    myTimer = 0;
  }
    //Time-Pause
  if (buttonPressedE()){
    millsD=millis();
    myTimer = 0;
  }



MesswertHf=0;
  for(int i=0;i<5;i++){
    MesswertHf+=analogRead(AnalogPin);
  }
  MesswertHf=trunc(MesswertHf/5);
  SpannungR2=(Quellspannung/1023.0)*MesswertHf;
  WiderstandHf=R1*(SpannungR2/(Quellspannung-SpannungR2));
 }

boolean buttonPressedA(){
static unsigned long lastChange = 0;
static byte lastState = LOW;
static byte state;
   byte actState = digitalRead(buttonPinA);
   if (actState != lastState) {
      lastState = actState;
      lastChange = millis();
   }
   if (state != actState && millis()-lastChange > 20){
     state = actState;
     return !state; // Returns true only when state changes from HIGH to LOW
   }
  return false;
}


boolean buttonPressedB(){
static unsigned long lastChange = 0;
static byte lastState = LOW;
static byte state;
   byte actState = digitalRead(buttonPinB);
   if (actState != lastState) {
      lastState = actState;
      lastChange = millis();
   }
   if (state != actState && millis()-lastChange > 20){
     state = actState;
     return !state; // Returns true only when state changes from HIGH to LOW
   }
  return false;
}

boolean buttonPressedC(){
static unsigned long lastChange = 0;
static byte lastState = LOW;
static byte state;
   byte actState = digitalRead(buttonPinC);
   if (actState != lastState) {
      lastState = actState;
      lastChange = millis();
   }
   if (state != actState && millis()-lastChange > 20){
     state = actState;
     return !state; // Returns true only when state changes from HIGH to LOW
   }
  return false;
}

boolean buttonPressedD(){
static unsigned long lastChange = 0;
static byte lastState = LOW;
static byte state;
   byte actState = digitalRead(buttonPinD);
   if (actState != lastState) {
      lastState = actState;
      lastChange = millis();
   }
   if (state != actState && millis()-lastChange > 20){
     state = actState;
     return !state; // Returns true only when state changes from HIGH to LOW
   }
  return false;
}

boolean buttonPressedE(){
static unsigned long lastChange = 0;
static byte lastState = LOW;
static byte state;
   byte actState = digitalRead(buttonPinE);
   if (actState != lastState) {
      lastState = actState;
      lastChange = millis();
   }
   if (state != actState && millis()-lastChange > 20){
     state = actState;
     return !state; // Returns true only when state changes from HIGH to LOW
   }
  return false;
}


void dPrint(int zeile, int spalte, String text){
      lcd.setCursor(zeile,spalte); 
      lcd.print(text);    
}

void dSendFloat(String vor, String nach, float meldung){
     String zuSendenX = vor+String(meldung)+nach;
      //dPrint(10,2,String(zuSendenX));
      Serial.println(zuSendenX);  
}

void dSendString(String vor, String nach, String meldung){
     String zuSendenX = vor+meldung+nach;
           dPrint(10,3,String(zuSendenX));
      Serial.println(zuSendenX);  
}

long millies(){

  return millis()-millsD;
}

Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden. Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.

mfg ein Moderator.

Ohne den Sketch anzuschauen frage ich Dich: Wie sieht es mit der Spannungsversorgung aus? Ist diese Leistungsstark genug um den Servo zu versorgen?
Grüße Uwe

Hattest Du die beiden Massen ( Minuspole Stromquelle und Arduino) verbunden?
Grüße Uwe

Keine Ahnung ob das nun die Probleme beseitigt:

Servo nicht vom 5V pin des Arduinos versorgen sondern von einem eigenen Netzteil aus

keine Strings verwenden. (Die verbrauchen immer mehr Speicherplatz was zum Programm-Crash führt)
Stattdessen SafeStrings verwenden

long millies(){

  return millis()-millsD;
}

Alles was mit millis()zu tun hat als unsigned long deklarieren

Wenn es "direkt an den Pins funktioniert hat aber mit externem Netzteil nicht dann hat bestimmt die GND_Verbindung zwischen externem Netzteil und dem Arduino gefehlt

Hallo,

hmm - nun habe ich es mit der externen Stromversorgung am Nano getestet und jetzt klappt es. Beim Uno war es genau umgekehrt.
Ich habe natürlich die Spannungsquelle genommen, die ich auch für das betreiben des Arduino genommen habe. Komisch - ging beim Uno nicht. Nun, jetzt klappt es - vielen Dank!
Gruß
Dirk

Die Stelle ist kaputt.
An anderen Stellen kannst du es richtig!

Auch mir schmeckt der übermäßige Einsatz von String nicht.

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