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)
Hallo,
ich habe weiterhin viel versucht, sogar nen ATmega32 eingebaut, aber irgendwie klappt das mit dem ACS nicht. Was wäre eine günstige Alternative.
Mich würde auch interessieren ob man unbedingt das mit 36kHz modulierte Signal braucht oder könnte man auch die IR-LEDs auf Dauerlicht setzen und dann mit IR-Phototransistoren eine Reflexion detektieren? Oder hat das nicht soviel Reichweite?
Es tut mir leid, das ich so einfache Fragen stelle, aber ich hab das Problem, dass ich derzeit keinen IR-Phototransistor habe und das somit nicht testen kann und bevor ich dann sinnlos Geld ausgebe...
VIelen Dank für eure Hilfe
Der Vorteil der Kombination 36kHz-modulierte-irLED und dazu passendes Empfängermodul/-IC à la SFH5110 ist einmal die Anpassung an das Umgebungslicht und zum andern die Sicherheit gegen Fremdlicht wie Leuchtstofflampen, Gewitterblitze etc. Anm: die 36 kHz sind auf das Empfängermodul abgestimmt, es gibt Systeme mit anderen Modulationsfrequenzen: 38 kHz oder 40 ..., das funktioniert ebenso.... ob man ... 36kHz modulierte Signal braucht oder könnte man auch die IR-LEDs auf Dauerlicht setzen ...
Deshalb wurde dieses System auf der Grundlage des asuro vor Jahren von waste (klick) aus der Taufe gehoben. Damit hatte ich ausführlich weiter experimentiert (klick) weil mich diese Technik beeindruckte. Dabei hatte ich diese Messung etwas weiter ausgebaut, um sowohl Hindernisse als auch Abgründe zu detektieren (wieder ...). Das läuft prächtig. Ich hatte das in verschieden meiner Roboter eingebaut, zum Beispiel Dottie - die laufende Coladose - oder in WALL R, wo das gleiche System auch eine gestufte Reaktion auf verschiedene Abstände ermöglichte.
Dieses System läuft aber weder in wastes Urform noch in meiner Variante über ADC. Sowohl Beschreibungen als auch Code ist in den verlinkten Threads mehrfach enthalten. Vielleicht ist diese Lösung etwas für Dich? Jedenfalls viel Erfolg (und GEduld) mit Deinem Projekt.
Ciao sagt der JoeamBerg
Hallo Oberallgeier,
Danke für deine Anwort. Ich hab leider zur Zeit wenig Zeit im Internet, deswegen konnte ich noch nicht alle Links verfolgen. Aber ich habe weiterhin experimentiert. Bei dem TSOP 31236 ist es doch so, dass sobald ein 36kHz Signal einwirkt, dass sich der Ausgang auf Low zieht, richtig? Jetzt hab ich nen Programm geschrieben, wo die IR-LEDs dauernd mit 36kHz blinken (mit Multimeter nachgemessen: 36,1 kHz). Ich habe dann den IR-Empfänger neben dir IR-LED gebaut und mit dem Messgerät die Spannung auf Ausgang vom TSOP gemessen (ca 5V). Jetzt habe ich in verschiedenen Entfernung meine Hand davor gehalten, aber der Ausgang bleibt unverändert. Dann habe ich einen kleinen Spiegel genommen und ca. 1cm vor dem Empfänger schaltet er den Ausgang auf Low. Warum habe ich keine Reichweite?
Dann hab ich ein weiteres Programm geschrieben wo, die LEDs nur 200ms lang blinken und 800 ms aus sind. Mit einmal habe ich schon mehr Reichweite (etwa 10 cm). Ist das so normal?
Danke, Geduld ist hier wirklich gefragt. Ich finde es so schade, dass der RP6 code nicht einfach funktioniert. Naja, da ich momentan auf Montage bin, kann ich leider nicht überprüfen, ob die LEDs bei dem RP6 code blinken. Zuhause habe ich ein Oszi, da kann ich das detailiert ausmessen.
Ich werde aber deine Links noch weiter durcharbeiten.
Vielen Dank für deine Hilfe und ich freue mich über weitere ;D
MfG
RP6fahrer
Hi RP6fahrer,
Das war -denke ich- klar, weil beim RP6 ins ACS auch noch IRCOMM verschachtelt ist. Das war nicht 1:1 übertragbar.Ich finde es so schade, dass der RP6 code nicht einfach funktioniert.
Andererseits:
Man kann es gut schaffen, ein ACS hinten technisch genauso umzusetzen wie vorn und das auch mit dem µC des RP6 auszuwerten. Ein eigener µC dafür ist fast schon Overkill.
Die Auswertung kann so aussehen:
Du schreibst eine Funktion, die die LEDs mit 36 kHz blinken läßt. Zusätzlich kannst du die beiden LEDs einzeln ein-/ausschalten und mit 2 Portpins auch die Intensität (durch die Vorwiderstände) verändern.
Ob ein 36 kHz IR-Signal empfangen wurde, wertest du mit dem TSOP aus.
Das alles ist für dich sicher nicht neu. Aber: Das Programm dafür dürfte auch relativ einfach umzusetzen sein. Möglicherweise müßte man dazu aber die BaseLib modifizieren.
Wenn du all das nicht machen willst, könnte man hinten auch 2 SHARP-IR-Distanzsensoren und 2 Bumper dranbauen, wie fabqu das beim MultiIO Projekt gemacht hat: Klick!
Gruß
Dirk
Lesezeichen