Bascom Abrunden u. Nachkommastellen Fehler

#5646394
Lesenswert?

Hallo,
ich habe ein Problem, denn ich müsste eine Zahl abrunden und deren 
Nachkommastellen anzeigen, wenn diese vorhanden sind.
1
Dim Ms As Long 
2
Dim A As Long    
3
Dim Rechnenval As Double 
4
Dim Wert As Long
5

6
Wert = 1000
7
ms = 3526 
8

9
If Ms >= wert Then
10
A = fix(ms / wert)
11
Rechnenval = Frac(ms / wert)
12
END IF

Bei beiden gibt es folgende Fehlermeldung:
integer or long expected for abs()

Was mache ich falsch?
#5646884
Lesenswert?

löter schrieb:
> Mach keine Berechnung in den Klammern von FIX
> Mach alle Variablen SINGLE

Guter Tipp, im Simulator läuft es damit.

Mein Vorschlag wäre Dword zu benutzen, wenn der Wertebereich ausreicht. 
Läuft schneller und macht keine Rundungsfehler.




$regfile = "M8def.dat"

$hwstack = 128
$swstack = 128
$framesize = 64
$crystal = 3686400


Dim Ms As Single
Dim A As Single
Dim Rechnenval As Single
Dim Wert As Single
Dim Merke As Single


Wert = 1000
Ms = 3526

If Ms >= Wert Then
   Merke = Ms / Wert
   A = Fix(merke)
   Rechnenval = Frac(merke)
End If


Print "Merke=" ; Merke
Print "A=" ; A
Print "Rechnenval=" ; Rechnenval



'*******************************************
' Vorschlag:

Dim _ms As Dword
Dim _a As Dword
Dim _rechnenval As Dword
Dim _wert As Dword

_wert = 1000
_ms = 3526

If _ms >= _wert Then
   _a = _ms / _wert
   _rechnenval = _ms Mod _wert
End If

Print
Print "_A=" ; _a
Print "_Rechnenval=" ; _rechnenval
End
Gast #5647206
Lesenswert?

Hallo,
vielen Dank für die Infos.

Was soll mein Programm machen?
Ich gebe an, in wieviel ms die Led an und dann wieder ausgeschaltet 
werden soll.
Hierzu rechne ich natürlich alles um, aber es macht eben nicht das was 
es soll.
Normalerweise müsste nach 6452 ms, also 6,452 sek die led bzw. aus 
gehen.
Wenn ich es in den atmega8 übernehme, dann leuchtet die led in 1 Sekund 
extrem oft.

Hier mein bisheriger Programmiercode:
<pre>
$regfile = "M8def.dat"
$crystal = 1000000
$hwstack = 100
$swstack = 100
$framesize = 100


'Timer0 konfigurieren
'1000000 (Systemtakt) / 1 (Prescaler) = 1000000 (Counts)
Config Timer0 = Timer , Prescale = 1

'Timer0 Overflow Interrupt
'Dieser Interrupt wird beim Überlauf (255 nach 0) ausgelöst
'1000000 (Counts) / 256 (8-Bit Timer) = 3906,25 (Interrupts die Sekunde)
On Timer0 On_timer0_overflow
Enable Timer0

Enable Interrupts

Config Portb = Output
Dim A As Long
Dim B As Long
Dim Ende As Single
Dim Aa As Integer
Dim Ueberlaeufe As Double
Dim Onems As Double
Dim Anzahlms As Long
Dim Rechnen(4) As Double
Dim Rechne(2) As Long

Ueberlaeufe = 3906.25
Anzahlms = 6452

Onems = Ueberlaeufe / 1000
'3,90625

Rechnen(1) = Onems * Anzahlms
'25203,125
'Wieviele Überläufe, wichtig für Variabele a
Rechnen(2) = Rechnen(1) / Ueberlaeufe
'6,452
Rechne(1) = Fix(rechnen(2))
'6
Rechnen(3) = Frac(rechnen(2))
'0,452
Rechnen(4) = Rechnen(3) * Ueberlaeufe
'1765,625
Rechne(2) = Abs(rechnen(4))
'1766

A = 0
Aa = 0
B = 0
Do


Portb.0 = 1
Do

Loop Until Aa = Rechne(1)
A = 0
Aa = 0
B = 0
ende = 0
Portb.0 = 0
Do

Loop Until Aa = Rechne(1)
A = 0
Aa = 0
B = 0
ende = 0

Loop

End



On_timer0_overflow:
A = A + 1
   If Aa = Rechne(1) Then
   B = B + 1
      If B = Rechne(2) Then
      Ende = 1
      End If
   End If

   If A = 3906 Then
   Aa = Aa + 1
   A = 0
   End If

Return
</pre>

Ich habe jetzt folgenden Bereich so gelassen:
<pre>
Do

Loop Until Aa = Rechne(1)
</pre>

und nicht so:
<pre>
Do

Loop Until Aa = Rechne(1) and ende = 1
</pre>

Da es anscheinend schon bei rechne(1) das Problem liegt.
Gast #5647215
Lesenswert?

Es finden also 3906.25 Timerüberläufe in 1 Sekunde statt.
Um es dann dementsprechend besser zu rechnen, da gibt es einen externen 
Quarz für, aber ich weiss nicht mehr dem Quarz seine MHZ Zahl.
Dann ist der Timerüberlaufwert eine Ganzzahl, ohne Nachkommastelle
Gast #5647238
Lesenswert?

Marvin schrieb:
> andy_help schrieb:
>> 3906,25 (Interrupts die Sekunde)
>
> Warum so ein krummer Wert?
> Wenn man mit Zeitwerten arbeiten will, nimmt man einen Interrupt im
> ms-Abstand; d.h. 1000 Interrupts pro Sekunde. Dann kann man sich die
> ganze Umrechnerei sparen.


Prescaler Werte:
1 , 8 , 64, 256,1024

1 MHZ sind 1000000HZ.
1000000 / 1 = 1000000 /256    =3906,25
1000000 / 8 =125000/256       =488,28125
1000000 / 64 = 15625/256      =61,03515625
1000000 /256 =3906,25/256     =15,2587890625
1000000 / 1024 = 976,5625/256 =3,81469726562

Wenn ich 1 MHZ habe, diesen durch den Prescaler u. dem Timerwert teile, 
erhalte ich immer einen Wert mit Nachkommastelle.
Es gibt aber einen externen Quarz, bei dem durch die Teilung dann Werte 
ohne Nachkommastelle entstehen, aber mir fällt der entsprechende externe 
Taktgeber für den Atmega nicht mehr ein
Gast #5647292
Lesenswert?

andy_help schrieb:

> Es gibt aber einen externen Quarz, bei dem durch die Teilung dann Werte
> ohne Nachkommastelle entstehen, aber mir fällt der entsprechende externe
> Taktgeber für den Atmega nicht mehr ein

Dann nimm einen Quarz mit 1,024MHz. Da kommst Du auch auf "richtige" 
Zahlen.
Oder: Du läßt im Interrupt den Timer immer wieder mit einem Wert 
vorladen, so daß er nicht seinen vollen Umfang zählen muß und erzeugst 
auf diese Weise
gut benutzbare Zeiten.
Gast #5647341
Lesenswert?

freebasic Beispiel:
dim wert as double
dim a as integer
dim b as double
wert = 2562.1345351
a = fix(wert)
b =frac(wert)

print wert
print a
print b

Ergibt folgende Ausgabe:
 2562.1345351
 2562
 0.1345350999999937

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren