-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 13

Thema: Ultraschall Sensor im Selbstbau

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    08.04.2006
    Beiträge
    23

    Ultraschall Sensor im Selbstbau

    Anzeige

    Hallo,
    bin schon seit einiger Zeit hier am mitlesen und basteln. Im Forum kommt ja immer wieder die Frage nach einem Ultraschall Sensor im selbstbau hoch. Im Bereich Wissen gibt es ja die Schaltung von manf. Diese Schaltung hat bei mir im fliegenden Aufbau leider ein paar Probleme gemacht, so dass ich mir eine Alternative überlegt habe.

    Im Anhang (test.png) ist der Schaltplan. Der Chip ist bei mir ein ATTiny2313 nicht wie im Bild der 90S2313.

    Die Funktionsweise ist wie folgt:

    1. Senden von 16 40kHz Impulsen
    2. Schleife im Hauptprogramm gleichzeitig capturen von Interrupts mit Analog Comparator
    3. Berechnen der Entfernung und Ausgabe auf Bar Leds.
    4. 10 ms warten und wieder los

    Auf dem Bild (signals_at_ain0_and_ain1.jpg ) nun ein Scope Bild von den Vorgängen an den Eingängen AIN0 (die "bewegte" Linie) und AIN1 (die gerade Linie). Getriggert wir auf den Start der Pulse.

    Hier habe ich noch eine Frage an die "Analog Gurus" hier im Forum. ca. 1 Periode nach Ende der Pulse kriege ich "Schmutz" im Verstärkerteil des Empfängers, der erste kleine Ausschlag auf dem Bild. Kann mir jemand Tips geben wie ich den Verstärker noch optimieren kann?

    Die Software folgt sobald ich die ein bisschen gesäubert habe.
    Als nächstes soll der Chip noch I2C sprechen um von meiner Masterplatine zum Messen aufgefordert zu werden, damit entfällt dann die Endlosschleife mit den 10ms.

    <<--Edit die kaputten Bilder weg, dafür funktionierende rein -->>
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken test_154.png   signals_at_ain0_and_ain1.jpg  

  2. #2
    Super-Moderator Lebende Robotik Legende Avatar von Manf
    Registriert seit
    30.01.2004
    Ort
    München
    Alter
    63
    Beiträge
    12.222
    Die beiden schwarzen Bilder mit der Größe 377 bytes und 155 bytes können wir später noch entfernen. Kannst Du ein aktuelles einsetzen?

    Eine kleine Störung des Empfängers beim Senden kommt je nach Aufbau schon machmal vor. Man verwendet oft auch eine laufzeitabhängige Empfindlichkeit beim Erkennen des Echos die diesen Effekt mit unterdrückt.

    Häufig werden OPs verwendet, die mit geringen Versorgungspannungen gut auskommen. Wird der TL082 mit 5V und GND betrieben?
    Manfred

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    08.04.2006
    Beiträge
    23
    Hallo Manf,
    Zitat Zitat von Manf
    Die beiden schwarzen Bilder mit der Größe 377 bytes und 155 bytes können wir später noch entfernen. Kannst Du ein aktuelles einsetzen?
    Habe ich erledigt. Gebe zu das ich sonst nicht so in Foren aktiv bin .

    Zitat Zitat von Manf
    Eine kleine Störung des Empfängers beim Senden kommt je nach Aufbau schon machmal vor. Man verwendet oft auch eine laufzeitabhängige Empfindlichkeit beim Erkennen des Echos die diesen Effekt mit unterdrückt.
    Habe mir insofern geholfen, als das ich die Widerstände R10 und R6 unsymetrisch ausgelegt habe (Fehler im Schaltplan, die Werte sind vertauscht). Dadurch ist die Referenzspannung an AIN1 etwas höher als die virtuelle Masse an den OpAmps. Das geht ganz gut, nur nimmt es mir natürlich in der Entfernung (so ab 1m) die Möglichkeit Dinge zu erkennen, da die Signalspannung an der Hürde scheitert.

    Zitat Zitat von Manf
    Häufig werden OPs verwendet, die mit geringen Versorgungspannungen gut auskommen. Wird der TL082 mit 5V und GND betrieben?
    Manfred
    Ja, das sind die Pins 4 und 8 die im Schaltplan zu sehen sind.
    Die Versorgungsleitungen habe ich jetzt beide mal mit 100n direkt am Pin des OpAmps versucht zu beruhigen, aber ohne Erfolg. Anbei noch ein Bild von den Vorgängen. Ich vermute das sich da in der Schaltung eine Rückkopplung aufbaut. Dafür spricht auch die Tatsache, dass die Störung die Frequenz des Sendeimpulses hat.
    Es ist wohl nicht der Empfänger zu sein der den benachbarten Sender "hört", da dafür der "zeitliche Abstand" des Signals zum "räumlichen Abstand" zu gross ist (ich kriege kürzere Laufzeite wenn ich die Hand direkt vor beide Halte).
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken outputvsamplifiedinput.jpg  

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    08.04.2006
    Beiträge
    23

    Die Firmware für den Sensor

    Hallo,
    und hier ist die "Firmware" für den Sensor.

    Kurzer Ablauf:

    Im Hauptprogramm wird eine Endlosschleife durchlaufen. Diese stösst immer wieder den Timer an, der zum einen die Variable timer_ticks hochzählt und die ersten 16 mal auch noch die Signale an PB2 und PB3 invertiert. Gleichzeitig wir der Analoge Komparator eingeschaltet und wartet auf einen höhere Spannung an AIN0 als an AIN1. Ist dies der Fall, so wird der Wert von timer_ticks in echo_ticks gespeichert und das horchen aufgegeben.
    Derzeitig schaut das Hauptprogramm nach einer Festen Zeit (200 ticks) nach ob ein Echo empfangen wurde und berechnet daraus die Entfernung. Diese wird dann effektvoll auf der Barled dargestellt.

    In Zukunft soll die Software die Entfernung noch über I2C oder SPI ausgeben können. SPI hätte den Vorteil, dass der gleiche Stecker zum programmieren und kommunizieren genutzt werden kann.


    Achso ein Thema über das ja auch immer wieder gerne diskutiert wird :
    der Bauteilwert beläuft sich derzeitig grob auf 12€ die Schaltung ist also auch von dieser Seite noch interessant.
    Angehängte Dateien Angehängte Dateien
    • Dateityp: c ultra.c (4,3 KB, 169x aufgerufen)

  5. #5
    Super-Moderator Lebende Robotik Legende Avatar von Manf
    Registriert seit
    30.01.2004
    Ort
    München
    Alter
    63
    Beiträge
    12.222
    der Bauteilwert beläuft sich derzeitig grob auf 12€ die Schaltung ist also auch von dieser Seite noch interessant.
    Nur kurz vorweg:
    Ich habe es nicht ausgeknautscht aber mehr als die Hälfte (ca. 5-6€) sollten die Bauteile hierfür nicht kosten.
    http://www.roboternetz.de/wissen/ind...hall_Interface
    Manfred

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    14.05.2005
    Beiträge
    42
    Hi Leute.

    Ich habe die Schaltung mal nachgebaut, da sie doch recht klar strukturiert ist.

    Das C Programm habe ich nach Bascom adaptiert (siehe Listing.)

    Aber irgendwie habe ich nur Erkennung, wenn ich die beiden US Kapseln zueinanderhalte, dann kann ich auf dem Display eine Entfernung in Abhängigkeit vom Kapselabstand lesen. Wenn ich versuche eine Reflexion zu erhalten (Kapseln parallel), kommt nichts bei raus, obwohl der Untergrund Schall reflektieren müsste.

    Evtl. kann mir ja jemand auf die Sprünge helfen. Könnte ein doofer Fehler sein, habe nur gerade ein Brett vorm Kopf.

    Danke,
    Jango


    Code:
    $regfile = "m32def.dat"
    $crystal = 8000000
    
    ' ... Zeug fürs LCD weggelassen
    
    Declare Sub Us_burst
    Declare Sub Clear_burst
    Declare Sub Enable_ain
    
    Const Soundspeed_per_tick = 4                               ' 4.3mm Both Ways Per Tick
    
    Const Timercount = 100                                      ' $crystal / 80000    Preload For Timer
    Const Bursts = 16                                           ' Number Of Half Periods To "ping"
    
    'Toggle The Ports When Reached 8 000 000 / 80 000 = 100 !!!
     Config Timer0 = Timer , Prescale = 1
     Enable Timer0
     On Timer0 Isr_timer0
     Timer0 = 256 - Timercount
    
    
     Config Aci = On , Compare = Off , Trigger = Rising
     On Aci Isr_aci
    
    
    ''' register unsigned char timer_ticks asm("r10");  /* ticks since start of ping */
     Dim Echo_ticks As Word                                     '      /* ticks when the echo was received */
     Echo_ticks = 0
     Dim Distance As Word
     Distance = 0
    
     Dim Timer_ticks As Word
     Timer_ticks = 0
    
       Config Pind.6 = Output
       Config Pind.7 = Output
       Config Pinb.2 = Input             ' AIN bei MEga32
       Config Pinb.3 = Input            ' AIN bei MEga32
    
       Enable Interrupts
    
    Do
       Echo_ticks = 0
       Timer_ticks = 0
       Call Us_burst
    
       Enable Aci
    
       While Timer_ticks < 500
          $asm
             nop
          $end Asm
       Wend
    
      Call Clear_burst
    
       Distance = Echo_ticks * Soundspeed_per_tick              'in mm
    
      Locate 2 , 1
      Lcd Distance ; " mm   "
    
      Waitms 10
    Loop
    
    End
    
    ' Interrupt Handler for Timer/Counter 0
    Isr_timer0:
       Incr Timer_ticks
    
       If Timer_ticks <= Bursts Then
          Toggle Portd.6
          Toggle Portd.7
       End If
    
       Timer0 = 256 - Timercount
    Return
    
    Sub Us_burst
       Portd.6 = 0                                              'on
       Portd.7 = 1                                              'off
       Timer0 = 256 - Timercount
       Start Timer0
    End Sub
    
    Sub Clear_burst
       'Stop it
       Stop Timer0
       Portd.6 = 0                                              'off
       Portd.7 = 0                                              'off
    End Sub
    
    Isr_aci:
     Echo_ticks = Timer_ticks
     Disable Aci
    Return

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    14.05.2005
    Beiträge
    42
    Hmm. jetzt hab ich auch nochmal das Originalprogramm von teran42 in einen ATTINy2313 geflashed. (Mein Bascom Teil muss ich wohl nochmal überarbeiten, bzw. will ich erstmal sehen, ob meine "Hardware" stimmt, um das als Fehler auszuschliessen.)

    Wenn ich am Transmitter lausche höre ich auch ein leises "Brummen", ich nehme an das sind abwechselnd die 16 Pulse und 200 Wartezyklen, die zusammen für mein Ohr eine Schwingung ergeben.

    Nunja egal eigentlich, auf jedenfall tut sich etwas, nur nicht ganz richtig.

    Ist kein Objekt in Sicht sind alle LEDs aus.
    Nähere ich mich gehen alle an und dann nacheinander 3 Stück aus.
    Dh, bin ich direkt davor, sind noch 4 an.
    Ich nehme an, ich muss noch etwas mit der Empfindlichkeit spielen?!
    Oder liegt das einfach an Störungen, weil alles auf dem Steckbrett aufgebaut ist?!

    Grüße
    Jango

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    08.04.2006
    Beiträge
    23
    Hallo,
    war ein paar Tage offline. Schön das sich ein paar Nachbauten finden. Die Anzahl der LEDs in einer estimmten Entfernung kann in dem Original ab Zeile 80 verändert werden. Wenn da vier LEDs anbleiben frage ich Dich mal ob Du daran gedacht hast den 2313 intern auf 8 Mhz umzustellen? (takt plus teiler). Bis gestern funktionierte das Ganze bei mir auch nur auf einem Steckbrett mit den oben beschriebenen Ungereimtheiten. Ich löte mir das ganze gerade au einer Platine zusammen. In den nächsten Tagen werde ich mal eine Version posten in der der Controller vier Sensoren bedient und die Infos dann per I2C an einen Mastercontroller weitergibt. Mit einem geht das schon.
    An die Basic User folgender Hinweis: - der Interrupt für das Senden ist sehr kritisch. Wenn der Compiler zuviele Anweisungen darin hat, oder die Abfrage zu kompliziert übersetzt, bleiben Euch keine Taktzyklen für das Haupttprogramm. Das ist der Grund warum die timer_ticks als register variable geführt ist. Das spart ca. 4 Zyklen pro Interrupt auf die es ankam. Ich bin weich geworden bevor ich das im Simulator vom AVR Studio gesehen habe.


    Bis denne...

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    14.05.2005
    Beiträge
    42
    Die Fusebits sollten stimmen (8Mhz mit Ponyprog gesetzt und auf "Invertierung" geachtet).
    Vielleicht bekomme ich es ja noch hin, bin auf jedenfall schon sehr zufrieden, im momentanen Zustand könnte der Bot sehen, aha in ca. 20-30 cm kommt was, ich bremse meine Fahrt ab, bzw. starte Ausweichmanöver, und.. In < 10 CM ist was, ich stoppe erstmal.

    Bin schon sehr gespannt auf deine Verwirklichung, dass der 2313 mehrere Sensoren ansteuert (für mich sollen es zwei sein.) und das per I2C an den "Master" abgibt. Dann wäre meine vorläufige Kollisionserkennung schonmal prima.

    Danke,...

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    08.04.2006
    Beiträge
    23
    Hallo,
    hier schonmal die I2C Version mit einem Sensor:
    Code:
    	#define F_CPU 8000000 			//internal Oscillator CKDIV8 not set fuse low 0xXX //TODO
    	#define	TWI_slaveAddress  0x10
    	#define ULTRASONIC_VERSION	"Built " __DATE__ " " __TIME__	
    
    	#define TRANSMIT_DIST01	0x01
    
    	#include <avr/io.h>
    	#include <avr/interrupt.h>
    	#include <util/delay.h>
    	#include "i2c-slave.h"
    
    
    	void us_burst(void);
    	void clear_burst(void);
    	void enable_ain(void);
    
    
    	#define soundspeed_per_tick 4 		//4.3mm both ways per tick
    
    	#define BURSTS 16					// number of half periods to "ping"
    	#define TIMERCOUNT 	F_CPU / 80000	// preload for timer
    										// toggle the ports when reached 8 000 000 / 80 000 = 100 !!!
    
    	register unsigned char timer_ticks asm("r10"); 	/* ticks since start of ping */
    	unsigned char echo_ticks=0; 	 				/* ticks when the echo was received */
    	int distance=0;
    	unsigned char disp;
    
    /* 
     * Main Program
     */
    int main (void){
    
    
    	unsigned char command, active;
    
      	// Own TWI slave address
      	i2c_initialize ( TWI_slaveAddress );
    	sei(); 			// allow ints
    	
    
    	DDRD = 0x7f; 	// everything output
    
    	DDRB |= (1<<PB2);   // Pin 2 Output
    	DDRB |= (1<<PB3);   // Pin 3 Output
    	DDRB &= ~(1<<PB1);// Pin 0 Input
    	DDRB &= ~(1<<PB0);// Pin 0 Input
        PORTD = 0x7f;
    	active = 0;
    	while (1) {
    		if (active==0) {
    			echo_ticks = 0;
    			timer_ticks = 0;
    			us_burst();
        		enable_ain();
    			active = 1;
    		}
    		if ((active==1) & (timer_ticks>240))
    		{		
    			//while ((timer_ticks<240) ){	//arbitrary end but mine can't see further
    				asm("nop"); 
    			clear_burst();
    			active = 0;
    			//distance = echo_ticks * soundspeed_per_tick;
    
    			
    			disp = 0;
    			if (echo_ticks > 110) {
    				disp |= _BV(PD6);
    			}
    			if (echo_ticks > 80) {
    				disp |= _BV(PD5); 
    			}
    			if (echo_ticks > 50) {
    				disp |= _BV(PD4);
    			}	
    			if (echo_ticks > 30) {
    				disp |= _BV(PD3);
    			}	
    			if (echo_ticks > 20) {
    				disp |= _BV(PD2);
    			}	
    			if (echo_ticks > 10) {
    				disp |= _BV(PD1);
    			}	
    			if (echo_ticks > 0) {
    				disp |= _BV(PD0);
    			}	
    			PORTD = disp;			//show it
    			while (i2c_reply_ready()==0) {} //wait to put data
    			if (i2c_reply_ready()){
    			    i2c_rdbuf[0] = echo_ticks;		// put data in I2C buffer
       				i2c_reply_done(1);
    			}
    		}
    
    	
    		if (i2c_message_ready()) {
       			i2c_message_done(); // don't do anything
    		}
    		_delay_ms(3.0);		// wait for next run	
    
    	}
    }
    
    /*
     * Interrupt Handler for Timer/Counter 0 
     */
    ISR (TIMER0_COMPA_vect){
     timer_ticks ++;
     if (timer_ticks <=BURSTS) {	
    	 PORTB ^= ((1<<PB3)|(1<<PB2)); //toggle the Pins
     }
    }
    
    
    
    /*
     * Timer 0:
     */
    void us_burst(void){
    	PORTB |= (_BV(PB3)); 		// ON
    	PORTB &= ~(_BV(PB2)); 		// OFF
     	TCNT0  = 0x00;             	// TIMER0 preload
    
    	TCCR0A &=  ~(_BV(COM0A1));
    	TCCR0A &=  ~(_BV(COM0A0)); 	//Normale mode OC0A disconnected
    	TCCR0A &=  ~(_BV(COM0B1));
    	TCCR0A &=  ~(_BV(COM0B0)); 	//Normale mode OC0B disconnected
    	TCCR0A |=  _BV(WGM01);		// CTC
    	TCCR0B |=  _BV(CS00) ;		// use internal clock 		
    								//no, we do it by hand
    	//_BV(COM00) ;    			// Toggle OC0 on compare match		
    	OCR0A = TIMERCOUNT;			// toggle bei erreichen 8 000 000 / 80 000 = 100 !!!
    	TIMSK  |= _BV(OCIE0A);	 	// enable Output Compare 0 overflow interrupt
    	GTCCR  |= _BV(PSR10);		// clear timer counter prescaler
    	SREG   |= _BV(SREG_I);
    	sei();                		// enable interrupts
    }
    
    void clear_burst(void) {
    	//Stop it
     	TCCR0A &= ~(1<<CS00); // stopt den timer 
     	TCCR0A &= ~(1<<CS01);
     	TCCR0A &= ~(1<<CS02);
     	TIMSK &= ~(1<<OCIE0A);
    	PORTB &= ~(_BV(PB2) | _BV(PB3) ); // OFF
    }
    
    
    /*
     * Analog compare handling
     */
    
    ISR (ANA_COMP_vect) {
    	echo_ticks = timer_ticks;
    	ACSR &= ~(_BV(ACIE)); // turn interupt off, so we don't catch the next wave again	
    }
    
    void enable_ain(void) {
    	ACSR &= ~(_BV(ACIE)); // interupt has to be off whenn switching ACD (see Datasheet) 
    	ACSR &= ~(_BV(ACD));  // zero means turn on Analog comparator
    	ACSR |=  _BV(ACIE) | _BV(ACIS0) | _BV(ACIS1); // interupt enable, trigger on rising edge
    }
    Dazu braucht ihr noch die usi-slave.zip, die es in folgendem Thread zum download gibt (relativ weit unten):
    http://www.mikrocontroller.net/forum/read-4-290268.html

    Abfragen könnt ihr den Sensor dann vom "Hauptrechner" aus wie folgt (Beispiel mit der TWI Library von Peter Fleury):
    Code:
    unsigned char readDist01(void) {
    	unsigned char ret;
    	ret = i2c_start(UltrasonicSlaveAddress+I2C_READ);
        if (ret ==1) {
    		beep();
    	}		
    	else {
    		ret = i2c_readNak();
    	}
    	return ret;
    }
    Comments welcome.

    Anbei noch 2 Bilder von Work in Progress. Ich habe versucht den analogen Teil zusammen mit den Kapseln auf eine Platine outzusourcen. Kann das einer von euch mit klassischen Bauteilen (kein SMD) noch kleiner?

    So long
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken sensor2_154.jpg   sensor_671.jpg  

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •