Чтение и отправка с помощью Arduino?
Я использую Arduino в приложении IoT, где мне нужно считывать импульсы, поступающие от датчика, и отправлять среднее значение этих импульсов, не пропуская ни одного импульса при отправке значения. Возможно ли добиться такой операции, зная, что Arduino — это одноядерный чип?
Я читал о библиотеках Protothreading
, но они могут пропускать импульс во время фазы проверки, поэтому я хочу узнать, есть ли другое решение
@bouhmid , 👍0
Обсуждение1 ответ
Лучший ответ:
Хотя Arduino имеет только одно ядро ЦП и может выполнять только одну инструкцию программы за раз, он не ограничен выполнением только одной задачи за раз.
MCU — это сложное устройство со множеством встроенных в него периферийных устройств. Центральный процессор — это всего лишь один небольшой блок всего устройства.
Большая часть программы — это просто инструкции, сообщающие периферийным устройствам, как им работать.
Например, при отправке данных через последовательный порт ЦП не говорит: «Отправь этот бит. Теперь подожди. Теперь отправь этот бит. Теперь подожди еще раз» — вместо этого он просто говорит: «Вот этот байт для отправки. Теперь иди и отправь его, и скажи мне, когда закончишь». Затем периферийное устройство UART отправляет байт сам по себе, без дальнейшего ввода от ЦП, оставляя ЦП свободным для выполнения других задач.
Затем есть периферийные устройства таймера. ЦП настраивает их на счет от источника синхронизации и выполняет разные действия в зависимости от разных событий, например, при подсчете достигается определенное число и т. д. ЦП не нужно делать "Считай до одного. Считай до одного. Считай до одного". Он просто делает "Считай от 0, используя этот источник синхронизации, и скажи мне, когда достигнешь 100" (например).
Аналогично, есть «Внешние прерывания». ЦП не нужно сидеть и смотреть на пин ввода-вывода все время, спрашивая «Вы уже изменились? Вы уже изменились? Вы уже изменились?» — он просто говорит «Скажите мне, когда вы изменились», и ЦП уходит заниматься другими делами.
Конечно, все эти вещи имеют свои оговорки. Самая большая заключается в том, что если ЦП делает что-то очень критичное по времени, например, вручную «бит-бэнгирует» последовательные данные через контакт GPIO (например, с помощью SoftwareSerial), его можно настроить на игнорирование всех этих сигналов прерывания от периферийных устройств. Это означает, что если вы используете «внешнее прерывание» для подсчета импульсов и вам нужно использовать SoftwareSerial для связи, возможно, что процедуры отправки или приема SoftwareSerial могут привести к тому, что обнаружение импульса будет либо задержано (на самом деле это не проблема), либо полностью пропущено.
Поэтому вам не следует использовать SoftwareSerial, если этого можно избежать, если вы хотите использовать внешние прерывания для такого рода операций.
Другой вариант — использовать таймер. Я упоминал, что они просто считают вверх от 0 (или могут также считать вниз) с использованием настраиваемого источника синхронизации. Этот подсчет происходит полностью независимо от ЦП и продолжается независимо от того, включены или выключены прерывания. И замечательная новость заключается в том, что большинство таймеров можно настроить (в зависимости от того, какой Arduino вы используете) на использование внешнего сигнала в качестве источника синхронизации для подсчета.
Это означает, что вы можете настроить таймер для подсчета импульсов независимо от того, что делает ЦП. Все, что вам нужно сделать, это время от времени (как часто это зависит от того, как часто поступают ваши импульсы — у таймера есть ограничение на то, сколько он может подсчитать, прежде чем переполнится) спрашивать таймер, сколько он насчитал, и сбрасывать его счетчик на 0. Это можно сделать как часть вашей процедуры «отправки». Получите счетчик, сбросьте его на 0 и отправьте результаты.
Что делать, если частота, которую я считаю, является переменной? Может ли решение с таймером работать?, @bouhmid
Да. Он заботится только о фронтах. Пока количество импульсов, которое вам нужно посчитать, меньше максимального, которое может посчитать таймер (или вы "расширяете" его с помощью прерывания по переполнению) в течение периода, в который вы считываете и сбрасываете счетчик, его не волнует частота (до тех пор, пока она ниже 1/2 частоты системных часов)., @Majenko
Я понял ваше решение, однако, если я использую таймер в качестве счетчика, как я узнаю время, в течение которого я подсчитывал свои импульсы, чтобы получить среднее значение?, @bouhmid
Имеется более одного таймера. Таймер0 управляет millis()
., @Majenko
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Одно слово: прерывания. Погуглите их., @Majenko
Опубликуйте больше подробностей того, чего вы пытаетесь достичь. Вы хотите считать импульсы? Перебивает, как сказал Маженко., @MichaelT
да, мне нужно подсчитать импульсы, поэтому я не хочу, чтобы в момент отправки значения я пропускал импульс, @bouhmid
Я гуглил
polthread
иpollthread
, и ничего не нашел. Не могли бы вы дать ссылку? В любом случае, посчитайте каждый импульс вISR
(один оператор должен это сделать), а вloop()
вы можете вычислить и вывести среднее значение, используяmillis()
, @Greenonlineизвините, это protothreading вот ссылка https://www.hackster.io/reanimationxp/how-to-multithread-an-arduino-protothreading-tutorial-dd2c37, @bouhmid
@Majenko, если я буду использовать прерывания каждый раз, когда получаю импульс, не нарушит ли это функцию отправки? Зная, что мне придется отправлять значение каждый период времени, @bouhmid
Если только функция отправки не полагается на синхронизацию критических битовых ударов, нет, вы не "помешаете" ей. Что это за мифическая "функция отправки"? Что вы используете для связи? Как вы ею управляете?, @Majenko
Я отправляю свое среднее значение по сети Lora на шлюз., @bouhmid