Seite 4 von 5

#46 Re: Servo Position-Halten - Adruino Nano

Verfasst: 31.07.2018 19:59:42
von CubaLibreee
Mach ich was falsch? Beim Hochladen von Sketch von Tim folgender Fehler:
Unbenannt.jpg
Ach ja. Meine Nanos sind endlich da...

#47 Re: Servo Position-Halten - Adruino Nano

Verfasst: 31.07.2018 20:37:26
von telicopter
Bitte keine Aneinanderreihung verschiedener Codes machen. ;) Wenn du einen hier geposteten Code verwenden möchtest, musst du diesen immer in einen komplett leeren! Sketch kopieren und hochladen. Ansonsten kommt es nämlich zu doppelt deklarierten Variablen und mehr als einer Main/Loop Funktion

Viele Grüße und viel Glück
Tim

#48 Re: Servo Position-Halten - Adruino Nano

Verfasst: 31.07.2018 20:49:51
von CubaLibreee
Jetzt hab ichs. hab nen falschen Code benutzt. Dein letzter geht nun auf anhieb! :mrgreen:

Dann geh ich mal fix etwas löten...

Bis später... :mrgreen: :mrgreen:

#49 Re: Servo Position-Halten - Adruino Nano

Verfasst: 31.07.2018 21:17:11
von telicopter
Wollte doch meinen, dass das in dem Bild nicht mein Code ist :mrgreen:

#50 Re: Servo Position-Halten - Adruino Nano

Verfasst: 31.07.2018 21:29:53
von telicopter
Und bitte bedenken, dass ich bei mir im Code die Pins D5-D7 als Eingänge und die Pins D8-D10 als Ausgänge definiert habe. Wenn du das anders haben willst, muss du die Zuweisung oben in den Defines entsprechend ändern. :)

Grüße Tim

#51 Re: Servo Position-Halten - Adruino Nano

Verfasst: 31.07.2018 21:45:35
von CubaLibreee
telicopter hat geschrieben:Und bitte bedenken, dass ich bei mir im Code die Pins D5-D7 als Eingänge und die Pins D8-D10 als Ausgänge definiert habe. Wenn du das anders haben willst, muss du die Zuweisung oben in den Defines entsprechend ändern. :)

Grüße Tim
Ich bin zwar blöd in Sachen Elektronik und programmieren aber net ganz blöd. Konnte soweit deinen Code noch lesen! Und was soll ich sagen! Geiler Scheiß!!! Mit deinem Standard Code viel viel besser als die Kaufmodule!!!
Knüppelmitte passt nicht ganz das habe ich einfach am Sender mit dem Servotrimm erledigt. Und die Auflösung Knüppel - Servo ist mir zu extrem. Sprich ich wünsch mir das etwas mehr Expo. Sollte aber auch mit dem Sender machbar sein.
Wenn du jetzt noch das LED ON OFF mit rein packst, hast n Kasten Bier gewonnen! :mrgreen:

Ich lad noch fix n Video hoch dauert nur noch n kleinen Mom...

Edit: sind die A0 bis A7 auch zu verwenden das ich den Code z.B so umschreibe das die A Pins die Eingänge sind und die D Pins die Ausgänge oder ist das nicht möglich???

#52 Re: Servo Position-Halten - Adruino Nano

Verfasst: 31.07.2018 21:59:25
von CubaLibreee
Erster Test mit Tim´s Code ohne Feintuning am Sender und am Code!!! :mrgreen: :mrgreen: :mrgreen:

https://youtu.be/3u-Dl7HAPK0

Klasse echt!!!
:blob5:

#define MAX_SPEED 30 //Maximale Geschwindigkeit bei Knüppelvollausschlag (Microsekunden-Inkrement je Berechnungsschritt)
#define RC_TOTZONE 40 //Totzone um die Knüppelmitte

umgedingselt. Perfekt!!! :mrgreen:

Geil!!!

#53 Re: Servo Position-Halten - Adruino Nano

