- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 4 von 4

Thema: adc0, adc1, scl

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    01.12.2010
    Ort
    Dörpen
    Alter
    26
    Beiträge
    120

    adc0, adc1, scl

    Anzeige

    Praxistest und DIY Projekte
    hey roboterfans...
    ich habe mal wieder ein problem.
    ich möchte für meinen roboterarm 3 Servos an die rp6 base anschließen, einmal an adc0, dann an adc1 und an scl....
    allerdings weiß ich nicht wie man sie ansteuert. könnt ihr mir da vielleicht weiter helfen?

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    17.09.2004
    Alter
    39
    Beiträge
    647
    Wenns dir um die grundsätzliche Ansteuerung geht, dann benutz mal die Suchfunktion oder schau im RN-Wiki. Das wurde schon oft erklärt.

    Gruß Daniel
    Unser Sommer ist ein grün angestrichener Winter. Das einzige reife Obst, das wir haben, sind gebratene Äpfel. [Heinrich Heine]

  3. #3
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Grundsätzlich unterscheidet man blockierende und nicht blockierende Ansteuerungen. Blockierend bedeutet, das Programm wird nicht weiter fortgeführt wärend die Servoimpulse erzeugt werden. (Wie so ein Impuls aussehen sollte ist Grundlage, das solltest du schon wissen). Die Impulse werden solange erzeugt bis das Servo genug Zeit hatte die Zielpossition zu erreichen. Ein Beispiel mit Servo an LED1 (IO1):
    Code:
    // RP6 steuert ein Servo an der SL1-LED mit Sleep() 
    
    #include "RP6RobotBaseLib.h" 
    
    uint8_t i; 
    
    int main(void) 
    { 
    initRobotBase(); 
    
       while(true) 
       { 
          i=0;                           // i mit Startwert laden 
          while(getBumperLeft() && (i<5))   // Wenn links gedrückt fünf Impulse senden 
          { 
             setLEDs(1);                // Impuls High senden 
             sleep(10);                 // ca. 10 * 100µs warten 
             setLEDs(0);                // Impuls Low senden 
             sleep(200-10);             // ca. 20ms - 1ms Pause 
             i++; 
          } 
    
          i=0; 
          while(getBumperRight() && (i<5)) 
          { 
             setLEDs(1); 
             sleep(20); 
             setLEDs(0); 
             sleep(200-20); 
             i++; 
          } 
       } 
    
       return 0; 
    }
    https://www.roboternetz.de/community...l=1#post414115

    Es wird solange ein Impuls erzeugt wie ein Bumper gedrückt wird. Ein Sleep(1) dauert beim RP6 0,1ms, Sleep(10) entsprechend 1ms bzw. Sleep(20) eben 2ms. Obwohl man mit dieser Methode auch mehrere Servos gleichzeitig ansteuern kann, ist sie letztlich eine Sackgasse, denn der RP6 kann ja nichts nebenher erledigen. Wenn er doch etwas anderes macht erhalten die Servos keine Impulse mehr und dein Roboterarm knickt ab...

    Ganz anders verhalten sich interruptgesteuerte Ansteuerungen. Hier wird vom (Haupt-)Programm ledig die Zielposition vorgegeben, die Interruptsteuerung sorgt dann im Hintergrund dafür, das die entsprechenden Impulse erzeugt werden. Blöd ist allerdings dabei, dass die Lib des RP6 alle Timer belegt. Die einfachste libverträgliche Lösung ist deshalb wohl dieser Ansatz:
    Code:
    // Servoansteuerung mit Timer1                                         31.1.2010 mic
    
    // Einfach und elegant, warum finde ich das erst jetzt? Timer1 (RP6-Motoransteuerung)
    // läuft ja sowieso im Hintergrund. Deshalb kann man die "klassische" Servoansteuerung
    // in die Overflow-ISR einbauen und mit ca. 19kHz aufrufen lassen. Timersetup der Lib:
    // Mode 10, Phase Correct mit ICR1 als Top ergibt bei ICR1=210 ca. 8MHz/420=19047,6Hz ;)
    
    // Drehbereich meiner RS-2-Servos ist von ca. 14 bis ca. 38
    
    #include "RP6RobotBaseLib.h"
    
    volatile uint8_t servo1, servo2, servo3, p; 	// Servopositionen und Impulszähler
    uint8_t c; 												// ein Char zur freien Verfügung
    
    int main(void)
    {
       initRobotBase();
       servo1=servo2=servo3=26;	// Servomitte?
       TIMSK |= (1 << TOIE1); 		// Die Timer1 Overflow-ISR zur Servoansteuerung
    	DDRA |= (E_INT1);          // Servopins auf Ausgang setzen
       DDRC |= (SCL | SDA);
       setLEDs(1);                // und los!
       startStopwatch1();
       startStopwatch2();
       startStopwatch3();
    	while(1)
       {
       	for(c=0;c<6;c++)            // 6 mal ein einfaches Demo....
    		{
    		   setLEDs(1<<c);
    			servo1=servo2=servo3=26; // mitte
       		p=50; while(p);          // warten bis 50 Impulse gesendet (ca. 1 Sek.)
       		servo1=servo2=servo3=14; // links
       		p=50; while(p);
       		servo1=servo2=servo3=38; // rechts
       		p=50; while(p);
    		}
    		setStopwatch1(0);
    		setStopwatch2(0);
    		setStopwatch3(0);
    		while(c)                    // und 6 mal ein etwas anspruchsvolleres Demo
    		{
    		   setLEDs(1<<c);
    		   if(getStopwatch1()>1000)
    		   {
    		      setStopwatch1(0);
    				switch(servo1)
    		      {
    		         case 38: servo1=30; break;
    		         case 30: servo1=20; break;
    		         case 20: servo1=14; break;
    		         case 14: servo1=21; break;
    		         case 21: servo1=31; break;
    		         case 31: servo1=38; break;
    				}
    			}
    		   if(getStopwatch2()>100)
    		   {
    		      setStopwatch2(0);
    		      servo2++;
    		      if (servo2 > 38) { servo2=14; c--; }
    			}
    		   if(getStopwatch3()>300)
    		   {
    		      setStopwatch3(0);
    		      if (servo3 == 10) servo3=50; else servo3=10;
    			}
    			task_RP6System(); // Verträglichkeitstest ;)
    		}
       }
       return 0;
    }
    ISR (TIMER1_OVF_vect)
    {
    	static uint16_t servocount=1;
    	if(servocount > servo1) PORTA &= ~E_INT1; else PORTA |= E_INT1; 		// PA4 XBUS 8
    	if(servocount > servo2) PORTC &= ~SCL; else PORTC |= SCL; 				// PC0 XBUS 10
    	if(servocount > servo3) PORTC &= ~SDA; else PORTC |= SDA; 				// PC1 XBUS 12
    	if(servocount < 400) servocount++; else {servocount=1; if(p) p--;} 	// p = 1/50 Sek
    }
    https://www.roboternetz.de/community...l=1#post447000

    Nachteil dieser eigentlich bestechend einfachen Lösung ist die geringe Auflösung der Servopositionen. (Vielleicht kann man das auch mit einem anderen Timer tricksen?) Vorteil ist eben, dass die Impuls durchgehend erzeugt werden, egal was man im Hauptprogramm macht.

    Beim Anschluss an ADC0 oder ADC1 muss man beachten, dass das Pinout auf der RP6-Platine nicht servokonform ist. Deshalb muss man am Servostecker Plus und Minus tauschen:

    Klicke auf die Grafik für eine größere Ansicht

Name:	servoanschluss1_klein.jpg
Hits:	7
Größe:	14,4 KB
ID:	19387

    Vielleicht reicht dir das schon zum Einstieg.

    Gruß

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

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    01.12.2010
    Ort
    Dörpen
    Alter
    26
    Beiträge
    120
    Beim Anschluss an ADC0 oder ADC1 muss man beachten, dass das Pinout auf der RP6-Platine nicht servokonform ist. Deshalb muss man am Servostecker Plus und Minus tauschen:
    ok danke bisdahin für die vielen hinweise.. allerdings wollte ich eigentlich nur wissen wie man adc0 und 1 in einem programm mit einbaut. für scl weiß ich es ja jetzt (
    Code:

    // Servoansteuerung mit Timer1 31.1.2010 mic // Einfach und elegant, warum finde ich das erst jetzt? Timer1 (RP6-Motoransteuerung) // läuft ja sowieso im Hintergrund. Deshalb kann man die "klassische" Servoansteuerung // in die Overflow-ISR einbauen und mit ca. 19kHz aufrufen lassen. Timersetup der Lib: // Mode 10, Phase Correct mit ICR1 als Top ergibt bei ICR1=210 ca. 8MHz/420=19047,6Hz // Drehbereich meiner RS-2-Servos ist von ca. 14 bis ca. 38 #include "RP6RobotBaseLib.h" volatile uint8_t servo1, servo2, servo3, p; // Servopositionen und Impulszähler uint8_t c; // ein Char zur freien Verfügung int main(void) { initRobotBase(); servo1=servo2=servo3=26; // Servomitte? TIMSK |= (1 << TOIE1); // Die Timer1 Overflow-ISR zur Servoansteuerung DDRA |= (E_INT1); // Servopins auf Ausgang setzen DDRC |= (SCL | SDA); setLEDs(1); // und los! startStopwatch1(); startStopwatch2(); startStopwatch3(); while(1) { for(c=0;c<6;c++) // 6 mal ein einfaches Demo.... { setLEDs(1<<c); servo1=servo2=servo3=26; // mitte p=50; while(p); // warten bis 50 Impulse gesendet (ca. 1 Sek.) servo1=servo2=servo3=14; // links p=50; while(p); servo1=servo2=servo3=38; // rechts p=50; while(p); } setStopwatch1(0); setStopwatch2(0); setStopwatch3(0); while(c) // und 6 mal ein etwas anspruchsvolleres Demo { setLEDs(1<<c); if(getStopwatch1()>1000) { setStopwatch1(0); switch(servo1) { case 38: servo1=30; break; case 30: servo1=20; break; case 20: servo1=14; break; case 14: servo1=21; break; case 21: servo1=31; break; case 31: servo1=38; break; } } if(getStopwatch2()>100) { setStopwatch2(0); servo2++; if (servo2 > 3 { servo2=14; c--; } } if(getStopwatch3()>300) { setStopwatch3(0); if (servo3 == 10) servo3=50; else servo3=10; } task_RP6System(); // Verträglichkeitstest } } return 0; } ISR (TIMER1_OVF_vect) { static uint16_t servocount=1; if(servocount > servo1) PORTA &= ~E_INT1; else PORTA |= E_INT1; // PA4 XBUS 8 if(servocount > servo2) PORTC &= ~SCL; else PORTC |= SCL; // PC0 XBUS 10 if(servocount > servo3) PORTC &= ~SDA; else PORTC |= SDA; // PC1 XBUS 12 if(servocount < 400) servocount++; else {servocount=1; if(p) p--;} // p = 1/50 Sek }
    )

Ähnliche Themen

  1. Frage zu ADC1
    Von Joggel84 im Forum Robby RP6
    Antworten: 3
    Letzter Beitrag: 30.10.2010, 16:53
  2. Poti an ADC0/ADC1
    Von neo3000 im Forum Robby RP6
    Antworten: 4
    Letzter Beitrag: 24.10.2010, 01:09
  3. A/D Wandler freerun ADC0 und ADC1 ohne Interrupt
    Von guenter1604 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 7
    Letzter Beitrag: 14.12.2009, 12:01
  4. ADC0 funktioniert, ADC1 bis ADC5 nicht (Atmega8)
    Von DEAF BOY im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 06.03.2007, 15:26
  5. Strommessung (Differenz) über ADC0 und ADC1
    Von RHS im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 9
    Letzter Beitrag: 19.02.2007, 18:55

Berechtigungen

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

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad