Перейти к содержанию

Гусеничный Робот


Faoxis

Рекомендуемые сообщения

Здравствуйте! Есть гусеничный робот. Спереди на нем стоят два фотодиода. Есть черная линия по которой он должен ездить и поворачивать с помощью ШИМа. У правляющий порт - С. Комбинация PORTC |= 0x82U; заставляет его ехать вперед. Вроде бы ничего сложного, но уже несколько дней не могу понять в чем накосячил. Стоит на месте и не едет. При этому, если без ШИМа подать на ножки напряжения, то начинает ехать прямо как ему и положено.

Я не прошу разбирать весь код (но и не откажусь smile3.gif), но не могли бы вы окинуть свежий взгяд на листинг программы ? Вдруг увидите что-нибудь. Спасибо!

#include <mega32.h>
#include <delay.h>

unsigned char x = 0, y = 0;
unsigned char K = 0;

/////////////////////////////////////////////////////////////////////////////////////////
////////////////////// Объявленияе функций //////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////

//Заставляем робот ехать вперед (настройка портов)
//-----------------------------------------------------------------------------------------
void start();

//Настройка АЦП
//-----------------------------------------------------------------------------------------
void init_adc();

//Чтение из АЦП
//-----------------------------------------------------------------------------------------
unsigned int read_adc(unsigned char Pin_ADC);

//Настройка таймера 0 и 2
//-----------------------------------------------------------------------------------------
void init_timer02();

//Настройка таймера 0 и 2
//-----------------------------------------------------------------------------------------
void init_timer1();

// Вызов прерывания
//-----------------------------------------------------------------------------------------
interrupt [TIM1_OVF] void workplease(void);



/////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Функция main //////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
void main()
{
init_adc();
init_adc();
init_timer02();
init_timer1();

start();

#asm("sei") // Разрешение прерывания
while(1)
 {


 }
}




/////////////////////////////////////////////////////////////////////////////////////////
////////////////////// Описание функций /////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////

// Установка АЦП
//-----------------------------------------------------------------------------------------
void init_adc()
{
ADMUX = 0x40U; //выбираем источник питания АЦП 5v
ADCSRA |= 0x07U; // устанавливаем предделитель 128 (ADPS2, ADPS1, ADPS0), он нужен из-за того, что ацп занимает много тактов
ADCSRA |= 0x80U; // Включаем АЦП (ADEN)
}

// Чтение из АЦП
unsigned int read_adc(unsigned char Pin_ADC)
{
 ADMUX |= Pin_ADC & 0x07U; // Разрешаем менять только 3 последний бита
 delay_us(10); // Задержка на 10 микросек по даташиту
 ADCSRA |= 0x40U; // Выставлем бит ADIF для запуска преобразования
 while((ADCSRA & 0x10) == 0); // Ждем пока оно совершится

 return ADCW; // Возвращем сразу значение старшего и младшего бита АЦП
}

// Порты
//-----------------------------------------------------------------------------------------
void start()
{

DDRD |= 0x80U;
DDRB |= 0x08U;

DDRC |= 0x82U;

PORTC |= 0x82U;
}

// Таймеры 0 и 2
//-----------------------------------------------------------------------------------------
void init_timer02()
{
// Указываем явным образом начальное значение регистра счета
TCNT0 = 0x00U;
TCNT2 = 0x00U;

// Укахываем начальное значение регистра сравнения
		 // Впоследствии оно будет меняться ШИМом
OCR0 = 0x3F;
OCR2 = 0x3F;

// Регистр настройки
TCCR0 = 0x48U; // Fast PWM
TCCR0 |= 0x20U; // Сброс в 0 при прямом счете
TCCR0 |= 0x01U; // Считаем ипульсы кварцевого генератора без предделителя

TCCR2 = 0x48U; // Fast PWM
TCCR2 |= 0x20U; // Сброс в 0 при прямом счете
TCCR2 |= 0x01U; // Считаем ипульсы кварцевого генератора без предделителя

}

