Велосипедный спидометр Arduino

stels
Offline
Зарегистрирован: 03.01.2014

приветствую

есть проект

Велосипедный спидометр на Arduino

и ссылка на оригинал статьи

Arduino Bike Speedometer

я немного переделал код под км/ч и не serial lcd, у меня получилось это

//bike speedometer
//by Amanda Ghassaei 2012
//http://www.instructables.com/id/Arduino-Bike-Speedometer/

/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*/

//outputs speed of bicycle to LCD

//calculations
//tire radius ~ 13.5 inches
//circumference = pi*2*r =~85 inches
//max speed of 35mph =~ 616inches/second
//max rps =~7.25

#define reed A0//pin connected to read switch
#include <LiquidCrystal.h>//установил обычный дисплей
LiquidCrystal lcd(12, 11, 5, 4, 3, 6);
//storage variables

int reedVal;
long timer = 0;// time between one full rotation (in ms)
float mph = 0.00;
float circumference;
boolean backlight;

int maxReedCounter = 100;//min time (in ms) of one rotation (for debouncing)
int reedCounter;


void setup(){

reedCounter = maxReedCounter;
circumference = 2095; //здесь явно задал окружность
pinMode(1,OUTPUT);//tx
pinMode(2,OUTPUT);//backlight switch
pinMode(reed, INPUT);
lcd.begin(16, 2);

Serial.write(12);//clear

// TIMER SETUP- the timer interrupt allows preceise timed measurements of the reed switch
//for mor info about configuration of arduino timers see http://arduino.cc/playground/Code/Timer1
cli();//stop interrupts

//set timer1 interrupt at 1kHz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;
// set timer count for 1khz increments
OCR1A = 1999;// = (1/1000) / ((1/(16*10^6))*8) - 1
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS11 bit for 8 prescaler
TCCR1B |= (1 << CS11);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);

sei();//allow interrupts
//END TIMER SETUP

}



ISR(TIMER1_COMPA_vect) {//Interrupt at freq of 1kHz to measure reed switch
reedVal = digitalRead(reed);//get val of A0
if (reedVal){//if reed switch is closed
if (reedCounter == 0){//min time between pulses has passed
mph = (3.6*float(circumference))/float(timer);//calculate miles per hour // и переделал формулу
timer = 0;//reset timer
reedCounter = maxReedCounter;//reset reedCounter
}
else{
if (reedCounter > 0){//don't let reedCounter go negative
reedCounter -= 1;//decrement reedCounter
}
}
}
else{//if reed switch is open
if (reedCounter > 0){//don't let reedCounter go negative
reedCounter -= 1;//decrement reedCounter
}
}
if (timer > 2000){
mph = 0;//if no new pulses from reed switch- tire is still, set mph to 0
}
else{
timer += 1;//increment timer
}
}

void displayMPH(){
lcd.clear();//clear
lcd.print("Speed =");
lcd.setCursor(0, 1);
lcd.print(mph);
//Serial.write(" MPH ");
//Serial.write("0.00 MPH ");
}

void loop(){
//print mph once a second
displayMPH();
delay(1000);
}

подскажите, я правильно провел вычисления?

как можно добавить одометр?

stels
Offline
Зарегистрирован: 03.01.2014

извиняюсь за форматирование, пока нет возможности вставить в нормальном, позже поправлю

stels
Offline
Зарегистрирован: 03.01.2014

новая версия

//bike speedometer
//by Amanda Ghassaei 2012
//<a href="http://www.instructables.com/id/Arduino-Bike-Speedometer/" rel="nofollow">http://www.instructables.com/id/Arduino-Bike-Speedometer/</a>

/*
* This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 */

//outputs speed of bicycle to LCD

//calculations
//tire radius ~ 13.5 inches
//circumference = pi*2*r =~85 inches
//max speed of 35mph =~ 616inches/second
//max rps =~7.25

#define reed A0//pin connected to read switch
#include <LiquidCrystal.h>//установил обычный дисплей
LiquidCrystal lcd(12, 11, 5, 4, 3, 6);
//storage variables

int reedVal;
int odo;//количество оборотов колеса
long timer = 0;// time between one full rotation (in ms)
float mph = 0.00;
float circumference;
boolean backlight;
char vivod;

int maxReedCounter = 100;//min time (in ms) of one rotation (for debouncing)
int reedCounter;


void setup(){
  odo=0;
  reedCounter = maxReedCounter;
  circumference = 2095; //здесь явно задал окружность
  pinMode(1,OUTPUT);//tx
  pinMode(2,OUTPUT);//backlight switch
  pinMode(reed, INPUT);
  lcd.begin(16, 2);

  Serial.write(12);//clear

  // TIMER SETUP- the timer interrupt allows preceise timed measurements of the reed switch
  //for mor info about configuration of arduino timers see <a href="http://arduino.cc/playground/Code/Timer1" title="http://arduino.cc/playground/Code/Timer1" rel="nofollow">http://arduino.cc/playground/Code/Timer1</a>
  cli();//stop interrupts

  //set timer1 interrupt at 1kHz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1 = 0;
  // set timer count for 1khz increments
  OCR1A = 1999;// = (1/1000) / ((1/(16*10^6))*8) - 1
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS11 bit for 8 prescaler
  TCCR1B |= (1 << CS11);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);

  sei();//allow interrupts
  //END TIMER SETUP

}



ISR(TIMER1_COMPA_vect) {//Interrupt at freq of 1kHz to measure reed switch
  reedVal = digitalRead(reed);//get val of A0
   
  if (reedVal){//if reed switch is closed
    if (reedCounter == 0){//min time between pulses has passed
      mph = (3.6*float(circumference))/float(timer);//calculate miles per hour // и переделал формулу
      odo++;
      timer = 0;//reset timer
      reedCounter = maxReedCounter;//reset reedCounter
    }
    else{
      if (reedCounter > 0){//don't let reedCounter go negative
        reedCounter -= 1;//decrement reedCounter
      }
    }
  }
  else{//if reed switch is open
    if (reedCounter > 0){//don't let reedCounter go negative
      reedCounter -= 1;//decrement reedCounter
    }
  }
  if (timer > 2000){
    mph = 0;//if no new pulses from reed switch- tire is still, set mph to 0
  }
  else{
    timer += 1;//increment timer
  }
}

void displayMPH(){
  lcd.clear();//clear
  lcd.print("Speed ");
  lcd.setCursor(6, 0);
  lcd.print(mph);
  lcd.setCursor(0, 1);
  lcd.print(String(byte(odo*circumference/1000000))+"km  "+int(odo*circumference/1000)+"m");
 /* lcd.setCursor(9, 1);
  lcd.print(int(odo*circumference/1000));*/
}

void loop(){
  //print mph once a second
  displayMPH();
  delay(1000);
}

 

stels
Offline
Зарегистрирован: 03.01.2014

и еще маленький вопрос, как лучше записать данные в eeprom, что-бы не использовать лишний раз цикл записи-чтения?

в идеале бы при выключени, но как это сделать пока не знаю

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

stels пишет:

в идеале бы при выключени, но как это сделать пока не знаю

Контроль питания + ионистор.

std
Offline
Зарегистрирован: 05.01.2012

Можно сделать выключатель по кнопке, с КМОП-триггером (4043 к примеру), или уход в SLEEP_MODE_PWR_DOWN, а перед этим писать в EEPROM. Но тогда больше актуально на 8 МГц и с трёхвольтовым экраном, чтобы не греть окружающее пространство всякими step-up'ами.

stels
Offline
Зарегистрирован: 03.01.2014

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

третья версия прошивки с одометром

 

//bike speedometer
//by Amanda Ghassaei 2012
//<a href="<a href="http://www.instructables.com/id/Arduino-Bike-Speedometer/" rel="nofollow">http://www.instructables.com/id/Arduino-Bike-Speedometer/</a>" rel="nofollow"><a href="http://www.instructables.com/id/Arduino-Bike-Speedometer/" rel="nofollow">http://www.instructables.com/id/Arduino-Bike-Speedometer/</a></a>

/*
* This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 */

//outputs speed of bicycle to LCD

