|
Дополнение для радиоаппаратуры 2.4GHz |
|
|
|
Mar 25 2012, 15:42
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 12-10-11
Пользователь №: 67 694

|
Добрый день. Разрабатываю дополнение для радиоаппаратуры. Вот кое-что написал прошу Ваших комментариев, по алгоритму, организации кода, что можно улучшить. Код /** Задача: Необходимо управлять коллекторным двигателем по средствам ШИМ. Двигатель должен начинать движение с ускорением. Управление должно происходить в зависимости от входных сигналов. Входы: 1. Основной сигнал - прямоугольные импульсы амплитудой 5В, длительностью 20 мС, вехняя часть 1000 - 2000 мкС. 2. Два дискретных датчика - верхнее и нижнее положение. Выходы: Два выхода процессора, их комбинации управляют двигателем. Вверх - по ч.с., вниз против ч.с. |--------------------------------------------------------| | |Стоит |Вверх |Вниз |Зафиксирован | |--------------------------------------------------------| |Выход1 | 0 1 0 1 | |--------------------------------------------------------| |Выход2 | 0 0 1 1 | |--------------------------------------------------------| */
#include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include "AE_Util.h"
#define PULSE_PIN PIND #define PULSE_PPIN PD2 #define PULSE_MID_WIDTH 188// Средняя длительность импульса 1500/8 = 188. #define PULSE_WIDTH_TOLER 5 // Допуск по ширине импульса #define PULSE_QUANTITY 10 // Количество анализируемых импульсов (0...255)
#define MOT_DDR DDRD #define MOT_PORT PORTD #define MOT_PIN1 PD4 #define MOT_PIN2 PD5 #define MOT_UP sbi(MOT_PORT, MOT_PIN1); cbi(MOT_PORT, MOT_PIN2) #define MOT_DOWN cbi(MOT_PORT, MOT_PIN1); sbi(MOT_PORT, MOT_PIN2) #define MOT_STANDBY cbi(MOT_PORT, MOT_PIN1); cbi(MOT_PORT, MOT_PIN2)
#define SEN_PIN PINA #define SEN_UP_PIN PA0 #define SEN_DOWN_PIN PA1
enum {S_NO, S_UP, S_DOWN, S_BOTH};
// Глобальные переменные volatile u8 g_abPUW[PULSE_QUANTITY];// Массив ширин верхней части импульса 1 == 8 мкС. volatile u8 g_bPulNum;
// Глобальные функции u8 Measuring(); u8 GetSen();
ISR(INT0_vect) { if(PULSE_PIN & (1 << PULSE_PPIN)) // Начало верхней части { TCCR0=0x03; TCNT0=0x00; } else // Конец верхней части { if(TCCR0 != 0)// Только если таймер предварительно был запущен, чтобы замеры делать с начала импульса { g_abPUW[g_bPulNum++] = TCNT0; TCCR0=0x00; }
} }
int main(void) { sbi(MOT_DDR, MOT_PIN1); sbi(MOT_DDR, MOT_PIN2);
// Чтобы входные импульсы стабилизировались _delay_ms(500); while(1) { if(GetSen() != S_DOWN) { MOT_DOWN; while(GetSen() != S_DOWN); MOT_STANDBY; } else { u8 bTol, bMid; do { bMid = Measuring(); if(bMid <= PULSE_MID_WIDTH) { bTol = PULSE_MID_WIDTH - bMid; } else { bTol = bMid - PULSE_MID_WIDTH; } }while(bTol < PULSE_WIDTH_TOLER); MOT_UP; while(GetSen() != S_UP); MOT_STANDBY; _delay_ms(500); MOT_DOWN; while(GetSen() != S_DOWN); MOT_STANDBY; } }
return 0; }
u8 Measuring() { g_bPulNum = 0; TCCR0=0x00;// Таймер выключен sbi(GICR, INT0);// Разрешаем прерывание INT0 cbi(MCUCR, ISC01);// Прерывание будет происходить при любом изменении уровня на INT0 sbi(MCUCR, ISC00); sbi(GIFR, INTF0);// Сбросить прерывание INT0 sei();// Глобальное разрешение прерываний
while(g_bPulNum < PULSE_QUANTITY);// Ожидаем необходимое количество импульсов
cli(); cbi(GICR, INT0); TCCR0 = 0x00;
// Вычисляем среднее значение u8 b; int iMid = 0; for(b = 0; b < PULSE_QUANTITY; b++) { iMid += g_abPUW[b]; } iMid /= PULSE_QUANTITY;
return iMid; }
u8 GetSen() { volatile u8 bRes = SEN_PIN & (1 << SEN_DOWN_PIN); bRes |= (SEN_PIN & (1 << SEN_UP_PIN)); return bRes; }
|
|
|
|
|
Mar 25 2012, 17:34
|
Гуру
     
Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295

