Forum: Mikrocontroller und Digitale Elektronik Ladung or Entladung eines Kondensator mit Free Running Mode ATmega 8


von Riki F. (Firma: Herr) (riki12)


Lesenswert?

Hallo zusammen,
ich bin ganz neu mit  Mikrocontroller und habe folgendes zu tun:
- ich möchte die Spannung bei Kondensator-Ladung erfassen
- ich habe mich für Free Running Mode entschieden
- die Spannung soll auf eeprom geschrieben  und ausgelesen werden.

so sieht mein Code aus:
1
....
2
#define u16 unsigned int
3
u16 Ssoll;
4
u16 Spann;
5
u16 eeFooWord EEMEM;
6
7
8
int main(void){
9
uint16_t ausgabe =0;
10
11
DDRC = 0x01;       // damit ist dann PC0 ein Ausgang
12
ADMUX = (1 << REFS0) | (1 << ADLAR) ;     
13
ADMUX |= (1<< MUX0); // ADC1 als Quelle auswählen
14
  
15
ADCSRA |= (1<<ADFR)|(1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);  // Free Running mode ,Frequenzvorteiler auf 8
16
  
17
ADCSRA |= (1<<ADSC);                            // Start Conversion
18
  
19
  
20
while ( !(ADCSRA & (1<<ADSC)) ) {}  // auf Abschluss der Konvertierung warten
21
  {
22
    if ( PORTC |= 0x01)            // Set PC0
23
    {
24
    ausgabe +=ADCH; // Erste 8 Bit von 10 Bit nehmen.
25
    //c=ADC*0.004883;
26
    return ausgabe;                 // ADC auslesen und zurückgeben
27
   adcval = 0.00483*ausgabe;  // 
28
  eeprom_write_word(&eeFooWord, adcval);  // Schreiben
29
    
30
      
31
  Spann = eeprom_read_word(&eeFooWord); // lesen
32
33
  //  ADCSRA &= ~(1<<ADEN);            // ADC deaktivieren
34
      _delay_ms(100); //  ms Wartezeit
35
}
36
    else
37
    {
38
      PORTC  &= ~0x01 ; //Reset PC0
39
      // _delay_ms(250);       //250ms warten
40
    }
41
    
42
  }
43
  return (0);
44
45
}

ich habe meinen Kondensator an Oszi. geschaltet und je nach Wert von PC0 
kann ich die Ladung oder Entladung beobachten. (Atmel Studio 6.2)
aber ich  möchte die Spannung bei Ent-und Ladung erfassen.

1. Wie kann ich dies machen?
2. wie funktioniert das Schreiben und Lesen auf Eeprom beim Free Running 
Mode (Ein Code wäre optimal). ich weiß auch nicht, ob ich es lieber mit 
Single Conversion Mode machen soll
Danke in Voraus

: Bearbeitet durch User
von Riki12 (Gast)


Lesenswert?

ist hier niemand, brauche Hilfe

von Karl H. (kbuchegg)


Lesenswert?

Was versprichst du dir vom Free Running Mode?
Der bringt dir nichts, wenn du die gesampelten Daten nicht schnell genug 
abholen bzw. loswerden (also speichern) kannst.

BTW: Auf EEPROM schreiben ist vergleichsweise langsam.

von Karl H. (kbuchegg)


Lesenswert?

Was spricht dagegen, ganz einfach die Routinen aus dem AVR-GCC-Tutorial 
erst mal einfach nur zu übernehmen.

https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Analoge_Ein-_und_Ausgabe#Der_interne_ADC_im_AVR

Dein Programm wird dann vom Prinzip her zu:
1
...
2
3
uint16_t EEpromAddress;
4
5
int main()
6
{
7
  uint16_t adc_val;
8
9
  EEpromAddress = 0;
10
  ADC_Init();
11
12
  while( 1 ) {
13
    adc_val = ADC_Read( 0 );
14
    eeprom_write_word( EEpromAddress, adc_val);    
15
    EEpromAddress++;
16
  }
17
}

noch simpler gehts eigentlich kaum mehr. Die Einstellung der 
Referenzspannung in den ADC Routinen musst du noch kontrollieren bzw. 
anpassen.
Überlegen musst du dir noch, wie du den Beginn bzw. das Ende der Messung 
triggerst, bzw. da muss noch eine Abfrage rein, damit du das EEPROM 
nicht "überläufst". Aber das überlass ich dir.

von Karl H. (kbuchegg)


Lesenswert?

PS: in deinem Code sind so einige Probleme enthalten.
1
while ( !(ADCSRA & (1<<ADSC)) ) {}  // auf Abschluss der Konvertierung warten

