Велосипедный спидометр 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

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

74LS00
Offline
Зарегистрирован: 11.04.2016
Читаю по ссылке и там вообще кода нет, один хэловорд который зачемто автор приделал.
В оригинале тоже куча фуфла и гдето в днище скеч похожий на нужный.
 
Я так понял принцип измерения скорости не отличается, все пара десятков подобных кодов одинаковые. Отличие в этом это то что использована не ардуиновская функция, а чистый сишный код. В таком случае сомневаюсь что это может работать.
Я так понял что работать это должно если delay будет очень большим, около 700, больше чем частота импульсов, иначе показания обнуляются, в общем велосипед на такой скорости точно не поедет.
 
ded.izya.dnepr
Offline
Зарегистрирован: 03.12.2019

а некто не пробовал это выводить на OLED экранчик выводить??????

Morroc
Offline
Зарегистрирован: 24.10.2016

OLED днем хреново аидно, хороший контрастный LCD лучше.

ded.izya.dnepr
Offline
Зарегистрирован: 03.12.2019

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

74LS00
Offline
Зарегистрирован: 11.04.2016

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

 

Вы вообще о каких OLED говорите, это заказная технология, таких деталей не продают, на них делают только заводскую технику.

Цветных OLED я вообще никогда не видел, их просто не существует. Из нецветных видел модули 1602, которые сами по себе не маленькие и полностью повторяют форм фактор ЖК модулей которые ставились во многую технику лет 20 назад, у них же были и ВЛИ варианты которые сейчас по 50уе тоже можно найти. Так вот про эти 1602 OLED поговаривают что они шумят неслабо, возможно под них просто надо фильтрацию питания отдельную чтоб не мешала основной схеме.
Но я бы предпочёл дисплей 12864 на котором и собираю, есть ещё большие с 800х600, но там цены и вовсе на сотни баксов. Модульных OLED больше 1602 я не видел, возможно чтото есть.

Второй вариант OLED это маленькие модульки около дюйма, цена на которые просто космическая, а рабочий экран пара квадратных сантиметров, это не говоря о мерцании. На таком сделать спидометр можно, 2 цифры туда влезут, чтото большее там не рассмотреть. 

Подобное обсуждение есть тут https://radiokot.ru/forum/viewtopic.php?f=43&t=174552

ded.izya.dnepr
Offline
Зарегистрирован: 03.12.2019

https://arduino.ua/prod1263-oled-displei-modyl-belii
вот на таком у меня собран указометер и стоит он у меня в коробочке на приборной панели не чем не затемненый и не затеняемый. 
Он некуя не кушает и аккумулятора 18650 будет хватать на долго.
Вот в этой статье описано хорошо по этому дисплею https://mysku.ru/blog/china-stores/37346.html

74LS00
Offline
Зарегистрирован: 11.04.2016

Так вот и я про то. Экран 1 на 2см, 2см^2, размер модуля 7.3см^2, это более чем в 3.5 раза больше чем рабочая часть, а вся эта махина будет занимать площадь. Вообще напоминает статью "велоодометр" из старого журнала, только там от наручных часов экран был.

Я бы не сказал что яркий, а вот мерцание там конкретное. Покупался за 400р на али года 4 назад, тогда это была новинка и пару лет их вообще у китайцев не было.

В общем самый дерьмовый экран по всем параметрам, не знаю какой в них вообще смысл.

100мка=0.1ма
128*64=8192
8192*0.1=819.2ма
ну допустим в среднем 400ма.
Самый ёмкий 18650 3.2ач.
Итого 3.2/0.4=8ч вашей батарейки хватит надолго ровно на один рабочий день.
 
Ну хотя если вы катаетесь по полчаса в день и приколхозите схему которая будет его гасить когда вел стоит, то на недельку хватит.
Не забудьте купить крепление чтоб удобно снимать было всё это дело и носить на зарядку, ну хотя вероятно вел вы в хату таскаете к розетке.
 
Интересно этот ваш обзорщик каким местом думал когда надпись на экране фоткал. Надеюсь он не забыл под лупой посчитать сколько там пикселей у этой писульки.
Для правильного замера надо сделать замеры без текста, с 1 пикселем и со всеми пикселями, и тогда считать сколько жрёт контролер и сколько пиксели
dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

74LS00, про потребление из муськи вычитали? .  Лень искать точные данные, предполагаю что он не больше 20мА кушает :)

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

dimax пишет:

74LS00, про потребление из муськи вычитали? .  Лень искать точные данные, предполагаю что он не больше 20мА кушает :)

dimax, я измерял - реально чуть более 5 мА

74LS00, большинство остальных аргументов - про площадь, про мерцание - тоже из пальца высосаны.

74LS00
Offline
Зарегистрирован: 11.04.2016

Я вот прям щяс на него смотрю и чёт мерцание никуда не делось.

Ну если вы любитель рамочных экранов, то вы её не видите.

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

ded.izya.dnepr
Offline
Зарегистрирован: 03.12.2019

myOLED.setBrightness(255); // увеличиваем подсетку

74LS00
Offline
Зарегистрирован: 11.04.2016

а теперь кто скажет как в этом дряннолм движке отписаца от темы.

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

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

74LS00 пишет:

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

Главаная форума ->  мой профиль - > Изменить - и там внизу есть две настройки уведомлений.

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

ded.izya.dnepr
Offline
Зарегистрирован: 03.12.2019

в письме на почте есть такое:
 
"Отключить уведомления о комментариях к 


этой теме можно перейдя по следующей 

ссылке - 

http://arduino.ru/comment_notify/disable/a4bd434cb92998022bb959e99767d0b99d. "

перешел и будет тебе счастье

Уведомления о новых комментариях к этому материалу для вас отключены. Спасибо.

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

ded.izya.dnepr пишет:

в письме на почте есть такое:
 
"Отключить уведомления о комментариях к 


этой теме можно перейдя по следующей 

ссылке - 

http://arduino.ru/comment_notify/disable/a4bd434cb92998022bb959e99767d0b99d. "

перешел и будет тебе счастье

Уведомления о новых комментариях к этому материалу для вас отключены. Спасибо.

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

74LS00
Offline
Зарегистрирован: 11.04.2016

Да я уже понял надо забанить к чёрту этот сайт на стороне почтового сервиса, других вариантов нет

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

74LS00 пишет:

Да я уже понял надо забанить к чёрту этот сайт на стороне почтового сервиса, других вариантов нет

я понажимал эти ссылки в каждом приходящем письме в течении, примерно, двух-трех недель - и все, уведомления пропали :)