Forum: Mikrocontroller und Digitale Elektronik ADC mit ATmega8A


von AVR-Anfänger (Gast)


Lesenswert?

Hi Ihr,
ich wollte mir eine kleine Kapazitive Sensor Schaltung programmieren und 
dazu brauche ich einen ADC.
Als Controller habe ich einen ATmega8A und iwo noch einen ATTiny84, aber 
ich wills erstmal mit dem ATmega zum laufen bekommen.

Die Grundfunktionen wie Tongenerator etc funktionieren.

Ich habe jetzt nur das Problem dass ich den ADC nicht hinbekomme... 
Trotz einiger Tutorials...

Ich habe den ADC initialisiert und dann wollte ich mir den ADC Wert als 
16bit integer zurückgeben lassen und dann logisch verknüpfen mit der 
Schaltung.

Logik steht auch schon nur mag der ADC nicht so wie ich will...

Gibt es eine möglichkeit sich Werte an dre Console ausgeben zu lassen 
wir bei Arduino? Ich habe die leise Befürchtung dass die Werte einfach 
komplett anderst sind als die bei Arduino und deshalb vll was nicht 
funktioniert...

Andererseits muss allgemein was mit der Initialisierung nicht stimmen... 
Habe schon alles probiert und iwi mag er bei egal welcher logischen 
Verknüpfung nicht in die "if(...)" reinspringen...

Hier mal meine Initialisierung und die ADCread funktion: (Die Kommentare 
könnt ihr vernachlässigen habe ich für mich rein gemacht..)




void ADC_Init(void) {

  uint16_t result;

  // interne Referenzspannung als Refernz für den ADC wählen:
  ADMUX = (1<<REFS1) | (1<<REFS0);

  // Bit ADFR ("free running") in ADCSRA steht beim Einschalten
  // schon auf 0, also single conversion
  ADCSRA = (1<<ADPS1) | (1<<ADPS0);     // Frequenzvorteiler
  ADCSRA |= (1<<ADEN);                  // ADC aktivieren

  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man 
liest
     also einen Wert und verwirft diesen, um den ADC "warmlaufen zu 
lassen" */

  ADCSRA |= (1<<ADSC);                  // eine ADC-Wandlung
  while (ADCSRA & (1<<ADSC) ) {}         // auf Abschluss der 
Konvertierung warten
  /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
     Wandlung nicht übernommen. */
  result = ADCW;
}


******************************************************************
******************************************************************
******************************************************************
uint16_t readADC(uint8_t channel) {

  uint8_t i;
  uint16_t result = 0;

  // ADEN wird 1 gesetzt = ADC aktivieren
  // ADPS2 = 1 und ADPS1 = 1  beduetet:
  // Teilungsfaktor ist = 64
  // Quelle: 
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Analoge_Ein-_und_Ausgabe#Messen_eines_Widerstandes
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);

  // ADMUX wählt den zu messenden Kanal
  // "channel" des Multiplexers waehlen
  // REFS1 = 1 und REGS0 = 1 Interne Referenzspannung verwenden (also 
2,56 V)
  // REFS1 = 0 und REGS0 = 0 Externe Regerenzspannung verwenden ()
  ADMUX = channel | (1<<REFS1) | (1<<REFS0);

  // ADCSRA initialisiert den ADC und definiert dessen Funktion
  // Den ADC initialisieren und einen sog. Dummyreadout machen
  // ADSC bleibt solange 1 bist die Konvertierung abgeschlossen ist
  ADCSRA |= (1<<ADSC);
  while(ADCSRA & (1<<ADSC));

  // Jetzt 3x die analoge Spannung and Kanal channel auslesen
  // und dann Durchschnittswert ausrechnen.
  for(i=0; i<3; i++) {
    // Eine Wandlung
    ADCSRA |= (1<<ADSC);
    // Auf Ergebnis warten...
    while(ADCSRA & (1<<ADSC));

    result += ADCW;
  }

  // ADC wieder deaktivieren
  ADCSRA &= ~(1<<ADEN);

  result /= 3;

  return result;
}





Danke schonmal!!

LG

von Tom M. (Gast)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #2752018:
> Logik steht auch schon nur mag der ADC nicht so wie ich will...

