Что-то здесь не так.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

ЕвгенийП пишет:

[Диалог из фильма Кин-дза-дза:

- Ну, это на глаз.
- Дикари!

Вы это серьезно про "на глаз".  Или все-таки определенная операция требует какого-то регламентрованного,  и конечно же в наших интересах - не завышенного времени?

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

slava.ru38 пишет:

Вы это серьезно про "на глаз".  Или все-таки определенная операция требует какого-то регламентрованного,  и конечно же в наших интересах - не завышенного времени?

Ну, Вы задаёте идиоткие вопросы, и естественно, получаете идиотские ответы.

Длительность задержки определяется тем, для чего она нужна. Если в даташите написано, что "после приёма команды датчику требуется 2 микросекунды, для того, чтобы резултат стал надёжным", значит нужно делать задержку в 2 микросекунды, а если в Вашем модуле стоит фильтр по питанию в котором конденсатор 10мс заряжется, значит от подачи питания до попытки что-то с модулем делать нужно выждать 10 мс, чтобы питание модуля вышло на рабочий режим. Ну и так далее, какая нужна задержка, такую и ставишь. Какое тут может быть общее правило?

slava.ru38
Offline
Зарегистрирован: 28.11.2016

ЕвгенийП пишет:

Ну, Вы задаёте идиоткие вопросы, и естественно, получаете идиотские ответы.

Длительность задержки определяется тем, для чего она нужна. Если в даташите написано, что "после приёма команды датчику требуется 2 микросекунды, для того, чтобы резултат стал надёжным", значит нужно делать задержку в 2 микросекунды, а если в Вашем модуле стоит фильтр по питанию в котором конденсатор 10мс заряжется, значит от подачи питания до попытки что-то с модулем делать нужно выждать 10 мс, чтобы питание модуля вышло на рабочий режим. Ну и так далее, какая нужна задержка, такую и ставишь. Какое тут может быть общее правило?

Конечно обидно быть идиотом, но видимо это участь всех, кто только начинает познавать новую, ранее неведомую  для себя область. Поэтому постараюсь сдержаться и не буду обижаться. Вы имеете ввиду даташит на ардуино, или какой? Потому что меня интересует конкретно пауза в строках 83, 92, 101, 109. Ну и соответственно строки 177, 182, 186, 191

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Arhat109-2 пишет:

Ещё надо заметить, что для обратного преобразования в расстояние Вы зачем-то делите вычисленное время на 58 (иногда делят на 59), в то время как операции целочисленного деления у Ардуино нет и в помине, а деления вещественных чисел нет как класса чисел и вовсе. Куда как полезнее делить на такие чиселки, которые являются степенями двойки, чтобы заменить деление сдвигами. Если предварительно умножить нашу скорость в 0.335 мм/мксек на скажем 1024, то получим константу 343.040, что мало отличается от 343 (0,012%!) и, в этом случае мы можем измеренное время в микросекундах домножить на эту константу и поделить на 1024, а поскольку "туда и обратно", то на 2048 что куда как экономичнее и быстрее делается Арудиной! Кто и с какого перепою предложил делить на 58 - ума не приложу, каким надо быть безграмотным программистом.

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

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Грамотный программист ЗНАЕТ что МК не имеет ни вещественной составляюшей данных ни даже целочисленного деления, а равно как и остатка от него. Поэтому он НЕ СТАНЕТ применять и уж тем более включать в базовую библиотеку код, основанный на этих операциях от слова СОВСЕМ.

Это кстати, также относится к реализации буферизации так любимого всеми Serial и stream.h .. исключительно безграмотная поделка и хоть бы один задумался, я уж молчу про "поправил". :(

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Arhat109-2, Вы подходите к вопросу не с той стороны.

Нужно - исходя из задачи, а Вы - исходя из имеющихся средств для ее решения.

Ничего страшного в применении FP нет, нужно лишь соблюсти два условия:

- понимать, зачем это нужно,

- оценить величину накладных расходов и их влияние на возможность решения задачи.

И еще раз: если датчику нужно от 1000 до 5000 мкс для получения данных, то абсолютно безразлично, потратит МК на обработку этих данных 1 мкс или 50 мкс.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

http://arduino.ru/forum/obshchii/vremya-vypolneniya-otdelnykh-komand-ard... Между прочим - это ваша тема. Вспоминайте сколько занимает длинное целое и вещественное деление. Есть ещё https://www.gnu.org/savannah-checkouts/non-gnu/avr-libc/user-manual/benc... по некоторым сложным функциям вещественной арифметики и преобразованиям. Да, не забудьте что операция деления может тоже потребовать неявного преобразования форматов "туда" и "обратно". Тоже не мелочь.

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

В частности конкретно тут управление движением робота - существует принципиальная разница будет исполняться код ровно 4мсек (4000мксек) или "хде-то так": от 3 до 5-и. Тут только что обсуждали тему "скоростное движение по линии" .. так вот чтобы ПИД нормально работал он просто ОБЯЗАН получать данные и отдавать команды управления через СТРОГО ФИКСИРОВАННОЕ ВРЕМЯ. Иначе это не ПИД, а порнография.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Arhat109-2, да, это моя тема. Потому что мне нередко приходится заниматься оптимизацией скорости работы кода. Это, как мне кажется, должно наводить на мысль, что я также задавался вопросом, когда следует проводить такую оптимизацию, а когда - нет.

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

И, кстати, ПИД НЕ ОБЯЗАН получать данные строго регулярно. Разумеется, если он грамотно написан.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Так не надо проводить "оптимизацию", когда можно писать СРАЗУ грамотно! Всеж просто.. :)

А Вы похоже не обратили внимания на то, что приведенная функция работает одинаковое время независимо от измеряемой дальности ..

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Arhat109-2 пишет:

Так не надо проводить "оптимизацию", когда можно писать СРАЗУ грамотно! Всеж просто.. :)

О том, что такое "грамотно" - сколько людей, столько и мнений.

Цитата:

А Вы похоже не обратили внимания на то, что приведенная функция работает одинаковое время независимо от измеряемой дальности ..

Не обратил. Но если это так, то IMHO это БЕЗРАМОТНО написанная функция, если она может измерить расстояние, допустим, за 1 мс, но все равно упорно тратит на это 5 мс.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

:)

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Изменил немного скетч. В строки 119, 129, 139 внес дополнительные параметры (таймаут) - 3500 мкс. Убрал световую сигнализацию пока, кое-где делеи уменьшил. Вроде работает корректно и успевает среагировать на статус датчиков линии. Но так как я пока НЕГРАМОТНЫЙ программист - еще буду оттачивать.  

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Меньше обращайте внимания на тутошние споры "ниочем". Да, и грамотный программист, это не тот "ктовсёзнает", ибо "невозможно объять необъятное" (с) Козьма Прутков. А тот, кто сначала изучает вопрос, продумывает решение и только потом пишет. А не наоборот: сначала пишет, а потом "оптимизирует и сопровождает" (устраняет свои же косяки за бабки клиента). :)

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Хотя споры и бывают пустыми, но в споре рождается истина (если конечно спор конструктивный). И в данной ветке из этих "споров" считаю для себя извлек много полезного. Читая и изучая материал самостоятельно я узнал меньше, чем обсуждая проблему с опытными людьми

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Ищите, да обрящете. В целом, посмотрел ваш код. Он примитивен и написан "в лоб" в предположении что исполнительные механизмы робота отрабатывают ваше управляющее воздействие "мгновенно", а это совсем не так. Так, к примеру, мотор при изменении управляющего воздействия быстрее 8-12мсек практически их игнорирует от слова "совсем", поскольку есть волшебное слово "инерция". Инерция самого мотора, инерция вращения колеса, инерция всей тележки.

Далее, при управлении моторами в повороте, надо помнить о том, что есть центробежная сила, которая в зависимости от радиуса и скорости поворота смещает "суммарный" центр тяжести тележки в сторону внешнего колеса. А моторы, по крайней мере обыкновенные коллекторные, имеют прямую механическую характеристику скорости вращения от .. приложенного момента. То есть, чем сильнее нагрузка на колесо от центробежной силы, тем медленнее крутится мотор и как результат - тележка едет по совсем иному радиусу, чем Вам бы хотелось и ожидалось от скорости изменения ШИМ. У гонщиков это явление носит название "перенос веса в повороте", пошукайте. Весьма интересно и познавательно.

Ещё далее, управляя скоростью моторов через ШИМ, вы по сути изменяете напряжение на моторе. Конденсатор мотора в данном месте играет роль интегратора ШИМ. А опять же, как известно, механическая характеристика коллекторного мотора на пост. магнитах .. упс, линейна по выходной мощности от поданного напряжения. То есть, для уменьшения скорости Вы по сути уменьшаете выходную мощность мотора, что под нагрузкой, превышающей мошность тупо останавливает мотор совсем. На практике, типовой ШИМ менее 30..50 (а то и все 100!) - это останов мотора. А поскольку трение в движении несколько меньше трения покоя, то зависимость скорости движения от величины ШИМ - сильно нелинейна на малых значениях ШИМ .. скажем от 30 до 70 один характер, от 70 до 100 - другой и от 100 и далее третий. Это если апроксимировать грубо. От этого частично можно уйти повышением рабочего напряжения на моторе и общим снижением значений ШИМ, скажем 6-и вольтовый мотор можно питать от 9-12в, но при этом не совать ему ШИМ больше 75-50% заполнения.

