реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> как правильно получать цифровой сигнал
Zike
сообщение May 31 2007, 05:51
Сообщение #1





Группа: Новичок
Сообщений: 7
Регистрация: 22-12-05
Пользователь №: 12 550



Вопрос такой: Как правильно получать цифровой сигнал?

есть:
передатчик (Atmega8 + лазер), при нажатии на кнопку микроконтроллер посылает 5 раз (можно и больше) повторяющийся 13 битный код Баркера (1111100110101), длина импульсов 1 и 0 одинакова (1 милисекунда).

аналогавая часть приемника (фотодиод и операционник) выдает через конденcатор и транзистор на ножку микроконтроллера (тоже Atmega8) кратковременные импульсы (единиц) соответствующие переходу от 0 к 1 передатчика, т.е. приемник (микроконтроллер знает когда начинается 1 у передатчика)

Теперь вопрос такой как правильно получать данные, т.е. в буфере микроконтроллера должен появится код такойже как и в передатчике (1111100110101)

ставить прерывание на ножку по смене уровня, а потом считать время по 1 милисекунде и смотреть состояние что там далее за бит идет и так далее?

или не используя прерывание по смене уровня на ноге а тупо сканировать ногу с паузой в 1 милисекунду?

Как подобные системы вообще реализуются? я новичек в электронике и программировании микроконтроллеров, поэтому если что не так сформулировал, поправте, буду учиться...
Go to the top of the page
 
+Quote Post
Doka
сообщение May 31 2007, 06:14
Сообщение #2


Electrical Engineer
******

Группа: СуперМодераторы
Сообщений: 2 163
Регистрация: 4-10-04
Пользователь №: 778



тему переношу в "В помощь начинающему"


--------------------
Блог iDoka.ru
CV linkedin.com/in/iDoka
Sources github.com/iDoka


Never stop thinking...........................
Go to the top of the page
 
+Quote Post
Laksus
сообщение May 31 2007, 08:25
Сообщение #3


Частый гость
**

Группа: Участник
Сообщений: 146
Регистрация: 16-05-05
Пользователь №: 5 069



Цитата
...
длина импульсов 1 и 0 одинакова (1 милисекунда).
...
ставить прерывание на ножку по смене уровня, а потом считать время по 1 милисекунде и смотреть состояние что там далее за бит идет и так далее?

или не используя прерывание по смене уровня на ноге а тупо сканировать ногу с паузой в 1 милисекунду?

Если у Вас длина импульса равна 1 мсек, то после прерывания надо проверять через 0.5мсек,
чтобы проверить середину импульса.
То же и при "тупом" опросе, период опроса должен быть по крайней мере в 2 раза короче
чем длина импульса
(теорема Котельникова
http://ru.wikipedia.org/wiki/Теорема_отсчё...икова_—_Шеннона
)

Цитата
Как подобные системы вообще реализуются? я новичек в электронике и программировании микроконтроллеров, поэтому если что не так сформулировал, поправте, буду учиться...

А почитайте в даташите на какую нибудь атмегу как работает UART.
_____________
Александр
Go to the top of the page
 
+Quote Post
-=Женек=-
сообщение Jun 2 2007, 02:50
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 559
Регистрация: 6-09-06
Пользователь №: 20 131



Zike

Вот как это делал я:
Цитата
#define MUX_STATE (0 << REFS1)|(0 << REFS0)
#define ADC_STATE (1 << ADEN)|(1 << ADPS2)|(1 << ADPS1)|(1 <<ADPS0)
//#ifdef F_CPU
#define F_CPU 16000000UL
//#endif

int pps=0;

unsigned char h=0,m=0,sec=0;
glcdRect_t r;
int x, _x,i,j, crc;
unsigned byte;

int ReadADC(unsigned char ChannelNum)
{
ADMUX = ChannelNum | MUX_STATE;
ADCSRA = (1 << ADSC) | ADC_STATE;
while ( (ADCSRA & ( 1 << ADIF))==0);
ADCSRA|=0x10;
return ADCW;
}


beep()
{
for (int i=0;i<100;i++)
{
PORTD |= _BV(PD2);
_delay_ms(1);
PORTD &= ~_BV(PD2);
_delay_ms(1);
}
}

void tri_beep()
{
beep();
_delay_ms(100);
beep();
_delay_ms(100);
beep();
_delay_ms(100);
}

void timer_init(void)
{

TCNT1H=TCNT1L=0;
OCR1A=15624;
TCCR1A=0;
TCCR1B=(1<<WGM12)|(1<<CS12)|(1<<CS10); //clk/64 1000000/64=15625
TIMSK=(1<<OCIE1A);


}

SIGNAL(SIG_OUTPUT_COMPARE1A)