//calculations
//tire radius ~ 13.5 inches
//circumference = pi*2*r =~85 inches
//max speed of 35mph =~ 616inches/second
//max rps =~7.25

#define reed A0//pin connected to read switch
#include <LiquidCrystal.h>//установил обычный дисплей
LiquidCrystal lcd(12, 11, 5, 4, 3, 6);
//storage variables

int reedVal;
int odo;//количество оборотов колеса
long timer = 0;// time between one full rotation (in ms)
float mph = 0.00;
float circumference;
boolean backlight;
char vivod;

int maxReedCounter = 100;//min time (in ms) of one rotation (for debouncing)
int reedCounter;


void setup(){
  odo=0;
  reedCounter = maxReedCounter;
  circumference = 2095; //здесь явно задал окружность
  pinMode(1,OUTPUT);//tx
  pinMode(2,OUTPUT);//backlight switch
  pinMode(reed, INPUT);
  lcd.begin(16, 2);

  Serial.write(12);//clear

  // TIMER SETUP- the timer interrupt allows preceise timed measurements of the reed switch
  //for mor info about configuration of arduino timers see <a href="<a href="http://arduino.cc/playground/Code/Timer1" rel="nofollow">http://arduino.cc/playground/Code/Timer1</a>" title="<a href="http://arduino.cc/playground/Code/Timer1" rel="nofollow">http://arduino.cc/playground/Code/Timer1</a>" rel="nofollow"><a href="http://arduino.cc/playground/Code/Timer1" rel="nofollow">http://arduino.cc/playground/Code/Timer1</a></a>
  cli();//stop interrupts

  //set timer1 interrupt at 1kHz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1 = 0;
  // set timer count for 1khz increments
  OCR1A = 1999;// = (1/1000) / ((1/(16*10^6))*8) - 1
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS11 bit for 8 prescaler
  TCCR1B |= (1 << CS11);
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);

  sei();//allow interrupts
  //END TIMER SETUP

}



ISR(TIMER1_COMPA_vect) {//Interrupt at freq of 1kHz to measure reed switch
  reedVal = digitalRead(reed);//get val of A0
   
  if (reedVal){//if reed switch is closed
    if (reedCounter == 0){//min time between pulses has passed
      mph = (3.6*float(circumference))/float(timer);//calculate miles per hour // и переделал формулу
      odo++;
      timer = 0;//reset timer
      reedCounter = maxReedCounter;//reset reedCounter
    }
    else{
      if (reedCounter > 0){//don't let reedCounter go negative
        reedCounter -= 1;//decrement reedCounter
      }
    }
  }
  else{//if reed switch is open
    if (reedCounter > 0){//don't let reedCounter go negative
      reedCounter -= 1;//decrement reedCounter
    }
  }
  if (timer > 2000){
    mph = 0;//if no new pulses from reed switch- tire is still, set mph to 0
  }
  else{
    timer += 1;//increment timer
  }
}

void displayMPH(){
  lcd.clear();//clear
  lcd.print("Speed ");
  lcd.setCursor(6, 0);
  lcd.print(mph);
  lcd.setCursor(0, 1);
  lcd.print(String(byte(odo*circumference/1000000))+"km "+int(odo*(int(circumference)%1000000))/1000+"m"); //здесь одометр, отдельно км и м, вычислить именно метры элегантней способа не нашел
  lcd.setCursor(11, 1);
  lcd.print(odo);//вывод оборотов колеса для отладки
}

void loop(){
  //print mph once a second
  displayMPH();
  delay(1000);
}

 

 

adel
adel аватар
Offline
Зарегистрирован: 03.02.2015

доброго времени суток

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

в принципе код достаточно понятен, не понятно только со строки 53

053   //set timer1 interrupt at 1kHz
054   TCCR1A = 0;// set entire TCCR1A register to 0
055   TCCR1B = 0;// same for TCCR1B
056   TCNT1 = 0;
057   // set timer count for 1khz increments
058   OCR1A = 1999;// = (1/1000) / ((1/(16*10^6))*8) - 1
059   // turn on CTC mode
060   TCCR1B |= (1 << WGM12);
061   // Set CS11 bit for 8 prescaler
062   TCCR1B |= (1 << CS11);
063   // enable timer compare interrupt
064   TIMSK1 |= (1 << OCIE1A);
065  
066   sei();//allow interrupts
067

  //END TIMER SETUP

 что означает значение TCCR1A (1B); TCNT и другие сокращения?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

adel, это настройка таймера. Все непонятные сокращения -названия регистров. Общая суть  его -запускать каждую миллисекунду функцию ISR(Timer1 

adel
adel аватар
Offline
Зарегистрирован: 03.02.2015

по сути это функция? если я правильно понял

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

adel пишет:

по сути это функция? если я правильно понял

Неа, по сути, это команды.

adel
adel аватар
Offline
Зарегистрирован: 03.02.2015

опять возвращаюсь к данному скетчу

собрал код, собрал на LCD1602 - работает

пересобрал все на TFT не без помощи участников форума

пин перебил на А5 - так как А0 занят экраном - не обойти пока мне его

 

собрал - почти работает

почти заключается в том что он считает мне скорость 74 миль/час

одометр верно считает заданное растояние

 это все происходит при том что я ничего не делаю - отключаю геркон - продолжает считать

код перелопатил - считывание задано с А5 - куда копать?

может что то с пином не так?

stels
Offline
Зарегистрирован: 03.01.2014

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

adel
adel аватар
Offline
Зарегистрирован: 03.02.2015

решил вопрос
немного не правильно собрал аппаратную часть и поэтому ток постоянно шел мимо геркона параллельно

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

adel
adel аватар
Offline
Зарегистрирован: 03.02.2015

ну у меня применение не к велосипеду, а к мото

но все же у меня нет скоростей больше 150

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

какой внешний диаметр колеса?

adel
adel аватар
Offline
Зарегистрирован: 03.02.2015

21" только обод

stels
Offline
Зарегистрирован: 03.01.2014

jeka_tm пишет:

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

void loop(){
114   //print mph once a second
115   displayMPH();
116   delay(1000);
117

}

ну вот, посчитал, вывел, ждем 1000мс. За это время пару обороов может пропустить, проще запомнить значение millis и выводить, когда millis будет больше на тысячу запомненного состояния millis.

я сейчас вообще пытаюсь не использовать в программах delay, где больше трех строк кода

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а я и не говорил про delay

прерывание. на колесе магнит например. на ободе датчик холла или катушка просто. далее согласующая цепи-2 или 3 пин ардуино - дисплей

куда проще. достаточно примеры посмотреть чтобы сделать

stels
Offline
Зарегистрирован: 03.01.2014

понял теперь

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

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

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

ну сам тогда думай))

adel
adel аватар
Offline
Зарегистрирован: 03.02.2015

сижу перечитываю код более углубленно уже и тут наткнулся на такие строки