das wird nichts werden. Technisch gesehen, sagt dir das ADSC Bit, ob der 
ADC arbeitet oder nicht. Im Free Running Modus arbeitet der aber 
praktisch dauernd. D.h. du wirst dieses Bit nie auf 0 erwischen. Free 
Running macht eigentlich nur Sinn, wenn man mit Interrupts arbeitet oder 
wenn man ganz einfach den aktuellen ADC Wert ganz simpel ausliest "ohne 
Rücksicht auf Verluste."
Aber eigentlich brauchst du den Free Running gar nicht. WEnn du messen 
willst, setz das ADSC Bit um den ADC zu starten und warte auf das 
Ergebnis. Genau so, wie es die Tutorial Routinen machen.
1
    if ( PORTC |= 0x01)            // Set PC0
2
    {
3
    ausgabe +=ADCH; // Erste 8 Bit von 10 Bit nehmen.
4
    //c=ADC*0.004883;
5
    return ausgabe;                 // ADC auslesen und zurückgeben
was macht der return da mitten drinn?
und warum summierst du den ADC Wert?

Darf man fragen, was das hier
1
    if ( PORTC |= 0x01)            // Set PC0
sein soll? Wozu ein if? Welchen Zweck soll das haben?

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Und achte auf deine Code Formatierung.
Es ist kein Zufall, dass diejenigen mit dem scheuslichsten Code auch 
immer die mit den dümmsten Fehlern sind.

Denn: Hauptschleife sehe ich auch keine in deinem Code.

: Bearbeitet durch User
von Riki12 (Gast)


Lesenswert?

if ( PORTC |= 0x01)            // Set PC0
ist mit dem Mosfet Verbunden. dies soll mit HIGH der Transistor 
schalten. Wenn er geschaltet ist, soll ich mit der Erfassung von Werten 
anfangen und dann die speichern

von Karl H. (kbuchegg)


Lesenswert?

Riki12 schrieb:
> if ( PORTC |= 0x01)            // Set PC0
> ist mit dem Mosfet Verbunden. dies soll mit HIGH der Transistor
> schalten. Wenn er geschaltet ist, soll ich mit der Erfassung von Werten
> anfangen und dann die speichern

Ob der geschaltet ist oder nicht, kannst du aber so nicht feststellen.

WEnn du
1
   PORTC |= 0x01;

ausführen lässt, dann wechselt der Pin auf 1. Zumindest wird der 
entsprechende Ausgangstreiber im AVR entsprechend umgeschaltet. Ob der 
Pin tatsächlich auf 1 gegangen ist oder nicht (weil zb ein Kurzschluss 
vorliegt), das kannst du so nicht feststellen. Genausowenig wie du auf 
die Art feststellen kannst, ob das was am Pin hängt auch das tut, was du 
erwartest.

Das schöne an einem µC ist: wenn du ihn anweist, einen Pin auf 1 zu 
setzen, dann tut er das auch. Immer. (Ausser natürlich wenn es 
physikalische Beschränkungen gibt, wie zb ein Kurzschluss). D.h. das 
brauchst du nicht testen. Und so (auf die Art) kannst du das sowieso 
nicht testen.

von Riki F. (Firma: Herr) (riki12)


Angehängte Dateien:

Lesenswert?

Hallo,
ich habe jetzt versucht meine Code wie hier steht: 
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Analoge_Ein-_und_Ausgabe#Der_interne_ADC_im_AVR
aber ich habe ein Paar Fehler und ich möchte gern sie wegkriegen.
void ADC_Init(void)
{
ADMUX |= (1<<REFS0);                            // vcc als 
Referenzspannung

//ADMUX = (1 << REFS0) | (1 << ADLAR) ;


ADCSRA = (1<<ADPS1) | (1<<ADPS0);  // Free Running mode 
,Frequenzvorteiler auf 8
ADCSRA |= (1<<ADEN);

ADCSRA |= (1<<ADSC);                            // Start Conversion
  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
}

uint16_t EEpromAddress;
int main(void){

  uint16_t adc_val ;
  EEpromAddress =0;
    ADC_Init();


  DDRC = 0x01;       // damit ist dann PC0 ein Ausgang
  /* ADC initialisieren */
    while( 1 ) {
      if ( PORTC |= 0x01)
      {
        adc_val = ADC_Read( 1 );
        eeprom_write_word( EEpromAddress, adc_val);
        EEpromAddress++;
        eeprom_read_word(EEpromAddress);
      }
      else
      {
         PORTC  &= ~0x01 ; //Reset PC0
      }
    }
    return (0);
  }



Danke im Voraus

von Riki12 (Gast)


Lesenswert?

.....??????

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.