Тонкости использования If и While операторов!

Swat_III
Offline
Зарегистрирован: 08.09.2016
Доброго всем дня! Возникла такая проблема мне необходимо что бы при наступлении условия if 
переменная принимала значение контанты или булевого значения true или false
  
Собственно есть такой код: необходимо что бы условие сохранялось постоянно а не только во время время (magnitude >= freq1 && magnitude <= spoon1 )
Как заставить переменную занять только одно значение при наступлении события в if (....) и больше его не менять? Спасибо!
 bool fr1 = true;

if (magnitude >= freq1 && magnitude <= spoon1 ) 
 digitalWrite(ledRed, HIGH);

 

#include <Goertzel.h>

int sensorPin = A0;
int led = 13;
int ledRed = 5;
int ledGreen = 4;
int ledWhite = 3;
float target_freq;
float spoon1;
float spoon2;
float spoon3;
float sampling_freq;
float freq1;
float freq2;
float freq3;
bool fr1;
bool fr2;
bool fr3;


void setup() {
  pinMode(led, OUTPUT);
  pinMode(ledRed, OUTPUT);
  pinMode(ledGreen, OUTPUT);
  pinMode(ledWhite, OUTPUT);
  Serial.begin(9600);
  target_freq = 300.00;
fr1 = false;
fr2 = false;
fr3 = false;
}

void loop() {

  float freq1 = 349.23;
  float freq2 = 329.63;
  float freq3 = 293.66;
  float spoon1 = freq1 + 4.0;
  float spoon2 = freq2 + 4.0;
  float spoon3 = freq3 + 4.0;

  static float pattern[] = { 587.33, 698.46, 775.33, 880.21 };

  float n = 20.0;
  float sampling_freq = 9000;

  Goertzel goertzel = Goertzel(target_freq, n, sampling_freq);
  goertzel.sample(sensorPin); //Will take n samples
  float magnitude = goertzel.detect();  //check them for target_freq


 bool fr1 = true;
  if (magnitude >= freq1 && magnitude <= spoon1 ) {
    digitalWrite(ledRed, HIGH);
  

  }
  else {
    fr1 = false;
  }

 bool fr2 = true;
  if (magnitude >= freq2 && magnitude <= spoon2 ) {
    digitalWrite(ledGreen, HIGH);
  }
 
  else {
    fr2 = false;
  }

bool fr3 = true;
  if (magnitude >= freq3 && magnitude <= spoon3 ) {
    digitalWrite(ledWhite, HIGH);
  }


  else {
    fr3 = false;
  }


  if (fr1 && fr2 && fr3 == true) {
    delay(1000);
    digitalWrite(ledRed, LOW);
    digitalWrite(ledGreen, LOW);
    digitalWrite(ledWhite, LOW);
    delay(100);
    digitalWrite(ledRed, HIGH);
    digitalWrite(ledGreen, HIGH);
    digitalWrite(ledWhite, HIGH);
    delay(100);
    digitalWrite(ledRed, LOW);
    digitalWrite(ledGreen, LOW);
    digitalWrite(ledWhite, LOW);
    delay(100);
    digitalWrite(ledRed, HIGH);
    digitalWrite(ledGreen, HIGH);
    digitalWrite(ledWhite, HIGH);
    delay(100);
    digitalWrite(ledRed, LOW);
    digitalWrite(ledGreen, LOW);
    digitalWrite(ledWhite, LOW);
    delay(100);
  }

  Serial.println(magnitude);
  Serial.println(fr1);
  Serial.println(fr2);
  Serial.println(fr3);
  Serial.println("\r\n");


}

 

 

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

Перепубликуйте текст сообщения нормально - голову сломал его читаючи и так ничего и не понял.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Если нужно установить переменную только если она еще не установлена, при это проверять условия, то сначала нужно проверить установлена переменная или нет, а потом проверять условия установки, типа:

if (переменная еще не установлена) {
    if (если условия выполняются) {
        установить переменную;
    }
}

Правда понятия не имею, что имел в вдиу ТС, я так понял условие задачи;

 

Swat_III
Offline
Зарегистрирован: 08.09.2016

Так постараюсь как можно проще. 

Есть переменная magnitude это данные с датчика (микрофона) и сравнивает эти данные с искомой частотой (freq1, freq2, freq3) константа spoon1, spoon2, spoon3 служит для "вилки" условия if. Мне необходимо что бы при наступлении этого условия (bool fr1) принимала значение true навсегда! Однако сейчас это происходит только на мгновение исполнения условия if

<strong>bool fr1 = true;
053   if (magnitude >= freq1 && magnitude <= spoon1 )

 

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

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

Других вариантов не существует.

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

