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

Thema: Robosapien V1 mit RP6 steuern!

  1. #1

    Robosapien V1 mit RP6 steuern!

    Anzeige

    LiFePo4 Akku selber bauen - Video
    Hallo zusammen,

    möchte gerne mit dem RP6 meinen Robosapien V1 steuern.
    Leider funktioniert es nicht unten mein Anweisungen. Den TimerInterupt habe ich in der RP6RobotBaselib auskommentiert. Vielleicht hat einer nen Tip!

    Code:
    #include "RP6RobotBaseLib.h"
    uint16_t z;
    uint8_t i;
    uint8_t ir_command;
    uint16_t Zeit;
    
    void Delay_us(uint16_t Verzoegerung)
    {
    	Zeit=0;
    	while(Zeit<=Verzoegerung);
    }
    
    void ir_code_833(void)
    {
    	for(z=0; z<= 33;z++)
    	{
    		PORTD = (1<<PIND7);
    		Delay_us(13);
    		PORTD &= ~(1<<PIND7);
    		Delay_us(12);
    	}
    }
    
    void ir_code_6666(void)
    {
    	for(z=0; z<= 266;z++)
    	{
    		PORTD = (1<<PIND7);
    		Delay_us(13);
    		PORTD &= ~(1<<PIND7);
    		Delay_us(12);
    	}
    }
    
    ISR (TIMER2_OVF_vect)
    {
    	Zeit++;
    }
    
    int main(void)
    {
    	initRobotBase();
    
    	TCCR2 = (1 << WGM21) | (0 << COM20) | (1 << CS20);
    	OCR2 = 0x08; // 0x66 = 78,4kHz @8MHz
    
    	// Initialize Timer Interrupts:
    	TIMSK = (1 << OCIE0); //| (1 << OCIE2); // Fixed: Timer2 Interrupt is turned
    	// off by default now! It is only active
    	// when ACS/IRCOMM are transmitting.
    	TIMSK |= (1 << OCIE2);
    
    	while(true)
    	{
    		ir_command=137; //Left Arm Up
    
    		ir_code_6666(); //ir-signal 6666us
    		for( i=1; i<= 8;i++)
    		{
    			if ((ir_command & 0x80)==0)
    			{
    				Delay_us(833);
    				ir_code_833();
    			}
    			else
    			{
    				Delay_us(3333);
    				ir_code_833();}
    				ir_command=ir_command << 1;
    			}
    	}
    	return(0);
    }

  2. #2
    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

    Zuerst eine Warnung: Die IR-CommLED hängt über R6 (10Ohm) direkt an der Batteriespannung. Wenn Q5 nicht mit einem Trägertakt angesteuert wird kann die IRLED zerstört werden! Zum Testen wäre eine Ausgabe an eine StatusLED sicherer, wenns dann blickt kann man richtig loslegen.

    Auf den ersten Blick scheint mir folgender Fehler vorzuliegen: Der Timer2 mit Prescaler 1 und OCR2=8 blockiert alles weil zwischen den Matches nur 8 Takte (!) Zeit bleiben. Das reicht nicht einmal aus um die ISR auszuführen:

    Code:
    ISR (TIMER2_OVF_vect)
    {
        1880:	1f 92       	push	r1
        1882:	0f 92       	push	r0
        1884:	0f b6       	in	r0, 0x3f	; 63
        1886:	0f 92       	push	r0
        1888:	11 24       	eor	r1, r1
        188a:	8f 93       	push	r24
        188c:	9f 93       	push	r25
    	Zeit++;
        188e:	80 91 0c 01 	lds	r24, 0x010C
        1892:	90 91 0d 01 	lds	r25, 0x010D
        1896:	01 96       	adiw	r24, 0x01	; 1
        1898:	90 93 0d 01 	sts	0x010D, r25
        189c:	80 93 0c 01 	sts	0x010C, r24
        18a0:	9f 91       	pop	r25
        18a2:	8f 91       	pop	r24
        18a4:	0f 90       	pop	r0
        18a6:	0f be       	out	0x3f, r0	; 63
        18a8:	0f 90       	pop	r0
        18aa:	1f 90       	pop	r1
        18ac:	18 95       	reti
    Nur zur Erinnerung: Ein Riskprozessor wie die ATMegas braucht mindestens einen Takt pro Befehl. Auch ohne den Sprung ist deine ISR einfach zu lang.

    Ich habe dein Programm mit der Overflow-ISR für Timer2 übersetzt weil diese ISR von der RP6-Lib nicht verwendet wird (und ich deshalb die Comp-ISR nicht ausblenden muss). So kann man bequem den Timer2 in eigenen Anwendungen verwenden und bei Bedarf initialiert man den Timer einfach wieder mit den Lib-Parametern. Mein Setup für eine 100kHz-Servo-ISR sieht so aus:

    Code:
    	// Initialize Timer2 - 100kHz für Servos mit Overflow-ISR
    	TCCR2 = (0 << WGM21) | (0 << COM20) | (1 << CS20); // Normal Mode, no prescaler
    	TCNT2  = -80; // alle 80 Takte ein Interrupt
    	TIMSK |= (1 << TOIE2); // Timer2 Overflow-Interrupt erlauben
    Weil das Counterregister nach dem Überlauf mit 0 geladen wird muss man in der ISR selbst einen neuen Startwert setzen:
    Code:
    ISR (TIMER2_OVF_vect)
    {
    	TCNT2  = -80; // alle 80 Takte ein Interrupt
    ...
    }
    Nach diesem Prinzip könnest du vermutlich auch deine Zeiten erzeugen. Anstelle der -80 müssen bei dir eben die an deine Zeiten angepassten Werte stehen.

    Hast du Infomationen zum Protokoll des Robosapien?

    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!

  3. #3

    Protokoll Robosapien und noch ein Versuch!

    Vielen Dank Radbruch!

    Du könntest natürlich Recht haben.
    Unten habe ich das Protokoll des Robosapiens aufgeführt.
    Trägerfrequenz ist 39,2kHz.
    Habe inzwischen noch einen erneuten Versuch unternommen und mein Programm ähnlich aufgebaut wie in der lib des RP6 zum senden von RC5-Signalen.

    Timing based on 1/1200 second clock (~.833ms)
    Signal is normally high (idle, no IR).
    Start: signal goes low for 8/1200 sec.
    Data bits: for each of 8 data bits, space encoded signal depending on bit value
    Sends the most significant data bit first
    If the data bit is 0: signal goes high for 1/1200 sec, and low for 1/1200 sec.
    If the data bit is 1: signal goes high for 4/1200 sec, and low for 1/1200 sec.
    BTW: The first bit (msb) is always 1 (valid codes are from $80 to $FF)

    Carrier is 39,2 kHz


    Code:
    #include "RP6RobotBaseLib.h" 	
    
    
    uint16_t Zaehler=0;
    uint8_t i;
    uint8_t ir_command=137;
    uint8_t Aufgabe=0;
    uint8_t Zeichen=0;
    
    ISR (TIMER2_COMP_vect)
    
    {
    if(Aufgabe==0){
    	if(Zeichen==0){
    	Aufgabe=1;
    	Zaehler=0;}
    	if(Zeichen>0 && Zeichen<9){
    	Zaehler=0;
    		if ((ir_command & 0x80)==0){
    		Aufgabe=2;}
    		else{Aufgabe=3;}
    	ir_command=ir_command << 1;
    	Zeichen++;
    	}
    	if(Zeichen==9){
    	PORTD &= ~(1<<PIND7);
    	Zeichen=0;
    	ir_command=137;
    	Aufgabe=0;}
    	
    }
    if(Aufgabe==1){
    	if(Zaehler<520){
    	PORTD ^= (1<<PIND7);			//PORTD ^= (1<<PIND7);
    	Zaehler++;}
    	else{
    	Aufgabe=0;
    	Zeichen=1;}
    }
    if(Aufgabe==2){
    	if(Zaehler<65){
    	PORTD &= ~(1<<PIND7);}			//PORTD &= ~(1<<PIND7);
    	else{
    		if(Zaehler<130){
    		PORTD ^= (1<<PIND7);}		//PORTD ^= (1<<PIND7);
    		else{ Aufgabe=0;}
    	}
    Zaehler++;
    }
    
    if(Aufgabe==3){
    	
    	if(Zaehler<260){
    	PORTD &= ~(1<<PIND7);}				//PORTD &= ~(1<<PIND7);
    	else{
    		if(Zaehler<325){
    		PORTD ^= (1<<PIND7);}		//PORTD ^= (1<<PIND7);
    		else{ Aufgabe=0;}
    	}
    Zaehler++;
    }
    
    
    }
    
    
    
    int main(void)
    {
    	initRobotBase(); 
    	
    	TCCR2 = (1 << WGM21) | (0 << COM20) | (1 << CS20);
    	OCR2  = 0x66; // 0x66 = 78,4kHz @8MHz
    	
    	// Initialize Timer Interrupts:
    	TIMSK = (1 << OCIE0); //| (1 << OCIE2); // Fixed: Timer2 Interrupt is turned 
    	                      // off by default now! It is only active 
    						  // when ACS/IRCOMM are transmitting.
    	TIMSK |= (1 << OCIE2);
    	
    	
    	while(true)
    	{
    	
    	}
    
    	return 0; 
    }

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    24.01.2008
    Ort
    Zürich
    Beiträge
    604
    Hi,

    ich hab zwar keine Ahnung ob das überhaupt noch im Programm steht (*sry grade zu müde um mehr zu lesen *)
    aber ganz oben iss mir dashier aufgefallen:

    Code:
    void Delay_us(uint16_t Verzoegerung) 
    { 
       Zeit=0; 
       while(Zeit<=Verzoegerung); 
    }
    dabei iss aber, egal mit welchem parameter man die Funktion Delay_us aufruft dann sofort ewiger Stillstand

    denn da Verzögerung nicht negativ sein kann (wies mit 0 iss weiss ich garned iss aber egal) MUSS sie immer >= 0 sein

    das bedeutet soviel wie wenn du einfach while(1); hinschreibst


    ich vermute das sollte eigentlich so aussehen:

    Code:
    void Delay_us(uint16_t Verzoegerung) 
    { 
       Zeit=0; 
       while(Zeit<=Verzoegerung)Zeit++; 
    }
    ach ja, dabei sit aber noch zu beachten, dass die funktion nicht soviele us wartet wie verzögerung groß ist, die takte eines µCs sind soweit ich weiss noch kleiner...

    da diese art von delay eh blockierend ist, kann man auch gleich die delay.h oder wie die genau heißt hernehmen...


    LG Pr0gm4n

  5. #5
    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

    Es sollte eine möglichst genaue Verzögerung sein, deshalb wird die Variable "Zeit" in der Interrupt-Service-Routine incrementiert (vergrößert?):

    Code:
    ISR (TIMER2_OVF_vect) 
    { 
       Zeit++; 
    }
    Wenn man das berücksichtigt hat die Zeile in Delay_us() wieder Sinn:

    while(Zeit<=Verzoegerung);

    Allerdings sollte man Zeit als volatile vereinbaren. Soweit ich weiß zwingt das den Kompiler die Variable im Ram zu halten und erst damit wird der wechselseitige Zugriff von ISR und Hauptprogramm auf die Variable möglich. Aber wirklich wissen tu ich nix:

    volatile uint16_t Zeit;

    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!

  6. #6
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    24.01.2008
    Ort
    Zürich
    Beiträge
    604
    Hi,

    also das mit volatile weiss ich ned so genau aber es sollte dann so ablaufen dass man zeit besser als globale variable deklariert (was er oben auch macht) und sie innerhalb der funktion Delay_us() initialisiert mit dem wert 0 (ihn zuweist)

    das passt also doch alles, sry, hab mich vertan hab wie gesagt nich den nerv gehabt so müde nochmal soviel zu lesen jezt nach 3 stunden schlaf oder was des warn iss schon n bissl besser

    das "incrementiert (vergrößert?)" deute ich so dass du nicht sicher bist?

    inkrementieren heisst um eins erhöhen ja.


    LG Pr0gm4n

  7. #7
    Hallo Zusammen,

    werde mal die Varaiable Zeit als volatile deklarieren, und noch nen Versuch machen.

    Vielen Dank erst mal für die Unterstützung! Werde mich melden ob das Ding funzt.

  8. #8
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    24.01.2008
    Ort
    Zürich
    Beiträge
    604
    Hi,

    also ich versteh zwar ned warum du das machen willst, denn mit deiner Lösung mit Zeit als globaler Variable funktioniert das 100%ig

    wenn dann liegt der Fehler wo anders

    LG Pr0gm4n

  9. #9
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    14.01.2008
    Beiträge
    164
    So ist das Timing.
    Funktioniert bei mir tadellos.
    Noch die Einstellungen für einen Atmega32 mit 8mhz bei mir :
    DDRD|=(1<<PD5);
    PORTB=0;
    OCR1A=101;
    TCCR1B=(1<<WGM12)|(1<<CS10);
    TCCR1A=(1<<COM1A1);

    Code:
    void ir_command(uint8_t command)
    {
    	uint8_t mask;
    
    	TCCR1A=(1<<COM1A0);
    	delay_us(6666);
    	TCCR1A=(1<<COM1A1);
    
    	for (mask=0x80; mask>0; mask=mask>>1 )
    	{
    		if ( command & mask )
    			{
    			delay_us(3333);
    			TCCR1A=(1<<COM1A0);
    			delay_us(833);
    			TCCR1A=(1<<COM1A1);
    			}
    			else
    			{
    			delay_us(833);
    			TCCR1A=(1<<COM1A0);
    			delay_us(833);
    			TCCR1A=(1<<COM1A1);
    			}
    	}
    }
    das sind die Befehle:


    Red Commands:
    =============
    (Page P.7)
    81 (129) - Right Arm Up
    84 (132) - Right Arm Down
    85 (133) - Right Arm In
    82 (130) - Right Arm Out
    83 (131) - Tilt Body Right

    89 (137) - Left Arm Up
    8C (140) - Left Arm down
    8D (141) - Left Arm In
    8A (13 - Left Arm Out
    8B (139) - Tilt Body Left

    (Page P.
    80 (12 - Turn Right
    88 (136) - Turn Left
    86 (134) - Walk Forward
    87 (135) - Walk Backward
    8E (142) - Stop

    92 (146) - Right Sensor Program
    94 (14 - Sonic Sensor Program
    93 (147) - Left Sensor Program
    90 (144) - Master Command Program
    91 (145) - Program Play

    Green Commands:
    ===============
    (Page P.9)
    A1 (161) - Right Hand Thump
    A4 (164) - Right Hand Pickup
    A5 (165) - Lean Backward
    A2 (162) - Right Hand Throw
    A3 (163) - Sleep

    A9 (169) - Left Hand Thump
    Ac (172) - Left Hand Pickup
    AD (173) - Lean Forward
    AA (170) - Left Hand Throw
    AB (171) - Listen

    (Page P.10)
    A0 (160) - Right Turn Step
    A8 (16 - Left Turn Step
    A6 (166) - Forward Step
    A7 (167) - Backward Step
    AE (174) - Reset

    B2 (17 - Right Sensor Program Execute
    B4 (180) - Sonic Sensor Program Execute
    B3 (179) - Left Sensor Program Execute
    B0 (176) - Master Command Program Execute
    B1 (177) - Wake Up

    Orange Commands:
    ================
    (Page P.11)
    C1 (193) - Right Hand Sweep
    C4 (196) - High 5
    C5 (197) - Right Hand Strike 1
    C2 (194) - Burp
    C3 (195) - Right Hand Strike 2

    C9 (201) - Left Hand Sweep
    CC (204) - Talk Back
    CD (205) - Left Hand Strike 1
    CA (202) - Whistle
    CB (203) - Left Hand Strike 2

    (Page P.12)
    C0 (192) - Right Hand Strike 3
    C8 (200) - Left Hand Strike 3
    C6 (19 - Bulldozer
    C7 (199) - Opps!
    CE (206) - Roar

    D2 (210) - Demo 1
    D4 (212) - Dance
    D3 (211) - Demo 2
    D0 (20 - All Demo
    D1 (209) - Power Off

Berechtigungen

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

12V Akku bauen