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

aleksstreg
Offline
Зарегистрирован: 08.07.2015

Прошу помощи знатоков.

Для старта машинок на время, все как на трассах автогонок. Ардуино уно + lcd2004 (20,4) + 2 кнопки (Старт и Стоп, потом можно заменить на датчики) + 3 светодиода. Смысл такой:

- при нажатии кнопки "Старт",поочередно, с задержкой, включаются 3 светодиода и включается таймер (гонка началась);

- работа таймера отображается в верхней строчке

-при пересечении финиша 1 машинки срабатывает кнопка "Стоп" (потом можно и сенсор поставить) и во второй строке появляется время 1 машинки

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

Просмотрел в инете что нибудь подобное, пока получилось вот так:

[code]
int Blink1=8;
int Blink2=9;
int Blink3=10;
int StartPin=2;
int StopPin=3;
int h,m,s; // переменные для минут, секунд, милисекунд
boolean z;  // переменная для отображения точки
// подключаем библиотеку индикатора
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4); // Для экрана 20х4 (четырехстрочный) 
//LiquidCrystal_I2C lcd(0x27, 16, 2); // Для экрана 16х2 (двухстрочный
// Variables will change :
int ledState = LOW;             // ledState used to set the LED
unsigned long previousMillis = 0;        // will store last time LED was updated
const long interval = 5;           // interval at which to blink (milliseconds)
void setup() {
//нужно настроить порты на чтение, читаем как использовать кнопки, как настраивать порты.
 pinMode(StartPin, INPUT);
digitalWrite(StartPin, HIGH);
pinMode(StopPin, INPUT);
digitalWrite(StopPin, HIGH);
lcd.begin(); 
delay(2000);
digitalWrite(Blink1,HIGH);
delay(1500);
digitalWrite(Blink2,HIGH);
delay(2000);
digitalWrite(Blink3,HIGH);
}

