Forum: Mikrocontroller und Digitale Elektronik AtMega8 2. ADC benutzen


von Tobias K. (messfehler)


Lesenswert?

Hallo,

ich will mit meinem AtMega8 (fertig verschalten auf dem 
Experimentierboard von myAVR) eine Spannung von 0-5V messen.
Das ganze lief auch Anfangs über den ADC0 des µC ganz gut, nur habe ich 
den Fehler gemacht die Schaltspitzen meiner Spannung außer acht zu 
lassen, diese haben meinen ADC-Pin zerstören.

Mittlerweile habe ich die Schaltung umgestellt, sodass diese 
Spannungsspitzen nicht mehr vorkommen ;-)

Der AtMega8 hat ja laut Datenblatt mehrere ADC Pins, kann ich einfach 
den Wert über einen anderen Pin einlesen? Wenn ja, wie? Oder bleibt mir 
nichts anderes übrig einen neuen zu kaufen?

Mein bisheriger Quelltext:
1
class Application : public Controller
2
{
3
    // Bausteine und Attribute .........................................
4
    protected: uint8_t wert;
5
    protected: uint8 spannung,analogwert;    //Variablen für Berechnung und Ausgabe festlegen
6
    protected: AnalogDevice spannungmesser;  //Analoges Gerät
7
    protected: Uart konsole;                 //Ausgabe über Uart
8
    protected: String text;                  //Ausgabetext
9
    
10
    // Funktionen ......................................................
11
    public: void onStart()
12
    {
13
        ddrB.bit0 = 1;            //B.0 als Ausgang
14
        ddrB.bit1 = 1;            //B.1 als Ausgang
15
        ddrC.bit1 = 0;            //C.1 auf Eingang
16
        portC.bit1 = 0;           //C.1 ohne Pull-Up
17
        spannungmesser.config(0);
18
        konsole.config(9600);
19
        wert=0;
20
    }
21
    public: void onWork()
22
    {
23
        portB.bit0 = 1;            //B.0 ein -> Relais ein
24
        portB.bit1 = 1;            //B.1 ein -> LED ein
25
        waitUs(50000);            
26
        portB.bit0 = 0;             //B.0 aus
27
        portB.bit1 = 0;             //B.1 aus
28
        waitUs(5000000);            
29
}
30
    
31
public: void onTimer10ms()
32
{
33
analogwert=spannungmesser.getValue8();//Variable analogwert auslesen
34
        spannung=analogwert*50/255;            //Errechnen des realen Spannungswertes                
35
        konsole.sendByte(analogwert);            //Analogwert an Konsole für Oszi
36
37
text.format("Spannung= %u,%u V \n",spannung/10,spannung%10); //Formatierung Ausgabetext
38
39
konsole.sendString(text); // Textausgabe an Konsole
40
}
41
} app;  // Anwendungsinstanz

Das bringt mich zu meinem 2. Problem:

Ich kann die Uart Ausgabe nicht takten, sozusagen gibt mir die Uart die 
Werte in einem mir unbekannten (jedoch zu hohem) Takt aus.
Versuche ich über "waitUs" eine kurze Pause zu bewirken sendet mit die 
Uart gar nichts mehr. Verhindert die Funktion onStart das ganze? Wie 
umgehe ich das?

Vielen Dank. :-)

: Bearbeitet durch User
von H.Joachim S. (crazyhorse)


Lesenswert?

Ich würde den Controller entsorgen, selbst wenn er sonst noch 
funktioniert, kostet ja nicht die Welt.
Ansonsten kannst du natürlich auf einen anderen Eingang wechseln. Evtl. 
gehts.

von Karl H. (kbuchegg)


Lesenswert?

Tobias K. schrieb:

> Der AtMega8 hat ja laut Datenblatt mehrere ADC Pins, kann ich einfach
> den Wert über einen anderen Pin einlesen?

Das kommt drauf an, was du wirklich zerstört hast.

Der Mega hat ja nicht 8 ADC-SChaltungen sondern nur einen einzigen.
Über einen auf dem IC eingebauten 'Schalter' kannst du einen der 8 ADC 
Pins an diesen einen real existierenden ADC anschalten und mit dem ADC 
die Spannung an diesem Pin messen.

> Wenn ja, wie?

In dem du den Multiplexer (so heißt der Schalter) auf den gewünschten 
Pin einstellst.

> Oder bleibt mir
> nichts anderes übrig einen neuen zu kaufen?