|
Цитата(e-leks @ Mar 25 2012, 19:42)  Разрабатываю дополнение для радиоаппаратуры. Вот кое-что написал прошу Ваших комментариев, по алгоритму, организации кода, что можно улучшить. Задача: Необходимо управлять коллекторным двигателем по средствам ШИМ. Двигатель должен начинать движение с ускорением. А что, можно начать движение и без ускорения ??? Интересно, и очень. А по делу - невозможно понять, какой совет вам нужен. Изучать чужой код у меня нет ни малейшего желания, особенно после прочтения первых комментариев, содержащих массу самых разных ошибок ...
|
|
|
|
|
Mar 25 2012, 18:22
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 12-10-11
Пользователь №: 67 694

|
Цитата(kovigor @ Mar 25 2012, 21:34)  ...комментариев, содержащих массу самых разных ошибок ... Можно было указать хотя бы каких? Вообще не ожидал такого качества помощи в ветке "для начинающих". Еще раз спасибо!
Сообщение отредактировал e-leks - Mar 25 2012, 18:22
|
|
|
|
|
Mar 26 2012, 11:26
|

Местный
  
Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658

|
Цитата(e-leks @ Mar 25 2012, 18:42)  Вот кое-что написал прошу Ваших комментариев, по алгоритму, организации кода, что можно улучшить. Насчет алгоритма , думаю былобы намного нагляднее еслибы вы нарисовали алг. ввиде блочной схемы , а программа как ее реализация. Кстати, интересно что у вас в "AE_Util.h" ?
|
|
|
|
|
Mar 26 2012, 16:24
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 12-10-11
Пользователь №: 67 694

|
Постараюсь конкретизировать вопросы. 1. С/С++ является аппаратно-независимый языком. Т.е. в основном коде программы не должно быть записей типа "PORTB"? Код #define MOTOR_PORT PORTA volatile uint8_t *pMotorPotr = &PORTB; Какой вариант более предпочтителен? Хотелось бы знать как специалисты соединяют аппарат с программой. Правильно ли я понимаю что в основном это делается чтобы при необходимости поменять камень? Как нибудь так. Код #ifdef KAMEN1 #define MOTOR_PORT PORTA #elif defined KAMEN2 #define MOTOR_PORT PORTB #endif Для AHTOXA: Большое спасибо! Очень трудно разбириться в вопросе без поддержки. Для MaxiMuz: Файл AE_Util.h: Код #ifndef AE_UTIL_H #define AE_UTIL_H
#define cbi(reg, bit) (reg &= ~(1<<bit)) #define sbi(reg, bit) (reg |= (1<<bit)) #define u8 unsigned char
#endif // AE_UTIL_H Здесь мои мизерные утилиты. А алгоритм такой: 1. Измеряем ширину верхних частей определенного кол-ва импульсов. 2. Находим среднее значение. 3. В зависимости от результата, управляем двигателем или не трогаем его. 4. Вообще должен получится самосвал. Если средняя ширина импульса отличается от заданной (кто-то дернул рычаг на передатчике), подаем кузов вверх. 5. Ждем пока отчитается датчик верхнего положения. 6. Пауза. 7. Переполюсовываем движек. 8. Дожидаемся отчета датчика нижнего положения. И опять пункт №1.
Сообщение отредактировал e-leks - Mar 26 2012, 16:27
|
|
|
|
|
Mar 26 2012, 17:59
|
Гуру
     
Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295

