Sketch komprimieren.

Hallo

Ich hab Emir folgendes Sketch gemacht um 2 Servos über eine Webseite mit schiebe Reglern zu steuern.
Das Sketch funktioniert auch, doch nun möchte ich das Sketch verkleinern, falls noch mal 2 Servos dazu kommen.
Um folgenden Bereich Handelt es sich:

  if (str_servo == "1" && str_angle != String(intPosServo01 -1)) {
    if (intDrehWert < intPosServo01) {    
      while(intPosServo01 >= intDrehWert) {
        intPosServo01 = intPosServo01 - 1;              
        Servo01.write(intPosServo01);     
        delay(intWarte);   
      }   
    }
    if (intDrehWert > intPosServo01) {
      while(intPosServo01 <= intDrehWert) {
        intPosServo01 = intPosServo01 + 1;          
        Servo01.write(intPosServo01);     
        delay(intWarte);    
      }   
    } 
  }
  if (str_servo == "2" && str_angle != String(intPosServo02 -1)) {
    if (intDrehWert < intPosServo02) {    
      while(intPosServo02 >= intDrehWert) {
        intPosServo02 = intPosServo02 - 1;             
        Servo02.write(intPosServo02);     
        delay(intWarte);   
      }   
    }
    if (intDrehWert > intPosServo02) {
      while(intPosServo02 <= intDrehWert) {
        intPosServo02 = intPosServo02 + 1;           
        Servo02.write(intPosServo02);     
        delay(intWarte);    
      }   
    } 
  }

Damit Steuer ich die Servos an, wäre es nicht möglich das ich das so dynamisch mache das ich das nur einmal brauche, und damit x beliebige Servos ansteuern kann?

  if (str_servo == "1" && str_angle != String(intPosServo01 -1)) {
    if (intDrehWert < intPosServo01) {    
      while(intPosServo01 >= intDrehWert) {
        intPosServo01 = intPosServo01 - 1;              
        Servo01.write(intPosServo01);     
        delay(intWarte);   
      }   
    }
    if (intDrehWert > intPosServo01) {
      while(intPosServo01 <= intDrehWert) {
        intPosServo01 = intPosServo01 + 1;          
        Servo01.write(intPosServo01);     
        delay(intWarte);    
      }   
    } 
  }

Ich hoffe das war verständlich was ich möchte :expressionless:

Gruss Sascha

Hallo Sascha,
Du kannst an zwei Stellen schnell Speicher sparen:

  • Verzicht auf die String-Klasse (stattdessen char-Arrays abgeschlossen durch '\0' [C-String] verwenden wenn es unbedingt Text sein muss; ansonsten numerische Kennung für die Servo-Identifikation)
  • Alles was gleich ist in eine Methode auslagern und der als Parameter jeweils das richtige Servo-Objekt übergeben und dann darauf arbeiten. Damit musst bei Änderungen nur an einer Stelle ackern und der Methode ist es egal, ob Du statt servo1 irgendwann mal servo5 reinsteckst

Gruß Walter

while(intPosServo01 >= intDrehWert) {
        intPosServo01 = intPosServo01 - 1;             
        Servo01.write(intPosServo01);     
        delay(intWarte);   
      }

ist eine große Pause in der nichts anderes gemacht wird. Also solage das Servo bewegt wird kann der Sketch nichts anderes machen.
Grüße Uwe

Hallo

@uwefed
ja das soll auch so sein, es soll immer nur ein Server bewegt werden. Die schleife brauchte ich auch damit der Server in einem "gemütlichen" Tempo zum Ziel fährt :slight_smile:

@wno158
Puh das war jetzt bissel viel für meine paar Gehirnzellen. Um ehrlich zu sein weis sich gar nicht was Du meinst :frowning:

mach statt einzelnen Objekten Servo01, Servo02, Servo03 ein array mit Objekten.

lies einfach hier mal: control servos by an array; how to write the sw for controlling the lib - Programming Questions - Arduino Forum

du hast dann halt ein servo[0].write, servo[1].write, servo[2].write etc.

Wenn du dann aus deinem str_servo ein int gemacht hast (atoi, toInt ...), dann kannst du das für den Zugriff auf das konkrete Objekt nutzen.

Achtung wir beginnen mit dem Zählen bei 0.

neuling321:
Puh das war jetzt bissel viel für meine paar Gehirnzellen. Um ehrlich zu sein weis sich gar nicht was Du meinst :frowning:

Dann hätte ich noch einen Link: mehrere Servomotoren betreiben

