+7-960-0655211 (Билайн)
+7-987-4207734 (МТС)
интернет-магазин
доставка по России и СНГ
нам уже 10 лет!

Форум

Страницы: 1
atmega8/tsop1736/tamiya, простой робот с ик управлением
 
Начал изучать контроллеры пару месяцев назад. Цель была простой, хотелось научиться делать простых и дешевых роботов. Начал с контроллеров atmega, разобрал даташит, изучил несколько стандартов передачи данных между периферией, очень долго мучал ик связь. В итоге решил, что пора, купил в этом магазине редуктор, гусеницы, и платформу. Робот управляется по ик связи по протоколу daewoo, довольно простой протокол, можно почитать здесь http://users.telenet.be/davshomepage/daewoo.htm

Основные компоненты робота atmega8, tsop1736, драйвер двигателей l293d. Запитал все дело никелево-кадмиевым аккумулятором на 9.6 вольт и емкостью на 700mAh через стабилизатор lm7805. Который почему-то греется очень сильно даже когда моторы не работают. Через некоторое время лмка похоже перегревается и робот совсем перестает ехать.

Код
/*
Распознавание протокола Daewoo
Управление роботом
В коде много различных функции для отладки, я их не убираю, может кому-то пригодятся, 
например есть поддержка uart, запись команд daewoo на eeprom
код для avr studio 4
*/
#define F_CPU 8000000UL
#include <avr/io.h>
#include <avr/interrupt.h> 
#include <util/delay.h> 
#include <stdint.h>
#include <stdio.h>

#include <avr/eeprom.h>
volatile unsigned char num = 0,nump = 0,nump_next = 0,nump_old =0,nump_next_old =0;
volatile unsigned int arr[256];

unsigned int arr_patterns[10][2] = {{0b00010100,0b00000010},{0b00010100,0b00000011},{0b00010100,0b00000001}};

unsigned int time;
char str[100];
int adr = 0x0000;

// Отправка одного символа
void SendByte(char byte)
{
   while(!(UCSRA & (1<<UDRE)));
   UDR=byte;
}

// Отправка строки
void SendStr(char *string)
{
while (*string!='\0')
   {
      SendByte(*string);
      string++;
   }
}
 
ISR(USART_RXC_vect)
{

}

ISR(USART_TXC_vect)
{
   
}

ISR(INT0_vect){
   //num = 0;
   //PORTC |= _BV(PC1);   
}

ISR(INT1_vect){
   
   TCCR1B = (0<<CS12)|(0<<CS11)|(0<<CS10);
   time = TCNT1;
   TCNT1 = 0;
   TCCR1B = (0<<CS12)|(1<<CS11)|(0<<CS10);
   //Если вдруг ваш контроллер имеет большую частоту, чем 8мГц, то нужно time еще разделить на подходящее число
   //например ваш контроллер работает на частоте 12мГц, предделитель у нас 8, значит поделить нужно еще на 1.5
   //т.е. считаем микросекунды.
   arr[num] = time;
   num++;
   PORTC ^= _BV(PC0);
   
}

//Процедура обработки прерывания по Таймеру 1
ISR (TIMER1_COMPA_vect)
{
   TCCR1B = (0<<CS12)|(0<<CS11)|(0<<CS10)|(0<<WGM12); //предделитель clk/1024, режим таймера СТС
   TCNT1=0x00;
   PORTC &= ~_BV(PC0);

   /*if(num != 0){
      
      
      SendStr("=== Start ===\n\r");
      int i;
      for(i = 1; i<num;i++){
         //arr[i] = arr[i]/1.5;
         eeprom_write_word ((uint16_t*) adr, arr[i]);
         adr++;
         //eeprom_write_byte ((unsigned char*) adr, ((unsigned int *)arr[i])[0]);
         adr++;
         sprintf(str,"%u\n\r",arr[i]);
         SendStr(str);
      }
      SendStr("=== End ===\n\r");
   }*/
   
   //num = 0;
   //num = 0;
   //int i;
   //for(i = 0; i<= 254; i++){
   //   arr[i] = 0;
   //}

   /*arr[0] = 0;
   arr[1] = 0;
   arr[2] = 0;*/
   //PORTC &= ~_BV(PC1);
   PORTC |= _BV(PC0);
   //num = 0;

   //PORTC ^= 1<<PC1;   

   /*if (((PORTC&(1<<PC1))>>1)==1) // Проверка состояния переключателя
   {
      PORTC &= ~_BV(PC1);
   }else{
      PORTC |= _BV(PC1); 
   }*/
   //led_2000_1();

}

