- LiTime Speicher und Akkus         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 15

Thema: Atmega8 ADC \ eeprom

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    12.08.2014
    Beiträge
    11

    Frage Atmega8 ADC \ eeprom

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hi,

    nach stunden des Probierens und suchen hier meine Fragen....
    Ich möchte am Analog eingang einen Strom messen, und diesen Wert ins eeporm speichern damit ich ihn nach dem einschalten wieder habe, das Ganze wird an einer 12V 3Ah Batterie angeschloßen.

    Zum Testen hab ich Versucht and den PC0 einen Widerstand hängen und den auf die 5V vom µC gehängt, aber nach einen Spannungswert hat es mir nicht ausgesehen.. (hab es um den Wert zu sehen in den eeprom gepseichert)

    1) wie könnte ich den adc wert sonst ausgeben ohne lcd display bzw. eeprom ?

    2) Soweit ich das richtig nachgelesen habe bekomme ich vom analog eingang aber nur einen Spannungs wert und damit ich ich auf meinen Strom komme müsste das dann so aussehen
    u = ADC*5.0;
    i = u/r;

    3) Daher das eeprom auf ca. 100.000 cyclen brenzt ist, wird es nicht sinnvoll sein den Wert immer zu beschreiben.
    Meine Idee wäre so eine art dauerplus damit der µC immer unter spannung (Ruhemodus oder so) ist und der Wert im RAM somit erhalten bleibt aber geht das ohne das die Baterie gleich leer ist ?

    Code:
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/eeprom.h>
    
    uint16_t eeLastValueAddr EEMEM = 1;
    uint16_t lastValue = 0;
    
    int main()
    {
        // Set PORTD as Output
    	DDRD = (1<<PD7)| (1<<PD6)|(1<<PD5) | (1<<PD4) | (1<<PD3) | (1<<PD2)| (1<<PD1)| (1<<PD0);
    
    	// Set PortB (PB0,PB1) as Input
        PORTB |= (1<<PB0);
    	PORTB |= (1<<PB1);
    
        // Set Reference to AVCC and input to ADC0
        ADMUX = (1<<REFS0);
    
        // Enable ADC, set prescaler to 16
        // Fadc=Fcpu/prescaler=1000000/16=62.5kHz
        // Fadc should be between 50kHz and 200kHz
        ADCSRA = (1<<ADFR)|(1<<ADEN)|(1<<ADPS2);
    
        // Start the first conversion
        ADCSRA |= (1<<ADSC);
    
        while (1)
    	{
            if (!(PINB & (1<<PB0)) && !(PINB & (1<<PB0)))
            {
                //Ruecksetzung des Wertes
    			lastValue = 0;
                eeprom_write_word (&eeLastValueAddr, lastValue);
            }
            if ((PINB & (1<<PB0)))
            {
    		    //Analog Wert lesen und in eeprom schreiben
    			lastValue = ADC;
                eeprom_write_word(&eeLastValueAddr, lastValue);
    			Set_LED();
            }
    
            //Wartezeit fuer Taster abfrage
            _delay_ms(100);
        }
    }
    
    void Set_LED()
    {
    	switch (lastValue)
    	{
    		case > 700:
    			PORTD = 0b00000000;
    			break;
    
    		case > 600:
    			PORTD = 0b10000000;
    			break;
    
    		case > 500:
    			PORTD = 0b11000000;
    			break;
    
    		case > 400:
    			PORTD = 0b11100000;
    			break;
    
    		case > 300:
    			PORTD = 0b11110000;
    			break;
    
    		case > 200:
    			PORTD = 0b11111000;
    			break;
    
    		case > 100:
    			PORTD = 0b11111100;
    			break;
    
    		case >50:
    			PORTD = 0b11111110;
    			break;
    			
    		case 0:
    			PORTD = 0b11111111;
    			break;
    	}
    }

  2. #2
    Erfahrener Benutzer Lebende Robotik Legende Avatar von PICture
    Registriert seit
    10.10.2005
    Ort
    Freyung bei Passau in Bayern
    Alter
    72
    Beiträge
    11.077
    Hallo!

    Zitat Zitat von live5 Beitrag anzeigen
    Meine Idee wäre so eine art dauerplus damit der µC immer unter spannung (Ruhemodus oder so) ist und der Wert im RAM somit erhalten bleibt aber geht das ohne das die Baterie gleich leer ist ?
    Eine Baterrie wird nach eine Zeit t = C / I leer, wobei C seine Kapazität (hier 3 Ah) und I laufender Stromverbrauch ist. Beispielweise, wenn deine Schaltung 1 mA aus der 3 Ah Batterie ständig "saugt", dann wird die Batterie theoretisch nach 3000 Stunden, also ca. 4 Monaten leer.
    MfG (Mit feinem Grübeln) Wir unterstützen dich bei deinen Projekten, aber wir entwickeln sie nicht für dich. (radbruch) "Irgendwas" geht "irgendwie" immer...(Rabenauge) Machs - und berichte.(oberallgeier) Man weißt wie, aber nie warum. Gut zu wissen, was man nicht weiß. Zuerst messen, danach fragen. Was heute geht, wurde gestern gebastelt. http://www.youtube.com/watch?v=qOAnVO3y2u8 Danke!

  3. #3
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Die µC-Schaltung kann man schon sehr sparsam machen. Mit Sleepmodes und sparsamen Regler sind Werte Deutlich unter 1mA, so um 10 µA drin. Es reicht auch nur für die Zeit zu Puffern (per Elko), die der µC zum schreiben der Daten in EEPROM braucht. Das sind eher nur ein paar Millisekunden.
    Die ausgabe zu Testzwecken geht etwa per UART an den PC (RS232).

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    12.08.2014
    Beiträge
    11
    ok,danke...

    eine frage hätte ich noch zum set_sleep_mode...

    Also dann würde ich z.B PC1 die AVCC (5V) messen und wenn diese unter 4.5V abfällt könnte ich ihn in den set_sleep_mode(SLEEP_MODE_PWR_DOWN) setzen.
    Wenn am INT0 wieder 5V anliegen sollte der Interrup reagieren und ihn wieder starten.

    Ist das so richtig oder habe ich einen denkfehler ?
    Geändert von live5 (12.08.2014 um 12:40 Uhr)

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    01.03.2008
    Ort
    Niederlanden
    Beiträge
    1.170
    Du möchtest AVcc an PC1 messen. Aber gegen welcher Referenzspannung wird das passieren? Was wird den ADC-Wert 1023 definieren?


    Zurück zu deinem ersten Beitrag. Dort sagst du, du hast ein Widerstand zwischen PC0 und 5 Volt geschaltet. Und davon möchtest du ein Spannung messen, und daraus ein Strom berechnen. Was bedeutet diese Strom für dich? Was ist den Zweck? Leider geht das messen einer Spannung nicht auf diese weise. Ein Pin das als Eingang geschaltet wird ist hochohmig. Da fliest kaum Strom rein. Den Widerstand wird den Spannung an den Pin nur zu 5 Volt hoch ziehen. Und immer ein Wert in die nahe von 1023 bekommen.Wenn du ein Spannung messen möchtest, nimmst du ein Spannungsteiler aus 2 Widerstanden zwischen GND und 5 Volt. Dann den Mittelpunkt der beiden Widerstanden messen. Den Ratio der Widerstanden ist abhängig von dein Anwendung.


    Den AVR Mikrocontroller haben oft ein internen Spannungsreferenz, den man auch als Mess-eingang wählen kann. Als Referenz für den ADC wert 1023 kannst du aber auch aVcc wählen, was oft quasi gleich an Vcc angeschaltet ist. Und damit ist es möglich den Bordspannung zu messen, aber in ein invertierte Weg.
    Geändert von Valen (12.08.2014 um 22:29 Uhr)

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    12.08.2014
    Beiträge
    11
    Ziel wäre es einen Drucksensor anzuschließen und dessen wert einzulesen (ergibt 4-20mA aus)
    Ich habe mich jetzt nur mal auf das einlesen des ADC konzentriert, bei mir wären 5V = 1023

    Mein aktuelles Problem ist das der ADC wert > 205 und < 409 ist und das Immer sogar wenn nichts angeschlossen ist ?
    Ich konnte den Fehler noch nicht finden, daher ich noch kein Poti habe verwende ich verschiedene widerstände.

    Code:
    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/eeprom.h>
    
    uint16_t lastValue = 0;
    uint16_t ADC_Read(uint8_t channel);
    
    int main()
    {
      // Set PORTD as Output
      DDRD = (1<<PD7)| (1<<PD6)|(1<<PD5) | (1<<PD4) | (1<<PD3) | (1<<PD2)| (1<<PD1)| (1<<PD0);
      PORTD |= ((1 << PD7) | (1 << PD6) |(1<<PD5) | (1<<PD4) | (1<<PD3) | (1<<PD2)| (1<<PD1)| (1<<PD0));
    
      ADC_init();
    
      while (1)
      {
        //0V = 0
        //1V = 205
        //2V = 409
        //3V = 614
        //4V = 816
        //5V = 1023
        //Vgemessen=lastValue*5/1024;
    
        lastValue = ADC_Read(0);
        if (lastValue = 0) {
           PORTD = 0b11111111;
        }
        else if (lastValue > 205) {
           PORTD = 0b11111110;
        }
        else if (lastValue < 409) {
          PORTD = 0b11111100;
        }
        else if (lastValue > 614) {
           PORTD = 0b11111000;
        }
        else if (lastValue > 816) {
          PORTD = 0b11110000;
        }
        else if (lastValue > 1023) {
          PORTD = 0b11100000;
        }
        }
    }
    
    /* ADC initialisieren */
    void ADC_init(void) {
        // die Versorgungsspannung AVcc als Refernz wählen:
        ADMUX = (1<<REFS0);
        // oder interne Referenzspannung als Referenz 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. */
        (void) ADCW;
    }
    
    /* ADC Einzelmessung */
    uint16_t ADC_Read(uint8_t channel)
    {
        // Kanal waehlen, ohne andere Bits zu beeinflußen
        ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
        ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
        while (ADCSRA & (1<<ADSC) ) {   // auf Abschluss der Konvertierung warten
        }
        return ADCW;                    // ADC auslesen und zurückgeben
    }
    Klicke auf die Grafik für eine größere Ansicht

