Оглавление:

Отправка числовых данных от одного Arduino к другому: 16 шагов
Отправка числовых данных от одного Arduino к другому: 16 шагов

Видео: Отправка числовых данных от одного Arduino к другому: 16 шагов

Видео: Отправка числовых данных от одного Arduino к другому: 16 шагов
Видео: Уроки Arduino #13 - создаём свою функцию 2024, Июль
Anonim
Отправка числовых данных от одного Arduino к другому
Отправка числовых данных от одного Arduino к другому

Вступление

Дэвид Палмер, CDIO Tech. в Астонском университете.

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

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

Что оно делает

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

Оборудование

  • 2 Ардуино
  • 2 USB-вывода
  • соединительные провода (по мере необходимости)
  • 1 ПК / ноутбук с Arduino IDE (доступен для бесплатной загрузки с веб-сайта Arduino.cc)

Шаг 1. Настройка - сначала настройте оборудование

Настройка - сначала настройте оборудование
Настройка - сначала настройте оборудование
Настройка - сначала настройте оборудование
Настройка - сначала настройте оборудование

Подключите 2 Arduinos к 2 USB-портам на вашем компьютере.

Подсказка: неплохо было бы обозначить их как M и S (главный и подчиненный), чтобы вы не запутались позже (как показано на двух фотографиях здесь).

Шаг 2: Настройка - Настройте свой экран

Настройка - Настройте свой экран
Настройка - Настройте свой экран

Лучше всего настроить свой экран так, чтобы

  • IDE, загруженная с мастер-программой слева и
  • что с Рабом справа.

Держите последовательные мониторы для Maser и Slave слева и справа, как показано на снимке экрана здесь.

Шаг 3: Настройте главный конец, затем соедините вместе - Часть 1

Установите главный конец, затем соедините вместе - Часть 1
Установите главный конец, затем соедините вместе - Часть 1

Когда вы настраиваете свой Master End Serial Monitor для отправки двух чисел, вы всегда должны использовать начальный и конечный символы, разделители и символ-разделитель запятой, как вы видите здесь.

Теперь вам нужно соединить 2 Arduino вместе через последовательный порт. Это делается с помощью двух соединительных проводов.

Я использовал зеленый и желтый

  • Сначала возьмите желтый, он должен подключаться к D6 в одном Arduino и D7 во втором.
  • Затем противоположный зеленый провод, D7 на первом и D6 на втором Arduino.

В качестве альтернативы, если у вас есть что-то доступное, например пара модулей Bluetooth - например, HC-05 - они также будут работать, чтобы дать вам точно такой же эффект, как и приведенные выше провода.

Шаг 4: Настройте главный конец, затем соедините вместе - Часть 2

Установите главный конец, затем соедините вместе - Часть 2
Установите главный конец, затем соедините вместе - Часть 2
Установите главный конец, затем соедините вместе - Часть 2
Установите главный конец, затем соедините вместе - Часть 2

Мы используем библиотеку Software Serial. Дополнительная информация доступна по этой ссылке

Вы можете увидеть его в строке 7 любой из программ. Он конфигурирует цифровые контакты 7 и 6 как TX и RX (передача и прием). Вот как данные будут передаваться из Master Arduino по зеленому проводу в Slave, и, когда программа Slave во втором Arduino завершит свою работу, обратно по желтому проводу. Внизу того же рисунка (в окне Serial Monitor) вы можете видеть, что данные, которые мы передали, теперь успешно прошли цикл, описанный здесь, и вернулись в ПК в виде пары целых чисел, красиво разделенных.

Шаг 5: Обзор эскизов / программ - структура программы

Обзор эскизов / программ - структура программы
Обзор эскизов / программ - структура программы
Обзор эскизов / программ - структура программы
Обзор эскизов / программ - структура программы

Компоновка Как и во всех скетчах Arduino, есть 3 основные части:

  • Заявления
  • Установка
  • Основной цикл

Как часто бывает, мы использовали здесь четвертый раздел, который является добавлением «Функции». Если вы не знакомы с использованием функций, вы можете найти в Google "функции Arduino", и вы найдете сайты с объяснениями, подобные примеру, по этой ссылке: www.tutorialspoint.com/arduino/arduino_functions…..

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

Три использованных блока можно увидеть в верхней части каждой иллюстрации окон IDE выше:

  • simpleRxTx0330Master
  • общий
  • Примечания

На самом деле это отдельные файлы внутри папки программы, как вы можете видеть в этом представлении Windows Explorer для файлов программы Slave.

