Помогите новичку с плавным вкл и выкл ленты

metdet93
Offline
Зарегистрирован: 27.01.2016

Добрый вечер. Ковыряюсь, ковыряюсь, никак не могу логически связать между собой две задачи. Есть грубо говоря кнопка (датчик ИК) и светодиод (лента через мосфет). Кнопка должна каждый раз инвертировать значение, нажал светит, еще раз нажал тухнет (такой скетч прикрепил). Но чтобы зажигалась и тухла не резко, а плавно, на протяжении секунды. на ум пришел только цикл For, но как их подружить между собой не могу понять. Заранее спасибо!

const int LED=3;
const int BUTTON=2;
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean ledOn = false;

void setup ()
{
pinMode (LED, OUTPUT);
pinMode (BUTTON, INPUT);
}

boolean debounce(boolean last)
{
 boolean current = digitalRead(BUTTON);
if (last != current) 
  {
    delay(5);
    current = digitalRead(BUTTON);
    return current;
  }
}

void loop()
{
currentButton = debounce(lastButton);
if (lastButton == LOW && currentButton == HIGH)
{
   ledOn = !ledOn;
}
lastButton = currentButton;
digitalWrite(LED, ledOn);
}

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Попробуйте, для начала просто сделать плавное включение ленты безо всяких кнопок. 

adamst
Offline
Зарегистрирован: 30.01.2020

в цикле нужно увеличивать продолжительность свечения светодиода, правильно написал человек в первом посте, сначала просто сделай плавное зажигание: в цикле зажигай на время T светодиод а потом гаси его на это же время и увеличивай это время T в цикле, посмотришь что получится.

MichaelS
Offline
Зарегистрирован: 19.07.2016

 

Скетч плавного включения светодиода от Ардуино
 

#define LED_PIN 6 // задаем имя для Pin6

void setup() {
    pinMode(LED_PIN, OUTPUT); // инициализируем Pin6 как выход
}

void loop() {
   // плавное включение светодиода
   // начальное значение на Pin6 i=0, если i<=255, то прибавляем к i единицу
	for(int i=0;i<=255;i++) {
	analogWrite(LED_PIN, i);
	delay(5); // ставим задержку для эффекта
   }

   //плавное затухание светодиода
   // начальное значение на Pin6 i=255, если i>=255, то вычитаем от i единицу
	for(int i=255;i>=0;i--) {
	analogWrite(LED_PIN, i);
	delay(5); // ставим задержку для эффекта
   }

}

 

на самом деле для красивого медленного эффекта там надо по SIN синусу гасить. но как правильно лень искать

 

metdet93
Offline
Зарегистрирован: 27.01.2016
Спасибо конечно, но само по себе плавное выключение и выключение уже сто раз делал, и понимаю как это работает. Никто не дал совет как решить конкретно мою проблему, совместить первоначальный скетч и For вместе. 
 
Конкретно сейчас мне нужно сделать подсветку на кухню, которая срабатывает на руку через ИК датчик, если махнуть перед им на расстоянии 5 см. И оно работает по описанному изначально алгоритму, но в темноте когда резко зажигается и гаснет не приятно на глаза, вот и решил улучшить, какой смысл мне чтобы просто туда сюда само мигало крглосуточно
asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Оформи плавное включение и выключение в виде отдельных функций, а затем вызывай их по нажатии кнопки

metdet93
Offline
Зарегистрирован: 27.01.2016
const int LED=3;
const int BUTTON=2;
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean ledOn = false;

void setup ()
{
pinMode (LED, OUTPUT);
pinMode (BUTTON, INPUT);
}

//-----------------------------------------------------------
 
void on () 
{
  for(int i=0;i<=255;i++) 
  {
    analogWrite(LED, i);
    delay(5)  
  }
}

void off ()
{
  for(int i=255;i>=0;i--) 
  {
    analogWrite(LED, i);
    delay(5);  
  }
}

