Hallo
Bild hier
Aus Zeitgründen habe ich es leider nicht geschafft eine vernünftige Software zu erstellen. Nach Druck auf den linken Bumper wird das hellste Teelicht im Blickbereich angesteuert und beschossen, ein Druck auf den rechten Bumper wiederholt den Schuss. Mein Konzept funktioniert nur im Halbdunkel, aber bei strahlender Sonne braucht man eh keine Teelichter;)
Sensor ist die Projekt-Cam, Ausbläser ist ein Luftballon auf einem PET-Flaschenrest der mit einer Wäscheklammer und zwei Servos gespannt und abgeschossen wird:
Bild hier Bild hier Bild hier
http://www.youtube.com/watch?v=qgmKWWT4lps
http://www.youtube.com/watch?v=l79jabBqgo0
Helferleinkatze ist natürlich auch mit dabei ;)
GrußCode:// Teelicht löschen mit RP6 12.4.2010 mic #include "RP6RobotBaseLib.h" #define auf 30 #define zu 12 #define aus 0 #define spannen 14 #define holen 38 uint8_t klammer=0, ziehen=0; // Servos aus void init(void); void setMotorPWM(uint8_t power_links, uint8_t power_rechts); uint16_t richtung(void); void schuss(void); int main(void) { init(); while(1) { writeInteger(richtung(), 10); writeString_P("\n"); setLEDs(63); // ready do { schuss(); while(!(getBumperRight() || getBumperLeft())); // weiteren Schuss auslösen } while(!getBumperLeft()); // nächste Kerze } return(0); } ISR (TIMER1_OVF_vect) { static uint16_t servocount=1; if(servocount > klammer) PORTC &= ~SCL; else PORTC |= SCL; // PC0 XBUS 10 if(servocount > ziehen) PORTC &= ~SDA; else PORTC |= SDA; // PC1 XBUS 12 if(servocount < 400) servocount++; else servocount=1; } void init(void) { initRobotBase(); DDRC |= (SCL | SDA); // Servopins auf Ausgang setzen TIMSK |= (1 << TOIE1); // Die Timer1 Overflow-ISR zur Servoansteuerung extIntOFF(); // schaltet den E_INT1-Port auf Eingang für den ADC // ADC interne Referenz 2,56V, Ergebniss linksbündig, Kanal ADC4 (E_INT1) ADMUX = (1<<REFS1) | (1<<REFS0) | (1<<ADLAR) | 4; // setzte free running triggern SFIOR = (0<<ADTS2) | (0<<ADTS1) | (0<<ADTS0); // kein interupt, Wandler einschalten, prescaller /2 ADCSRA = (0<<ADIE) | (1<<ADEN) | (0<<ADPS2) | (0<<ADPS1) | (1<<ADPS0); // Autotriggern bedeutet jetzt free running aktivieren, altes Flag löschen ADCSRA |= (1<<ADATE) | (1<<ADIF); // Initialisierung starten ADCSRA |= (1<<ADSC); // und noch die wohl eher unnötige Initiallesung while (!(ADCSRA & (1<<ADIF))); ADCSRA |= (1<<ADIF); //powerON(); } // Achtung! Die PWM-Werte werden hier OHNE Rampe verändert! void setMotorPWM(uint8_t power_links, uint8_t power_rechts) { extern uint8_t mleft_ptmp, mright_ptmp; if(power_links > 210) power_links = 210; if(power_rechts > 210) power_rechts = 210; mleft_power=mleft_ptmp=power_links; mright_power=mright_ptmp=power_rechts; OCR1BL = power_links; OCR1AL = power_rechts; if(power_links || power_rechts) TCCR1A = (1 << WGM11) | (1 << COM1A1) | (1 << COM1B1); else TCCR1A = 0; } uint16_t richtung(void) { uint8_t bildspeicher[100], *bildzeiger; // 100 Byte Bildspeicher sollten reichen uint8_t zeile, sync, c; // und dürfen NICHT global sein! uint16_t spalte_max, spaltenwerte[12]; writeString_P("-------------------------\n"); do { spalte_max=0; for(c=0; c<12; c++) { setLEDs(c); // working bildzeiger=&bildspeicher[0]; // Zeiger auf Start des Bildspeicherbereich zeile=c*20+35; // aktuelle Zeile (35 Zeilen sind der Schrott beim Bildstart) cli(); do // Warten auf langen Syncbereich = Bildstart { sync=0; while (ADCH > 20); // warten solange Bilddaten erkannt werden while (ADCH < 30) sync++; // Länge des Sync-Signal zählen }while (sync < 40); // größer 40 bedeutet Bildstart while(zeile--) { while (ADCH > 20); // Bilddaten while (ADCH < 30); // Sync } do *bildzeiger=ADCH; while(*bildzeiger++ > 20); // schnelle Zeile einlesen sei(); spaltenwerte[c]=0; for(zeile=0; zeile<48; zeile++) // 64 Pixel zusammenzählen { spaltenwerte[c]+=bildspeicher[zeile]; setLEDs(zeile); } if(spaltenwerte[c] > spalte_max) spalte_max=spaltenwerte[c]; } for(c=0; c<12; c++) // größten Spaltenwert suchen { if(spaltenwerte[c] == spalte_max) spalte_max=c; } writeString_P("hellste Spalte: "); writeInteger(spalte_max, 10); writeString_P(" Spaltenwert: "); writeInteger(spaltenwerte[spalte_max], 10); writeString_P("\n"); //if(spaltenwerte[spalte_max] > 3000) { if(spalte_max > 6) {setMotorDir(FWD,FWD); setMotorPWM(100,0);} else if(spalte_max <6) {setMotorDir(BWD,FWD); setMotorPWM(100,0);} //mSleep(200); //setMotorPWM(0,0); //mSleep(500); else setMotorPWM(0,0); } }while(spalte_max !=6); return(spaltenwerte[spalte_max]); // Summenhelligkeit der Spalte } void schuss(void) { klammer=auf; mSleep(500); ziehen=holen; mSleep(500); klammer=zu; mSleep(300); ziehen=spannen; mSleep(500); klammer=auf; mSleep(200); klammer=zu; mSleep(200); klammer=0; }
mic
[Edit]
Ich hab's zerlegt, weil der Ballon kaputt ging. Der kleine Knubbel war im Ballon als Greifpunkt für die Klammer. Das Sieb stammt aus einem Kaffeepad.







Zitieren

Lesezeichen