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
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
>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.
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
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.
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.