Начал изучать контроллеры пару месяцев назад. Цель была простой, хотелось научиться делать простых и дешевых роботов. Начал с контроллеров 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, почему она себя так ведет? Ток там явно меньше ампера.
Костя Лосев пишет: 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<Также, стоит определиться со стилем написания
Я помню ещё сложнее что-то придумал, когда осваивал си bit_is_set(PORTC, PC1) и bit_is_clean(PORTC, PC1) для проверки состояния бита. Если компилятор не знает таких функций, то
во всем вы правы код выложил только потому, что его попросили приложить, так бы не выложил, стыдна
Про макросы для проверки это ценная инфа спасибо, про дефайн я думал так сделать, но все лень было.
Про лмку так и не понял, у меня мультиметр без силы тока, докуплю еще один и замеряю. Даташит посмотрел по схеме которую вы посоветовали, я давно к ней присматривался, но показалось сложно. И по силе тока я так понял нужно под 2 ампера, потянет?
Костя Лосев пишет: 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 который вы предлагаете? Я честно погуглил, почитал различные статьи.
Костя Лосев пишет: да через лмку, моторы от редуктора тамия рассчитаны на 3 вольта, но я ее кормлю от стабилизатора, не от батареи 9.6v же их кормить, тогда щетки выгорят моментально.
А где можно почитать про вариант dc-dc который вы предлагаете? Я честно погуглил, почитал различные статьи.
И почему-же lmка греется? ЛМка разницу напряжений переводит в тепло. Т.е. вы почти половину потребляемой роботом энергии тратите на тепло. В вашем случае достаточно того dc-dc, который вы показали. Ибо у аккума напряжение почти не проседает. А DC/DC имеет КПД порядка 95%. только с вашим током лучше внешний ключ(транзистор) у DC/DC юзать. А лучше для моторов отдельный DC/DC, а логику питать через lmку, там токи мизерные. Питать микроконтроллер параллельно движкам будет вешать и ребутать контроллер. При токе через лмку 2 ампера(и падении 4.6, ну примем на 5 ампер) у вас нагрев порядка 10 Ватт, это половина моего паяльника:)
В апноуте на mc34063. Но в вашем случае достаточно понижающего преобразователя.
.... это не редуктор это часть вытащена из сломанной купольной видеокамеры наблюдения (ответная часть от серво вклеена в пластину оргстекла, перед этим я заметил что часть видеокамеры очень хорошо скользит по оргстеклу , такое хорошее свойство захотелось использовать) ... далее ГОЛОВУ на 2-х сторонний скотч очень удобно размещать на платформах!