Autor Beitrag
MCPC10
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 35

Win 10, Win Server 2016
C# (VS 2015, VS2017, VS2019), Assembler (Atmel Studio 7.0)
BeitragVerfasst: Mo 04.01.16 20:16 
Hallo erstmal :),

Ich hoffe das ich hier richtig bin für meine Frage :)

Also ich habe das Problem das ich einen Panzer per Lenkrad über USB ansteuern möchte (Arduino) über C# und SharpDX komm ich an die Daten des Lenkrades und kann diese auch soweit interpretieren auch Serial Communication funktioniert mit dem Arduino bestens aber derzeit funktioniert die Lenkung nur wenn der Panzer ausreichend schnell ist. Hier ein bisschen Code dazu:

int leftTrackSpeed = lenkradWert * (sollGeschwindigkeit/32767// 32767 ist weil das Lenkrad bei Vollanschlag 32767 zurückgibt

Wie gesagt das Problem liegt daran, das wenn ich keine Geschwindigkeit habe die Lenkung nicht funktioniert. Wenn der Panzer sehr langsam ist, lenkt der extrem langsam, was nicht wirklich Realistisch ist :(.

Ich hoffe einer oder mehrere von euch können mir bei diesem Problem helfen.
Bei Fragen, bin ich gerne zu euren Diensten ;)

Danke :)
Ralf Jansen
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 4700
Erhaltene Danke: 991


VS2010 Pro, VS2012 Pro, VS2013 Pro, VS2015 Pro, Delphi 7 Pro
BeitragVerfasst: Mo 04.01.16 21:14 
Das drumherum kann ich nicht beurteilen aber alleine deine Zeile Code hat ein Problem.

lenkradWert und sollGeschwindigkeit sind vermutlich Integer und bei einer Division Integer/Integer kommt natürlich am Ende wieder ein Integer raus.
Bedeutet jeder Wert zwischen 0 und 32766 für sollGeschwindigkeit wird den Ausdruck zu 0 werden lassen. Auch 32766/32767 ist in Integermathematik 0 (halt mit Rest 32766 der hier aber unter den Tisch fällt).

Zum Beispiel ein (unter obiger Annahme das die Variablen Integer sind)
ausblenden C#-Quelltext
1:
int leftTrackSpeed = (int)((double)lenkradWert * (sollGeschwindigkeit / 32767.0));					

sollte näher am gewünschten sein.
MCPC10 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 35

Win 10, Win Server 2016
C# (VS 2015, VS2017, VS2019), Assembler (Atmel Studio 7.0)
BeitragVerfasst: Mo 04.01.16 22:05 
user profile iconRalf Jansen hat folgendes geschrieben Zum zitierten Posting springen:
Das drumherum kann ich nicht beurteilen aber alleine deine Zeile Code hat ein Problem.

lenkradWert und sollGeschwindigkeit sind vermutlich Integer und bei einer Division Integer/Integer kommt natürlich am Ende wieder ein Integer raus.
Bedeutet jeder Wert zwischen 0 und 32766 für sollGeschwindigkeit wird den Ausdruck zu 0 werden lassen. Auch 32766/32767 ist in Integermathematik 0 (halt mit Rest 32766 der hier aber unter den Tisch fällt).

Zum Beispiel ein (unter obiger Annahme das die Variablen Integer sind)
ausblenden C#-Quelltext
1:
int leftTrackSpeed = (int)((double)lenkradWert * (sollGeschwindigkeit / 32767.0));					

sollte näher am gewünschten sein.


Also das was ich dahin geschrieben habe ist nur eine Vereinfachung des Codes denn ich selber benutze derzeit :)
Noch Wichtig da ich über Arduino Arbeite (H-Brücke), ist 255 die maxGeschwindigkeit und sie ändert sich je nach Gas bis 0. :)

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
sollGeschwindigkeit = Convert.ToInt16(BremseGas() * (maxGeschwindigkeit / 32767f)); //BremseGas liefert einen -32767<=0=>32767 zurück je nach Lenkeinschlag
            Beschleunigungskontrolle();

            if (lenkrad > 0)
            {
                rightTrackSpeed = Convert.ToInt16(geschwindigkeit - lenkrad);
                leftTrackSpeed = geschwindigkeit;
            }
            else if (lenkrad < 0)
            {
                leftTrackSpeed = Convert.ToInt16(geschwindigkeit - (lenkrad *-1));
                rightTrackSpeed = geschwindigkeit;
            }
            else
            {
                rightTrackSpeed = geschwindigkeit;
                leftTrackSpeed = geschwindigkeit;
            }


Aber trotzdem DANKE !
icho2099
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 101
Erhaltene Danke: 12

