2 переменных в цикле while

Ar_PHARAZON
Offline
Зарегистрирован: 28.09.2018

Здравствуйте. Помогите разобраться с циклом. 

Есть 2 светодиодных ленты (холодная и теплая белая). Баланс между цветами лент и общая яркость управляються двумя энкодерами по этой схеме:

  inv = 255 - balance;
  intens = (brightness * inv) ;
  balance_result = (balance * brightness) ;
  
  led_cw = map(intens,0,65025,0,255);
  led_ww = map(balance_result,0,65025,0,255);
    
  analogWrite(MOSFET_CW, led_cw); 
  analogWrite(MOSFET_WW, led_ww); 

Все работает. Данные записываются в еепром каждые 5 сек.

Теперь пытаюсь добавить плавное включение двух лент в setup с помощью while:

  while (fadeValue <= led_cw && fadeValue2 <= led_ww)
  {
    analogWrite(MOSFET_CW, fadeValue++);
    analogWrite(MOSFET_WW, fadeValue2++);
    delay(10);
  }

Но такой код работает только для одной из переменных (в данном случае led_cw так как она в коде идет первой). Таким образом, сначала видно плавное ключение, а потом резкий "скачок" led_ww после окончания цикла.

Насколько я понял, в while нельзя запихнуть оператор "и", поэтому вторая переменная игнорируется? 

С циклом for та же проблема.

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

sadman41
Offline
Зарегистрирован: 19.10.2016

А смысл? Скоро EEPROMa у Вас не будет, так что зачем тут плавный поджиг...

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Навскидку:

bool strip1Done = false;
bool strip2Done = false;

while(1)
{
	if(!strip1Done)
	{
		analogWrite(MOSFET_CW, fadeValue++);
		if(fadeValue > 254)
			strip1Done = true;
	}
	
	if(!strip2Done)
	{
			analogWrite(MOSFET_WW, fadeValue2++);
			if(fadeValue2 > 254)
				strip2Done = true;
	}
	
	if(strip1Done && strip2Done)
		break;
	
  delay(10);
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

А я бы так бахнул, пожалуй:

while (fadeValue < led_cw || fadeValue2 < led_ww)
{
  if (fadeValue < led_cw) { 
     fadeValue++;
     analogWrite(MOSFET_CW, fadeValue);
  }
  if (fadeValue2 < led_cw) { 
   fadeValue2++; 
   analogWrite(MOSFET_WW, fadeValue2);
  }
  delay(10);
}

Или так, чтобы позапутанней:

while (fadeValue < led_cw || fadeValue2 < led_ww)
{
  fadeValue  += (fadeValue  < led_cw) ? 1 : 0;
  fadeValue2 += (fadeValue2 < led_cw) ? 1 : 0;
  analogWrite(MOSFET_CW, fadeValue);
  analogWrite(MOSFET_WW, fadeValue2);
  delay(10);
}

 

b707
Offline
Зарегистрирован: 26.05.2017

например

byte i =0;
while (i < 255)
{
  fadeValue = map(i,0,255,0,led_cw);
  fadeValue2 = map(i,0,255,0,led_ww);
  analogWrite(MOSFET_CW, fadeValue);
  analogWrite(MOSFET_WW, fadeValue2);
  i++;
  delay(10);
 }
sadman41
Offline
Зарегистрирован: 19.10.2016

У B707 более правильный вариант с точки зрения синхронизации финиша, но и менее экономный в ресурсе.

b707
Offline
Зарегистрирован: 26.05.2017

DIYMan sadman41

- в ваших вариантах есть нюанс - при существенной разнице led_cw и led_ww баланс белого съедет, поскольку ленты будут разгораться с разной скоростью

sadman41
Offline
Зарегистрирован: 19.10.2016

b707 пишет:

- в ваших вариантах есть нюанс - при существенной разнице led_cw и led_ww баланс белого съедет, поскольку ленты будут разгораться с разной скоростью

Есть такое, но вопрос о равномерности пока что не стоял, стоял вопрос о выходе из цикла ;) 

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

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

sadman41 пишет:

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

Золотые слова ;)

Ar_PHARAZON
Offline
Зарегистрирован: 28.09.2018

b707 пишет:

например

byte i =0;
while (i < 255)
{
  fadeValue = map(i,0,255,0,led_cw);
  fadeValue2 = map(i,0,255,0,led_ww);
  analogWrite(MOSFET_CW, fadeValue);
  analogWrite(MOSFET_WW, fadeValue2);
  i++;
  delay(10);
 }

Спасибо!! Есть небольшой тормоз со второй лентой, но его практически не видно :) 

Насчет еепром, не так выразился :) там в коде каждые 5 сек проверяет есть ли изменение по энкодерам и если да, то пишем.

Тем не менее, хотелось бы хоть приблизительно понять, на сколько хватит встроенного еепрома? 

b707
Offline
Зарегистрирован: 26.05.2017

да, кстати, надо же и на главный вопрос ТС ответить, а то он так и запомнит, что в while можно только одно условие использовать...

Ar_PHARAZON пишет:

Насколько я понял, в while нельзя запихнуть оператор "и", поэтому вторая переменная игнорируется? 

неправильно поняли. Можно и "и", и "или". и "больше равно" - вообще любые комбинации логических операторов хоть по 20 штук условий.

Проблема вашего кода была не в цикле, а в логике.

sadman41
Offline
Зарегистрирован: 19.10.2016

Надолго хватит, если крутить энкодеры не будете.

 

b707
Offline
Зарегистрирован: 26.05.2017

Ar_PHARAZON пишет:

Тем не менее, хотелось бы хоть приблизительно понять, на сколько хватит встроенного еепрома? 

гарантия 100000 циклов записи, а дальше как повезет. При непрерывной перезаписи каждые 5 сек - примерно на неделю :)

Ar_PHARAZON
Offline
Зарегистрирован: 28.09.2018

Предположим еепром исчерпал свой ресурс, а так как данные для переменных brightness и balance мы получаем из еепром при запуске ардуины:

int brightness = EEPROM.read(0); 
int balance = EEPROM.read(1);

то выходит, что программа дальше работать не будет? Или этим переменным автоматически будет присвоен 0 ?

Как написать строку, где если еепром не отвечает, то переменная brightness будет равна например 155? И ленты запустятся со средней яркостью

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

епром будет отвечать. читаться просто из него будет мусор. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

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

Ar_PHARAZON
Offline
Зарегистрирован: 28.09.2018

DetSimen пишет:

епром будет отвечать. читаться просто из него будет мусор. 

А как тогда подстраховаться? 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Ar_PHARAZON пишет:

А как тогда подстраховаться? 

Шапочкой из фольги, как вариант.

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

Подстраховываются, например - записывая одно значение несколько раз, и читая его потом. Если все прочитанные значения одинаковы - еепром не глючит. Это - один из вариантов.

Ar_PHARAZON
Offline
Зарегистрирован: 28.09.2018

DIYMan пишет:

Шапочкой из фольги, как вариант.

Ну мы не ищим легких путей :))

DIYMan пишет:

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

это успокаивает

DIYMan пишет:

Подстраховываются, например - записывая одно значение несколько раз, и читая его потом. Если все прочитанные значения одинаковы - еепром не глючит. Это - один из вариантов.

То есть если при чтении еепром данные не равняются диапазону от 0 до 255 то еепрому гайки и присваиваем свое значение, я правильно понял?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Ar_PHARAZON пишет:

То есть если при чтении еепром данные не равняются диапазону от 0 до 255 то еепрому гайки и присваиваем свое значение, я правильно понял?

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

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

Короче, решение комплексное, как правило.

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

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

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

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

andriano пишет:

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

Плюсую.

sadman41
Offline
Зарегистрирован: 19.10.2016

Я, например, пишу по всей длине EEPROM - каждый раз со сдвигом на ячейку. При этом предыдущую стартовую забиваю 0x00. Потом, в случае записи одного значения, не превышающего 254, делаю к нему +1 (чтобы не было нуля) и дополнительно пишу его XOR на какую-нить величину (типа CRC незамысловатого) в следующую ячейку. На старте просто просматриваю EEPROM, пока не найду ячейку с ненулевым значением, делаю считанному XOR и сравниваю со значением след. ячейки. Совпало - значит считано верно, Можно сделать считанному -1 и использовать. Если несколько ячеек нужно писать, в первую помещаю префикс, потом данные +CRC8. На старте тот же алгоритм - бежим по EEPROM, нашли префикс, считали данные, CRC проверили. Совпало - ОК, не совпало - берем значения по-умолчанию. Ну, там еще проверки на достижение конца, перескок на нулевую ячейку, понятное дело, и все такое.

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

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

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

sadman41 пишет:

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

Насколько мне известно, во flash-памяти в одну ячейку записывается несколько битов информации. В этом случае "износ битовых позиций" теряет смысл.