-         

Ergebnis 1 bis 10 von 10

Thema: servoposition über adc(poti) steuern

  1. #1

    servoposition über adc(poti) steuern

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    Hallo.
    ich hab bis jetzt mit Bascom gearbeitet. ich hab mit Bascom als letztes die positionen von zwei Servos über zwei potis gesteuert. jetzt bin ich gerade am c++ erlernen. die ersten versuche sind auch gut gelaufen. doch jetzt hab ich gerade ein Problem. ich möchte nun in c++ die Servoposition über den adc-eingang (über poti regelbar) steuern.
    ich hab auch schon einiges über adc-programmierung gelesen doch ich komm nicht weiter.
    ich muss den adc wert ja irgendwie auslesen. der rest sollte dann kein problem mehr sein. da ich das dann mit einer switch oder if-anweisung lösen kann.
    hat mir jemand ein beispielprogramm zum auslesen des adc. vielleicht noch mit ein paar beschreibungen.
    danke schon mal

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    33
    Beiträge
    2.378
    studiere gründlich das datenblatt, das ist eigentlich sehr aufschlussreich aber hart im lesen

    versuch mal mittels datenblatt folgendes zu verarbeiten
    Code:
    SIGNAL (SIG_OVERFLOW2)
    {
    	if ((TCCR2 & (BV(COM21) | BV(COM20))) != 0) TCCR2 &= ~(BV(COM21) | BV(COM20));
    	else if (Count%32 == 0) TCCR2 |= BV(COM21) | BV(COM20);
    	if ((PIND & BV(PD6)) && !(PIND & BV(PD7))) OCR2 = -55-16;
    	else if ((PIND & BV(PD7)) && !(PIND & BV(PD6))) OCR2 = -55+16;
    	else {
    		diff = ADCL + (ADCH << 8);
    		diff = (diff/32)-16;
    		OCR2 = -47+(diff);  
    	}
    }
    
    SIGNAL (SIG_OUTPUT_COMPARE2)
    {
    //	TCCR2 &= ~(BV(COM21) | BV(COM20));
    }
    
    int main(void)
    {
    	Count = 0;
    	diff = 0;
    	dir = 4;
    	cli();
    	ADCL = 0;
    	ADCH = 0;
    	DDRB = BV(PB4) | BV(PB5) | BV(PB3);
    	PORTB = BV(PB4);
    	TCNT2 = 0;
    	OCR2 = -55;
    	TCCR2 = BV(WGM21) | 
    			BV(WGM20) |
    			BV(COM21) |
    			BV(COM20) | 
    			BV(CS22) | 
    			BV(CS21);
    	TIMSK = BV(TOIE2);// | BV(OCIE2);
    	sei();
    	PORTB = BV(PB5);
    	ADCSRA = BV(ADFR) | BV(ADPS2) | BV(ADPS1);
    	ADMUX = BV(REFS0);
    	ADCSRA |= BV(ADEN);
    	ADCSRA |= BV(ADSC);
    	while (1){
    	}
    }
    Atmega8 mit 8Mhz intern getaktet, das oszi hat ne saubere 1ms +-0.5ms flanke angezeigt und der servo reagiert auch wie erwartet

    Link zu Youtube-Video

  3. #3
    hi,
    danke für die Antwort. sind ja nette filmchen. nicht schlecht.
    ich wollt noch fragen was ich dafür für eine lib benötige. ich bekomm nämlich nur Fehlermeldungen

    danke

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    33
    Beiträge
    2.378
    ahso die includes hab cih in ne headerfile gemacht sry XD

    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <avr/timer.h>
    #include <avr/signal.h>
    #include <avr/sleep.h>
    dateinamen sind bei mir

    Atmega8Test.c / .h

    auf timer und sleep kannste sicherlich pfeifen, die hab ich nur aus nem weiteren versuch einfach mitkopiert XD

  5. #5
    also ich hab jetzt ein programm im internet gefunden. ich habs n bisschen verändert. ich möchte jetzt das die led's an portD leuchten wenn an PC0 ADC0 mehr als 2,5V (>512) anliegen. ist das so ok. bei mir passiert nämlich nichts.

    Code:
    #include <avr/io.h>
    
    
    uint16_t auswertung (void);
    volatile uint16_t wert=0;
    
    int main (void)
    {
      uint16_t i=0,ergebnis=0;
    
      //Ports initialisieren
      DDRC  = 0xFF; //Port C als Ausgang für die LED's
      PORTC = 0XFF; //Pull Up's aktiviert
    
    
      while(1)
      {
        ergebnis = auswertung();
    
    
        if ( (ergebnis < 512) && (ergebnis > 1) )
        {
          PORTC = (0b00001111);
        }
        else PORTC = (0b10101010);
    
      }
    }
    
    
    
    uint16_t auswertung (void)
    {
    
    
    //Initialisieren
    ADCSRA = ((1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0));
    ADMUX = ((1<<MUX0) | (1<<MUX1) | (1<<MUX2));
    
    //Dummy Auslesung als Warm-Up wie im Tutorial
    ADCSRA |= (1<<ADSC);
    while (ADCSRA & (1<<ADSC));
    
    //Messung
    ADCSRA |= (1<<ADSC);
    while (ADCSRA & (1<<ADSC));
    
    wert = ADCL; //ERR
    wert += (ADCH<<8); //Alternativ 'wert = ADCW;'
    
    ADCSRA &= ~(1<<ADEN); //ADC Disable
    
    return wert;
    
    }

  6. #6
    sorry war der falsche code. das war der urspüngliche

    Code:
    #include <avr/io.h>
    
    
    uint16_t auswertung (void);
    volatile uint16_t wert=0;
    
    int main (void)
    {
      uint16_t i=0,ergebnis=0;
    
      //Ports initialisieren
      DDRD  = 0xFF; //Port C als Ausgang für die LED's
      PORTD = 0XFF; //Pull Up's aktiviert
    
    
      while(1)
      {
        ergebnis = auswertung();
    
    
        if ( (ergebnis < 512) && (ergebnis > 1) )
        {
          PORTD = (0b11111111);
        }
        else PORTD = (0b00000000);
    
      }
    }
    
    
    
    uint16_t auswertung (void)
    {
    
    
    //Initialisieren
    ADCSRA = ((1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0));
    ADMUX = (1<<MUX0) ;
    
    //Dummy Auslesung als Warm-Up wie im Tutorial
    ADCSRA |= (1<<ADSC);
    while (ADCSRA & (1<<ADSC));
    
    //Messung
    ADCSRA |= (1<<ADSC);
    while (ADCSRA & (1<<ADSC));
    
    wert = ADCL; //ERR
    wert += (ADCH<<8); //Alternativ 'wert = ADCW;'
    
    ADCSRA &= ~(1<<ADEN); //ADC Disable
    
    return wert;
    
    }

  7. #7
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    33
    Beiträge
    2.378
    hast du denn den AVCC AGND unf AREF richtig beschaltet ?? also die versorgung für den AD-Wandler ?

  8. #8
    agnd und avcc ist richtig beschaltet. aref hab ich nicht beschaltet hat aber bei Bascom auch keine probleme gemacht.

  9. #9
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    54
    Beiträge
    5.781
    Blog-Einträge
    8
    Hallo

    Ist ADC0 nicht Kanal 0 und müste deshalb nicht ADMUX mit 0 geladen werden? (ADMUX=0)

    Gruß

    mic

    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  10. #10
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    33
    Beiträge
    2.378
    na du machst mir spass, schau mal bitte in das datenblatt, da steht wenn du aus dem ADMUX register refs1 UND refs2 = 0 hast wird AREF als REFERENZ benutzt!! Du MUSST es also beschalten!!!

    MUX0 heisst das du ADC1 verwendest um zu messen und NICHT ADC0

    einfach wie in meinem beispiel einen 100nF (geht auch größer) von AREF zu VCC und ADMUX = BV(REFS0); MEHR NICHT

    bitte erst das datenblatt vernünftig lesen dann AREF unbeschaltet lassen ^^ (im datenblatt wird sogar ausdrücklich gebeten AREF nie unbeschaltet zu lassen wenn man ADC verwendet)


    EDIT: wenn ich das kabel vom steckboard nehme was zum ADC0 führt und es in der luft hängt, kann ich mit dem finger näher kommen und der servo fährt allmählich in die endlage ... gut möglich das du bei deien ersten versuchen einfach nur glück hattest

Berechtigungen

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