Hallo RP6 Fans,

manchmal hilft ein Impulslängen- und Frequenzmesser:
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
 *
 * ****************************************************************************
 */

/*****************************************************************************/
Dieses Programm macht die M32 zu einem solchen "Messgerät" mit der Input Capture Funktion.

Viel Spaß damit

Gruß Dirk