Точный Таймер На Ардуино

kosta-87
Offline
Зарегистрирован: 19.01.2012

Привет всем!! Я начинающий в сфере ардуино, понадобился таймер и решил его сделать сам, по идее таймер  должен быть с разрешением 1,999 сек короче должен считать секунды и  миллисекунды, и должно быть 2 кнопки старт и стоп таймерa. я только начал изучать программирование на ардуино накаляпал пару цветомузык простеньких но думаю далеко мне до таймера, прошу помочь с программой в.с. скетчем есть Arduino Uno R3, lcd 16x2 HD44780, макетная плата и короче всё что надо. думаю код не должен быть очень сложным и прошу помочь в написании хотяб как начать или какойнибудь совет  заранее благодарен всём кто поможет. еще я слышал про внешний таймер с которого считывается время, подскажите пожалуйстo точно что это такое я видел по 2$ на ебай RTC Module Clock Timer Memory.

melvladimir
Offline
Зарегистрирован: 08.03.2013

Какая точность интересует?

Если кроме таймера ничего больше, то можно сделать простой разницей между millis() на момент нажатия кнопки "старт" и нажатием кнопки "стоп".

Если использовать 2 внешних прерывания (читаем attachInterrupt), то на дребезг можно забить, поскольку 10 повторных нажатий погоды не делает.

Если нужна высокая точность, то использовать micros().

kosta-87
Offline
Зарегистрирован: 19.01.2012

melvladimir пишет:

Какая точность интересует?

Если кроме таймера ничего больше, то можно сделать простой разницей между millis() на момент нажатия кнопки "старт" и нажатием кнопки "стоп".

Если использовать 2 внешних прерывания (читаем attachInterrupt), то на дребезг можно забить, поскольку 10 повторных нажатий погоды не делает.

Если нужна высокая точность, то использовать micros().

 

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

melvladimir
Offline
Зарегистрирован: 08.03.2013

Вот практически готовый скетч, осталось только включить нужные порты на чтение и поставить у них значение HIGH.
То, что millis и micros работают с момента включения - для нас не важно. Нам нужны "отрезки".

volatile unsigned long start = 0; //переменная для хранения начального значения millis
volatile unsigned long stop = 0; //переменная для хранения полученного промежутка времени
unsigned long prev_ms = 0; //переменная для создания отрезков, чтобы не использовать delay

void setup() {
//нужно настроить порты на чтение, читаем как использовать кнопки, как настраивать порты.
attachInterrupt(0, begin, FALLING);
attachInterrupt(1, end, FALLING);
Serial.begin(9600);
}

void loop() {
	if ((millis() - prev_ms) >  500) { //вывод данных каждые 500мс
		prev_ms = millis();
		Serial.println(stop);
	}
}

void begin() {
	start = millis(); //получаем текущее значение millis
}

void end() {
	stop = millis() - start; //вычисляем промежуток
}

 

melvladimir
Offline
Зарегистрирован: 08.03.2013

А дребезг можно обойти программно, например вот так:

volatile unsigned long start = 0; //переменная для хранения начального значения millis
volatile unsigned long stop = 0; //переменная для хранения полученного промежутка времени
volatile int once = 0; //переменная для игнорирования повторного нажатия кнопки
unsigned long prev_ms = 0; //переменная для создания отрезков, чтобы не использовать delay

void setup() {
//нужно настроить порты на чтение, читаем как использовать кнопки, как настраивать порты.
attachInterrupt(0, begin, FALLING);
attachInterrupt(1, end, FALLING);
Serial.begin(9600);
}

void loop() {
	if ((millis() - prev_ms) >  500) { //вывод данных каждые 500мс
		prev_ms = millis();
		Serial.println(stop);
	}
}

void begin() {
	if (once == 0) { //проверяем, нажималась ли уже кнопка старт
		start = millis(); //получаем текущее значение millis
		once = 1; //ставим метку "старт был нажат"
		stop = 0; //обнуляем предыдущий замер, а можно и не обнулять :)
	}
}

void end() {
	if (once == 1) { //проверяем, нажималась ли кнопка старт
		stop = millis() - start; //вычисляем промежуток
		once = 0; //убираем метку
	}
}

 

kosta-87
Offline
Зарегистрирован: 19.01.2012