// Таймера 1
//-----------------------------------------------------------------------------------------
void init_timer1()
{
TCCR1B |= 0x04U; // устанавливаем режим СТС (сброс по совпадению
TIMSK |= 0x10U; // устанавливаем бит разрешения прерывания 1ого счетчика по совпадению с OCR1A(H и L)

OCR1AH = 0b00000111; // определяем число сравнения. Определяем как часто делать прерывания
OCR1AL = 0b00000000;

TCCR1B |= 0x01U; //запуск таймера без предделителя
}

// Прерывание
//-----------------------------------------------------------------------------------------
interrupt [TIM1_OVF] void workplease(void)
{
x = read_adc(0x00); // Значение с ножки А0
y = read_adc(0x01); // Значение с ножки А1

K = x - y; // Модуль разности

if (x < y)
 OCR0 = OCR0 - K * 10;
else
 OCR2 = OCR2 - K * 10;


}

Изменено пользователем Faoxis
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Здравствуйте, а Вы можете представить принципиальную схему робота?

Распишите, более подробно, желаемую логику работы робота.

На схеме 3 фотодиода. На самом деле их два и они на портах A0, A1.

ab943b340fed.png

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

// Вызов прерывания
//-----------------------------------------------------------------------------------------
interrupt [TIM1_OVF] void workplease(void);



// Прерывание
//-----------------------------------------------------------------------------------------
interrupt [TIM1_OVF] void workplease(void)
{
x = read_adc(0x00); // Значение с ножки А0
y = read_adc(0x01); // Значение с ножки А1

K = x - y; // Модуль разности

if (x < y)
 OCR0 = OCR0 - K * 10;
else
 OCR2 = OCR2 - K * 10;


}

я не особо селен в авирах, но как я понимаю OCR0 и OCR2 скважность ШИМ, размерность регистров char(8бит)

функция read_adc(0x00) - размерность int , x,y - размерность char ??????

Ссылка на комментарий
Поделиться на другие сайты

// Вызов прерывания
//-----------------------------------------------------------------------------------------
interrupt [TIM1_OVF] void workplease(void);



// Прерывание
//-----------------------------------------------------------------------------------------
interrupt [TIM1_OVF] void workplease(void)
{
x = read_adc(0x00); // Значение с ножки А0
y = read_adc(0x01); // Значение с ножки А1

K = x - y; // Модуль разности

if (x < y)
 OCR0 = OCR0 - K * 10;
else
 OCR2 = OCR2 - K * 10;


}

я не особо селен в авирах, но как я понимаю OCR0 и OCR2 скважность ШИМ, размерность регистров char(8бит)

функция read_adc(0x00) - размерность int , x,y - размерность char ??????

Согласен, моя ошибка. Но робот все еще не едет.

Ссылка на комментарий
Поделиться на другие сайты

// Прерывание

//-----------------------------------------------------------------------------------------

interrupt [TIM1_OVF] void workplease(void)

{

..........

}

void init_timer1()

{

TCCR1B |= 0x04U; // устанавливаем режим СТС (сброс по совпадению

TIMSK |= 0x10U; // устанавливаем бит разрешения прерывания 1ого счетчика по совпадению с OCR1A(H и L)

......

}

Ссылка на комментарий
Поделиться на другие сайты

// Прерывание

//-----------------------------------------------------------------------------------------

interrupt [TIM1_OVF] void workplease(void)

{

..........

}

void init_timer1()

{

TCCR1B |= 0x04U; // устанавливаем режим СТС (сброс по совпадению

TIMSK |= 0x10U; // устанавливаем бит разрешения прерывания 1ого счетчика по совпадению с OCR1A(H и L)

......

}

Не понял. У меня же так и написано ? В чем ошибка ?

Ссылка на комментарий
Поделиться на другие сайты

C этой строчкой разобрался:

TCCR1B |= 0x04U; // устанавливаем режим СТС (сброс по совпадению

Поставил:

TCCR1B |= 0x08U; // устанавливаем режим СТС (сброс по совпадению

