Forum: Mikrocontroller und Digitale Elektronik AD Wandlung mit 10bit über RS232


von falk Grieffenagen (Gast)


Lesenswert?

Hallo,

Bin neu im Bereich Mikrokontroller. Habe mit das Buch und den Bausatz
von Roland Walter besorgt, sprich ich arbeite mit dem ATMega8 und
Bascom. Ich möchte einen Widerstandsbereich von ca 10k-17k möglichst
genau digitalisieren (das ganze 6-fach)und die Ergebnisse über die
RS232 Schnittstelle ausgeben. Mit den AD Wandlern klappt das mehrfache
Abtasten im 8bit modus gut das Auslesen des Registers ADCH gibt die
Ergebnisse. Das Problem ist nur, dass ich bei dem kleinen
Widerstandsbereich nur ca 60 unterschiedliche Werte pro Widerstand
bekomme. Wenn ich das richtig verstanden habe, kann ich in Bascom nur
bis zu 9 bit über die Schnittstelle in einem Datenwort fassen und den
Wandler entweder auf 8 oder 10 bit programmieren, sprich ich muss für
10 bit ein 8 und ein 2 bit Wortnacheinander schreiben. Wenn ich
versuche nacheinander ADCL und ADCH auszulesen(erst UDR=ADCL für die
unteren 8 bit dann UDR=ADCH für die oberen 2 bit), bekomme ich nicht
was ich erwarte.
Fragen:
1.Wie kann ich 6x10 bit über die RS232 möglichst schnell schicken?
2.Gibt es außer die Spannung am ADC analog zu verstärken einen anderen
Weg zu einer Höheren Auflösung?
3.Wie kann ich analog den Widerstandsbereich von 10-17k auf z,B. 0-25k
transformieren(OP-Schaltung)?
Vielen Dank

Falk

von Roland P. (pram)


Lesenswert?

Hi,

das ADC Register muss in der richtigen Reihenfolge ausgelesen werden,
soweit ich weiß (steht im Datenblatt)

Das mit 9 Bit würd ich bleiben lassen, tust dich schwer das wieder mit
dem PC einzulesen. Ansich ist die Idee mit 2 Byte nicht schlecht. In
die restlichen 6 Bits kannst dann noch die Kanalnummer schreiben. Ich
würd sogar so weit gehen:
1. Byte = ADCL & 0x7F

2. Byte = ADCL >> 7 | ADCH << 1 | chan << 3 | 0x80

Als Bits:
0 L L L L L L L
1 C C C C H H L
dann hast auch das Problem mit der Syncronisation am PC erledigt. Wenn
das MSB gesetzt ist, hast die Kanalnummer, ADCH sowie das erste Bit von
ADCL drin.

Zum Widerstandsmessen: Wenn du auf OP's verzichten willst, könntest du
eine Konstruktion mit negativer Hilfsspannung von z.B. -5V verwenden und
VREF dann auf den maximal erzielaren Wert setzen

+5V
|
|
10..17K
|
+---> ADC 0..1,29V
|
17K
|
|
-5V

Gruß
Roland

von Wolfram (Gast)


Lesenswert?

>Wenn ich das richtig verstanden habe, kann ich in Bascom nur
>bis zu 9 bit über die Schnittstelle in einem Datenwort fassen und den
>Wandler entweder auf 8 oder 10 bit programmieren, sprich ich muss für
>10 bit ein 8 und ein 2 bit Wortnacheinander schreiben. Wenn ich
>versuche nacheinander ADCL und ADCH auszulesen(erst UDR=ADCL für die
>unteren 8 bit dann UDR=ADCH für die oberen 2 bit), bekomme ich nicht
>was ich erwarte.

Dafür das du neu in Mikrocontrollerprogrammierung bist und in BASCOM
programmierst kommst du erstaunlich gut mit Bitbreiten zurecht.
Du machst nur einen Fehler:
Die Bitbreite der Werte die du schickst und die Bitbreite deines
Übertragungsweges haben nichts miteinander zu tun. Die Abhängigkeit die
du da konstruierst wird dich bei grösseren Projekten in eine Sackgasse
oder zumindest in Probleme führen. Das erste erzeugst du schon.
(UDR=ADCL,UDR=ADCH) nicht das es nicht funktionieren würde, aber es ist
kein sauberer Programmierstil.

Dein Programm sollte so aussehen
1. Einlesen des ADCwertes
2. evt. Umformen des Wertes
3. Versenden des Wertes (mit evt. Protokoll)
4. Zu 1.

Über die Serielle Schnittstelle des AVR kannst du prinzipiell 9bit
übertragen, der PC wird nur nicht sehr glücklich damit.
Nimm 8bit ,1 oder 2 Stopbit, keine Parität. Niemand hindert dich die
Werte vor der Übertragung noch zu Komprimieren und auf PC Seite wieder
auszupacken, wenn du mehr aus deiner Verbindung herausholen willst.

