Выбор архитектуры и возможно ли это на Ардуине.

Тема в разделе "Arduino & Shields", создана пользователем Alex19, 20 сен 2014.

  1. Alex19

    Alex19 Гуру

    День добрый.

    После долгого перерыва, появилось время на приятное:), вернутся к своему проекту.
    Есть сомнения, а правильной ли дорогой я иду и возможно ли это.

    Вкратце о проекте.
    Делаю систему управления своими станочками. Код представляет собой конечный автомат, некая последовательность операций. С компьютера шлются данные настроек, команд пока Serial, могут придти в любое время, поэтому в начале loop должен проверять наличие данных.

    Планировал делать на Mega, но надо 12-bit АЦП и приличная скорость, возможно придется делать на Due.

    Суть вопроса.
    На станке есть 7 линейных потенциометров (принцип их работы как у модулей-слайдеров http://amperka.ru/product/slider-module) , на выходе аналоговый сигнал.

    Скорость перемещения данных потенциометров до 1000мм/с. Пропустить 0,1мм я не могу, следовательно, должен опрашивать их в режиме нон стоп. Расчет времени опроса в 1000000 микросекунд / 10000 (десятые мм), получаем 100 микросекунд.

    Можно наверно сделать цикл loop не более 100 микросекунд, но с учетом проверок Serial это не представляется возможным.

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

    Типичный код, обработки линеек, AnalogReadOne(b1) и AnalogReadOne(b2) линейки
    Код (Text):

            // b63 – проверка, разогрета ли масса
            // b23 концевик, конец затухания закрытия пресс-формы, пресс-формы закрыта
            // b29r концевик, остановка возврата шнека, наверно и старт шнека начинается от b29r
            if (DigitalReadOne(b63) && AnalogReadOne(b1) >= b23 && AnalogReadOne(b2) >= b29r)
            {
                // Устанавливаем значение P2
                // 1-я ступень давления
                AnalogWriteWithCheckDoorAndHoldKey(s51in, p2, '4');

                // Устанавливаем значение V3
                // 1-я скорость впрыска
                AnalogWriteWithCheckDoorAndHoldKey(s50in, v3, '4');

                // Запускаем подвод шнека s6
                DigitalWriteWithCheckDoorAndHoldKey(s6, HIGH, '4');

                // Запускается таймер t2
                if (previousT2 == 0)
                {
                    // Устанавливаем таймер t2
                    previousT2 = millis();
                }
            }
     
    Мне пришла в голову такая мысль.
    Вставить эти обработки в таймеры, делать прямой доступ к регистрам для записи чтения портов и использовать FAST ADC и т.д.

    Но тогда по сути, придется засунуть всю программу в данные обработчики таймеров, с конечным автоматом. Думаю там я смогу добиться выполнения всего прерывания в течении максимум 100 микросекунд.

    Но все эти мысли мне кажутся, какими-то странными и не уверен в том, что это возможно. Может есть другой, более элегантный способ?

    Прошу Вашей помощи, мне не нужен код, мне нужно только направление в какую сторону, копать.
    Заранее благодарен.
     
  2. Unixon

    Unixon Оракул Модератор

    А если крайние значения обнаруживать аппаратно? Поставить несколько 12bit DAC (SPI/I2C) + компараторы, выходы с компараторов на ноги прерываний. Ну а UART опрашивать только когда не ожидается критичного события.

    В принципе можно и встроенным компаратором воспользоваться, но я не в курсе что там с несколькими каналами и можно ли их так настроить.
     
    Alex19 нравится это.
  3. Unixon

    Unixon Оракул Модератор

    Поводу протокола передачи команд. Можно воспользоваться асинхронным протоколом, нечувствительным к задержкам. Для однонаправленного соединения нужно минимум три сигнала (запрос, ответ, данные). Если интересует, распишу логику автоматов.
     
  4. Alex19

    Alex19 Гуру

    Большое спасибо за ответ.

    Отличный вариант, замены analogWrite, получения максимально быстрого ответа с датчика. На на Mega я получаю, чтение около 32 микросекунд, Due будет только вечером.

    Но так как крайние положения могут меняться постоянно надо будет занять SPI, а я уже задумался о UDP. В таком случае не уверен, что скорости переключения SPI хватит. Надо проверить.

    Там нет не критических событий. В этом вся беда.

    Думаю о UDP, надо проверить есть W5100, может купить W5200.

    А такая идея, вообще живая или это моя фантазия?
     
  5. Alex19

    Alex19 Гуру

    Большое спасибо. Очень интересно, но мне жалко Вашего времени, скажите в какую сторону копать. Я упертый:).
     
  6. Unixon

    Unixon Оракул Модератор

    А что из себя представляют функции, вызываемые в обработчике?
     
  7. Alex19

    Alex19 Гуру

    Не сразу сообразил, это передача в 1 сторону, мне не подходит, он отсылает данные назад и т.д.
     
  8. Unixon

    Unixon Оракул Модератор

    Не проблема, двунаправленная линия = две однонаправленных.
     
  9. Alex19

    Alex19 Гуру

    Обычные функции оберток, по сути матричная клавиатура 4X4 и работа с ногами цифровыми и аналоговыми.
     
  10. Alex19

    Alex19 Гуру

    Тогда, подскажите пожалуйста куда копать, можно 2-3-4 аруины и т.д.:), любые решения одним словом.

    Хотел скинуть код, чтобы было понятно. Но он большой, поэтому проще говорить о принципах, код я всегда переделаю. На всякий вставил в прищепку, сюда он ни когда не поместится, там еще 1 десятая от конечного решения.

    UPD. Плюс он не оптимизирован, поэтому проще говорить о принципах
     

    Вложения:

    • TPA.zip
      Размер файла:
      15 КБ
      Просмотров:
      306
  11. Unixon

    Unixon Оракул Модератор

    В общем, это скорее всего какой-то древний велосипед, я его для собственных нужд как-то расписывал с нуля. Чем-то похоже на протокол обмена данными через процессорную шину у старого доброго Z80.

    Суть в следующем.

    0) начало цикла обмена: линия данных в третьем состоянии или не содержит актуальных данных, сигналы запроса и ответа опущены.
    1) передатчик выставляет на линию данных (или даже параллельную шину) актуальные данные.
    2) передатчик поднимает сигнал запроса (данные готовы) и ждет, когда приемник поднимет сигнал ответа (что данные получены).
    3) приемник считывает данные и поднимает сигнал ответа (данные получил).
    4) передатчик опускает сигнал запроса (знает, что приемник получил данные) и ждет когда приемник опустит сигнал ответа.
    5) приемник видит, что сигнал запроса опущен и опускает сигнал ответа (знает, что передатчик знает, что он получил данные).
    6) передатчик убирает актуальные данные с линии/шины и при необходимости переводит ее в третье состояние. цикл обмена закончен.

    Оригинальный рисунок в приложении.
    asyncserial.jpg
     
    Alex19 нравится это.
  12. Unixon

    Unixon Оракул Модератор

    При возможности переводить линию/шину данных в третье состояние, она может быть физически двунаправленной. Альтернативно, линии могут быть реализованы по схеме с открытым коллектором.
     
  13. Alex19

    Alex19 Гуру

    Огромное спасибо!
    Теперь надо это переварить и подумать, хватит ли у меня ума, чтобы это реализовать:).
     
  14. Alex19

    Alex19 Гуру

    И еще один, архитектурный вопрос.

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

    Но при такой шине, ардуина - одно потоковая. Следовательно я не могу выделить чтение и отправку в отдельный поток. Есть шанс, потерять значения линеек пока, идет оправка или чтение.

    Не очень понятно, можно конечно вставить в loop данную систему отправки/получения данных и больше ни чего. А в прерывания по таймеру всю обработку. Схема вроде рабочая, но какая-то на мой взгляд не совсем правильная.
     
  15. Unixon

    Unixon Оракул Модератор

    Нужно вписать отправку и получение в общий автомат, т.е. заменить все while() и for() на if().
    Там на рисунке приведены идеализированные процедуры просто для иллюстрации идеи.
    На самом деле, конечно же, не должно быть циклов ожидания, а только очень быстрое прощелкивание состояний автомата.

    Коряво как-то выразился...

    Нужно переписать блокирующие процедуры из примера в неблокирующий цикл автомата протокола и вызывать его из loop(). За каждый проход автомат протокола должен сделать всего 2-3 операции чтения-записи и проверку условия. Данные можно передавать по нескольким линиям, т.о. организуя параллельную шину. Это очень удобно делать на Arduino Mega, т.к. у нее непрерывно побитно выведены целых три порта, т.е. можно прямым обращением к портам работать очень быстро с 8-24 битной шиной.
     
    Последнее редактирование: 20 сен 2014
  16. Alex19

    Alex19 Гуру

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

    Попробую пояснить.
    Есть программа, при включении она загружает нужны параметры с компьютера.
    Потом идет цикл, цикл это выполнения моего конечного автомата от А до Я.

    Вот, что понимаю по циклом
    Код (Text):

    switch (Work) {
        case A:
            ...
            break;
        case B:
            ...
            break;
         .....
        case End:
            ...
            break;
    }
     
    Оператор, во время цикла, меняет значения, положения линек, давления и т.д. Вводит на компьютере, от туда передаются данные на аруину, она отвечает, что данные приняла. И в следующем цикле применяют новые параметры, при этом выполнения цикла не прерывается.

    UPD. Кроме этого, ардуина сообщает о положении линеек, давления и т.д. на компьютер. Если бы не было компьютера, задача была бы относительно простой.
     
    Последнее редактирование: 20 сен 2014
  17. Alex19

    Alex19 Гуру

    Если вставить в получения данных, в общий цикл, например в начале. То цикл может не отработать корректно, если получение данных и обработка данных не будет выполнено вовремя.
     
  18. Unixon

    Unixon Оракул Модератор

    Вот именно поэтому отвлечение от первой задачи - управления станком на вторую задачу - общение с компьютером (например, посредством еще одной интерфейсной ардуины) должно происходить на минимально короткое время. За один цикл вашего автомата будет выполняться только один цикл автомата протокола, передача одного байта (допустим, что мы используем 10 сигнальных проводов - 2 управляющих и 8 для шины данных) будет происходить только за 6 циклов автомата протокола, при этом каждый его проход будет очень коротким.

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

    Alex19 Гуру

    То есть, я ставлю 1 ардуину приемником и передатчиком, 2-ой для выполнения цикла, но они должны общаться между собой. Между 2 платами 10 проводов, цифровая шина. Допустим, это есть.

    Но 2-ой плате надо будет получать, данные. Хотя если просто читать порты, это должно быть быстро.

    Да получение данных, конечной платой выполняющий цикл должно быть, очень быстрым, чтобы не помешать выполнению цикла. Она должна та же быстро отправлять данную на интерфейсную ардуину. То есть максимум 100 микросекунд, на 1 байт.
     
  20. Alex19

    Alex19 Гуру

    Так вроде до меня дошло:).

    А если читать, через регистры должно получится. Хватило бы ума, чтобы это реализовать.
    Большое спасибо! Буду пробовать.