Kannst du den Fehler etwas genauer beschreiben? Welche Rückgabewerte 
erwartest du, was liefert die Funktion zurück?

Auf den ersten Blick kann ich nix ungewöhnliches sehen. Hälst du die 
Spannungswerte (Limite 2.56V) ein?

> Gibt es eine möglichkeit sich Werte an dre Console ausgeben zu lassen
> wir bei Arduino?

Ich verwende dazu gerne die uart Library von Fleury 
(http://jump.to/fleury).

von Tom M. (Gast)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #2752018:
> Habe schon alles probiert und iwi mag er bei egal welcher logischen
> Verknüpfung nicht in die "if(...)" reinspringen...

Liegt da der Fehler? Zeig mal deine if() Konstruktion!

Wenn du source code mit den passenden Tags ausrüstet, ist er noch 
leichter zu lesen ([ C ] und [ /C ]

von AVR-Anfänger (Gast)


Lesenswert?

Naja das Problem ist dass ich 3 unterschiedliche Sensoren auslesne will 
und die dann wie folgt verknüpfe:

Aber es funktioniert nicht...^^
Dann muss ich mir das mal mit der UART anschauen... Hättest du vll einen 
Beispielcode? Ich würde mir gerne die 3SensorValues ausgeben lassen und 
anschauen wie die sich verändern bei annäherung an die Sensorfläche.





sensorValue1 = readADC(0);
  sensorValue2 = readADC(2);
  sensorValue3 = readADC(4);
  if(sensorValue1 > Kalibration1 + 10  &&  sensorValue2 < Kalibration2 + 
11  &&  sensorValue3 < Kalibration3 + 11){

      Tone(40,100);

  }

  if(sensorValue2 > Kalibration2 + 10  &&  sensorValue1 < Kalibration1 + 
11  &&  sensorValue3 < Kalibration3 + 11){

      Tone(30,100);

  }

  if(sensorValue3 > Kalibration3 + 10  &&  sensorValue1 < Kalibration1 + 
11  &&  sensorValue2 < Kalibration2 + 11){

      Tone(20,100);

  }

  if(sensorValue1 > Kalibration1 + 10  &&  sensorValue2 > Kalibration2 + 
11){

    Tone(40,1000);
    _delay_ms(100);
    Tone(30,1000);
    _delay_ms(100);
    Tone(20,100);
    _delay_ms(1000);

  }

von spess53 (Gast)


Lesenswert?

Hi

Vielleicht solltest du dich mal entscheiden, wo du den ADC 
initialisierst.

MfG Spess

von AVR-Anfänger (Gast)


Angehängte Dateien:

Lesenswert?

Hier mal der komplette Code...^^

von AVR-Anfänger (Gast)


Lesenswert?

Also das mit der UART... iwi mag das nich...

Hat jemand eine Idee was an der ADC falsch sein könnte?

von Tom M. (Gast)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #2752218:
> Also das mit der UART... iwi mag das nich...

Fehlerbeschreibung? Mann...
1
#include "uart.h"

und
1
   /* Standardausgabe auf uart */
2
   uart_init( UART_BAUD_SELECT(115200,F_CPU) );
3
   sei();
4
5
   uart_puts_P("Alive!\r\n");

ist nun wirklich nicht schwer.

von Tom M. (Gast)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #2752218:
> Hat jemand eine Idee was an der ADC falsch sein könnte?

Erklär mir mal den Algorithmus, den du in Sensorlogik() implementieren 
willst.

von AVR-Anfänger (Gast)


Lesenswert?

Also iwi muss was am ADC nich stimmen.... da passiert garnicht mit den 
sensorValues... -.-....

von AVR-Anfänger (Gast)


Lesenswert?

Also in Sensorlogik weill ich die 3 SensorAnalogwerte in die Integer 
speichern und diese dann abfragen. Ich hatte diese Logik auf einem 
Arduino genau so aufgebaut und da hatte das gut funktioniert.

Die AD Wandlung hatte immer einen Wert zwischen 400-420 zurück gegeben 
und wenn ich mit der Hand an die Sensorflächen rann bin hat sich dieser 
Wert erhöht und dann sollte für jeden Sensor einzeln ein anderer Ton 
ertönen.

Das hatte soweit geklappt nur is jetzt natürlich im reinen C die AD 
Wandlung anders wie in Arduino mit "analogRead()" ^^

von AVR-Anfänger (Gast)


Lesenswert?

@ tom

ich versuchs nochmal...^^ sry... und wenns nicht klappt gibts auch eine 
Fehlerbeschreibung!

von Hubert G. (hubertg)


Lesenswert?

Gibt dein Compiler keine Warning aus?
Kann nicht sagen ob es mit dem Fehler was zu tun hat, aber genau aus dem 
Grund lasse ich keine Warnig stehen.
Zeile 206, 208, 1000 als uint8_t geht nicht.
Zeile 230 Wert bei Initialisierung von i fehlt.

von AVR-Anfänger (Gast)


Angehängte Dateien:

Lesenswert?

@ Hubert,
ja das hab ich auch grad gesehn. Hab hier mal die verbesserte Version 
mit dem Versuch die UART einzubinden...^^

Mag er aber iwi nicht...


undefined reference to 'uart_init'
undefined reference to 'PSTR'
undefined reference to 'uart_puts_p'

von AVR-Anfänger (Gast)


Angehängte Dateien:

Lesenswert?

Jetzt dreht der Compiler durch -.- =(

von Andreas B. (andreasb)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #2752245:
>
> Das hatte soweit geklappt nur is jetzt natürlich im reinen C die AD
> Wandlung anders wie in Arduino mit "analogRead()" ^^

Du kannst die Funktionen die du in Arduino verwendet hast auch in deinen 
Code kopieren (zumindest grundsätzlich).

Ohne jetzt den Fehler in deinem Code gesucht zu haben, verstehe ich das 
richtig das du jetzt eigene Hardware gebaut hast?

Wie hast du AREF bestückt? Der geht mal ganz schnell vergessen, und wenn 
dieser nicht beschaltet ist verhält sich der AD Wandler "komisch".

Zum Fehler im Code oben, wie auch immer du Kompillierst: Es fehlen die 
Defines für den Takt und für den MCU Type.

Bei meinem Makefile sieht das so aus (nur Ausschnitt):
1
DEVICE  = atmega8
2
F_CPU   = 8000000
3
COMPILE = avr-gcc -Wall -std=c99 -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE)


mfg Andreas

von AVR-Anfänger (Gast)


Lesenswert?

Also das mit dem AVR-Studio brauche ich soweit ich weiß kein MAKEFILE

Probeprogramme haben ja auch alle funktioniert via AVR-Studio nur die 
dumme ADC Wandlung klappt nicht^^

von Andreas B. (andreasb)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #2752353:
> Also das mit dem AVR-Studio brauche ich soweit ich weiß kein MAKEFILE

Habe ich schon gedacht, dann hast du aber irgendwelche 
Projekteinstellungen oder so.

> Probeprogramme haben ja auch alle funktioniert via AVR-Studio nur die
> dumme ADC Wandlung klappt nicht^^

Nochmals, hast du die Hardware selbst gebaut?
Wenn ja, wie ist AREF bestückt?



mfg Andraes

von AVR-Anfänger (Gast)


Angehängte Dateien:

Lesenswert?

Aso sorry...

Hier der Beschaltungsplan

von Andreas B. (andreasb)


Lesenswert?

Ok, ich sehe keinen Fehler im Schaltplan.

Hier ein Codebeispiel für den ADC das definitiv läuft auf dem ATMega8A
1
/*
2
 * ADC Messen
3
 */
4
static uint8_t ADCRead(void) {
5
  ADCSRA |= (1 << ADSC);            // eine Wandlung "single conversion"
6
  while(ADCSRA & (1 << ADSC));      // auf Abschluss der Konvertierung warten
7
  return ADCH;                      // ADC auslesen und zurückgeben (8bit, ansonsten ADCW)
8
}
9
10
/*
11
 * ADC initialisieren
12
 */
13
void ADCInit(void) {
14
  ADMUX  = (0 << REFS1) | (1 << REFS0); // AVCC with external capacitor at AREF pin
15
  ADMUX |= (1 << ADLAR); // 255 Stufen, 8bit
16
  ADMUX |= 0; // X => ADCX selected
17
18
  ADCSRA  = (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Frequenzvorteiler: 128
19
  ADCSRA |= (1 << ADEN); // ADC aktivieren
20
21
  /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
22
    also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
23
24
  ADCRead();
25
}

ps. das ganze stammt mehr oder weniger aus dem Wiki


mfg Andreas

von AVR-Anfänger (Gast)


Lesenswert?

Wie kann ich mit diesem ADC unterschiedliche Pins auslesen?

von spess53 (Gast)


Lesenswert?

Hi

>Wie kann ich mit diesem ADC unterschiedliche Pins auslesen?

Indem du den Kanal mit den MUX-Bits einstellst.

MfG Spess

von AVR-Anfänger (Gast)


Lesenswert?

z.B. so
1
//ADC Messen
2
static uint16_t readADC2(uint8_t mux) {
3
  ADMUX = mux;
4
  ADCSRA |= (1 << ADSC);            // eine Wandlung "single conversion"
5
  while(ADCSRA & (1 << ADSC));      // auf Abschluss der Konvertierung warten
6
  return ADCH;                      // ADC auslesen und zurückgeben (8bit, ansonsten ADCW)
7
}

von AVR-Anfänger (Gast)


Lesenswert?

jetzt kommt zwar kein Compile Fehler mehr aber der ADC gibt mir immer 
noch keinen Wert zurück...

Angeschlossen is, die Schaltung die bei Arduino problemlos funktioniert 
hat, an den Pins PC0-PC5

diese stehen im Datenblatt als ADC's weiß grad nich woran das jetzt 
liegen kann dass die readADC2  "0" zurück gibt... =(

von spess53 (Gast)


Lesenswert?

Hi

>ADMUX = mux;

Damit überschreibst du alle anderen Einstellungen in ADMUX.

ADMUX =~(1<<MUXn|...|1<<MUX0);  // alle MUX-Bits löschen
ADMUX |= mux;                   // MUX-Bits setzen

Ich hoffe das stimmt so, da meine C-Kenntnisse etwas rudimentär sind.

MfG Spess

von AVR-Anfänger (Gast)


Lesenswert?

Ok danke,
ja ich versuch das morgen mal. Bin eben erst heim gekommen und jetzt hab 
ich keinen Kopf mehr für...^^

von spess53 (Gast)


Lesenswert?

Hi

Gerade gesehen. Sollte

ADMUX &=~(1<<MUXn|...|1<<MUX0);  // alle MUX-Bits löschen

heissen.

MfG Spess

von AVR-Anfänger (Gast)


Lesenswert?

MUXn scheints nicht zu geben....^^

von AVR-Anfänger (Gast)


Angehängte Dateien:

Lesenswert?

kann man die von Arduino erzeugten HexFiles auch per Avr-Studio 
importieren und dann flashen?

Glaube das würde meine Probleme lösen.... Verliere langsam die Lust am 
Recherchieren -.- kann doch nich so schwer sein der misst....


Zumal einfache Codes ja funktionieren oO....

Ich poste mal den Arduino Code und den C-Code dazu... vll hat ja jemand 
die Güte und Hiflt mir... Oder kommt jemand aus der Nähe von 77815 Bühl? 
Ich würde Bier und ne Pizza stellen und wäre suuuuper Dankbar wenn mir 
dabei jemand helfen würde!

LG
AVR-Anfänger


PS: Kann sein dass die Varianten etwas unterschiedlich sind.. Aber das 
Grundprinzip ist sollte eigentlich das gleiche sein.

1.) Kalibration des Kapazitiven Sensoren (Damit sich ein 
gleichbleibender Spannungszustand herstellt - Kondensatoren aufladen 
sozusagen)

2.) Logische Abfrage welcher Sensor gedrückt wurde (sensorValue1 > 
Kalibration...... also der aktuelle Spannungswert größer als der am 
Anfang gemessene. Spannung steigt bei Näherung an den Kapazitiven 
Sensor)

3.) Erzeugen unterschiedlicher Töne bei betätigen eines Sensors.


Hardware:
a) ATMEGA8A    oder    ATTINY84

b) 3 Sensoren - an den Anschlüssen C0-C5

c) Lautsprecher an D0 oder B0   verbunden mit GND


Danke schonmal!!

LG
AVR_Anfänger

von Andreas B. (andreasb)


Lesenswert?

AVR-Anfänger schrieb im Beitrag #2754761:
> kann man die von Arduino erzeugten HexFiles auch per Avr-Studio
> importieren und dann flashen?

Ja, sofern du den gleichen oder einen kompatiblen AVR verwendest.
(Arduino verwendet warscheinlich ein ATMega328 welcher nicht kompatibel 
ist zum ATMega8)

>
> Glaube das würde meine Probleme lösen.... Verliere langsam die Lust am
> Recherchieren -.- kann doch nich so schwer sein der misst....

Ich würde immer noch Hardwareprobleme nicht ausschliessen.

1. bringe UART zum laufen, damit du debugmeldungen zum PC senden kannst. 
Alternativ ein HD44780 Display.

2. nimm das ADC Beispiel aus dem Wiki.

Wenn das nicht läuft hast du ein Hardwareproblem, obwohl dein Schaltplan 
korrekt ist heisst das noch nicht das deine Verkabelung das auch ist.



mfg Andreas

von Hubert G. (hubertg)


Lesenswert?

1
void Kapazitaet(){
2
  
3
  // damit keine Ladung abfliessen kann werden beide Als Input geschaltet
4
  // 0 = Output und 1 = Input
5
  DDRC  = 0b00111111;
6
  PORTC = 0b00000000;
Das ist falsch. 0 = Input und 1 = Output beim DDRC

von Hubert G. (hubertg)


Lesenswert?

Habe das In-Out mal richtig gestellt.
Auf meinem Testboard ändert sich der Ton wenn ich am PortC was mache. 
Habe allerdings keine Sensoren.

von AVR-Anfänger (Gast)


Lesenswert?

Oh...
ja das is natürlich fatal wenn die Kapazitive-funktion falsch arbeitet 
:D

Dann is mir jetz auch klar wieso der ADC immer 0 ausgegeben hatte....


@Hubert G.  kannst du den Code mal posten bzw uploaden?

Wäre klasse!!!


Das war das was mir heute morgen noch eingefallen is und was ich noch 
checken wollte ob die Kapazitive-Funktion überhaupt so arbeitet wie sie 
soll...^^

danke =)

von AVR-Anfänger (Gast)


Lesenswert?

Bin ja mal gespannt wann das Projekt funktioniert...

von Hubert G. (hubertg)


Angehängte Dateien:

Lesenswert?

Ob es allerdings so funktioniert wie du es dir vorstellst, kann ich 
nicht sagen. Die Funktion ist mir nicht ganz klar.

von AVR-Anfänger (Gast)


Lesenswert?

Klasse Danke!!

Ja sehe gerade dass da teilweise noch unnötiger Code drinnen war... Aber 
gut wenns funktioniert stell ichs nochmal online dann is es eindeutiger 
was das Programm machen soll^^

Werde es heute abend gleich mal versuchen nach der Arbeit!

Vielen Dank aufjedenfall nochmal Hubert!!!!!

von AVR-Anfänger (Gast)


Lesenswert?

Was für Zahlenwerte hat er dir denn ausgespuckt für den sensorValue? oO


Beim Arduino waren es immer so ca 400 oder 500 also als integer Wert...

und hatten eine Streuung von +-2 also 398, 399 , 400 etc.... und wenn 
ich dann mit dem finger an die touchfläche bin ist der wert um ca 100 
angestiegen... und dann konnte ich mit meiner Sensorlogik die "Taster" 
schalten bzw die Töne schalten.

Es soll eigentlich nur dann wenn ein Sensor "gedrückt" wird ein Ton 
kommen. Hatte das in de rversion noch falsch...
also das "Tone() " vor den "if" Abfragen einfach wegdenken... hatte da 
nur was versucht...


Aso du hast ja keinen Sensor -.- ups... ja dann probier ich mal weite 
rrumm... oO :D


ABER es scheint aufjedenfall an den Input Output dings gelegen zu 
haben!! =) Vielen Lieben Dank!!!

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.