PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : SRF05: Abfrage, Berechnung; Ergebnis immer 0



Jaecko
28.03.2010, 17:50
Moin.

Hab mal wieder ein kleines Problem.
Ich bin gerade dabei, einen SRF05 auszulesen.

Vom Prinzip her send ich einfach den 10µs-Trigger und mess dann die Zeit des Antwort-Pulses über den Timer1.
Wird die steigende Flanke empfangen, startet der Timer mit Prescaler 8, d.h. die Dauer des Pulses entspricht dem Timerwert / 2 (bei 16MHz FCPU)
Ist der Antwortpuls beendet (fallende Flanke), wird der Timer gestoppt und das Ergebnis berechnet.
In der main lass ich mir das Ergebnis über I2C an ein LCD ausgeben, zusammen mit einer laufenden Nummer als Kontrolle, ob sich was tut.
Die Nummer läuft hoch, das Ergebnis bleibt jedoch immer 0.

Ich geh davon aus, dass gemessen wird, da die LED am SRF05 blinkt und man auch ein leises Knacken vom Ultraschallsender hört.

Die betreffenden Codes sind angehängt.

Sieht hier jemand nen Fehler?

main.c:


int main (void)
{
_delay_ms(100);
I2C_Init(100000ul);
SRF05_Init();

sei();
ui16_t measures = 0;

while(1)
{
sprintf(I2C_SendText, "%5d = %06ld ", measures++, SRF05_GetResponseTime());
I2C_PutS(0x20, (ui8_t*)I2C_SendText, 20);
_delay_ms(100);
}
}



srf05.c:


#include "srf05.h"

typedef enum
{
SRF_IDLE = 0,
SRF_WAITING_FOR_ECHO,
SRF_ECHO_ACTIVE,
SRF_RESULT_READY,
SRF_TIMEOUT
} e_srfstate;

volatile ui16_t SRF_ValueBuffer[400];
volatile ui16_t SRF_ValueBufferIndex = 0;

volatile ui8_t SRF_Overflows = 0;
volatile ui16_t SRF_TCNT = 0;
volatile ui32_t SRF_TotalTimeTicks = 0;

volatile e_srfstate SRF_State = SRF_IDLE;

void SRF05_Init(void)
{
// Setup result pin
SRF_RESULT_PORT &=~ (1 << SRF_RESULT_PIN);
SRF_RESULT_DDR &=~ (1 << SRF_RESULT_PIN);

// setup trigger pin
SRF_TRIGGER_PORT &=~ (1 << SRF_TRIGGER_PIN);
SRF_TRIGGER_DDR |= (1 << SRF_TRIGGER_PIN);

// Setup result pin interrupt:
SRF_RESULT_INT_ISC_REG |= (1 << SRF_RESULT_INT_ISC_BIT);

}

ui32_t SRF05_GetResponseTime(void)
{
// Response signal 100µs - 25ms
// FCPU = 16MHz
// Prescaler 8 => 2 MHz => 0.5 µs tick duration

// Prepare Timer
TCCR1A = 0; // Standard timer; just count here
TCCR1B = 0; // Stop timer
TCNT1 = 0;
SRF_Overflows = 0;
SRF_TCNT = 0;
SRF_TotalTimeTicks = 0;

// clear a possible pending interrupt request
SRF_RESULT_INT_FLAG_REG |= (1 << SRF_RESULT_INT_FLAG_BIT);

// enable interrupt
SRF_RESULT_INT_MSK_REG |= (1 << SRF_RESULT_INT_MSK_BIT);

// enable timer overflow interrupt
TIMSK |= (1 << TOIE1);

SRF_State = SRF_WAITING_FOR_ECHO;

// Send trigger pulse (10µs)
SRF_TRIGGER_HIGH();
_delay_us(10);
SRF_TRIGGER_LOW();

// wait until measurement is complete
while((SRF_State == SRF_ECHO_ACTIVE) || (SRF_State == SRF_WAITING_FOR_ECHO))
{
// nothing to do; just wait...
}

// Calculate result
SRF_TotalTimeTicks = SRF_Overflows;
SRF_TotalTimeTicks <<= 16;
SRF_TotalTimeTicks += SRF_TCNT;

return SRF_TotalTimeTicks;
}


ISR(SRF_RESULT_ISR)
{
ui8_t pinlevel = SRF_RESULT_INPUT & (1 << SRF_RESULT_PIN);

if (pinlevel)
{
// rising edge: result pulse started
// start timer for counting
TCCR1B = (1 << CS11);
SRF_State = SRF_ECHO_ACTIVE;
}
else
{
// falling edge: result pulse end
// stop timer
SRF_TCNT = TCNT1;
TCCR1B = 0;

// disable trigger interrupt
SRF_RESULT_INT_MSK_REG &=~ (1 << SRF_RESULT_INT_MSK_BIT);

// disable timer overflow interrupt
TIMSK &=~ (1 << TOIE1);
SRF_State = SRF_RESULT_READY;
}
}

ISR (SIG_OVERFLOW1) // Interrupt Timer 1
{
SRF_Overflows++;
}


srf05.h


#ifndef _SRF05_H_
#define _SRF05_H_

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "glob_defs.h"
#include "glob_type.h"

#define SRF_TRIGGER_PORT PORTD
#define SRF_TRIGGER_DDR DDRD
#define SRF_TRIGGER_PIN 4

