Контроллер для кордовых электричек

Маркс

напряжение меняется, но не сильно.
там не столько меняется напряжение, сколько амплитуда и частота


на этих графиках видно. желтые это фазовые сигналы при разных оборотах

надо еще подумать, если пойму откуда лишние импульсы на выходе ОУ,
может получится с ними побороться без программных изысков

VitalikV

Лишние импульсы, могут быть корректировкой. Например регулятор считает, что нужный магнит должен прилететь на следующий зуб через 0,2секунды, а он из-за нагрузки , или перегазовки , прилетает , через 0,4 секунды, и чтобы провернеуть мотор дальше, отправляет дополнительный импульс, который выпадает из алгоритма.

Такое может быть? Или у меня фантазия разыгралась уже?))))

VitalikV

Скетч от простейшего регулятора на Атмеге, может чем поможет …

// Управление бесколлекторным двигателем постоянного тока без датчиков на ATmega48 #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> #include <avr/wdt.h>

// Фаза U(Верхнее плечо) #define UH_ON TCCR2A |= (1 << COM2A1); #define UH_OFF TCCR2A &= ~(1 << COM2A1);

// Фаза U(Нижнее плечо) #define UL_ON PORTB |= (1 << PB5); #define UL_OFF PORTB &= ~(1 << PB5);

// Фаза V(Верхнее плечо) #define VH_ON TCCR1A |= (1 << COM1B1); #define VH_OFF TCCR1A &= ~(1 << COM1B1);

// Фаза V(Нижнее плечо) #define VL_ON PORTB |= (1 << PB4); #define VL_OFF PORTB &= ~(1 << PB4);

// Фаза W(Верхнее плечо) #define WH_ON TCCR1A |= (1 << COM1A1); #define WH_OFF TCCR1A &= ~(1 << COM1A1);

// Фаза W(Нижнее плечо) #define WL_ON PORTB |= (1 << PB0); #define WL_OFF PORTB &= ~(1 << PB0);

#define PHASE_ALL_OFF UH_OFF;UL_OFF;VH_OFF;VL_OFF;WH_OFF;WL_OFF;

#define SENSE_U ADMUX = 0; // Вход обратной ЭДС фазы U #define SENSE_V ADMUX = 1; // Вход обратной ЭДС фазы V #define SENSE_W ADMUX = 2; // Вход обратной ЭДС фазы W

#define SENSE_UVW (ACSR&(1 << ACO)) // Выход компаратора

#define START_PWM 50 // Минимальный ШИМ при запуске

unsigned char position, speed; volatile unsigned char commutation_step = 0; volatile unsigned char rotor_run = 0; // Счетчик импульсов обратной ЭДС

// Крутим по часовой стрелке void commutation(char startup) { switch (commutation_step) { case (0): if(!SENSE_UVW || startup) { UH_ON; // На фазе U - ШИМ WH_OFF; // Фаза W отключена SENSE_W; // Активируем вход фазы W commutation_step = 1; // Следующий шаг TCNT0 = 0; // Обнуляем счетчик T1 } break;

    case (1):
        if(SENSE_UVW || startup)
        {
            VL_OFF; // На фазе V - лог. 0
            WL_ON;  // На Фазе W - лог. 1
            SENSE_V; // Активируем вход фазы V
            commutation_step = 2;
            TCNT0 = 0; // Обнуляем счетчик T1
        }
        break;

    case (2):
        if(!SENSE_UVW || startup)
        {
            UH_OFF; // Фаза U отключена
            VH_ON;  // На фазе V - ШИМ
            SENSE_U; // Активируем вход фазы U
            commutation_step = 3;
            TCNT0 = 0; // Обнуляем счетчик T1
        }
        break;
 
    case (3):
        if(SENSE_UVW || startup)
        {
            UL_ON;  // На фазе U - лог. 1
            WL_OFF; // На Фаза W - лог. 0
            SENSE_W; // Активируем вход фазы W
            commutation_step = 4;
            TCNT0 = 0; // Обнуляем счетчик T1
        }
        break;

    case (4):
        if(!SENSE_UVW || startup)
        {
            VH_OFF;  // Фаза V отключена
            WH_ON;   // На фазе W - ШИМ
            SENSE_V; // Активируем вход фазы V
            commutation_step = 5;
            TCNT0 = 0; // Обнуляем счетчик T1
        }
        break;

    case (5):
        if(SENSE_UVW || startup)
        {
            UL_OFF; // На фазе U - лог. 0
            VL_ON;  // На Фазе V - лог. 1
            SENSE_U; // Активируем вход фазы U
            commutation_step = 0;
            TCNT0 = 0; // Обнуляем счетчик T1
        }
        break;
}

}

// Обработчик прерывания по компаратору. Детектор обратной ЭДС ISR(ANALOG_COMP_vect) { if(rotor_run == 200) commutation(0); rotor_run++; if(rotor_run > 200) { rotor_run = 200; wdt_reset(); } }