077     if (reedCounter == 0){//min time between pulses has passed
078      mph = (3.6*float(circumference))/float(timer);//calculate miles per hour // и переделал формулу

 

так вот, в первоисточнике в строке вместо 3.6 было значение 56,8

я понимаю что 3.6 это производная от 3600 / 1000, но это значение справедливо при переводе м/с в км/ч

а мы указываем значение колеса в чем? в м? или все же в мм (судя по цифре именно в мм)

а время отсчета считается в "мкс" или в "мс" или в "с"?

собственно вот такой и вопрос

VitalikNic
Offline
Зарегистрирован: 14.03.2015

Зачем юзать чужой код давайте вместе создадим свой

Для начала определимся что хотим получить ?

Я такойже програмиист ка и все, даже хуже, пока пробую все на экране 16/2

Обрисуя как я вижу велокомпьютер экран от 5110 плата
NANO 3.0 и любой контроллер литий ионной батареи. Корпус будет такойже но чуть больше

http://www.thingiverse.com/thing:188205

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

 

 

 

 

adel
adel аватар
Offline
Зарегистрирован: 03.02.2015

5110 экран мне не совсем подходит, я бы из OLED собрал себе экран, но тоже не аис

пока ищу экран подобно 5110 но которыи не бликует на солнсе и большими размерами

по поводу кода, тоже бы поучаствовал бы, но не силен в этом

VitalikNic
Offline
Зарегистрирован: 14.03.2015

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

Самое обидное в этом, что совсем не чего не понятно

//set timer1 interrupt at 1kHz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;
  // set timer count for 1khz increments
  OCR1A = 1999;// = (1/1000) / ((1/(16*10^6))*8) - 1
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS11 bit for 8 prescaler
  TCCR1B |= (1 << CS11);   
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  
  sei();//allow interrupts
  //END TIMER SETUP

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

Сдесь все боле мене понятно

ISR(TIMER1_COMPA_vect) {//Прерывание на частота 1 кГц для проверки геркона
  if(analogRead(reed) >= 680 && analogRead(reed) <= 742){//Геркон замкнут при таких показаниях
    reedVal = true;
  }else{
    reedVal = false;
  }

if (reedVal){//Геркон замкнут

if (timer > 110){
   moving = true;
}

if (reedCounter == 0){//Минимальное время между импульсами прошло
     if(moving){
      kmh = (56.8*float(circumference))/float(timer)*1.61;//километры в час
      distance += deltaD;
      distanceBuffer
      }
      reedCounter = maxReedCounter;//Сбрасываем reedCounter
      timer = 0;//Сбрасываем таймер геркона
  } else{
      if (reedCounter > 0){//Не улетаем в минуса
        reedCounter -= 1;//Уменьшаем reedCounter
      }
    }
  }else{//Если геркон не замкнут
    if (reedCounter > 0){//Не улетаем в минуса
      reedCounter -= 1;//Уменьшаем reedCounter
    }
  }
  if (timer > 2000){
    kmh = 0;//Если долго нет сигналов от геркона, мы стоим.
    moving = false;
  }else{
    timer += 1;//Увеличиваем таймер
  } 
}

Переделаю все под LCD 16/2? пока едет экран 5110

adel
adel аватар
Offline
Зарегистрирован: 03.02.2015

VitalikNic пишет:

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

ну на верху темы этот де код мусолится

 

adel
adel аватар
Offline
Зарегистрирован: 03.02.2015

а что если реализовать работу таким образом
 

запускаем ардуину и счетчик

в момент поступления сигнала от геркона извлекаем из памяти переменную "time1" к примеру (если переменная не записана то принимаем значение равное 0)

и присваиваем значению "time2" реальное значение счетчика

time2 - time1 = Vвремя оборота

вычиляем пройденный путь

вычисляем скорость

выводим на экран

значению "time1" присваемваем значение "time2" 

записываем "time1" в память

выполнили задачу запустили заново

VitalikNic
Offline
Зарегистрирован: 14.03.2015

Так дело движется..

Уже есть рабочий пример для экрана 5110 (собирал из кусков на разных форумах)

Прошел первые испытания на макете )))

Напечатал корпус.

Добавит еще осталосось.

1. Меню настройки

2. Добавить измерения напряжения на аккамуляторе Li-Io

3. Еще не разобрался полностью с часами, и  не понятна сама процедура записи и чтения в eerom  (для внешней и внутренней памяти)

4. Не совсем ясно как добавить второй датчик для педалей (нужно ли использовать второй выход для аппаратного пррывания?)

5. Как реализовать энергосбережни (тоесть когда нет срабатывания от датчико в течение допустим 30 сек то контроллер выключал всех потребителей) ?

Как то так.

 

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

VitalikNic пишет:

....

2. Добавить измерения напряжения на аккамуляторе Li-Io

.....

Привет.

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

https://youtu.be/PdtF6JnS6jo

Корпус прикольный, пока не прочитал пост думал что взяли от сгоревшего китайского велокомпа.

ovaday
Offline
Зарегистрирован: 05.05.2016

Делаю свой проект самокатокомпьютера, возникла проблема с взаимодействием геркона и спидометра, постоянно скачет 0- 16км/ч, хотя колесо раскручиваю равномерно и скорости выше 10км/ч быть попросту не может.

Геркон работает нормально, с подключением тоже проблем нет - проверял. Делаю на nokia 5110LCD, с быстродействием у нее проблем нет, проверял выводом микросекунд - обновляется достаточно оперативно.