//-----------------------------------------------------------

boolean debounce(boolean last)
{
 boolean current = digitalRead(BUTTON);
if (last != current) 
  {
    delay(5);
    current = digitalRead(BUTTON);
    return current;
  }
}

void loop()
{
currentButton = debounce(lastButton);
if (lastButton == LOW && currentButton == HIGH)
{
   ledOn = !ledOn;
}
lastButton = currentButton;
digitalWrite(LED, ledOn);
}

Вот так ? только я так понял что программа "не знает" текущее состояние LED, чтобы вызывать функции загорания или угасания, она просто каждый инвертирует наоборот и все, как бистабильное реле. Или я не правильно понимаю ?

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

А теперь попробуй заменить строчку 54 на

If (ledOn) on();

else off();

 

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

Поставьте конденсатор и никакого for вообще не нужно.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

ЕвгенийП пишет:

Поставьте конденсатор и никакого for вообще не нужно.

На длинную ленту, ну очень, большой конденсатор понадобится.

metdet93
Offline
Зарегистрирован: 27.01.2016

Мигает примерно раз в секунду все время, в зависимости от режима или резко загорается и плавно гаснет, или наоборот. Но теперь и режим с кнопки раза с десятого меняется)))

const int LED=3;
const int BUTTON=2;
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean ledOn = false;

void setup ()
{
pinMode (LED, OUTPUT);
pinMode (BUTTON, INPUT);
}

void on () 
{
  for(int i=0;i<=255;i++) 
  {
    analogWrite(LED, i);
    delay(5);  
  }
}

void off ()
{
  for(int i=255;i>=0;i--) 
  {
    analogWrite(LED, i);
    delay(5);  
  }
}

boolean debounce(boolean last)
{
 boolean current = digitalRead(BUTTON);
if (last != current) 
  {
    delay(5);
    current = digitalRead(BUTTON);
    return current;
  }
}

void loop()
{
currentButton = debounce(lastButton);
if (lastButton == LOW && currentButton == HIGH)
{
   ledOn = !ledOn;
}
lastButton = currentButton;
if (ledOn) on();
else off();
}

 

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

asam пишет:

На длинную ленту, ну очень, большой конденсатор понадобится.

А что, ТС писал про длинную ленту? Наверное. я пропустил что-то.

metdet93
Offline
Зарегистрирован: 27.01.2016

3 метра, 45 ватт

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

metdet93,

Вы спросили как подружить for с Вашим кодом. Дело в том, что использование for в данном контексте - суть неверное решение, которое плодит больше проблем, чем решает. Ну, допустим, Вам кто-то поможет с for, хотите я предскажу Ваш следующий вопрос? Пожалуйста, Вы скажете: "всё работает, но получается так, если уж он начал включаться, то пока полностью не включится - не прекратит, даже если уже давно поступила команда "выключаться взад", как сделать, чтобы он адекватно и своевременно реагировал на команды?". В ответ Вам посоветуют избавиться от for. И чё? "Мыло и мочало - мы начнём сначала"?

Т.е. Вы изначально неверно задали вопрос. Вместо того, чтобы спросить "Как правильно делаются такие вещи?", Вы придумали неправильное решение и просите помощи в его реализации. Видите разницу?

Запомните, циклы, если они длиннее, чем перебрать несколько байтов ответа от датчика - категорически выбиваются из самой идеологии программирования автоматики. Если ими воспользоваться, то, чтобы автоматика таки работала, придётся ставить такие костыли, что мам не горюй.

Привыкайте обходиться без циклов. У Вас уже есть цикл for - в нём вызывается функция loop. Пользуйтесь им. Никакой другой цикл Вам не нужен.

Я могу рассказать Вам как делаются такие задачи (но только вечером). Вам это нужно? Или хотите дожать идею с for? Скажите, а то если Вам не надо, мне не хочется пальцы бить. Будете делать - расскажу, ну, а "ни хочите - не ешьте" :-)

metdet93
Offline
Зарегистрирован: 27.01.2016

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

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

Дак электронщик это должен на какой-нить 555-й спаять, а сверху Д245 с КУ202-М накрутить, а не страдать программизмом.

MaksVV
Offline
Зарегистрирован: 06.08.2015

тынц . там пост #3

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

metdet93 пишет:
Если Вам не сложно, очень буду ждать)
Сегодня не вышло, но завтра в течение дня точно напишу.

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

ЕвгенийП пишет:

Поставьте конденсатор и никакого for вообще не нужно.

Конденсатор может помочь плавно изменять ток через резистор, а вот с диодом/стабилитроном такой фокус не пройдет. 

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

Ну, так резистор нужен, а светодиод у моего ребёнка на копилке вполне себе плавно гаснет.

metdet93
Offline
Зарегистрирован: 27.01.2016

так это же раздел форума по программированию))))) уже спортивный интерес блин...)))

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

metdet93 пишет:

так это же раздел форума по программированию))))) уже спортивный интерес блин...)))

а совет в #16 не помог?

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

Итак, как и обещал, расскажу, как бы я это делал.

Для начала, необходимо более или менее чётко сформулировать задачу. Начинающие игнорируют этот этап чуть реже, чем всегда, и, собственно, большинство проблем произрастают именно из этого, а не из неумения пользоваться циклами.

Кстати, если Вы говорите о подсветке на кухне, то мне кажется в Вашем первом посте ошибка. Вы пишете, что при повторном поступлении сигнала нужно выключать. Но, насколько я понимаю задачу – сигнал в Вашем случае, это «шевеление человека». Поэтому при повторном поступлении сигнала нужно продлевать время свечения. А выключать надо если сигнал не поступал в течение какого-то времени (т.е. не было шевеления – ушёл человек).

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

Итак, имеется один управляющий сигнал, одно исполняющее устройство и таймер.

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

Исполняющее устройство (ИУ) в любой момент времени находится в одном из четырёх состояний: «включено», «выключено», «в процессе включения» и «в процессе выключения». Начальное состояние исполняющего устройства – «выключено». Процессы включения и выключения характеризуются уровнем. В процессе включения уровень растёт с минимума до максимума, а в процессе выключения понижается с максимума до минимума.

Таймер отсчитывает время от последнего поступления сигнала до выключения подсветки (если за это время не поступил новый сигнал). Назовём это время – временем свечения (ВС).

Логика работы устройства такова. Постоянно, один раз в миллисекунду, по кругу повторяется следующая последовательность действий:

  1. ЕСЛИ Сигнал поступил, ТО
    1. ЕСЛИ ИУ находится в состоянии «выключено» или «в процессе выключения», ТО
      1.  перевести его в состояние «в процессе включения»
    2. установить значение таймера в ВС.
  2. ИНАЧЕ (если сигнал НЕ поступил)
    1. ЕСЛИ ИУ находится в состоянии «включено» или «в процессе включения» ТО
      1. Уменьшить значение таймера на 1
      2. ЕСЛИ значение таймера равно 0 ТО
        1. перевести ИУ в состояние «в процессе выключения»
  3. ЕСЛИ ИУ находится в состоянии «в процессе включения» ТО
    1. Увеличить уровень на ИУ
    2. ЕСЛИ уровень достиг максимума ТО
      1. Перевести ИУ в состояние «включено»
  4. ИНАЧЕ ЕСЛИ ИУ находится в состоянии «в процессе выключения» ТО
    1. Уменьшить уровень на ИУ
    2. ЕСЛИ уровень достиг минимума ТО
      1. Перевести ИУ в состояние «выключено»

Мне кажется, это всё. При такой логике устройство будет работать именно так, как я описал выше. Причём, заметьте, в п.п. 1 и 2, когда мы переключаем ИУ в состояние «в процессе включения» или «в процессе выключения», мы никак не меняем его уровень. Это означает, что если устройство включалось (светодиод разгорался), а где-то на середине этого процесса мы перевели его на выключение, он спокойно начнёт гаснуть из того положения в котором он был в момент переключения (не будет загораться полностью).

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

Если всё понятно, то вот только теперь можно переходить к написанию собственно программы. Вот, смотрите, сейчас я перепишу это же самое в виде программы – сравните. Я ведь ничего не делаю – я просто тупо записываю ровно это же в других словах. В комментариях к строкам программы указаны номера пунктов из алгоритма, приведённого выше.

void loop(void) {
	static STATES currentState = OFF; // состояние
	static uint32_t theTimer = 0;	// таймер
	static uint32_t oldMillis = 0;	// работаем 1 раз в 1 мс.
	const uint32_t currentMillis = millis();
	if (oldMillis == currentMillis) return; 
	oldMillis = currentMillis;

	if (signalDetected(currentMillis)) { // #1
		if (currentState == OFF || currentState == GOING_OFF) { // #1.1
			currentState = GOING_ON; // #1.1.1
		}
		theTimer = LIGHT_PERIOD; // #1.2
	} else { // #2
		if (currentState == ON || currentState == GOING_ON) { // #2.1
			theTimer --; // #2.1.1
			if (theTimer == 0) { // #2.1.2
				currentState = GOING_OFF; // #2.1.2.1
			}
		}
	}
	if (currentState == GOING_ON) { // #3
		const bool gotMaximum = changePWM(currentMillis, 1); // #3.1
		if (gotMaximum) { // #3.2
			currentState = ON; // #3.2.1
		}
	} else if (currentState == GOING_OFF) { // #4
		const bool gotMinimum = changePWM(currentMillis, -1); // #4.1
		if (gotMinimum) { // #4.2
			currentState = OFF; // #4.2.1
		}
	}
}

Сравнили? Прямо построчно и попунктно? Тоже самое написано?

Чего тут не хватает до полного счастья?

Определения всех состояний. Определим

enum STATES { ON, GOING_ON, OFF, GOING_OFF };

Определения константы "времени свечения" если сигнал не поступил. Определим как 2 минуты

static const uint32_t LIGHT_PERIOD = 1000ul * 60 * 2; // две минуты

Ну, и двух функций signalDetected и changePWM. Определим и их, пока пустыми:

//
//	Возвращает true, если поступил сигнал
//
bool signalDetected(const uint32_t curMillis) {
	return true;
}

//
//	увеличивае (если step > 0) или уменьшает (если step < 0)
//	уровень PWM на нагрузке и возвращает истину, если 
//	уровень достиг максимума или минимума соответсвенно
//
bool changePWM(const uint32_t curMillis, int8_t step) {
	return true;
}

Вы можете спросить "для чего функциям передаётся текущий миллис?". Ответ - обычно, пригождается, но если не пригодится, потом можно будет убрать.

Собственно нам осталось написать только те две маленькие функции, всё остальное готово.

Вы видите здесь циклы? Нет? А знаете почему? Потому, что их здесь нет!

Давайте попробуем написать функции. 

Функция signalDetected  может быть какой угодно. Она может работать с датчиком, запрашивать температуру воздуха на Луне или настроение Вашей тёщи - это неважно. Всё, что от неё требуется - вернуть true если сигнал поступил и false - если он не поступил. Я напишу её для кнопки, которая выдаёт LOW когда нажата и HIGH, когда отпущена. Опрос кнопки буду делать каждые 16 мс (давим дребезг) и сигнал считает поступившим, когда копку сначала нажали, а потом отпустили (т.е. момент отпускания - есть момент появления сигнала). Функция получается такая:

//
//	Возвращает true, если поступил сигнал
//
bool signalDetected(const uint32_t curMillis) {
	static uint32_t lastTime = 0;
	const uint32_t debouncePeriod = 16;
	if (curMillis - lastTime < debouncePeriod) return false; // нефиг часто опрашивать
	lastTime = curMillis;
	static bool currentlyPressed = false;
	const uint8_t btnState = digitalRead(PIN_BUTTON);
	if (! currentlyPressed && btnState == LOW) { // не была нажата, а теперь нажали
		currentlyPressed = true;
	} else if (currentlyPressed && btnState == HIGH) { // была нажата, а теперь отпустили
		currentlyPressed = false;
		return true; // есть сигнал!
	}
	return false;
}

Функция changePWM может (и должна) быть умной. Например, она может увеличивать (уменьшать) скважность нелинейно, а по логарифмическому закону, чтобы человеку казалось, что диод разгорается линейно. Но это уж Вы сами. Я не буду заморачиваться, а тупо напишу увеличение/уменьшение на 1 каждые 10мс. Таким образом, время полного "разгорания" - 2,56 секунды, хотя на глаз будет казаться, что меньше, т.к. в конце (или в начале, в случае угасания) яркость уже почти не будет меняться. Получилось вот так:

//
//	увеличивает (если step > 0) или уменьшает (если step < 0)
//	уровень PWM на нагрузке и возвращает истину, если 
//	уровень достиг максимума или минимума соответственно
//
bool changePWM(const uint32_t curMillis, int8_t step) {
	static uint8_t pwm = 0;
	static uint32_t lastTime = 0;
	const uint32_t changePeriod = 10;
	if (curMillis - lastTime < changePeriod) return false; // нефиг часто менять
	lastTime = curMillis;
	bool result = false;
	if (step > 0) {
		if (pwm < 255) pwm ++;
		result = pwm == 255;
	} else {
		if (pwm > 0) pwm --;
		result = pwm == 0;
	}
	analogWrite(PIN_LED, pwm);
	return result;
}

Ну, собственно задача решена - осталось добавить настройку пинов и собрать всё вместе:

static const uint32_t LIGHT_PERIOD = 1000ul * 60 * 2; // две минуты
enum STATES { ON, GOING_ON, OFF, GOING_OFF };

#define	PIN_BUTTON	11
#define	PIN_LED	10

void setup() {
	pinMode(PIN_BUTTON, INPUT_PULLUP);
}

//
//	Возвращает true, если поступил сигнал
//
bool signalDetected(const uint32_t curMillis) {
	static uint32_t lastTime = 0;
	const uint32_t debouncePeriod = 16;
	if (curMillis - lastTime < debouncePeriod) return false; // нефиг часто опрашивать
	lastTime = curMillis;
	static bool currentlyPressed = false;
	const uint8_t btnState = digitalRead(PIN_BUTTON);
	if (! currentlyPressed && btnState == LOW) { // не была нажата, а теперь нажали
		currentlyPressed = true;
	} else if (currentlyPressed && btnState == HIGH) { // была нажата, а теперь отпустили
		currentlyPressed = false;
		return true; // есть сигнал!
	}
	return false;
}

//
//	увеличивает (если step > 0) или уменьшает (если step < 0)
//	уровень PWM на нагрузке и возвращает истину, если 
//	уровень достиг максимума или минимума соответственно
//
bool changePWM(const uint32_t curMillis, int8_t step) {
	static uint8_t pwm = 0;
	static uint32_t lastTime = 0;
	const uint32_t changePeriod = 10;
	if (curMillis - lastTime < changePeriod) return false; // нефиг часто менять
	lastTime = curMillis;
	bool result = false;
	if (step > 0) {
		if (pwm < 255) pwm ++;
		result = pwm == 255;
	} else {
		if (pwm > 0) pwm --;
		result = pwm == 0;
	}
	analogWrite(PIN_LED, pwm);
	return result;
}
	
void loop(void) {
	static STATES currentState = OFF; // состояние
	static uint32_t theTimer = 0;	// таймер
	static uint32_t oldMillis = 0;	// работаем 1 раз в 1 мс.
	const uint32_t currentMillis = millis();
	if (oldMillis == currentMillis) return; 
	oldMillis = currentMillis;

	if (signalDetected(currentMillis)) { // #1
		if (currentState == OFF || currentState == GOING_OFF) { // #1.1
			currentState = GOING_ON; // #1.1.1
		}
		theTimer = LIGHT_PERIOD; // #1.2
	} else { // #2
		if (currentState == ON || currentState == GOING_ON) { // #2.1
			theTimer --; // #2.1.1
			if (theTimer == 0) { // #2.1.2
				currentState = GOING_OFF; // #2.1.2.1
			}
		}
	}
	if (currentState == GOING_ON) { // #3
		const bool gotMaximum = changePWM(currentMillis, 1); // #3.1
		if (gotMaximum) { // #3.2
			currentState = ON; // #3.2.1
		}
	} else if (currentState == GOING_OFF) { // #4
		const bool gotMinimum = changePWM(currentMillis, -1); // #4.1
		if (gotMinimum) { // #4.2
			currentState = OFF; // #4.2.1
		}
	}
}

По идее, всё должно работать как описано.

Я должен извиниться, код писался наспех, на коленке и не проверялся. Может я где и лопухнулся (хотя старался повнимательнее). Обычно я так не делаю, но тут навалилось всё, а говорить Вам ещё раз "не вышло, давайте завтра" мне уже неудобно. Но, по-любому здесь идея и подход к разработке значительно ценнее самого кода, а это я, надеюсь, до Вас донёс. Хотя, вроде, и работать должно.

P.S.
заметьте, при том решении, что получилось, состояния ON и OFF - лишние. Если их аккуратно убрать, то ничего не изменится. Но я не стал их убирать. Они "на вырост". Если захочется добавить фичи, то они наверняка сгодятся.

metdet93
Offline
Зарегистрирован: 27.01.2016

По поводу того что я изначально двигался по неверному пути это не так) я же хотел не автоматику как в уличных прожекторах с PIR датчиками,  а просто бесконтактный ручной выключатель, в идеале бесшумный) ИК датчик со своими 4-5 см расстояния срабатывания идеально справился с этой функцией, провел рукой перед ним - "включилась подсветка", еще раз провел - "выключилась". Потом уже после первых испытаний захотелось плавности, а то о чем вы говорите возможно позже при достаточных знаниях добавлю в проект (чтобы даже в выключенном состоянии подсветка включалась сама при входе человека в темное время (тот же PIR на движение, и фоторезистор например)) Вообще начал усиленно учить язык и микроконтроллеры, меня эта ситуация очень сильно подтолкнула.

Залил ваш полный скетч, после первого нажатия плавно загорается, примерно за 1 сек, и больше на кнопку не реагирует (светодиод остается включенным). Большое спасибо что не забыли, уделили столько времени) буду разбираться дальше сам на основании вашего подхода к разработке) знать в каком направлении двигаться это действительно самое ценное, этот проект можно заменить готовым модулем ик датчика для светодиодных лент, за 150 руб, который делает все тоже самое что я хочу. Цель скорее научиться программировать. Просто не был морально готов к тому что даже такая простая задумка настолько относительно сложна в реализации))  

 

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

metdet93 пишет:
плавно загорается, примерно за 1 сек, и больше на кнопку не реагирует (светодиод остается включенным).

Реагирует. Кнопка же у меня не выключает светодиод, а восстанавливает время.

Т.е. загорелся, если кнопку не трогать, то через две минуты начал гаснуть (Вы, видимо, не дождались). А вот всякий раз, когда Вы нажимаете кнопку, интервал 2 минуты восстанавливается. Т.е. гаснуть начнёт через две минуты после нажатия кнопки.

А то, что Вам надо выключать по кнопке, ну переделайте, я же написал Вам как надо делать. Начните с переделки словесного описания, потом программа сама переделается.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Евгений! Не мечите бисер перед ... ТС. Он даже словестного описания программы не прочитал, а саму ее просто скопирастил даже не разбираясь. А написали Вы классно - надо выносить в отдельную тему и приляпывать!

metdet93
Offline
Зарегистрирован: 27.01.2016

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

metdet93
Offline
Зарегистрирован: 27.01.2016

сейчас буду разбирается как изменить логику) как только придет успех скину скетч)

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

metdet93 пишет:

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

да ладно врать-то...

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

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

DetSimen пишет:

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

Скорее ЕвгенийП использует навык виляния на пустом месте, но видно сейчас более-менее расжеванное решение. Ну разумеется для нас. ТС видно будет еще долго смотреть на скетч квадратными глазами.

ЕвгенийП пишет:
Для начала, необходимо более или менее чётко сформулировать задачу. Начинающие игнорируют этот этап чуть реже, чем всегда, и, собственно, большинство проблем произрастают именно из этого, а не из неумения пользоваться циклами.
  А вот без этого навыка в жизни ну никак, а не только в программировании. Тут я +100500

metdet93
Offline
Зарегистрирован: 27.01.2016

У меня так слабо получается видать не от того что я "язык не могу выучить", а даже не могу составить логику работы контроллера на русском.  У меня какая-то хрень получается:

1. ЕСЛИ поступил сигнал

2. Плавно зажигаем ленту (пин) 0-255

3. ЕСЛИ поступил сигнал 

4. Плавно гасим пин 255-0

 

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

 

metdet93
Offline
Зарегистрирован: 27.01.2016

Пока начал узучать азы,

Код, тайный язык информатики Чарльз Петцольд

Дэвид Гриффитс, Дон Гриффитс Изучаем программирование на C

 

Но блин, кажется теперь что я гуманитарий

MaksVV
Offline
Зарегистрирован: 06.08.2015

научитесь использовать таймер на миллис. На форуме полно инфы по этому поводу. И применяйте флаги. 

Также вам нужно в понимании разделять, сигнал и изменение сигнала -  это разные вещи. Для того чтобы определить, что на входе произошло изменение лог уровня можно использовать дополнительную переменную "прошлое значение". 

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

и по поводу отказа от цикла фор рекомендую внимательнее посмотреть пример по ссылке в посте #16. Всё таки этот пример по проще для понимания , чем у Евгения. 

bwn
Offline
Зарегистрирован: 25.08.2014

metdet93 пишет:

2. Плавно зажигаем ленту (пин) 0-255

Начните с малого, аки в детском саду: алгоритм, как подмести пол -
Встать
Подойти к метле 
Взять метлу в руку (Можно понизить уровень)
                                      Поднять рабочую руку
                                      Протянуть к метле
                                      Обхватить пальцами черенок
                                      Сжать пальцы
                                      Поднять руку
                                      Переместить руку с метлой к себе
Пройти в дальний угол комнаты
Label   Опустить метлу на пол у крайней линии
Сделать движение рукой в сторону комнаты
Поднять метлу
Сделать шаг вдоль линии
IF (Не достигли края) Goto Label
Переместиться назад 
Переместиться на новую линию в сторону комнаты
Goto Label
.......................
......................))))))))))

Команда, "ходить на", здесь для упрощения.))))

metdet93
Offline
Зарегистрирован: 27.01.2016

Да, я понял что не хватает понимания алгоритмов, вообще математика по нолям. Буду её тоже учить, можете мне какой нибудь материал полезный по алгоритмам скинуть как для чайника, если есть. Я вот зашёл по первой ссылке в Гугле, и вот, это темный дремучий лес для меня.https://neerc.ifmo.ru/wiki/index.php?title=%D0%94%D0%B8%D1%81%D0%BA%D1%80%D0%B5%D1%82%D0%BD%D0%B0%D1%8F_%D0%BC%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0,_%D0%B0%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC%D1%8B_%D0%B8_%D1%81%D1%82%D1%80%D1%83%D0%BA%D1%82%D1%83%D1%80%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85

bwn
Offline
Зарегистрирован: 25.08.2014

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

Ваш пункт: "2. Плавно зажигаем ленту (пин) 0-255", не может быть выполнен одним оператором, значит его надо дробить.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Кроме того Ваши пункты должены звучать так 

1. ЕСЛИ поступил сигнал

      1.1. ЕСЛИ Лента находится в выключенном состоянии 

              1.1.1 Плавно зажигаем ленту (пин) 0-255

      1.2. ИНАЧЕ 

           1.2.1 Плавно гасим пин 255-0

2. ......

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

metdet93 пишет:

У меня так слабо получается видать не от того что я "язык не могу выучить", а даже не могу составить логику работы контроллера на русском.  У меня какая-то хрень получается:

1. ЕСЛИ поступил сигнал

2. Плавно зажигаем ленту (пин) 0-255

3. ЕСЛИ поступил сигнал 

4. Плавно гасим пин 255-0

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

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

Ну, например, попытайтесь подробно расписать, что бы Вы лично делали, если бы стояла задача:

2. Плавно зажигаем ленту (пин) 0-255

Да, и еще: нужно попытаться выделить, что именно Вам необходимо запоминать, чтобы выполнить следующие действия. Тут можно представить, что Вы продолжаете работу, начатую кем-то. Вот Вы только что пришли, что Вам должен сообщить тот, кто делал работу до Вас, чтобы Вы могли продолжать работу с текущего (а не начального) момента.
mortonlame
Offline
Зарегистрирован: 21.07.2020

Всем доброго времени суток, в том числе и Вам, Евгений! Я правильно понимаю, что для добавления фоторезистора в схеме, нужно, просто в строчке 62 после ==OFF добавить && digitalRead(//предположим//foto;1)? Второй вопрос связан с моей неопытностью в программировании: данный код будет работать, если вместо кнопки, будет датчик движения?

   

 

wer_wolf
Offline
Зарегистрирован: 08.08.2016

ЕвгенийП пишет:

 Получилось вот так:

//
//	увеличивает (если step > 0) или уменьшает (если step < 0)
//	уровень PWM на нагрузке и возвращает истину, если 
//	уровень достиг максимума или минимума соответственно
//
bool changePWM(const uint32_t curMillis, int8_t step) {
	static uint8_t pwm = 0;
	static uint32_t lastTime = 0;
	const uint32_t changePeriod = 10;
	if (curMillis - lastTime < changePeriod) return false; // нефиг часто менять
	lastTime = curMillis;
	bool result = false;
	if (step > 0) {
		if (pwm < 255) pwm ++;
		result = pwm == 255;
	} else {
		if (pwm > 0) pwm --;
		result = pwm == 0;
	}
	analogWrite(PIN_LED, pwm);
	return result;
}

Доброго времени, очень понравилось и пояснение и код, но я как не искал не могу понять логики этих строк.

result = pwm == 255;

Может кто-то пнуть меня в ссылку где описывается такая конструкция и принцеп ее работы, вариант равно со сдвигом я встречал, а вот равно со сравнением нет.

Заранее спасибо.

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

Принцип работы: вычисляется кондишн "pwm == 255" (точно так же, как в if) и результат присваивается переменной result. Если значение переменной pwm равно 255, то результатом вычисления кондишна будет true, что и попадет в result.  

wer_wolf
Offline
Зарегистрирован: 08.08.2016

sadman41 пишет:

Принцип работы: вычисляется кондишн "pwm == 255" (точно так же, как в if) и результат присваивается переменной result. Если значение переменной pwm равно 255, то результатом вычисления кондишна будет true, что и попадет в result.  

Спасибо за ответ. У меня почему-то мысли пошли в сторону проверки на превышение, если меньше 255 то запишет значение если больше или равно то 255 :)