Verfasst: 31.07.2018 22:16:12
von telicopter
Wollte nur ein paar Fehler von vornherein ausschließen. :mrgreen:
Schön dass es soweit schon mal funktioniert. Ich bin gerade erstaunt darüber, wie schnell die Servos bei dir laufen. :shock: Also wenn dir das zu schnell ist, dreh einfach mal den Parameter MAX_SPEED ein bisschen runter ( vielleicht mal auf 10 oder 20). Der definiert die maximale Schrittweite, mit der die Servoposition bei Knüppelvollausschlag pro Schleifenzyklus inkrementiert wird.

Die LED zu implementieren, sollte kein Problem sein. Ich habe nur Bedenken, dass die zusätzliche Kanalabfrage zu einem Anstieg des Servoruckelns führen könnte. Aber Versuch macht ja bekanntlich klug und wie es aussieht, scheint dein Arduino etwas zackiger im Rechnen zu sein. Wer weiß, was für ein altes Toastbrot von Arduino ich hier gerade liegen hatte :mrgreen:

#54 Re: Servo Position-Halten - Adruino Nano

Verfasst: 31.07.2018 22:38:41
von CubaLibreee
Hier das sind die Guten Stücke: Klick

Werde die Tage noch ein nettes Gehäuse drucken, sauber verkabeln und Stecker beschriften, dann in Prototyp Bagger implantieren und bissi im Wohnzimmer spielen und mich so langsam mit der Steuerung vertraut machen.

Ich steh in deiner Schuld mein Guter! :P

#55 Re: Servo Position-Halten - Adruino Nano

Verfasst: 01.08.2018 00:14:40
von telicopter
Wenn ich mal Hilfe beim 3D-Druck brauche, weiß ich ja, an wen ich mich wenden muss. :mrgreen:

Die LED Funktion habe ich jetzt mal implementiert. Allerdings habe ich gerade keinen Arduino zur Hand, sodass ich das Testen dir überlasse. :wink: Ne kleine LED kannst du mit entsprechendem Vorwiderstand direkt mit dem Arduino ansteuern. Alles was darüber hinaus geht, benötigt dann entsprechend einen Transistor oder einen LED-Treiber, um dir nicht den Arduino zu grillen.
Wenn du Lust hast, kannst du auch mal versuchsweise die Filterfunktionen etwas entschärfen, da diese hauptsächlich von der Signalqualität des verwendeten Empfängers abhängen. Es könnte gut sein, dass dein Empfänger weniger rauscht und durch eine Reduktion der Filterung noch etwas "Control-Authority" herauszuholen ist. :D
Also vielleicht einfach mal LM_SIZE = 1 und wenn noch nichts zuckt oder wandert, die RC_TOLERANCE etwas herabsetzen. Ansonsten halt einfach alles so lassen wie es ist. :mrgreen:

Code: Alles auswählen

#include <Servo.h>

#define LED_RC_PIN 4       //Empfänger LED-Steuerkanal D4
#define RC1_PIN 5       //Empfänger Steuer-Kanal D5
#define RC2_PIN 6       //Empfänger Steuer-Kanal D6
#define RC3_PIN 7        //Empfänger Steuer-Kanal D7

#define SERVO1_PIN 8    //Servosteuerleitung D8
#define SERVO2_PIN 9    //Servosteuerleitung D9
#define SERVO3_PIN 10    //Servosteuerleitung D10
#define LED_OUT_PIN 11   //LED Steuerleidung D11

#define RC_MIN  1000      //Maximale und minimale Pulslänge 
#define RC_MAX  2000
#define MAX_SPEED 50      //Maximale Geschwindigkeit bei Knüppelvollausschlag (Microsekunden-Inkrement je Berechnungsschritt)
#define RC_TOTZONE 10     //Totzone um die Knüppelmitte
#define RC_INPUT_TOLERANCE 35     //Toleranzbereich der RC-EIngangssignale in Microsekunden
#define LM_SIZE 2         //Breite des Laufenden Mittelwert-Filters

Servo servo_1;
Servo servo_2; 
Servo servo_3;


unsigned int prevPulse [3] = {0, 0, 0};    //letzte berechnete Pulsweite
unsigned int actPulse [3] ={0, 0, 0};      //aktuelle berechnete Pulsweite
unsigned int LM[LM_SIZE][3];              // Letzte Messungen
unsigned int sum [3]= {0, 0, 0};          //Summe aller Messungen
int channelPin[3] = {RC1_PIN, RC2_PIN, RC3_PIN};       //Array mit den Servobelegungen
unsigned int servoPosition[3] = {1500, 1500, 1500};   //aktuelle Servoposition als Pulsweite
byte index = 0;     //Position im Array der Messwerte



void setup()
{
  servo_1.attach(SERVO1_PIN);
  servo_2.attach(SERVO2_PIN);
  servo_3.attach(SERVO3_PIN);

  InitializeLMArray();    //Initialisierung der Filterfunktion
  pinMode (LED_OUT_PIN, OUTPUT); 
  
  Serial.begin(115200);
}


void loop()
{
  readChannelFiltered();
  LEDcontrol();
}



/*****************************************************************************************************************************
// Funktion zum Simulieren der Hydraulik-Eigenschaften
//
*****************************************************************************************************************************/
unsigned int Hydraulik(int pulse, int servoNr )
{
  if (abs( pulse - 1500) <= RC_TOTZONE)   //Anpassung der RC-Totzone in der Knüppelmitte
  {
    pulse = 1500;
  }
  
  int correction = map(pulse, RC_MIN, RC_MAX, -MAX_SPEED, MAX_SPEED); 
  servoPosition[servoNr]  +=  correction;

  if ( servoPosition[servoNr] <= RC_MIN  )
  {
    servoPosition[servoNr] = RC_MIN;
  }
  if ( servoPosition[servoNr] >= RC_MAX)
  {
     servoPosition[servoNr] = RC_MAX;
  }
  return servoPosition[servoNr];
}



/*****************************************************************************************************************************
// Funktion zum Auslesen und Filtern der RC-Eingangskanäle mithilfe eines laufenden Mittelwertfilters
//
*****************************************************************************************************************************/
void readChannelFiltered()
{
   unsigned int currPulse;
   
   for (int i = 0; i <= 2 ; i++)
   {
      currPulse = pulseIn(channelPin[i], HIGH, 25000);  //Aufnahme der RC-Pulsweite
      if(currPulse == 0)
      {
        currPulse = 1500;  //Ausgabe des Neutralwertes, wenn kein gültiger Puls vorhanden
      }
 
 
      sum [i] -= LM[index][i];    //Berechnung des gleitenden Mittelwertes
      LM[index][i] = currPulse;
      sum[i] += LM[index][i];

      actPulse[i] =  sum [i] / LM_SIZE;   //Gleitender Mittelwert wird zur aktuellen Pulsweite
      
      
      if ( abs (prevPulse[i] - actPulse[i]) <= RC_INPUT_TOLERANCE)    //Unterdrückung von Servozittern durch die Einführung eines Toleranzbereiches 
      {                                                               //Wenn neuer Wert innerhalb der Toleranz liegt, wird der alte Wert weiterverwendet
         actPulse[i] = prevPulse[i];
      }
     
      prevPulse[i] = actPulse[i];
      
     servo_1.writeMicroseconds(Hydraulik(actPulse[0], 0)); //Möglichst häufige Ansteuerung der Servos für einen flüssigeren Lauf
     servo_2.writeMicroseconds(Hydraulik(actPulse[1], 1));
     servo_3.writeMicroseconds(Hydraulik(actPulse[2], 2));
   }
   
   index++;
   index = index % LM_SIZE;
}