{
char *text;
// beep();
sprintf(text," %i ",pps);
glcdMoveTo(10,10);
glcdPrint(text, 0);

_x=x;
PORTD |=_BV(PD0);
x=ReadADC(0);
PORTD &=~_BV(PD0);
if (x != _x)
{
sprintf(text," %i ",x);
glcdMoveTo(50,153);
glcdPrint(text, 0);
if (x>_x) glcdFillRect(105,170,125,170-x/5,BLUE);
if (x<_x) glcdFillRect(105,10,125,170-x/5,WHITE);
}

pps=0;

}

send_pack(unsigned int byte)
{
int x;
unsigned char i,_bit;
unsigned int recieved_byte;
recieved_byte=0x00;

for (i=0;i<16;i++)
{
PORTD |=((byte >> i) & 0x01)<<0;
x=ReadADC(0);
if (x>50) recieved_byte |= 1 << i;
if (x<51) recieved_byte |= 0 << i;
PORTC=recieved_byte;
PORTD &= ~_BV(PD0);
}

if (recieved_byte==byte) return 1;
return 0;
}



void main()
{
char *text;

#define cnt 1
#ifndef USE_AUTOINIT
glcdDisplayInit(); // в дальнейшем проверить запуск без этой строки...
#endif

DDRD = 0xFF;
DDRC = 0xFF;
ADCSRA=0x87;

glcdClearScreen(1);
glcdFillRect(0,0,132,176,RGB(0x66,0x66,0x66));
glcdSetFgColor(BLUE);
glcdSetFrColor(BLUE);
glcdSetBkColor(WHITE);
glcdSetOrientation(3);
glcdSelectFont(f9x14, 0); // font is stored in FLASH, demontrate read callback
glcdMoveTo(10,10);



timer_init();
asm("sei");
while (1)
{
asm("cli");
pps++;

crc=send_pack((((unsigned)rand())<<1)+rand());

if (crc==1) PORTD |= _BV(PD7);
if (crc==0)
{
PORTD |= _BV(PD5);
// tri_beep();
}
asm("sei");
}


/*

PORTD |= _BV(PD0);
_x=x;
x=ReadADC(0);
if (x != _x)
{
sprintf(text," %i ",x);
glcdMoveTo(50,153);
glcdPrint(text, 0);
if (x>_x) glcdFillRect(105,170,125,170-x/5,BLUE);
if (x<_x) glcdFillRect(105,10,125,170-x/5,WHITE);
}

*/





}



Правда, оговорюсь, передавал и принимал сигнал один и тот же контроллер, и передавал я побитно, а анализировал побайтно.

Но посмотрите, может быть поможет.
Go to the top of the page
 
+Quote Post
el34
сообщение Jun 2 2007, 08:12
Сообщение #5


инженер
****

Группа: Свой
Сообщений: 717
Регистрация: 4-03-05
Пользователь №: 3 064



для программной реализации (без прерываний по ноге от приемника) делают прерывания от таймера минимум в три раза чаще , чем длительность бита и потом принимают решение
два-из-трех для улучшения помехозащищенности

вы не сказали как включен операционник ...
и если он без гистерезиса, то вы можете получить множественные прерывания в моменты перехода
если используете прерывания по фронту/спаду старт. импульса
и тогда все не оч. хорошо
(точнее плохо).....


--------------------
........поужинали вяленой рыбой, кот лежал рядом, молчали.......
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 2 2007, 08:23
Сообщение #6


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Цитата(Zike @ May 31 2007, 08:51) *
кратковременные импульсы (единиц) соответствующие переходу от 0 к 1 передатчика, т.е. приемник (микроконтроллер знает когда начинается 1 у передатчика)
Боюсь что тут у вас системная ошибка - вы не отличите 1111 от 1000. Если у вас нет возможности на другую ножку завести импульсы при переходе от 1 к 0, то при модуляции лучше применить манчестерское кодирование.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
el34
сообщение Jun 2 2007, 08:45
Сообщение #7


инженер
****

Группа: Свой
Сообщений: 717
Регистрация: 4-03-05
Пользователь №: 3 064



добавлю : если вы все же примете бинарную последовательность ,
то затем надо-бы применить либо согласованную фильтрацию либо коррелятор,
плюс к ним еще пороговое устройство :
я думаю не зря же передают сигналы кодом Баркера....
ведь можно было б и один раз лазером моргнуть....
понимаете куда клоню?


--------------------
........поужинали вяленой рыбой, кот лежал рядом, молчали.......
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 26th July 2025 - 04:33
Рейтинг@Mail.ru


Страница сгенерированна за 0.01404 секунд с 7
ELECTRONIX ©2004-2016