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
volatileunsignedintmicroseconds=0;// to save pulse length
22
volatileuint8_tINT1_interrupt=0;// to indicate whether an INT1 interrupt has already occurred
23
volatileuint8_tmeasurement_complete=0;// is used to indicate that the measurement is complete
24
25
// Function to initialize the SRF05-Interface
26
voidSRF05_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
voidSRF05_Measure(void)
44
{
45
uint16_tdist=0;
46
chardistanceBuf[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
// 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
ein Tipp von mir:
der SRF05 gibt ja pro cm 58us high zurück, also: lass einen Timer alle
58us ein hoch zählen (ab einfachsten im CTC-mode)
Ich würde die PCInts nehmen (nehme ich generell lieber). Diese reagieren
auf jeden Flankenwechsel.
D.h. bei der Steigenden Flanke speicherst du dir den 58us-Timerwert ab.
Bei einer fallenden Flanke ziehst du den aktuellen Timerwert vom
gespeicherten ab.
UND: das ist deine Distanz in Zentimetern.
Denke allerdings dran, dass wenn du den Mode mit nur einem
Auslöse-/Echo-Pin nimmst, du vor dem Start-Signal die PCInts abschalten
musst und danach wieder ein.
Zu deinem Code:
warum nutzt du Interrupts, wenn du sowieso auf das Ergebnis wartest?
Dann könnte man einfach pollen und dein Problem würde wahrscheinlich
einfacher zu lösen sein.
Hallo nochmal,
dein Timer stimmt leider noch nicht.
Jens K. schrieb:> uint16_t timerCNT = 0;
volatile fehlt, sonst kriegt der Compiler das ändern in der ISR nicht
mit, bzw. er optimiert es, da er denkt, dass die Variable nie geändert
wird.
Jens K. schrieb:> // Setup timer 1> TCNT1 = 65478; // Preload> TCCR1B |= (1<<CS11); // Prescaler 8> TIMSK1 |= (1<<TOIE1); // Enable overflow interrupt
der Preload ist zwar gut gemeint, gilt aber leider nur bis zum ersten
Overflow, ab da zählt der Timer wieder schön von 0 hoch.
Jens K. schrieb:> //Interrupt every 58µs> ISR(TIMER1_OVF_vect)> {> timerCNT++;> }
Du müsstest dann hier auch einen Preload machen.
Aber warum das? Setze dich mal mit dem CTC mode auseinander.
Dieser setzt den Timer beim erreichen der ISR automatisch auf 0 zurück.
Ein Beispiel:
1
TIMSK5=(1<<OCIE5A);
2
TCCR5B=(1<<CS51)|(1<<WGM52);//prescaler 8, CTC
3
OCR5A=58*2;//58us@16MHz
Aber eigentlich sollte mit einem richtigen Timer der Code klappen