/*****************************************************************************************************************************
// Funktion zum Ansteuern einer LED
//
*****************************************************************************************************************************/
void LEDcontrol()
{
  unsigned int currPulse = pulseIn(LED_RC_PIN, HIGH, 25000);  

  if (currPulse >= 1500)
  {
    digitalWrite (LED_OUT_PIN, HIGH);
  }
  else 
  {
    digitalWrite (LED_OUT_PIN, LOW);
  }
}



/*****************************************************************************************************************************
// Initialisierungsfunktion zum Auffüllen aller Arraywerte 
//
*****************************************************************************************************************************/
void InitializeLMArray()
{
  while ( index < LM_SIZE)
  {
   unsigned int currPulse;
   
   for (int i = 0; i <= 2 ; i++)
   {
    
      currPulse = pulseIn(channelPin[i], HIGH, 25000);  //Aufnahme der RC-Pulsweite
      if(currPulse == 0)
      {
        currPulse = 1500;   //Ausgabe des Neutralwertes, wenn kein gültiger Puls vorhanden
      }
 
      sum [i] -= LM[index][i];    //Berechnung des gleitenden Mittelwertes
      LM[index][i] = currPulse;
      sum[i] += LM[index][i];

      actPulse[i] =  sum [i] / (index + 1 );   //Gleitender Mittelwert wird zur aktuellen Pulsweite
      
      
      if ( abs (prevPulse[i] - actPulse[i]) <= RC_INPUT_TOLERANCE)    //Unterdrückung von Servozittern durch die Einführung eines Toleranzbereiches 
      {                                                               //Wenn neuer Wert innerhalb der Toleranz liegt, wird der alte Wert weiterverwendet
         actPulse[i] = prevPulse[i];
      }
     
      prevPulse[i] = actPulse[i];
   }

    servo_1.writeMicroseconds(1500); //Servoposition in Neutrallage halten bis Initialisierung beendet
    servo_2.writeMicroseconds(1500);
    servo_3.writeMicroseconds(1500);
   
   index++;
  }
  index = 0;
}

#56 Re: Servo Position-Halten - Adruino Nano

Verfasst: 05.08.2018 19:25:00
von CubaLibreee
Hi Tim,

so habe gestern und heute die 3x Nanos verlötet und eins davon in meinen Prototyp Bagger eingebaut. Ich war am verzweifeln, hat ewig nicht funktioniert. Erst als ich den Skectch ohne LED drauf gespielt hatte ging wieder alles so wie gewohnt! Bei dem Sketch mit LED kann ich zwar die LED steuern, aber nur ein Servo von den dreien!??

Ich habe den LED + direkt an D11 gelötet. Dazwischen ist ein Widerstand! Kann die LED auch steuern mit dem Entsprechenden Kanal. Aber wie gesagt 2x Servos sind dann Tod?!?

Hast du eine Idee???

#57 Re: Servo Position-Halten - Adruino Nano

Verfasst: 05.08.2018 23:05:30
von telicopter
Hi,
erstmal sorry, dass es nicht funktioniert hat. Ich hatte den Code wie gesagt nur geschrieben und nicht mehr getestet. Da ich jetzt allerdings gerade wieder alle nötigen Sachen da hatte, habe ich noch mal ein Paar Zeilen überarbeitet, sodass es zumindest bei mir jetzt wieder läuft. Allerdings scheint der Servolauf jetzt noch ruckeliger geworden zu sein, da wir im schlimmsten Fall zusätzliche 20ms auf einen Eingangspuls des LED-Kanals warten müssen. So wie es aussieht, ist hier wohl ( zumindest mit meinen eingeschränkten Fähigkeiten) die Grenze erreicht, bei denen sich die ganzen Timer und Interrupts so gerade eben noch nicht gegenseiten blockieren. Ich persönlich würde die LED Funktion wohl doch besser extern mit einer kleinen Servoelektronik lösen und dafür die restliche Servosteuerung etwas smoother gestalten. Wenn der neue Code allerdings zufriedenstellend bei dir läuft, spricht natürlich nichts dagegen, das ganze doch über den Arduino laufen zu lassen.

Grüße
Tim

