Forum: Mikrocontroller und Digitale Elektronik Bascom Abrunden u. Nachkommastellen Fehler


von Andreas B. (andy_help)


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?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

WatbBascom nicht diese Sprache, die pro Zeile nur 1 Berechnung konnte. 
Seit wann kann man in Bascom bei der Parameterübergabe rechnen?
Brauchst du da nicht eine Zwischenvariable?

von Alex D. (allu)


Lesenswert?

Andreas B. schrieb:
> Rechnenval As Double

Andreas B. schrieb:
> integer or long expected for abs()

Vielleicht liegt es am Double ?

von Jim Beam (Gast)


Lesenswert?

Andreas B. schrieb:
> Bei beiden gibt es folgende Fehlermeldung:

Bei welchen "beiden" denn?
ich sehe nur EIN Codebeispiel...

von löter (Gast)


Lesenswert?

Fehlermeldung paßt nicht
Mach keine Berechnung in den Klammern von FIX
Mach alle Variablen SINGLE

von Alex D. (allu)


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

von andy_help (Gast)


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.

von andy_help (Gast)


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

von Marvin (Gast)


Lesenswert?

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.

von andy_help (Gast)


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

von Ratgeber (Gast)


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.

von andy_help (Gast)


Lesenswert?

Hm...ok, aber warum rechnet das Programm nicht so wie es soll?
double  -> für Nachkommastellen
Fix     -> Entfernt die Nachkommastellen
frac    -> Nur die Nackommastellen

von andy_help (Gast)


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

von Ratgeber (Gast)


Lesenswert?

> dim a as integer

Hier machst Du es richtig: A als Integer. Ganz oben in dem Programm aber 
nicht. Da ist der falsche Datentyp in Gange.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.