Мы сделали это по очень веской причине.

  • Когда мы создавали программу, мы пришли к выводу, что большая часть программы для Мастера была такой же, как и для Раба.
  • В итоге мы вытащили все общие части на вкладку, которую мы поэтому назвали «общая», а затем каждый раз, когда мы отлаживали часть (тестировали ее и были удовлетворены, что она работает нормально), мы просто копировали и вставляли эту вкладку целиком. поперек от Мастера к Рабу или наоборот.
  • Вкладки заметок также идентичны, так как дизайн общий.

Ни одна из функций не вызывается из настройки, все они вызываются из цикла, поэтому мы создали их после настройки, но до цикла.

Шаг 6: Дизайн сверху вниз

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

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

Это соответствует хорошей философии дизайна, которой учат во многих университетах, и называется CDIO (если вы еще не знаете этот, вы можете погуглить и найти сайты, чтобы объяснить это, например: https://www.cdio.org/s.) По сути, это говорит: не начинайте Дизайн, пока у вас не будет ясна концепция. Не начинайте реализацию, пока не получите четкий дизайн. Не ожидайте, что он заработает, пока вы не проясните реализацию. Сначала C, затем D, I и O. На каждом последующем этапе вы повторяете (возвращайтесь к циклу (-ам), поэтому, как только вы будете довольны своим начальным циклом проектирования, вернитесь и убедитесь, что он все еще соответствует Концепции, и обновите C, если вам нужно. И так далее, поэтому, даже когда вы перешли в режим работы, вернитесь наверх и снова посмотрите, как сейчас выглядит C, затем D и I, и сделайте и проверьте все при необходимости можно изменить. С программированием эскизов это работает точно так же, если вы проектируете сверху вниз.

Шаг 7: Концепция и дизайн - Часть 1

Концепция и дизайн - Часть 1
Концепция и дизайн - Часть 1
Концепция и дизайн - Часть 1
Концепция и дизайн - Часть 1

Концепция здесь выглядит как общие требования, указанные во вкладке «Примечания».

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

Посмотрите, как мне нравится начинать, фактически CTRL-C копируя комментарии в начало цикла, а затем начинаю заполнять пробелы командами, которые будут делать эти вещи.

На самом деле это нормально компилируется, как вы можете видеть внизу экрана на рисунке. Это идет от этапа D к I CDIO, и по мере разработки кода неплохо продолжать обход этого цикла D-I.

Теперь пора перейти к следующему этапу, там есть комментарий, в котором говорится, что мы собираемся: // получить что-то с аппаратного USB, затем мы собираемся передать это на программный последовательный канал. Мы пишем этот код, чтобы это произошло - строки с 133 по 138 показаны здесь желтым маркером.

Шаг 8: Концепция и дизайн - Часть 2

Концепция и дизайн - Часть 2
Концепция и дизайн - Часть 2
Концепция и дизайн - Часть 2
Концепция и дизайн - Часть 2

Две первые две функции, которые мы здесь представляем, - это (recv () и tran () для получения от аппаратного порта и передачи на программный порт - следовательно, вызывая их с показанными параметрами «hw» или «sw».

В дополнение к ним мы добавили тест для глобальной переменной newData. Это флаг, который мы установим внутри функции void recv ();. Когда сообщение получено, эта переменная помечается с false на true. Мы делаем это так, чтобы передавать сообщение только в том случае, если оно было получено (flag == true) в строке 134. И как только мы передали наше сообщение, что «работа выполнена», мы снова сбрасываем флаг обратно в false в строке 137.

Мы снова можем проверить компиляцию (от D до I), и на этот раз у нас появится сообщение об ошибке «не объявлено» (показано). Это говорит нам, что мы не объявили recv (); функция. Мы планируем сделать это позже, поэтому только сейчас, чтобы позволить нам получить чистую компиляцию, нам нужно создать фиктивную функцию или функцию-заполнитель, как показано ниже.

Мы снова можем проверить компиляцию (от D до I), и на этот раз у нас есть еще одно сообщение об ошибке «не объявлено» для tran (); функция. Для этого нужно создать аналогичную заглушку. Мы снова можем проверить компиляцию (от D до I), и на этот раз мы обнаружим, что это работает отлично; Все идет нормально.

Шаг 9: Завершите основной цикл: A) Получение с USB, B) Получение от ведомого Arduino

Завершите основной цикл: A) Получение с USB, B) Получение от ведомого Arduino
Завершите основной цикл: A) Получение с USB, B) Получение от ведомого Arduino
Завершите основной цикл: A) Получение с USB, B) Получение от ведомого Arduino
Завершите основной цикл: A) Получение с USB, B) Получение от ведомого Arduino

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

Есть еще одно руководство по отладке эскизов, к которому можно обратиться, чтобы понять, что мы здесь сделали и почему. Обратитесь к инструкции «Как создавать и тестировать скетчи Arduino, пока они не заработают».