А вот, что не так с прерыванием и регистром TIMSK не понял.

Ссылка на комментарий
Поделиться на другие сайты

TIM1_OVF это не по совпадению, а по переполнению.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

interrupt [TIM1_COM]

Не цитируйте целиком предыдущее сообщение. Модераторы накажут.

Изменено пользователем Sergey-Ufa
Ссылка на комментарий
Поделиться на другие сайты

interrupt [TIM1_COM]

Сделал так:

interrupt [TIM1_COM] void workplease(void)
{
x = read_adc(0x00); // Значение с ножки А0
y = read_adc(0x01); // Значение с ножки А1

K = x - y; // Модуль разности
if (x < y)
 OCR0 = OCR0 - K * 10;
else
 OCR2 = OCR2 - K * 10;

}

Пишет, что не знает никакого TIM1_COM.

Может interrupt [TIM1_COMPA] ?

Прошил - не едет. Где-то еще косяки :)

Изменено пользователем Faoxis
Ссылка на комментарий
Поделиться на другие сайты

Вы в какой среде пишете? Мое обозначение для CVAVR'а. В этом файле

#include <mega32.h>

должны быть определены через #define все принятые обозначения.

В 4-м посту ИМХО обратил ваше внимание на несоответствие типов данных в том куске, который вы только что привели. Здесь ошибок полно:

K = x - y; // Модуль разности

К определено, как unsigned, а вы можете получить здесь отрицательный результат.

x = read_adc(0x00); // Значение с ножки А0

y = read_adc(0x01); // Значение с ножки А1

read_adc возвращает unsigned int, а присваивает его unsigned char

OCR0 = OCR0 - K * 10;

OCR0 unsigned char, а вы вычитаете из него unsigned int, да еще умноженный на 10

Вобщем эта часть кода может работать совершенно непредсказуемо и требует коренной переделки.

если без ШИМа подать на ножки напряжения, то начинает ехать прямо как ему и положено.

Как вы это напряжение подавали? Я бы посоветовал для проверки схемы временно изменить код так, чтобы на PB3 и PD7 постоянно шла лог.1

Кстати, что происходит в отладчике. Работа ШИМ на всех симуляторах должна просматриваться.

Пишет, что не знает никакого TIM1_COM.

Может interrupt [TIM1_COMPA] ?

Да, это я ошибся.

Изменено пользователем Sergey-Ufa
Ссылка на комментарий
Поделиться на другие сайты

В 4-м посту ИМХО обратил ваше внимание на несоответствие типов данных в том куске, который вы только что привели. Здесь ошибок полно:

K = x - y; // Модуль разности

К определено, как unsigned, а вы можете получить здесь отрицательный результат.

А мне и не надо, чтобы ответ был отрицальный. Ведь если тип unsigned, минус пропадает и получается модуль числа, разве нет ?

x = read_adc(0x00); // Значение с ножки А0

y = read_adc(0x01); // Значение с ножки А1

read_adc возвращает unsigned int, а присваивает его unsigned char

Это я исправил уже. Ниже приведу полный листинг измененной программы, чтобы не путаться.

OCR0 = OCR0 - K * 10;

OCR0 unsigned char, а вы вычитаете из него unsigned int, да еще умноженный на 10

Тип переменной К исправил на char.

Как вы это напряжение подавали? Я бы посоветовал для проверки схемы временно изменить код так, чтобы на PB3 и PD7 постоянно шла лог.1

Пробовал. Едет тупо вперед как и положено.

Компилятор использую Code Vision AVR. Прошиваю через AVR Studio 4. Полный листинг измененной программы:

#include <mega32.h>
#include <delay.h>
unsigned int x = 0, y = 0;
unsigned char K = 0;
/////////////////////////////////////////////////////////////////////////////////////////
////////////////////// Объявленияе функций //////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//Заставляем робот ехать вперед (настройка портов)
//-----------------------------------------------------------------------------------------
void start();
//Настройка АЦП
//-----------------------------------------------------------------------------------------
void init_adc();
//Чтение из АЦП
//-----------------------------------------------------------------------------------------
unsigned int read_adc(unsigned char Pin_ADC);
//Настройка таймера 0 и 2
//-----------------------------------------------------------------------------------------
void init_timer02();
//Настройка таймера 0 и 2
//-----------------------------------------------------------------------------------------
void init_timer1();
// Вызов прерывания
//-----------------------------------------------------------------------------------------
interrupt [TIM1_COMPA] void workplease(void)
{
x = read_adc(0x00); // Значение с ножки А0
y = read_adc(0x01); // Значение с ножки А1

K = x - y; // Модуль разности
if (x < y)
 OCR0 = OCR0 - K * 10;
else
 OCR2 = OCR2 - K * 10;

}


/////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Функция main //////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
void main()
{
init_adc();
init_timer02();
init_timer1();

start();

#asm("sei") // Разрешение прерывания
while(1)
 {


 }
}

/////////////////////////////////////////////////////////////////////////////////////////
////////////////////// Описание функций /////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
// Установка АЦП
//-----------------------------------------------------------------------------------------
void init_adc()
{
ADMUX = 0x40U; //выбираем источник питания АЦП 5v
ADCSRA |= 0x07U; // устанавливаем предделитель 128 (ADPS2, ADPS1, ADPS0), он нужен из-за того, что ацп занимает много тактов
ADCSRA |= 0x80U; // Включаем АЦП (ADEN)
}
// Чтение из АЦП
unsigned int read_adc(unsigned char Pin_ADC)
{
 ADMUX &= 0xF8U;
 ADMUX |= (Pin_ADC & 0x07U); // Разрешаем менять только 3 последний бита
 delay_us(10); // Задержка на 10 микросек по даташиту
 ADCSRA |= 0x40U; // Выставлем бит ADSC для запуска преобразования
 while((ADCSRA & 0x10)  == 0); // Ждем пока оно совершится

 return ADCW; // Возвращем сразу значение старшего и младшего байта АЦП
}

// Порты
//-----------------------------------------------------------------------------------------
void start()
{

DDRD |= 0x80U;
DDRB |= 0x08U;

DDRC |= 0x82U;

PORTC |= 0x82U;
}
// Таймеры 0 и 2
//-----------------------------------------------------------------------------------------
void init_timer02()
{
// Указываем явным образом начальное значение регистра счета
TCNT0 = 0x00U;
TCNT2 = 0x00U;

// Укахываем начальное значение регистра сравнения
		 // Впоследствии оно будет меняться ШИМом
OCR0 = 0x3F;
OCR2 = 0x3F;

// Регистр настройки
TCCR0 = 0x48U; // Fast PWM
TCCR0 |= 0x20U; // Сброс в 0 при прямом счете
TCCR0 |= 0x01U; // Считаем ипульсы кварцевого генератора без предделителя

TCCR2 = 0x48U; // Fast PWM
TCCR2 |= 0x20U; // Сброс в 0 при прямом счете
TCCR2 |= 0x01U; // Считаем ипульсы кварцевого генератора без предделителя

}
// Таймера 1
//-----------------------------------------------------------------------------------------
void init_timer1()
{
TCCR1B |= 0x08U; // устанавливаем режим СТС (сброс по совпадению )
TIMSK |= 0x10U; // устанавливаем бит разрешения прерывания 1ого счетчика по совпадению с OCR1A(H и L)

OCR1AH = 0b00000111; // определяем число сравнения. Определяем как часто делать прерывания
OCR1AL = 0b00000000;

TCCR1B |= 0x04U; //запуск таймера без предделителя
}