Но .. тут уже надо помнить о том, что типовой драйвер L298N - имеет биполярные выходные каскады и "съедает" на себе от 1 до 2в от поданного напряжения. Для уточнения есть смысл померять непосредственно свой драйвер. Кстати, оба плеча драйвера могут отрижать по-разному (у меня 1 такой есть: разница подаваемого напряжения на моторы до 0.5в!). Отсюда, типовой 6-и вольтовый мотор (китайские робо-тележки) питающийся через L298N от 6 вольт получает в лучшем случае только 5, а то и все 4. А при просадке аккумуляторов/батареек и того меньше.

Вопрос с питанием ваще очень важен и мало где освещен. Дело в том, что исполнительные устройства в т.ч. и даже датчики "жрут" ток нерегулярно, что приводит при плохом питании к броскам напряжения на МК и его перезагрузках "внезапно". Для контроля таких состояний, проще всего ставить в setup() задержку на 3-5сек и моргание светодиодом по её началу и/или завершению. У нас это уже давно "типовой блок" в setup(). Если есть проблемы с перезагрузкой, то это сразу обнаруживается: робот внезапно встает на 3-5 секунд и "машет" светодиодом, что легко заметно.

Питанию систем надо уделять самое пристальное внимание: датчики неплохо дооснащать гасящими керамическими конденсаторами на 0.1н х 25-50в допаиваясь непосредственно у входного контакта; ставить дополнительный стабилизатор на 5в и нормальным током, если у вас есть хотя бы пара серводвигателей, даже если они "микро SG-90" (под нагрузкой вполне может отжирать до 800мА, проверено), снабжая его тоже гасящими конденсаторами. Питание на вход стабилизатора дуньки как правило подается от того же источника что и идет на моторы. Соответственно, неплохо увеличить емкость электролита на входе стабилизатора, который стоит за защитным диодом до 300-600мкф. на соответствующее напряжение, особенно если от него питаются дополнительные устройства, в т.ч. и датчики. Я сразу перепаиваю на 470мкф х 16в, пока хватает. Но у нас сейчас работает Нано на самодельном расширительном шилде на базе LM2596-5.0 с предельной токоотдачей до 3 ампер. На выходе стоит конденсатор 560мкфх6.3в + 2х0.1н

Далее. Для управления по линии можно обойтись и даже 1 датчиком, но в этом случае придется ездить "змейкой" постоянно проверяя наличие края линии. Для машинок с 2-я датчиками и широкой линией, гораздо проще ставить датчики не снаружи, а внутри линии по краям. В этом случае Вы будете в состоянии контролировать состояние "потеря линии справа/слева" по порядку изменения состояний датчиков, чего нельзя сделать при установке датчиков снаружи линии. Для узких линий эту задачу можно легко решать установкой 3-х датчиков, один из которых ставится по центру линии. Два датчика, стоящие снаружи - не позволяют полноценно отследить потерю линии и являются "полумерой", также как и езда на одном датчике.

Для полноценного управления, найдите и почитайте про ПИД-регулировки. Это на самом деле очень просто:

П - пропорциональное управление: чем дальше и дольше робот отклоняется от оси линии (цели), тем большее воздействие надо приложить к моторам;

И - интегральное (накопленная сумма отклонения): чем дольше и стабильнее отклоняется робот от цели, тем больше надо применять воздействие, возвращающее его обратно;

Д - дифференциальное (разностное) управление: чем быстрее происходят изменения в отклонении от цели, тем больше должно быть возвращающее воздействие.

Собственно и все. ПИД-регулятор, это всего лишь "сумма" этих решений, применяемая к моторам тележки. Настройка ПИД-регулятора - это подбор весовых коэффициентов, уравнивающих все три составляющих для достижения плавного возвращения на линию. Собственно вот и вся "теория", ничего сложного тут нет.

Соответственно, если Вы хотите использовать ПИД-управление, вам потребуется более 2-х датчиков. Чем точнее Вы можете измерять сигнал отклонения от оси линии - тем точнее сможете подобрать ПИД-регулировку. Ситуация даже с 2-я датчиками в какой-то мере позволяет ПИД-регулировку, но уже на базе оценки и учета времени отклонений.. в этом плане, решение задачи сильно упрощается, если весь цикл работы loop() производится за одно и тоже контрольное время. Это то, ради чего приведенный пример выравнивает время измерения расстояния до заданного, даже если расстояние измерено "быстро". В целом, измерение за 4мсек позволяет вам видеть препятствия на около 500мм от датчика, что в большинстве случаев более чем достаточно.

Этих же 4мсек как правило хватает "за глаза", чтобы снять показания даже с аналоговых датчиков, обработать их и даже по непростой программе и подать управляющие воздействия на моторы. Управлять моторами чаще чем 8-16мсек - на практике ваще бессмысленно, если у Вас только нет желания пожечь драйвер моторов из-за выбросов самоиндукции. :)

Соответственно, отсюда правильнее перестроить программу "в целом":

1. Показания датчика расстояний снимать каждые 35мсек, если прошло время с предыдущего поиска препятствия. Иначе, снимаем показания с датчиков линии в течение тех же 4мсек. Можно снять даже по нескольку раз и "усреднить" бегущим средним или наложить цифровой фильтр или как-то ещё побороться с ошибками (они тоже случаются регулярно!);

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

3. если пришло время (прошло 8-16мсек), то изменяем состояния моторов. Обоих и ОДНОВРЕМЕННО. Не забываем, что если надо переключить мотор с одного направления на обратное, то необходимо погасить самоиндукцию небольшой паузой в 1-2мсек. Это же время выдерживаем при любом изменении моторов.

.. мы тоже начинали с писанины кучи методов управления моторами .. проходит с пониманием задачи. :)

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

P.S.

Может уже сложить все эти "покатушки" и рекомендации в какой-то "проект" на сайт, что скажет Alexander? :)

slava.ru38
Offline
Зарегистрирован: 28.11.2016

   Уважаемый Arhat109-2. Благодарю за пристальное внимание к моему проекту, который естественно считаю пробным и далеким от безошибочного. Однако не вскрыты все карты. Но начну с того, что уже с самого начала проекта, когда просто работал над движением по линии ( без всяких датчиков) "поиграв" со скоростью ШИМ, убедился в правдивости ваших слов об инерции. Поэтому в моем случае оптимальным была установка именно такого напряжения ШИМ. Больше - инерция выкидывала на поворотах, меньше - не тянула. 

   Вся правда в том, что данный проект - инициатива моего начальника. Сам я  - слесарь КИПиА. И Занимаюсь автоматизацией производстенного процесса, только не на роботизированном уровне. А на примитивном, но достаточным для нашего производства: датчики темп, уровня, ТРМ, LOGO.  Сложнее - нет необходимости. И с ПИД регулированием немного знаком. Пока только в робототехнике я для себя впервые узнал область применения ПИД. 

  И вот начальник задумал производство роботизировать. Это я думаю не последнее, что мне поручено сделать, а только начало. Суть в следующем: сделать прототип телеги (то, что я и сделал). И если все отточится и срастется - будет телега по больше с грузоподьемностью 50 - 150 кг, которая сама будет отвозить нужный груз по нужному маршруту. Поэтому моей задачей было просто сделать прототип. А там конечно же придется управлять уже более мощной нагрузкой. Скорее всего это будут редукторные двигателя. И поэтому там у вопроса с инерцией и "переносов веса в повороте" будут  уже совершенно другие показатели. Хотя конечно же суть проблемы не меняется.

  Поэтому впереди у меня еще будут вопросы по управлению мощной нагрузкой и шлифовка параметров под уже тот вес и мощностные характеристики.

  А вот про несимметричность драйвера моторов вы открыли мне глаза. Думал там симметрично все. А я думал, почему у меня моторы с разной ( не критично, но все же) частотой вращаются?

  С бросками по питанию при плохом питании еще не сталкивался. Так как использовал в испытания 12 в. БП от бесперебойника, чего по напряжению и емкости  хватает за глаза. Но учту этот момент. Но не совсем понял про контороль за таким состоянием с помощью диода и настройках SETUP. Еще раз почитаю, попробую осмыслить.

   По поводу стабилизатора: планируется только датчики линии (про ПИД подумаю об увеличении их количества), датчики препятствия и световая звуковая сигнализация. Всё. Наверно смысла нет питать их отдельно. Хотя разве что разгрузить мк.

 К слову, линия у меня шириной 50 мм и датчики стоят внутри по краям. Когда выходит один датчик за пределы - у второго есть запас для реакции, что уменьшает вероятность победы инерции. Но варианты с толщиной линии и количеством датчиков будем еще оттачивать для более плавного хода. Поэтому "змейку" вообще не хотелось бы.

  Но вот не совсем понял определение "управлять моторами не чаще 8-16мс". Что зачит "управлять моторами в течение 8-16мс? ( наверно глупый вопрос, но что поделаешь.) И также выдерживать время при любом изменении мотора - это в SETUP предусмотреть delay при изменении состояния мотора?

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Все что я писал, относится к "модельному варианту" - движению игрушечного робота по линиям. В т.ч. и на и для соревнований. Движение роботизированной и тяжелой тележки .. отдайте на расчет специалистам. Без моделирования и подбора номенклатуры деталей по требуемым параметрам - ваша моделька так и останется моделькой. Тут требуется полноценный конструкторский рассчет и проектирование, а не "горе от ума и нищеты". В т.ч. и вашего "насяльника", если Вы всего лишь "слесарь". Если студент - то сами знаете что и как надо делать, справитесь. :)