#define SRF_RESULT_PORT PORTD
#define SRF_RESULT_DDR DDRD
#define SRF_RESULT_INPUT PIND
#define SRF_RESULT_PIN 3

#define SRF_RESULT_INT_ISC_REG (MCUCR)
#define SRF_RESULT_INT_ISC_BIT (ISC11)

#define SRF_RESULT_INT_MSK_REG (GICR)
#define SRF_RESULT_INT_MSK_BIT (INT1)

#define SRF_RESULT_INT_FLAG_REG (GIFR)
#define SRF_RESULT_INT_FLAG_BIT (INTF1)

#define SRF_RESULT_ISR SIG_INTERRUPT1

#define SRF_TRIGGER_HIGH() (SRF_TRIGGER_PORT |= (1 << SRF_TRIGGER_PIN))
#define SRF_TRIGGER_LOW() (SRF_TRIGGER_PORT &=~ (1 << SRF_TRIGGER_PIN))

void SRF05_Init(void);
ui32_t SRF05_GetResponseTime(void);

#endif

Del
28.03.2010, 17:54
Hast du die andere Variante ohne I2C ausprobiert, hat bei mir besser funktioneirt.

Jaecko
28.03.2010, 18:01
Ohne I2C seh ich nix mehr, da das Display per I2C dranhängt.
Zudem ist später dann auch I2C der einzige Weg für den Datenaustausch.

Der SRF05 selber hat kein I2C. Den gibts erst ab SRF08 oder 10.

sternst
28.03.2010, 19:11
Sieht hier jemand nen Fehler? Ja, ich denke schon, aber um sicher zu sein, müsste man mal wissen, um welchen Controller es sich eigentlich handelt.

Jaecko
28.03.2010, 19:30
Upsa verplant: ATMega8, ext. Quarz mit 16MHz; VCC 5V.

sternst
28.03.2010, 20:26
Externer Interrupt ist auf fallende Flanke konfiguriert
=> steigende Flanke (Pulsanfang) löst keinen Interrupt aus
=> Timer wird nicht gestartet
=> Interrupt bei fallender Flanke (Pulsende) liest 0 aus
=> Ergebnis immer 0

Jaecko
28.03.2010, 20:45
Thx.
Mal wieder zu schnell übers Datenblatt geflogen bzw. den Wert vertauscht.
Die Zeile in der srf05.h muss dann logischerweise so aussehen:

#define SRF_RESULT_INT_ISC_BIT (ISC10)

Stas
21.04.2010, 16:23
Hi Jaecko!
Hat es geklappt bei dir? Hast du zufällig Quelltext für mich?:)))

Jaecko
21.04.2010, 16:41
Naja, Quelltext liegt im ersten Posting.
Und mit ändern der Zeile für die Interrupt source klappts auch perfekt.

Stas
21.04.2010, 19:33
So gut kenne ich mich leider nicht aus. Welche Zeile genau?

Ach so, hab eben gesehen das du ATMega8 hast. Würde dieser Quelltext auf einem ATMEGA32 (RP6) funktionieren?

Jaecko
21.04.2010, 19:35
Die Zeile hier:
#define SRF_RESULT_INT_ISC_BIT (ISC10)

Der Code geht auf nem Mega32 genau so. Du musst halt nur alle #defines in der .h anpassen auf die jeweiligen Pins/Interrupts.
Direkt auf dem Mega32 des RP6 wirds vermutlich nicht gehen, aber auf dem Erweiterungsmodul evtl schon.

Ich hab das Radar auch an nem RP6 dran; nur hab ich halt alles in den ATMega8 ausgelagert, damit der in Ruhe messen kann und sich nicht noch um die ganze Steuerung kümmern muss.

Stas
21.04.2010, 19:44
Was muss in dieser Zeile geändert werden?

Und was muss ich an den #defines ändern?

Sorry, wenn ich so blöd frage:)

Habe den SRF05 an den ADC2 drangelötet.

Jaecko
21.04.2010, 20:02
Die musst du so anpassen, dass eben die Ports/Pins/Register mit denen zusammen passen, die du am Mega32 verwenden willst.
Und bei der Zeile muss die Interruptquelle so geändert werden, dass der Result-Pin bei steigender UND fallender Flanke auslöst, nicht wie's bei mir zuerst war nur bei fallender Flanke.

Torrentula
13.06.2011, 11:08
Sorry, wenn ich das Thema noch mal ausgrabe, aber welche Werte liefert "SRF05_GetResponseTime()" jetzt eigentlich zurück?

Ich verstehe einfach diese Rechenoperation nicht:


SRF_TotalTimeTicks <<= 16;


Lasse ich mir das auf die Schnitstelle ausgeben kommen nur komische Werte daher...

Hoffe, dass das nochmal beantwortet wird :)

MfG

Torrentula

Kampfwurst_Hugo
24.09.2011, 16:59
Hallo

Weis jemand ob der Code auf Seite 1 funktioniert oder hat der noch einen Fehler??

Torrentula
24.09.2011, 17:40
Der Code funktioniert eigentlich schon, bei mir wird allerdings gelegentlich einfach der Wert 0 zurückgegeben, obwohl kein Objekt im Weg ist.

Habe das Problem leider nicht beheben können, und bin deshalb für meinen Roboter auf Arduino umgestiegen.

MfG

Torrentula