void loop()
{
 if(digitalRead(StartPin)==HIGH) {
  unsigned long currentMillis = millis();
if(currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
s++;   
if (s>59)   
{
s=0;       // присваиваем значение 0 переменной s
m++;     // добавляем 1 к переменной m отвечающей за секунды
}
// секция подсчета секунд
if (m>59)   // если значение m больше 59
{
m=0;       // присваиваем значение 0 переменной m
h++;     // добавляем 1 к переменной h отвечающей за минуты
}
// секция подсчета минут
if (h>23)   // если значение h больше 23
{
h=0;       // присваиваем значение 0 переменной h
}
// секция вывода информации
// вывод милисекунд
if (s<10) //если милисекунд меньше 10
{
lcd.setCursor(13, 0); // курсор в 6 позицию 0 строки
lcd.print(0); //печатаем 0
lcd.setCursor(14, 0); //курсор в 7 позицию 0 строки
lcd.print(s); //печатаем значение переменной s
}
else 
{
lcd.setCursor(13, 0); //иначе курсор в 6 позицию 0 строки
lcd.print(s); // печатаем значение переменной s
}
lcd.setCursor(12, 0); // курсор в 5 позицию 0 строки
lcd.print(":"); //  печатаем разделитель между милисекундами и секундами
// вывод секунд
if (m<10)
{
lcd.setCursor(10, 0);
lcd.print(0);
lcd.setCursor(11, 0);
lcd.print(m);
}
else
{
lcd.setCursor(10, 0);
lcd.print(m);
}
lcd.setCursor(9, 0); // курсор в 2 позицию 0 строки
lcd.print(":"); //  печатаем разделитель между секундами и минутами
// вывод минут
if (h<10)
{
lcd.setCursor(7, 0);
lcd.print(0);
lcd.setCursor(8, 0);
lcd.print(h);


Пробовал еще вот так (в одной из тем было)

[code]
int Blink1=8;
int Blink2=9;
int Blink3=10;
int h,m,s; // переменные для минут, секунд, милисекунд
boolean z;  // переменная для отображения точки
// подключаем библиотеку индикатора
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4); // Для экрана 20х4 (четырехстрочный) 
volatile unsigned long start = 0; //переменная для хранения начального значения millis
volatile unsigned long stop = 0; //переменная для хранения полученного промежутка времени
volatile int once = 0; //переменная для игнорирования повторного нажатия кнопки
unsigned long prev_ms = 0; //переменная для создания отрезков, чтобы не использовать delay
volatile int state = HIGH;
   void setup() {
 //нужно настроить порты на чтение, читаем как использовать кнопки, как настраивать порты.
  pinMode(2, INPUT);
  digitalWrite(2, HIGH);
  pinMode(3, INPUT);
 digitalWrite(3, HIGH);
 attachInterrupt(0, begin, LOW);
 attachInterrupt(1, end, LOW);
 lcd.begin(); 
 delay(2000);
digitalWrite(Blink1,HIGH);
delay(1500);
digitalWrite(Blink2,HIGH);
delay(2000);
digitalWrite(Blink3,HIGH);
}
  void loop() {
      if ((millis() - prev_ms) >  10) { //вывод данных каждые 500мс
          prev_ms = millis();
          s++;   
if (s>59)   
{
s=0;       // присваиваем значение 0 переменной s
m++;     // добавляем 1 к переменной m отвечающей за секунды
}
// секция подсчета секунд
if (m>59)   // если значение m больше 59
{
m=0;       // присваиваем значение 0 переменной m
h++;     // добавляем 1 к переменной h отвечающей за минуты
}
// секция подсчета минут
if (h>59)   // если значение h больше 23
{
h=0;       // присваиваем значение 0 переменной h
}
// секция вывода информации
// вывод милисекунд
if (s<10) //если милисекунд меньше 10
{
lcd.setCursor(13, 0); // курсор в 6 позицию 0 строки
lcd.print(0); //печатаем 0
lcd.setCursor(14, 0); //курсор в 7 позицию 0 строки
lcd.print(s); //печатаем значение переменной s
}
else 
{
lcd.setCursor(13, 0); //иначе курсор в 6 позицию 0 строки
lcd.print(s); // печатаем значение переменной s
}
lcd.setCursor(12, 0); // курсор в 5 позицию 0 строки
lcd.print(":"); //  печатаем разделитель между милисекундами и секундами
// вывод секунд
if (m<10)
{
lcd.setCursor(10, 0);
lcd.print(0);
lcd.setCursor(11, 0);
lcd.print(m);
}
else
{
lcd.setCursor(10, 0);
lcd.print(m);
}
lcd.setCursor(9, 0); // курсор в 2 позицию 0 строки
lcd.print(":"); //  печатаем разделитель между секундами и минутами
// вывод минут
if (h<10)
{
lcd.setCursor(7, 0);
lcd.print(0);
lcd.setCursor(8, 0);
lcd.print(h);
}
else
{
lcd.setCursor(7, 0);
lcd.print(h);
}
}
}
void begin() {
if (once == 0) { //проверяем, нажималась ли уже кнопка старт
start = millis(); //получаем текущее значение millis
once = 1; //ставим метку "старт был нажат"
stop = 0; //обнуляем предыдущий замер, а можно и не обнулять :)
}
}
void end()   {
if (once == 1) { //проверяем, нажималась ли кнопка старт
stop = millis() - start; //вычисляем промежуток
once = 0; //убираем метку
}
}

[/code]

В итоге таймер работает и отображается на 1 строке экрана. Кнопки стоп и старт при нажатии останавливают таймер (пока держишь, потом дальше идет счет). 

Как вытащить данные при замыкании кнопки стоп для статичного отображения на 2 строке экрана. Пробовал повторять в loopе отображать одновременно таймер сразу в 2-х и более строках, что бы потом как то тормозить отображение таймера построчно (2,3,4), но видимо из-за этого замедляется процесс в loope и секунда становятся удлиняется (т.е. отображение одной секунды сравнимо с 3 -4 секундами).

В общем, первая проба сделать скейтч для ардуино. Help Me Please!!!

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

Я предлагаю свой код

/*
//#1 светодиоды красный -> 8 (red_pin)  0 горит/ 1 нет
                желтый  -> 9 (yellow_pin) 0 горит/ 1 нет
                зеленый -> 10 (green_pin) 0 горит/ 1 нет
//#2 кнопки Старт -> 2 (start_pin) 0 нажата/ 1 нет
              GND ->  GND
            Стоп   -> 3 (stop_pin)  0 нажата/ 1 нет
               GND ->  GND
//#3 I2C LCD1602      GND -> GND 
                      +5V -> +5V
                      SDA -> A4(SDA)
                      SCL -> A5(SCL)
*/
//#0
uint32_t timer=0;
uint8_t plus=0;
//#1
const int red_pin=8; // светодиод красный
uint8_t red;
const int yellow_pin=9; // светодиод желтый
uint8_t yellow;
const int green_pin=10; // светодиод зеленый
uint8_t green;
const uint16_t interval=1000;// с каким периодом зажигаются светодиоды
//#2
const int start_pin=2; // нога кнопки старт 
const int stop_pin=3; // нога кнопки стоп
uint8_t start_btn,start_old_btn;
uint8_t stop_btn,stop_old_btn;
//#3
  #include <Wire.h> 
  #include <LiquidCrystal_I2C.h>
  LiquidCrystal_I2C lcd(0x27,16,2);  // Устанавливаем дисплей
 void setup() {
//#1
   pinMode(red_pin, OUTPUT);  // гасим красный светодиод
   digitalWrite(red_pin,red=1);
   pinMode(yellow_pin, OUTPUT);// гасим желтый светодиод
   digitalWrite(yellow_pin,yellow=1);
   pinMode(green_pin, OUTPUT);// гасим зеленый светодиод
   digitalWrite(green_pin,green=1);
//#2
   pinMode(start_pin, INPUT_PULLUP);// подключаем кнопку Старт
   start_btn =digitalRead(start_pin);
   pinMode(stop_pin, INPUT_PULLUP);// подключаем кнопку Стоп
   stop_btn =digitalRead(stop_pin);
//#3
    lcd.init()             ;                     
    lcd.backlight()        ; // Включаем подсветку дисплея
}
void loop() {
  static uint32_t MILLIS ;
  MILLIS = millis() ;
 //#0 10 миллисек поток таймера
 static uint32_t future0 = 0 ;
 if (MILLIS >=future0){
   future0=future0+10;
   timer=timer+plus;
   }
 //#1  непрерывно управляем светодиодами
 static uint32_t future1 = 0 ;
  if (!green&&(MILLIS >=future1)) { // гасим зеленый 
       digitalWrite(green_pin,green=1);
       } 
  if (!yellow&&(MILLIS >=future1)) { // гасим желтый и включ зеленый и включ таймер
       digitalWrite(yellow_pin,yellow=1);
       future1=MILLIS+interval;
       digitalWrite(green_pin,green=0);
       plus=1; timer=0;
       } 
 if (!red&&(MILLIS >=future1)) {  // гасим красный и включ желтый
       digitalWrite(red_pin,red=1);
       future1=MILLIS+interval;
       digitalWrite(yellow_pin,yellow=0);
        } 
 //#2 непрерывно опрашиваем кнопки
    start_old_btn=start_btn;
    start_btn =digitalRead(start_pin);
    if (!start_btn && start_old_btn) { // если нажата кнопка старт
       future1=MILLIS+interval;
       digitalWrite(red_pin,red=0); // вкл красный
         }
    stop_old_btn=stop_btn;
    stop_btn =digitalRead(stop_pin);
    if (!stop_btn && stop_old_btn) { // если нажата кнопка стоп
    plus=0; // остановить таймер
    }
 //#3 0,5 секунд обновление экрана
  static uint32_t future3 = 0 ;
   if (MILLIS >=future3){
       future3=future3+500;
       lcd.clear(); 
       lcd.print(timer);
   }
 }

 

aleksstreg
Offline
Зарегистрирован: 08.07.2015

Спасибо, попробую разобраться.

А как сделать нормальное отображение таймера на экране минуты:секунды:милисекунды. Сейчас на экране получается просто меняющийся набор цифр по мере работы таймера. Может как то включается? 

Еще 

48     lcd.init()  

 пришлось заменить

на lcd.begin() , а то ругается при компиляции и экран поправить с  LiquidCrystal_I2C lcd(0x27,16,2) на  LiquidCrystal_I2C lcd(0x27,20,4)

может не правильно что то сделал? или библиотеку какую надо подключать?

aleksstreg
Offline
Зарегистрирован: 08.07.2015

Интересно, подключил другую библиотеку LiquidCrystal_I2C lcd - теперь lcd.init() принимает.

Обнаружил у себя таймер DS3231, буду на нем колдовать с уно.