1. Уважаемый Гость! При написании вопросов в раздел форума [ArduCopter] Вопросы, проблемы и решения обязательно придерживаться шаблона сообщения, оговоренного в правилах раздела! Если сообщение не будет оформлено должным образом, то и ответ на вопрос будет с наименьшим приоритетом. Старайтесь дать максимально полную информацию по вашей проблеме, чтобы можно было более детально рассматривать вопрос!
    Скрыть объявление
  2. Уважаемый Гость! Хотите получать кэшбэк с покупок в online-магазинах? Сервис "Zozi.ru" дает такую возможность!
    Скрыть объявление
  3. Друзья! Для нашего ресурса необходим дополнительный объем пространства в облаке Dropbox. Подробнее.
    Скрыть объявление

Arduino и AVR (Atmel) микроконтроллеры

Тема в разделе "Наши другие увлечения", создана пользователем raefa, 9 мар 2016.

Реклама. Купить это место.
  1. raefa

    raefa Главнокомандующий Команда форума

    Регистрация:
    3 янв 2015
    Сообщения:
    4.324
    Город:
    Zhigulevsk
    Имя:
    Александр
    Последнее редактирование: 19 окт 2017
  2. An_private

    An_private Старший научный сотрудник

    Регистрация:
    6 июн 2016
    Сообщения:
    595
    Город:
    Санкт-Петербург
    Имя:
    Андрей Коробейников
    Ну и делайте на двух прерываниях. Вроде у arduino пару внешних прерываний можно сделать без проблем.
    Не, я конечно могу предложить целый спектр решений, от внешнего счётчика и регистра сдвига до мелкой FPGA, но это явно не тот уровень:p:whistling:
     
  3. Marksheider

    Marksheider Научный сотрудник

    Регистрация:
    1 дек 2016
    Сообщения:
    332
    Город:
    Прокопьевск
    Имя:
    Артем
    Не, мне бы че попроще. чтоб на пальцах было понятно.
    я тут пытался мотор запустить шаговый на прерываниях, но я так и не понял как вообще работают эти прерывания. везде описываюся слишком заумно и явно опуская некие тонкости.
     
  4. An_private

    An_private Старший научный сотрудник

    Регистрация:
    6 июн 2016
    Сообщения:
    595
    Город:
    Санкт-Петербург
    Имя:
    Андрей Коробейников
    Не, не получится. У ATMEGA328 всего три таймера, причём один из них по умолчанию использован по SysTick, а два используются для формирования PWM. Это в STM32 этих таймеров до дури, а в avr сильно не разбежишься.
    Так что только через прерывания. А что там сложного то? Создаём процедуру обработки прерывания и задаём - от чего прерывание происходит и всё. Не на ассемблере же писать.
     
  5. Marksheider

    Marksheider Научный сотрудник

    Регистрация:
    1 дек 2016
    Сообщения:
    332
    Город:
    Прокопьевск
    Имя:
    Артем
    Что такое void sens() ? вроде раньше ее не было ни где а тут появилась. Почему нельзя все сделать в loop ???
    Код:
    unsigned long lastflash;
    int RPM;
    
    void setup() {
        Serial.begin(9600);  //открыть порт
        attachInterrupt(0,sens,RISING); //подключить прерывание на 2 пин при повышении сигнала
        pinMode(3, OUTPUT);   //3 пин как выход
        digitalWrite(3, HIGH);  //подать 5 вольт на 3 пин
    }
    void sens() {
        RPM=60/((float)(micros()-lastflash)/1000000);  //расчет
        lastflash=micros();  //запомнить время последнего оборота
    }
    
    void loop() {
        if ((micros()-lastflash)>1000000){ //если сигнала нет больше секунды
            RPM=0;  //считаем что RPM 0
        }
        Serial.println(RPM);   //вывод в порт
        delay(50);  //задержка для стабильности
    }
     
  6. An_private

    An_private Старший научный сотрудник

    Регистрация:
    6 июн 2016
    Сообщения:
    595
    Город:
    Санкт-Петербург
    Имя:
    Андрей Коробейников
    Объявление процедуры (sens), которая не возвращает никакого значения (void).
    Это и есть процедура обработки прерывания. Её подключают в
    attachInterrupt(0, sens, RISING);
    Процедура, кстати, дико перегруженная. Обычно в процедуре делают только что-то типа:
    in1_counter++;
    и всё. А вся обработка идёт уже в loop.
    Потому, что не успеть. Всякие там dtostrf и запросы данных с весов занимают много времени. Если в это время придёт сигнал с датчика холла, то он будет потерян.

    Автору данного творения, кстати, оборвать уши. Не объявить переменные, используемые в прерывании, как volatile - полное ламерство и прямой путь к сложнопредсказуемым глюкам.
     
  7. Marksheider

    Marksheider Научный сотрудник

    Регистрация:
    1 дек 2016
    Сообщения:
    332
    Город:
    Прокопьевск
    Имя:
    Артем
    Вот вот, а это великий и могучий Алекс Гайвер. Вот и думай потом чего у него правильно а чего нет.

    Тогда не понятно, сигнал с датчика холла будет идти постоянно, пока крутится мотор. как тогда ардуинка все остальное будет делать если она будет по прерыванию обрабатывать только сигнал с датчика холла???
     
  8. An_private

    An_private Старший научный сотрудник

    Регистрация:
    6 июн 2016
    Сообщения:
    595
    Город:
    Санкт-Петербург
    Имя:
    Андрей Коробейников
    Великий и могучий только Дональд Кнут :) Ну и Керниган+Ричи в программировании на си. А расплодившихся последнее время ламеров, считающих себя великими даже и не знаю как называть.
    Что значит "постоянно"? Предположим 10000 об/мин. Это всего-то 167 об/сек, то есть 167 прерываний в секунду. Прерывание обычно обрабатывается примерно 50-100 тактов, то есть в худшем варианте обработка одного прерывания займёт 100/16 = 6,25 мкс. И всех 167 - около 1 мс. То есть всего 1/1000 процессорного времени. Основной процесс этого даже не заметит.
     
  9. Marksheider

    Marksheider Научный сотрудник

    Регистрация:
    1 дек 2016
    Сообщения:
    332
    Город:
    Прокопьевск
    Имя:
    Артем
    Ок, тогда как понять
    in1_counter++;
    Это пин с которого идет сигнал от датчика?
     
  10. An_private

    An_private Старший научный сотрудник

    Регистрация:
    6 июн 2016
    Сообщения:
    595
    Город:
    Санкт-Петербург
    Имя:
    Андрей Коробейников
    Просто :) Как увеличение счётчика на единицу. Ведь что нам надо знать - сколько импульсов пришло за секунду. Соответственно - в основном цикле обнуляем счётчик и фиксируем момент начала отсчёта. Крутим циклы и проверяем - не прошла ли секунда. Если прошла, то смотрим содержимое счётчика и считаем - каким оборотам это соответствует. Всё, опять обнуляем счётчик и по кругу.
    А в прерывании только увеличиваем счётчик на единицу.
     
    LampGraph нравится это.
  11. An_private

    An_private Старший научный сотрудник

    Регистрация:
    6 июн 2016
    Сообщения:
    595
    Город:
    Санкт-Петербург
    Имя:
    Андрей Коробейников
    Если очень кратко, то надо сделать примерно так:

    в начале:
    Код:
    volatile unsigned long start_t1, stop_t1, start_t2, stop_t2;
    volatile uint16_t rpm_cntr1, rpm_cntr2;
    
    в setup:
    Код:
    attachInterrupt(digitalPinToInterrupt(2), interrupt1, RISING);
    attachInterrupt(digitalPinToInterrupt(3), interrupt2, RISING);
    rpm_cntr1 = 0;
    rpm_cntr2 = 0;
    
    две процедуры обработки прерываний:
    Код:
    void interrupt1() {
    if (rpm_cntr1 == 0) start_t1 = micros();
    stop_t1 = micros();
    rpm_cntr1++;
    }
    void interrupt2() {
    if (rpm_cntr2 == 0) start_t2 = micros();
    stop_t2 = micros();
    rpm_cntr2++;
    }
    
    в loop:
    Код:
    float realRPM1 = ? (rpm_cntr1 < 2) 0.0 : float(rpm_cntr1 - 1) * 60000000.0 / float(stop_t1 - start_t1);
    rpm_cntr1 = 0;
    float realRPM2 = ? (rpm_cntr2 < 2) 0.0 : float(rpm_cntr2 - 1) * 60000000.0 / float(stop_t2 - start_t2);
    rpm_cntr2 = 0;
    
    по идее еще неплохо бы добавить проверки на переполнение, но это уже по желанию.
    --- Сообщения объединены, 14 ноя 2017 ---
    Ну и еще в loop надо бы добавить noInterrupts() и interrupts() до и после получения данных соответственно.
    Вот неплохая статейка по прерываниям (правда на английском):
    http://gammon.com.au/interrupts
     
    Marksheider нравится это.
  12. An_private

    An_private Старший научный сотрудник

    Регистрация:
    6 июн 2016
    Сообщения:
    595
    Город:
    Санкт-Петербург
    Имя:
    Андрей Коробейников
  13. Marksheider

    Marksheider Научный сотрудник

    Регистрация:
    1 дек 2016
    Сообщения:
    332
    Город:
    Прокопьевск
    Имя:
    Артем
    В общем собрал я отдельный скеч чтоб разобраться как он будет работать, и наткнулся на знак вопросса, на нем выдает ошибку при компиляции.

    Мне это не победить, скеч целиком тут
    что тут означает знак вопросса?
    Код:
    float realRPM1 = ? (rpm_cntr1 < 2) 0.0 : float(rpm_cntr1 - 1) * 60000000.0 / float(stop_t1 - start_t1);
    rpm_cntr1 = 0;
    float realRPM2 = ? (rpm_cntr2 < 2) 0.0 : float(rpm_cntr2 - 1) * 60000000.0 / float(stop_t2 - start_t2);
    rpm_cntr2 = 0;
     
  14. An_private

    An_private Старший научный сотрудник

    Регистрация:
    6 июн 2016
    Сообщения:
    595
    Город:
    Санкт-Петербург
    Имя:
    Андрей Коробейников
    тьфу, блин, пардон :)
    float realRPM1 = (rpm_cntr1 < 2) ? 0.0 : float(rpm_cntr1 - 1) * 60000000.0 / float(stop_t1 - start_t1);
    rpm_cntr1 = 0;
    float realRPM2 = (rpm_cntr2 < 2) ? 0.0 : float(rpm_cntr2 - 1) * 60000000.0 / float(stop_t2 - start_t2);
    rpm_cntr2 = 0;
    --- Сообщения объединены, 15 ноя 2017 ---
    А про длину строки - он пишет, что строка Izmeritel Obormotov слишком длинная для массива. И это правда - в ней 19 символов (включая завершающий 0).
     
  15. Marksheider

    Marksheider Научный сотрудник

    Регистрация:
    1 дек 2016
    Сообщения:
    332
    Город:
    Прокопьевск
    Имя:
    Артем
    Это не критическая ошибка:thumbsup:. Спасибо, скомпилировался.
    --- Сообщения объединены, 15 ноя 2017 ---
    Подключать сигнал с датчика на выходы А2 и А3???
    И почему когда вставляешь перед loop то выдает ошибку при компиляции?
    Код:
    void interrupt1() {
    if (rpm_cntr1 == 0) start_t1 = micros();
    stop_t1 = micros();
    rpm_cntr1++;
    }
     
  16. Marksheider

    Marksheider Научный сотрудник

    Регистрация:
    1 дек 2016
    Сообщения:
    332
    Город:
    Прокопьевск
    Имя:
    Артем
    Объясните мне пожалуйста все таки формулу как считаются обороты.
    float realRPM1 = (rpm_cntr1 < 2) ? 0.0 : float(rpm_cntr1 - 1) * 60000000.0 / float(stop_t1 - start_t1);
    rpm_cntr1 = 0;
    что значит (rpm_cntr1 < 2) ? 0.0 :
     
  17. An_private

    An_private Старший научный сотрудник

    Регистрация:
    6 июн 2016
    Сообщения:
    595
    Город:
    Санкт-Петербург
    Имя:
    Андрей Коробейников
    D2 и D3
    Что если счётчик прерываний меньше 2, то выдавать 0.0, если 2 и больше, то выдавать результат расчёта.
    rpm_cntr1 - 1 - это сколько всего периодов (полных оборотов) мы зафиксировали. -1 потому, что на первом прерывании мы только фиксируем момент начала и всё.
    60 000 000 - это сколько микросекунд в одной минуте
    stop_t1 - start_t1 - это сколько микросекунд прошло от первого прерывания до последнего
    соответственно и всё, дальше, мне кажется, очевидно

    Да, ещё, если это используется в отдельной программе, то надо бы делать задержку, иначе между loop'ами будет проходить слишком мало времени. Либо задать, что RPM не считается до тех пор, пока не произошло хотя бы 3 (с потолка) прерывания.

    То есть примерно так:
    float realRPM1 = 0.0;
    if (rpm_cntr1 > 4)
    {
    realRPM1 = float(rpm_cntr1 - 1) * 60000000.0 / float(stop_t1 - start_t1);
    rpm_cntr1 = 0;
    }
    Какую именно?
     
  18. Marksheider

    Marksheider Научный сотрудник

    Регистрация:
    1 дек 2016
    Сообщения:
    332
    Город:
    Прокопьевск
    Имя:
    Артем
    Вот эти. Или так и должно быть куда я прописал? в конец?
    Потому что гдето написано что нужно писать эту часть перед loop ? но тогда ошибку выдает.
     
  19. An_private

    An_private Старший научный сотрудник

    Регистрация:
    6 июн 2016
    Сообщения:
    595
    Город:
    Санкт-Петербург
    Имя:
    Андрей Коробейников
    Я и спрашиваю: какую. Какую ошибку выдаёт?
     
  20. Marksheider

    Marksheider Научный сотрудник

    Регистрация:
    1 дек 2016
    Сообщения:
    332
    Город:
    Прокопьевск
    Имя:
    Артем
    упс а сейчас не выдает:rolleyes:, видать я где то наглючил.
    от какой скорости начинается счет? почему то не реагирует на пальцы проносимые над датчиком, хотя сам датчик срабатывает.
     
  21. An_private

    An_private Старший научный сотрудник

    Регистрация:
    6 июн 2016
    Сообщения:
    595
    Город:
    Санкт-Петербург
    Имя:
    Андрей Коробейников
    Хз. Зависит от времени выполнения loop.
    Я же написал - как надо переписать код, чтобы он не начал считать пока не получил хоть сколько-то значимое количество прерываний.
     
Реклама. Купить это место.