Hallo erstmal,
also ich hab einen etwas lustigen 8051 ähnlichen prozessor der sehr
langsam ist und..
Addieren
Subrahieren
Shiften
und if abfragen kann.
und ich hab 2 Messwerte die mir X und Y werte darstellen, ich hab noch
ca. 40 Zeilen an Code frei ( rest komplett verbraucht ), und würde gerne
Radius ( auflöung von 3~4 Bit reicht vollkommen ) und Entfernung zum
Mittelpunkt errechnen, Genauigkeit ist nicht ganz so tragisch.
Lookup Table oder gibts einen Mathe Guru der nen gute Trick kennt?
Radius und Entfernung zum Mittelpunkt ist für mich dasselbe...
Sinus braucht man dafür nicht, dafür aber Pythagoras.
- X soweit nach rechts schieben, bis nur 4 Bit übrigbleiben
(bei 8-bit Werten 4x bei 16-Bit Werten da High-Byte 4x)
- in zwei Register laden, Summe=0
a) solange zweites Register >0, erstes Register zur Summe addieren
wenn zweites Register >0 dann springe nach a)
- im Summenregister steht jetzt X^2
- mit Y und einem anderen Summenregister genauso verfahren
- beide Quadrate addieren
- resultat=0, diff=1
wenn bei der Summe ein Übertrag aufgetreten ist, resultat=16, diff=33
b) wenn diff>low(summe) dann ende
- resultat=resultat+1, summe(low)=summe(low)-diff, diff=diff+2
- goto b
Ob das jetzt in 40 "Zeilen" noch reingeht, weiss ich leider nicht.
Gruß Jörg
ja dürfte sich ausgehen, beim Cordic Algo muss ich soweit ichs bis jetzt
verstanden hab einen atan Lookup Table bauen, denk nicht das ich soviel
platz hab.
kannst du das in einem Pseudo C erklären? ( hab 8 Bit eingang und 8 Bit
ausgang )
danke für die Info,
nunja ich vermute zurzeit eher das die Skalierung meiner zahlen das
problem ist, meine Eingangswerte für X und Y sind 0 bis 255 und als
ausgang hätte ich einen Radius von 0 bis 255 und einen Winkel von 0 bis
8
der Mittelpunkt meines kreises ist x=127 y=127
ich glaub ich schaff es sogar 50 Zeilen rauszuboxen, problem ist mein
Ram hat nur 16Bytes, wie genau die atan Lookup Table sein muss hab ich
auch noch nicht abgecheckt ...
Also anstatt eines sinus hab ich ein "quasi Rechteck geschaffen, das is
jetzt eine 255x255er Anzeige
code dazu:
uchar sinus( int z )
{
int x = 255;
int y = 0;
int dx = 0;
int dy = 0;
int i = 0;
// Form1->Memo1->Clear();
for ( i = 0; i < 8 ; i++ )
{
dx = x >> i;
dy = y >> i;
if( z > 127 )
{
x = x - dy;
y = y + dx;
z = z - atan(128>>i)*64;
}
else
{
x = x + dy;
y = y - dx;
z = z + atan(128>>i)*64;
}
// Form1->Memo1->Lines->Add(
AnsiString().sprintf("x:%dy:%dz:%d",x,y,z) );
}
return y;
}
Jankey wrote:
> ausgang hätte ich einen Radius von 0 bis 255 und einen Winkel von 0 bis> 8
0 bis 8?
0 bis 7 (inklusive) als Integer?
dazu brauchst du keinen atan, das geht mit Koordinatenvergleich
und einer if-then-else Kaskade.
(px/py ... Koordinaten des Punktes
mx/my ... Koordinaten des Mittelpunktes
1
dx=px-mx
2
dy=py-my
3
4
if(dx>0)
5
if(dy>0)
6
if(dx>dy)
7
Winkel=0
8
else
9
Winkel=1
10
else
11
if(dx>-dy)
12
Winkel=7
13
else
14
Winkel=6
15
else
16
if(dy>0)
17
if(-dx>dy)
18
Winkel=3
19
else
20
Winkel=2
21
else
22
if(-dx>-dy)
23
Winkel=4
24
else
25
Winkel=5
Einfach mal einen Kreis aufzeichnen, die 8 Sektoren einzeichnen
und überlegen, welche Abhängigkeiten für die X und Y Koordinaten
in jedem Sektor gelten.
Eigentlich suche ich sowas:
Angle[0~248] = aTan(y/x);
das aTan mit y/x zu realisieren mit Cordic erstellt sich als etwas
schwierig, zumals ich nur 8 Bit Rechenbreite zur verfügung habe und alle
mit 16 Bit und mehr rechnen. Koordinatenvergleich is keine Ausreichend
genaue Methode.
lg
so mit dem Ding schafft man einen Sauberen 8 Bit Sinus
Mittelpunkt ist 127
int i = 0;
for ( i = 0; i < 8 ; i++ )
{
y -= (x >> i);
x += (y >> i);
}
return y;
so, problem bei der Berechnung ist das er aus irgend einem Grund 2x den
Winkel durchrechnet, hat eigentlich einer von denen die CORDIC hier
gepostet haben auch wirklich mal versucht in einem uController
nachzubauen?
uchar phi( int x , int y )
{
int z = 128;
int i = 0;
int X = x;
int Y = z;
for (i = 1; i <= 10; ++i)
{
x >>= 1;
z >>= 1;
if( Z < 0 )
{
Y += x;
Z -= z;
}
else
{
Y -= x;
Z += z;
}
}
return Z;
}
Nein, hab auch bisher noch keinen Cordic benutzt, aber das ist die
einfachste genaue Methode.
Gehts jetzt um den Radius oder den Winkel? Es gibt noch eine sehr simple
Näherung für den Radius: Betrag der längeren Koordinate plus 0,4142 *
der Betrag der kürzeren. Das stimmt exakt alle 45 Grad. Ich habs mal
benutzt um niederfrequente AM zu demodulieren.
Also Winkel ist vorrangig, wenn der Radius "kann" egal sein, schöner
wärs natürlich wenn ich ihn noch reinklopfen könnte, zurzeit überlege
ich mithilfe eines Integrators eine Sinusähnliche Kennlinie nachzubauen
...
irgendwie komm ich einfach nicht auf den Winkel von 255*atan(y/x)...
Jankey wrote:
> irgendwie komm ich einfach nicht auf den Winkel von 255*atan(y/x)...
Rein aus dem Bauch heraus würde ich mal sagen: da gibt es auch
keine vernünftige Näherung. Der tan, und damit auch die
Umkehrfunktion, ist eine sehr unangenehme Funktion.
Mal anders aufgezäumt: Wozu brauchst du den das Ganze. Vielleicht
gibt es eine Möglichkeit ohne den Winkel auszukommen.
ich hab 2 Eingangssignale als X und Y Positions und will die Richtung
anzeigen in die die 2 Werte Zeigen, problem dabei, das system in das ich
anzeigen will ist Radial ...
Jankey wrote:
> ich hab 2 Eingangssignale als X und Y Positions und will die Richtung> anzeigen in die die 2 Werte Zeigen,
Muss das eine Zahlenanzeige sein oder reicht ein Pfeil, der
in die richtige Richtung weist?
> X und Y Positions
sind das Positionen in einem kartesischen Koordinatensystem?
(Im Moment spukt mir der Begriff 'ähnliche Dreiecke' durch
den Kopf. Erzähl mal mehr über den Input)
Jankey wrote:
> Ja Karthesische Eingangskoordinaten von 0 bis 255 auf X und Y, ausgang> ist dann eine Polare sagen wir mal "anzeige" ...
Grrrrrr
Kannst du nicht mal ein bischen konkreter werden.
Was ist so schwer daran, zu sagen:
Ich habe einen Joystick und möchte die Auslenkung dem
Benutzer anzeigen.
* Als Anzeige habe ich ein LCD auf dem Auslenkung und Winkel
in Form von Zahlen ausgegeben werden soll
* Als Anzeige habe ich ein graphisches LCD, auf dem ein Pfeil
die aktuelle Joystick Stellung symbolisieren soll
Im ersten Fall kommt man um die Arcus-Winkelfunktionen Funktionen
nicht herum. In letzterem aber schon.
(*) Nur so als Beispiel. Ich weis ja nicht was du machen willst.
*x = 1;
float dx;
*y = 0;
int i = 0;
*x = 0.6073*(*x);
for( i = 0; i < 8 ; i++ )
{
dx = (*x);
if( z>=0 )
{
(*x) -= (*y) * (1.0/pow(2,i)) ;
(*y) += dx * (1.0/pow(2,i)) ;
z -= atan((double)(1/pow(2,i)))*(180/M_PI);
}
else
{
(*x) += (*y) * (1.0/pow(2,i)) ;
(*y) -= dx * (1.0/pow(2,i)) ;
z += atan((double)(1/pow(2,i)))*(180/M_PI);
}
}
So hab jetzt diese Funktion hier mehr oder weniger aus dem Web Adaptiert
und etwas modifiziert. als Input hat sie denk Winkel, als output X & Y,
die funktion müsste man eigentlich nur umdrehen ... so irgendwie ...
Jankey wrote:
> kann ich leider nicht ( patent pending ),
Ja genau. Weil hier hundertausend Leute rumhängen, die nur
darauf warten dass einer die Megaidee postet um sie zu
kopieren. Dafür sollen alle anderen im Nebel rumstochern
welches Problem du eigentlich hast.
> wie wäre denn letzteres> möglich?
sagte ich doch schon: ähnliche Dreiecke und damit Strahlensatz
sei Px/Py die Eingangsposition, Wertebereich zb. -1000 ... +1000
in beiden Achsen.
Sei weiters, Qx/Qy die gesuchte Endposition auf einem Kreis am
Display, wobei der Mittelpunkt wieder als 0 angenommen wird.
Dann gilt:
L = sqrt( Px * Py + Py * Py )
Qx = Px / L
Qy = Py / L
und der Vektor QX/Qy ist sogar in der Länge proportional
dem Vektor Px/Py
Dein Display habe nun dem Mittelpunkt bei 127/127 und der
Kreis soll einen Durchmesser von 127 Pixel haben, somit
wird der Einheitsvektor Qx/Qy auf eine Länge von 127 gebracht
und um 127 Einheiten verschoben.
Qx = ( Px / L ) * 127 + 127
Qy = ( Py / L ) * 127 + 127
Und schliesslich soll der Pfeil auch noch in der Länge
proportional der Auslenkung in Px/Py sein. Bei einer
Auslenkung in der jeweiligen Achse von 1000 soll der Pfeil
bis an den Kreis heranreichen:
Qx = ( Px * L 1000 L ) * 127 + 127
Qy = ( Py * L 1000 L ) * 127 + 127
ein bischen kürzen
Qx = ( Px / 1000 ) * 127 + 127
Qy = ( Py / 1000 ) * 127 + 127
und siehe da, sogar die Wurzelberechnung braucht keiner mehr.
Jetzt mag dein Wertebereich für Px/Py nicht -1000 ... 1000 sein
sondern meinetwegen 0 ... 512 mit 256 als Mittenposition und
255 als Auslenkung zu beiden Seiten
Qx = ( ( Px - 256 ) / 255 ) * 127 + 127
Qy = ( ( Py - 256 ) / 255 ) * 127 + 127
Da das aber so trivial ist, fürchte ich, das wird dir als
jemand der an einem Patent arbeitet, nicht wirklich weiterhelfen.
eigentlich eine gute Idee, nur das man /255*127 auch als /2 schreiben
kann ..und wenn du dann auflößt kommt
Qx = (Px>>1 - 127)+127
Qy = (Py>>1 - 127)+127
Qx = Px>>1
Qy = Py>>1
daran erkennt man aber einen echten denker :) er beschäftigt sich mit
leidenschaft.
Das mit Patenten ist so: Wenn man irgendwo vor Veröffentlichung des
Patents etwas darüber öffentlich gestellt hat is es sinnlos & nicht
schützbar.
Also nach langem hin und her, auf signed integer funktioniert es richtig
gut, aber auf unsigned char ( 8 bit unsigned ) funktioniert es einfach
nicht weils eigentlich in den Negativen bereich gehen müsste ..