PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [gelöst] best. wert "aufteilen"



Che Guevara
23.05.2008, 02:47
servus,

ich möchte mir jetzt ein analoges "messgerät" mit einem atmega32 bauen.
dieses soll (vorerst) einfach eine spannung zwischen 0 und 5 volt an einem best. analogen port (porta) des atmega einlesen und dann auf/mit zwei 7-segment anzeigen widergeben.
soweit der plan, doch:

die anzeige soll eine kommastelle haben (z.b. 2,5 volt).
deswegen muss ich den wert,der eingelesen wird (nach dem umwandeln in die volt zahl ....... aus 200 werrden z.b. ungefähr 0,9 volt) aufteilen.
hier, in diesem beispiel (0,9 volt) muss ich auf der ersten anzeige eine 0 darstellen, auf der zweiten anzeige eine 9.
wie teile ich einen wert zwischen 0 und 5 mit einer nachkommastelle auf zwei variablen auf (softwaremässig)????

mfg
chris

johns
23.05.2008, 04:34
hallo,

also da du eine kommastelle willst würde ich mit 10-fachem adc messwert rechnen, denn dann kann mit integer arithmetik gerechnet werden, was sich positiv auf die maschinencodegrösse und performance auswirkt. weiters bieten sich bei den divisionen durch 2er potenzen bitshifts an (1024 = 2^10). und do solltest mindestens auf eine weitere kommastelle runden.

um deine eigendliche frage zu beantworten:
angenommen du freundest dich mit dem vorschlag des 10-fachen adc wertes an... dann erhältst du die ziffer vor dem komma durch dividision mit 10, und die nachkomma ziffer mit einem modulo 10.

so würde mein vorschlag als c code aussehen: (nicht getestet, es ist schon spät und bier!)


#define AREF_VOLTAGE 50 // 10x the voltage for integer arithmetics
...
uint_16 dividend = AREF_VOLTAGE * adc_value; // we need this twice
uint_8 voltage = dividend >> 10; // division by 1024 (=2^10)
uint_16 remainder = dividend - (voltage << 10); //for rounding
if(remainder >= 512) voltage++; // minimal rounding without math lib
//if(remainder >> 9) voltage++; // could be more efficient...
uint_8 ones = voltage / 10; //note: integer division
uint_8 tenths = voltage % 10; // modulo


vermutlich liesse sich der code weiter optimieren... vieleicht hat ja noch jemand eine idee :)


lg + hth

PicNick
23.05.2008, 13:42
Wenn es sicher ist, daß du immer nur eine Vorkommastelle hast:


DIM einer AS BYTE
DIM komma AS BYTE
DIM zehntel AS BYTE
DIM strg AS string * 6 AT einer OVERLAY

DIM volt as SINGLE ' das ist die Voltzahl, also z.B. 0.9

strg = str(volt) ' macht aus 0.9 --den string "0.9"

davon steht "0" wegen OVERLAY immer auch in der Variablen "einer"
der dezimalpunkt in "komma"
"9" steht in "zehntel"



den rest kannst du

Che Guevara
23.05.2008, 15:27
danke für eure antworten!!

@johns
leider kann ich deinem code überhauptnichts entnehmen, da ich c gar nicht verstehe *schaem*
trotzdem danke dür deine antwort

@PicNick
ich habe deinen code so einigermassen verstanden und habe jetzt noch die wichtigsten sachen angehängt:

$regfile = "m32def.dat"
$crystal = 16000000

Config Adc = Single , Prescaler = Auto
Config Portb = Output
Config Portc = Output

Portc.0 = 1
Portc.1 = 1
Portc.2 = 1
Portc.3 = 1
Portc.4 = 1
Portc.5 = 1
Portc.6 = 1
Portc.7 = 1

DIM einer AS BYTE
DIM komma AS BYTE
DIM zehntel AS BYTE
Dim Strg As String * 6 At Einer Overlay
Dim X As Word
Dim Volt As Single
Dim A As Integer

A = 5 * X
Volt = A / 1024

Strg = Str(volt)

Do
Start Adc
X = Getadc(0)
If Einer = 1 Then
Portc.0 = 0
Elseif Einer = 2 Then
Portc.0 = 1
Portc.1 = 0
Elseif Einer = 3 Then
Portc.1 = 1
Portc.2 = 0
End If
Loop

End


allerdings leuchtet keine led auf dem rn-control dabei auf!! :-( was habe ich falsch gemacht/vergessen??

mfg
chris

PicNick
23.05.2008, 15:45
$regfile = "m32def.dat"
$crystal = 16000000

Config Adc = Single , Prescaler = Auto
Config Portb = Output
Config Portc = Output

Portc.0 = 1
Portc.1 = 1
Portc.2 = 1
Portc.3 = 1
Portc.4 = 1
Portc.5 = 1
Portc.6 = 1
Portc.7 = 1

DIM einer AS BYTE
DIM komma AS BYTE
DIM zehntel AS BYTE
Dim Strg As String * 6 At Einer Overlay
Dim X As Word
Dim Volt As Single

$const faktor = 5 / 1024 ' feste werte soll gleich der kompiler ausrechnen

Start Adc

Do
X = Getadc(0)
Volt = X ' umwandeln in gleitkomma
Volt = Volt * faktor

Strg = Str(volt)
einer = einer AND &H0F ' aus ascii wird &H00-&H05

select case einer
case 0: 'pin setzen für 0
case 1: 'pin setzen für 1
case 2: 'pin setzen für 2
case 3: 'pin setzen für 3
case 4: 'pin setzen für 4
case else: 'pin setzen für was weiss der Teufel
end select
Loop
End

Bei deinen Segment-Pins blick' ich jetzt nicht durch, aber das ist ja nicht das Problem

Che Guevara
23.05.2008, 17:53
danke, das funtioniert jetzt ganz gut !!

aber ich möchte ja auch noch zehntel darstellen, wie kann ich das den machen????

tut mir leid, dass ich das nicht selbst kann, aber ich kann noch nicht sehr lange programmieren und brauche deßhalb ein paar starthilfen.

mfg
chris

PicNick
23.05.2008, 18:52
Nun, genauso, nur sind es mehr "case"


zehntel = zehntel AND &H0F ' aus ascii wird &H00-&H09

select case einer
case 0: 'pin setzen für 0
case 1: 'pin setzen für 1
case 2: 'pin setzen für 2
case 3: 'pin setzen für 3
........
case 9: 'pin setzen für 9
case else: 'pin setzen für was weiss der Teufel
end select
Loop


da gibt es statt "case" was besseres, aber ich bin grad im Druck und kann dir das jetzt nicht aufschreiben

Che Guevara
23.05.2008, 20:19
ok,danke.
jetzt funzts!! :-)

mfg
chris