Смотреть updateDisplay() смысла нет, скорее всего проблема в ISR(TIMER1_COMPA_vect), хотя может и loop неправильно скорректировал. Сам код:

#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
Adafruit_PCD8544 display = Adafruit_PCD8544(3,4,5,6,7);
int count=0;
#define reed A3//

//storage variables
float radius = 4;//Радиус шины в дюймах. У 26 дюймовой шины, около 13.5 (магия)

boolean reedVal;
long timer = 0;//Время между оборотами в миллисекундах
float kmh = 0.00;//Скорость в км/ч
int kmhcel = 0;
int kmhost = 0;
float circumference;

float distance = 0;//Дистанция поездки в метрах

long totalDistance = 0;//Дистанция всех поездок в метрах
long totalTime = 0;//Время всех поездок в минутах
float distanceBuffer = 0;//Несохранённая дистанция поездки в метрах
long timeBuffer = 0;//Несохранённое время поездки в секундах

float deltaD;//Проезжаем за оборот в метрах
boolean moving = false; //флаг - едем или нет
long times = 5;//Время езды в секундах
unsigned long prevtimes = 0;
int timem=0;
int hour = 0;
long lastTime = millis();
long cureed = 0;
long prevreed = 0;
long duration = 0;


int maxReedCounter = 70;//Минимальное время в миллисекундах на оборот
int reedCounter;


void setup(void)
{
  pinMode(10, OUTPUT);//Магия для карты памяти
  
  reedCounter = maxReedCounter;
  deltaD = 2*3.415926535*radius*0.025;//Проезжается за один оборот колеса в метрах
  circumference = 2*3.14*radius;//То же самое, но с меньшей точностью (для измерения скорости) и не в метрах
  pinMode(A0, INPUT);
  
  // TIMER SETUP- the timer interrupt allows preceise timed measurements of the reed switch
  //for mor info about configuration of arduino timers see http://arduino.cc/playground/Code/Timer1
  cli();//stop interrupts

  //set timer1 interrupt at 1kHz
  TCCR1A = 0;// set entire TCCR1A register to 0
  TCCR1B = 0;// same for TCCR1B
  TCNT1  = 0;
  // set timer count for 1khz increments
  OCR1A = 1999;// = (1/1000) / ((1/(16*10^6))*8) - 1
  // turn on CTC mode
  TCCR1B |= (1 << WGM12);
  // Set CS11 bit for 8 prescaler
  TCCR1B |= (1 << CS11);   
  // enable timer compare interrupt
  TIMSK1 |= (1 << OCIE1A);
  
  sei();//allow interrupts
  //END TIMER SETUP
  display.begin();
  display.display(); // show splashscreen
  display.clearDisplay();
}


ISR(TIMER1_COMPA_vect) {//Прерывание на частота 1 кГц для проверки геркона
  if(analogRead(reed) >= 400 && analogRead(reed) <= 1000){//Геркон замкнут при таких показаниях
    reedVal = true;
  }else{
    reedVal = false;
  }

if (reedVal){//Геркон замкнут

if (timer > 100){
   moving = true;
}

if (reedCounter == 0){//Минимальное время между импульсами прошло
     if(moving){
      kmh = (56.8*float(circumference))/float(timer)*1.61;//километры в час
      distance += deltaD;
      distanceBuffer;
      }
      reedCounter = maxReedCounter;//Сбрасываем reedCounter
      timer = 0;//Сбрасываем таймер геркона
  } else{
      if (reedCounter > 0){//Не улетаем в минуса
        reedCounter -= 1;//Уменьшаем reedCounter
      }
    }
  }else{//Если геркон не замкнут
    if (reedCounter > 0){//Не улетаем в минуса
      reedCounter -= 1;//Уменьшаем reedCounter
    }
  }
  if (timer > 3000){
    kmh = 0;//Если долго нет сигналов от геркона, мы стоим.
    moving = false;
  }else{
    timer += 1;//Увеличиваем таймер
  } 
}

void updateDisplay(){
  display.setContrast(50);
  display.clearDisplay();   // clears the screen and buffer

unsigned long cutimes = millis();
if (cutimes-prevtimes>=1000){times++;prevtimes=cutimes;}
if (times>=60){ timem++; times=0;};
if (timem>=60){ hour++; timem=0;};


  // text display tests
  display.setTextSize(0);
    for (uint8_t i=1; i < 16; i++) {
    display.setCursor(0,i*3-3);
    display.write(22);
  }   
  for (uint16_t i=1; i < 15; i++) {
    display.setCursor(77,i*3);
    display.write(22);
  }   
  for (uint16_t i=0; i < 82; i++) {
   display.drawPixel(i, 47, BLACK);
  }
  display.setCursor(0,-1);
  display.write(29); 
  display.setCursor(77,0);
  display.write(15); 
  display.setCursor(52,15);
  display.print("km/h"); 
  if (timem<10){display.setCursor(51,25); display.print("0"); display.setCursor(57,25);}else{display.setCursor(51,25);};
  display.print(timem);
  display.setCursor(61,25);
  display.print(":");
  if (times<10){display.setCursor(65,25); display.print("0"); display.setCursor(71,25);}else{display.setCursor(65,25);};
  display.print(times);
  display.setCursor(47,25);
  display.print(":");
  display.setCursor(43,25);
  display.print(hour);
    display.setTextSize(4);
  display.setTextColor(BLACK);
  kmhcel = (kmh*100)/100;
  kmhost = ((kmh*1000)/1000)*10;
  if (kmh<10){
    display.setCursor(25,0);
  display.print(kmhcel);
  display.setTextSize(2);
   display.print(".");
   display.print(kmhost%10);
  } else{
    display.setCursor(5,0);
  display.print(kmhcel);
  display.setTextSize(2);
   display.print(".");
   display.print(kmhost%10);};
  display.setTextSize(1);
  display.setCursor(8,35);
  display.print("DST:");
  display.setCursor(32,35);
  if (distance >= 1000){
    display.print(distance/1000);
    display.setCursor(63,35);
    display.print("km");
  } else{
    display.print(distance);
  display.setCursor(70,35);
  display.print("m");
  };
  display.display();
}


void loop(void)
{
  if (reedVal){//Геркон замкнут
if (timer <= 110){
  moving = false;//Мы остановились, замкнув геркон
}else{
   moving = true;
}
  }
  updateDisplay();
//  saveData();
  
  if (moving){
  int d = (int)((millis()-lastTime));}
  
  lastTime = millis();
}

Все идет в замкнутом постоянном цикле, без всяких delay, может в этом и есть проблема?

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

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

 

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

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

Я бы не стал искать ошибки, а написал снова и по-уму. У меня фантазии не хватило понять глубокий смысл вычислений в строках 154-155. Почему прерывание от таймера, а не от геркона, почему геркон на аналоговом входе, а не на цифровом, почему обновление экрана в каждом цикле, а не раз в секунду, зачем вычисления с плавающей точкой каждую миллисекунду и т.д и т.п????

Ты бы стал искать ошибки в этом опусе?

"Смиеца суслег в ниуютнай норке.
На спинко апракинулсо жучог.
Хахочит йожиг, носецо па горке,
Сафсем с котушег съехал дурачог!
Литайут птичке странныме кругаме,
И ржот кобылко з пенкай иза рта.
Сороконожко дрыгаит нагаме.
Ац смеха слёзке льюцо у крата.
Ржут белачке и падают з диревьеф.
Сава забавно ухает ф дупле.
Хахочит грач да выпаденья перьеф.
И мушко са свирчком нависиле.
Кузнечеги смиююцо в трафке где-то,
Мышонаг, змейко, ящерко и тля...
Стояло жаркое, засушливое лето.
Гарели сцуко канапляные паля..."

Олег М.
Олег М. аватар
Offline
Зарегистрирован: 22.11.2015

Andy пишет:

Ты бы стал искать ошибки в этом опусе?

"Смиеца суслег в ниуютнай норке.
На спинко апракинулсо жучог.
.....
Гарели сцуко канапляные паля..."


Сам сочинил или как?
Если сам, то где траву такую забористую берешь?
Пишит исчо!
Или пруфлинк в студию!

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

Первая строка и яндекс в помощь. Здесь другие перлы с комментариями.