Um folgenden Bereich Handelt es sich:

   if (str_servo == "1" && str_angle != String(intPosServo01 -1)) {

Nein, es handelt sich erstmal um den von dir nicht gezeigten Bereich, fürchte ich.
Aus String str_servo; ein byte servoIndex; machen und
aus String str_angle; ein int. Der Verzicht auf Strings komprimiert noch mehr als du im Übersetzungsergebnis erkennen kannst.

Dann natürlich den doppelten Code in eine Funktion auslagern, die zweimal aufgerufen wird, evtl. drittens aus servo01 und servo02 ein Array machen, damit du das viertens leichter in einer Schleife aufrufen kannst.

Irgendwie verstehe ich eure Sprache nicht, bzw. was ihr mir das sagt. Ich lasse es wohl so oder muss einen anderen Arduino mit mehr Speicher kaufen.

Danke

Gruss Sascha

Ich lasse es wohl so

Wenn alles geht, ist das schon eine Option.

Allerdings verstehe ich nicht, was an dem Datentyp String, den du ja verwendest, nicht zu verstehen ist. String ist speicheraufwendiger, nutzloser Schnickschnack. Wenn du Speicher sparen willst, fang da an.

Kann mir denn da echt keine auf die Sprünge helfen?
Nicht jeder ist doch gleich ein Mega Programmierer, wenn es so wäre
bräuchte man die Foren ja nicht mehr.

Ich habe versucht die String gegen Integer Variablen zu tuaschen, doch nun funktioniert die Abfrage nicht.
Auch das Serial.println bringt mir kein Ergebnis mehr :frowning:

int int_servo;
int int_angle;

int_servo = touchStr.substring(0,int_pos01).toInt();
int_angle = touchStr.substring(int_pos01+1,int_len -2).toInt();

Das hat mir schon bissel platzt gebracht, aber eben noch nicht genug.

#include <Servo.h>
#include <Phpoc.h>
PhpocServer server(80);
 

// Servo-Objekt erzeugen
Servo Servo01;
Servo Servo02;

int intPosServo01 = 91;
int intPosServo02 = 91;
int int_len;
int int_pos01;

int int_servo;
int int_angle;
String touchStr;


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

  // initialize PHPoC [WiFi] Shield:
  Phpoc.begin(PF_LOG_SPI | PF_LOG_NET);
  //Phpoc.begin();

  // start WebSocket server
  server.beginWebSocket("ball_on_fire");

  // print IP address of PHPoC [WiFi] Shield to serial monitor:
  //Serial.print("WebSocket server address : ");
  //Serial.println(Phpoc.localIP());
 
  Servo01.attach(6);
  Servo01.write(intPosServo01);
  Servo02.attach(7);
  Servo02.write(intPosServo02);
 
}

void loop() {
  
  // wait for a new client:
  PhpocClient client = server.available();

  if (client) {
    // read a string that is terminated by a carriage return and a newline
    // characters:
    touchStr = client.readLine();
   // Serial.println(touchStr);
  }
   
   ServoRun();
}

void ServoRun() {

  int_len = touchStr.length();
  int_pos01 = touchStr.indexOf("-");
  int_servo = touchStr.substring(0,int_pos01).toInt();
  int_angle = touchStr.substring(int_pos01+1,int_len -2).toInt();

 
  if (int_servo == "1" && int_angle != intPosServo01) {
    if (int_angle < intPosServo01) {    
      while(intPosServo01 >= int_angle) {
        intPosServo01 = intPosServo01 - 1;              
        Servo01.write(intPosServo01);     
      }   
    }
    if (int_angle > intPosServo01) {
      while(intPosServo01 <= int_angle) {
        intPosServo01 = intPosServo01 + 1;          
        Servo01.write(intPosServo01);     
      }   
    } 
  }

}

neuling321:
Kann mir denn da echt keine auf die Sprünge helfen?

Dann schreibe ganz genau was du wissen willst.
Wenn dir die bisherigen Antworten nicht reichten, schreibe WAS du nicht verstanden hast und wobei du noch Hilfe brauchst.

Beschreibe deine Hardware, setze anklickbare Links auf die Produkte die du einsetzt.
Wenn die Helfer irgendwelche Libraries installieren müssten, setze Links auf die Libraries wo sie her sind.
Handelt es sich um ein Hardwareproblem, mach einen Schaltplan und ein Echtbild und setze es hier rein.

Speicherproblem? Wie viel Speicher verbraucht der Sketch jetzt - auf wie viel willst du runterkommen.

Immer noch nicht klar? Stelle eine konkrete Frage.

Hallo Sascha,
es geht doch voran: Du hast jetzt Deine Servokennung schon auf int umgestellt und den Servocode in eine Funktion ausgelagert. Prima!