WIN XP, WIN 7, WIN 10
Delphi 6 Prof, Delphi 2005, FPC
BeitragVerfasst: Di 05.01.16 09:55 
Da du nur die innere Kette verlangsamt, ohne die äußere zu beschleunigen, muss sich dein Fzg so verhalten.
Dem Lenkeinschlag sollte eine Drehgeschwindigkeit zugeordnet werden, und dann zu der Sollgeschwindigkeit addiert/subtrahiert (außen/innen) werden.
Das erlaubt dann auch Drehen auf der Stelle.
Mit einer nicht linearen Zuordnung Lenkeinschlag/Drehgeschwindigkeit wird das dann auch
Feinfühlig.
MCPC10 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 35

Win 10, Win Server 2016
C# (VS 2015, VS2017, VS2019), Assembler (Atmel Studio 7.0)
BeitragVerfasst: Di 05.01.16 18:25 
user profile iconicho2099 hat folgendes geschrieben Zum zitierten Posting springen:
Da du nur die innere Kette verlangsamt, ohne die äußere zu beschleunigen, muss sich dein Fzg so verhalten.
Dem Lenkeinschlag sollte eine Drehgeschwindigkeit zugeordnet werden, und dann zu der Sollgeschwindigkeit addiert/subtrahiert (außen/innen) werden.
Das erlaubt dann auch Drehen auf der Stelle.
Mit einer nicht linearen Zuordnung Lenkeinschlag/Drehgeschwindigkeit wird das dann auch
Feinfühlig.


Also die Idee gefällt mir aber wenn ich 255 als max Wert habe und wenn ich das Gas durchdrücke kann keine Lenkung mehr dazu tun (denn Arduino 255 = Motordrehzahl am Limit) oder wie meinst du es. Danke nochmal ;)
ausblenden C#-Quelltext
1:
2:
3:
lenkrad = lenkung * (255/32767f);

leftTrackSpeed = (gas + lenkrad) * (255/512f);


Meinst du so oder verstehe ich was falsch (Code aus den Gedanken, kann Fehler enthalten) :)

Danke nochmal !
icho2099
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 101
Erhaltene Danke: 12

WIN XP, WIN 7, WIN 10
Delphi 6 Prof, Delphi 2005, FPC
BeitragVerfasst: Di 05.01.16 23:53 
Natürlich musst du den Wertebereich für die Stellgrößen begrenzen. Und am Limit ist am Limit.
Dann geht kein Addieren mehr, aber Subtrahieren auf der Innenseite geht immer noch.
Also zunächst alle Werte berechnen, dann auf den Bereich der Stellgrößen skalieren und ggf.
am Limit abschneiden.
Ich würde den Range der Lenkung, also die Steigung der Funktion
Lenkeinschlag-->Drehgeschwindigkeit, von der Sollgeschwindigkeit abhängig machen. Damit erreichst du bei hoher Geschwindigkeit kleinere Lenkwirkung und verhinderst Überschläge.
Und ein kleiner Totbereich um den Lenkeinschlag 0 herum verhindert das Zappeln bei Geradeausfahrt.
MCPC10 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 35

Win 10, Win Server 2016
C# (VS 2015, VS2017, VS2019), Assembler (Atmel Studio 7.0)
BeitragVerfasst: Mi 06.01.16 14:41 
user profile iconicho2099 hat folgendes geschrieben Zum zitierten Posting springen:
Natürlich musst du den Wertebereich für die Stellgrößen begrenzen. Und am Limit ist am Limit.
Dann geht kein Addieren mehr, aber Subtrahieren auf der Innenseite geht immer noch.
Also zunächst alle Werte berechnen, dann auf den Bereich der Stellgrößen skalieren und ggf.
am Limit abschneiden.
Ich würde den Range der Lenkung, also die Steigung der Funktion
Lenkeinschlag-->Drehgeschwindigkeit, von der Sollgeschwindigkeit abhängig machen. Damit erreichst du bei hoher Geschwindigkeit kleinere Lenkwirkung und verhinderst Überschläge.
Und ein kleiner Totbereich um den Lenkeinschlag 0 herum verhindert das Zappeln bei Geradeausfahrt.


Haste auch eine Idee wie ich das schreiben soll, also ein Code Beispiel, denn ich verstehe noch nicht wie ich das Programmieren soll. :)

Danke :)
icho2099
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 101
Erhaltene Danke: 12

WIN XP, WIN 7, WIN 10
Delphi 6 Prof, Delphi 2005, FPC
BeitragVerfasst: Fr 08.01.16 16:02 
Hallo,

weil C jetzt nicht so meins ist, hab ich was in Delphi gebastelt.
Vielleicht hilft dir das ja, guckst du Anhang.

