html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Система автоматического подсчета кругов и времени для RC-автомоделей. Часть 2 Протоколы AMB20 и AMBRc

В предыдущей статье я рассказывал о транспондерах, как передается информация от транспондера к декодеру по воздуху. Сегодня я расскажу как передать информацию о номере и время транспондера в компьютер.

Часть информации я подчерпнул здесь и на rctech.net

Соберем схему

А соберем ее на макетке без пайки:

Что нам нужно:1. atmega16 (в моем девайсе стоит atmega32, но суть не меняется)2. Кварц для USART 7.3728Мгц. (В моем девайсе — 16.59Мгц)3. Кварц часовой на 32кгц.4. USB-Rs232 переходник5. Светодиод, кнопочка и резистор.Что бы не париться с прошивкой МК — зальем ему бутлоадер. Отличная статья есть на easyelectronics.ru. Вот именно им я и пользуюсь. Светодиод и кнопочка нужна и для бутлоадера и для основной программы.В нашем декодере есть собственные часы для более точного подсчета времени прохождения круга, а как еще точнее можно сделать? Да ни как, просто передавать номер транспондера и время, когда он был пройден через петлю.Светодиод в бутлоадере будет говорить о том, что бутлоадер загружен. А в основной программе он будет просто моргать, говоря о том, что с часами все в порядке.Кнопочкой мы будем имитировать проезд модели над петлей.USB-Rs232 я взял всеми любимый FT232RL, который требует минимум обвязки. В принципе, подойдет любой USB-RS232 переходник.Схема в протеусе что бы видеть что выдает терминал:

AMB20

Данный протокол можно разделить на две части: Инициализация контроллера и передачи информации о транспондере и времени.
Подсчет времени
Таймер с 32кгц кварцем прерывается раз в секунду.
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
char i;
if (++GlobalS==60)
    {
    if (++GlobalM==60) 
        {
        GlobalH++;
        GlobalM=0;
        }
    GlobalS=0;
    }        
LED=!LED;
}
Я думаю тут все ясно и просто.
Инициализация
Во время инициализации программа открывает СОМ порт и сажает RTS на землю. Выход этого сигнала повесим на INT0 контроллера. По прерыванию отсылаем в компьютер программе @00000001 и сбрасываем время в контроллере:
delay_ms(100);
printf("@00000001\r\n");
GlobalH=0;
GlobalM=0;
GlobalS=0;
GlobalMs=0;
Прохождение метки через петли
Что бы программа понял, что через петлю прошла метка, ей нужно отправить запись вида:@AABBCCDDEEгдеAA — номер транспондера от 1 до 99BB — часыCC — минутыDD — секундыEE — сотые секунды
Trans=1;
MS=GlobalMs_Timer/2.56;
H=GlobalH;
M=GlobalM;
S=GlobalS;
printf("@%02u%02u%02u%02u%02u\r\n",Trans,H,M,S,MS);
К примеру:@0102030405значит, что транспондер с номером 01 прошел петлю на 2 час 3 минуты 4 секунды и 50мс

Все очень даже просто.
Код программы
/*****************************************************
This program was produced by the
CodeWizardAVR V2.05.0 Professional
Automatic Program Generator
© Copyright 1998-2010 Pavel Haiduc, HP InfoTech s.r.l.
http://www.hpinfotech.com

Project : 
Version : 
Date    : 01.04.2013
Author  : 
Company : 
Comments: 


Chip type               : ATmega16
Program type            : Application
AVR Core Clock frequency: 7,372800 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*****************************************************/

#include <mega16.h>


#ifndef RXB8
#define RXB8 1
#endif

#ifndef TXB8
#define TXB8 0
#endif

#ifndef UPE
#define UPE 2
#endif

#ifndef DOR
#define DOR 3
#endif

#ifndef FE
#define FE 4
#endif

#ifndef UDRE
#define UDRE 5
#endif

#ifndef RXC
#define RXC 7
#endif

#define FRAMING_ERROR (1<<FE)
#define PARITY_ERROR (1<<UPE)
#define DATA_OVERRUN (1<<DOR)
#define DATA_REGISTER_EMPTY (1<<UDRE)
#define RX_COMPLETE (1<<RXC)

// USART Receiver buffer
#define RX_BUFFER_SIZE 32
char rx_buffer[RX_BUFFER_SIZE];

#if RX_BUFFER_SIZE <= 256
unsigned char rx_wr_index,rx_rd_index,rx_counter;
#else
unsigned int rx_wr_index,rx_rd_index,rx_counter;
#endif

// This flag is set on USART Receiver buffer overflow
bit rx_buffer_overflow;

// USART Receiver interrupt service routine
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {
   rx_buffer[rx_wr_index++]=data;
#if RX_BUFFER_SIZE == 256
   // special case for receiver buffer size=256
   if (++rx_counter == 0)
      {
#else
   if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
   if (++rx_counter == RX_BUFFER_SIZE)
      {
      rx_counter=0;
#endif
      rx_buffer_overflow=1;
      }
   }
}

#ifndef _DEBUG_TERMINAL_IO_
// Get a character from the USART Receiver buffer
#define _ALTERNATE_GETCHAR_
#pragma used+
char getchar(void)
{
char data;
while (rx_counter==0);
data=rx_buffer[rx_rd_index++];
#if RX_BUFFER_SIZE != 256
if (rx_rd_index == RX_BUFFER_SIZE) rx_rd_index=0;
#endif
#asm("cli")
--rx_counter;
#asm("sei")
return data;
}
#pragma used-
#endif

// USART Transmitter buffer
#define TX_BUFFER_SIZE 256
char tx_buffer[TX_BUFFER_SIZE];

#if TX_BUFFER_SIZE <= 256
unsigned char tx_wr_index,tx_rd_index,tx_counter;
#else
unsigned int tx_wr_index,tx_rd_index,tx_counter;
#endif

// USART Transmitter interrupt service routine
interrupt [USART_TXC] void usart_tx_isr(void)
{
if (tx_counter)
   {
   --tx_counter;
   UDR=tx_buffer[tx_rd_index++];
   }
}

#ifndef _DEBUG_TERMINAL_IO_
// Write a character to the USART Transmitter buffer
#define _ALTERNATE_PUTCHAR_
#pragma used+
void putchar(char c)
{
if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
   {
   tx_buffer[tx_wr_index++]=c;
   ++tx_counter;
   }
else
   UDR=c;
}
#pragma used-
#endif

// Standard Input/Output functions
#include <stdio.h>
#include <delay.h>

char GlobalH,GlobalM,GlobalS,GlobalMs;
float TempFloat;
#define GlobalMs_Timer TCNT2
#define LED PORTD.7 
unsigned int Trans;

// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
delay_ms(100);
printf("@00000001\r\n");
GlobalH=0;
GlobalM=0;
GlobalS=0;
GlobalMs=0;
}


interrupt [EXT_INT1] void ext_int1_isr(void)
{
char H,M,S,MS,Trans;
Trans=1;
MS=GlobalMs_Timer/2.56;
H=GlobalH;
M=GlobalM;
S=GlobalS;
printf("@%02u%02u%02u%02u%02u\r\n",Trans,H,M,S,MS);
}
 
interrupt [EXT_INT2] void ext_int2_isr(void)
{

}

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{

}

interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
char i;
if (++GlobalS==60)
    {
    if (++GlobalM==60) 
        {
        GlobalH++;
        GlobalM=0;
        }
    GlobalS=0;
    }        
LED=!LED;
}

void main(void)
{
PORTA=0x00;
DDRA=0x00;
PORTB=0x00;
DDRB=0x00;
PORTC=0x00;
DDRC=0x00;
PORTD=0b1001100;
DDRD=0x80;

TCCR0=0x05;
TCNT0=0x00;
OCR0=0x00;

ASSR=0x08;
TCCR2=0x05;
TCNT2=0x00;
OCR2=0x00;

GICR|=0xE0;
MCUCR=0x0A;
MCUCSR=0x00;
GIFR=0xE0;

TIMSK=0x41;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=0x00;
UCSRB=0xD8;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x2F;

#asm("sei")

while (1)
      {                                               
      }
}
Недостатки этого протокола очевидны — номер транспондера не больше 99. Рассмотри другой протокол.

AMBRC

