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

У меня есть установка, состоящая из магнита, подвешенного над катушкой датчика. Он действует как маятник и создает сигнал ~ 4 мВ, когда качается над катушкой — он проходит через два каскада LM358 для генерации сигнала 5 В. Сигнал очень грязный с большим количеством "звонков" Этот сигнал подается на контакт A0 Arduino Uno. Я использовал MegunoLink.h и Filter.h, который является библиотекой экспоненциальных фильтров, затем применил ограничение и карту, наконец, преобразовав в чистую прямоугольную волну 0–400 (единиц?) около 1 секунды с переменным рабочим циклом. Это та информация, которая мне нужна, так как она говорит мне, что магнит наводится на датчик (рабочий цикл увеличивается по мере приближения). Но когда я применяю pulseInLong, я получаю только строку нулей на последовательном мониторе. Что я делаю не так? Вот скетч:

// Программирование Джереми 130520
// доработка модуля рикошета
//https://www.megunolink.com/documentation/arduino-libraries/exponential-filter/
//https://www.google.com/search?q=how+to+use+arduino+pulsein

#include "MegunoLink.h"
#include "Filter.h"
// Создаем новый экспоненциальный фильтр с весом 5 и начальным значением 0.
ExponentialFilter<long> ADCFilter(5, 0);

int coilPin = 8;
int analogIn = A0;
unsigned long pulseLength;
unsigned long signal_1;

void setup() 
{
  pinMode(coilPin, OUTPUT);
  pinMode(analogIn,INPUT);
  Serial.begin(9600);
  }

void loop()
{
 int RawValue = analogRead(analogIn);
  ADCFilter.Filter(RawValue);
 signal_1 =(ADCFilter.Current());
 signal_1 = constrain(signal_1,80, 200);
 signal_1 = map(signal_1, 80, 200,0,400);
 if (signal_1 >= 200) {signal_1 = 400; digitalWrite(coilPin, HIGH);}
 if (signal_1 < 200) {signal_1 = 0; digitalWrite(coilPin, LOW);}

 Serial.println(signal_1); //используем плоттер

//pulseLength = pulseInLong(coilPin, HIGH);
 //Serial.println(pulseLength);
 delay(10);  
}

измененный рабочий цикл

вывод в конце

, 👍1


1 ответ


Лучший ответ:

0

Вы не можете использовать pulseInLong(), так как это блокирующая функция. Это ждет, пока вход возрастет, затем ждет, пока он снова не упадет, и только затем он возвращает значение. Пока он ждет, остальная часть программы не могу бежать. Это означает, что вы не сможете фактически сгенерировать сигнал, который вы пытаетесь засечь.

Самое простое решение – самостоятельно рассчитать время с помощью micros(). Ты необходимо реализовать детектор границ, то есть некоторую логику, которая запоминает предыдущее состояние сигнала и замечает его изменение:

static bool is_high;  // является ли вход в данный момент ВЫСОКИМ?
static uint32_t time_of_rise;  // когда он поднялся?

if (!is_high && signal_1 >= 200) {  // нарастающий фронт
    time_of_rise = micros();
    is_high = true;
} else if (is_high && signal_1 < 200) {  // задний фронт
    uint32_t pulse_width = micros() - time_of_rise;
    is_high = false;
    Serial.println(pulse_width);
}
,

Спасибо, Эдгар, выглядит хорошо - завтра попробую и вернусь к вам., @Jeremy Brown

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