|
Цитата(e-leks @ Mar 26 2012, 19:24)  А алгоритм такой: 1. Измеряем ширину верхних частей определенного кол-ва импульсов. 2. Находим среднее значение. 3. В зависимости от результата, управляем двигателем или не трогаем его. 4. Вообще должен получится самосвал. Если средняя ширина импульса отличается от заданной (кто-то дернул рычаг на передатчике), подаем кузов вверх. 5. Ждем пока отчитается датчик верхнего положения. 6. Пауза. 7. Переполюсовываем движек. 8. Дожидаемся отчета датчика нижнего положения. И опять пункт №1. Не знаю, может, я чего-то не понял, но алгоритм тут проще простого - берем отсчеты с линии, на которой вы наблюдаете ваш ШИМ - сигнал (достаточно часто берем), например, в течение секунды. Получаем либо нули, либо единички. Единички приплюсовываем друг к другу в какой-то переменной, нули отбрасываем. Спустя секунду смотрим, сколько принято единичек. Если больше некоторого порога - что-то там включаем или выключаем. P.S. Еще раз. Все ваши сообщения составлены так, что из них крайне трудно что-то понять. Проще говоря, они составлены небрежно. Обижайтесь - не обижайтесь, но это так. Учитесь кратко и четко формулировать свои мысли ...
|
|
|
|
|
Mar 26 2012, 18:23
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 12-10-11
Пользователь №: 67 694

|
Цитата(kovigor @ Mar 26 2012, 21:59)  ...в течение секунды. Получаем либо нули, либо единички. Единички приплюсовываем друг к другу в какой-то переменной, нули отбрасываем. Спустя секунду смотрим, сколько принято единичек. Если больше некоторого порога - что-то там включаем или выключаем... У сигнала ШИМ частота постоянна, это Вам не ЧИМ, соответственно количество единичек за определенный промежуток времени будет одинаково. Алгоритм измерения: 1. В начале верхней части импульса обнуляем регистр таймера и запускаем его. 2. В конце верхней части сохраняем результат регистра таймера в массив и при желании останавливаем таймер и обнуляем регистр. 3. Повторяем предыдущие пункты необходимое количество раз. 4. Берем элементы массива и высчитываем среднее значение. Цитата(kovigor @ Mar 26 2012, 21:59)  ...Все ваши сообщения составлены так, что из них крайне трудно что-то понять... Мне далеко до Вас в плане электронники, поэтому я обращаюсь к Вам. Подскажите как правильно задавать вопросы. Мой вопрос Цитата Хотелось бы знать как специалисты соединяют аппарат с программой? достаточно конкретен?
|
|
|
|
|
Mar 26 2012, 18:33
|
Гуру
     
Группа: Свой
Сообщений: 5 273
Регистрация: 30-03-10
Пользователь №: 56 295

|
Цитата(e-leks @ Mar 26 2012, 21:23)  У сигнала ШИМ частота постоянна, это Вам не ЧИМ, соответственно количество единичек за определенный промежуток времени будет одинаково. Почему это ????? Частота постоянна, это так. Например, 1 КГц. Допустим, у нас есть два сигнала. Первый сигнал - 1000 миллисекундных иголочек, принятых за секунду. Второй сигнал - 1000 200-миллисекундных импульсов, принятых, опять же, за секунду. Применяем к этим наборам импульсов мой алгоритм. Как думаете, для какого из наборов мы получим больше единичек ? И во сколько раз больше мы их получим ?
|
|
|
|
|
Mar 26 2012, 18:34
|

фанат дивана
     
Группа: Свой
Сообщений: 3 387
Регистрация: 9-08-07
Из: Уфа
Пользователь №: 29 684

|
Цитата(e-leks @ Mar 26 2012, 22:24)  1. С/С++ является аппаратно-независимый языком. Т.е. в основном коде программы не должно быть записей типа "PORTB"? Если программа работает с портом, то ей никак не обойтись без записей типа "PORTB" Если планируете применять разные камни, то можете сделать что-то типа файла-описания аппаратной платформы. Например, в файле camen1.h: Код #define MOTOR_UP что-то_там #define MOTOR_DOWN что-то_там , в файле camen2.h то же самое, но для камня-2. И в зависимости от камня, для которого собираете, включайте нужный заголовочный файл. Если замените #define на inline-функции, то это будет ещё красивее. Это уже получится мини-HAL, hardware-abstraction layer (уровень абстрагирования от аппаратуры). ЗЫ. "В начале верхней части импульса" = "по фронту", "в конце верхней части" = "по спаду". Так понятнее.
--------------------
Если бы я знал, что такое электричество...
|
|
|
|
|
Mar 27 2012, 11:45
|

