Измерение каденса и скорости

sezam
Offline
Зарегистрирован: 15.11.2015

Добрый день, форумчане-ардуинцы!

Это моя первая статья, так-что не пинайте :)

Пару месяцев назад приобрел велостанок для занятий в зимнее время и решил на праздниках добавить возможность мониторинга основных показателей с использованием герконов: скорость и расстояние, каденс, пульс, с возможностью сохранения результатов на флешку для просмотра на ПК.

Тем уже было много на этом форуме и многие части кода покажутся знакомыми.

Появилась проблема в рассинхронизации показателей.

Первым делом сделал расчёт скорости и пройденного расстояния на таймере. Вроде бы всё стабильно работает.

Затем решил добавить расчёт каденса с использованием одного из прерываний (вывод D3). Сначала появился дребезг по 5-6 прерываний за одно срабатывание геркона. Заменил схему подключения (было - плюс идет на геркон, затем через сопротивление 10К спускается на землю, средняя точка идет на ардуку) на новую (плюс через сопротивление идет на геркон и спускается на землю, средняя точка - на ардуинку).

Геркон для скорости подключен по схеме: плюс идет на геркон, затем через сопротивление 10К спускается на землю, средняя точка идет на ардуку.

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

Использую Arduino Pro Mini.

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

//bike speedometer
//by Amanda Ghassaei 2012
//<a href="<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>" rel="nofollow"><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></a>

//outputs speed of bicycle to LCD


#define reed A0//pin connected to read switch

int reedVal;
int cadVal;
int odo;//количество оборотов колеса

int caden = 1; // пин D2 для каденса
volatile int count = 0; // счетчик оборотов (каденс)
int lastCount = 0;  // переменная хранящая последнее значение счётчика оборотов
int count4period = 0;  // количество оборотов совершонное за период
int int_m = 0; // переменная времени цикла
int count_n = 0;

float odo_m; // расстояние в метрах для одометра
long timer = 0;// time between one full rotation (in ms)
float mph = 0.00;
float circumference;

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

// ниже переменные чисто для дебага и доп инфо в сериал порте:
long time;  // переменная которой присваивается значение внутреннего счётчика времени
long lastTime;  // переменная хранящая последнее значение счётчика времени
int period;  // период времени отработки

void setup(){
  odo=0;
  reedCounter = maxReedCounter;
  circumference = 2260; //здесь явно задал окружность (мм)
  pinMode(reed, INPUT);
  pinMode(caden, INPUT);

  // 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="<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>" title="<a href="<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>" rel="nofollow"><a href="<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></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
  Serial.begin(9600);

  attachInterrupt(caden, cadens, FALLING);
}

void cadens () {
  count = count+1;
  //Serial.println("+");
/*  
  //if(digitalRead(2)==HIGH) { //при нажатии кнопки
  //Если от предыдущего нажатия прошло больше 100 миллисекунд
  if (millis() - previousMillis >= 100) {
    //Запоминается время первого срабатывания
    previousMillis = millis();
  }
  if (led==oldled) { //происходит проверка того, что состояние кнопки не изменилось
    led=!led;
  }
*/

  
}


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(){
  Serial.print("Speed ");
  Serial.print(mph);
  Serial.print("  S = ");
  odo_m = float((odo)*circumference)/1000.0; // пройденное расстояние в метрах
  Serial.println(String((int(odo_m) / 1000))+"km "+(int(odo_m) % 1000)+"m"); //здесь одометр, отдельно км и м, вычислить именно метры элегантней способа не нашел
}

void loop(){
  //print mph once a second
  displayMPH();
  // каденс считается раз в 5 секунд с выдачей результата о нахождении в определенных зонах
  if (int_m == 5) {

    //time = millis();  // после дебага удалить или закоментить 
    //period = time - lastTime;  // после дебага удалить или закоментить 
 
    //Serial.println(period);  // после дебага удалить или закоментить
    

    
    count4period = (count - lastCount)/4;
    //Serial.println(count4period);  // после дебага удалить или закоментить

    
    count_n = count4period*4;
    if (count4period >= 6 && count4period <= 9) {  // частота педалирования за 5 секунд -- 6=72 9=108 == 60/5=12 6=72 / 7=84 / 8=96 / 9=108
    //digitalWrite(ledGreen, HIGH);
    //digitalWrite(ledRed, LOW);
      Serial.println("  Green (72-108 об/мин): "+String(count4period)+" = "+String(count_n));
    } else {
        if(count4period > 9){
        //digitalWrite(ledGreen, LOW);
        //digitalWrite(ledRed, HIGH);
          Serial.println("  Red (> 108 об/мин): "+String(count4period)+" = "+String(count_n));
        } else {
          //digitalWrite(ledGreen, LOW);
          //digitalWrite(ledRed, LOW);
          Serial.println("  Low (< 72 об/мин): "+String(count4period)+" = "+String(count_n));
        }
    }
    //lastTime = time;  // после дебага удалить или закоментить
    //lastCount = count;  
    lastCount = count;
    int_m = 0;
  }
  delay(1000);
  int_m = int_m + 1;
}

 

 

 

Green
Offline
Зарегистрирован: 01.10.2015

sezam, а разве вы не знаете, что станок это как резиновая женщина.) И толку никакого!
С другой стороны, китайский измеритель скорости и каденса стоит копейки, не правда ли?