Оказывается он заработал, но не полностью. Я распечатал на нескольких листах черную линию с изгибами по которой он должен ехать и положил его на нее. Никакой реакции не было, сейчас я попробовал его подталкнуть и он поехал и даже правильно свернул прямо по линии!.. Но потом снова остановился. Попробовал проделать опыт еще несколько раз. Оказалось, что он начинает ехать только с толчка и не долго, быстро останавливается. И еще иногда его клинит и он резко сам начинает ехать почти перпендикулярно черной линии. Что с ним творится вообще не пойму... Напряжение же подается... Да и если напрямую поддать единицу, то он как порядочный робот едет тупо вперед без всяких толчков.

Изменено пользователем Faoxis
Ссылка на комментарий
Поделиться на другие сайты

void init_timer1();
// Вызов прерывания
//-----------------------------------------------------------------------------------------
interrupt [TIM1_COMPA] void workplease(void)
{
x = read_adc(0x00); // Значение с ножки А0
y = read_adc(0x01); // Значение с ножки А1

K = x - y; // Модуль разности
if (x < y)
 OCR0 = OCR0 - K * 10;
else
 OCR2 = OCR2 - K * 10;

}


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

если тип unsigned, минус пропадает и получается модуль числа, разве нет ?

Нет. В хелпе к CVAVR'у прочитайте про типы данных и посмотрите, чем отличаются unsigned и signed

Тип переменной К исправил на char.

Это положение не изменяет. Еще раз прочитайте про типы данных и диапазоны принимаемых ими значений.

Оказывается он заработал, но не полностью.

Это все следствие абсолютно неправильной части кода, в которой определяются значения ШИМ. Там скорее всего не только ошибки с типами, но может быть и неработоспособный алгоритм, по которому определяется поведение робота. Начните продумывать алгоритм с учетом случайного начального положения робота относительно линии и соответственно случайных данных с АЦП.

Изменено пользователем Sergey-Ufa
Ссылка на комментарий
Поделиться на другие сайты

Да, вы все были правы. Оказалось, что максимальный коэффициент заполнения (проверил опытом) для преодаления роботом собственной массы (чтобы гусеницы крутились не только в воздухе) должен быть 0xD9U.

Новая проблема. )) АЦП почему-то работает сам по себе. Даже если я вытаскиваю провод с фотодиодами, x и y меняются как не в чем не бывало. Не могу понять от чего они зависят и как сделать их зависимыми от фотодиодов.

Изменено пользователем Faoxis
Ссылка на комментарий
Поделиться на другие сайты

А от того, что вы отключили фотодиоды, разве АЦП перестанет работать? Остаются висящие в воздухе входа, на которых из-за высокого входного сопротивления будет находится плавающий потенциал и будет гулять туда-сюда сам по себе.

Ссылка на комментарий
Поделиться на другие сайты

Робот заработал и едет по линии! Правда делает это очень не плавно. Чтобы было плавно надо строить мат. модель и систему управления, чем я заниматься не буду. Для архива выложу последнюю рабочую версию программы:

// I'm not afraid! Go!
#include <mega32.h>
#include <delay.h>
#include <stdio.h>

//#define abs(x) (x>0):x?-x
unsigned int x = 0, y = 0;
unsigned int K = 0;
/////////////////////////////////////////////////////////////////////////////////////////
////////////////////// Объявленияе функций //////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//Заставляем робот ехать вперед (настройка портов)
//-----------------------------------------------------------------------------------------
void start();
//Настройка АЦП 
//-----------------------------------------------------------------------------------------
void init_adc();
//Чтение из АЦП 
//-----------------------------------------------------------------------------------------
unsigned int read_adc(unsigned char Pin_ADC);
//Настройка таймера 0 и 2
//-----------------------------------------------------------------------------------------
void init_timer02();
//Настройка таймера 0 и 2
//-----------------------------------------------------------------------------------------
void init_timer1();
void init_USART();
// Вызов прерывания
//-----------------------------------------------------------------------------------------
interrupt [TIM1_COMPA] void workplease(void);

/////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// Функция main //////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
void main()   
{

   init_USART();
   init_adc();
   init_timer02();
   init_timer1();

   start();

   #asm("sei")  // Разрешение прерывания
   while(1)
 {


 }
}


/////////////////////////////////////////////////////////////////////////////////////////
////////////////////// Описание функций /////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////   
// Установка АЦП
//-----------------------------------------------------------------------------------------
void init_adc()
{
ADMUX = 0x40U;  //выбираем источник питания АЦП 5v
ADCSRA |= 0x07U; // устанавливаем предделитель 128 (ADPS2, ADPS1, ADPS0), он нужен из-за того, что ацп занимает много тактов
ADCSRA |= 0x80U; // Включаем АЦП (ADEN)
}
// Чтение из АЦП
unsigned int read_adc(unsigned char Pin_ADC)
{
    ADMUX &= 0xF8U;
    ADMUX |= (Pin_ADC & 0x07U); // Разрешаем менять только 3 последний бита
    delay_us(10); // Задержка на 10 микросек по даташиту
    ADCSRA |= 0x40U; // Выставлем бит ADSC  для запуска преобразования
    while((ADCSRA & 0x10) == 0); // Ждем пока оно совершится

    return ADCW;  // Возвращем сразу значение старшего и младшего байта АЦП  
}

// Порты
//-----------------------------------------------------------------------------------------
void start()
{

   DDRD |= 0x80U;
   DDRB |= 0x08U;

   DDRC |= 0x82U;

   PORTC |= 0x82U;
}
// Таймеры 0 и 2
//-----------------------------------------------------------------------------------------
void init_timer02()
{
   // Указываем явным образом начальное значение регистра счета
   TCNT0 = 0x00U;
   TCNT2 = 0x00U;   

   // Указываем начальное значение регистра сравнения
		    // Впоследствии оно будет меняться ШИМом
   OCR0 = 0xD9U;   // Минимальное значение при котором он в рабочем режиме
   OCR2 = 0xD9U;   // преодолевает собственную массу


   // Регистры настройки
   TCCR0 = 0x48U; // Fast PWM
   TCCR0 |= 0x20U; // Сброс в 0 при прямом счете
   TCCR0 |= 0x01U; // Считаем ипульсы кварцевого генератора без предделителя

   TCCR2 = 0x48U; // Fast PWM
   TCCR2 |= 0x20U; // Сброс в 0 при прямом счете
   TCCR2 |= 0x01U; // Считаем ипульсы кварцевого генератора без предделителя   

}
// Таймера 1
//-----------------------------------------------------------------------------------------
void init_timer1()
{
   TCCR1B |= 0x08U; // устанавливаем режим СТС (сброс по совпадению )  
   TIMSK |= 0x10U; // устанавливаем бит разрешения прерывания 1ого счетчика по совпадению с OCR1A(H и L)

   OCR1AH = 0x0DU; // определяем число сравнения. Определяем как часто делать прерывания
   OCR1AL = 0x2CU; // Примерно 1 мс

   TCCR1B |= 0x04U; //запуск таймера без предделителя
}

// USART
//-----------------------------------------------------------------------------------------
void init_USART()
{
    // USART initialization
   // Communication Parameters: 8 Data, 1 Stop, No Parity
   // USART Receiver: On
   // USART Transmitter: On
   // USART Mode: Asynchronous
   // USART Baud Rate: 57600
   UCSRA=0x00;
   UCSRB=0x18;
   UCSRC=0x86;
   UBRRH=0x00;
   UBRRL=0x03;
}
// Прерывание
//-----------------------------------------------------------------------------------------
interrupt [TIM1_COMPA] void workplease(void)
{
   x = read_adc(0x00);  // Значение с ножки А0
   y = read_adc(0x01);  // Значение с ножки А1

//   K = abs(x - y); // Модуль разности

   if ((x - y) < -150)
   {  
	  OCR2 = 0;
	  OCR0 = 0xFF;

   }
   else if ((x - y) > 150)	   
   {
	   OCR2 =  0xFF;   
	   OCR0 =  0;
   }			  
   else
   {
    OCR0 = 0xD9U;
    OCR2 = 0xD9U;
   }			
} 

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...