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

Slash

Участник
  • Постов

    198
  • Зарегистрирован

  • Посещение

Репутация

0 Обычный

Информация о Slash

  • Звание
    Частый гость
    Частый гость

Контакты

  • Сайт
    Array
  • ICQ
    Array

Информация

  • Город
    Array

Посетители профиля

4 105 просмотров профиля
  1. Удерживать мне не нужно, в покое на вал нет нагрузки. Макс скорость вращения вала - 5 об/секунду. Скорее всего будет редуктор. Пусть мотор 3000 об/мин. Редуктор 1:10. Питание - 220 В / 1 фаза. Про момент точно не скажу, но в текущей реализации двигатель справляется. Если будет не хватать, можно взять двигатель мощнее. А если ухудшить точность позиционирования до +/- 3 градусов?
  2. Добрый день. Какое железо нужно, чтобы повернуть вал асинхронного электродвигателя (трехфазный 370 Вт) на 1 оборот? Попасть нужно в ту же позицию +/- 1 градус. Чтобы ошибка не накапливалась, т.е. через 10 тыс оборотов было +/- 1 градус. Не зависеть от нагрузки на валу (в разумных пределах конечно, в пределах возможности двигателя). Можно было установить и менять ускорение разгона и торможения (независимо) и скорость вращения. Так понимаю, для это нужен частотный преобразователь. Какими функциями он должен обладать, чтобы это все можно было решить? Нужен энкодер я так понимаю, чтобы частотник знал в какой сейчас позиции двигатель? Управлять частотником предполагается через Raspberry Pi, по интерфейсу, который есть в частотнике (пусть rs-485). но это не принципиально.
  3. Как можно подтвердить опыт в разработке по методологиям?
  4. Расскажите, пожалуйста, если есть какая-то информация. Если я правильно понимаю, то речь идет о предприятии, где делают беспилотник имени рода хищных птиц из подсемейства канюков семейства ястребиных )) Видел статью, где были приведены суммы госзаказов за 2015, 2016 год. Двукратный рост. Не думаю, что есть предпосылки, к тому, что рост не сохраниться. Кому-то эти заказы надо делать. На предприятии (вроде бы) около 500 разработчиков. 10% рост коллектива при таком росте заказов - это не много(на XX.ру висят где-то 40 вакансий разработчиков).
  5. Выпаяйте родной разъем USB и впаяйте гребенку.
  6. Здравствуйте! Сделана плата на основе микроконтроллера. Нужно одновременно поддерживать несколько версий встроенного ПО. Помимо логики работы, версии отличаются инициализацией периферийных модулей. Если с логикой работы более-менее приемлемо получается директивами условной компиляции, то с разными версиями инициализации периферийных модулей не знаю что делать. Если модули обобщать, чтобы они были более гибкими, и в разных версиях просто настраивались по-разному, боюсь, модуль сильно разрастется. И не всегда получается хорошо абстрагировать модуль, чтобы охватывались все варианты. Пока остановился на такой реализации периферии: класс с минимально-необходимым интерфейсом. class Uart1 { public: enum Baudrate { ... }; Uart1(); void setBaudrate(Baudrate b); void write(uint8_t * data, uint32_t size); ... private: DMA_HandleTypeDef mDmaTx; UART_HandleTypeDef mUart; ... }; Реализация по месту, без особых обобщений. void Uart1::write(uint8_t * data, uint32_t size) { __HAL_DMA_DISABLE(&mDmaTx); mUart.Instance->CR3 &= ~USART_CR3_DMAT; mDmaTx.Instance->CPAR = reinterpret_cast<uint32_t>(&mUart.Instance->TDR); mDmaTx.Instance->CMAR = reinterpret_cast<uint32_t>(data); const uint32_t dataLength = size; mDmaTx.Instance->CNDTR = dataLength; mUart.Instance->CR3 |= USART_CR3_DMAT; __HAL_DMA_ENABLE(&mDmaTx); } Если нужна другая инициализация модуля - меняю *cpp файл модуля. Пока думаю, что проект для всех вариантов ПО должен быть один и все версии файлов должны быть в нем. Так вот, что делать с файлами периферии? 1. Можно раскинуть по папкам version1/uart1.cpp version2/uart1.cpp Но не компилируется - объектные файлы с одинаковыми именами. 2. Можно менять им имена в зависимости от версии uart1_ver1.cpp uart1_ver2.cpp И тогда придется еще вводить для каждой версии свое пространство имен, если хочу сохранить имя класса единое. Не эстетично :rolleyes: 3. Как-то организовать на уровне системы контроля версий. Пока не понимаю как, при условии, что все версии нужно вести параллельно. 4. Сделать header only файлы периферии. Не очень красиво, не рекомендуют.
  7. Для С++ есть Clang Format. http://format.krzaq.cc/ тут можно поиграть онлайн. Но если переменные называть i, j, k, l, m - тут ничего не поможет. В смысле, все нормально, рабочее место за вами.
  8. Или так на шаблонах (по-русски с подробным объяснением) http://easyelectronics.ru/rabota-s-portami...erov-na-si.html
  9. brag, можете показать реализацию variable element-size queue? Как у меня сделано: очередь выдрана из mbed #include <stdint.h> #include <string.h> #include "cmsis_os.h" #include "mbed_error.h" bool handlerMode() { return __get_IPSR() != 0; } // Очередь с ленивой инициализацией - инициализируется в момент первого использования. // Сделано для обхода проблемы с неопределенным порядком инициализации глобальных объектов. // Очереди создаются глобально и менеджер памяти создается глобально. // Очередь использует выделение памяти в куче, поэтому должна быть создана после менеджера памяти. // Поэтому и сделана ленивая инициализация. // Бывают случаи, когда первое использование очереди происходит в прерывании, что недопустимо. // На этот случай, нужно вызывать метод create() явно, до первого использования. template<typename T, size_t N> class Queue { public: Queue(const char * name = NULL) : mName(name) {} /** Put a message in a Queue. @param data data. @param millisec timeout value or 0 in case of no time-out. (default: 0) @return status code that indicates the execution status of the function. */ bool put(const T & data, uint32_t millisec = 0) { if (!mQueueId) { create(); } portBASE_TYPE taskWoken = pdFALSE; // не понятно, зачем это надо if (handlerMode()) { if (xQueueSendToBackFromISR(mQueueId, reinterpret_cast<const void *>(&data), &taskWoken) == pdTRUE) { portEND_SWITCHING_ISR(taskWoken); return true; } } else { TickType_t ticks = millisec / portTICK_PERIOD_MS; if (ticks == 0) { ticks = 1; } if (xQueueSendToBack(mQueueId, reinterpret_cast<const void *>(&data), ticks) == pdTRUE) { return true; } } return false; } /** Get a message or Wait for a message from a Queue. @param millisec timeout value or 0 in case of no time-out. (default: osWaitForever). @return event information that includes the message and the status code. */ bool hasMessage(uint32_t millisec = osWaitForever) { if (!mQueueId) { create(); } bool hasMessage = false; portBASE_TYPE taskWoken = pdFALSE; if (handlerMode()) { hasMessage = xQueueReceiveFromISR(mQueueId, reinterpret_cast<void *>(&mData), &taskWoken) == pdTRUE; portEND_SWITCHING_ISR(taskWoken); } else { TickType_t ticks = 0; if (millisec == osWaitForever) { ticks = portMAX_DELAY; } else if (millisec != 0) { ticks = millisec / portTICK_PERIOD_MS; if (ticks == 0) { ticks = 1; } } hasMessage = xQueueReceive(mQueueId, reinterpret_cast<void *>(&mData), ticks) == pdTRUE; } return hasMessage; } const T & message() const { return mData; } T & message() { return mData; } size_t spaceAvailable() const { return uxQueueSpacesAvailable(mQueueId); } // нельзя вызывать из прерывания. void create() { // неплохо бы проверять, что мы находимся не в прерывании mQueueId = xQueueCreate(N, sizeof(T)); if (!mQueueId) { error("Error initialising the queue object\n"); } if (mName) { vQueueAddToRegistry(mQueueId, mName); } } private: const char * mName; QueueHandle_t mQueueId; T mData; }; В очередь пихаю свой доморощенный Variant: #include <algorithm> template <size_t N> class Variant { public: Variant() {} template <typename T> Variant(const T & t) { std::copy(reinterpret_cast<const uint8_t *>(&t), reinterpret_cast<const uint8_t *>(&t) + sizeof(mData), mData); } template <typename T> T get() const { return *reinterpret_cast<const T *>(mData); } template <typename T> T * value() { return reinterpret_cast<T *>(mData); } Variant & operator= (const Variant & other) { std::copy(other.mData, other.mData + sizeof(mData), mData); return *this; } float toFloat() const { return get<float>(); } uint32_t toUInt32() const { return get<uint32_t>(); } private: uint8_t mData[N]; }; Использование: struct Message { ... }; typedef Variant<sizeof(Message)> MessageVariant; // знаю, что структура Message самая большая из помещаемых в MessageVariant Queue<MessageVariant, 10> queue; ... if (queue.hasMessage()) { const MessageVariant & msgVar = queue.message(); const Message & msg = msgVar .data().get<Message>(); } Реализация на моем уровне знания шаблонов.
  10. Использовал провод МПО http://tcentr.su/p12883913-provod-montazhnyj-mpo.html Изоляция очень неохотно плавится от паяльника, разноцветный, многожильный, луженый.
  11. Учиться. Нужны материалы? Просто С++ - любые 3 хорошие книги (читать в фоне). Со спецификой embedded - мне очень понравилась эта книга https://vk.com/wall-112797241_4 Быстрый старт. 1. Начните использовать ссылки. 2. Начните использовать С++ приведения типов reinterpret_cast, static_cast, const_cast. Запретите себе приведение типов в стиле C. 3. Используйте namespace. 4. Используйте перегрузку функций (если надо конечно). 3. Пробуйте проектировать простые классы. Напишите класс светодиода, пусть плохенький (для начала). Это уже объектно-ориентированный анализ и проектирование, есть отдельные книги. Спрашивайте здесь, как написать класс под ту или иную задачу.
  12. Если имеется ввиду std::string, то да, лучше не использовать. Но со строками как-то работать надо, поэтому колхозим свой велосипед: #pragma once #include <cstring> #include <string> #include <algorithm> #include <stdio.h> #include <string.h> #include <stdlib.h> namespace mylib{ template <size_t S> struct String { String() { clear(); } String(const char * str) { clear(); copy(str); } size_t size() const { return S; } // количество символов в буфере, исключая терминирующий \0 size_t occupied() const { return std::char_traits<char>::length(buf); } void clear() { std::fill(buf, buf + S, 0); } bool contains(const char * str) const { return std::strstr(buf, str) != NULL; } String<S> & operator=(const char * str) { copy(str); return *this; } char buf[S]; private: // копируем по указателю str символов не более (размер нашей строки - 1). // если копируемая строка меньше (размер нашей строки - 1), остаток добивается \0 void copy(const char * str) { size_t size = std::min(S - 1, std::char_traits<char>::length(str)); std::char_traits<char>::copy(buf, str, size); } }; } Класс добивается своими методами по потребностям. Можно полностью содрать интерфейс с std::string. Если встречу хорошо написанный класс строки, с удовольствием выкину свою поделку :)
  13. С++ в embedded обычный, поэтому изучайте по любой книге. Специфика embedded в ограниченности ресурсов, поэтому нужно отчетливо понимать "сколько стоит" та или иная языковая конструкция. К примеру, RTTI - тяжелая вещь, ее не применяют в первую очередь (хотя можно, если хочется). https://vk.com/wall-112797241_4 https://vk.com/wall-112797241_104?w=away-112797241_104 https://vk.com/wall-112797241_147
  14. Т.к. вы выбрали msvc2013, в комплекте с Qt не шел компилятор. Его нужно установить отдельно (Visual C++ Compiler). И в настройках его прописать. Тут нужно не ошибиться с версий компилятора, точно не помню, то ли устанавливать точно 2013 года, то ли можно самый новый. Но, рекомендую установить пакет qt-opensource-windows-x86-mingw492-5.5.1.exe. Там уже идет компилятор в комплекте. Все настраивается. В прошлый раз я неправильно показал, какую галку нужно ставить - та галка просто предкомпилированные компоненты. Вот картинки 2-х установщиков, первый c MinGW, второй с MSVC. Обратите внимание, что во втором случае компилятора нет. Галка с компилятором MinGW по умолчанию НЕ стоит.
  15. Скачайте offline установщик с сайта qt. При установке не снимайте галок с компилятора, и все установится нормально. В настройках у вас должно быть примерно так, как на картинке.
×
×
  • Создать...