Geändert von PICture (05.06.2012 um 17:51 Uhr)
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!
Hallo
Ein Blick in den Schaltplan (Seite 2) der Base offenbart es:
Bild hier
Die ACS-LEDs können getrennt angesteuert werden:
(Aus RP6RobotBaseLib.c)Code:/** * Disables the ACS task. * ACS and IRCOMM Transmissions/Receptions will not work anymore. */ void disableACS(void) { acs_state = ACS_STATE_IDLE; TIMSK &= ~(1 << OCIE2); IRCOMM_OFF(); PORTB |= ACS_L; PORTC |= ACS_R; obstacle_right = false; obstacle_left = false; } /** * Enables the ACS task. */ void enableACS(void) { TIMSK &= ~(1 << OCIE2); IRCOMM_OFF(); PORTB |= ACS_L; PORTC |= ACS_R; obstacle_right = false; obstacle_left = false; acs_state = ACS_STATE_IRCOMM_DELAY; } /** * Turn ACS Power off. * * Example: * * setACSPwrOff(); * */ void setACSPwrOff(void) { DDRD &= ~ACS_PWR; PORTD &= ~ACS_PWR; DDRB &= ~ACS_PWRH; PORTB &= ~ACS_PWRH; PORTB &= ~ACS_L; PORTC &= ~ACS_R; } /** * Set ACS Power low. * * Example: * * setACSPwrLow(); * */ void setACSPwrLow(void) { DDRD |= ACS_PWR; PORTD |= ACS_PWR; DDRB &= ~ACS_PWRH; PORTB &= ~ACS_PWRH; } /** * Set ACS Power medium. * * Example: * * setACSPwrMed(); * */ void setACSPwrMed(void) { DDRD &= ~ACS_PWR; PORTD &= ~ACS_PWR; DDRB |= ACS_PWRH; PORTB |= ACS_PWRH; } /** * Set ACS Power high. * * Example: * * setACSPwrHigh(); * */ void setACSPwrHigh(void) { DDRD |= ACS_PWR; PORTD |= ACS_PWR; DDRB |= ACS_PWRH; PORTB |= ACS_PWRH; }
Mit ACS_PWR und ACS_PWRH kann man R8 und R9 in unterschiedlichen Kombinationen ansteuern und so den Strom durch die ACS-LEDs und die Leuchtstärke beeinflußen.
Gruß
mic
[Edit]
Ach ja, ganz vergessen, die Kathoden liegen an ACS_L/ACS_R. Die Leds leuchten, wenn sie auf low liegen und über R8/9 ein high ausgegeben wird:
Bild hier
[Noch ein Edit]
Bei der Suche nach dem Urheber der 36kHz-Trägerfrequenz für das ACS habe ich die getrennte Ansteuerung der ACS-LEDs gefunden:
(Ebenfalls aus RP6RobotBaseLib.c)Code:// ------------------------------- /** * Timer 2 Compare ISR * ACS & IRCOMM * * WARNING: DO NOT CHANGE THIS! * NEVER try to control the IRCOMM by your own routines if you do not * know what you are doing! * */ ISR (TIMER2_COMP_vect) { static uint8_t ircomm_pulse; if(acs_state < 2) { // If ACS is not active, perform IRCOMM transmissions if(ircomm_pulse) { // Do we have IR pulses to send? if(ircomm_pulse < 60) { // Bi-Phase encoding... if(ircomm_data & 0x4000) // check current bit PORTD ^= (1<<PIND7); // Toggle IRCOMM port else PORTD &= ~(1<<PIND7); // deactivate IRCOMM port } else if(ircomm_data & 0x4000) // The same as above, but the other way round: PORTD &= ~(1<<PIND7); // deactivate IRCOMM port else PORTD ^= (1<<PIND7); // Toggle IRCOMM port ircomm_pulse--; } else if(ircomm_send) { // Do we still have data? PORTD &= ~(1<<PIND7); ircomm_data <<= 1; // Next Bit! ircomm_pulse = 120; ircomm_send--; } else PORTD &= ~(1<<PIND7); // no more pulses - IR LEDs off! } else if(acs_pulse) { // Send ACS IR pulses? if(sysStatACS.channel == ACS_CHANNEL_LEFT) // which channel? PORTB ^= ACS_L; else PORTC ^= ACS_R; acs_pulse--; } else { // no more pulses - IR LEDs off! PORTB |= ACS_L; PORTC |= ACS_R; } }
Geändert von radbruch (05.06.2012 um 18:28 Uhr)
Bild hier
Atmel’s products are not intended, authorized, or warranted for use
as components in applications intended to support or sustain life!
Hey Leute,
ich weiß, das dieses Thema schon vor Jahren abgeschlossen wurde, aber ich habe zu meinem Problem keinen anderen Thread gefunden. Da ich momentan Montagemäßig unterwegs bin und dort immer mal Freizeit hab, hab ich gedacht, ich kümmer mich mal wieder um meinen RP6. Ich habe ihm eine Bumperplatine hinten angebaut mit zwei Bumpern, deren Anschluss und Auswertung genau wie die der vorderen Bumper erfolgt. Sie heißen nur Bumper_backleft und Bumper_backright. Ich habe die auch I2C tauglich gemacht und alles funktioniert wunderbar. Jetzt habe ich mir gedacht, ich baue das ACS auch nochmal für hinten nach. Da ich noch nen ATmega 16 übrig hab, hab ich mir gedacht, den nehme ich für das ACS nach hinten. Ich habe dann die Schaltung auf ein Steckboard 1:1 nachgebaut, wie ich sie in der Anleitung des Roboters gefunden hab. Die gleichen Teile, IR-LEDs usw, außer den IR Empfänger. Das ist bei mir ein TSOP31236. Der ist aber gleich wie der von Arexx verwendete (Datenblattvergleich). Den Programmcode nur für ACS, Timer2 steuerung INT2 hab ich alles von der RP6 Library übernommen. Compilieren ging einwandfrei und das laden via ISP in den Controller ging auch. Aber das Programm macht nichts. Es will einfach nicht funktionieren.
Das ist mein ganzes Programm:
Das einzige was passiert Die LEDs gehen an, nach 200ms geht nur LED an IOB5 aus. Mehr macht er nicht. Wie gesagt, der Programmcode ist komplett aus der RP6 Library übernommen.Code:#include "ATmega16.h" /**************************************************************/ void acsStateChanged(void) { if(obstacle_left) PORTB ^= IOB0; } /***************************************************************/ int main(void) //Hier beginnt das Hauptprogramm { initATmega(); PORTB |= IOB0 | IOB4 | IOB5; //Hier hängen StatusLEDs dran delay_ms(200); PORTB &= IOB0 & IOB5; ACS_setStateChangedHandler(acsStateChanged); enableACS(); setACSPwrHigh(); while (1) { task_ACS(); } return 0; }
Hier mal ein Auszug für initATmega():
Das ist eigentlich genauso aufgebaut wie initRobotBase();Code:void initATmega(void) { portInit(); // Setup port directions and initial values. // THIS IS THE MOST IMPORTANT STEP! //Initialisierung ADC ADCSRA = (0<<ADEN) | (0<<ADIE) | (1<<ADPS2) | (1<<ADPS1)| (1<<ADIF); ADMUX |= (1<<REFS0); //Interne Referenzspannung nehmen //SFIOR = 0; GICR = (1 << INT2); MCUCSR = (0 << ISC2); // Initialize Timer 0 - 100µs cycle for Delays/Stopwatches, etc.: TCCR0 = (0 << WGM00) | (1 << WGM01) | (0 << COM00) | (0 << COM01) | (0 << CS02) | (1 << CS01) | (0 << CS00); OCR0 = 99; // Initialize Timer2 - ACS: TCCR2 = (1 << WGM21) | (0 << COM20) | (1 << CS20); OCR2 = 0x6E; // 0x6E = 72kHz @8MHz // Initialize Timer Interrupts: TIMSK = (1 << OCIE0);// | (1 << OCIE2); //Der Timer Interrupt wird initialisiert // Initialize ACS: sysStatACS.channel = ACS_CHANNEL_RIGHT; acs_state = ACS_STATE_IRCOMM_DELAY; sei(); // Enable Global Interrupts }
Ich hoffe ihr könnt mir helfen. Ich habe mir gedacht, wenn ich das 1:1 nachbaue, dann müsste es Fehlerfrei funktionieren. Könnt ihr mir nen Tipp geben, wie ich herausfinden kann, ob die LEDs mit 36KHz blinken. Wo wird denn die 36KHz Frequenz überhaupt eingestellt? Mit OCR2 = 0x6E ?
Wenn ich statt der IR-LEDs eine superhelle LED ranhänge, die leuchtet nicht. Möglicherweise ist das schon der Grund. Ich hoffe ihr könnt mir nen guten Tip geben.
VIelen Dank schonmal für eure Hilfe
MfG
RP6fahrer
PS:
Achja, mit Digitalkamera schauen hab ich auch versucht, aber man sieht weder beim RP6 noch hier die leuchtenden LEDs..
Da wird man sicher den RP6-Code nicht unverändert übernehmen können.
Du hast ja einen ATmega 16 und nicht den 32. Da dürfte bei der Initialisierung nicht alles identisch sein. Ich habe das jetzt aber nicht nachgeschaut.
Gruß
Dirk
Hi,
danke erstmal für deinen ersten Gedanken... Also, ein Problem hat sich schon gelöst. Ich hatte nen Zahlendreher drin und hab das falsche Programm geladen. Deswegen ging das mit den 36 KHz der IR-LEDs nicht. Gut Problem behoben. Ich habe die LED an IOB5 so programmiert, dass sie ihren Zustand jedes mal wechselt, sobald ein Interrupt an INT2 (ACS) eingeht. Diese blinkt jetzt im Dauerfeuer. ziehe ich beide IR-LEDs raus, dann hört das blinken auf. Das Problem ist nur, dass ich die Signal (obstacle_left und obstacle_right) nicht auswerten kann.Ich werde aber auf jeden Fall nochmal das Datenblatt zur Initialisierung des Timer2 und INT2 wälzen. Ich hoffe, ich finde was.
Ich freue mich über weitere Tipps und gedanken
Schönen Sonntag noch
PS: Könnt ihr mir nen Denkansatz geben für ein eigenes ACS Programm. Die RC5 Code Auswertung brauche ich ja nicht. Mir reicht es, wenn der Controller Links, rechts, mitte auswerten kann.
Ich hab aus dem RP6 code jetzt alles rausgenommen, was mit IRCOMM und RC5 zu tun hat.
Das Problem, was ich jetzt aber nach wie vor hab, ich kann obstacle_left und obstacle_right nicht auswerten. Meine Status-Leds hab ich soweit programmiert, dass mir eine anzeigt, wie der Interrupt Eingang arbeitet. Diese leuchtet etwa mit halber Helligkeit, was ja bedeutet, dass dort ein wechselndes Signal anliegt. Ziehe ich nun eine IR-LED ab, dann blinkt sie ganz schnell. Ziehe ich beide IR-LEDs ab, dann hört das blinken auf. Das heißt ja dann scheinbar, dass der TSOP ein Signal von den Dioden bekommt. Und scheinbar bekommt er es ja auch immer wechselseitig. Aber ich kann mir nicht erklären, warum das obstacle nicht funktioniert. Kann es wirklich daran liegen, dass ich einen Atmega 16 statt Atmega 32 verwende. Ich habe im Datenblatt zum Timer2 und INT2 nachgeschaut und das ist soweit identisch. Ich hoffe wirklich, dass ihr noch nen guten Tipp für mich habt.
Geändert von RP6fahrer (24.07.2013 um 09:37 Uhr)
Lesezeichen