Name:	Drawing1.jpg
Hits:	10
Größe:	51,9 KB
ID:	28892

  7. #7
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    Nur ein Hinweis.
    Du kannst Probleme bekommen wenn du AREF mit AVCC verbindest. An AREF gehört ein 100n Kondensator nach GND.
    Wenn du, wie in deinem Fall einmal die interne Referenz verwenden willst, fließt ein Ausgleichsstrom in AREF.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

  8. #8
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651
    ... aktuelles Problem ... ADC wert > 205 und < 409 ... Immer sogar wenn nichts angeschlossen ist ...

    Code:
    ...
    /* ADC Einzelmessung */
    uint16_t ADC_Read(uint8_t channel)
    {
        // Kanal waehlen, ohne andere Bits zu beeinflußen
        ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
        ADCSRA |= (1<<ADSC);            // eine Wandlung "single conversion"
        while (ADCSRA & (1<<ADSC) ) {   // auf Abschluss der Konvertierung warten
        }
        return ADCW;                    // ADC auslesen und zurückgeben
    }
    Wenn das Ergebnis gleich ist - egal ob am ADC eine Spannung anliegt oder der Pinn in der Luft hängt - dann klingt das doch danach, dass der ADC "nichts" misst. Jedenfalls nichts Sinnvolles. Oder?

    Rechne mal bitte: Dein Vorteiler ist clock/8. WENN Du den Controller mit 8 MHz fährst (ist ja nicht unüblich, Du gibst hier leider nix an) dann bekommst Du eine ADC-Frequenz von 1 MHz. Dieser Takt ist die Stoppuhr für die Abläufe des ADC - der zählt die Takte und bemisst damit seine Samplezeit, seine Wandlungszeit und so.
    Zitat Zitat von Atmel-Datasheet 8271E–AVR–07/2012
    ... By default, the successive approximation circuitry requires an input clock frequency between 50kHz and 200kHz to get maximum resolution. If a lower resolution than 10 bits is needed, the input clock frequency to the ADC can be higher than 200kHz to get a higher sample rate...
    Nun siehts also so aus, als sei Dein ADC-Takt zu hoch >>WENN<< meine Annahme mit den 8 MHz stimmt. Musst halt rechnen.

    Verdächtig erscheint mir auch Dein Kanalwechsel bei Deiner ADC_Read-Funktion mit der unmittelbar folgenden Leseaktion. Lies Dir dazu mal das Datenblatt durch, Abschnitt Changing Channel oder so, dort ist ausgeführt wie glaubhaft der erste Wert nach dem Kanalwechsel ist. Und ein Kanalwechsel erfolgt (meines Wissens nach) auch dann, wenn durch den Befehl derselbe Kanal wie vorher ausgewählt wird . . .

    Und Huberts Hinweis ist ja auch im Datenblatt (... Analog Input Circuitry ...) näher erläutert *gg*
    Ciao sagt der JoeamBerg

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    12.08.2014
    Beiträge
    11
    ja der Controller läuft mit 8Mhz...

    Wenn ich das richtig verstehe das ist mein Teilungsfaktor falsch...
    Nach dieser Rechnung müsste ich den Faktor 64 Nehmen und nich 8 ist das so korrekt von mir ?

    TFmin=CLK/200kHz=8000000/200000=40
    TFmax=CLK/50kHz=8000000/50000=160
    ADCSRA = (1<<ADPS1) | (0<<ADPS0); // Teilungsfaktor (64)

  10. #10
    Erfahrener Benutzer Roboter Genie Avatar von HeXPloreR
    Registriert seit
    08.07.2008
    Ort
    Bad Bramstedt
    Alter
    45
    Beiträge
    1.369
    Hallo,

    zusätzlich, und nicht ganz unwichtig, finde ich es auch zu sagen das ein Analogsensor meist einen Spannungswert (V) aus gibt. Mir ist bisher kein Drucksesnor begegnet/bekannt der das nicht tut - mal abgesehen von I²C und PWM und so weiter, wo also der Sensor die Spannungswerte selbst vorverarbeitete und als "Datenpaket" verschickt. Bist Du denn sicher das dein Sensor mA(mpere) ausgibt? Welcher Sensor ist das genau? Oder sind es doch eher mV?

    Um das Problem mit der ADC-Grundbeschaltung zu lösen würde ich mir persönlich den Schaltplan der RN-Control diesbezüglich rein tun. Diese ist aber dann definitiv nur für Spanungen (V) am ADC gedacht. Ob man dazu einen Shunt aufbauen muss damit man Ampere erhält .... hab ich mich noch nicht ausreichen damit beschäftigt deswegen bleibt diese Antwort von mir offen.

    Blöd wäre es ja nur wenn der Sensor sowieso schon "wirklich" einen mA-Wert als verkappten "Spannungswert" liefert ... frage mich grade ob man an so einem Wert überhaupt dann noch was umrechnen muss, wenn es schon der gesuchte Wert ist?

    Das Problem bei Deiner ersten Rechnung oben wird sein, das Du nur *5,0 rechnest. Dadurch ist eine 10 Bit-Wert schon mit dem kleinsten Messwert von 1 Bit auf 5. Und das sagt ja quasi garnichts aus ebensowenig wie 5115 bei max wert - es sei denn man rechnet sich das auch wieder umständlich um... dieser wert müsste also noch durch 1023 (10Bit) geteilt werden U = ADC-bit * Ref (5V) /1023-bit. Daraus kann man eine Konstante erstellen = Ref(5V)/1023 mit der dann der ADC-Wert nur noch multupliziert werden muss um die korrekte Spannung angegeben zu bekommen.

    Hüstel: und der Sensor sollte natürlich im angegeben Spannungsbereich (etwa 3,3 - 5V) funktionieren.

    Hüstel nochmal: Du solltest mal schauen ob in Deinem zweiten Programm Dein "Vgemessen" ggf nicht in einem Kommentar stehen sollte. Und ob es gut ist "LastValue" zu prüfen obwohl Du "Vgemessen" vergleichen möchtest, oder?
    Wenn Du vermutlich eine Art Bargraph Anzeige realisieren möchtest dann sollte auch nicht nur der Wert für den 409er Vergleich auf kleiner (<) geprüft werden sondern Alle. Ggf machte es auch Sinn bei dieser Art des Vergleichs die Reihenfolge umzudrehen, also erst auf den größten ADC-Wert zuerst zu prüfen. Denn dann sind es weniger Vergleiche wenn man davon ausgeht das eher eine hohe Spannung anliegt als eine niedrige. 1023 als Vergleichswert könnte man vernachlässigen...


    Viele Grüße
    Jörg
    Geändert von HeXPloreR (13.08.2014 um 20:20 Uhr)

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. ATMega32, Werte vom ADC ins EEPROM
    Von Spessi im Forum C - Programmierung (GCC u.a.)
    Antworten: 9
    Letzter Beitrag: 13.11.2008, 00:12
  2. ATMega8 + EEPROM
    Von Bumbum im Forum C - Programmierung (GCC u.a.)
    Antworten: 6
    Letzter Beitrag: 14.06.2008, 23:00
  3. I2C-EEprom an ATMega8
    Von .Johannes. im Forum AVR Hardwarethemen
    Antworten: 1
    Letzter Beitrag: 08.06.2006, 14:42
  4. ATmega8 aus dem EEPROM lesen und ins EEPROM Schreiben
    Von melowtrax im Forum AVR Hardwarethemen
    Antworten: 6
    Letzter Beitrag: 20.02.2006, 23:32
  5. Messwerte aus ADC in internem EEPROM vom ATMega8 abspeichern
    Von RalfP im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 5
    Letzter Beitrag: 28.10.2005, 17:43

Stichworte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiTime Speicher und Akkus