Ich habe folgendes Problem, Mein Ziel ist es im Zuge eines Maturaprojektes ein Programm in Assembler für die Steuerung eines Roboters zu schreiben. Der verwendete µController ist ein ATmega16 und die Programmierebene AVR-Studio 4. In Assembler habe ich schon hineingeschnuppert und mir ein Grundwissen dieser Sprache angeeignet. Mein Ziel ist es jetzt ein Programm auf die Beine zu stellen, welches 5 Sensorwerte (0V - 2,54V) mit dem ADC über 5 Kanäle einlest und mit einem "Kontrastwert" vergleicht. Der Kontrastwert soll quasi eine Schwelle (zB. 1V) sein, bei deren Überschreitung der jeweilige Sensor auf aktiv gesetzt werden soll. Die Sensoren sollen nun je nach dem welche(r) Sensor(en) aktiv ist/sind nach einer Tabelle je ein bestimmtes Ereignis resultieren. Dieses Ereignis ist dann die PWM mit der ich einen Servomotor ansteuern werde. Für die Ansteuerung des Servos steht bereits ein Programm, wer einen Servo ansteuern will und ein Programm braucht stelle ich es gerne bereit. Hab schon einige verschiedene Programme geschrieben, wo der Fehler liegt bin ich selber nicht draufgekommen. Freerunning Mode ist zur Zeit in Verwendung um ständig die Sensordaten einzulesen. Reichen würde es aber jede millisekunde alle 5 Sensoren einzulesen. Wie das genau funktioniert mit der ADC-Wandlung und wann sie fertig ist und beginnt konnte ich aus dem Datenblatt des µC nicht rauslesen. Würd mich sehr freuen wenn sich jemand die mühe und aufwand nimmt und mir bei dieser Problemstellung unter die Arme greifen könnte. vl. ist noch interessant zu wissen für was das ganze gut sein soll. der Roboter soll in der lage sein eine Linie zu verfolgen und die 5 Sensoren dienen zur Information, wo die Linie sich gerade befindet und in welche Richtung der Servo lenken soll. dann bedank ich mich recht herzlich schon mal im vorhinein mfg. Philip ps: in den Anhang gebe ich mal ein Programm das ich geschrieben habe um die 5 Sensoren einzulesen und an Leds die aktiven Sensoren auszugeben.
> Hab schon einige verschiedene Programme geschrieben, wo der Fehler liegt > bin ich selber nicht draufgekommen. Und wie sollen wir drauf kommen, wenn Du nicht erzählst, was für ein Fehler überhaupt auftritt bzw. was konkret nicht so funktioniert, wie es soll?
leider weiß ich nicht welcher Fehler auftritt :( jedenfalls wird am Ausgang (Leds) ein falsches Ergebnis geliefert.
Ich habe mal über den Code drübergeschaut und keine Stelle gefunden, an der Du das Ergebnis der A/D-Wandlung ausliest und irgendwie verarbeitest. Hab ich da was übersehen oder hast Du da was ganz elementar wichtiges vergessen?
Gast
#761947
Ich lass das Ergebnis des ADC linksbündig ins Register schreiben. Dazu nehme ich aber im ADC-Register nur 8 der 10 bit-Auflösung. diese 8 Höchstwertigen bits lese ich dann "einfach" vom ADCH-Register aus. ich kopier mal vl. den quelltext rein damit wir auch über das selbe reden.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | |
73 | |
74 | |
75 | |
76 | |
77 | |
78 | |
79 | |
80 | |
81 | |
82 | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 | |
90 | |
91 | |
92 | |
93 | |
94 | |
95 | |
96 | |
97 | |
98 | |
99 | |
100 | |
101 | |
102 | |
103 | |
104 | |
105 | |
106 | |
107 | |
108 | |
109 | |
110 | |
111 | |
112 | |
113 | |
114 | |
115 | |
116 | |
117 | |
118 | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 | |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | |
140 | |
141 | |
142 | |
143 | |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | |
150 | |
151 | |
152 | |
153 | |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | |
178 | |
179 | |
180 | |
181 | |
182 | |
183 | |
184 | |
185 | |
186 | |
187 | |
188 | |
189 | |
190 | |
191 | |
192 | |
193 | |
194 | |
195 | |
196 | |
197 | |
198 | |
199 | |
200 | |
201 | |
202 | |
203 | |
204 | |
205 | |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | |
212 | |
213 | |
214 | |
215 | |
216 | |
217 | |
218 | |
219 | |
220 | |
221 | |
222 | |
Ah, hatte das unten überlesen. Hast Du mal ne vereinfachte Version des Programms gemacht, um die Funktion des ADC und eine einfache Ausgabe mal zu testen? Der Code oben ist eigentlich schon etwas zu komplex, um einen "generellen funktioniert-nicht"-Fehler zu finden.
Ich verstehe aber nicht ganz, was da in der warte-Routine im Hauptprogrammteil gemacht wird. Speziell scheint mir, da wird ohne auf das Ende einer Wandlung zu warten einfach am ADCSRA und am ADMUX rumgeschraubt. Warum startest Du die Wandlung immer neu? Der Free-Running-Modus zeichnet sich schließlich dadurch aus, dass man das nur einmal machen muss, nämlich ganz am Anfang. Außerdem braucht man dafür nicht jedes Mal das ganze ADCSRA neu zu schreiben. Das ADCSRA liegt im bitadressierbaren Bereich. Es reicht dann völlig, das ADSC zu setzen.
Gast
#761996
Was mir zu deiner ISR auffällt, ist daß du am Anfang ein unnötiges cli und am Ende ein potenziell eher schädliches sei machst. Dafür fehlt dir die notwendige Sicherung des SREG. Am Anfang nach dem ersten push r16 sollte da noch stehen:
1 | |
2 | |
und direkt vor dem pop r16 am Schluß das dazugehörige:
1 | |
2 | |
ich versuche eben 5 kanäle des ADCs zu nutzen und sie nacheinander abzufragen. darum versuche ich es mir immer wenn der ADC fertig ist den Multiplexer (mux) um 1 zu erhöhen. Das mit dem SREG Speichern anstatt die Interrupts zu sperren ist eine gute Idee. Werds gleich mal ändern. Soviel ich weiß braucht der ADC 13 Zyklen für eine Wandlung. Das würde ja bedeuten, mein Hauptprogramm wird nicht einmal durchlaufen und der ADC ist schon paar mal fertig. Fällt euch eine möglichkeit ein bzw. habt ihr schon erfahrungen wie es besser funktionieren könnte 5 Kanäle hintereinander auszulesen und in 5 Register zu schreiben und danach diese 5 Register mit einem Vergleichswert(Kontrast) zu vergleichen und dann laut einer 5 Bit breiten Tabelle ein Ereignis treffen?
das hab ich jetz noch vergessen. ich setze das ADSC Bit weil es in der Simulation im AVR Studio immer zurückfällt. Anscheinend dürfte das AVR Studio den Freerunning mode nicht berücksichtigen in der Simulation. Und ohne das Admux zu ändern, weiß ich ja nicht welcher Kanal gerade vom Multiplexer ausgewählt ist und könnte es passieren dass ich den ADC-Wert ins falsche Sensorregister schreibe?
Philip Hahn wrote:
> Soviel ich weiß braucht der ADC 13 Zyklen für eine Wandlung.
Der braucht 13 ADC-Zyklen für eine Wandlung, nicht 13 CPU-Zyklen! 1
ADC-Zyklus sind bei Deiner Einstellung 32 CPU-Zyklen.
Hallo,
>ich versuche eben 5 kanäle des ADCs zu nutzen und sie nacheinander
abzufragen.
darum versuche ich es mir immer wenn der ADC fertig ist den Multiplexer
(mux) um 1 zu erhöhen.
Du kannst den MUX bereits im dritten ADC-Takt nach Beginn der Wandlung
umschalten, nach dem 2. ADC-Takt ist S&H fertig.
Nicht versehentlich die Referenzspannung verändern, nach einem
Umschalten dieser ist der nächste Wandlerwert Schrott.
Gruß aus Berlin
Michael
Hab den fehler noch immer nicht gefunden :( Schön langsam schließt sich der Kreis des Wissens bei mir aber noch ist im Programm ein kleiner fehler bzw. ein verständnisproblem.
Fällt euch eine möglichkeit ein bzw. habt ihr schon erfahrungen wie es besser funktionieren könnte 5 Kanäle hintereinander auszulesen und in 5 Register zu schreiben?
hmm habs grad nur überflogen aber ich mein mir fehlt hier irgendwie ADCL du MUSST wenn du die 10 Bit nutzt ADCL und dann ADCH auslesen (ob du das L willst oder nicht) oder Du liest ADCW bzw bei alten Prozessoren ADC aus. Aber nur ADCH auslesen ist nicht gut. ach mist sehe grad du nutzt ja nur das high hmm
Manuel Kauf wrote: > habs grad nur überflogen aber ich mein mir fehlt hier irgendwie ADCL > > du MUSST > > ADCL und dann ADCH auslesen (ob du das L willst oder nicht) > > oder Du liest ADCW bzw bei alten Prozessoren ADC aus. > > Aber nur ADCH auslesen ist nicht gut. Das ist Quatsch! Nur, wenn ADCL gelesen wurde, muss anschließend ADCH gelesen werden, um die Register wieder freizugeben. Wenn ADCL nicht angefasst wird, reicht es, nur ADCH zu lesen! Und ADC bzw. ADCW gibt es in Assembler nicht. In diesem Fall ist ADLAR gesetzt (also das Ergebnis linksbündig abgelegt). Wenn man nur 8 Bit braucht, muss man auch nur ADCH lesen.
jups hab mich grad verlesen ^^ hab nicht gesehen dass nu 8 bit :) (habs schon korrigiert ^^)
Gast
#765834
bin schon am verzweifeln =( es will einfach nicht funktionieren. Hat jemand von euch schon mal mehrere Kanäle "gleichzeitig" abgefragt und in ein Register geschrieben? wenn ja bitte ich mir zu helfen! mfg. Philip
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.