Ну и, строго говоря, такого поведения можно добиться только для статической или глобальной переменной, потому как все локальные переменные СУЩЕСТВУЮТ только на время выполнения содержащего их блока, а при СЛЕДУЮЩЕМ вхождении в этот же блок, строго говоря, под тем же именем будет уже другая переменная.

Хотя, с точки зрения локальной переменной - "навсегда" - это как раз до конца блока, т.е. до конца ее жизни.

 

PS. Чего конкретно хотите Вы, я из Вашего сообщения не понял, но могу предположить, что Вам следует убрать строку с повторным описанием булевой переменной (строка 52), добавить  в условие "&& !fr1" (строка 53) и присвоение "fr1=true" (строка 55), а также убрать ветрку else (строки 58-60).

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

научите меня, что делает идентификатор <strong>

Swat_III
Offline
Зарегистрирован: 08.09.2016

По сути у меня простая задача если fr1 fr2 fr3 = true то все светодиоды моргают, если хоть один из них = false то ждем пока усливие if(....) не будет выполнено. И весь косяк состоит в том что если условие и выполняется то на секунду а потом все по новой т.е. fr опять false. Было предложенно решение закинуть переменные которые должны будут стать константами ну т.е. "навсегда" в void setup но это тоже нифига не спасает, типо значение переменной в void setup "живет вечно"

Я просто не могу сообразить как присвоить fr1 fr2 fr3 значение true раз и навсегда до конца цикла? 

Swat_III
Offline
Зарегистрирован: 08.09.2016

 <strong> это есть следствие копипаста кода для Ардуино из браузера. Он пихает их сам автоматически))

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Если вставлять текст через Ctrl+Shift+V, то всё будет нормально. Форматирование текста и левые теги не вставляются, только чистый текст.

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

Swat_III пишет:

Я просто не могу сообразить как присвоить fr1 fr2 fr3 значение true раз и навсегда до конца цикла? 

fr1=true;
fr2=true;
fr3=true;

И больше их не трогать.

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

Swat_III пишет:

не могу сообразить как присвоить fr1 fr2 fr3 значение true раз и навсегда до конца цикла? 

Т.е. Вам нужна переменная, которая типа одноразовая. Один раз ей можно что-то присвоить, а потом она становится константой, так? А что происходит. если попытаться присвоить ещё раз? Игнорируется и значение остаётся неизменным?

Если всё так, могу предложить самый (ой, блин, а вдруг кто ещё круче придумает? Ну, ладно) один из самых извращенских способо это сделать. Надо? :)

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

.

Swat_III
Offline
Зарегистрирован: 08.09.2016

ДААААААААААААА именно так, а уже потом если вдруг мне будет нужно в самом конце цикла программы Я его тупо сброшу! Итак какой способ??? Мне главное эффективный ну и по возможности простой))

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

Swat_III пишет:

ДААААААААААААА именно так, а уже потом если вдруг мне будет нужно в самом конце цикла программы Я его тупо сброшу! Итак какой способ??? Мне главное эффективный ну и по возможности простой))

Если сделать так, как Вы хотите, "тупо сбросить" у Вас не получится. Не сбросится она. Останется true.

"Изращенно сбросить", правда, можно будет и в этом случае.

Но и от извращенного сбрасывания можно защититься.

Что-то мне кажется, Вам нужен вменяемый алгоитм, а не борьба с тем невменяемым, который у Вас сейчас есть, и который Вы вместо того, чтобы исправить, хотите сделать еще более невменяемым. Иначе этаборьба быстро исчерпает все ресурсы микроконтроллера.

 

Еще раз повторюсь: что Вам доподлинно нужно, я не понимаю, но, может, достаточно будет заменить это:

 bool fr1 = true;
  if (magnitude >= freq1 && magnitude <= spoon1 ) {
    digitalWrite(ledRed, HIGH);
  

  }
  else {
    fr1 = false;
  }

на это:

  if (magnitude >= freq1 && magnitude <= spoon1 && !fr1) {
    digitalWrite(ledRed, HIGH);
    fr1 = true;
  }

 

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

Ладно, извращённое решение будет завтра, уже поздно, а сейчас я Вам скажу по секрету самое простое.

Если у Вас есть переменная fr1, которая изначально false, а когда она станет true, то её уже нельзя менять, это делается очень просто. Просто никогда не присваивайте её false. зачем? Если она пока ещё итак false, так нахрена её этот же false ещё раз присваивать? А если она уже стала true, так значит false ей присваивать уже нельзя. Просто выбросьте из программы все присваивания этой перемнной false и будет Вам счастье.

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

Обещанное извращённое решение.

