Hallo liebe RoboterNETZ Gemeinde,
momentan möchte ich gern einen Magnetgeber mit der Auflösung von 2 auswerten. Dazu benutze ich den Atmega88p und benutze HTerm um mir die Werte auszugeben. Nur leider funktioniert das noch nicht ganz.![]()
Ich möchte das Ganze so gestalten, dass ich diesem eine Messdauer von bspw. 200ms vorgebe. ( Da sehr geringe Auflösung, aber dann noch recht gut geregelt werden soll, wobei die Programmdauer nicht sehr kritisch ist ) Während der Messdauer soll der 8-Bit Timer 0 also laufen und beide externene Interrupteingänge INT 0 und INT 1 ( sind also 2 Geber ) sollen bei einer steigenden Flanke einen Impuls weiter zählen.
Die 200ms habe ich versucht über einen Prescaler + mehrere Overflows einzustellen. Nur leider zeigt mein H-Term nur Kauderwelsch an, also so als würde es die Zeichen nicht interpretieren können. ( einmal Endekennung '\0' ) Es kommt auch nur ein einziges Mal ein Zeichen und nicht zyklisch wie die While Schleife es eigentlich machen söllte.
( Die Richtungsauswertung kommt erst im nachhinein, wenn wenigstens das funktioniert )
Vielen Dank schonmal für eure Hilfe!Code:#define F_CPU 16000000UL #include <avr/io.h> #include <stdio.h> #include <avr/interrupt.h> #include <util/delay.h> #define Baud 9600UL volatile uint16_t DRZ1, DRZ2; volatile uint8_t TIM0_Overflow, Drehrichtung1, Drehrichtung2; void UARTinit(){ UBRR0 = 103; // Baudrate laut Datasheet UCSR0B = (1<<TXEN0); // Enable Senden UCSR0C = (1<<UCSZ00) | (1<<UCSZ01); // Setze 8 Bit Datenlänge // Alles was 0 ist setzt Asynchron Modus, Normal Speed, 1 Stop Bit und keine Paritaet } int uart_send( unsigned char c) { while (!(UCSR0A & (1<<UDRE0))) { // mach nichts } //senden UDR0=c; return 0; } void uart_puts (char *s) { while (*s) { /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */ uart_send(*s); s++; } } ISR(INT0_vect) { DRZ1++; } ISR(INT1_vect) { DRZ2++; } ISR(TIMER0_OVF_vect) { TIM0_Overflow++; } uint16_t Inkrementalgeber(uint16_t* Drehzahl1, uint16_t *Drehzahl2) { TCNT0 = 0; DRZ1 = 0; // Alle Zählerwerte auf 0 zurücksetzen DRZ2 = 0; TIM0_Overflow = 0; TCCR0B |= (1<<CS02) | (1<<CS00); // Frequentvorteiler von 1024 --> 16MHz/1024 = 64us pro Tick UND TImer0 starten // 200ms/64us = 3125 --> 8 Bit Timer = 255 --> 12 * 255 + 1 * 65 = 3125 --> TIM0_Overflow = 12 und TCNT0 = 65, damit mit 8 Bit Timer und Prescaler 200ms Messzeit erreicht TIMSK0 |= (1<<TOIE0); // Overflow_Flag enablen EICRA |= (1<<ISC11) | (1<<ISC01) | (1<<ISC00) | (1<<ISC10); // INT0 und INT1 auf steigende Flanke triggern EIMSK |= (1<<INT1) | (1<<INT0); // INT1 und INT0 Interrupts enablen sei(); // Globale Interrupts erlauben while (1) { if (TIM0_Overflow >= 12) { if (TCNT0 >=65) { break; } } // tue nichts bis 200ms abgelaufen sind } TCCR0B &= ~((1<<CS02) | (1<<CS00)); // Timer stoppen cli(); // Globale Interrupts ausschalten *Drehzahl1 = DRZ1; // Werteübergabe der Drehzhalen an das Hauptprogramm *Drehzahl2 = DRZ2; } int main(void) { uint16_t Drehzahl1, Drehzahl2; uint8_t KanalA, KanalB; DDRD &= ~((1<<PIND2) | (1<<PIND3)); // INT0 und INT 1 als Kanaleingänge für beide Inkrementalgeber auswählen DDRD |= (1<<PIND1); // UART TX als Ausgang DDRD &= ~(1<<PIND0); TCCR0A &= ~((1<<WGM00) | (1<<WGM01)); // Normal Operation Mode für Timer0 auswählen TCCR0B &= ~(1<<WGM02); char s[30]; uint16_t x; while (1) { Inkrementalgeber(&Drehzahl1 , &Drehzahl2); Drehzahl1 = 150 * Drehzahl1; // Drehzahl in 1/min = 60s * ( 1000ms / Messdauer[ms] ) * ( Anzahl Flanken / Imp. pro Umdrehung [ Auflösung ] ) Drehzahl2 = 150 * Drehzahl2; // 60s * 1000/200 * DRZ/2 = 150*DRZ KanalA = Drehzahl1 / 72; // Untersetzung Getriebe einbringen KanalB = Drehzahl2 / 72; x=KanalA; sprintf(s, "Drehzahl 1: %.d 1/min \n", x); uart_puts( s ); //_delay_ms(200); x=KanalB; sprintf(s, "Drehzahl 2: %.d 1/min \n", x); uart_puts( s ); //_delay_ms(200); } }
Grüße,
Bucki







Zitieren
Lesezeichen