Wie gesagt: Kommt drauf an, was du genau zerschossen hast. Wenn es nur 
die Clamping Dioden erwischt hat, dann mag es auch so noch gehen.

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:

>> Wenn ja, wie?
>
> In dem du den Multiplexer (so heißt der Schalter) auf den gewünschten
> Pin einstellst.


Was mag wohl die 0 hier
1
        spannungmesser.config(0);
für eine Bedeutung haben.

Weißt du. Ich finde das immer ein wenig seltsam, wenn Leute hier 
aufschlagen, die sagen, 'sie' hätten ein Programm geschrieben und dann 
recht offensichtlich von dem Quelltext, den sie präsentieren nicht die 
geringste Ahnung haben, während alle die, die das zugrunde liegende 
Framework überhaupt nicht kennen, sofort mal 2 oder 3 heiße, viel 
versprechende Spuren sehen, denen es sich lohnen könnte nachzugehen.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Tobias K. schrieb:

> Ich kann die Uart Ausgabe nicht takten, sozusagen gibt mir die Uart die
> Werte in einem mir unbekannten (jedoch zu hohem) Takt aus.

Die Uart gibt ganz offensichtlich
1
 konsole.config(9600);
die Ausgaben mit 9600 Baud aus. Stell das Terminal auf 9600 und wenn die 
Taktfrequenz des µC korrekt eingestellt ist und auch das Framework diese 
Taktfrequenz kennt, dann muss das funktionieren.

Der häufigste Fehler an dieser Stelle ist der, dass der µC eben nicht 
mit der Taktfrequenz läuft, von der der Programmierer annimmt das er es 
tut. Wenn die Taktfrequenz aber nicht stimmt, dann stimmen zwangsläufig 
alle davon abhängigen Timings nicht mehr.

Ein nagelneuer Mega8 läuft ab Werk mit ca. 1Mhz aus dem internen 
Taktgenerator. Egal ob da phsyikalisch ein QUarz oder ein 
Quarzoszillator angeschlossen ist. Damit derartige Bausteine (die die 
Frequenz wesentlich exakter einhalten als der interne RC_generator) aber 
wirksam werden, muss man sie mittels der µC-internen Fusebits auch 
aktivieren. Tut man das nicht, dann kann der Quarz an den Anschlüssen 
hängen bis er vergammelt, der Mega benutzt ihn deswegen trotzdem nicht.

: Bearbeitet durch User
von Tobias K. (messfehler)


Lesenswert?

@Karl Heinz

vielen Dank für deine Hilfe. Konnte es umstellen, die anderen Pins 
funktionieren zum Glück. Habe aber dennoch zur Sicherheit einen neuen 
bestellt, denn der µC wird warm bis heiß und das sollte er im normalen 
Betrieb ja wohl nicht.

Und zu deiner Vermutung muss ich zugeben, ja ich habe den Quelltext aus 
einem Tutorial für ADC übernommen und nach meinem Denken angepasst und 
erweitert, da entgehen einem wohl solche Details, wie man z.B. den ADC 
Pin umstellt, habe das aber auch bisher noch nie benötigt.

Karl Heinz schrieb:

> Stell das Terminal auf 9600 und wenn die
> Taktfrequenz des µC korrekt eingestellt ist und auch das Framework diese
> Taktfrequenz kennt, dann muss das funktionieren.

Ich habe die Baudrate auf 600 gesenkt, auch in der UartBrdige 
Einstellung, nun sendet es in einer besseren Rate.

Problematisch ist jetzt nur, dass die LED nicht mehr ausgeht, also die 
Eingänge sich nicht mehr abschalten.

von JochenZ (Gast)


Lesenswert?

Hallo,

waitUs nimmt nur 8bit werte als Parameter

waitUs(5000000); das macht irgendwas nur nicht was du erwartest für 
längere Wartezeiten solltest du waitMs nehmen.

des weiteren vermeide im Timer-Interrupt die Multiplikation und Division 
und ganz besonders das Formatieren und senden von Strings, setze nur ein 
Flag und erledige das in onWork. In Interrupts immer nur schnelle Sachen 
machen alles was Zeit braucht muss in die Mainloop also hier onWork.

Gruß J.

von JochenZ (Gast)


Lesenswert?