// Обработчик прерывания по переполнению Т0. Работа двигателя без сигналов обратной ЭДС ISR(TIMER0_OVF_vect) {
commutation(1); // Если сработало прерывание, есть пропуски импульсов обратной ЭДС rotor_run = 0; // Сбрасываем счетчик импульсов OCR1A = START_PWM; // ШИМ минимум OCR1B = START_PWM; OCR2A = START_PWM; }

int main( void ) { //Watchdog on wdt_enable(WDTO_1S);

// Порты ввода/вывода DDRB = 0xFF; // Порт B - выход PORTB = 0x00;

// T0 - для старта и работы двигателя без сигналов обратной ЭДС TCCR0A = 0; TCCR0B = 0; TCCR0B |= (1 << CS02)|(1 << CS00); // Предделитель на 1024 TIMSK0 |= (1 << TOIE0); // Разрешаем прерывание по переполнению T0

// T1 и T2 ШИМ TCCR1A |= (1 << WGM10); // Режим Fast PWM, 8-bit TCCR1B |= (1 << CS10)|(1 << WGM12); // Без предделителя

TCCR2A |= (1 << COM2A1)| // Сброс вывода OC2A при совпадении (1 << WGM21)|(1 << WGM20); // Режим Fast PWM TCCR2B |= (1 << CS20); // Без предделителя

PHASE_ALL_OFF; // Выключаем все фазы

ADCSRB |= (1 << ACME); // Отрицательный вход компаратора подключаем к выходу мультиплексора АЦП DIDR1 |= (1 << AIN0D);

sei(); // Глобально разрешаем прерывания

while(1) { cli(); position = ADMUX; // Сохраняем позицию ротора в буфер ADMUX = (1 << MUX1)|(1 << MUX0); // Вход ADC3
ADCSRA |= (1 << ADEN) | (1 << ADPS1)|(1 << ADPS0); // Разрешаем АЦП, предделитель на 8 ADCSRA |= (1 << ADSC); // Запускаем преобразование АЦП while(ADCSRA & (1 << ADSC)){}; // Ждем окончания преобразования speed = ADC/4; ADCSRA = 0; // Выключаем АЦП ADCSRB = 0; ADCSRB |= (1 << ACME); // Отрицательный вход компаратора подключаем к выходу мультиплексора АЦП ADMUX = position; sei();

if(speed > START_PWM) { ACSR |= (1 << ACIE); // Разрешаем прерывание от компаратора TIMSK0 |= (1 << TOIE0); // Разрешаем прерывание по переполнению T0

if(rotor_run == 200) { // Если импульсы обратной ЭДС присутствуют, крутим наполную OCR1A = speed; OCR1B = speed; // Изменяем ШИМ OCR2A = speed; } } else { PHASE_ALL_OFF; // Все фазы выключены ACSR &= ~(1 << ACIE); // Запрещаем прерывание от компаратора TIMSK0 &= ~(1 << TOIE0); // Запрещаем прерывание по переполнению T0 }

} }

Маркс

Это маловероятно,
я совсем забыл, что в моей схеме ОУ работает без обратной связи, в режиме насыщения,
с Ку (коэф. усиления) стремящемся к бесконечности (в идеале)
А некоторые ОУ в таком режиме, при стечении обстоятельств в виде совпадения “сигналов на входах”
могут кратковременно “переворачивать” (инвертировать) сигнал на выходе.

как варианты

  • забить и продолжить изыскания в области программной фильтрации ошибочных данных
  • взять другую модель ОУ, не факт что поможет, ЕМНИП в больше или меньшей степени этому подвержены все ОУ
  • добавить обратную связь, для уменьшения Ку, тогда придется сразу прикручивать и формирователь сигнала, потому как на выходе ОУ будет синусоида, что усложнит схему, но совсем не факт, что вылечит )

до весны еще далеко, а процесс на месте не стоит.
кучку деталек и кусок текстолита уже купил, так что новую плату сотворить не долго,
заодно дорисую место для установки модуля гироскопа

Маркс

посвятил пол дня поиску косяка, повторил схема на макетке

и пронаблюдал траблу на осциллографе.

точно такая картинка наблюдается и на прототипе.
такие всплески с еще большей амплитудой проскакивают,
в том числе и на ниспадающем фронте и вызывают срабатывание прерывания.

на макетке купировать удалось, скорее всего не на 100 процентов,
но процентов 85 помех не пропустить на вход МК удалось,
а это значит, что количество ошибочных данных уменьшится на порядок.

Маркс

ну и вот, на выходе имеем первое приближение

Гувернер на базе Ардуино Нано.
Датчик оборотов пока собран на макетной плате.
Требуемые обороты в программе указываются в оборотах/минуту.

В программе установлено две полки оборотов, 2000 и 3000.
После старта гувернеру передается команда на установку оборотов 2000 об/минуту,
через пять секунд посылается новая команда - 3000 об/мин
и еще через пять секунд новая команда - 2000 об/минуту.
Все остальное делает программа.

2000 и 3000 проверял оптическим тахометром, все в пределах погрешности, заложенной в программе,
на данный момент это примерно 6 процентов, но что то мне подсказывает, что дельту можно убрать.

Сегодня поменяю конденсаторы на прототипе кросс платы и она должна заработать так же )