Да, если "тележка" и не в цеху, а с пушкой и на полигоне, то все одно - общие положения описаны верно, а детальный рассчет все одно делать в полноценном КБ. Ничего особо сложного нет. :)

slava.ru38
Offline
Зарегистрирован: 28.11.2016

нет границы для совершенства. Да и не в моем положении диктовать начальнику - что делать. Не получится - сам увидит это. Я могу лишь делать то, на что я способен. Ну разве с помощью ардуино и инженера механика нельзя создать такую тележку?  

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Можно. У нас в соседнем селе механик есть. Так и без Ардуино и начальников Т-34 и прочее железо восстанавливает до рабочего состояния. Даже на параде Победы каталось. Только, в таком разе, зачем Вам форум? :)

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Arhat109-2 пишет:

Можно. У нас в соседнем селе механик есть. Так и без Ардуино и начальников Т-34 и прочее железо восстанавливает до рабочего состояния. Даже на параде Победы каталось. Только, в таком разе, зачем Вам форум? :)

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

/*
#1 светодиод  (Led) пока мигает программа работает, перестала зависла программа
#2 УЗ датчики
датчик УЗ левый   trig ->14 (Utrasonic_L_trig_pin)
                  echo ->15 (Utrasonic_L_echo_pin)
датчик УЗ средний trig ->10 (Utrasonic_C_trig_pin)
                  echo ->11 (Utrasonic_C_echo_pin)
датчик УЗ правый  trig ->12 (Utrasonic_R_trig_pin)
                  echo ->13 (Utrasonic_R_echo_pin)
#3 датчики линии
датчик линии левый    ->19 (Line_Sensor_left_pin)   0 нормально / 1 фиксирует линию
датчик линии правый    ->18 (Line_Sensor_right_pin) 0 нормально / 1 фиксирует линию
#4 моторы
Мотор правый  ENA ->5 (M1_ENA_pin) скорость
              IN1 ->4 (M1_IN1_pin) вперед
              IN2 ->3 (M1_IN2_pin) назад
Мотор левый   ENA ->9 (M2_ENA_pin) скорость
              IN1 ->8 (M2_IN1_pin) вперед
              IN2 ->7 (M2_IN2_pin) назад

*/
//#1 мигающий светодиод
int Led_pin = 2; // задание номера вывода световой сигнализации
int Led = 0; // этой переменной устанавливаем состояние светодиода
//#4 моторы
const int M1_ENA_pin = 5; // Левый (А) мотор СКОРОСТЬ — ENA
const int M1_IN1_pin = 4; // Левый (А) мотор ВПЕРЕД — IN1
const int M1_IN2_pin = 3; // Левый (А) мотор НАЗАД — IN2
const int M1_Speed  = 90; // скорость левого мотора
const int M2_IN1_pin = 8; // Правый (В) мотор ВПЕРЕД — IN3
const int M2_IN2_pin = 7; // Правый (В) мотор НАЗАД — IN4
const int M2_ENA_pin = 9; // Правый (В) мотор СКОРОСТЬ — ENB
const int M2_Speed  = 90; // скорость левого мотора

// ****************** Основные команды движения ******************
void GO_stop()           {  // СТОП 
digitalWrite(M1_IN1_pin, 0);
digitalWrite(M1_IN2_pin, 0);
digitalWrite(M2_IN1_pin, 0);
digitalWrite(M2_IN2_pin, 0);
}
void GO_forward (int time) {  // ПРЯМО (время)
  digitalWrite(M1_IN2_pin, 0);
  digitalWrite(M1_IN1_pin, 1);
  analogWrite(M1_ENA_pin, M1_Speed);
  digitalWrite(M2_IN2_pin, 0);
  digitalWrite(M2_IN1_pin, 1);
  analogWrite(M2_ENA_pin, M2_Speed);
  delay (time);
  GO_stop ();
}
void GO_right (int time) { // ПОВОРОТ ВПРАВО (время)
  digitalWrite (M1_IN2_pin, 0);
  digitalWrite (M1_IN1_pin, 1);
  analogWrite (M1_ENA_pin, M1_Speed);
  digitalWrite (M2_IN2_pin, 0);
  digitalWrite (M2_IN1_pin, 0);
  delay (time);
  GO_stop ();
}
void GO_left (int time) { // ПОВОРОТ ВЛЕВО (время)
  digitalWrite (M1_IN2_pin, 0);
  digitalWrite (M1_IN1_pin, 0);
  digitalWrite (M2_IN2_pin, 0);
  digitalWrite (M2_IN1_pin, 1);
  analogWrite (M2_ENA_pin, M2_Speed);
  delay (time);
  GO_stop ();
}
//#3 УЗ датчики
const int Utrasonic_L_trig_pin = 14; // задание номера вывода левого trig УЗ датчика
const int Utrasonic_L_echo_pin = 15; // задание номера вывода левого echo УЗ датчика
const int Utrasonic_C_trig_pin = 10; // задание номера вывода центрального trig УЗ датчика
const int Utrasonic_C_echo_pin = 11; // задание номера вывода центрального echo УЗ дачика
const int Utrasonic_R_trig_pin = 12; // задание номера вывода правого trig УЗ датчика
const int Utrasonic_R_echo_pin = 13; // задание номера вывода правого echo УЗ датчика
// *********************Переменная измерение дистанции датчиками*************
unsigned int impulseTimeL = 0;
unsigned int impulseTimeC = 0;
unsigned int impulseTimeR = 0;
long distL = 0; // дистанция, измеренная левым УЗ датчиком
long distC = 0; // дистанция, измеренная центральным УЗ датчиком
long distR = 0; // дистанция, измеренная правым Уз датчиком
// **************************Измерение дистанции*********************
void izmdistL() {  // измерение дистанции левым УЗ датчиком
  digitalWrite(Utrasonic_L_trig_pin, 1);
  delay(10);
  digitalWrite(Utrasonic_L_trig_pin, 0); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
  impulseTimeL = pulseIn(Utrasonic_L_echo_pin, 1); // считывание расстояния с УЗ датчика
  distL = impulseTimeL / 58; // Пересчитываем в сантиметры
  delay(50);
}

void izmdistC() {// измерение дистанции центральным УЗ датчиком
  digitalWrite(Utrasonic_C_trig_pin, 1);
  delay(10);
  digitalWrite(Utrasonic_C_trig_pin, 0); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
  impulseTimeC = pulseIn(Utrasonic_C_echo_pin, 1); // считывание расстояния с УЗ датчика
  distC = impulseTimeC / 58; // Пересчитываем в сантиметры
  delay(50);
}

void izmdistR() {// измерение дистанции центральным УЗ датчиком
  digitalWrite(Utrasonic_R_trig_pin, 1);
  delay(10);
  digitalWrite(Utrasonic_R_trig_pin, 0); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
  impulseTimeR = pulseIn(Utrasonic_R_echo_pin, 1); // считывание расстояния с УЗ датчика
  distR = impulseTimeR / 58; // Пересчитываем в сантиметры
  delay(50);
}


// #4 датчики линии
const int Line_Sensor_left_pin = 19; // вход левого датчика линии
const int Line_Sensor_right_pin = 18; // вход правого датчика линии
bool Line_Sensor_left; // статус левого сенсора
bool Line_Sensor_right; // статус правого сенсора

void setup () {
  Serial.begin(9600); // запускаем серийный порт (скорость 9600)
  //#1 мигающий светодиод
  pinMode(Led_pin, OUTPUT); //Подключим светодиод
  digitalWrite(Led_pin, Led = 0);
  //#2 УЗ датчики
  pinMode(Utrasonic_L_trig_pin, OUTPUT); // задание режима работы вывода левого trig УЗ датчика
  pinMode(Utrasonic_L_echo_pin, INPUT); // задание режима работы вывода левого echo УЗ датчика
  pinMode(Utrasonic_C_trig_pin, OUTPUT); // задание режима работы вывода центрального trig УЗ датчика
  pinMode(Utrasonic_C_echo_pin, INPUT); // задание режима работы вывода центрального echo УЗ датчика
  pinMode(Utrasonic_R_trig_pin, OUTPUT); // задание режима работы вывода правого trig УЗ датчика
  pinMode(Utrasonic_R_echo_pin, INPUT); // задание ражима работы вывода правого echo УЗ датчика
  // #3 датчики линии
  pinMode (Line_Sensor_left_pin, INPUT); // определением pin левого датчика линии
  pinMode (Line_Sensor_right_pin, INPUT); // определением pin правого датчика линии
  //#4 моторы
  pinMode (M2_IN2_pin, OUTPUT); // Правый (В) мотор НАЗАД
  pinMode (M2_IN1_pin, OUTPUT); // Правый (В) мотор ВПЕРЕД
  pinMode (M1_IN2_pin, OUTPUT); // Левый (А) мотор НАЗАД
  pinMode (M1_IN1_pin, OUTPUT); // Левый (А) мотор ВПЕРЕД
}

void loop () {
  //#1
  static uint32_t past_1 = 0;
  if (millis() - past_1 >= 300) {// если подошло время
    past_1 = millis();
    digitalWrite(Led_pin, Led = ! Led); // переключим светодиод
  }
  //#2 УЗ датчики
  izmdistL();
  izmdistC();
  izmdistR();
  Serial.println(distL);
  Serial.println(distC);
  Serial.println(distR);
  //#3 датчики линии
  Line_Sensor_left = digitalRead (Line_Sensor_left_pin); // считываем сигнал с левого датчика полосы
  Line_Sensor_right = digitalRead (Line_Sensor_right_pin); // считываем сигнал с правого датичка полосы
  //#4 моторы
  if (distL > 50 && distC > 50 && distR > 50) { // если измеренная дистанция больше 50 сантиметров - едем
    if (! Line_Sensor_left && ! Line_Sensor_right ) // БЕЛЫЙ — БЕЛЫЙ — едем ПРЯМО
      GO_forward(10) ;// проехать прямо 10 миллисек
    else if (! Line_Sensor_left  && Line_Sensor_right) // ЧЕРНЫЙ - БЕЛЫЙ — поворот ВЛЕВО
      GO_left(10)    ;// проехать влево 10 миллисек
    else if (Line_Sensor_left && ! Line_Sensor_right) // БЕЛЫЙ - ЧЕРНЫЙ — поворот ВПРАВО
      GO_right(10)   ;// проехать вправо 10 миллисек
  }
}

 

slava.ru38
Offline
Зарегистрирован: 28.11.2016

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

  Но есть некоторые вопросы.

1) Для чего нужны строки 50, 59, 68. Это то о чем говорил Arhat109-2?

Arhat109-2 пишет:

3. если пришло время (прошло 8-16мсек), то изменяем состояния моторов. Обоих и ОДНОВРЕМЕННО. Не забываем, что если надо переключить мотор с одного направления на обратное, то необходимо погасить самоиндукцию небольшой паузой в 1-2мсек. Это же время выдерживаем при любом изменении моторов.

2) Почти все, что у меня было в SETUP, вы инициализировали до него, а в нем только указали режимы работы портов. В чем разница? И имеет ли это значительное влияние на программу?

3) Мы уже прошли, что при измерении оптимальней регламентировать таймаут. Вы его не указываете (строки 89, 98, 107) . Почему?

4) Зачем в строках 91, 100, 109 такая большая пауза? И нужна ли она там вообще.

5) Строки 116, 117 имеетсе ввиду функция boolean? Если да, то можно писать не полностью, а bool?

Вот мой отредактированный скетч. Правда пока без звука и света. Над ними пока поработаю с учетом многозадачности. А пока так вроде работает. До конца осмысли теперь, что имел ввиду andriano:

andriano пишет:

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

строки 108, 118, 128 - теперь замер расстояния не влияет на выполнение общей прораммы

//Робот с функцией следования по белой  полосе 

// **********************Установка выводов моторов ************************
int MotorLeftSpeed = 5; // Левый (А) мотор СКОРОСТЬ — ENA
int MotorLeftForward = 4; // Левый (А) мотор ВПЕРЕД — IN1
int MotorLeftBack = 3; // Левый (А) мотор НАЗАД — IN2
int MotorRightForward = 8; // Правый (В) мотор ВПЕРЕД — IN3
int MotorRightBack = 7; // Правый (В) мотор НАЗАД — IN4
int MotorRightSpeed = 9; // Правый (В) мотор СКОРОСТЬ — ENB
int duration;

// **********************Установка выводов УЗ датчиков***********************
int trigPinL = 14; // задание номера вывода левого trig УЗ датчика
int echoPinL = 15; // задание номера вывода левого echo УЗ датчика
int trigPinC = 10; // задание номера вывода центрального trig УЗ датчика
int echoPinC = 11; // задание номера вывода центрального echo УЗ дачика
int trigPinR = 12; // задание номера вывода правого trig УЗ датчика
int echoPinR = 13; // задание номера вывода правого echo УЗ датчика

// ********************* Установка выводов датчиков линии *******************
const int LineSensorLeft = 19; // вход левого датчика линии
const int LineSensorRight = 18; // вход правого датчика линии
int SL; // статус левого сенсора
int SR; // статус правого сенсора

// *********************Переменная измерение дистанции датчиками*************

unsigned int impulseTimeL=0; 
unsigned int impulseTimeC=0; 
unsigned int impulseTimeR=0; 
long distL=0; // дистанция, измеренная левым УЗ датчиком
long distC=0; // дистанция, измеренная центральным УЗ датчиком
long distR=0; // дистанция, измеренная правым Уз датчиком


// *********************************** SETUP ********************************
void setup ()
{
  Serial.begin(9600); // запускаем серийный порт (скорость 9600)
  
//*************** Задаем контакты моторов****************
pinMode (MotorRightBack, OUTPUT); // Правый (В) мотор НАЗАД
pinMode (MotorRightForward, OUTPUT); // Правый (В) мотор ВПЕРЕД
pinMode (MotorLeftBack, OUTPUT); // Левый (А) мотор НАЗАД
pinMode (MotorLeftForward, OUTPUT); // Левый (А) мотор ВПЕРЕД
delay(duration);

//*************** Задаем контакты датчиков полосы**************
pinMode (LineSensorLeft, INPUT); // определением pin левого датчика линии
pinMode (LineSensorRight, INPUT); // определением pin правого датчика линии


// ***************Задание режимов выводов УЗ датчиков**********************

pinMode(trigPinL, OUTPUT); // задание режима работы вывода левого trig УЗ датчика
pinMode(echoPinL, INPUT); // задание режима работы вывода левого echo УЗ датчика
pinMode(trigPinC, OUTPUT); // задание режима работы вывода центрального trig УЗ датчика
pinMode(echoPinC, INPUT); // задание режима работы вывода центрального echo УЗ датчика
pinMode(trigPinR, OUTPUT); // задание режима работы вывода правого trig УЗ датчика
pinMode(echoPinR, INPUT); // задание ражима работы вывода правого echo УЗ датчика
}

// ****************** Основные команды движения ******************
void forward (int a, int sa) // ВПЕРЕД
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, HIGH);
analogWrite (MotorRightSpeed, sa);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, HIGH);
analogWrite (MotorLeftSpeed, sa);
delay (a);
}
void right (int b, int sb) // ПОВОРОТ ВПРАВО (одна сторона)
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, LOW);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, HIGH);
analogWrite (MotorLeftSpeed, sb);
delay (b);
}
void left (int k, int sk) // ПОВОРОТ ВЛЕВО (одна сторона)
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, HIGH);
analogWrite (MotorRightSpeed, sk);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, LOW);
delay (k);
}
void stopp (int f) // СТОП
{
digitalWrite (MotorRightBack, LOW);
digitalWrite (MotorRightForward, LOW);
digitalWrite (MotorLeftBack, LOW);
digitalWrite (MotorLeftForward, LOW);
delay (f);
}

// **************************Измерение дистанции*********************

void izmdistL() // измерение дистанции левым УЗ датчиком
{
digitalWrite(trigPinL, HIGH);
delay(10);
digitalWrite(trigPinL, LOW); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
impulseTimeL = pulseIn(echoPinL, HIGH,3000); // считывание расстояния с УЗ датчика
distL=impulseTimeL/58; // Пересчитываем в сантиметры 
delay(10);
}

void izmdistC() // измерение дистанции центральным УЗ датчиком
{
digitalWrite(trigPinC, HIGH);
delay(10);
digitalWrite(trigPinC, LOW); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
impulseTimeC = pulseIn(echoPinC, HIGH,3000); // считывание расстояния с УЗ датчика
distC=impulseTimeC/58; // Пересчитываем в сантиметры 
delay(10);
}