Таким образом, эти отладочные строки [показаны 136-139] добавляются следующими в основной цикл, и, о чудо, вы можете протестировать их на главном конце, сделав отладочную переменную истинной, и компилируя (I), тогда, если вы подключаете Arduino, вы можете загрузить, открыть Serial Monitor и посмотреть, что возвращается в Serial Monitor, как показано здесь (вы видите, что добавлено сообщение «DEBUG MODE»?)

Шаг 10: получение и обработка данных в подчиненном Arduino

Получение и обработка данных в подчиненном Arduino
Получение и обработка данных в подчиненном Arduino
Получение и обработка данных в подчиненном Arduino
Получение и обработка данных в подчиненном Arduino

Получение от ведомого Arduino

Добавьте необходимый код для второго канала в основной цикл, программный приемник последовательного порта, как показано - строки с 149 по 155.

Вы видите, что структура в общих чертах основана на том, что мы написали выше для кейса Master?

Также вы увидите, что мы получаем ошибку компилятора, еще одну необъявленную функцию - на этот раз parseData (); - поэтому нам нужно сделать заглушку и для этого, прежде чем мы сможем запустить безошибочную тестовую компиляцию.

Обработка данных в Slave Arduino

Добавьте код основного цикла, необходимый для Arduino, если он настроен как ведомое устройство, как показано - строки с 163 по 174. Вы видите, что его структура очень похожа на структуру первого канала?

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

Шаг 11: напишите функцию приема

Напишите функцию приема
Напишите функцию приема

Функция приема - void recv (char from) {} - выполняет две основные задачи.

1, чтобы получить строку символов из USB-канала, и

2, чтобы получить один из каналов Arduino в Arduino.

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

Когда мы начинаем добавлять код к функции - чтобы создать функцию, которая что-то делает, а не просто заглушку - нам нужно не забыть удалить или закомментировать заглушку, которую она заменяет. В противном случае мы получим ошибку компиляции: refefintion of 'void lrec (char)'.

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

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

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

Теперь давайте посмотрим на код, который мы написали для функции recv ().

Это довольно чисто, вы можете увидеть использование условия if для создания двух частей функции, упомянутых выше.

Код внутри частей sw и hw имеет одинаковую форму, и я опишу его здесь.

Первая из пары строк в каждом случае - это начало цикла while. Если вы не знакомы с while, вы можете найти его на сайте Arduino.cc/Reference для объяснения и примеров. Здесь мы ждем, пока встроенная функция Serial не получила никаких символов и потому что переменная newData была отключена (т.е. условие newData == false истинно). Как только будет получен символ - или более одного символа - while перейдет ко второй строке в этой паре. Затем это вызовет recAstringChar (char); функция для обработки текущего символа. Затем эта пара строк будет чередоваться, пока (или до тех пор, пока) есть какие-либо символы, которые все еще необходимо получить. Как только все они будут выполнены, состояние while завершается, позволяя завершить следующий уровень if or else и, в свою очередь, разрешать rec (char); функция до конца. Таким образом, теперь получено полное сообщение.

Шаг 12: напишите подфункцию приема - часть 1

Напишите подфункцию приема - Часть 1
Напишите подфункцию приема - Часть 1
Напишите подфункцию приема - Часть 1
Напишите подфункцию приема - Часть 1

Теперь нам нужно написать функцию recAstringChar (char);. Из комментария к строке 50 здесь, вверху, видно, что его задача - обновить два буфера копиями входящего последовательного сообщения. [Оказалось, что пока я пытался заставить все это работать, я понял одну вещь: мне нужны два разных буфера - или, по крайней мере, это был самый простой способ обойти некоторые проблемы, поэтому он как бы превратился в необходимость 2 буфера, поэтому Я только что сделал их.] Я назвал один буфер: receiveData, а другой: receiveChars.

Буферы являются глобальными переменными, поэтому они объявляются на уровне модуля, см. Строки 9 и 10 общей вкладки. Внутри этой функции объявлены и другие переменные, которые поэтому имеют локальную область видимости, как показано здесь в строках 51-54. Здесь не место объяснять различия между глобальными и локальными переменными, но дополнительную информацию об этом можно найти в https://www.arduino.cc/glossary/en/ в разделах «Локальные» и «Глобальные».

Вы также можете узнать все о типах данных и модификаторах типов: static, boolean, byte, const, char в https://www.arduino.cc/reference/en/#variables, показанном здесь.

Основной поток программы в этой функции контролируется if в строке 56 здесь и соответствующим else в строке 74. Это касается двух сценариев.

а) [начиная со строки 74], когда полученное сообщение начинается. Это происходит, когда обнаруживается startMarker - он был определен как символ '<', поэтому всякий раз, когда мы тестируем скетч, мы всегда начинаем нашу строку с этого символа. Если мы этого не сделаем, то ничего не будет обработано как полученное, все это будет проигнорировано, как если бы мы набирали ерунду в командной строке клавиатуры «Serial Monitor».

