Ich versuche mich gerade daran einen Ultraschallsensor vom Typ SRV05 an einem ATmega328 zum laufen zu bringen. Folgender Code ist für das Handling des SRV05 zuständig:
1 | /*
|
2 | * SRF05.c
|
3 | *
|
4 | * Created: 08.03.2016 11:36:49
|
5 | * Author: Admin
|
6 | */
|
7 | |
8 | #include "SRF05.h" |
9 | #include "global.h" |
10 | #include "EDIP.h" |
11 | #include "uart.h" |
12 | #include <avr/io.h> |
13 | #include <util/delay.h> |
14 | #include <stdio.h> |
15 | #include <string.h> |
16 | |
17 | |
18 | #define TRIGGER PB1
|
19 | #define MEASURE PD3
|
20 | |
21 | volatile unsigned int microseconds = 0; // to save pulse length |
22 | volatile uint8_t INT1_interrupt = 0; // to indicate whether an INT1 interrupt has already occurred |
23 | volatile uint8_t measurement_complete = 0; // is used to indicate that the measurement is complete |
24 | |
25 | // Function to initialize the SRF05-Interface
|
26 | void SRF05_init(void) |
27 | {
|
28 | // Setup timer 1
|
29 | TCCR1A = (1<<WGM12); // CTC Mode of Timer 1 |
30 | // (8000000 / 8 ) / 10 = 1000 -> Every 1ms
|
31 | OCR1A = 10 - 1; // Interrupt fires every 10us |
32 | TIMSK1 |= (1<<OCIE1A); // Enable compare interrupt |
33 | |
34 | DDRB |= (1<<TRIGGER); // set trigger pin to output |
35 | |
36 | DDRD &= ~(1<<MEASURE); // set INT1 as input |
37 | EICRA |= (ISC10) | (ISC11); |
38 | EIMSK |= (1<<INT1); |
39 | }
|
40 | |
41 | |
42 | // Check distance
|
43 | void SRF05_Measure(void) |
44 | {
|
45 | uint16_t dist = 0; |
46 | char distanceBuf[20]; |
47 | |
48 | dist = 0; // Reset distance |
49 | microseconds = 0; // Reset ms counter |
50 | TCNT1 = 0; // Set timer 1 to 0 |
51 | |
52 | // Trigger the SRF05 measurement
|
53 | PORTB |= (1<<TRIGGER); |
54 | _delay_ms(1); // 1ms trigger signal |
55 | PORTB &= ~(1<<TRIGGER); |
56 | uart_send("Trigger\n\r", 9); |
57 | |
58 | while(measurement_complete != 1); // wait until measurement is complete |
59 | |
60 | |
61 | measurement_complete = 0; // Reset |
62 | |
63 | dist = microseconds / 29 ; |
64 | |
65 | // Print distance to LCD
|
66 | sprintf(distanceBuf, "Distanz: %ucm", dist); |
67 | LCD_clearLine(0x11); |
68 | LCD_Puts(distanceBuf, strlen(distanceBuf), 0x00, 0x11, 'L'); |
69 | }
|
70 | |
71 | |
72 | // Interrupt for signal from SRF05
|
73 | ISR(INT1_vect) |
74 | {
|
75 | // Only if there hasn't been triggered on a rising edge yet
|
76 | if(INT1_interrupt == 0) |
77 | {
|
78 | TCCR1B |= (1<<CS11); // Start timer with prescaler 8 |
79 | EICRA |= (1<<ISC11); // Set INT1 to trigger in falling edge |
80 | EICRA &= ~(1<<ISC10); |
81 | |
82 | INT1_interrupt = 1; // To indicate, that an interrupt has already occurred |
83 | }
|
84 | else
|
85 | {
|
86 | TCCR1B &= ~(1<<CS11); // Stop Timer |
87 | |
88 | INT1_interrupt = 0; // Reset variable |
89 | measurement_complete = 1; // Variable to indicate end of measurement |
90 | }
|
91 | |
92 | |
93 | EIFR = (1<<INTF1); |
94 | }
|
95 | |
96 | |
97 | //Interrupt every 10µs
|
98 | ISR(TIMER1_COMPA_vect) |
99 | {
|
100 | microseconds += 10; |
101 | }
|
Leider funktioniert es nicht so richtig. Auf dem LA sehe ich, dass der SRV05 sein Startsignal bekommt und brav darauf antwortet. Der µC zeigt mir nur einmal 0cm an, beim zweiten Aufruf der Funktion sendet er das Startsignal und hängt sich auf. Auf dem LA sehe ich, dass aber auch die zweite antwort vom SRV05 korrekt gesendet wird