void izmdistR() // измерение дистанции центральным УЗ датчиком
{
digitalWrite(trigPinR, HIGH);
delay(10);
digitalWrite(trigPinR, LOW); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
impulseTimeR = pulseIn(echoPinR, HIGH,3000); // считывание расстояния с УЗ датчика
distR=impulseTimeR/58; // Пересчитываем в сантиметры 
delay(10);
}

// *********************************** LOOP *********************************
// ********************** Режим следования по ЛИНИИ *************************
void loop ()
{

// ************************ Измерение дистанции************************
  izmdistL();
  izmdistC();
  izmdistR();
  Serial.println(distL);
  Serial.println(distC);
  Serial.println(distR);
  if (distL>40 || distL==0 && distC>40 || distC==0 && distR>40 || distR==0) // если измеренная дистанция больше 40 сантиметров или равна 0 -  едем 
  {   
     SL = digitalRead (LineSensorLeft); // считываем сигнал с левого датчика полосы
     SR = digitalRead (LineSensorRight); // считываем сигнал с правого датичка полосы

      // ************************* Следование по черной линии ***********************
      // РОБОТ на полосе — едем прямо
      if (SL == LOW & SR == LOW ) // БЕЛЫЙ — БЕЛЫЙ — едем ПРЯМО
      {
      forward (10, 130);// ПРЯМО (время, скорость)
      }
      // РОБОТ начинает смещаться с полосы — подруливаем
      else if (SL == LOW & SR == HIGH) // ЧЕРНЫЙ - БЕЛЫЙ — поворот ВЛЕВО
      {
      left (10, 130);// поворот ВЛЕВО (время, скорость)
      }
      else if (SL == HIGH & SR == LOW) // БЕЛЫЙ - ЧЕРНЫЙ — поворот ВПРАВО
      {
      right (10, 130);// поворот ВПРАВО (время, скорость)
      }
     // ФИНИШ - РОБОТ видит обоими датчиками полосу
     else if (SL == HIGH & SR == HIGH) // ЧЕРНЫЙ - ЧЕРНЫЙ - СТОП
     {
     stopp (10);// СТОП
     }
   }
else  // если измеренная дистанция меньше или равна минимальной - стоим
   {
     stopp (10); // СТОП
   }
}   

 

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Но пока еще над ним работаю, чтобы уйти от деления в строках 109, 119, 129. Нужно добавить индикацию светодиодом при рабочем состоянии. Но хочу, чтобы светил через разные промежутки времени. Например так 

// Эти переменные хранят временной шаблон для интервалов мигания
// и текущее состояние светодиода
int ledPin = 13; // номер пина со светодиодом
int ledState = LOW; // состояние светодиода
// последний момент времени, когда состояние светодиода изменялось
unsigned long previousMillis = 0;
long OnTime = 250; // длительность свечения светодиода (в миллисекундах)
long OffTime = 750; // светодиод не горит (в миллисекундах)
 
void setup() {
  // устанавливаем цифровой пин со светодиодом как ВЫХОД
  pinMode(ledPin, OUTPUT);
}
 
void loop() {
  // выясняем не настал ли момент сменить состояние светодиода
 
  unsigned long currentMillis = millis(); // текущее время в миллисекундах
  
  // если светодиод включен и светится больше чем надо
  if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
  {
    ledState = LOW; // выключаем
    previousMillis = currentMillis; // запоминаем момент времени
    digitalWrite(ledPin, ledState); // реализуем новое состояние
  }
  else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
  {
    ledState = HIGH; // выключаем
    previousMillis = currentMillis ; // запоминаем момент времени
    digitalWrite(ledPin, ledState); // реализуем новое состояние
  }
}

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

 И вообще по мере вникания в то, о чем шла речь в ветке - шлифовать для ухода от "примитивности". Особенно много есть над чем подумать после примеров скетчей и дополнительной теории Так что проект продолжается...  

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/*
#1 моторы
Мотор правый  ENA ->5 (M1_ENA_pin) скорость
              IN1 ->4 (M1_IN1_pin) вперед
              IN2 ->3 (M1_IN2_pin) назад
Мотор левый   ENA ->9 (M2_ENA_pin) скорость
              IN1 ->8 (M2_IN1_pin) вперед
              IN2 ->7 (M2_IN2_pin) назад
*/
class Cl_Motor {
  public:
    Cl_Motor(byte _1pin, byte _2pin, byte _3pin, byte _speed); // конструктор
    void in_setup(); // функцию засунуть в setup() программы
    void FORWARD(); // запустить мотор вперед
    void BACKWARD(); // запустить мотор назад
    void STOP();// остановить мотор
  private:
    byte ENA_pin; // пин  ENA
    byte N1_pin; // пин  N1
    byte N2_pin; // пин  N2
    byte Speed; // скорость мотора
    byte Motor;// 1 мотор вращается вперед/2 мотор вращается назад / 0 нет

};
Cl_Motor::Cl_Motor(byte _1pin, byte _2pin, byte _3pin, byte _speed) { // конструктор
  ENA_pin = _1pin; // пин  ENA
  N1_pin = _2pin; // пин  N1
  N2_pin = _3pin; // пин  N2
  Speed = _speed; // скорость мотора
}
void Cl_Motor::in_setup() { // функцию засунуть в setup() программы
  Motor = 0;
  analogWrite (ENA_pin, Speed);
  pinMode (N1_pin, OUTPUT);
  digitalWrite(N1_pin, 0);
  pinMode (N2_pin, OUTPUT);
  digitalWrite(N2_pin, 0);
}
void Cl_Motor::FORWARD() { // запустить мотор вперед
  if (Motor != 1) {
    Motor = 1;
    digitalWrite(N1_pin, 1);
    digitalWrite(N2_pin, 0);
  }
}
void Cl_Motor::BACKWARD() { // запустить мотор назад
  if (Motor != 2) {
    Motor = 2;
    digitalWrite(N1_pin, 0);
    digitalWrite(N2_pin, 1);
  }
}
void Cl_Motor::STOP() { // остановить мотор
  if (Motor != 0) {
    Motor = 0;
    digitalWrite(N1_pin, 0);
    digitalWrite(N2_pin, 0);
  }
}

// #1 моторы
Cl_Motor M1(5, 4, 3, 255); // создать мотор 1 (ENA=5,N1=4,N2=3,SPEED=255) 255 максимальная скорость
Cl_Motor M2(9, 8, 7, 255); // создать мотор 2 (ENA=9,N1=8,N2=7,SPEED=255) 255 максимальная скорость
void setup() {
  // #1 моторы
  M1.in_setup();// инициализировать мотор 1
  M2.in_setup();// инициализировать мотор 2
  // движение вперед
  M1.FORWARD();
  M2.FORWARD();
  delay (60000); // пауза 1 минута
  // движение назад
  M1.BACKWARD();
  M2.BACKWARD();
  delay (60000); // пауза 1 минута
  // вращение на месте
  M1.FORWARD();
  M2.BACKWARD();
  delay (60000); // пауза 1 минута
  // остановка
  M1.STOP();
  M2.STOP();
  delay (60000); // пауза 1 минута
}

void loop() {
  // #1 моторы

}

И наконец

/*
#1 светодиод  (Led) пока мигает программа работает, перестала зависла программа
#2 УЗ датчики
датчик УЗ левый   trig ->14 (L_TRIG_pin)
                  echo ->15 (L_ECHO_pin)
датчик УЗ средний trig ->10 (Utrasonic_C_trig_pin)
                  echo ->11 (C_ECHO_pin)
датчик УЗ правый  trig ->12 (R_TRIG_pin)
                  echo ->13 (R_ECHO_pin)
#3 датчики линии
датчик линии левый    ->19 (L_LinSen_pin)   0 нормально / 1 фиксирует линию
датчик линии правый    ->18 (R_LinSen_pin) 0 нормально / 1 фиксирует линию
#4 моторы
Мотор правый  ENA ->5 (M1_ENA_pin) скорость
              IN1 ->4 (M1_IN1_pin) вперед
              IN2 ->3 (M1_IN2_pin) назад
Мотор левый   ENA ->9 (M2_ENA_pin) скорость
              IN1 ->8 (M2_IN1_pin) вперед
              IN2 ->7 (M2_IN2_pin) назад

*/
class Cl_Motor {
  public:
    Cl_Motor(byte _1pin, byte _2pin, byte _3pin, byte _speed); // конструктор
    void in_setup(); // функцию засунуть в setup() программы
    void FORWARD(); // запустить мотор вперед
    void BACKWARD(); // запустить мотор вперед
    void STOP();// остановить мотор
  private:
    byte ENA_pin; // пин  ENA
    byte N1_pin; // пин  N1
    byte N2_pin; // пин  N2
    byte Speed; // скорость мотора
    byte Motor;// 1 мотор вращается вперед/2 мотор вращается назад / 0 нет
};
Cl_Motor::Cl_Motor(byte _1pin, byte _2pin, byte _3pin, byte _speed) { // конструктор
  ENA_pin = _1pin; // пин  ENA
  N1_pin = _2pin; // пин  N1
  N2_pin = _3pin; // пин  N2
  Speed = _speed; // скорость мотора
}
void Cl_Motor::in_setup() { // функцию засунуть в setup() программы
  Motor = 0;
  analogWrite (ENA_pin, Speed);
  pinMode (N1_pin, OUTPUT);
  digitalWrite(N1_pin, 0);
  pinMode (N2_pin, OUTPUT);
  digitalWrite(N2_pin, 0);
}
void Cl_Motor::FORWARD() { // запустить мотор вперед
  if (Motor != 1) {
    Motor = 1;
    digitalWrite(N1_pin, 1);
    digitalWrite(N2_pin, 0);
  }
}
void Cl_Motor::BACKWARD() { // запустить мотор назад
  if (Motor != 2) {
    Motor = 2;
    digitalWrite(N1_pin, 0);
    digitalWrite(N2_pin, 1);
  }
}
void Cl_Motor::STOP() { // остановить мотор
  if (Motor != 0) {
    Motor = 0;
    digitalWrite(N1_pin, 0);
    digitalWrite(N2_pin, 0);
  }
}