б) [строки с 56 по 73], который получает все остальные символы, какими бы они ни были, но они имеют дело с символами только после того, как произошло действительное начало (был получен '>', как в а) выше.)

В этих строках (с 74 по 78) мы помещаем полученный <в один из буферов (gotData [0]), но не в другой. Мы настраиваем указатель буфера (переменная: char ndx) так, чтобы он указывал на следующую резервную позицию буфера (receiveData [1]), используя команду постинкремента (++) в строке ndx ++;, и мы устанавливаем флаг выполнения в значение true.

Выполнение программы в этой части функции контролируется if в строке 57 здесь и соответствующим else в строке 65. Это касается двух сценариев.

а) [начиная со строки 65], когда полученное сообщение закончено. Это происходит, когда обнаруживается endMarker - определяется как>, поэтому всякий раз, когда мы тестируем наш скетч, мы всегда заканчиваем нашу строку этим символом. Одна из вещей, которые случаются, когда получен конечный символ, заключается в том, что глобальный флаг (технически переменная) newData устанавливается в значение true сразу после завершения функции, так что функция, которая вызвала нашу подфункцию (вызывающая функция: recv (char);) может «знать», что действительные новые данные были получены полностью.

б) [строки с 57 по 64], куда попадают все остальные символы, какими бы они ни были. Он просто аккуратно размещает их рядами в обоих буферах.

Шаг 13: напишите подфункцию приема - часть 2

Напишите подфункцию приема - Часть 2
Напишите подфункцию приема - Часть 2
Напишите подфункцию приема - Часть 2
Напишите подфункцию приема - Часть 2

Было бы полезно привести пример того, как выглядят 2 буфера, когда они были заполнены. Если бы мы вводили ввод, в буферах были бы отображаемые символы:

Итак, теперь вы можете видеть, что у нас есть один буфер, который состоит из тех же символов, которые мы ввели вначале, и один буфер, в котором есть только два значения и разделительная запятая. Теперь у нас есть некоторый код, который может принимать символы, которые мы вводим на клавиатуре Serial Monitor, мы можем перейти от фазы I CDIO к O, набрав несколько строк и посмотрев, что произойдет. Загрузите код в Master Arduino, откройте Serial Monitor и попробуйте ввести что-нибудь действительное, например Enter. Получаете ли вы эхо на экране монитора последовательного порта, подобное показанному здесь?

Шаг 14: напишите функции передачи и анализа

Напишите функции передачи и анализа
Напишите функции передачи и анализа
Напишите функции передачи и анализа
Напишите функции передачи и анализа

Первый для передачи

Итак, теперь мы получили строку, мы можем написать функцию передачи: tran (char); заменить его заглушку. Это позволит нам отправить строку от мастера к подчиненному Arduino, поэтому убедитесь, что оба устройства подключены и соединены вместе, чтобы протестировать эту новую функцию.

Введите эту функцию, как показано здесь в строках с 117 по 133. Как вы понимаете, она состоит из двух частей: одна для передачи на канал USB (аппаратный UART), а вторая для передачи на другой Arduino (программный UART). Это должно привести к ошибке компиляции. -бесплатно, и вы сразу можете загрузить скетч и посмотреть, что из этого получится. На этот раз пришлю. Вы получаете показанный результат?

Снимок экрана интересен тем, что строка "Получено" … должна выглядеть правильно, как и раньше, а строка "Передано" … теперь должна выглядеть правильно. Однако обратите внимание, что целочисленное преобразование не сработало. Есть еще немного кода, который нужно добавить, чтобы это работало.

Шаг 15: напишите функции передачи и анализа

Напишите функции передачи и анализа
Напишите функции передачи и анализа
Напишите функции передачи и анализа
Напишите функции передачи и анализа

Затем для анализа

Это фрагмент кода, который анализирует полученную строку для извлечения частичных числовых строк и преобразует их в целые значения. Это void parseData (); функция основного цикла

Замените заглушку синтаксического анализа кодом, показанным в строках 98–113. Загрузите его и посмотрим, решена ли проблема, которая у нас возникла с двумя целочисленными значениями. Давай попробуем.

Да, это работает, как показано, найдены целые числа 49 и 98.

Шаг 16: финал

Финал!
Финал!

Эти данные прошли по петле от ПК через Мастер через подчиненное устройство и снова через Мастер снова на ПК. После того, как законченная версия common загружена как на ведущий, так и на ведомый концы, и отключен режим отладки, мы можем увидеть данные, правильно полученные на обоих концах, как показано здесь.

Рекомендуемые: