Hallo RP6 Fans,
manchmal hilft ein Impulslängen- und Frequenzmesser:
Dieses Programm macht die M32 zu einem solchen "Messgerät" mit der Input Capture Funktion.Code:/* * **************************************************************************** * RP6 ROBOT SYSTEM - RP6 CONTROL M32 TESTS * **************************************************************************** * Example: Impulse length measurement with input capture * Author(s): Dirk * **************************************************************************** * Description: * * With this program the lengths of positive impulses of an unknown TTL signal * connected to the input capture pin (ICP) of the M32 (PD6, I/O pin 8) can be * displayed on the LCD. * If you uncomment the definition FREQUENCY, the frequency of the unknown TTL * signal will be displayed instead of the impulse length. * * ############################################################################ * The Robot does NOT move in this example! You can simply put it on a table * next to your PC and you should connect it to the PC via the USB Interface! * ############################################################################ * **************************************************************************** */ /*****************************************************************************/ // Includes: #include "RP6ControlLib.h" // The RP6 Control Library. // Always needs to be included! /*****************************************************************************/ // Defines: //#define FREQUENCY // Measure the frequency // (instead of the impulse length) /*****************************************************************************/ // Variables: typedef union { uint32_t i32; struct { uint8_t i8l; // Low byte uint8_t i8m; // Middle byte uint16_t i16h; // High uint }; } icrcounter_t; volatile uint16_t ovfcnt = 0; // Number of overflows during // the measurement volatile uint32_t timediff; uint32_t time; double result; #define FALLING_EDGE 0 // (or next rising edge) #define RISING_EDGE 1 volatile uint8_t edgeflag; char buffer[12]; // Buffer for ASCII conversion /*****************************************************************************/ // Functions: /** * TIMER1 Overflow ISR * * In this ISR the ICR1 overflows are counted. * */ ISR (TIMER1_OVF_vect) { ++ovfcnt; // Count the overflows } /** * TIMER1 Capture ISR * * In this ISR the cycles from a rising edge to the falling (or the next * rising) edge are calculated. * */ ISR (TIMER1_CAPT_vect) {static icrcounter_t icrcnt_start; icrcounter_t icrcnt_end; if (edgeflag == RISING_EDGE) { // Rising edge! icrcnt_start.i8l = ICR1L; // Low byte first icrcnt_start.i8m = ICR1H; // High byte is buffered ovfcnt = 0; // Reset overflow counter #ifndef FREQUENCY TCCR1B &= ~(1<<ICES1); // Next trigger: Falling edge #endif edgeflag = FALLING_EDGE; } else { // Falling (or next rising) edge! icrcnt_start.i16h = 0; // Reset upper 16 bits (start value) icrcnt_end.i8l = ICR1L; // Low byte first icrcnt_end.i8m = ICR1H; // High byte is buffered // If low ICR1H and waiting overflow interrupt: if ((icrcnt_end.i8m < 128) && (TIFR & (1<<TOV1))) { // Do the job of the waiting timer overflow interrupt: ++ovfcnt; TIFR = (1<<TOV1); // Clear Timer1 overflow interrupt } icrcnt_end.i16h = ovfcnt; // Upper 16 bits (overflow counter) timediff = icrcnt_end.i32 - icrcnt_start.i32; #ifndef FREQUENCY TCCR1B |= (1<<ICES1); // Next trigger: Rising edge #endif edgeflag = RISING_EDGE; } } /*****************************************************************************/ // Main function - The program starts here: int main(void) { initRP6Control(); // Always call this first! The Processor will not // work correctly otherwise. initLCD(); // Initialize the LC-Display (LCD) // Always call this before using the LCD! // Write some text messages to the LCD: showScreenLCD("################", "################"); mSleep(1500); showScreenLCD("<<RP6 Control>>", "<<LC - DISPLAY>>"); mSleep(2500); showScreenLCD("Imp. Measurement", "Version 1.00 ICP"); mSleep(2500); clearLCD(); // Clear the whole LCD Screen // Clear the four Status LEDs: setLEDs(0b0000); // Initialize the M32 ICP pin (PD6) as input: DDRD &= ~IO_PD6; PORTD |= IO_PD6; // Pullup on // Initialize the M32 Timer1 input capture function: edgeflag = RISING_EDGE; TCCR1B = (1<<ICES1) | (1<<CS10) // Trigger: Rising edge, no prescaling | (1<<ICNC1); // and noise canceler TIMSK = (1<<TICIE1) | (1<<TOIE1); // Activate capture & overflow ISR TIFR = (1<<TOV1) | (1<<ICF1); // Clear active interrupts while(true) { cli(); time = timediff; sei(); if (time > 0) { ultoa(time, buffer, DEC); // Convert to ASCII setCursorPosLCD(0, 0); writeStringLCD("CNT "); // Counter value ( / F_CPU [s]) writeStringLCD(buffer); writeStringLCD(" "); setCursorPosLCD(1, 0); #ifndef FREQUENCY result = (double) time / F_CPU; writeStringLCD("IMP "); // Impulse length [s] dtostrf(result, 11, 7, buffer); // Convert to ASCII #else result = (double) F_CPU / time; writeStringLCD("FRQ "); // Frequency [Hz] dtostrf(result, 11, 3, buffer); // Convert to ASCII #endif writeStringLCD(buffer); TIFR = (1<<TOV1) | (1<<ICF1); } } return 0; } /****************************************************************************** * Additional info * **************************************************************************** * Changelog: * - v. 1.0 (initial release) 27.02.2010 by Dirk * * **************************************************************************** */ /*****************************************************************************/
Viel Spaß damit
Gruß Dirk







Zitieren


Lesezeichen