Определяем новый тип данных «bool-девственница». Для это пишет вот такой файл с названием "Virgin.h":

///////////////////////////////////////////////////////////////////////////
//  Тип данных VirginBool  («bool-девственница»)
//
// Определяет логическую переменную, которая может иметь начальное
// значение, и которой можно присвоить новое значение, но только один раз.
//
// После первого присваивания, никакие другие не отрабатываются.
//
// Правда, есть операция «таки присвоить»! Это операция == при условии, 
// что переменная типа VirginBool стоит слева. Если она стоит справа, 
// то это честное сравнение, как обычно.
//
// Детали реализации см. в коде.
//
// ЛИЦЕНЗИЯ
// Данный код поставляется по лицензии ПНХ.
//
// 1. Вы можете свободно использовать или не использовать его в коммерческих, 
//    некоммерческих, и любых других, не запрещённых законом, целях.
//
// 2. Автор не несёт решительно никакой ответственности за любые положительные
//    или отрицательные результаты использования или неиспользования данного кода.
//
// 3. Если Вам таки хочется сделать автору предъяву, то … Вы знаете куда
//    Вам следует пройти, А если не знаете, то см. название лицензии.
//
// 4. Если данный код вдруг пригодился (как учебник или ещё как что) и Вам
//    почему-либо (ну, приболели, может) захотелось отблагодарить автора рублём,
//    то это всегда пожалуйста – WebMoney, кошелёк № R626206676373
//    (тут название лицензии не канает). 
//
#pragma once

class VirginBool : public Printable  {
	bool m_Value;
	bool m_Deflowered;
public:	
	VirginBool(const bool initialValue = false) {
		m_Deflowered = false;
		m_Value = initialValue;
	}

	template <typename T> bool operator = (T newVal) {
		if (! m_Deflowered) {
			m_Deflowered = true;
			m_Value = (bool) newVal;
		}
		return m_Value;
	}

	template <typename T> bool operator == (T newVal) {
		m_Deflowered = false;
		return *this = newVal;
	}

	template <typename T> operator T(void) const { 
		return (T) m_Value; 
	}

	size_t printTo(Print& p) const {
		return p.print(m_Value ? "true" : "false") + 
			p.print(m_Deflowered ? " (deflowered)" : " (still virgin)");
	}
	
	template <typename T> friend bool operator == (T compVal, const VirginBool & vbVal) {
		return vbVal.m_Value == compVal;
	}

};

И пользуемся.

Вот пример использования. Пример и вышеприведённый файл нужно просто положить в одну папку. Название папки - как название файла-примера, только без ".ino" (ну, всё, как обычно). Пример:

template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; }

#define	OUT	Serial
#define	BANDWIDTH	115200

#include "Virgin.h"

void setup(void) {
	OUT.begin(BANDWIDTH);
	
	VirginBool a, b;
	
	OUT << "a=" << a << " : must be false\n";

	a = true;
	OUT << "a=" << a << " : must be true\n";

	a = false;
	OUT << "a=" << a << " : must be true\n";

	a == false;
	OUT << "a=" << a << " : must be false\n";

	a = true;
	OUT << "a=" << a << " : must be false\n";

	a == 321;
	OUT << "a=" << a << " : must be true\n";

	OUT << "b=" << b << " : must be false\n";

	b = a;
	OUT << "b=" << b << " : must be true\n";

	// Это операция "таки присвоить"
	if (a == false) {
		OUT << "a == false : TRUE\n";
	} else {
		OUT << "a == false : FALSE\n";
	}

	// А это операция сравнения
	if (false == a) {
		OUT << "false == a : TRUE\n";
	} else {
		OUT << "false == a : FALSE\n";
	}
}

void loop(void) {}

 

Swat_III
Offline
Зарегистрирован: 08.09.2016

Вот вариант с "девствинницей" прикольный, но Я нифига не понял как его применять))) а вот && !fr1 надо попробовать, очень интересно, но по ощущениям думаю нифига не выйдет)) 

Swat_III
Offline
Зарегистрирован: 08.09.2016

Если кому то вдруг понадобится, проблему Я решил крайне просто и неожиданно, тупо выразив ее через int переменную. Получилось примерно так:

int K = 0;

бла, бла, бла....

if (freq1 >= magnitude && freq1 <= spoon1) {

 K = 7;

}

bool fr1 = true

if (K = 7) {

}

else fr1 = false;

Вот и все, К принимает значение "7" и больше его не меняет пока не присвоят ему другое значение...

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

Swat_III пишет:

К принимает значение "7" и больше его не меняет пока не присвоят ему другое значение...

Глубоко!

James
Offline
Зарегистрирован: 26.02.2016

.