Hallo, ich habe schon einige alte Beiträge durchstöbert, aber mir ist immernoch nicht so ganz klar, wie genau ich ein 10KR-schiebepoti an den ADC anschließe. Im Tutorial hier steht ja, wenn man AREF benutzt, sollte man, um den PIN nicht zu sehr zu belasten Werte um 100KR benutzen, ansonsten sollte man AVCC benutzen. Ich habe jetzt also das Poti an einer Seite an AVCC gehängt, an der anderen an GND. Der Schieber hängt am PINC0 wo der ADC channel 0 ist. Im ADMUX-register habe ich REFS0 gesetzt um AVCC als refferenz zu nehmen. Ist das alles so richtig? Ich bekomme nämlich immer nur 10mal die 0 als Ergebnis der conversion.
1. Avcc auf Vcc legen. 2. Aref mit 100nF auf GND legen. //Nicht super wichtig aber besser... 3. Poti zwischen Vcc und GND, Schieber auf ADC0. 4. ADCSRA |= (1<<ADEN) | (1<<ADSC) | (1<<ADATE) | (1<<ADPS2) | (1<<ADPS1); 5. ADMUX |= (1<<REFS0); Btw: Um welchen Controller handelt es sich? Hab einfach mal nen Mega16 angenommen...
Ach sooooo geht das, ok kein Wunder daß es nicht geklappt hat. Müßen das denn eignetlich exakt 100nF sein oder würden es auch 22 tun? Weil von denen hab ich etliche hier rumliegen... Dankeschön ;) Is ein Atmega 8535
Schau dir mal das Datenblatt vom 8535 an: http://www.atmel.com/dyn/resources/prod_documents/doc2502.pdf Dort aus Seite 207 findest Du das Blockschaltbild des ADC. Wenn Refs0 gesetzt ist liegt an AREF also AVCC oder die interne 2,56V Referenz abhänig davon ob Refs1 gesetzt ist. Offene Enden neigen zum Schwingen, darum wird dies mit dem Kondensator an AREF unterbunden, der genaue Wert des Kondensators ist dabei nicht so kritisch. Ich hatte 100nF angeführt da diese von den meisten Leuten eh als Abblockkondensatoren benutzt werden.
Ich habe hier jetzt noch ein Problem: Ich habe 11 Potis, angeschlossen über 3.5mm Klinkenkabel an meinem Board hängen. Diese switche ich über einen CD4067BE-16Kanal Multiplexer jeweils auf den ADC0. Mein Prog. auf dem Atmega ließt diese nach einander aus, verpackt sie zu einem String und sendet diesen per uart an den Rechner. Allerdings soll er nur senden, wenn sich seit dem letzten senden etwas verändert hat, damit ich keinen unendlichen Datenstrom habe. Das problem ist jetzt: wenn nich alle Potis angeschlossen sind, dann hängen die entsprechenden Buchsen ja in der Luft und ich habe riesig zittern auf dem ADC, folglich ist der Wert nach jeder Messung anders und ich habe wieder meinen Datenfluss. Wie könnte ich dafür sorgen, daß dieser Fall abgefangen wird?
Es wird nur gesendet, wenn sich der Wert um mehr als 1% (oder wieviel auch immer) von vorherigen Wert unterscheidet. Problem hierbei wären schleichende Änderungen, die so nicht registriert werden. Also als Ereignis zum Senden des Strings - Änderung > Schwellwert - zusätzlich alle 1s (oder wie oft auch immer) senden Letzteres könnte man beispielsweise realisieren indem man eine Variable alle 1ms um 1 herunter zählt. Bei Null wird gesendet, egal was ist. Nach dem Senden wird die Variable wieder auf 1.000 oder was auch immer gesetzt. Wird wegen Änderung > 1% gesendet, wird die Variable auch wieder hochgesetzt. Es gibt sicherlich hübschere Verfahren, aber ich denke so sollte das relativ einfach zu realisieren sein. Statt mit den rohen ADC-Daten zu arbeiten, könntest du ja auch sagen wir 4 oder 8 Messungen durchführen und den Mittelwert bilden. Das würde das Rauschen wahrscheinlich auch etwas vermindern.
Fallen mir spontan 3 Möglichkeiten ein: 1. Leg die nicht benutzten Buchsen auf GND. 2. Schieb die 2 LSB ins Nirvana. 3. Stell halt die Anzahl benutzter Buchsen am MC ein und sende nur die gewünschten. Wie stark zitterts denn?
wenn du einen 100k Widerstand nach Masse legst, floated dir der Eingang nicht mehr durch die Gegend. Wenn du ein 1k Poti benutzt, fällt dieser auch nicht ins Gewicht. Oder du legst den Pin direkt auf Masse und löst die Verbinduing sobald du das Poti anschließt
@ Kai Franke (kai-) Benutzerseite >wenn du einen 100k Widerstand nach Masse legst, floated dir der Eingang >nicht mehr durch die Gegend. Wenn du ein 1k Poti benutzt, fällt dieser Oder die interen Pull-Ups verwenden. Sind in etwas auch 100K. MFG Falk
Kai Franke wrote: > Oder du legst den Pin direkt auf Masse und löst > die Verbinduing sobald du das Poti anschließt Also z.B. Klinkenbuchsen mit Öffner verwenden (z.B. Pollin 450823 oder 450013)
Ich brauche 10Bit auflösung, sonst kriegt mein Programmierer die Krise wenn ich ihm mit nem 8Bit Signal ankomme ;) Ich lass mir schon den Mittelwert aus 10Messungen ausgeben. Naja, ich werd morgen mal den empfohlenen Kondensator zw AREF und GND löten, mal schauen wieviel der noch bringt... Ich denke ich werde mir ein paar Dummy-Stecker löten, mit nem Festen Widerstand drin, dann sollte ruhe sein. Das Board ist nämlich eignetlich soweit schon fertig. Danke für die Tips...
>> Ich denke ich werde mir ein paar Dummy-Stecker löten
wieso denn? Falk hatte doch eine gute Idee mit den Pullups, dann musst
du nur schnell im Programm was ändern anstatt den Lötkolben
anzuschmeißen
Das hatte ich gar nicht gesehn, wie is das gemeint? Kann ich am PortA den Pullup einfach einschalten, auch wenn der ADC aktiviert ist? Also PORTA |= (1<<PA0) ?
@ Phillip Hommel (Firma hs-bremen) (philharmony) >Kann ich am PortA den Pullup einfach einschalten, auch wenn der ADC >aktiviert ist? >Also PORTA |= (1<<PA0) ? AFAIK ja. MFG Falk
Hmm, allerdings geht der ADC jetzt nicht mehr durch den vollen Bereich von 0-1023 sonder fängt irgendwo bei 30 an... Ist nicht SOOO wild, aber wenn man das noch korrigieren könnte wärs natürlich super...
Ich habe jetzt die internen Pull Ups an, habe 100nF zwischen AREF und GND und lass zwischen 10 Mesungen mitteln und habe immernoch Zittern im letzten bit...Ne lösung?
@ Phillip Hommel (Firma hs-bremen) (philharmony) >GND und lass zwischen 10 Mesungen mitteln und habe immernoch Zittern im >letzten bit...Ne lösung? Damit leben. Das ist bei einem ADC prinzipbedingt so. MfG Falk
Ich denke ich werd das softwaremäßig abfangen. Ich werd die beiden Datenarrays nicht einfach nur vergleichen sondern von einander abziehen und nur bei einer Differenz von mehr als 2 soll er senden. Geht in C array1 - array2 ?
Phillip Hommel wrote: > Ich denke ich werd das softwaremäßig abfangen. > Ich werd die beiden Datenarrays nicht einfach nur vergleichen sondern > von einander abziehen und nur bei einer Differenz von mehr als 2 soll er > senden. > Geht in C array1 - array2 ? Grundlagen! Nein. Du musst Schleifen drüber legen.
Habe das mal probiert
1 | //Compare_Memory
|
2 | char compare_memory(void) |
3 | {
|
4 | unsigned char i = 0; |
5 | unsigned char result = 0; |
6 | for (i=0; i<11; i++) |
7 | {
|
8 | if (((data_act[(i*2+1)] - data_old[(i*2+1)])^2)>25) result = 1; |
9 | }
|
10 | return result; |
11 | }
|
Es soll also jedes zweite Byte der beiden pakete verglichen werden und sobald einmal eine Abweichung von mehr als 5 vorliegt (quadratisch wegen vorzeichen, oder kann ich das weglassen?) soll result eine 1 werden, sonst bleibt sie null. Aufruf sieht so aus:
1 | if(compare_memory()) sende_daten (...) ; |
... Läuft, allerdings nur bis zum ersten mal wenn das Low Byte über 255 wieder auf 0 geht. Dann reagiert er auf diese Achse gar nicht mehr, aber dafür auf alle anderen. Sobald ich eine andere Achse bewegt habe, geht die erste wieder...???
Phillip Hommel wrote: > Es soll also jedes zweite Byte der beiden pakete verglichen werden und > sobald einmal eine Abweichung von mehr als 5 vorliegt (quadratisch wegen > vorzeichen, oder kann ich das weglassen?) quadratisch ist wohl so ziemlich die schlechteste Lösung dafür. Wenn du tatsächlich die abs Funktion in C nicht kennst, ist es ziemlich simpel da selbst eine zu schreiben. int my_abs( int i ) { if( i < 0 ) return -i; return i; } ..... if( my_abs( data_act[i*2+1] - data_old[i*2+1] ) ) result = 1; ..... > Läuft, allerdings nur bis zum ersten mal wenn das Low Byte über 255 > wieder auf 0 geht. ? welches Low-byte? Machst du da byteweise Vergleiche? Warum liest du denn die ADC Ergebnisse nicht einfach mal in ein Int Array ein. Das vereinfacht doch die Sache beträchtlich. Jetzt versteh ich auch, warum du nur jedes 2.te Byte vergleichst. Das ist doch Unsinn und gehört in die Kategorie: Wie schiesse ich mir selber ins Bein. Also: Die beiden Bytes vom ADC holen und zu einem int zusammenfügen. Der gcc macht das schon ganz von alleine, wenn man das ADCW Pseudo- register ausliest. Ab dort hast du dann int und kannst damit wunderbar operieren.
Ich bin in C noch nicht so fit, aber ich lerne jeden tag was neues ;) Mit Abs funktioniert es. Vielen Dank erstmal! Der hintergrund warum ich byteweise arbeite ist der, daß ich per UART byteweise sende, und daher auch das Wertearray entsprechend byteweise aufbaue. Ich hole mir sogar den int-Wert aus dem ADCW, teile ihn aber dann in low und high part auf und füge dem High-Part dann noch eine Numerierung in die ersten 4 der 6 ungenutzten Bits ein. Würde ich als Int speichern, müßte ichs beim senden wieder zerpflücken, außerdem krieg ich ein Problem beim vergleichen wenn ich die Nummerierung da schon drin habe. Ich hoffe damit ich hab mich jetzt rausgeredet ;)
Hi Ich hab meinen Mega16 an einem 1KOhm Poti, und nach ner weile ist er schon ziemlich warm geworden... ist das normal? Gruß
Eigentlich sollte das nicht sein. Wird er auch warm wenn du das Poti wegnimmst? Ist die Schaltung auf einem Steckboard, Rasterplatine, ...? Wieviel strom zieht die Schaltung und was hängt sonst noch am Controller dran?
steckt auf so nem Steckbrett/Experimentierboars... Die Schaltung zieht 50mA Und am Controller hängt nur noch eine Duo LED.... Ohne Poti hab ich noch nicht versucht... aber ich denk nicht dass er da noch warm wird, sonst hängt ja nichts weiter dran... Gruß
Eben das wäre ja damit herauszufinden. Wenn er ohne Poti trotzdem warm wird, dann haste eventuell einen Kurzen irgendwo auf dem Steckboard. 50mA ist recht viel für den AVR, was zieht denn die LED alleine? Was zieht die Schaltung ohne die LED? Hast Du das Poti vielleicht falsch angeschlossen? Verändert sich der Stromverbrauch wenn Du das Poti verstellst? Sollte nämlich VCC bzw GND fälschlicherweise auf dem Abnehmerpin des Poti liegen und der Schieber ganz zu, dann hast du quasi einen Kurzschluss (oder zumindest recht niederohmige Verbindung) von VCC auf GND in die eine oder andere Richtung...
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.