//#1 мигающий светодиод
const int Led_pin = 2; // задание номера вывода световой сигнализации
bool Led = 0; // этой переменной устанавливаем состояние светодиода
//#4 моторы
Cl_Motor M1(5, 4, 3, 255); // создать мотор 1 (ENA=5,N1=4,N2=3,SPEED=255) 255 максимальная скорость
Cl_Motor M2(9, 8, 7, 255); // создать мотор 2 (ENA=9,N1=8,N2=7,SPEED=255) 255 максимальная скорость
//#3 УЗ датчики
const int L_TRIG_pin = 14; // задание номера вывода левого trig УЗ датчика
const int L_ECHO_pin = 15; // задание номера вывода левого echo УЗ датчика
const int C_TRIG_pin = 10; // задание номера вывода центрального trig УЗ датчика
const int C_ECHO_pin = 11; // задание номера вывода центрального echo УЗ дачика
const int R_TRIG_pin = 12; // задание номера вывода правого trig УЗ датчика
const int R_ECHO_pin = 13; // задание номера вывода правого echo УЗ датчика
long distL = 0; // дистанция, измеренная левым УЗ датчиком
long distC = 0; // дистанция, измеренная центральным УЗ датчиком
long distR = 0; // дистанция, измеренная правым Уз датчиком
// **************************Измерение дистанции*********************
long Utrasonic(int TRIG_pin, int ECHO_pin) {  // измерение дистанции левым УЗ датчиком
  digitalWrite(TRIG_pin, 1);
  delay(10);
  digitalWrite(TRIG_pin, 0); // импульс 10мс на вывод trig УЗ датчика для измерения расстояния
  return pulseIn(ECHO_pin, 1) / 58;
}
// #4 датчики линии
const int L_LinSen_pin = 19; // вход левого датчика линии
const int R_LinSen_pin = 18; // вход правого датчика линии
bool L_LinSen; // статус левого сенсора
bool R_LinSen; // статус правого сенсора

void setup () {
  Serial.begin(9600); // запускаем серийный порт (скорость 9600)
  //#1 мигающий светодиод
  pinMode(Led_pin, OUTPUT); //Подключим светодиод
  digitalWrite(Led_pin, Led = 0);
  //#2 УЗ датчики
  pinMode( L_TRIG_pin, OUTPUT); // задание режима работы вывода левого trig УЗ датчика
  pinMode( L_ECHO_pin, INPUT); // задание режима работы вывода левого echo УЗ датчика
  pinMode( C_TRIG_pin, OUTPUT); // задание режима работы вывода центрального trig УЗ датчика
  pinMode( C_ECHO_pin, INPUT); // задание режима работы вывода центрального echo УЗ датчика
  pinMode( R_TRIG_pin, OUTPUT); // задание режима работы вывода правого trig УЗ датчика
  pinMode( R_ECHO_pin, INPUT); // задание ражима работы вывода правого echo УЗ датчика
  // #3 датчики линии
  pinMode (L_LinSen_pin, INPUT); // определением pin левого датчика линии
  pinMode (R_LinSen_pin, INPUT); // определением pin правого датчика линии
  //#4 моторы
  M1.in_setup();// инициализировать мотор 1
  M2.in_setup();// инициализировать мотор 2
}

void loop () {
  static uint32_t past_1 = 0;
  if (millis() - past_1 >= 500) {// если подошло 0,5 секунды
    past_1 = millis();
    //#1
    digitalWrite(Led_pin, Led = ! Led); // переключим светодиод
    //#2 УЗ датчики
    distL = Utrasonic( L_TRIG_pin , L_ECHO_pin);
    Serial.println(distL);
    distC = Utrasonic( C_TRIG_pin , C_ECHO_pin);
    Serial.println(distC);
    distL = Utrasonic( R_TRIG_pin , R_ECHO_pin);
    Serial.println(distR);
    //#3 датчики линии
    L_LinSen = digitalRead (L_LinSen_pin); // считываем сигнал с левого датчика полосы
    R_LinSen = digitalRead (R_LinSen_pin); // считываем сигнал с правого датичка полосы
    //#4 моторы
    if (distL > 50 && distC > 50 && distR > 50 && ! L_LinSen )   M1.FORWARD();
    else  M1.STOP();
    if (distL > 50 && distC > 50 && distR > 50 && ! R_LinSen )   M2.FORWARD();
    else  M2.STOP();
  }
}

 

Logik
Offline
Зарегистрирован: 05.08.2014

Arhat109-2 пишет:

ПИД-регулировку, ..., решение задачи сильно упрощается, если весь цикл работы loop() производится за одно и тоже контрольное время. Это то, ради чего приведенный пример выравнивает время измерения расстояния до заданного, даже если расстояние измерено "быстро". В целом, измерение за 4мсек позволяет вам видеть препятствия на около 500мм от датчика, что в большинстве случаев более чем достаточно.

 

Перестаньте эту чепуху писать! Требовато постоянство времени loop - глупость несусветная. Вам уже и andriano про это писал. ПИД не требует ничего такого. Достаточно в численном диференцировании и интегрировании использовать реальное время между обсчетами и все. Если это кажется сложным (хотя чегож тут может быть сложного?!) то можна интерполировать показания датчиков на любое заданое время и обеспечить постоянство времени для ПИД при непостоянном loop. Как удобней в общем.  

Да, перед ПИД полезно сигнал подфильтровать слеганца, Кальманом например, особенно для составляющей Д пользительно будет. А для этого датчики надо опрашивать чаще чем ПИД просчитывать, что опять же разумней при максимально быстром loop.

ПС. И сами составляющие И и Д тоже слеганца фильтрануть. Ни то ни другое теоретически не могут изменится мгновенно, и резкие их изменения принимать во внимание нет смысла,  значить Кальман и тут уместен.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

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

Исправил - опечатка у вас была. Строка 132 не distL, а distR.

Загрузил - работает. Но все-таки тормозит реакция на изменение статуса датчиков линии. Об этом я спрашивал выше. 

Пока вникаю в ваш код, объясните мне "балбесу" то, о чем спрашивал ранее.

slava.ru38 пишет:

Но есть некоторые вопросы.

2) Почти все, что у меня было в SETUP, вы инициализировали до него, а в нем только указали режимы работы портов. В чем разница? И имеет ли это значительное влияние на программу?

3) Мы уже прошли, что при измерении расстояния оптимальней регламентировать таймаут. Вы его не указываете (строка 93) . Почему? Из-за этого, по всей видимости, и подтормаживает реакция на изменение статуса датчиков линии.

Ну и до кучи спрошу:
1) строки 22, 23, 29 неизвестные мне термины. Ни здесь http://arduino.ru/Reference , ни здесь https://www.arduino.cc/en/Reference/HomePage подобного не нашел. А может плохо искал.  Где о них почитать?
2) в строке значок "::" тоже мне неизвестен. И в тех же ссылках не нашел о нем ничего.
3) В LOOP вся операция стоит в фигурных скобках после условия с работой светодиода. Это сделано для индикации работоспособности программы? Если все зависло - это будет видно по диоду?
slava.ru38
Offline
Зарегистрирован: 28.11.2016

qwone пишет:

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

Ну и конечно буду признателен за 2 серию

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

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

http://arduino.ru/Hacking/LibraryTutorial. Позже запихну в библиотеку и вы будете просто подключать их в своей программе.

 Любая программа становится только тогда "рабочей",когда залита в устройство и это устройство работает. А у меня нет вашего устройства. Так что я точно не смогу дошлифовать напильником свою программу. Это придется вам. У меня нет ультрозвукового датчика. И я еще с ним не работал.  Так что в этой части я пользуюсь вашим куском.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Logik, Конечно можно учитывать реальное время промеж циклов ПИД и требование одинаковости прохождения loop() не является критичным. Я жеж так и написал "для удобства" ... и когда время исполнения loop() фиксировано, куда как проще не заморачиваться с реальным временем и вовсе.