Ein paar Konstante und globale Variable:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
Const
  //Lenkeinschlag: Annahme ist, dass die Lenkradstellung als Integer mit 12 Bit Auflösung
  //               geliefert wird und die Neutralstellung in der Mitte des Wertebereichs liegt
  cLEmin       =     0;       //LenkEinschlag voll links
  cLEmax       =  4095;       //LenkEinschlag voll rechts
  cLEOffset    =  2047;       //Offset für die Neutralstellung
  cLETh        =    16;       //Totzone um die Neutralstellung

  //Gashebel: Annahme ist, dass die Gashebelstellung als Integer mit 12 Bit Auflösung
  //          geliefert wird. Neutralstellung mitte.
  //          
  cGmin        =     0;
  cGmax        =  4095;
  cGOffset     =  2047;
  cGTh         =    16;


Var
  fLE          : Integer;     //aktuelle Lenkradstellung
  fLEAdapt     : Boolean;     //Lenkeinschlag an Vsoll anpassen ja/Nein
  fG           : Integer;     //aktuelle Gashebelstellung
  fVL          : Integer;     //Sollwert Geschwindigkeit Links
  fVR          : Integer;     //Sollwert Geschwindigkeit Rechts


Und dann wie du die Werte für die beiden Antriebe berechnen kannst.
Die Skalierung auf 8-Bit 0..255 oder -127..128 kriegst du sicher auch
alleine hin.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
//Werte berechnen
Procedure tForm1.DoIt;
Var V  : Integer;
    k  : Double;
begin
  //Lenkeinschlag:
  //Offset beseitigen: Neutralstellung = 0
  fLE := fLE - cLEOffset;
  //Nullpunkt Totbereich ausblenden
  If (fLE > -cLETh) AND (fLE < cLETh) then fLE := 0 else
  If (fLE < 0then fLE := fLE + cLETh else fLE := fLE - cLETh;

  //Sollwerte Geschwindigkeit/Gashebel:
  //Offset beseitigen:
  V   := fG - cGOffset;
  //Nullpunkt Totbereich ausblenden
  If (V > -cGTh) AND (V < cGTh) then V := 0 else
  If (V < 0then V := V + cGTh else V := V - cGTh;



  //Lenkwirkung abhängig von Gashebelstellung machen:
  //Lenkwirkung wird mit zunehmender Sollgeschwindigkeit kleiner
  If fLEAdapt then begin
    //Verhältnis V zu Vmax: in k abbilden
    k := 1 - (Abs(V) / (cGmax-cGOffset));
    //k reduziert den Lenkeinschlag proportional zu V
    fLE := Round(fLE * k);
  end;


  //Sollwerte für die beiden Ketten setzt sich aus
  //Gashebelstellung und Lenkeinschlag zusammen
  fVL := V + fLE;
  fVR := V - fLE;


  //Visualisierung der Werte;
  LblVL.Caption := IntToStr(fVL);
  LblVR.Caption := IntToStr(fVR);

end;


Der Rest ist nur schmückendes Beiwerk.

Moderiert von user profile iconTh69: Code- durch Delphi-Tags ersetzt
Einloggen, um Attachments anzusehen!

Für diesen Beitrag haben gedankt: MCPC10
MCPC10 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 35

Win 10, Win Server 2016
C# (VS 2015, VS2017, VS2019), Assembler (Atmel Studio 7.0)
BeitragVerfasst: Di 19.01.16 18:23 
So, hallo erstmal und danke für deinen Beitrag, hatte wegen der Schule (und Après Ski :) ) bis jetzt nicht wirklich Zeit gehabt ;)

Da ich Delphi nicht kenne, kann ich nicht wirklich viel mit dem Source anfangen aber deine Software sieht extrem "Geil" aus :)

Ich versuche mal zu verstehen wie das geht aber wie gesagt Delphi war mir bis jetzt, noch unbekannt :).

Moderiert von user profile iconTh69: Full-Quotes entfernt.
MCPC10 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 35

Win 10, Win Server 2016
C# (VS 2015, VS2017, VS2019), Assembler (Atmel Studio 7.0)
BeitragVerfasst: Mo 22.02.16 22:02 
Konnte deinen Source jetzt endlich lesen :) und in meinen C# Source einfügen. Wenn jemand interesse an Code hat dann bitte melden.

Habe jetzt noch eine andere frage, wenn jemand eine idee hat wie man eine bessere Geschwindigkeitskonrolle macht wäre ich ihm dankbar, denn derzeit nutze ich die Zei t aber das ist noch nicht so optimal den ich will das wenn man die Bremse drückt der "Motor" schneller abbremsen tut und das er auch langsam anfährt.

Danke nochmal für den Delphi Code und ich würde mich sehr freuen wenn mir jemand mit der Geschwindigkeitskonrolle helfen könnte. :)