von falk Grieffenagen (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Wolfram und Roland,

Danke für die Antworten.

Roland zu deinen Tips noch ein paar Fragen:
Das ich die Daten syncronisieren muss habe ich schon gemerkt,da die
Datenströme der (derzeit 3, es sollen 6 werden) Sensoren sich bei
mehrfachen an und ausschalten der AVR Spannung gern vertauschen.Ich
komme nur mit deinen Beschreibungen zu den beiden Bytes nich ganz
zurecht:
Man kann gut die Kanalinformation (1-6 meinst du doch, oder?) als 4 bit
message in das ADCL Byte geben, da nur 2 bit belegt sind und es als
erstes gesendet weden muss.
Wäre nicht  1. chan<<2|ADCL und 2.ADCH das einfachste?wofür ist es
notwendig die MSB 0 und 1 zu haben? ADCH nutzt doch alle bits für die
Information des Sensors, da darf ich doch nichts verändern, oder?
Davon abgesehen habe ich noch das Problem die 2 bytes wirklich zu
senden, anbei 1. das Bascomlisting, welches schonmal irgendwie geht,
dabei habe ich das Syncronproblem noch nicht bedacht und im Anschluß
meine im naiven Leichtsinn  veränderte Version...

Zur Widerstandsfrage, ich denke ich muss auf anderen Gründen doch op´s
verwenden, mache aber besser einen neuen Thread, bzw erstmal das eine.

Vielen Dank

Falk

von Marko (Gast)


Lesenswert?

Salut Falk,

Roland Walter arbeitet gern direkt mit den Registern,
das ist soweit auch in Ordnung, aber am Anfang tut man
sich da gern etwas schwer mit.
Da Du aber eh Bascom verwendest würd ich Dir raten
mit den Bascom eigenen Befehlen anzufangen.
Schau mal in der Hilfe von Bascom nach Getadc.
Mit dem Befehl kannst Du einen ADC Kanal einfach auslesen
(n Programmbeispiel ist da auch bei).
Prinzipiell gibt Dir der ADC ein 10Bit Wert zurück.
Da Du aber nur 8 Bit in die UART schicken kannst
mußt Du den Wert zerlegen in Highbyte und Lowbyte
Ich verwend für die Aktion zum Einlesen ne Word-Variable
(2Byte) und lege da per Overlay 2 Bytevariablen drüber.
Die andere Version ist es erst das LOwbyte in eine Bytevariable
zu übernehmen und dann per shift variable, right,8 das
highbyte auf die lowbyteposition zu schieben und das dann in eine
weitere Bytevariable zu übernehmen.
Die Bytes kannste dann ganz normal per UART übertragen.
Im PC mußt Du das Ganze dann umgekehrt machen, sprich die 2 Bytes
wieder in der ursprünglichen Reihenfolge wieder zusammensetzen
in eine Wordvariable.
Die ganze Prozedur mußt Du für jeden Kanal durchziehen.

Ich machs immer so, das ich in Bascom das Programm zunächst
mit den gewünschten Funktionen zusammenstricke und wenn das dann
das macht was ich mir vorstelle, dann geh ich ans straffen
indem ich z.B. die Bascom Befehle durch direkte Registeranweisungen
oder ASM-Module ersetze. So kann ich bei jedem Schritt schön sehen
ob mein Prog noch das macht was ich will und das ganze wird dann
etwas schneller und der Code mitunter kleiner.

von Roland P. (pram)


Lesenswert?

Ich hatte oben folgenden Gedanken:
ist das erste Bit 0, so sind die untersten 7 Bits von ADCL enthalten
ansonsten sind die Kanalinfos bzw die restl Bits enthalten.

Anhand des ersten Bits kannst du also definitiv unterscheiden, was in
den restl. 7 Bits drin steht, was aber nicht funktioniert, wenn du das
komplette ADCL überträgst. (Ausser du stellst die UART auf 9 Bit um,
was aber auf der PCSeite Probleme macht)

Zum Thema Bascom: Ich hab ehrlich gesagt noch nie was damit gemacht
(nur mit ASM und C)
Deshalb auch der C Syntax von oben.
In beiden Programmiersprachen ist es so, dass man VOR dem Schreiben ins
UDR-Register warten muss bis UDR-Empty ist.
Das machst du in deinem Code nicht.

in C sieht das z.B. so aus:
loop_until_bit_is_set(UCSRA, UDRE);
outp(b, UDR)

Gruß
Roland

von falk Grieffenagen (Gast)


Lesenswert?

Hallo Roland,
Vielen Dank für deine Antwort, mit der Zeile DO Loop until Ucsra.udr1=1
zwischen den UDR Befehlen funktioniert die Ausgabe und ich kann sie mit
Max/MSP auch in 10 bit dekodieren.
Das einzige Problem ist jetzt noch die Syncronisation Deinen Hinweis
mit
1. Byte = ADCL & 0x7F

2. Byte = ADCL >> 7 | ADCH << 1 | chan << 3 | 0x80

habe ich jetzt verstanden und die dekodierung in Max/MSP auch schon
programmiert, nur zickt Bascom mit dem Formatieren der Bytes rum.Ich
habe es wirklich 2 Stunden lang mit in Bascom probiert, es kamen immer
error meldungen.Wahrscheinlich ist da mit 2 Zeilen ASM getan, die kann
man in Bascom einbinden. Wenn du oder jemand anderes mir da einen
Hinweis geben könntest wäre das super.

Vielen Dank

Gruß

Falk

von Marko (Gast)


Lesenswert?

ist doch ganz einfach in bascom

Vor dem Programmcode:

z.B.
dim adc_wert as word at &H60
dim highbyte as byte at &H61 overlay
dim lowbyte as byte at &H60 overlay

die Adressen musste evtl. anpassen an deine ram-belegung

wenn du z.B. im highbyte das 7te bit manipulieren willst
geht das gaaanz einfach über

highbyte.7=1   oder highbyte.7=0

setzen oder rücksetzen

geht doch ganz easy, oder? der kniffligste part ist
n freier rambereich zu finden um die variablen drinne abzulegen

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.