Ну и конечно, требуется фильтрация данных. Для этого время исполнения loop() можно сделать не только фиксированным, но и озаботиться его небольшим значением .. меньше чем частота ПИД управления.

А так-то да, можно и реальное время считать и даже через float, и датчики и коэффициенты ПИД во float гонять .. только на паре датчиков - бессмысленно это всё. :)

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

qwone, что будет делать ваш код, если он наткнется на "перекресток" и оба датчика выдадут "черное" (линия)? :)

slava.ru38
Offline
Зарегистрирован: 28.11.2016

qwone пишет:

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

http://arduino.ru/Hacking/LibraryTutorial. Позже запихну в библиотеку и вы будете просто подключать их в своей программе.

 Любая программа становится только тогда "рабочей",когда залита в устройство и это устройство работает. А у меня нет вашего устройства. Так что я точно не смогу дошлифовать напильником свою программу. Это придется вам. У меня нет ультрозвукового датчика. И я еще с ним не работал.  Так что в этой части я пользуюсь вашим куском.

Все вопросы по коду отпали. Ну насчет "шлифовки", тут я солидарен с вами. 

Только не совсем понятно, чего мы в данном примере с классами добились. То, что программа меньше памяти занимает - это я увидел. Но экономия незначительная. Функции ведь выполняются и в моем "примитивном" коде, функциональности ведь вы не добавили.  Втолкуйте пожалуйста, чем ваш код лучше моего (ну кроме удобочитаемости и меньшего размера занимаемой памяти). Ведь результат: движение робота по линии с датчиками препятствия - достигнут с обоими кодами.

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

Однако все же все равно благодарю за ликбез

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

slava.ru38 пишет:

Втолкуйте пожалуйста, чем ваш код лучше моего (ну кроме удобочитаемости и меньшего размера занимаемой памяти).

 

ВЫ всерьез рассчитываете, что кто-то здесь будет пересказывать сотни страниц монографий?

Если нитересно, почитайте сами https://www.ozon.ru/context/detail/id/3905587/

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Arhat109-2 пишет:

qwone, что будет делать ваш код, если он наткнется на "перекресток" и оба датчика выдадут "черное" (линия)? :)

Ну если робот мужчина - повернёт на лево, женщина - обратное )))

Dimmm
Dimmm аватар
Offline
Зарегистрирован: 07.11.2016

так долго собачитесь

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Сам файл программы 

/*
#1 кнопки
кнопка 1 -> 10 (btn_LF_pin) левый вперед 0 нажата / 1 нет
кнопка 2 -> 11 (btn_LB_pin) левый назад 0 нажата / 1 нет
кнопка 3 -> 12 (btn_RF_pin) правый вперед 0 нажата / 1 нет
кнопка 4 -> 13 (btn_RB_pin) правый назад 0 нажата / 1 нет
#2 моторы
Мотор правый  ENA,IN1,IN2 ->5,4,3  скорость,вперед,назад
Мотор левый   ENA,IN1,IN2 ->9,8,7  скорость,вперед,назад
*/
// #1 кнопки
const int btn_LF_pin = 10;
bool btn_LF;
const int btn_LB_pin = 11;
bool btn_LB;
const int btn_RF_pin = 12;
bool btn_RF;
const int btn_RB_pin = 13;
bool btn_RB;
// #2 моторы
#include "Cl_Motor.h"
Cl_Motor M1(5, 4, 3, 255); // создать мотор 1 (ENA=5,N1=4,N2=3,SPEED=255) 255 максимальная скорость
Cl_Motor M2(9, 8, 7, 255); // создать мотор 2 (ENA=9,N1=8,N2=7,SPEED=255) 255 максимальная скорость
void setup() {
  // #1 кнопки
  pinMode(btn_LF_pin, INPUT_PULLUP);
  pinMode(btn_LB_pin, INPUT_PULLUP);
  pinMode(btn_RF_pin, INPUT_PULLUP);
  pinMode(btn_RB_pin, INPUT_PULLUP);
  // #2 моторы
  M1.in_setup();// инициализировать мотор 1
  M2.in_setup();// инициализировать мотор 2
}

void loop() {
  // #1 кнопки
  btn_LF = digitalRead(btn_LF_pin);
  btn_LB = digitalRead(btn_LB_pin);
  btn_RF = digitalRead(btn_RF_pin);
  btn_RB = digitalRead(btn_RB_pin);
  // #2 моторы
  if (! btn_LF && btn_LB) M1.FORWARD();// движение вперед левого мотора
  else if ( btn_LF && ! btn_LB) M1.BACKWARD(); // движение назад левого мотора
  else M1.STOP(); // остановка левого мотора
  
  if (! btn_RF && btn_RB) M2.FORWARD();// движение вперед правого мотора
  else if ( btn_RF && ! btn_RB) M2.BACKWARD(); // движение назад правого мотора
  else M2.STOP(); // остановка правого мотора
}

И надо забросить в папку скетча файлы Cl_Motor.h 

// Cl_Motor.h
#ifndef Cl_Motor_h
#define Cl_Motor_h

#include "Arduino.h"

class Cl_Motor {
  public:
    Cl_Motor(byte _1pin, byte _2pin, byte _3pin, byte _speed); // конструктор
    void in_setup(); // функцию засунуть в setup() программы
    void FORWARD(); // запустить мотор вперед
    void BACKWARD(); // запустить мотор вперед
    void STOP();// остановить мотор
  private:
    byte ENA_pin; // пин  ENA
    byte N1_pin; // пин  N1
    byte N2_pin; // пин  N2
    byte Speed; // скорость мотора
    byte Motor;// 1 мотор вращается вперед/2 мотор вращается назад / 0 нет

};
#endif // Cl_Motor.h

и  Cl_Motor.cpp

// Cl_Motor.cpp

#include "Arduino.h"
#include "Cl_Motor.h"

Cl_Motor::Cl_Motor(byte _1pin, byte _2pin, byte _3pin, byte _speed) { // конструктор
  ENA_pin = _1pin; // пин  ENA
  N1_pin = _2pin; // пин  N1
  N2_pin = _3pin; // пин  N2
  Speed = _speed; // скорость мотора
}
void Cl_Motor::in_setup() { // функцию засунуть в setup() программы
  Motor = 0;
  analogWrite (ENA_pin, Speed);
  pinMode (N1_pin, OUTPUT);
  digitalWrite(N1_pin, 0);
  pinMode (N2_pin, OUTPUT);
  digitalWrite(N2_pin, 0);
}
void Cl_Motor::FORWARD() { // запустить мотор вперед
  if (Motor != 1) {
    Motor = 1;
    digitalWrite(N1_pin, 1);
    digitalWrite(N2_pin, 0);
  }
}
void Cl_Motor::BACKWARD() { // запустить мотор назад
  if (Motor != 2) {
    Motor = 2;
    digitalWrite(N1_pin, 1);
    digitalWrite(N2_pin, 0);
  }
}
void Cl_Motor::STOP() { // остановить мотор
  if (Motor != 0) {
    Motor = 0;
    digitalWrite(N1_pin, 0);
    digitalWrite(N2_pin, 0);
  }
}

 

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Ваш loop() , без принтов будет отрабатываться за сотню микросекунд примерно .. и? Датчик, едущий "по краю" через раз будет выдавать "черное" или "белое" .. что сделает ваш код очень хорошим средством "спалить" мотор или его драйвер. ТАК делать - не стоит.. :) В том смысле, что вопрос инерции в вашем варианте отсутствует как класс вовсе.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Arhat109-2 пишет:

Ваш loop() , без принтов будет отрабатываться за сотню микросекунд примерно .. и? Датчик, едущий "по краю" через раз будет выдавать "черное" или "белое" .. что сделает ваш код очень хорошим средством "спалить" мотор или его драйвер. ТАК делать - не стоит.. :) В том смысле, что вопрос инерции в вашем варианте отсутствует как класс вовсе.

вы имеете ввиду чей loop? мой или qwone?

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Пардон, глупый вопрос.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Если руководствоваться этой информацией http://robocraft.ru/blog/electronics/772.html

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