int main(void)

{

   #define XTAL 8000000L
   #define baudrate 9600L
   #define bauddivider (XTAL/(16*baudrate)-1)
   #define HI(x) ((x)>>8)
   #define LO(x) ((x)& 0xFF)
 
   UBRRL = LO(bauddivider);
   UBRRH = HI(bauddivider);
   UCSRA = 0;
   UCSRB = 1<<RXEN|1<<TXEN|1<<RXCIE|0<<TXCIE;
   UCSRC = 1<<URSEL|1<<UCSZ0|1<<UCSZ1;

   // настраиваем порты ввода-вывода

   
   DDRC |= _BV(PC4);
   DDRC |= _BV(PC3);
   DDRC |= _BV(PC2);
   DDRC |= _BV(PC0);
   DDRC |= _BV(PC1);
   PORTC |= _BV(PC0);

   //Настраиваю int0
   GICR |= ( 1 << INT1 ); 
   GICR |= ( 1 << INT0 );
   //DDRD &= ~_BV(DDD2);
   //PORTD |= _BV(PD2);
   DDRD &= ~_BV(DDD3);
   PORTD |= _BV(PD3);

   //Настраиваем режим сна
   //Idle
   MCUCR |= 1<<SE| 0 << ISC11 | 1 << ISC10;
   //Stand by
   //MCUCR |= 1<<SM2|1<<SM1|0<<SM0|1<<SE;
   //Power-down
   //MCUCR |= 1<<SM1|1<<SE;


   // настраиваем таймер
   TCCR1A = 0x00;
   TCCR1B = (0<<CS12)|(0<<CS11)|(0<<CS10)|(0<<WGM12); //предделитель clk/1024, режим таймера СТС
   TCNT1=0x00;
   //OCR1A=65535; // выбор коэффициента деления 
   TIMSK=(1<<OCIE1A); // разрешение прерывания по совпадению

   asm ("sei"); // Разрешение прерываний



   while (1) {
      //Декодирование адреса и команды по протоколу Daewoo
      nump_old= nump = num-36;
      nump_next_old = nump_next = nump+1;
      unsigned int address = 0,command = 0;
      int i,j,res;
      res = -1;

      if(arr[nump]>7000 && arr[nump]<9000 && arr[nump_next]>3000 && arr[nump_next]<5000){

         //SendStr("Address\n\r");
         for(j = 0;j<8;j++){
            nump = nump+2;
            nump_next = nump + 1;
            /*SendStr("Next byte\n\r");
            sprintf(str,"%u\n\r",arr[nump]);
            SendStr(str);
            sprintf(str,"%u\n\r",arr[nump_next]);
            SendStr(str);*/
            if(arr[nump_next]>1400){
            //if(arr[nump+2]>300){
               address |= 1 << j;
            }
         }
      
         //sprintf(str,"Address %u\n\r",address);
         //SendStr(str);

         nump = nump+2;
         //SendStr("Command\n\r");
         for(j = 0;j<8;j++){
            nump = nump+2;
            nump_next = nump + 1;
            /*SendStr("Next byte\n\r");
            sprintf(str,"%u\n\r",arr[nump]);
            SendStr(str);
            sprintf(str,"%u\n\r",arr[nump_next]);
            SendStr(str);*/
            if(arr[nump_next]>1400){
            //if(arr[nump+2]>300){
               command |= 1 << j;
            }
         }

         //sprintf(str,"Command %u\n\r",command);
         //SendStr(str);

         //SendStr("Serching command.. .\n\r");
         for(i = 0;i<=2;i++){


            if(arr_patterns[i][0] == address && arr_patterns[i][1] == command){
               res = command;
               //sprintf(str,"num_next %u\n\r",nump_next);
               //SendStr(str);
               arr[nump_old]=0;
               arr[nump_next_old]=0;
               //num = 0;
               break;
            }else{
               res = -1;
            }

         }

         //Тут рулим драйвером двигателей в зависимости от нажатых клавиш пульта ДУ.
         if(res == 3){
            PORTC |= _BV(PC2);
            PORTC |= _BV(PC3);
            _delay_ms(500);
            PORTC &= ~_BV(PC2);
            PORTC &= ~_BV(PC3);
         }else if(res == 2){
            PORTC |= _BV(PC3);
            PORTC |= _BV(PC1);
            _delay_ms(500);
            PORTC &= ~_BV(PC1);
            PORTC &= ~_BV(PC3);
         }else if(res == 1){
            PORTC |= _BV(PC4);
            PORTC |= _BV(PC1);
            _delay_ms(500);
            PORTC &= ~_BV(PC1);
            PORTC &= ~_BV(PC4);
         }


         
      }
      //led_2000_1();
      //asm("sleep");
   }; // Бесконечный цикл

   

}


Фотографии показывать не буду, робот вблизи ужасен :)

А видео пожалуйста.

Первый тест:


Собранный робот
Первый тест. Тут видно, что робот движется рывками - просядает напряжение и ресетится контроллер, позже зарядил аккумулятор и робот стал послушней.

Тут я не заметил, что гайки открутились :) и робот слегка умер. В конце вовремя пикнул мультиметр, проконстатировал, что роботу конец :)


А теперь несколько вопросов к знающим.
  • Нормальный звук у редуктора? У меня такое чувство, что собрал я его неправильно.
  • Что может быть с lm7805, почему она себя так ведет? Ток там явно меньше ампера.
  • Намного станет лучше с питанием, если купить или сделать импульсный блок питания? Например такой http://robotshop.su/e-store/catalog/250/914/
Изменено: Костя Лосев - 22.05.2011 23:18:02
 
Цитата
Костя Лосев пишет:
0)Что может быть с lm7805, почему она себя так ведет? Ток там явно меньше ампера. Схему-бы глянуть.
1)Намного станет лучше с питанием, если купить или сделать импульсный блок питания? Например такой http://www.robototehnika.ru/e-store/catalog/250/914/
0)Ток большой(измерить амперметром), бракованная лмка, большая разница напряжений входа и выхода.
1)Лучше buck-or-burst преобразователь - он сам повышает или понижает напругу. Например на mc34063.

По поводу отладочного кода я делаю так
Код
#define DEBUG //в начале файла
<..>
#ifdef DEBUG
 отладочный код
#endif
<..>
#ifdef DEBUG
 отладочный код
#endif

Т.е. чтобы отключить отладку достаточно закомментировать #define DEBUG
Если дебаг не используется, то отладочный код даже не буден скомпилирован.

Если юзается WinAVR(avr-gcc), то вместо asm ("sei" ;) ; можно просто sei(); в студии хз.

Такая конструкция:
TCCR1B = (0<Не очень имеет смысл ибо на выходе 0. ибо x==x|(0<Также, стоит определиться со стилем написания
Код
   PORTC |= _BV(PC0);

   //Настраиваю int0
   GICR |= ( 1 << INT1 );
   GICR |= ( 1 << INT0 ); 

юзать _BV(x) или (1<
Очень интересный код:
Код
if (((PORTC&(1<<PC1))>>1)==1) 

Я помню ещё сложнее что-то придумал, когда осваивал си :)
bit_is_set(PORTC, PC1) и bit_is_clean(PORTC, PC1) для проверки состояния бита.
Если компилятор не знает таких функций, то
Код
#define bit_is_set(sfr, bit) ((sfr&(1<<bit))!=0)
#define bit_is_clear(sfr, bit) ((sfr&(1<<bit))==0)


Не стоит повторять константы без особой необходимости.
Код
   #define F_CPU 8000000UL
   #define XTAL 8000000L 

Куда лучше
Код
   #define F_CPU 8000000UL
   #define XTAL F_CPU 


Тут лучше вместо if юзать switch
Код
         if(res == 3){
            PORTC |= _BV(PC2);
            PORTC |= _BV(PC3);
            _delay_ms(500);
            PORTC &= ~_BV(PC2);
            PORTC &= ~_BV(PC3);
         }else if(res == 2){
            PORTC |= _BV(PC3);
            PORTC |= _BV(PC1);
            _delay_ms(500);
            PORTC &= ~_BV(PC1);
            PORTC &= ~_BV(PC3);
         }else if(res == 1){
            PORTC |= _BV(PC4);
            PORTC |= _BV(PC1);
            _delay_ms(500);
            PORTC &= ~_BV(PC1);
            PORTC &= ~_BV(PC4);
         } 


Код
switch(res){
case 3: 
            PORTC |= _BV(PC2);
            PORTC |= _BV(PC3);
            _delay_ms(500);
            PORTC &= ~_BV(PC2);
            PORTC &= ~_BV(PC3);
break;
case 2:
            PORTC |= _BV(PC3);
            PORTC |= _BV(PC1);
            _delay_ms(500);
            PORTC &= ~_BV(PC1);
            PORTC &= ~_BV(PC3);
break;
<...>
}

printf ИМХО слишком много флеша кушает, чтобы её юзать.
Надеююсь, что я написал поможет в будущем :)
 
во всем вы правы :) код выложил только потому, что его попросили приложить, так бы не выложил, стыдна :)