Dann musst Du (erstmal) nur noch Deine Abfrage anpassen.
Aus

  // if (int_servo == "1" && int_angle != intPosServo01) {

sollte dann besser

  if (int_servo == 1 && int_angle != intPosServo01) {

werden.

Ich weiss nicht, ob println() mit Variablen vom Typ String umgehen kann. An der Stelle würde ich dann erstmal die Ausgabe als C-String versuchen:

Serial.println(touchStr.c_str());

Danach hast Du zwei Möglichkeiten zum weiteren Vorgehen:
Die String-Klasse loswerden und dann das Werk "multi-Servo-tauglich" machen oder halt umgekehrt. Ich würde erst an die Stringklasse gehen, damit schaffst Du am schnellsten Platz.

Um die String-Klasse loszuwerden, musst Du Dich ein wenig mit dem Datentyp 'char' und Arrays davon beschäftigen (string - klein geschrieben).

Dein Phpoc-Client liefert jedenfalls beim readLine() schon passende Werte zurück (siehe PhpocClient.h, Zeile 72ff):

// Zeiger auf eine Zeile, die kannst Du Zeichen für Zeichen bis zum '\n' durchackern
char *readLine(void);
// oder:
// Übergabe der Zeile in einen von Dir bereitzustellenden Puffer, z.B. char puffer[20] wenn Du maximal 19 Zeichen erwartest
int readLine(uint8_t *buf, size_t size);

Gruß Walter

Und bitte nicht böse sein, dass die meisten hier keinen fertigen Code posten. Das erfordert erstens, dass wir Dein komplettes Problem nachbauen (Code kompilieren und testen) und zweitens hilft es Dir nur wenig - Du hast mehr davon, wenn Du selber probierst und dabei lernst. Bei ganz konkreten Problemen (wie der Vergleich eines int mit einem String) sieht das natürlich anders aus.
Viel Erfolg!

Das hat mir schon bissel platzt gebracht, aber eben noch nicht genug.

Das Programm aus Posting #9 kompiliert nicht bei mir.

Warnungen in Phpoc.cpp und Phpoc.h ohne Ende.

Ganz besonders Absurd, erscheint mir dieses:

\libraries\PHPoC\src\Phpoc.cpp:67:0: warning: "S2M_FLAG_TXB" redefined

#define S2M_FLAG_TXB 0x1000 /* data is in tx buffer */

In file included from E:\Programme\arduino\portable\sketchbook\libraries\PHPoC\src/Phpoc.h:40:0,

from \libraries\PHPoC\src\Phpoc.cpp:58:

\libraries\PHPoC\src/Sppc.h:53:0: note: this is the location of the previous definition

#define S2M_FLAG_TXB 0x2000 /* data is in tx buffer */

Und schlussendlich ein error.

\libraries\PHPoC\src\Sppc.cpp:415:46: error: invalid conversion from 'char*' to 'uint8_t* {aka unsigned char*}' [-fpermissive]

len = read(readstr_buf, READSTR_BUF_SIZE - 2);

Pfade gekürzt

Leider kann ich mit so einem Werkzeug gar nicht arbeiten.

Mit Phpoc kenne ich mich nicht aus, da lasse ich die Finger von.

Da ich in #5 schon einen prozeduralen Ansatz verlinkt habe, nun noch ein Ansatz mit Methode:

#include <Servo.h>
// Servo-Objekt erzeugen
Servo Servo01;
Servo Servo02;

struct Motoren {
  byte pin;
  int angle;
  int posServo;
  Servo *ServoNN;
  void init(byte _pin, byte _posServo, Servo *_ServoNN) {
    pin = _pin;
    angle = 0;
    posServo = _posServo;
    ServoNN = _ServoNN;
    ServoNN->attach(pin);
    ServoNN->write(posServo);
  }
  void run(int _angle) {
    angle = _angle;
    if (angle != posServo) {
      if (angle < posServo) {
        while (posServo > angle) {
          posServo = posServo - 1;
          ServoNN->write(posServo);
        }
      }
      if (angle > posServo) {
        while (posServo < angle) {
          posServo = posServo + 1;
          ServoNN->write(posServo);
        }
      }
    }
  }
} motor1, motor2;

void setup() {
  Serial.begin(9600);
  while (!Serial);
  motor1.init(6, 91, &Servo01);
  motor2.init(7, 91, &Servo02);
}
void loop() {
  static byte winkel1 = 90, winkel2 = 90;
  motor1.run(winkel1);
  winkel1 = (winkel1 + 1) % 181;
  motor2.run(winkel2);
  winkel2 = (180 - winkel1);
  delay(100);
}

Was in loop steht, dient nur zum Testen, ob sich was bewegt.

Hallo

Also ich habe mir dieses Shield gekauft:
PHPoC Shield

Das mit PHP ist überhaut nicht schlimm, man macht auf dem PHPoC Shield eine Webseite die an das Arduino die benötigten Parameter übergibt. Wirklich easy. Aber im Arduino Sketch wird es mit dem Umwandeln von String to Integer oder umgekehrt echt kompliziert :-(.

Wie gesagt das Arduino Sketch aus meinem Start Post läuft, ich kann über die Webseite, die Servos steuern. Ich wollte halt das Arduino Sketch noch bissel komprimieren da ich noch ein paar Ansteuerungen dazu programmieren wollte.

Werde nun versuchen, das was hier vorgeschlagen umzusetzen.

Wie gesagt das Arduino Sketch aus meinem Start Post läuft,

Ein bis zur Untestbarkeit verstümmeltes Fragment!

Hier ein "langsamer" Servo, ohne Phpoc.

Eingabe auf der Seriellen Konsole (Zeilen ende mit CR):
1-90 (und Senden drücken)
1 == Servonummer, hier von 0 bis 1
90 == Winkel , hier von 0 bis 180

Servo läuft langsam zur Zielposition

#include <Servo.h> 


class WalkingServo : public Servo
{
  protected:
   const byte pin;
   byte zielpos;

  public:
   WalkingServo(const byte pin):pin(pin),zielpos(0){}

   void init()
   {
     attach(pin);
   }

   void walk()
   {
     byte pos = read();

     if(pos != zielpos)
     {
      Serial.print("step ");Serial.println(millis());
     }
     
     if(pos < zielpos) write(pos+1);
     if(pos > zielpos) write(pos-1);
   }

   void walkto(byte newpos)
   {
      zielpos = newpos;
   }
  
};

const byte anzahlServos = 2;
WalkingServo servos[anzahlServos] {6,7};

const byte bufferSize = 20;
char buffer[bufferSize] = "";
byte bufferIndex = 0;

void serialEvent()
{
  char zeichen = Serial.read();

  switch(zeichen)
  {
    case '\r': goto auswertung;
    case '\n': goto ende; // ignorieren

    case '0' ... '9': break; // akzeptieren
    case '-': break;  // akzeptieren

    default: goto resetParser;
  }

  Serial.print("Zeichen= ");Serial.println(zeichen);
  
  if(bufferIndex > (bufferSize - 2)) goto resetParser;
  
  buffer[bufferIndex] = zeichen;
  bufferIndex++;
  buffer[bufferIndex] = 0;
  goto ende;

  auswertung:
    Serial.println(buffer);
    unsigned int servo;
    unsigned int pos;
    if(2 > sscanf(buffer,"%u-%u",&servo,&pos))  goto resetParser;
    if(servo >= anzahlServos) goto resetParser;
    if(pos > 180) goto resetParser;

    servos[servo].walkto(pos);
    Serial.print("servo=");Serial.print(servo);Serial.print(" ");
    Serial.print("pos=");Serial.print(pos);Serial.println("");
  
  resetParser:
    Serial.println("Parser Reset");
    buffer[0] = 0;
    bufferIndex = 0;

  ende: ; 
}


void setup() 
{
 Serial.begin(9600);
 Serial.println("Start");
 for(WalkingServo &servo:servos)
 {
  servo.init();
  servo.walkto(91);
 }
}

unsigned long timestamp = 0;
const unsigned long speed = 100; // hohe werte = langsamer Servo

void loop() 
{
  if(millis()-timestamp > speed)
  {
    timestamp += speed;
    for(WalkingServo &servo:servos) servo.walk();
  }
}

kaum getestet, da keine Servos vorhanden

Verstehe deine aussage nicht.
Wieso ist das verstümmelt?

Dieses Sketch was Du da hast hängt sich dauernd auf, das habe ich schon paar mal wieder aus der Versenkung raus geholt.

Das PHPoC gibt ja nur die Daten an das Arduino weiter, hat also mit dem Ansprechen des Servos nichts zu tun.

Weil es nur ein Fragment eines vollständigen Sketches ist, ist es verstümmelt.

Gruß Tommy

Nein es ist das komplette Sketch, halt ohne die PHPoC Datei, aber da liegt ja auch nicht mein Problem.

Array der Servo Motoren erstellen:

// Servo-Objekt erzeugen
Servo srv0;
Servo srv1;

struct srvNN[] = {srv0,srv1};

Aufruf der der einzelnen Servos:

srvNN[servo_nr].write(intPosServo);

Leider funktioniert der der Aufruf des Servos nicht

Komplettes Sketch:

#include <Servo.h>
#include <Phpoc.h>
PhpocServer server(80);
 

// Servo-Objekt erzeugen
Servo srv0;
Servo srv1;

struct srvNN[] = {srv0,srv1};

int intPosServo = 91;
int int_len;
int int_pos01;

int int_servo;
int int_angle;
String touchStr;


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

  // initialize PHPoC [WiFi] Shield:
  Phpoc.begin(PF_LOG_SPI | PF_LOG_NET);
  //Phpoc.begin();

  // start WebSocket server
  server.beginWebSocket("ball_on_fire");

  // print IP address of PHPoC [WiFi] Shield to serial monitor:
  //Serial.print("WebSocket server address : ");
  //Serial.println(Phpoc.localIP());
 
  srv0.attach(6);
  srv0.write(intPosServo);
  srv1.attach(7);
  srv1.write(intPosServo);
 
}

void loop() {
  
  // wait for a new client:
  PhpocClient client = server.available();

  if (client) {
    // read a string that is terminated by a carriage return and a newline
    // characters:
    touchStr = client.readLine();
    //touchStr = client.read();
    //Serial.println(touchStr);
    int_len = touchStr.length();
    int_pos01 = touchStr.indexOf("-");
    int_servo = touchStr.substring(0,int_pos01).toInt();
    int_angle = touchStr.substring(int_pos01+1,int_len -2).toInt();  
  
    if (int_angle != intPosServo -1) {
      
      RunServo(int_angle, intPosServo, int_servo);
      
    }  
  }
}

void RunServo(int angle, int PosServo, int servo_nr ) {

    if (angle < PosServo) {    
      while(PosServo >= int_angle) {
        intPosServo = intPosServo - 1;              
        ServoNN[servo_nr].write(intPosServo);     
      } 
    }
    if (int_angle > intPosServo) {
      while(intPosServo <= int_angle) {
        intPosServo = intPosServo + 1;          
        srvNN[servo_nr].write(intPosServo);     
      }   
    }   
}

neuling321:
Das mit PHP ist überhaut nicht schlimm, ...

Wenn man von PHP kommt, sind Zeichenketten in C++ gruselig, zumindest für mich :slight_smile:

Anstelle von dem, was vom Shield kommt, nutze ich den seriellen Monitor mit Eingaben wie "1-123", wobei der Monitor auf "Neue Zeile" stehen muß. Dann kann man sscanf zum Zerpflücken der Zeichenkette verwenden.

Feldindexe zählen ab 0, Du zählst die Motoren ab 1, das muß per Programm korrigiert werden.

#include <Servo.h>
// Servo-Objekt erzeugen
Servo Servo01;
Servo Servo02;

struct Motoren {
  Motoren(byte pin, byte angle, Servo *ServoNN): pin(pin), angle(angle), posServo(0), ServoNN(ServoNN) {}
  byte pin;
  byte angle;
  byte posServo;
  Servo *ServoNN;
  void init() {
    ServoNN->attach(pin);
    ServoNN->write(posServo);
  }
  void run(byte _angle) {
    angle = _angle;
    if (angle <= 180) {
      if (angle != posServo) {
        if (angle < posServo) {
          while (posServo > angle) {
            posServo = posServo - 1;
            ServoNN->write(posServo);
          }
        }
        if (angle > posServo) {
          while (posServo < angle) {
            posServo = posServo + 1;
            ServoNN->write(posServo);
          }
        }
      }
    }
  }
};

struct Motoren motor[] {
  {6, 91, &Servo01},
  {7, 91, &Servo02}
};

void setup() {
  Serial.begin(9600);
  while (!Serial);
  for (Motoren &m : motor) m.init();
}
void loop() {
  const byte BUFLEN = 20;
  static char buf[BUFLEN];
  static byte mot = 0, winkel = 90;
  static byte pos = 0;
  if (Serial.available()) {
    char zeichen = Serial.read();  // es wird "<Motornummer>-<Winkel>" bsp. "1-55" erwartet
    buf[pos] = zeichen;
    if (zeichen == '\n') {
      sscanf(buf, "%hhu-%hhu", &mot, &winkel);
      if (mot > 0 && mot < 3) {
        motor[mot-1].run(winkel);
      }
      pos = 0;
      Serial.print(mot);
      Serial.print('\t');
      Serial.print(winkel);
      Serial.print('\t');
      Serial.print(buf);
    } else {
      pos = (1 + pos) % BUFLEN;
    }
    buf[pos] = '\0';
  }
}

combie:
Hier ein "langsamer" Servo, ohne Phpoc.

Ok, warst schneller!