/*  Ultrasonic.ino
#1 УЗ датчики
датчик УЗ левый   ->14,15 (L_TRIG_pin,L_ECHO_pin)
датчик УЗ средний ->10,11 (C_TRIG_pin,C_ECHO_pin)
датчик УЗ правый  ->12,13 (R_TRIG_pin,R_ECHO_pin)
#2 светодиод  (Led_pin)->2  1 горит (предмет в опасной близости)/ 0 не горит (путь свободен)
*/
//#1 УЗ датчики
const uint32_t dangerous_distance = 50 * 58 ;// 50 расстояние в см
const int L_TRIG_pin = 14; // задание номера вывода левого trig УЗ датчика
const int L_ECHO_pin = 15; // задание номера вывода левого echo УЗ датчика
const int C_TRIG_pin = 10; // задание номера вывода центрального trig УЗ датчика
const int C_ECHO_pin = 11; // задание номера вывода центрального echo УЗ дачика
const int R_TRIG_pin = 12; // задание номера вывода правого trig УЗ датчика
const int R_ECHO_pin = 13; // задание номера вывода правого echo УЗ дачика
bool US_L, US_C, US_R; // флаги УЗ датчиков 1 - есть препятсвтвие / 0 нет
// #2 светодиод
const int Led_pin = 2; // задание номера вывода светодиода
bool Led ; // этой переменной устанавливаем состояние светодиода
void setup() {

  //#1 УЗ датчики
  pinMode( L_TRIG_pin, OUTPUT); // задание режима работы вывода левого trig УЗ датчика
  pinMode( L_ECHO_pin, INPUT); // задание режима работы вывода левого echo УЗ датчика
  pinMode( C_TRIG_pin, OUTPUT); // задание режима работы вывода центрального trig УЗ датчика
  pinMode( C_ECHO_pin, INPUT); // задание режима работы вывода центрального echo УЗ датчика
  pinMode( R_TRIG_pin, OUTPUT); // задание режима работы вывода правого trig УЗ датчика
  pinMode( R_ECHO_pin, INPUT); // задание ражима работы вывода правого echo УЗ датчика
  //#2  светодиод
  pinMode(Led_pin, OUTPUT); //Подключим светодиод
  digitalWrite(Led_pin, Led = 0);
}

void loop() {
  static uint32_t past_1 = 0;
  static uint32_t mpast_1 = 0;
  if (millis() - past_1 >= 100) {// если подошло 0,1 сек (не чаще 50мс)
    past_1 = millis();
    //#1 УЗ датчики
    US_L = US_L = US_L = 0; //обнулить флаги
    digitalWrite(L_TRIG_pin, 0);
    digitalWrite(C_TRIG_pin, 0);
    digitalWrite(R_TRIG_pin, 0);
    delayMicroseconds(2);
    digitalWrite(L_TRIG_pin, 1);
    digitalWrite(C_TRIG_pin, 1);
    digitalWrite(R_TRIG_pin, 1);
    delayMicroseconds(10);
    digitalWrite(L_TRIG_pin, 0);
    digitalWrite(C_TRIG_pin, 0);
    digitalWrite(R_TRIG_pin, 0);
    mpast_1 = micros();
    while (micros() - mpast_1 <= dangerous_distance) { // пока не истекло время отклика на критическом расстоянии
      if (! digitalRead(L_ECHO_pin)) US_L = 1; // если пришел отклик с левого
      if (! digitalRead(C_ECHO_pin)) US_C = 1; // если пришел отклик с центрального
      if (! digitalRead(R_ECHO_pin)) US_R = 1; // если пришел отклик с правого
    }
    //#2  светодиод
    digitalWrite(Led_pin, Led = US_L || US_C || US_R);// если пришел отклик с лобого конца , то горит.
  }
}

 

slava.ru38
Offline
Зарегистрирован: 28.11.2016

в 40 строке наверно должно быть US_L = US_C = US_R = 0. Спасибо за вариант. Сейчас осмысливать буду. Правда, не совсем понял значение 9 строки... Почему там умножение на 58

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Строка 40 US_L = US_C = US_R = 0.  Это присвоение 3-м переменным 0. Смотри синтаксис Си.

Строка 9 . Программе не нужно минимальное расстояние до вашей платформе, точнее это расстояние задается максимальным временем эха . 50(см) * 2 (туда и обратно) * 29 (скорость звука в см/ микросекунду)*.  Эхо от более дальних препятсвий нам не надо, значит и ждать их нам ни к чему. А это ускоряет работу датчиков. Не проверял, так самого датчика нет. Вы проверьте сами и посмотрите все ли там правильно.

slava.ru38
Offline
Зарегистрирован: 28.11.2016

про присвоение 3-м переменным 0 - это я понял. Имел ввиду, что в скетче опечатка. в 40 строке

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Но если это - время эха и потом мы это время сравниваем в 53 строке с micros, то чтобы найти dangerous_distance (то есть время эха), нам нужно расстояние поделить на скорость. А вы расстояние УМНОЖАЕТЕ на скорость. Не понятно мне  - почему? 

slava.ru38
Offline
Зарегистрирован: 28.11.2016

и 29 - это не скорость звука в см/микросекунду, а время. Примерно  29 миллисекунд звуку нужно, чтобы преодолеть 5м туда (максимальнов озможное расстояние до препятствия) и обратно.

Мне кажется так. Поправьте,если ошибаюсь

Поэтому кажется можно сразу занести в 9 строке в переменную  вместо арифметических действий - 3000 (микросекунды). Хотя у вас получается то же самое в результате подсчета. Наверно я че- то не догоняю

Правда попробовал. Светодиод что в вашем случае постоянно горит, что после заноса 3000. Попробую через сериал пропустить. 

Выводит 1 везде постоянно. Правда у меня кабинет маленький. Препятствие примерно метра 2 - 3. Меньше во всяком случае 5 метров

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

http://mash-xxl.info/info/191807/

Скорость звука в воздухе 343 м/с. Или 343 *100 см / 1000 000 мкс = 0.0343 см/ мкс . Или 1 / 0.0343 = 29.15 мкс / см.  То есть за 29.15 мкс звук в воздухе проходит 1 см. А у нас туда и обратно. 29.15*2 = 58.3 мкс.  То есть если сигнал пришел через 58 мксек то растояние до препятствие 1 см . Так как  программисту много глюков нужно учесть, то проще записать

const uint32_t  dist = 50 * 58; // где 50 см расстояние до препятствия и 58 поправочный коэффициент
// и если надо изменить расстояние, то можно поменять 50 на нужную величину.

Таже программа но под 1 сонар

/*  Ultrasonic_solo.ino
#1 УЗ датчики
датчик УЗ  ->14,15 (L_TRIG_pin,L_ECHO_pin)
#2 светодиод  (Led_pin)->2  1 горит (предмет в опасной близости)/ 0 не горит (путь свободен)
                   GND ->GND
*/
//#1 УЗ датчики
const uint32_t dangerous_distance = 50 * 58 ;// 50 расстояние в см
const int L_TRIG_pin = 14; // задание номера вывода левого trig УЗ датчика
const int L_ECHO_pin = 15; // задание номера вывода левого echo УЗ датчика
bool US_L; // флаги УЗ датчиков 1 - есть препятсвтвие / 0 нет
// #2 светодиод
const int Led_pin = 2; // задание номера вывода светодиода
bool Led ; // этой переменной устанавливаем состояние светодиода
void setup() {

  //#1 УЗ датчики
  pinMode( L_TRIG_pin, OUTPUT); // задание режима работы вывода левого trig УЗ датчика
  pinMode( L_ECHO_pin, INPUT); // задание режима работы вывода левого echo УЗ датчика
  //#2  светодиод
  pinMode(Led_pin, OUTPUT); //Подключим светодиод
  digitalWrite(Led_pin, Led = 0);
}

void loop() {
  static uint32_t past_1 = 0;
  static uint32_t mpast_1 = 0;
  if (millis() - past_1 >= 100) {// если подошло 0,1 сек (не чаще 50мс)
    past_1 = millis();
    //#1 УЗ датчики
    US_L = 0; //обнулить флаги
    digitalWrite(L_TRIG_pin, 0);
    delayMicroseconds(2);
    digitalWrite(L_TRIG_pin, 1);
    delayMicroseconds(10);
    digitalWrite(L_TRIG_pin, 0);
    mpast_1 = micros();
    while (micros() - mpast_1 <= dangerous_distance) { // пока не истекло время отклика на критическом расстоянии
      if (! digitalRead(L_ECHO_pin)) US_L = 1; // если пришел отклик с левого
    }
    //#2  светодиод
    digitalWrite(Led_pin, Led = US_L );// если пришел отклик с левого , то горит.
  }
}

 

slava.ru38
Offline
Зарегистрирован: 28.11.2016

Вот я двоешник-балбес. Спасибо qwone за терпение и тактичное объяснение. До 0,0343см/мкс я досчитал, а дальше пропорцию не составил количество мкс на 1 см. Со скоростью разобрался - признаю оплошал: 29 - это скорость, а не время.

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

qwone пишет:

http://mash-xxl.info/info/191807/

Скорость звука в воздухе 343 м/с.

Скорость звука в воздухе зависит от массы параметров, прежде всего - от температуры. И указывать ее до третьего знака, не приводя температуру, которой она соответствует, некорректно.

Если мне не изменяет память, скорость звука при условиях близких к нормальным достаточно точно аппроксимируется зависимостью c=20.05*sqrt(T).

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

andriano пишет:

Если мне не изменяет память, скорость звука при условиях близких к нормальным достаточно точно аппроксимируется зависимостью c=20.05*sqrt(T).

Ничего Вам не изменяет. При "правильном" составе воздуха (23% - кислород, 76% - азот и 1%-аргон) примерно так оно и есть. У меня коэффициент получился 20,02, но это дела никак не меняет, т.к. там просто нет такой точности. Температура. разумеется, абсолютная.