Как работает функция while(analogRead(A0)) в этом коде?
Синусоидальная волна подается на A0
, и я хотел бы рассчитать частоту. Если определенный порог пересечен, запустите таймер..... насчитайте 5 таких пересечений.....затем остановите таймер. Код прилагается. Несмотря на то, что я понимаю while()
с логическими операторами, такими как while(состояние<5)
(показано в коде), я не понимаю использования while(analogRead(A0))
. Я хотел бы знать, как он функционирует по отношению к коду? Программа и так работает нормально. Протестировал это в Tinkercad и получил ошибочные показания, когда был прокомментирован while(analogRead(A0))
. Большое вам спасибо, что прочитали мой вопрос ^_^.
void loop()
{
while(State<5)
{
val=analogRead(A0);
if(val>200)
{
Serial.println("Threshold Crossed");
if(State==0)
{
Start_Time=millis();
}
State++;
while(analogRead(A0)); //Я ЭТОГО НЕ ПОНИМАЮ
}
}
End_Time=millis();
Period=(Start_Time-End_Time)/5;
Frequency=1000/(Start_Time-End_Time)
Serial.println(Frequency);
State=0;
}
@Nawaz, 👍1
Обсуждение2 ответа
Лучший ответ:
Как вы правильно заметили, while
обычно принимает bool в качестве аргумента. Однако, главным образом по историческим причинам, C/C++ на самом деле не различает int и bool, и поэтому условия могут быть целочисленного типа. Любое условие, будь то через некоторое время
или если
, может быть типа int. Условие принимает значение true, если оно не равно нулю. Таким образом, условие while(analogRead(A0));
циклы (ничего не делают) , пока analogRead не
вернет 0.
Я думаю, что теперь я понимаю, что эта линия просто работает как своего рода задержка. Без while(analogRead(A0)), сразу после пересечения первого порога (скажем, val теперь 202), состояние становится +1, и программа снова переходит к "val=analogRead(A0)". Значение val теперь равно 210, поэтому состояние снова увеличится.........и пока состояние>5, значение val, вероятно, достигнет 250. Это, безусловно, даст неправильный период времени. С другой стороны, в то время как(analogRead(A0)) продолжает цикл до false (0), дает достаточно времени, чтобы val пересек порог, а затем стал меньше порога, чтобы пересечение можно было обнаружить снова. Спасибо!, @Nawaz
@Nawaz Не задержка, а скорее “продолжайте проверять значение, пока оно не станет тем, что я ищу”. Это не имеет ничего общего со *временем*, но *ценностью*., @Dave Newton
Да, но функция analogRead() может никогда не возвращать идентичный 0 (смещение в 20 мВ предотвратило бы это). Или только изредка из-за случайного шума. Это эквивалентно сравнению поплавков с фиксированными значениями. Возможно, обратите внимание на это в своем ответе?, @Peter Mortensen
То, что вы реализовали, возможно, неосознанно, называется гистерезис. Ваша программа проводит большую часть своего времени в любом из этих двух состояний:
- Он постоянно выполняет внешний
цикл while, и считанное значение составляет ≤ 200. Он выходит из этого состояния, как только считывает значение , превышающее 200.
- Он постоянно запускает внутренний
цикл while, и считанное значение > 0. Он выходит из этого состояния только тогда, когда
analogRead()
возвращает ноль.
Гистерезис-хороший способ подавления шума, когда вы хотите обнаружить
сигнал, пересекающий пороговое значение. Однако я бы рекомендовал вам использовать его
более контролируемым образом. В частности, второй порог
, вероятно, должен быть больше нуля, иначе он не будет преодолен, если
сигнал не достигнет уровня земли. Как минимум, вы можете
заменить внутренний цикл while чем-то вроде:
while (analogRead(A0) >= 100)
/* подождите, пока сигнал не станет достаточно низким */;
Для справки, эта логика может быть реализована неблокирующим
способом, что позволит программе выполнять другие действия, например, отвечать на
нажатия кнопок, ожидая переходов. Для этого вам нужна
переменная для записи текущего состояния сигнала (скажем, НИЗКОГО
или
ВЫСОКОГО
) и записи изменений состояния при пересечении соответствующих пороговых
значений.
На рисунке ниже реализована эта неблокирующая техника в цикле()
,
в то время как функция setup()
блокирует во время ожидания первого НИЗКОГО
→ ВЫСОКОГО
переход:
const int LOW_THRESHOLD = 100;
const int HIGH_THRESHOLD = 200;
uint8_t state; // либо НИЗКОЕ, либо ВЫСОКОЕ
uint8_t count = 0; // подсчитайте время начала переходов от НИЗКОГО к ВЫСОКОМУ
uint32_t start_time;
void setup() {
// Дождитесь первого перехода НИЗКИЙ - > ВЫСОКИЙ.
while (analogRead(A0) >= LOW_THRESHOLD)
/* Дождитесь НИЗКОГО состояния. */;
while (analogRead(A0) < HIGH_THRESHOLD)
/* Дождитесь ВЫСОКОГО состояния. */;
state = HIGH;
// Запишите время перехода.
start_time = millis();
}
void loop() {
// Запись переходов.
uint8_t val = analogRead(A0);
if (state == HIGH && val < LOW_THRESHOLD) {
state = LOW;
} else if (state == LOW && val >= HIGH_THRESHOLD) {
state = HIGH;
++count;
}
if (count >= 5) {
// Сообщить об измеренной частоте.
uint32_t end_time = millis();
int frequency = 1000 * count / (end_time - start_time);
Serial.println(frequency);
// Готовьтесь к следующему раунду.
start_time = end_time;
count = 0;
}
}
Re *"В частности, второй порог, вероятно, должен быть больше нуля, иначе он не будет преодолен, если сигнал не достигнет уровня земли".*. Действительно. И, возможно, добавить более общее утверждение о сравнении на равенство (с фиксированными значениями) для такого выхода АЦП (шум, скорость изменения входного сигнала и т.д.)?, @Peter Mortensen
@PeterMortensen: Это, как правило, весьма актуально. Однако причины, по которым обычно не следует сравнивать значение АЦП для равенства, не совсем применимы к частному случаю сравнения с нулем., @Edgar Bonet
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
выведите значение " analogRead(A0)"... это сообщит вам, когда он выйдет из цикла while, @jsotola
Можете ли вы [исправить](https://arduino.stackexchange.com/posts/85491/edit) отступ в коде?, @Peter Mortensen
Re *"Синусоидальная волна подается на A0"*: Какова ее амплитуда и смещение постоянного тока? Каково выходное сопротивление генератора сигналов (что это за генератор сигналов)? Как это связано? Переменный ток подключен?, @Peter Mortensen