Dirk
05.03.2010, 19:24
Hallo RP6 Fans,
manchmal hilft ein Impulslängen- und Frequenzmesser:
/*
* ************************************************** **************************
* 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
manchmal hilft ein Impulslängen- und Frequenzmesser:
/*
* ************************************************** **************************
* 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