This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| de:examples:sensor:ultrasonic [2009/04/09 10:35] – angelegt nierhoff | de:examples:sensor:ultrasonic [2020/07/20 09:00] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 16: | Line 16: | ||
| // | // | ||
| // Mikk Leini | // Mikk Leini | ||
| + | // Department of Mechatronics | ||
| + | // Tallinn University of Technology | ||
| + | // | ||
| + | // NB! | ||
| + | // CPU clock has to be 14745600 hz | ||
| // | // | ||
| // 2009 | // 2009 | ||
| Line 23: | Line 28: | ||
| #include < | #include < | ||
| #include < | #include < | ||
| - | #include < | ||
| // Include common library | // Include common library | ||
| - | #include "pinops.h" | + | #include < |
| + | #include "pin.h" | ||
| + | #include "lcd.h" | ||
| + | |||
| // Configuration | // Configuration | ||
| #define INTEGRATION_STEP 5 | #define INTEGRATION_STEP 5 | ||
| + | |||
| // Math operations | // Math operations | ||
| #define MIN(a, b) ((a) < (b) ? (a) : (b)) | #define MIN(a, b) ((a) < (b) ? (a) : (b)) | ||
| #define MAX(a, b) ((a) > (b) ? (a) : (b)) | #define MAX(a, b) ((a) > (b) ? (a) : (b)) | ||
| #define INTEGRATE(value, | #define INTEGRATE(value, | ||
| + | |||
| // Configure pins | // Configure pins | ||
| - | #define SEGMENT_DISPLAY_LATCH | ||
| - | #define SEGMENT_DISPLAY_DATA_OUT | ||
| - | #define SEGMENT_DISPLAY_CLOCK | ||
| #define LEDR | #define LEDR | ||
| - | #define US_TRIGGER | + | #define US_TRIGGER |
| - | #define US_ECHO | + | #define US_ECHO |
| + | |||
| // Ultrasonic data structure | // Ultrasonic data structure | ||
| struct | struct | ||
| Line 51: | Line 54: | ||
| unsigned short result; | unsigned short result; | ||
| } ultrasonic; | } ultrasonic; | ||
| + | |||
| // 16 bit timestamp | // 16 bit timestamp | ||
| volatile unsigned long timestamp = 0; | volatile unsigned long timestamp = 0; | ||
| - | |||
| - | // | ||
| - | // 7 segment display initialization | ||
| - | // | ||
| - | void segment_diplay_init(void) | ||
| - | { | ||
| - | // Set latch, data out and clock pins as output | ||
| - | setup_output_pin(SEGMENT_DISPLAY_LATCH); | ||
| - | setup_output_pin(SEGMENT_DISPLAY_DATA_OUT); | ||
| - | setup_output_pin(SEGMENT_DISPLAY_CLOCK); | ||
| - | } | ||
| - | // | ||
| - | // Digit writing to 7 segment display | ||
| - | // | ||
| - | void segment_display_write(unsigned char digit) | ||
| - | { | ||
| - | unsigned char map; | ||
| - | // Decimal to segment map | ||
| - | switch (digit) | ||
| - | { | ||
| - | case 0 : map = 0b00111111; break; // Every bit corresponds to one segment | ||
| - | case 1 : map = 0b00000110; break; // " | ||
| - | case 2 : map = 0b01011011; break; // " | ||
| - | case 3 : map = 0b01001111; break; // " | ||
| - | case 4 : map = 0b01100110; break; | ||
| - | case 5 : map = 0b01101101; break; | ||
| - | case 6 : map = 0b01111100; break; | ||
| - | case 7 : map = 0b00000111; break; | ||
| - | case 8 : map = 0b01111111; break; | ||
| - | case 9 : map = 0b01100111; break; | ||
| - | default: map = 0b01111001; | ||
| - | } | ||
| - | |||
| - | // Latch low | ||
| - | clear_pin(SEGMENT_DISPLAY_LATCH); | ||
| - | |||
| - | // Send every bit in the byte. MSB (most significant bit) first. | ||
| - | for (signed char i = 7; i >= 0; i--) | ||
| - | { | ||
| - | // If bit is set, sets the data out pin, otherwise not | ||
| - | set_pin_to(SEGMENT_DISPLAY_DATA_OUT, | ||
| - | |||
| - | // Clock high for certain period | ||
| - | set_pin(SEGMENT_DISPLAY_CLOCK) | ||
| - | _delay_us(1); | ||
| - | |||
| - | // Clock low for certain period | ||
| - | clear_pin(SEGMENT_DISPLAY_CLOCK) | ||
| - | _delay_us(1); | ||
| - | } | ||
| - | |||
| - | // Latch high | ||
| - | set_pin(SEGMENT_DISPLAY_LATCH); | ||
| - | } | ||
| - | |||
| - | |||
| // | // | ||
| - | // 0.1ms clock Timer1 | + | // Start measuring timer |
| // | // | ||
| void clock_init(void) | void clock_init(void) | ||
| Line 120: | Line 67: | ||
| TCCR1A = BIT(WGM11); | TCCR1A = BIT(WGM11); | ||
| TCCR1B = BIT(WGM13) | BIT(WGM12) | BIT(CS10); | TCCR1B = BIT(WGM13) | BIT(WGM12) | BIT(CS10); | ||
| - | + | ||
| - | // Top = 1475 | + | // Adjust timer period so that we get 1cm of |
| - | // Clock = 14.745600 Mhz / 1475 = ~10 kHz | + | // measured distance every overflow. |
| - | // Period = 1 / Clock = 0.1 ms | + | // |
| - | ICR1 = 1475; | + | // Formula: |
| + | // Timer period | ||
| + | // The period is multiplied by 2 because the sound travels | ||
| + | // forth and back. | ||
| + | ICR1 = 893; | ||
| + | |||
| // Enable overflow interrupt | // Enable overflow interrupt | ||
| TIMSK = BIT(TOIE1); | TIMSK = BIT(TOIE1); | ||
| } | } | ||
| + | |||
| // | // | ||
| // Delay | // Delay | ||
| - | // Time in 0.1 of milliseconds | + | // Time in ~60 of microseconds |
| // | // | ||
| void delay(unsigned int time) | void delay(unsigned int time) | ||
| { | { | ||
| unsigned long end_time, temporary = 0; | unsigned long end_time, temporary = 0; | ||
| + | |||
| // Interrupt safe timestamp waiting | // Interrupt safe timestamp waiting | ||
| cli(); | cli(); | ||
| end_time = timestamp + time; | end_time = timestamp + time; | ||
| sei(); | sei(); | ||
| + | |||
| while (temporary < end_time) | while (temporary < end_time) | ||
| { | { | ||
| Line 151: | Line 102: | ||
| } | } | ||
| } | } | ||
| + | |||
| // | // | ||
| // Timer1 overflow interrupt | // Timer1 overflow interrupt | ||
| Line 159: | Line 110: | ||
| timestamp++; | timestamp++; | ||
| } | } | ||
| + | |||
| // | // | ||
| // Ultrasonic initialization | // Ultrasonic initialization | ||
| Line 168: | Line 119: | ||
| ultrasonic.state | ultrasonic.state | ||
| ultrasonic.result = 0; | ultrasonic.result = 0; | ||
| + | |||
| // Setup pins | // Setup pins | ||
| - | setup_output_pin(US_TRIGGER); | + | pin_setup_output(US_TRIGGER); |
| - | setup_input_pin(US_ECHO); | + | pin_setup_input(US_ECHO); |
| + | |||
| // External interrupt on any logical change | // External interrupt on any logical change | ||
| EICRB = BIT(ISC40); | EICRB = BIT(ISC40); | ||
| + | |||
| // Enable external interrupt 4 | // Enable external interrupt 4 | ||
| EIMSK = BIT(INT4); | EIMSK = BIT(INT4); | ||
| } | } | ||
| + | |||
| // | // | ||
| // Trigger ultrasonic pulse | // Trigger ultrasonic pulse | ||
| Line 188: | Line 139: | ||
| if (ultrasonic.state > 0) | if (ultrasonic.state > 0) | ||
| return; | return; | ||
| + | |||
| // Trigger ultrasonic pulse | // Trigger ultrasonic pulse | ||
| ultrasonic.state = 1; | ultrasonic.state = 1; | ||
| - | set_pin(US_TRIGGER); | + | pin_set(US_TRIGGER); |
| delay(1); | delay(1); | ||
| - | clear_pin(US_TRIGGER); | + | pin_clear(US_TRIGGER); |
| } | } | ||
| + | |||
| // | // | ||
| // External interrupt - on echo pulse | // External interrupt - on echo pulse | ||
| Line 202: | Line 153: | ||
| { | { | ||
| unsigned char b; | unsigned char b; | ||
| - | + | ||
| - | get_pin_value(US_ECHO, b); | + | pin_get_value(US_ECHO, b); |
| + | |||
| // Rising edge ? | // Rising edge ? | ||
| if (b && (ultrasonic.state == 1)) | if (b && (ultrasonic.state == 1)) | ||
| Line 211: | Line 162: | ||
| ultrasonic.state = 2; | ultrasonic.state = 2; | ||
| } | } | ||
| + | |||
| // Falling edge ? | // Falling edge ? | ||
| else if (!b && (ultrasonic.state == 2)) | else if (!b && (ultrasonic.state == 2)) | ||
| Line 219: | Line 170: | ||
| } | } | ||
| } | } | ||
| + | |||
| // | // | ||
| // Get ultrasonic result | // Get ultrasonic result | ||
| Line 226: | Line 177: | ||
| { | { | ||
| unsigned short result; | unsigned short result; | ||
| + | |||
| // Interrupt safe result reading | // Interrupt safe result reading | ||
| cli(); | cli(); | ||
| Line 232: | Line 183: | ||
| sei(); | sei(); | ||
| asm volatile (" | asm volatile (" | ||
| + | |||
| return result; | return result; | ||
| } | } | ||
| + | |||
| // | // | ||
| // Program entrance function | // Program entrance function | ||
| Line 241: | Line 192: | ||
| int main(void) | int main(void) | ||
| { | { | ||
| - | volatile unsigned short lowValue | + | unsigned short value = 0; |
| - | volatile unsigned short highValue = 0x0000; | + | char buffer[8]; |
| - | volatile | + | |
| - | volatile unsigned | + | |
| // Initializing | // Initializing | ||
| clock_init(); | clock_init(); | ||
| - | ultrasonic_init(); | + | ultrasonic_init(); |
| - | segment_diplay_init(); | + | pin_setup_output(LEDR); |
| - | setup_output_pin(LEDR); | + | |
| + | // Init display | ||
| + | lcd_init(LCD_DISP_ON); | ||
| + | lcd_gotoxy(0, | ||
| + | lcd_puts(" | ||
| + | |||
| // Enable global interrupts | // Enable global interrupts | ||
| sei(); | sei(); | ||
| + | |||
| // Endless loop | // Endless loop | ||
| while (1) | while (1) | ||
| { | { | ||
| - | // Blink LED every second | + | // Blink LED constantly |
| cli(); | cli(); | ||
| - | set_pin_to(LEDR, (timestamp % 10000) > 1000); | + | pin_set_to(LEDR, (timestamp % 10000) > 1000); |
| sei(); | sei(); | ||
| - | + | ||
| - | // Constantly try triggering | + | // Trigger |
| ultrasonic_trigger(); | ultrasonic_trigger(); | ||
| - | + | ||
| - | // Read ultrasonic result | + | // Read last ultrasonic result |
| INTEGRATE(value, | INTEGRATE(value, | ||
| - | + | ||
| - | // Check for new lower limit | + | // Go-to first row and to first character |
| - | lowValue = MIN(lowValue, value); | + | lcd_gotoxy(0, 1); |
| - | + | ||
| - | // Check for new higher limit | + | // Output text |
| - | highValue = MAX(highValue, value); | + | itoa(value, buffer, 10); |
| - | + | lcd_puts(buffer); | |
| - | // Calculate relative value | + | lcd_puts(" |
| - | // Range from lowValue to highValue is converted to 0 to 9 | + | |
| - | relativeValue = 9 * (value - lowValue) / (highValue - lowValue); | + | |
| - | + | ||
| - | // Write digit | + | |
| - | segment_display_write(relativeValue); | + | |
| // Delay a while | // Delay a while | ||
| - | delay(50); | + | delay(200); |
| } | } | ||
| } | } | ||
| </ | </ | ||