Местный
  
Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658

|
Судя по описанию и самой программе , управление скоростью двигателя не предусмотренно. Цитата Необходимо управлять коллекторным двигателем по средствам ШИМ. Двигатель должен начинать движение с ускорением. Управление должно происходить в зависимости от входных сигналов. по ШИМ только задается вх.воздействие , кот. запускает процесс а к чему "Дополнение для радиоаппаратуры 2.4GHz" вообще непонятно )
|
|
|
|
|
Mar 27 2012, 15:31
|

Местный
  
Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658

|
e-leks не указал каким компилятором пользуется, но кстати у меня подобная конструкция Код while(GetSen() != S_DOWN); в WinAVR с -Оs ключом не работает!
|
|
|
|
|
Mar 27 2012, 16:55
|
Участник

Группа: Участник
Сообщений: 22
Регистрация: 12-10-11
Пользователь №: 67 694

|
Цитата(kovigor @ Mar 26 2012, 22:33)  Допустим, у нас есть два сигнала. Нет же сигнал один, частота 50Гц, ширина верхней части варьируется в зависимости от команды от приемника. Соответственно ваш метод даст 50 единичек вне зависимости от команд (ширины импульса). Цитата(AHTOXA @ Mar 26 2012, 22:34)  Если программа работает с портом, то ей никак не обойтись без записей типа "PORTB"  Если возможно приведите пример Вашего кода касаюшийся обращения к порту. В теле main() запись типа PORTA выглядит как то по-детски? Нет? Цитата(AHTOXA @ Mar 26 2012, 22:34)  Если замените #define на inline-функции, то это будет ещё красивее. Это уже получится мини-HAL... Можно микропример? Цитата(MaxiMuz @ Mar 27 2012, 15:45)  Судя по описанию и самой программе , управление скоростью двигателя не предусмотренно. по ШИМ только задается вх.воздействие , кот. запускает процесс
а к чему "Дополнение для радиоаппаратуры 2.4GHz" вообще непонятно ) Да к сожалению скорость не регулируется, просто пока не подобрал драйвер (аппаратный) для двигателя. А дополнение в следующем. Есть стандартная аппаратура приемник-передатчик управляет моделями в связке с сервомашинками. Приемник имеет несколько каналов с сигналом ШИМ, для сервомашинок это и нужно. Мне понадобилось приделать к модели что-то типа самосвала. Двигатель через пасик вращает ось, по оси ходит ползун. Ползун через шарнир прикреплен к одной стороне кузова. Также на ползуне две пружинки (датчики верхнего и нижнего положения). Все... Цитата(MaxiMuz @ Mar 27 2012, 19:31)  e-leks не указал каким компилятором пользуется, но кстати у меня подобная конструкция Код while(GetSen() != S_DOWN); в WinAVR с -Оs ключом не работает! Компилятор GNU AVR GCC, среда Code::Blocks 10.05. Лично у меня все компилируется без ошибок, даже в Proteus все работает. Уважаемые участники, если это не затрагивает Ваших религиозных убеждений, приведите участки Вашего "реального" кода где вы из main() обращаетесь к портам и регистрам. Удачи.
Сообщение отредактировал e-leks - Mar 27 2012, 17:32
|
|
|
|
|
Mar 27 2012, 18:27
|

Местный
  
Группа: Участник
Сообщений: 253
Регистрация: 15-04-10
Из: Волгоград
Пользователь №: 56 658

|
По поводу Код while(GetSen() != S_DOWN); может быть не совсем то что у вас, покажу на примере: Код while(flag_ms != 2); 32: 80 91 60 00 lds r24, 0x0060 36: 82 30 cpi r24, 0x02; 2 38: 19 f4 brne .+6 ; 0x40 <__SREG__+0x1> TCNT0=10; 3a: 8a e0 ldi r24, 0x0A; 10 3c: 82 bf out 0x32, r24; 50 3e: 08 95 ret 40: ff cf rjmp .-2 ; 0x40 <__SREG__+0x1>
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|