огромное вам спасибо Владимир, я написал вот это но не работает

 

unsigned long startml;
unsigned long stopml;
unsigned long currentml;
unsigned long dragtime;
int startbt = 10;
int stopbt = 11;
 
void setup() {
  pinMode (startbt, INPUT);
  pinMode (stopbt, INPUT);
  Serial.begin(9600);
}
 void loop()
{
  if (startbt == LOW){
  startml = millis();
}
 if (stopbt == LOW){
    currentml = millis();
    dragtime = (currentml - startml);
    Serial.println(dragtime);
 }
}

 

 

melvladimir
Offline
Зарегистрирован: 08.03.2013

Обязательно читать: http://arduino.ru/Tutorial/DigitalPins
Поскольку в коде нет включения подтягивающего резистора, скорее-всего из-за этого и не работает.

Попробуйте полностью мой код + добавьте в него включение портов на чтение + подтягивающего резистора.
Для UNO внешнее прерывание на портах 2 (кнопка старт) и 3 (снопка стоп).

melvladimir
Offline
Зарегистрирован: 08.03.2013

И вот это тоже рекомендую почитать: http://arduino.ru/Reference/AttachInterrupt
Внешние прерывания - хорошая штука :)

kosta-87
Offline
Зарегистрирован: 19.01.2012
сделал вот так по вашему скетчу все заработало огромное вам спасибо!!
 
 
volatile unsigned long start = 0; //переменная для хранения начального значения millis
volatile unsigned long stop = 0; //переменная для хранения полученного промежутка времени
volatile int once = 0; //переменная для игнорирования повторного нажатия кнопки
unsigned long prev_ms = 0; //переменная для создания отрезков, чтобы не использовать delay
volatile int state = LOW;

void setup() {
//нужно настроить порты на чтение, читаем как использовать кнопки, как настраивать порты.
pinMode(2, INPUT);
digitalWrite(2, HIGH);
pinMode(3, INPUT);
digitalWrite(3, HIGH);
attachInterrupt(0, begin, FALLING);
attachInterrupt(1, end, FALLING);
Serial.begin(9600);
}

void loop() {
	if ((millis() - prev_ms) >  500) { //вывод данных каждые 500мс
		prev_ms = millis();
		Serial.println(stop);
	}
}

void begin() {
	if (once == 0) { //проверяем, нажималась ли уже кнопка старт
		start = millis(); //получаем текущее значение millis
		once = 1; //ставим метку "старт был нажат"
		stop = 0; //обнуляем предыдущий замер, а можно и не обнулять :)
	}
}

void end() {
	if (once == 1) { //проверяем, нажималась ли кнопка старт
		stop = millis() - start; //вычисляем промежуток
		once = 0; //убираем метку
	}
}

 

 

kosta-87
Offline
Зарегистрирован: 19.01.2012

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

melvladimir
Offline
Зарегистрирован: 08.03.2013

Пожалуйста :)

Для увеличения точности можно заменить millis на micros (там, где отрезки делает по 500мс - менять не надо), но не обязательно.

Также можно сохранять предыдущий результат и выводить новый в новой строке. Или вообще 4 варианта (для дисплея 1602).

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

kosta-87
Offline
Зарегистрирован: 19.01.2012

на lcd это вывести не получается там применены 2, 3, выводы. я думаю на 7сегментные табло вывести время. вы довольно хорошо и быстро придумали скетч а я несколько недель как начал вникать в ардуино пока мне не так легко понять, но кое-что я понимаю. отчет будет максимум до 1мин в миллисекундах ну это уже я придумаю как сделать. огромное вам спасибо ешё раз.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

pinMode(2, INPUT);
digitalWrite(2, HIGH);

меняем на pinMode(2, INPUT_PULLUP);  ( Так понятнее)

 

melvladimir
Offline
Зарегистрирован: 08.03.2013

Выводы на дисплей вроде можно переопределить, точно не уверен (не пробовал).

Самое сложно - найти "доступно" написанные инструкции и примеры с описанием и комментариями.

Клапауций
Offline
Зарегистрирован: 10.02.2013

melvladimir пишет:

Выводы на дисплей вроде можно переопределить, точно не уверен (не пробовал).

переопределяется на любые другие.