ATmega32 Erweiterung US-Modul anschließen

all about robots

ATmega32 Erweiterung US-Modul anschließen

Postby Flario on Sat Aug 23, 2008 3:15 pm

Hi,

dieser Beitrag bezieht sich auf das US-Modul SRF05 von E-Robotix.

Image

Das Modul wird als fertig Teil geliefert unt muss nur noch eingebaut werden.
Es steht 2 Moden zur Auswahl wobei entweder 1 Pin oder 2 Pins gebraucht werden.



Mode 1 (2 Pins)

Image

hierbei wird ein Impuls in den "Trigger Input" von minimum 10us gesendet,
und "Echo Output" erhalten wir ein Signal in der Länge die der Schall gebraucht hat.
Das echo liegt zwischen 100us und 25ms. Sollte kein Object gefunden werden
wird nach 30ms abgebrochen.

Hierzu ein Diagramm:
Image

Als Beispiel hab ich den "Trigger Input" an PB1 und den "Echo Output" an PB0 angeschlossen.
(+5V und GND muss ebenfalls Angeschlossen werden)

Hier der Beispiel Code:
Code: Select all
//Wichtig! die Taktfrequenz eures ATmega32 müsst ihr für _delay_us(..) definieren!
//Je nach dem ob ihr 8mhz od. 16mhz habt.
#define F_CPU 8000000
//#define F_CPU 16000000

#include <util/delay.h>

#include "asuro.h"
#include "lcd.h" //nur Falls ein LCD Vorhanden ist.

int main()
{

    Init();
    LCDInit(); //Falls ein LCD Display Vorhanden ist dieses Initialisieren.
   
    DDRB &= ~( 1 << PB0 );  //PB0 auf Eingang setzen
    DDRB |=  ( 1 << PB1 );  //PB1 auf Ausgang Setzen
                                   
    PORTB &= ~( 1 << PB1 ); //PB1 auf LOW

    while(1)
    {
        unsigned int sleep = 0, dist = 0;
       
        PORTB |= ( 1 << PB1 );  //Impuls Starten
        _delay_us(11);          //Wie lange der Impuls ist, ist eigentlich egal,
                                //da die Messung erste gestarted wird nachdem der impuls zu ende ist.
        PORTB &= ~( 1 << PB1 ); //Impuls Beenden
       
        cli(); //Interrupts Deaktivieren
       
        while(1)
        {
            _delay_us(1);
           
            if(PINB & ( 1 << PB0 )) //Wenn das echo Signal kommt...
            {
                sleep++; //zeit zählen               
            }else if(sleep > 0) //wenn es zuende ist aus der schleife aussteigen
            {
                dist = (unsigned int)((long)sleep / 29L); //Entfernung in cm Berechnen
                                                         //in der Anleitung steht zwar uS/58=cm aber das ist bei mir nur die hälfte ?! deshalb /29
                                                         //ist zwar nicht die genaueste methode aber bei nicht all zu großen entfernungen gets cm. genau
                break;
            }
        }
       
        sei(); //Interrupts wieder Aktivieren
       
        LCDClear(); //Nur wenn ein LCD Vorhanden ist
        LCDWriteString("Sleep: "); //lönnen wir die werte hier anzeigen.
        LCDWriteInteger(sleep);
        LCDSetCursor(0,1);
        LCDWriteString("Dist : ");
        LCDWriteInteger(dist);

        //Ansonsten die Daten an die IR schnittstelle senden.
        SerPrint("Sleep: ");
        PrintInt(sleep);
        SerPrint(" Dist: ");
        PrintInt(dist);
        SerPrint("\n");

        Msleep(100); //100Ms warten bis das echo komplett ausklingt
                     //Minimum sind laut beschreibung 50Ms
       
    }

}



Mode 2 (1 Pin)

die Pin sparende Methode.
Hierbei wird der Mode Pin an GND connected und "Echo Output" sowie "Trigger Input" sind am gleichen Pin.

Image

es wird wieder ein minimum 10us Triggersignal gesendet. Danach mussd er Pin auf eingang gestellt werden,
und wie zuvor auf das Echo Signal warten und die Länge messen. Die zeit zwischen Trigger Signal ende und dem echo
Singal beträgt Minimum 700us (Laut beschreibung) währenddessen hat man zeit den Pin umzustellen.

Hierzu wieder ein diagramm:
Image

als Beispiel hab ich dieses mal den "Trigger Input" und den "Echo Output" an PB2 angeschlossen.

Hier der Beispielcode:
Code: Select all
#define F_CPU 8000000

#include <util/delay.h>