Этот протокол требует гораздо больше памяти от МК. Дальше будет ясно почему. Разделить этот протокол можно на три части: инициализация декодера, проход через метку и статус декодера.
Инициализация
Программа шлет декодеру следующий текст "?;0;0;0;" и возврат коретки (clcf) байты — (0x0D,0x0A). Больше ничего интересного в декодер программа не шлет. Поэтому когда на входе имеем байтик 0x0A и ставим флаг инициализации (зачем нужны флаги будет рассказано ниже).
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
   {
   rx_buffer[rx_wr_index++]=data;   
   if (data==0x0A) {TimeToInit=1;}   //Здесь смотрим на байты и ставим флаг
#if RX_BUFFER_SIZE == 256
   // special case for receiver buffer size=256
   if (++rx_counter == 0)
      {
#else
   if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
   if (++rx_counter == RX_BUFFER_SIZE)
      {
      rx_counter=0;
#endif
      rx_buffer_overflow=1;
      }
   }
}
А вот в главном цикле мы инициализируемся:
      if (TimeToInit)
        {
        putchar(1);   
        printf("$\t%i\t7\t0\t1\t1\t",decoderid);
        putchar(0xF8);
        putchar(0xF9);
        printf("\r\n");
        GlobalS=0;
        GlobalMs_Timer=0;    
        sequence_number=0;     
        TimeToInit=0;
        }  
Полного описания протокола я не нашел, нашел только частичный. Запись в СОМ порт будет отправлена вида:
01 24 09 31 30 30 09 37 09 30 09 31 09 31 09 F8 F9 0D 0A
Здесь номер декодера 100. Запись всегда начинается с байта (0x01). Дальше идет знак $. Между каждым значением идет знак Tab (0x09). Все записи заканчиваются возвратом каретки (0x0D 0x0A). Ну и не забываем, что нужно сбросить время и sequence_number. sequence_number — это номер посылки, с каждой посылкой инкрементируется.
Статус декодера
Каждые 4 секунды нам необходимо слать статус. Посылка вида:
# 100 980 0 x06BA
Байты примерно такие:
01 23 09 31 30 30 09 31 30 32 38 09 30 09 78 39 42 39 46 0D 0A
Здесь видно номер декодера, sequence_number, какой то ноль (не знаю зачем он) и контрольная сумма. Контрольная сумма считается в процедуре putchar:
void putchar(char c)
{
while (tx_counter == TX_BUFFER_SIZE);
#asm("cli")
crcwork = (crcTable[(crcwork >> 8) & 0xff] ^ (crcwork << 8) ^ c); //вот здесь мы считаем контрольную сумму
if (tx_counter || ((UCSRA & DATA_REGISTER_EMPTY)==0))
   {
   tx_buffer[tx_wr_index++]=c;
   ++tx_counter;
   }
else
   UDR=c;    
#asm("sei")
}
таблица crcTable подсчитана заранее, она здесь:
Скрытый текст
flash unsigned int crcTable[256]={0,4129,8258,12387,16516,20645,24774,28903,33032,37161,41290,45419,49548,53677,57806,61935,4657,528,12915,8786,21173,17044,29431,25302,37689,33560,45947,41818,54205,50076,62463,58334,9314,13379,1056,5121,25830,29895,17572,21637,42346,46411,34088,38153,58862,62927,50604,54669,13907,9842,5649,1584,30423,26358,22165,18100,46939,42874,38681,34616,63455,59390,55197,51132,18628,22757,26758,30887,2112,6241,10242,14371,51660,55789,59790,63919,35144,39273,43274,47403,23285,19156,31415,27286,6769,2640,14899,10770,56317,52188,64447,60318,39801,35672,47931,43802,27814,31879,19684,23749,11298,15363,3168,7233,60846,64911,52716,56781,44330,48395,36200,40265,32407,28342,24277,20212,15891,11826,7761,3696,65439,61374,57309,53244,48923,44858,40793,36728,37256,33193,45514,41451,53516,49453,61774,57711,4224,161,12482,8419,20484,16421,28742,24679,33721,37784,41979,46042,49981,54044,58239,62302,689,4752,8947,13010,16949,21012,25207,29270,46570,42443,38312,34185,62830,58703,54572,50445,13538,9411,5280,1153,29798,25671,21540,17413,42971,47098,34713,38840,59231,63358,50973,55100,9939,14066,1681,5808,26199,30326,17941,22068,55628,51565,63758,59695,39368,35305,47498,43435,22596,18533,30726,26663,6336,2273,14466,10403,52093,56156,60223,64286,35833,39896,43963,48026,19061,23124,27191,31254,2801,6864,10931,14994,64814,60687,56684,52557,48554,44427,40424,36297,31782,27655,23652,19525,15522,11395,7392,3265,61215,65342,53085,57212,44955,49082,36825,40952,28183,32310,20053,24180,11923,16050,3793,7920};
Сам код для посылки выглядит так:
      if (TimeToSendAmbStatus)
        {
        sequence_number++;                           
        putchar(1);                              
        crcwork=0xFFFF; 
        printf("#\t%i\t%i\t0\t",decoderid,sequence_number);  
        printf("x%02X%02X\r\n",((crcwork>>8)&0xff),(crcwork&0xff));                                                                             
        TimeToSendAmbStatus=0;
        }   
