Hallo Leute, bin neu hier, nimmt es mir nicht übel falsch im falschen Thread poste, aber habe gerade ein Projekt am laufen und komme nicht weiter. Und zwar sollen ich über das MiniMexle mit dem ATMega88 einen Servo über PWM ansteuern (bereits hier im Forum gefunden) und während dessen, einen Sharp IR Sender/Empfänger die Umgebung abscannen lassen und bei einem Hindernis, mit einem Abstand <10cm sollen die LED aufblinken. Irgendwie habe ich einen Wurm im meinem Quellcode und ich wäre dankbar, wenn Ihr mit dabei behilflich sein könntet. Vielen Dank im Vorraus Orhan /*====================================================================== ======= Projekt: Abstandsmessung mit Sharp-IR-Sensor-GP2Y0A21YK0F inkl. Umgebungsscan anhand eines schwenkenden Servomotors ======================================================================== =====*/ // Deklarationen //=================================== // Festlegung der Quarzfrequenz #ifndef F_CPU // optional definieren #define F_CPU 18432000UL // MiniMEXLE mit 18,432 MHz Quarz #endif //=================================== // Include von Header-Dateien #include <avr/io.h> // I/O Konfiguration (intern weitere Dateien) #include <util/delay.h> // Definition von Delays (Wartezeiten) #include <stdio.h> #include <stdlib.h> #include "lcd_lib_de.h" // Funktionsbibliothek zum LCD-Display //=================================== //Servo Einstellungen #define SERVOMAX 5100 //2,4ms => +100% => (F_CPU 8 1000 * 2,4) -1 #define SERVOMIN 1150 //0,5ms => -100% => (F_CPU 8 1000 * 0,5) -1 #define SERVOCENTER 3340 //1,45ms => 0% => (F_CPU 8 1000 * 1,45) -1 #define SERVOFRAME 46079 //20ms => (F_CPU 8 1000 * 20) -1 //=================================== // Konstanten #define ON_TIME 10 // "Ein-Zeit" in Inkrementen zu 100 ms #define OFF_TIME 10 // "Aus-Zeit" in Inkrementen zu 100 ms float abstand_digital = 0; float abstand_analog = 0; char Ausgabe[5]; #define VORTEILER_WERT 90 // Faktor Vorteiler = 90 #define HUNDERTSTEL_WERT 10 // Faktor Hunderstel = 10 unsigned char vorteiler = VORTEILER_WERT; // Zaehlvariable des Vorteilers unsigned char hundertstel = HUNDERTSTEL_WERT; // Zaehlvariable Hunderstel volatile bool timertick=0; // Bit-Botschaft alle 0,111ms (bei Timer-Interrupt) volatile bool takt10ms=0; // Bit-Botschaft alle 10ms volatile bool takt100ms=0; // Bit-Botschaft alle 100ms //=================================== // Konstanten: Steigung und Y-Wert #define M1 -0.0625 // n=1: 5 bis 7,5cm #define C1 960.3125 #define M2 -0.0138 // n=2: 7,5 bis 10cm #define C2 920.1035 #define M3 -0.0208 // n=3: 10 bis 12,5cm #define C3 740.208 #define M4 -0.0294 // n=4: 12,5 bis 15cm #define C4 620.3675 #define M5 -0.04545 // n=5: 15 bis 20cm #define C5 535.68175 #define M6 -0.0714 // n=6: 20 bis 25cm #define C6 426.428 #define M7 -0.1 // n=7: 25 bis 30cm #define C7 357.5 #define M8 -0.014286 // n=8: 30 bis 35cm #define C8 309.2858 #define M9 -0.2 // n=9: 35 bis 40cm #define C9 277 #define M10 -0.2857 // n=10: 40 bis 50cm #define C10 256.428 #define M11 -0.5 // n=11: 50 bis 60cm #define C11 235 #define M12 -0.6667 // n=12: 60 bis 70cm #define C12 230.002 #define M13 -1.0 // n=13: 70 bis 80cm #define C13 245 unsigned int Marray [14]={100,150,200,300,400,500,600,700,800}; // Zuweisung der Y-Werte #define Y10 440 // Abstand = 10cm #define Y15 310 // Abstand = 15cm #define Y20 245 // Abstand = 20cm #define Y30 175 // Abstand = 30cm #define Y40 135 // Abstand = 40cm #define Y50 110 // Abstand = 50cm #define Y60 95 // Abstand = 60cm #define Y70 80 // Abstand = 70cm #define Y80 75 // Abstand = 80cm //=================================== // Makros #define SET_BIT(PORT, BIT) ((PORT) |= (1<<BIT)) // Einzelbit auf Port SET #define CLR_BIT(PORT, BIT) ((PORT) &= ~(1<<BIT)) // Einzelbit auf Port RESET bool LED1 = 0; bool LED2 = 0; bool blink=0; //=================================== // Funktionsprototypen void initDisplay(); // Initialisierung Display und Startanzeige void adc_init(); // Initialisierung A-D-Wandler aufrufen void adc_convert(); // Initialisierung Abfrage void calc_abstand(); // Initialisierung Berechnung des Abstandes void ausgabe_abstand(); // Initialisierung der Displayanzeige void blinken_led(); // Initialisierung LED blinken void Init_Timer0(); // Initialisierung Timer0 //=================================== // Funktionsprototypen volatile int adc_conversion; volatile int calc_tick; volatile int timer_count=0; volatile int fuenfhundertms_tick=0; float y=0; uint8_t disp_temp1 = 0; uint8_t disp_temp2 = 0; uint8_t disp_temp3 = 0; uint8_t disp_temp4 = 0; unsigned int disp_temp = 0; int temp; unsigned int M; //=================================== // Hauptprogramm int main() // Start des Hauptprogramms { lcd_init(); initDisplay(); Init_Timer0(); adc_init(); DDRC&=~(1<<DDC5); PORTC&=~(1<<PINC5); DDRD|=(1<<PIND1)|(1<<PIND0); TCCR2A = 0; // Timer 2 auf "Normal Mode" schalten TCCR2B |= (1<<CS21); // mit Prescaler /8 betreiben TIMSK2 |= (1<<TOIE2); // Overflow-Interrupt aktivieren sei(); DIDR0 |= (1 << ADC5D); // Digitalen Eingang abschalten while(1) { if(takt100ms) { takt100ms=0; adc_convert(); calc_abstand(); ausgabe_abstand(); // ausgabe(); blinken_led(); } } } // Ende des Hauptprogramms void init(void) { DDRB |= (1<<PB1); //OCR1x Ports auf Ausgang //Timer0, Mode 14 Fast-PWM, prescaler 8 ICR1=SERVOFRAME; //Impulswiederholzeit 20ms OCR1A=SERVOCENTER; //Servo Mittelstellung TCCR1A |= (1<<COM1A1) | (1<<COM1B1) |(1<<WGM11); TCCR1B |= (1<<WGM13) | (1<<WGM12) | (1<<CS11); } int main_servo(void) { init(); _delay_ms(1000); while(1) { //Servos auf MIN OCR1A = SERVOMIN; _delay_ms(1000); //Servos auf CENTER OCR1A = SERVOCENTER; _delay_ms(1000); //Servos auf MAX OCR1A = SERVOMAX; _delay_ms(1000); while(1) { //Servos auf MIN OCR1A = SERVOMIN; _delay_ms(1000); //Servos auf MAX OCR1A = SERVOMAX; _delay_ms(1000); } } } // Funktionen ================================================================= //=================================== // Initialisierung A-D-Wandler void adc_init (void) { ADCSRA|=((1<<ADEN)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADPS2)); // Vorteiler 128 ADMUX|=((1<<REFS0)|(1<<REFS1)| (5<<MUX0)); // 1,1V als Referenzspannung } //=================================== // A-D-Wandlung ( 100ms ) void adc_convert (void) { // if(adc_conversion) // { adc_conversion = 0; unsigned int convert = 0; // ADCSRA |=(1<<ADEN); // A-D-Wandler einschalten ADCSRA |=(1<<ADSC); // Umwandlung beginnen while (ADCSRA & (1<<ADSC)); // Warten bis Wandlung beendet { } // convert = ADCL; // Lower Byte auslesen // convert += (ADCH<<8); // Higher Byte auslesen convert=ADC; temp=convert; // ADCSRA &= ~(1<<ADEN); // A-D-Wandler ausschalten abstand_digital = convert; // } } //=================================== // Berechnung des Abstandswertes alle 100ms void calc_abstand (void) { if(calc_tick) { calc_tick = 0; y = (abstand_digital*1100)/1024; // y-Wert bestimmen lcd_gotoxy(1,8); // Ausgabe des aktuell berechneten Wertes //lcd_putstr("M1"); if ((y<=Y10)&&(y>Y15)) //Abstand zwischen 10 und 15cm { // lcd_putstr("M1 "); M=1; abstand_analog = (y-C1)/(M1); //Geradengleichung } if ((y<=Y15)&&(y>Y20)) //Abstand zwischen 15 und 20cm { //lcd_putstr("M2 "); M=2; abstand_analog = (y-C2)/(M2); } if ((y<=Y20)&&(y>Y30)) //Abstand zwischen 20 und 30cm { // lcd_putstr("M3 "); M=3; abstand_analog = (y-C3)/(M3); } if ((y<=Y30)&&(y>Y40)) //Abstand zwischen 30 und 40cm { //lcd_putstr("M4 "); M=4; abstand_analog = (y-C4)/(M4); } if ((y<=Y40)&&(y>Y50)) //Abstand zwischen 40 und 50cm { //lcd_putstr("M5 "); M=5; abstand_analog = (y-C5)/(M5); } if ((y<=Y50)&&(y>Y60)) //Abstand zwischen 50 und 60cm { //lcd_putstr("M6 "); M=6; abstand_analog = (y-C6)/(M6); } if ((y<=Y60)&&(y>Y70)) //Abstand zwischen 60 und 70cm { //lcd_putstr("M7 "); M=7; abstand_analog = (y-C7)/(M7); } if ((y<=Y70)&&(y>Y80)) //Abstand zwischen 70 und 80cm { //lcd_putstr("M8 "); M=8; abstand_analog = (y-C8)/(M8); } if (M<1) //if (y=10) { blink=1; } else { blink=0; } disp_temp = abstand_analog; disp_temp1 = disp_temp / 1000; //Zehnerstelle disp_temp2 = (disp_temp % 1000) / 100; //Einerstelle disp_temp3 = (disp_temp % 100) / 10; //Zehntelstelle disp_temp4 = (disp_temp % 10) / 1; //Hundertstelstelle } } //=================================== // Initialisierung Display-Anzeige void initDisplay() // Start der Funktion { lcd_init(); // Initialisierungsroutine aus der lcd_lib lcd_gotoxy(0,0); // Cursor auf 1. Zeile, 1. Zeichen lcd_putstr(" Abstandsmessung"); // Ausgabe Festtext: 16 Zeichen // lcd_gotoxy(1,13); // Cursor auf 2. Zeile, 1. Zeichen // lcd_putstr("cm "); // Ausgabe Festtext: 16 Zeichen } // Ende der Funktion //=================================== // Ausgabe Abstand void ausgabe_abstand() { lcd_gotoxy(1,7); // Cursor auf 2. Zeile, 1. Zeichen lcd_putstr("s="); // s= Abstand unsigned int Mtemp=Marray[M]; lcd_putc(48 + (Mtemp/100)%10); // Ausgabe Festtext: 16 Zeichen lcd_putc(48 + (Mtemp/10)%10); // Ausgabe Festtext: 16 Zeichen lcd_putstr(","); lcd_putc(48 + Mtemp%10); lcd_putstr("cm"); } // Ende der Funktion //=================================== //LED1 + LED2 blinken void blinken_led() { if (blink==1) //if (y=10cm) { PORTD^=((1<<PIND1)|(1<<PIND0)); } if (blink==0) { PORTD&=~((1<<PIND0)|(1<<PIND1)); } } // Ende des Programms //=================================== // Timer 1 - verschiedene Taktzeiten /* Takt1 - 100ms - Teiler 7 (~7,25) Takt2 - 250ms - Teiler 18 (~18,12) Takt3 - 500ms - Teiler 36 (~36,23) berechnet durch t/0.0138=Teiler die nicht benötigten Taktzeiten sollen als Text hinterlegt werden */ void Init_Timer0(void) // Initialisierung Timer 0 { TCCR0A |= (1<<WGM01); // Clear Timer on Compare (CTC) TCCR0B |= ((1<<CS02)|(1<<CS00)); // Prescaler auf Teilung durch 1024 setzen OCR0A = 249; // Output Compare Register A belegen TIMSK0 |= (1<<OCIE0A); // Interrupt Timer/C0 Output Compare Match A sei(); } //=================================== // Interrupt-Routine ISR (TIMER0_COMPA_vect) // Takteinstellung für A-D-Wandlung /* // Takt1 - 100ms { timer_count++; if (timer_count == 7) { timer_count = 0; hundertms_tick = 1; adc_conversion = 1; calc_tick = 1; } } */ /* // Takt2 - 250ms { timer_count ++; if (timer_count == 18) { timer_count = 0; zweifuenfzigms_tick = 1; adc_conversion = 1; calc_tick = 1; } } */ //Takt3 - 500ms { timer_count ++; if (timer_count == 36) { timer_count = 0; fuenfhundertms_tick = 1; adc_conversion = 1; calc_tick = 1; } } ISR (TIMER2_OVF_vect) /* In der Interrupt-Routine sind die Softwareteiler realisiert, die die Takt- botschaften (10ms, 100ms, 1s) fuer die gesamte Uhr erzeugen. Die Interrupts werden von Timer 2 ausgeloest (Interrupt Nr. 1) Ausgangsvariable: takt10ms takt100ms takt1s */ { timertick = 1; // Botschaft 0,111ms senden --vorteiler; // Vorteiler dekrementieren if (vorteiler==0) // wenn 0 erreicht: 10ms abgelaufen { vorteiler = VORTEILER_WERT; // Vorteiler auf Startwert takt10ms = 1; // Botschaft 10ms senden --hundertstel; // Hunderstelzaehler dekrementieren if (hundertstel==0) // wenn 0 erreicht: 100ms abgelaufen { hundertstel = HUNDERTSTEL_WERT; // Teiler auf Startwert takt100ms = 1; // Botschaft 100ms senden } } }
folgende Meldung wird ausgewertet nachdem der Code aufgebaut wird: Build started 7.1.2013 at 13:49:29 avr-gcc -mmcu=atmega88p -Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT AbstandsmessungSharp.o -MF dep/AbstandsmessungSharp.o.d -c ../AbstandsmessungSharp.c ../AbstandsmessungSharp.c: In function 'main_servo': ../AbstandsmessungSharp.c:258: warning: no return statement in function returning non-void avr-gcc -mmcu=atmega88p -Wl,-Map=AbstandsmessungSharp.map AbstandsmessungSharp.o -o AbstandsmessungSharp.elf avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature AbstandsmessungSharp.elf AbstandsmessungSharp.hex avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex AbstandsmessungSharp.elf AbstandsmessungSharp.eep || exit 0 avr-objdump -h -S AbstandsmessungSharp.elf > AbstandsmessungSharp.lss AVR Memory Usage ---------------- Device: atmega88p Program: 6026 bytes (73.6% Full) (.text + .data + .bootloader) Data: 377 bytes (36.8% Full) (.data + .bss + .noinit) Build succeeded with 1 Warnings...
Orhan T. schrieb: > ../AbstandsmessungSharp.c:258: warning: no return statement in function > returning non-void Dann gibt doch deiner Main Funktion einen Returnwert und wenn es 0 ist.
Orhan T. schrieb: > Irgendwie > habe ich einen Wurm im meinem Quellcode und ich wäre dankbar, wenn Ihr > mit dabei behilflich sein könntet. Es wäre sehr viel einfacher, wenn du das Problem näher beschreiben könntest. Bitte hänge den Code als Anhang an. So ist der schlecht lesbar. Oliver
> int main_servo(void) { > init(); > _delay_ms(1000); > while(1) { > //Servos auf MIN > OCR1A = SERVOMIN; > > _delay_ms(1000); > ... Ähm. Du hast da etwas missverstanden. Bestehenden Komplett-Beispiele weiterverwenden bedeutet nicht, den Code einfach so wie er ist, in das bereits vorhandenen Code einkopieren und der Compiler soll sich dann selbst zusammensuchen, wie das alles zusammengehört. Wenn du Servo-Code gefunden hast, dann übernimmst du die Programm-IDEE und baust diese in deinem Programm ein. Indem du NEUEN Code schreibst und nicht einfach nur auf Biegen und Brechen stumpfsinnig kopierst. Dass man beim Schreiben des neuen Codes, den einen oder anderen Codeabschnitt mehr oder weniger 1:1 kopieren kann, liegt in der Natur der Sache. Aber komplette main() einfach so einzukopieren, das geht mit 100% Sicherheit schief. Bei der Übernahme und Weiterbenutzung von fremden Code, steht an erster Stelle, dass man die in diesem Code ausgedrückte Idee versteht und dann sich ansieht, wie diese Code-Idee ins eigene Programm hineinpasst. Der Code in main_servo, den du zukopiert hast, der zeigt dir, wie du die Servo-Funktionalität benutzen kannst, welche Initialisierungen zb nötig sind. D.h. du musst dir in DEINEM main() überlegen, wie und wo du dort genau dieselbe Initialisierung gebacken kriegst. Und der Rest von main_servo() ist einfach nur ein Beispiel, das zeigt was man tun muss, wenn man das Servo an eine bestimmte Position schicken will. D.h. da überlegst du dir in DEINEM Programm, wie und wo du in DEINEM Programm die Position herbekommst an die das Servo fahren soll und übernimmst aus dem Beispiel die Technik (ist ja nur eine Zuweisung), wie du diese Position dem 'Servo-Treiber' kommunizierst. Solche Codebeispiele sind im Grunde fast immer gleich zu sehen: Da gibt es Funktionalität, die in Form von Funktionen zur Verfügung gestellt wird, die mehr oder weniger 1:1 übernommen werden kann. Und das main() im Beispiel zeigt einem, wie man diese Funktionalität beispielhaft verwendet bzw. einsetzt.
das Forum stimmt. Was nicht stimmt ist deine Frage. 1. Aufbau: MiniMexle? was ist das? sollen wir uns jetzt selber dusslig suchen? 2. Code in [c ] [/ c] tags (ohne leerzeichen) posten 3. Problembeschreibung: was genau geht denn nicht?
Ich fürchte, main_servo() wird niemals aufgerufen. Das ist auch gut so, weil die Funktion niemals zurückkehren würde. Mehrere Sachen "gleichzeitig" machen ist nicht soo einfach. Mit geschickter Nutzung von Interrupts lässt sich da evtl. was machen.
Hallo nochmal vielen herzlichen Dank für die superschnellen Antworten :) ja beim Reinkopieren habe ich leider vergessen, die int_... zu deklarieren jetzt klappt alles wunderbar :) trotzdem Vielen Dank
Sobald das Projekt fertig ist udn zu 100% alles richtig funktioniert werde ich den Quellcode hier rein setzen, damit diejenigen die in dieser Richtung was aufbauen möchten sich gerne bedienen können.
Orhan T. schrieb: > Sobald das Projekt fertig ist udn zu 100% alles richtig funktioniert > werde ich den Quellcode hier rein setzen, damit diejenigen die in dieser > Richtung was aufbauen möchten sich gerne bedienen können. Hmmm. (Ohne dich beleidigen zu wollen) Wenn ich mir den jetzigen Code so ansehe ....
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.