Code: Alles auswählen

#include <Servo.h>

#define LED_RC_PIN 4       //Empfänger LED-Steuerkanal D4
#define RC1_PIN 5       //Empfänger Steuer-Kanal D5
#define RC2_PIN 6       //Empfänger Steuer-Kanal D6
#define RC3_PIN 7        //Empfänger Steuer-Kanal D7

#define SERVO1_PIN 8    //Servosteuerleitung D8
#define SERVO2_PIN 9    //Servosteuerleitung D9
#define SERVO3_PIN 10    //Servosteuerleitung D10
#define LED_OUT_PIN 11   //LED Steuerleidung D11

#define RC_MIN  1000      //Maximale und minimale Pulslänge 
#define RC_MAX  2000
#define MAX_SPEED 50      //Maximale Geschwindigkeit bei Knüppelvollausschlag (Microsekunden-Inkrement je Berechnungsschritt)
#define RC_TOTZONE 10     //Totzone um die Knüppelmitte
#define RC_INPUT_TOLERANCE 35     //Toleranzbereich der RC-EIngangssignale in Microsekunden
#define LM_SIZE 2         //Breite des Laufenden Mittelwert-Filters

Servo servo_1;
Servo servo_2; 
Servo servo_3;


unsigned int prevPulse [4] = {0, 0, 0, 0};    //letzte berechnete Pulsweite
unsigned int actPulse [4] ={0, 0, 0, 0};      //aktuelle berechnete Pulsweite
unsigned int LM[LM_SIZE][4];              // Letzte Messungen
unsigned int sum [4]= {0, 0, 0, 0};          //Summe aller Messungen
int channelPin[4] = {RC1_PIN, RC2_PIN, RC3_PIN, LED_RC_PIN};       //Array mit den Servobelegungen
unsigned int servoPosition[4] = {1500, 1500, 1500, 1500};   //aktuelle Servoposition als Pulsweite
byte index = 0;     //Position im Array der Messwerte



void setup()
{
  servo_1.attach(SERVO1_PIN);
  servo_2.attach(SERVO2_PIN);
  servo_3.attach(SERVO3_PIN);

  InitializeLMArray();    //Initialisierung der Filterfunktion
  pinMode (LED_OUT_PIN, OUTPUT); 
  
  Serial.begin(115200);
}


void loop()
{
  readChannelFiltered();
  LEDcontrol(actPulse[3]);
}



/*****************************************************************************************************************************
// Funktion zum Simulieren der Hydraulik-Eigenschaften
//
*****************************************************************************************************************************/
unsigned int Hydraulik(int pulse, int servoNr )
{
  if (abs( pulse - 1500) <= RC_TOTZONE)   //Anpassung der RC-Totzone in der Knüppelmitte
  {
    pulse = 1500;
  }
  
  int correction = map(pulse, RC_MIN, RC_MAX, -MAX_SPEED, MAX_SPEED); 
  servoPosition[servoNr]  +=  correction;

  if ( servoPosition[servoNr] <= RC_MIN  )
  {
    servoPosition[servoNr] = RC_MIN;
  }
  if ( servoPosition[servoNr] >= RC_MAX)
  {
     servoPosition[servoNr] = RC_MAX;
  }
  return servoPosition[servoNr];
}



/*****************************************************************************************************************************
// Funktion zum Auslesen und Filtern der RC-Eingangskanäle mithilfe eines laufenden Mittelwertfilters
//
*****************************************************************************************************************************/
void readChannelFiltered()
{
   unsigned int currPulse;
   
   for (int i = 0; i <= 3 ; i++)
   {
     currPulse = pulseIn(channelPin[i], HIGH, 35000);  //Aufnahme der RC-Pulsweite
      if(currPulse == 0)
      {
        currPulse = 1500;  //Ausgabe des Neutralwertes, wenn kein gültiger Puls vorhanden
      }
 
 
      sum [i] -= LM[index][i];    //Berechnung des gleitenden Mittelwertes
      LM[index][i] = currPulse;
      sum[i] += LM[index][i];

      actPulse[i] =  sum [i] / LM_SIZE;   //Gleitender Mittelwert wird zur aktuellen Pulsweite
      
      
      if ( abs (prevPulse[i] - actPulse[i]) <= RC_INPUT_TOLERANCE)    //Unterdrückung von Servozittern durch die Einführung eines Toleranzbereiches 
      {                                                               //Wenn neuer Wert innerhalb der Toleranz liegt, wird der alte Wert weiterverwendet
         actPulse[i] = prevPulse[i];
      }
     
      prevPulse[i] = actPulse[i];
      
     servo_1.writeMicroseconds(Hydraulik(actPulse[0], 0)); //Möglichst häufige Ansteuerung der Servos für einen flüssigeren Lauf
     servo_2.writeMicroseconds(Hydraulik(actPulse[1], 1));
     servo_3.writeMicroseconds(Hydraulik(actPulse[2], 2));
   }
   
   index++;
   index = index % LM_SIZE;
}



/*****************************************************************************************************************************
// Funktion zum Ansteuern einer LED
//
*****************************************************************************************************************************/
void LEDcontrol(unsigned int LEDpulse)
{
    

  if (LEDpulse >= 1500)
  {
    digitalWrite (LED_OUT_PIN, HIGH);
  }
  else 
  {
    digitalWrite (LED_OUT_PIN, LOW);
  }
}



/*****************************************************************************************************************************
// Initialisierungsfunktion zum Auffüllen aller Arraywerte 
//
*****************************************************************************************************************************/
void InitializeLMArray()
{
  while ( index < LM_SIZE)
  {
   unsigned int currPulse;
   
   for (int i = 0; i <= 3 ; i++)
   {
    
     currPulse = pulseIn(channelPin[i], HIGH, 25000);  //Aufnahme der RC-Pulsweite
      if(currPulse == 0)
      {
        currPulse = 1500;   //Ausgabe des Neutralwertes, wenn kein gültiger Puls vorhanden
      }
 
      sum [i] -= LM[index][i];    //Berechnung des gleitenden Mittelwertes
      LM[index][i] = currPulse;
      sum[i] += LM[index][i];

      actPulse[i] =  sum [i] / (index + 1 );   //Gleitender Mittelwert wird zur aktuellen Pulsweite
      
      
      if ( abs (prevPulse[i] - actPulse[i]) <= RC_INPUT_TOLERANCE)    //Unterdrückung von Servozittern durch die Einführung eines Toleranzbereiches 
      {                                                               //Wenn neuer Wert innerhalb der Toleranz liegt, wird der alte Wert weiterverwendet
         actPulse[i] = prevPulse[i];
      }
     
      prevPulse[i] = actPulse[i];
   }

    servo_1.writeMicroseconds(1500); //Servoposition in Neutrallage halten bis Initialisierung beendet
    servo_2.writeMicroseconds(1500);
    servo_3.writeMicroseconds(1500);
   
   index++;
  }
  index = 0;
}

#58 Re: Servo Position-Halten - Adruino Nano

Verfasst: 06.08.2018 05:54:25
von CubaLibreee
Ist doch kein Problem. Ich teste ihn heute Abend. Und sonst mach ich die LEDs einfach über die olle Servosteuerung...

Dankeeeeeee...

#59 Re: Servo Position-Halten - Adruino Nano

Verfasst: 06.08.2018 18:09:54
von CubaLibreee
Code getestet. Funzt prima! Guter Mann...!!!
Dankeeeeeeee

#60 Re: Servo Position-Halten - Adruino Nano

Verfasst: 06.08.2018 21:57:32
von telicopter
Super, freut mich! Wenn noch Probleme da sind, kannst du dich ja hier melden. ;) Ansonsten bin ich natürlich sehr daran interessiert, dass du uns hier mit den weiteren Bauabschnitten auf dem Laufenden hälst :mrgreen:

Grüße Tim