Собственно говоря, регулировка построена на изменении длительности сигнала PWM на входе регулятора,
на основании данных с датчика оборотов мотора, построенного на операционном усилителе.
Датчик фиксирует прохождение обмоток регулятора над магнитами.

Программа сравнивает текущие обороты мотора с требуемыми и в зависимости от результата сравнения
увеличивает или уменьшает длительность импульса сигнала PWM.

Маркс

в общем прототип тоже работает,
осталось причесать программу и можно встраивать в таймер

Маркс

рисую новую версию кросс-платы, появился вопрос.
может стоит на плате разместить кнопку управления и пару светодиод для индикации ?
пока на плате место есть

VitalikV

Пару диодов можно, а вот кнопку, которая со временем начнет звинеть, думаю не надо…

Маркс
VitalikV:

которая со временем начнет звинеть,

это маловероятное явление, звон возможен только в момент нажатия/отпускания,
кроме того, количество срабатываний на отказ у кнопок достаточно велико,
в том числе и у китайских.
у меня Уно уже лет десять работает, кнопку Reset топтал не меренное количество раз )

VitalikV

А зачем эта кнопка нужна на кросс плате? Есть штатная кнопка на ардуино. Так же кнопка нужна на корпусе модели, тем более если модель объемная и мотор под капотом.

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

VitalikV

Кстати на счет акселерометра, может имеет смысл, на кросс плате разместить место для него, вместо кнопки. Акселерометры периодически всплывают в продаже на али.

А вот гироскоп наверное имеет смысл размещать по центру тяжести модели. Хотя и не обязательно.

Маркс
VitalikV:

А зачем эта кнопка нужна на кросс плате? Есть штатная кнопка на ардуино.

штатная - RESET, от нее ни тепло ни холодно, да и закрыта она росс платой получается.
а нужна кнопка управления, старт-стоп ну и мало ли что еще.

VitalikV:

отключения гироскопа, гувернера

режим без GYRO и GOVER будет, как и без одного из них,
но предстоит разобраться с логикой

VitalikV:

Кстати на счет акселерометра

MPU6050 - это 3-х осевой гироскоп + 3-х осевой акселерометр

VitalikV:

А вот гироскоп наверное имеет смысл размещать по центру тяжести модели.

нет никакого смысла, его задача угол тангажа измерять не более того

VitalikV
Маркс:

MPU6050 - это 3-х осевой гироскоп + 3-х осевой акселерометр

Вот тогда было бы не плохо эти функции разделить, при необходимости.

Не факт, что гироскоп в полете заработает правильно… Ибо его еще надо правильно по осям установить. Или в программе пофиг , по какой оси меняется угол?

Маркс
VitalikV:

Или в программе пофиг , по какой оси меняется угол?

до гироскопа еще доберемся, в стоковой версии устройства он должен стоять по осям X/Y/Z.
изменение положения не предусматривалось

VitalikV

А теперь если он распаян на плате таймера, то будет проблема с расположением таймера строго по осям. Не всегда есть место, особенно если это конверсия модели из двс в электро. Поэтому гироскоп наверное лучше отдельно.

Или как то калибровку гироскопа делать…

Маркс

доберусь до гироскопа, буду думать, как вариант выбор при программировании расположения гироскопа.

Маркс

Плату нарисовал, завтра распечатаю, вытравлю и буду паять

Слева внизу SMD кнопка и SMD светодиод пусть будут, справа J3 и J4 место подключения MPU6050

Маркс

У меня есть только две платы Pro Mini
По порядку слева 8MHz 3.3V и вторая 16MHz 5V.

На третью можно внимания не обращать, это гироскоп.

Так вот косяк в том, что платы отличаются расположение контактов A4/A5,
а это выходы для подключения i2c в том числе и гироскопа.
Прототип сделан для установки как раз на первый тип Про Мини,
но 3.3V питания и 8 МГц это не то, что нужно.

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

VitalikV

Сразу под 5В, так как BEC на регуляторе обычно от 5В и выше. Сейчас на более свежих регуляторах уже переключаемый SBEC на 5В/6В. Так что , ардуино, с питанием ниже 5В , не имеет смысла покупать для наших целей.

У меня например, плата Iskra mini, там вообще другое расположение контактов, но есть вход питания до 9В.

Может имеет смысл нарисовать две платы, одну под ардуино про мини 5В, а вторую чисто под шлейф, тем самым не привязываться к конкретному типу Ардуинки, расположению контактов на ней. Распаял шлейф как надо и полетел. И так же это даст возможность размещать кросс плату в любом удобном месте на модели, отдельно от ардуинки.