реклама на сайте
подробности

 
 
> Дополнение для радиоаппаратуры 2.4GHz
e-leks
сообщение Mar 25 2012, 15:42
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 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;
}
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
e-leks
сообщение Mar 26 2012, 16:24
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 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
Go to the top of the page
 
+Quote Post
kovigor
сообщение Mar 26 2012, 17:59
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 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. Еще раз. Все ваши сообщения составлены так, что из них крайне трудно что-то понять. Проще говоря, они составлены небрежно. Обижайтесь - не обижайтесь, но это так. Учитесь кратко и четко формулировать свои мысли ...
Go to the top of the page
 
+Quote Post
e-leks
сообщение Mar 26 2012, 18:23
Сообщение #4


Участник
*

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



Цитата(kovigor @ Mar 26 2012, 21:59) *
...в течение секунды. Получаем либо нули, либо единички. Единички приплюсовываем друг к другу в какой-то переменной, нули отбрасываем. Спустя секунду смотрим, сколько принято единичек. Если больше некоторого порога - что-то там включаем или выключаем...

У сигнала ШИМ частота постоянна, это Вам не ЧИМ, соответственно количество единичек за определенный промежуток времени будет одинаково.
Алгоритм измерения:
1. В начале верхней части импульса обнуляем регистр таймера и запускаем его.
2. В конце верхней части сохраняем результат регистра таймера в массив и при желании останавливаем таймер и обнуляем регистр.
3. Повторяем предыдущие пункты необходимое количество раз.
4. Берем элементы массива и высчитываем среднее значение.
Цитата(kovigor @ Mar 26 2012, 21:59) *
...Все ваши сообщения составлены так, что из них крайне трудно что-то понять...

Мне далеко до Вас в плане электронники, поэтому я обращаюсь к Вам. Подскажите как правильно задавать вопросы.
Мой вопрос
Цитата
Хотелось бы знать как специалисты соединяют аппарат с программой?
достаточно конкретен?
Go to the top of the page
 
+Quote Post

Сообщений в этой теме


Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd July 2025 - 04:55
Рейтинг@Mail.ru


Страница сгенерированна за 0.01417 секунд с 7
ELECTRONIX ©2004-2016