Тут видно как инкрементируется sequece_number. Вначале шлется 0x01, дальше сбрасывается crcwork = 0xFFFF. Шлем часть посылки. В это же время считается контрольная сумма. Следующим действием шлем нашу контрольную сумму и возврат каретки. И так каждые четыре секунды:
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
static char times;

if (++times==4) 
    {       
    TimeToSendAmbStatus=1;  
    times=0;
    }
GlobalS++;     
LED=!LED;
}
Отсылка номера транспондера и времени
Вот здесь начинаются сложности. Преобразовать время и номер транспондера и отправить его в буфер для USART занимает очень много времени (у меня как то было порядка 300мс) и вот поэтому я ничего не отправляю прямо в прерываниях, а оставляю это дело основному циклу. Для того что бы все работало, нужно использовать промежуточный буфер и немного переменных:
#define TranspondersCountMax 20
unsigned long int Transponders[TranspondersCountMax];
unsigned long int TranspondersTimeS[TranspondersCountMax];
unsigned int TranspondersTimeMS[TranspondersCountMax];
char TransponderNeedToSend, TranspondersCountInt, TranspondersCountMain;
Буфер у нас циклический кстати.А вот так мы будем заполнять буфер:
interrupt [EXT_INT1] void ext_int1_isr(void)
{
unsigned long int S;
unsigned int MS;
MS=GlobalMs_Timer*3.90625;
S=GlobalS;
if (TransponderNeedToSend<TranspondersCountMax) 
    {
    TransponderNeedToSend++;    
    Transponders[TranspondersCountInt]=1234567;
    TranspondersTimeS[TranspondersCountInt]=S;
    TranspondersTimeMS[TranspondersCountInt]=MS;                                       
    if (++TranspondersCountInt==TranspondersCountMax) TranspondersCountInt=0;
    }
}
А в основном цикле:
if (TransponderNeedToSend) 
        {                                       
        sequence_number++;                
        putchar(1);
        crcwork=0xFFFF;           
        printf("@\t%i\t%i\t%07lu\t%u.%03u\t130\t119\t2\t",
        decoderid,
        sequence_number,
        Transponders[TranspondersCountMain],
        TranspondersTimeS[TranspondersCountMain],
        TranspondersTimeMS[TranspondersCountMain]);
        //putchar('@');             
        //putchar(9);
        //printf("%i",decoderid);
        //putchar(9);
        //printf("%i",sequence_number);
        //putchar(9);         
        //printf("%07lu",Trans);
        //putchar(9);
        //printf("%u.%03u",S,MS);
        //putchar(9);
        //printf("130");
        //putchar(9);
        //printf("119");
        //putchar(9);
        //printf("2");
        //putchar(9);         
        printf("x%02X%02X\r\n",((crcwork>>8)&0xff),(crcwork&0xff));                                       
        if (++TranspondersCountMain==TranspondersCountMax) TranspondersCountMain=0; 
        TransponderNeedToSend--;
        }
В коментариях указано тоже самое, только проще для понимания, ведь в строчке "@\t%i\t%i\t%07lu\t%u.%03u\t130\t119\t2\t" черт ногу сломит. Отправка единицы, подсчет контрольной суммый — все тоже самое что и в отправке статуса декодера.
@ 100 10 1234567 37.589 130 119 2 xEB94
Как видите, все очень даже просто.

Пару слов о программах подсчета кругов

Есть много программ, совместимых с засечками AMB, но я предпочитаю пользоваться RCM Begginers. Она бесплатная, на русском языке и очень простая. Скачать ее можно тут. В России RCM Ultimate (которая покруче и дорогая) пользуется исключительной популярностью среди моделистов. И AMB20 и AMBRc настраиваются так:

Остальные программы мне не особо понравились.

Вместо заключения

Исходники на CodeVision Avr и схему для протеуса можно взять здесьВидео работы:
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

9

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • habrahabr.ru
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции