Помогите реализовать алгоритм

saniks
Offline
Зарегистрирован: 09.04.2013

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







int analogPin = 0; // здесь фоторезистор
int ledPin = 9; // светодиод
int val = 0; // переменная для хранения значения входного напряжения

void setup()
{
 pinMode(ledPin, OUTPUT);
}

void loop()
{
 val = analogRead(analogPin); // считываем значение с фоторезистора
 if (val <=400) 
  {
   // Здесь нужно вставить код проверяющий что условие истинно в течение 5сек.
   digitalWrite(ledPin, HIGH);
  }

}

 

__Alexander
Offline
Зарегистрирован: 24.10.2012

а разве mills это не тот-же внутренний таймер?

maksim
Offline
Зарегистрирован: 12.02.2012

Вы не поверите, но даже delay() использует "внутренний" таймер. И как вам написали выше millis() тоже. Так что без таймера не получится, а вот с помощью millis() можно. 

int analogPin = 0; // здесь фоторезистор
int ledPin = 9; // светодиод
int val = 0; // переменная для хранения значения входного напряжения

void setup()
{
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  val = analogRead(analogPin); // считываем значение с фоторезистора
  static uint32_t millis_prev;
  if (val <= 400) 
  {
    if(millis()-millis_prev >= 5000) 
      digitalWrite(ledPin, HIGH);
  }
  else
    millis_prev = millis();
}

 

Илья73
Offline
Зарегистрирован: 06.09.2013

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

int analog=0; 
int rPin=8; 
void setup()
 {
 pinMode(rPin,1); // 1 это HIGH , 0 - LOW
 }
void loop()
{
  analog=analogRead(1);
  if(analog<500)
      {
       digitalWrite(8,1);
      }
        else
      {
        digitalWrite(8,0);
      }
     
}
   

 

maksim
Offline
Зарегистрирован: 12.02.2012

Нужно сделать зону нечувствительности:

#define aPin A1 
#define rPin 8 

void setup()
{
  pinMode(rPin, 1);
}

void loop()
{
  int analog = analogRead(aPin);
  
  if(analog < 500) digitalWrite(8, 1);
  else if(analog > 550) digitalWrite(8, 0);

  delay(100);
}

 

Илья73
Offline
Зарегистрирован: 06.09.2013

Спасибо! И за #define тоже, только что читал тут на форуме что int лучше по назначению использовать, потому как памяти больше берет:)

gregoryl
Offline
Зарегистрирован: 09.09.2013

Хм... господа, Вы помоему что-то путаете, можно еще сказать что timer & delay связаны между собой, но вот millis это просто чтение регистра :-)

maksim
Offline
Зарегистрирован: 12.02.2012

Серьезно? Это какого такого регистра??? 

gregoryl
Offline
Зарегистрирован: 09.09.2013

maksim пишет:

Серьезно? Это какого такого регистра??? 

Серьезно ? А как же по Вашему оно работает ?

maksim
Offline
Зарегистрирован: 12.02.2012

Вам не кажется что подход - "я так думаю значит так оно и есть" мягко говоря неверный.

"Оно" не по моему работает, "оно" работает так как работает.

Объявляется переменная:

volatile unsigned long timer0_millis = 0;

В функции init() инициализируется таймер и разрешается прерывание по переполнению счетчика.

Каждый раз при срабатывании прерывания по переполнению счетчика в оработчике прерывания инкрементируется timer0_millis :

#if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
SIGNAL(TIM0_OVF_vect)
#else
SIGNAL(TIMER0_OVF_vect)
#endif
{
	// copy these to local variables so they can be stored in registers
	// (volatile variables must be read from memory on every access)
	unsigned long m = timer0_millis;
	unsigned char f = timer0_fract;

	m += MILLIS_INC;
	f += FRACT_INC;
	if (f >= FRACT_MAX) {
		f -= FRACT_MAX;
		m += 1;
	}

	timer0_fract = f;
	timer0_millis = m;
	timer0_overflow_count++;
}

При вызове функции millis() она возвращает значение переменной timer0_millis:

unsigned long millis()
{
	unsigned long m;
	uint8_t oldSREG = SREG;

	// disable interrupts while we read timer0_millis or we might get an
	// inconsistent value (e.g. in the middle of a write to timer0_millis)
	cli();
	m = timer0_millis;
	SREG = oldSREG;

	return m;
}

Так какой регистр читается?

gregoryl
Offline
Зарегистрирован: 09.09.2013

Это никак не противоречит, моим словам, разве, что в той части, что чтение идет из переменной. 

Я хотел лишь сказать, что использование millis() не оказывают негативного влияния на производительность, как это делают  timer & delay.

З.Ы. Вообще надо сказать, что такая реализвация несколько непонятна, зачем городить такой огорд при вызове прерывания, когда можно было просто пользоваться timer0_overflow_count с последующем умножением на  MILLIS_INC и коррекцией по FRACT_MAX. Для 90% задач не требуется конкретная единица времени, требуеются просто наличие clock().

 

maksim
Offline
Зарегистрирован: 12.02.2012

Как это не противоречит? 

gregoryl пишет:

Хм... господа, Вы помоему что-то путаете, можно еще сказать что timer & delay связаны между собой, но вот millis это просто чтение регистра :-)

Еще как противоречит. Что мы тут путаем? 

delay() использует micros(), которая организована (что касается таймера) тем же образом что и millis() :

void delay(unsigned long ms)
{
	uint16_t start = (uint16_t)micros();

	while (ms > 0) {
		if (((uint16_t)micros() - start) >= 1000) {
			ms--;
			start += 1000;
		}
	}
}

И delay() и micros() и millis() связаны между собой тем что используют одно и тоже прерывание таймера.

 

gregoryl
Offline
Зарегистрирован: 09.09.2013

maksim пишет:

Как это не противоречит? 

.............

И delay() и micros() и millis() связаны между собой тем что используют одно и тоже прерывание таймера.

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

Таймер - это таймер он сам по себе. 

micros & milis, пользуются общей переменной с таймером, но ни в коей мере не пользуются самим таймером.

delay стоит от таймера еще дальше чем первые 2 функции. Это вообще недорозумение ходячее в такой его реализации. Вы его случаем не сами написали ? Только из любви к человечеству возмите за основу ваш delay, а таймер и всю остальную лабуду заменим простенькой функцией micros ну и запустите все любойм дебагере и пройдите по шагам.

unsigned long xTime=65000;
unsigned long micros() {
	 xTime= xTime + 500; return xTime;
}

ну и запустите после этого простенький примерчик

int main(int argc, char * argv[])
{
	delay( 5000 );
	return 0;
}

Вообщем развлекайтесь, или для Вас это слишком смелые эксперименты ?

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

gregoryl пишет:

Я хотел лишь сказать, что использование millis() не оказывают негативного влияния на производительность, как это делают  timer & delay.

Для моего развития сугубо. Это как? Выполняется за нулевой отрезок времени?

gregoryl
Offline
Зарегистрирован: 09.09.2013

JollyBiber пишет:

Для моего развития сугубо. Это как? Выполняется за нулевой отрезок времени?

Почти. Если вы посмотрите код который приводили выше, то грубо говоря для время выполнения millis() это чтение из переменной где храниться текущее значение. Время выполнения конечно не ноль, но всего лишь несколько тактов процессора, и когда вы пишете свою программу вы можете не считать это по соти нулевым временем, ну примерно как вы считаете нулевым временем выполнения когда вы пишите int a = x + y;

З.Ы. millis() это не блокирующая операция в отличии от delay() 

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

gregoryl пишет:

JollyBiber пишет:

Для моего развития сугубо. Это как? Выполняется за нулевой отрезок времени?

З.Ы. millis() это не блокирующая операция в отличии от delay() 

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

gregoryl
Offline
Зарегистрирован: 09.09.2013

JollyBiber пишет:

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

Для меня тут ничего спорного нет. Неблокирующие операции это "религия", а не наличие или отсутсвие многозадачности. Никто не мешает вам самостоятельно параллелить :-) грубо говоря не надо ждать получения значения, нужно забить и прочитать в следующий раз, а пока нам есть чем заняться... :-)

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

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

gregoryl пишет:

Для меня тут ничего спорного нет.

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

gregoryl пишет:

Никто не мешает вам самостоятельно параллелить :-) грубо говоря не надо ждать получения значения, нужно забить и прочитать в следующий раз, а пока нам есть чем заняться... :-)

На ардуине? Нет уж, увольте...

gregoryl
Offline
Зарегистрирован: 09.09.2013

JollyBiber пишет:

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

Ну попробуйте, чем черт не шутит :-) вдруг у и Вас тоже в артуине живет магия космоса.

maksim
Offline
Зарегистрирован: 12.02.2012

gregoryl пишет:

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

Таймер - это таймер он сам по себе. 

micros & milis, пользуются общей переменной с таймером, но ни в коей мере не пользуются самим таймером.

delay стоит от таймера еще дальше чем первые 2 функции. 

Я не пойму вы о чем спорите? Или у вас не хватает знаний что даже не понимаете о чем вы спорите? Или вы специально идиотом претворяетесь?

Подход "я так думаю значит так оно и есть" в действии?

Я вам показал коды функций, разъяснил что откуда, какая связь между этими функциями и замете это не я придумал, можете сами посмотреть файлы wiring.c и Arduino.h. Какие то бредо-функции мне предлогаете проверить. Вы о чем вообще?

Повторяю вам еще раз.

Функции micros() millis() и delay() в том числе так как она использует micros(), все они завязаны на один и тот же таймер, а именно на прерывание по переполнению таймера.

 

maksim
Offline
Зарегистрирован: 12.02.2012

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

gregoryl
Offline
Зарегистрирован: 09.09.2013

Ню-Ню.... Я вообще о том, что 

1. Вы даже не в состоянии прочитать код который сами же приводите.

2. Вы, не проверя предложенных Вам аргументов охарактеризовали из как бредо-функции.

3. Вы можете повторять сколько угодно раз "халва", во рту слаще не станет.

 

maksim
Offline
Зарегистрирован: 12.02.2012

Ну так что спорим? Чисто символически 500р. на телефон.

1. Да ладно? То что его не можете прочитать вы не означает что не могу я. И вы случайно не экстрасенс? Тут на форуме их очень не хватает.

2. В чем по вашему я должен их проверять, вы форумом не ошиблись?

3. Все верно, не станет.

Araris
Offline
Зарегистрирован: 09.11.2012

maksim
Offline
Зарегистрирован: 12.02.2012

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

Ну ладно расскажу так.

Рассмотрим на УНО-подобной плате.

Открываем даташит на ATmega48PA/88PA/168PA/328P, а именно Timer/Counter0 и смотрим как он настраивается. Находим описание регистра TCCR0B:

и описание битов CS02, CS01, CS00

• Bits 2:0 – CS02:0: Clock Select
The three Clock Select bits select the clock source to be used by the Timer/Counter.

О-о! То что нужно No clock source (Timer/Counter stopped) - просто остановим таймер, ведь он же никак не связан с нашими функциями и особенно с функцией delay() !!!

Заливаем скейтч в дуину:

void setup()
 {       
  TCCR0B = 0;
  pinMode(13, OUTPUT);     
}

void loop()
 {
  digitalWrite(13, HIGH);   // set the LED on
  delay(1000);              // wait for a second
  digitalWrite(13, LOW);    // set the LED off
  delay(1000);              // wait for a second
}

С каким интервалом будет мигать светодиод? 

Заливаем следующий:

void setup()
{
  TCCR0B = 0;
  Serial.begin(9600);
}

void loop() 
{
  Serial.println(millis());
}
Что видите в мониторе?
 
И еще один:
void setup()
{
  TCCR0B = 0;
  Serial.begin(9600);
}

void loop() 
{
  Serial.println(micros());
}

И попробуйте тоже самое с магической силой космоса - удалите строку TCCR0B = 0;

Дальше будете уператься и стоять на своем - что эти функции никак не связаны и уж тем более таймером?

MacSim
Offline
Зарегистрирован: 28.11.2012

Теска 100% ПРАВ.

чтобы не использовать таймер надо циклить. при этом учитывать частоту кварца и значение предделителя.

(удивляюсь кто придумал делей и иже с ними на таймере. что нельзя #define F_CPU 8000000 и в цикле ее использовать. в таком исполнении как есть она предназначена считать время с момента включения. а мне не надо знать время с момента включения. обычная пауза нужна. NOP и все!)

столкнулся с проблемой delay -ев когда возникла необходимость юзать в своей проге  т1 и т2.

подружить их пока не получилось.

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

saniks = 1 пост, он же - вопрос....

все остальные посты - нафига ему оне щас? он учится... отошлите его в таймеры, на миллис и др.

ну почему начинающим не ответить опытным, а не - ТОЖЕначинающим ?

КТО знает про Лешака чо ???? ....давно не видел :(

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

saniks - определите два флага - "освещённость =< 400" и "менялась ли освещённость на > 400 за 300 сек"...

...через миллис()

...кататак

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

#4 - гистерезис.... 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

"...   1. Вы даже не в состоянии прочитать код который сами же приводите.   ..."

и ТАКОЕ бывает ?????? :(

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

"...... О-о! То что нужно No clock source (Timer/Counter stopped) - просто остановим таймер, ведь он же никак не связан с нашими функциями и особенно с функцией delay() !!!   ..."

.....блиииин, спрашивал же ранее про остановку таймера для некоторых целей..... :( ...сказали- нежелательно/невозможно...

....хорошо, что не поверил :)

MacSim
Offline
Зарегистрирован: 28.11.2012

SU-27-16 пишет:

"...... О-о!  :( ...сказали- нежелательно/невозможно.

..хорошо, что не поверил :)

Если верить посту #11  то все эти функции  в конечном счете юзают таймер 0. Поэтому без него работать не должны. Даже предделитель Т0 не надо трогать, а то секунда не секундой будет. Он на 64 запрограмирован.

 

Верить нельзя ничему! Проверяли? Пробывали остановить Т0 и использовать delay?

 

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

SU-27-16 пишет:

saniks = 1 пост, он же - вопрос....

все остальные посты - нафига ему оне щас? он учится... отошлите его в таймеры, на миллис и др.

ну почему начинающим не ответить опытным, а не - ТОЖЕначинающим ?

КТО знает про Лешака чо ???? ....давно не видел :(

Та они все закордонные куда то исчезли и лешак, и пухлявый, и дохтур((((