Absolut Betrag "ausrechnen"

Zuviel Werbung?
-> Hier kostenlos registrieren
Wir wissen immer noch nicht, was Deine Steuerung außer + - * / kann.
Kann sie MOD, WORD-OR und/oder Schiebebefehle?

Geht vielleicht sowas:
Code:
#define ABS(TestZahlABS)
  L  TestZahlABS
  OR 1
  MOD 2
  * TestZahlABS

Harald
 
@Heinileini:
Ja, die Sprache ich etwas komisch. Erinnert ein wenig an AWL. Nennt sich Heidenhain ST.
Der Anfang beginnt immer mit einem L (Lade/Load).
Danach kann man A (AND) O (OR) und was es noch alles gibt, einsetzen.
A, AN (AND NOT), O, ON, XO (exkl. ODER), XON, +, -, X (Multi), /, MOD, >> (schieben), <<, = (zuweisen)

IF sieht dann so aus:
IFT (Abfrage, ob Akku = TRUE ist)
IFF (Abfrage, ob Akku = FALSE ist)
...
...
ENDI

Im IF-Kopf meinte ich damit, dass ein ENDI nicht vor ein IFT stehen kann, ohne dass die vorherige Bedingung sicher ausgewertet wurde.
Code:
L   A
A   B
A[
    L   K+5
    >  K+4
]
IFT
ENDI
Dies würde funktionieren.

Code:
L   A
A   B
A[
    L   K+5
    >  K+4
    IFT
       L   K+20
       =  C
    ENDI
]
IFT
ENDI
Dies funktioniert nicht, würde aber die derzeitige ABS-Lösung sein.
Aktuell lege ich mir in jedem Baustein ein Dummy an, und schreibe mir das Ergebnis des derzeitigen ABS (mit IFT) darein und werte diesen dann in meinen darauffolgenden IF-Kopf aus.

Nun bin ich an dem Punkt, wo ich 2 ABS gleichzeitig benötigte und ggf. bald 3 brauche. Ich will aber nicht noch mehr Dummys anlegen, sondern suche eine Lösung, ohne das Ergebnis in eine Dummy-Variable zu speichern.
Damit das funktioniert, erlaubt mit Heidenhain in dem Moment leider nicht den Einsatz von IFT/ENDI :(
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hier steht die Formel für INT.
Den Algorithmus aus dem Beitrag #8 habe ich jetzt mal in AWL umgesetzt.
Ist erstaunlich kurz geworden.
Code:
FUNCTION "MyAbs2" : DINT
TITLE =Abs von DInt ohne Sprung

VAR_INPUT
  v : DINT ;    
END_VAR
BEGIN
NETWORK
TITLE =

      L     #v; 
      SSD   31; // Vorzeichen in alle Bits kopieren (mask)
      L     #v; 
      XOD   ; // XOR mit dem Eingangswert
      TAK   ; 
      -D    ; // mask subtrahieren
      T     #RET_VAL; // das war's

END_FUNCTION
Leider ist das die (möglicherweise unzulässig) patentierte Variante des Algorithmus.
So 'rum ist es nicht patentiert:
Code:
[COLOR="#008000"]// r = (v + mask) ^ mask;[/COLOR]
      L     #v;
      SSD   31; [COLOR="#008000"]// Vorzeichen in alle Bits kopieren (mask)[/COLOR]

      L     #v;
[COLOR="#008000"]//[/COLOR]    [COLOR="#0000FF"]ENT[/COLOR]   ;   [COLOR="#008000"]// bei PLCSIM und CPU mit 4 AKKUs[/COLOR]
      +D    ;   [COLOR="#008000"]// mask addieren[/COLOR]

      XOD   ;   [COLOR="#008000"]// XOR mit mask[/COLOR]
      T     #RET_VAL;
 
Zuletzt bearbeitet:
Wenn RechtsSchieben das Vorzeichen mitnimmt:

L #V // Variable laden
>> 31 // bei DINT um 32 bzw. bei INT um 16 Bit-Positionen nach rechts schieben
* 2 // mit 2 multiplizieren (oder um 1 Bit-Position nach links schieben)
+ 1 // 1 addieren
L #V // ZwischenErgebnis mit Variable multiplizieren
*

 
Zuletzt bearbeitet:
Da kommt leider der .... Compiler von Heidenhain dazwischen.
Die Lade-Befehl schreibt ein Byte, Word, Int, DWord, DInt immer in den 32 Bit Akku und wandelt in diesem Moment ein 16 Bit in ein 32 Bit.
Die Zuweisung = macht das ganze dann in die andere Richtung.
Sprich, bei Word-Zuweisung würden dann die ersten 16 Bit genommen, die anderen "verfallen".
Bei einem DWord wären die 32 dann "voll".
Irgendwie scheint die Heidenhain aber das Vorzeichen in diesem Fall nicht zu beachten, sprich es bliebt auf dem 16. Bit stehen, wenn ich schiebe im 32er Akku, dann interessiert das leider niemand :(
Sobald ich eine "Überprüfung" mache, ob 16 oder 32 Bit Wert, habe ich wieder mein IFT...
Ein Teufelskreis.

Sprich, bei einem DInt funktioniert es, bei einem INT leider nicht :(

Daher vor ja meine "Vorgabe" nur mit den Grundrechenarten eine Lösung finden. Heidenhain selbst löst das im übrigen auf mit einem Zwischenmerker...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Sprich, bei einem DInt funktioniert es, bei einem INT leider nicht
Wenn ich nicht schon graue Haare hätte . . .
Bei Dint funktioniert's, aber Du hast keine Chance eine IntZahl "artgerecht" in eine gleichbedeutende DintZahl umzuwandeln bzw. umgekehrt?

Ich ahne was:
Int in den Akku laden, dann 16 BitPositionen nach links schieben und dann wieder 16 Positionen nach rechts, danach sollte aber die Int Zahl im Dint-Format im Akku stehen.
 
Zuletzt bearbeitet:
Auf welche Lösung beziehst Du Dich?
Gibt es in der Heidenhain keine INT zu DINT Umwandlung (ITD, INT_TO_DINT, ...)?

Harald

Das wäre traumhaft. Nein, leider nicht :(

Ich beziehe mich auf das Schieben des Wertes.
Wenn ich ein Dint habe und die 32. Stell "rausschiebe" und dann mit einer Null zurückschiebe, dann funktioniert es. Ich kann auch eine Maske auf die Stelle setzen, gleicher Erfolg.
Bei einem INT leider nicht.
Da ich keine Auswertung ohne ein IF machen kann, müsste ich für INT und DINT zwei Makros schreiben. Mag ich aber nicht.
Wenn schon, denn schon :)
 
Zuletzt bearbeitet:
Wenn ich ein Dint habe und die 32. Stell "rausschiebe" und dann mit einer Null zurückschiebe, dann funktioniert es. Ich kann auch eine Maske auf die Stelle setzen, gleicher Erfolg.
:confused:
Meinst Du wirklich DINT? Das dürfte mit einem DINT nicht funktionieren. Ich hatte schon in #7 erklärt daß das nur bei REAL funktioniert.

INT = Festpunktzahl (Ganzzahl) 16 Bit, Format: Zweierkomplement
DINT = Festpunktzahl (Ganzzahl) 32 Bit, Format: Zweierkomplement
REAL = Gleitpunktzahl 32 Bit, Format: IEEE754

Harald
 
Zurück
Oben