#include "asuro.h"
#include "lcd.h"


int main()
{

    Init();
    LCDInit(); //Falls ein LCD Display Vorhanden ist dieses Initialisieren.
   
    while(1)
    {
        unsigned int sleep = 0, dist = 0;

        DDRB  |= ( 1 << PB2 );  //PB0 auf Ausgang Setzen
        PORTB |= ( 1 << PB2 );  //Impuls Starten
        _delay_us(11);          //Wie lange der Impuls ist, ist eigentlich egal,
        //da die Messung erste gestarted wird nachdem der impuls zu ende ist.
        PORTB &= ~( 1 << PB2 ); //Impuls Beenden

        cli(); //Interrupts Deaktivieren

        DDRB &=~ ( 1 << PB2 );  //PB0 auf Eingang Setzen

        _delay_us(600); //600us warten

        while(1)
        {
            _delay_us(1);

            if(PINB & ( 1 << PB2 )) //Wenn das echo Signal kommt...
            {
                sleep++; //zeit zählen
            }else if(sleep > 0)//wenn es zuende ist aus der schleife aussteigen
            {
                dist = (unsigned int)((long)sleep / 29L); //wie vorhin wieder die entfernung berechnen...
                                                     
                break;
            }
        }

        sei(); //Interrupts wieder Aktivieren

        LCDClear(); //Nur wenn ein LCD Vorhanden ist
        LCDWriteString("Sleep: "); //lönnen wir die werte hier anzeigen.
        LCDWriteInteger(sleep);
        LCDSetCursor(0,1);
        LCDWriteString("Dist : ");
        LCDWriteInteger(dist);

        Msleep(100); //Wieder warten bis das modul bereit ist...

    }

}




Anbringen:

Ich habe das US-Modul an eine ASURO Erweiterungsplatine mit
Stiften angeschlossen. Dadurch lässt es sich auch einfach entfernen.

Herzu zwei Bilder (Mode2)
poben.jpg
poben.jpg (36.35 KiB) Viewed 3937 times
punten.jpg
punten.jpg (37.07 KiB) Viewed 3929 times


Nachwort:

Natürlich kann man die Entfernung auch mittels der Schallgeschwindigkeit (~340m/s) berechnen.
Einfach die Zeit mal der Schallgeschwindigkeit durch 2 und schon hat man den genauen wert.
(Auf die Größen beim umrechnen aufpassen (uS/S, m/cm)).

Wie ich von Chris daraufhingeweißen worde ist meine Schleife etwas ungenau da _delay_us(1)
schon eine uS warted aber die restlichen funktionen der Schleife auch noch Rechenzeit benötigen.

chris wrote:Den Zeitmessfehler könnte man durch verschiedene Maßnahmen etwas minimieren:

- Taktzeit etwas grober wählen, also z.B. 20uS ( dann fällt die Ausführungszeit der restlichen Befehle weniger ins Gewicht)
- Oder Befehle innerhalb der while-Schleife minimieren ( 1. auf Empangssignal High warte, 2. Zählen und auf Empfangssignal low warten )
- Einen Timer des Mikrocontrollers verwenden ( was aber etwas kompliziert werden könnte )


Die Sache mit dem Timer gefällt mir am besten wobei ich mich noch nicht mit Timern auseinandergesetzt habe.
Mal sehn vllt. werd ich später dazu etwas Posten (oder jemand anders?).

Das US Modul funktioniert für mich Perferkt! (troz einiger anfänglicher logikfehler).
Es arbeite sehr genau und auch der Modus mit nur einem Pin ist sehr praktisch wenn man noch andere
erweiterungen gleichzeitig anbringen will.

Getested hab ich:

Auf der Höhe des Sensors:

1mm Kabel: 15cm
2-3 mm Kabel: 25cm
6mm Kabel: 35cm


Am Boden liegend (-4,5cm):

3x2cm Lego: ca. 250cm (noch weiter wurde schwer zum messen)
1€ Stehend: ca. 200cm
AABatteie Quer: ca. 50 cm
ASURO Verpackung: Zimmer zu klein ;P


die Entfernung ist immer so weit wie man das Objekt ohne probleme detected kann,
kann aber auch durch kleine fehler von mir beeinträchtigt worden sein.

das Modul ist beeindruckend genau.
hätte mir nicht gedacht dass der über solche entfernung noch so kleine dinge findet.

Ich hoffe ich konnte damit jemanden helfen

freuntliche grüße
Philipp
Flario
 
Posts: 18
Joined: Thu Aug 07, 2008 8:42 pm

Return to robots

Who is online

Users browsing this forum: No registered users and 1 guest

cron