Про макросы для проверки это ценная инфа спасибо, про дефайн я думал так сделать, но все лень было.

Про лмку так и не понял, у меня мультиметр без силы тока, докуплю еще один и замеряю. Даташит посмотрел по схеме которую вы посоветовали, я давно к ней присматривался, но показалось сложно. И по силе тока я так понял нужно под 2 ампера, потянет?

Тут ди-халт описывает импульсник на такой схеме http://easyelectronics.ru/istochniki-pitaniya-chast-2.html, такой подойдет?
Изменено: Костя Лосев - 23.05.2011 16:58:10
 
Цитата
Костя Лосев пишет:
1)во всем вы правы код выложил только потому, что его попросили приложить, так бы не выложил, стыдна
2)Про макросы для проверки это ценная инфа спасибо, про дефайн я думал так сделать, но все лень было.
3)Про лмку так и не понял, у меня мультиметр без силы тока, докуплю еще один и замеряю. Даташит посмотрел по схеме которую вы посоветовали, я давно к ней присматривался, но показалось сложно. И по силе тока я так понял нужно под 2 ампера, потянет?
4)Тут ди-халт описывает импульсник на такой схеме http://easyelectronics.ru/istochniki-...ast-2.html, такой подойдет?
1) :)
2) Макросы - это вообще очень удобная вещь. Например, можно как-то так #define DEBUG 3 #if (DEBUG>2) ... т.е. не просто дефайнено или нет.
3)Вы двигатели через LMку чтоли запитали?
4)Это просто понижающий. Если напруга не сильно просаживается(т.е. он должен только понижать), то да
 
да через лмку, моторы от редуктора тамия рассчитаны на 3 вольта, но я ее кормлю от стабилизатора, не от батареи 9.6v же их кормить, тогда щетки выгорят моментально.

А где можно почитать про вариант dc-dc который вы предлагаете? Я честно погуглил, почитал различные статьи.
 
Для данных двигателей от Tamia существуют аналоги на Pololu под 6 вольт! ;)

я уже заменил , чтоб на ровном месте не городить огород! :)
Изменено: Vladimir Smolentsev - 24.05.2011 00:42:34
 
в вашем роботе какой-то интересный черный редуктор стоит, что это такое? я таких не видел.
 
Цитата
Костя Лосев пишет:
да через лмку, моторы от редуктора тамия рассчитаны на 3 вольта, но я ее кормлю от стабилизатора, не от батареи 9.6v же их кормить, тогда щетки выгорят моментально.

А где можно почитать про вариант dc-dc который вы предлагаете? Я честно погуглил, почитал различные статьи.
И почему-же lmка греется? :) ЛМка разницу напряжений переводит в тепло. Т.е. вы почти половину потребляемой роботом энергии тратите на тепло. В вашем случае достаточно того dc-dc, который вы показали. Ибо у аккума напряжение почти не проседает. А DC/DC имеет КПД порядка 95%. только с вашим током лучше внешний ключ(транзистор) у DC/DC юзать. А лучше для моторов отдельный DC/DC, а логику питать через lmку, там токи мизерные. Питать микроконтроллер параллельно движкам будет вешать и ребутать контроллер.
При токе через лмку 2 ампера(и падении 4.6, ну примем на 5 ампер) у вас нагрев порядка 10 Ватт, это половина моего паяльника:)

В апноуте на mc34063. Но в вашем случае достаточно понижающего преобразователя.
 
2 Костя

.... это не редуктор это часть вытащена из сломанной купольной видеокамеры наблюдения :D (ответная часть от серво вклеена в пластину оргстекла, перед этим я заметил что часть видеокамеры очень хорошо скользит по оргстеклу , такое хорошее свойство захотелось использовать) ... далее ГОЛОВУ на 2-х сторонний скотч очень удобно размещать на платформах! :)
Изменено: Vladimir Smolentsev - 26.05.2011 21:42:24
 
Цитата
Основные компоненты робота atmega8, tsop1736, драйвер двигателей l293d
a схему можно?
Изменено: Роман Лютко - 02.01.2012 15:14:20
 
классный робот
:):D
Страницы: 1
Читают тему (гостей: 2)