hab mal ein Beispiel zusammengezimmert
1
class Application : public Controller
2
{
3
  // Bausteine und Attribute .........................................
4
    protected: uint8 spannung,analogwert;    //Variablen für Berechnung und Ausgabe festlegen
5
    protected: AnalogDevice spannungmesser;  //Analoges Gerät
6
    protected: Uart konsole;                 //Ausgabe über Uart
7
    protected: String text;                  //Ausgabetext
8
    protected: Led led;
9
  protected: DigitalOut relais;    
10
    protected: bool mustToggle;
11
    protected: bool mustSend;
12
    
13
        
14
    // Funktionen ......................................................
15
    public: void onStart()
16
    {
17
        // hier Initialisierungen durchführen
18
    relais.config(PORTB,BIT0);
19
    led.config(portB,bit1);        
20
        spannungmesser.config(1);
21
        konsole.config(9600);
22
        mustToggle=false;
23
        mustSend=false;
24
    }
25
    
26
    public: void onWork()
27
    {
28
      // die Mainloop nicht mit waitMs ausbremsen
29
        if (mustToggle)
30
        {
31
          mustToggle=false;
32
          relais.toggle();
33
          led.toggle();
34
        }
35
        
36
        if (mustSend)
37
        {
38
           mustSend=false;
39
          analogwert=spannungmesser.getValue8(); //Variable analogwert auslesen
40
          spannung=analogwert*50/255;            //Errechnen des realen Spannungswertes                
41
           // konsole.sendByte(analogwert);          //Analogwert an Konsole für Oszi
42
      // entweder Text oder binär !!! 
43
      text.format("Spannung= %u,%u V \n",spannung/10,spannung%10); //Formatierung Ausgabetext
44
      konsole.sendString(text); // Textausgabe an Konsole
45
      
46
        }
47
        
48
    }
49
    public: void onTimer10ms()
50
    {
51
        // alle 10 ms und alle 50ms das Signal mustSend setzen
52
        static uint8_t counter=0;
53
        counter++;
54
        if (counter>=5)
55
        {
56
          mustSend=true;
57
          counter=0;
58
        }
59
    }
60
    public: void onTimer100ms()
61
    {
62
        // alle 100 ms, und alle 500ms das Flag mustToggle setzen
63
        static uint8_t counter=0;
64
        counter++;
65
        if (counter>=5)
66
        {
67
          mustToggle=true;
68
          counter=0;
69
        }
70
        
71
    }
72
    
73
} app;  // Anwendungsinstanz

Gruß J.

von Tobias K. (messfehler)


Lesenswert?

@JochenZ:

Vielen Dank für deine Antworten!
Habe auch schon versucht das ganze über if-Schleifen zu lösen, aber da 
hing es an der Umsetzung. Auf deinen Weg wäre ich wohl so schnell nicht 
gekommen. ;)

Hab nur ein paar Kleinigkeiten wie Ports anpassen müssen.
Habs getestet und es klappt wunderbar.

von Peter D. (peda)


Lesenswert?

Tobias K. schrieb:
> nur habe ich
> den Fehler gemacht die Schaltspitzen meiner Spannung außer acht zu
> lassen, diese haben meinen ADC-Pin zerstören.

Eingänge schaltet man generell nicht direkt an Spannungsquellen. Da 
gehört ein Schutzwiderstand mindestens 1k, besser 10k in Reihe.
Und wenn diese Quellen der VCC vor- oder nacheilen können, ist er sogar 
Pflicht.
Die einzigen Anschlüsse, die direkt an Spannung liegen dürfen sind 
(A)VCC.

von Tobias K. (messfehler)


Lesenswert?

@Peter Dannegger:

Ich musste sowieso einen Spannungsteiler einsetzen, jetzt ist der 
Eingang mit einem 100k Widerstand abgesichert.
Will zur Sicherheit noch eine Z-Diode (5,1V) dazuschalten damit da 
nichts mehr anbrennen kann.

von Uwe S. (de0508)


Lesenswert?

Tobias K. schrieb:
> Vielen Dank für deine Antworten!
> Habe auch schon versucht das ganze über if-Schleifen zu lösen, aber da
> hing es an der Umsetzung. Auf deinen Weg wäre ich wohl so schnell nicht
> gekommen. ;)

Sorry das - http://www.if-schleife.de/ - gibt es nicht !

http://de.wikibooks.org/wiki/C-Programmierung:_Kontrollstrukturen

von Tobias K. (messfehler)


Lesenswert?

Sry.. erst denken..
Meinte natürlich if-Anweisung. ;)

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.