Технический форум по робототехнике.
chinga » 10 окт 2011, 17:45
Здравствуйте!)
вот занимаюсь проектом) цель, собрать устройство, которое находит направление источника звука.
схема работы таков:
звук двигается волной, и первый сигнал принимает PINA.3, затем ждет на какой микрофон попадет следующим, в нашем случае, принял сигнал вторым PINA.1, и программой считаем время до попадания на второй микрофон, и находим t. и что бы найти s,мы находим v*t, где у нас v=300м/с. теперь cos(beta) = s/l, где l мы знаем (расстояние между микрофонами PINA.1 и PINA.0) в моем случае 97см.
ведь должно же так работать?
вот код:
- Код: Выделить всё • Развернуть
/*****************************************************
Chip type : ATmega32
Program type : Application
AVR Core Clock frequency: 16,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 512
*****************************************************/
#include <mega32.h>
#include <stdlib.h>
#include <delay.h>
#include <stdio.h>
#include <math.h>
#include <lcd.h>
#define F_CPU 16000000;
#asm
.equ __lcd_port=0x12; PORTB
#endasm
void main(void){
unsigned char ch1[20];
int t = 0;
float beta1;
float beta;
PORTA=0xFF;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTC = 0x00;
DDRC = 0xFF;
lcd_init(16);
while (1){
if(PINA.3 == 0){
t = 0;
while(PINA.0 != 0 && PINA.1 != 0){}
if(PINA.0 == 0){
PORTC = 0b00000000;
PORTC.1 = 1;
while(PINA.1 != 0){
t++;
delay_us(1);
}
beta1 = 0.3*t/970;
beta = beta1*180.0/3.14;
sprintf( ch1,"beta= %u", beta );
lcd_gotoxy(0,1);
lcd_puts(ch1);
lcd_gotoxy(0,0);
lcd_puts("in the right");
delay_ms(2000);
PORTC = 0b00000000;
lcd_clear();
}
if(PINA.1 == 0){
PORTC = 0b00000000;
PORTC.0 = 1;
while(PINA.0 != 0){
t++;
delay_us(10);
}
beta1 = 0.3*t/970;
beta = beta1*180.0/3.14;
sprintf( ch1,"beta= %u", beta );
lcd_gotoxy(0,1);
lcd_puts(ch1);
lcd_gotoxy(0,0);
lcd_puts("in the left");
delay_ms(2000);
PORTC = 0b00000000;
lcd_clear();
}
lcd_gotoxy(0,0);
lcd_puts("in IF");
}
PORTC = 0b11110000;
lcd_gotoxy(0,0);
lcd_puts("out IF");
}
}
и при тестировании значение k начинает гнать, то есть показывать 20мкс и в следующий раз может показать 100000мкс. бывает даже когда показывает 0. но единственное что правильно работает, это он находит с права сигнал или с слева.
может быть проблема в микросхеме? что мк не успевает делать каун каждый микросекунд. проблема в мк?
- Вложения
-
Vovan » 10 окт 2011, 19:23
Не смотрю код, т.к. иноязычный я, а сообщу лишь те "подводные камни" с которыми столкнулся создавая робота-слухача, неск. лет назад. Во-первых кроме микрофона и кроме фильтра НЧ (на необходимую частоту звука, если это нужно) имеется некий ОУ наверное. Дык вот мне пришлось сначала отстроить прием звука в аналоговой ветке девайса, так, чтобы МК (я строил на 2313) с легкостью распознавал 1 и 0. После того когда это было более менее отстроено, вылез отраженный сигнал от стен и предметов, пришлось снизить чувствительность, а громкость звука повысить... Много времени было потрачено на правильную ориентировку микрофонов, т.к. робот был низкий, а расстояние между "ушами" всего 9см.
Т.о. предлагаю максимум внимания уделить аналоговой части "слуха".
Естесно это не панацея, но сообщаю чисто из собственного опыта, если все что я сообщил ужЕ учтено, извиняюсь...
chinga » 10 окт 2011, 19:33
у меня датчик
http://robozone.su/2008/05/31/sdvoennyj ... -baze.html. со встроенным компаратором.
и выходы беру цифорвые
chinga » 11 окт 2011, 11:24
может микроконтроллер поменять? уже почти год использую
HarryStar » 11 окт 2011, 14:15
У вас какой-то странный алгоритм судя по коду. Или по крайней мере очень непрозрачно написан.
Нужно:
1) Ждать пока на всех 3х входах будет 0 - начальное состояние - тишина.
2) Опрашивать все 3 и ждать пока хотя бы на одном будет 1 - пошел звук
3) Засечь время
4) Опрашивать остальные 2 и ждать пока на них будет 1
5) Записать время на обоих
6) Расчеты и вывод результата
7) Переход к 1)
У вас, скажем прямо, код непонятно написан и четкую логику проследить трудновато.
Добавлено спустя 5 минут 4 секунды:chinga писал(а):может микроконтроллер поменять? уже почти год использую
Думаете протух?
Если программируется и верификация проходит, значит все нормально
Strijar » 11 окт 2011, 17:03
А мне вот не понятно зачем там 3 датчика? Разве 2-х не достаточно? Пришел сначало в правый - ждем пока появиться в левом, пришел в левый - ждем правый. А может проще - записывать звук постоянно через АЦП и делать свертку между двумя каналами?
HarryStar » 11 окт 2011, 18:08
3 датчика для 360 градусов. 2 датчика дают зеркальную неопределенность. Я так понимаю ТС надо именно полный круг.
chinga » 11 окт 2011, 18:28
1) Ждать пока на всех 3х входах будет 0 - начальное состояние - тишина.
2) Опрашивать все 3 и ждать пока хотя бы на одном будет 1 - пошел звук
3) Засечь время
4) Опрашивать остальные 2 и ждать пока на них будет 1
5) Записать время на обоих
6) Расчеты и вывод результата
7) Переход к 1)
1) ждем когда на 1ый поступит сигнал.
когда звук издастся он поступит на первый датчик и и ждем когда поступит на второй или третьи. и когда поступит на третьи затем примется вторым. и мы считываем время с появления сигнала на второй по третьи. и дальше по формуле.
3 датчика для 360 градусов. 2 датчика дают зеркальную неопределенность. Я так понимаю ТС надо именно полный круг.
нет, третьи датчик для себя) можно и убрать. прост когда поступает сигнал на второй и затем на третьи, и на след хлопок будет влиять как с третьего начнется) не знаю объяснил или нет) вообщем поступает на второй и третьи, и когда на третьи поступит он сразу идет на третьи и ждет второй датчик) думаю объяснил)
3 датчика для 360 градусов. 2 датчика дают зеркальную неопределенность. Я так понимаю ТС надо именно полный круг.
это пробовал, но там трудновато будет с точными цифрами. я думаю что так не точно будет) и вычисление там уже другая)
Думаете протух?
Если программируется и верификация проходит, значит все нормально
прост бывает когда глючит)
что бы включить внешний кварц так же фъюзы выставляем?
- Вложения
-
- Fusen
HarryStar » 11 окт 2011, 18:58
chinga писал(а):думаю объяснил
Вообще не объяснили.
У вас явная ошибка в рассуждениях. Попробуйте по моему алгоритму и все получится. Если вам 3й датчик не нужен и достаточно 180 градусов, то соотв алгоритм упрощается:
1) Ждать пока на всех 2х входах будет 0 - начальное состояние - тишина.
2) Опрашивать все 2 и ждать пока хотя бы на одном будет 1 - пошел звук
3) Засечь время
4) Опрашивать оставшийся и ждать пока на нем будет 1
5) Записать время
6) Расчеты и вывод результата
7) Переход к 1)
chinga » 11 окт 2011, 19:59
1) Ждать пока на всех 2х входах будет 0 - начальное состояние - тишина.
2) Опрашивать все 2 и ждать пока хотя бы на одном будет 1 - пошел звук
3) Засечь время
4) Опрашивать оставшийся и ждать пока на нем будет 1
5) Записать время
6) Расчеты и вывод результата
7) Переход к 1)
вот так и у меня работает))точнее мой алгоритм такой
я не смог объяснить))))
Добавлено спустя 3 минуты 8 секунд:а фъюзы правильно выставлены?
space » 11 окт 2011, 20:01
chinga писал(а):что бы включить внешний кварц так же фъюзы выставляем?
Fuse
SUT0 можно убрать
chinga » 12 окт 2011, 11:01
работа с АЦП, он посчитает все и вот так: в начале ацп показывает примерно 20, затем после хлопка 100, ну в этой области, потом и стоит примерно в 90, не снижается значение, и следующий хлопок, и дальше 200 примерно, и затем 190 держит и стоит.. но иногда бывает когда нормально снижается значение. или там типа подтягивающего резистора надо поставить?
Добавлено спустя 35 минут 29 секунд:убрал передний микрофон.
- Код: Выделить всё • Развернуть
/*****************************************************
Chip type : ATmega32
Program type : Application
AVR Core Clock frequency: 16,000000 MHz
Memory model : Small
External RAM size : 0
Data Stack size : 512
*****************************************************/
#include <mega32.h>
#include <stdlib.h>
#include <delay.h>
#include <stdio.h>
#include <math.h>
#define F_CPU 16000000;
#asm
.equ __lcd_port=0x12; PORTB
#endasm
#include <alcd.h>
void main(void){
unsigned char ch1[20];
int k = 0;
int i;
PORTA=0xFF;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTC = 0x00;
DDRC = 0xFF;
lcd_init(16);
lcd_gotoxy(2,0);
lcd_puts("sound test");
delay_ms(1000);
for(i = 0; i<16; i++){
lcd_gotoxy(i,1);
lcd_putchar(0xff);
delay_ms(500);
}
lcd_clear();
lcd_gotoxy(3,0);
lcd_puts("start test");
delay_ms(1000);
lcd_clear();
while (1){
if(PINA.0 == 0){
PORTC = 0b00000000;
PORTC.1 = 1;
k = 0;
lcd_clear();
while(PINA.1 != 0){
k++;
delay_us(1);
}
sprintf( ch1,"k=%u", k );
lcd_gotoxy(0,1);
lcd_puts(ch1);
lcd_gotoxy(0,0);
lcd_puts("in the right");
k = 0;
delay_ms(2000);
PORTC = 0b00000000;
lcd_clear();
}
if(PINA.1 == 0){
PORTC = 0b00000000;
PORTC.0 = 1;
k = 0;
lcd_clear();
while(PINA.0 != 0){
k++;
delay_us(1);
}
sprintf( ch1,"k=%u", k );
lcd_gotoxy(0,1);
lcd_puts(ch1);
lcd_gotoxy(0,0);
lcd_puts("in the left");
k = 0;
delay_ms(2000);
PORTC = 0b00000000;
lcd_clear();
}
if(PINA.1 == 0 && PINA.0 == 0){\
lcd_clear();
lcd_gotoxy(0,1);
lcd_puts("in the center");
delay_ms(3000);
}
PORTC = 0b11110000;
lcd_gotoxy(0,0);
lcd_puts("out IF");
}
}
но результат тот же. прыгает жестко. то 0 показывает время между двумя микрофонами, то 30 или даже выше 1000.
dccharacter » 12 окт 2011, 12:19
От чего питается схема? Имел цирк с АДЦ при питании от USB - там сетевая помеха все рушит. Для таких точных измерений надо делать опторазвязанное питание.
chinga » 12 окт 2011, 12:32
питается от аккума 12В. через стабилизатор крен на 5.
Radist » 12 окт 2011, 13:37
Может быть я чего-то не понимаю. Известно лишь разница по времени прихода звука. А чтобы узнать где находится источник звука - надо знать два пути прохождения звука. Звук от источника распространяется во все стороны, доходит до первого микрофона - он включает таймер, потом до второго - он выключает таймер. У меня вот какое сомнение: достаточно ли этой информации, чтобы вычислить координаты источника звука? В качестве примера: источник звука находится точно между ушами на любом расстоянии от базы. Дельта равна нулю. И где источник? Но может быть это только для середины работает? Интуиция говорит что нельзя, а доказать выкладками математическими пока не могу.