Тахометр на оптике HELP!!!!!

Dark113
Offline
Зарегистрирован: 08.11.2017

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

int coil = 13;
int ledmass[13]={0,1,2,3,4,5,6,7,8,9,10,11,12};

 
void setup() {
  pinMode(coil, INPUT);
  digitalWrite(coil, HIGH);
for (int i=0; i<13; i++) {
 pinMode(ledmass[i], OUTPUT);}
  
    for (int i=0; i<13; i++){
      digitalWrite(ledmass[i],HIGH);
      delay(300);}
    
   for (int i=0; i<13; i++){
      digitalWrite(ledmass[i],LOW);}
}


void loop() {

int PRM = 0;
int a=0;
long time;



  if (digitalRead(coil) == LOW && a == 0)    
  {time=millis();   } 
  if (digitalRead(coil) == HIGH )
  {a=1;}
   if (digitalRead(coil) == LOW && a == 1)   
{time = millis()-time;  
  PRM = 60000/time;
   a=0;}

   unsigned char i = 13;
   int level = 7000;
   do{
    if (PRM>level){digitalWrite(ledmass[i],HIGH);}
    else          {digitalWrite(ledmass[i],LOW);}
    level=level-500;
    i=i-1;
    a=0;}
    while(i>=0);
}

 

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

А надо как?

Dark113
Offline
Зарегистрирован: 08.11.2017

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

5N62V
Offline
Зарегистрирован: 25.02.2016

Dark113 пишет:

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

Так может у Вас всегда выполняется условие (PRM>level)

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

Dark113
Offline
Зарегистрирован: 08.11.2017

 

[/quote]

Так может у Вас всегда выполняется условие (PRM>level)

[/quote]

Возможно.Каким образом это можно исправить? 

Dark113
Offline
Зарегистрирован: 08.11.2017

5N62V пишет:

 Кстати, я делал проект тахометра на арду, работает.

Можете поделится наработками?

5N62V
Offline
Зарегистрирован: 25.02.2016

так промониторьте состояние переменной PRM и level

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Этот код может Вам показать только цену на прошлогодняй овёс, но никак не обороты.

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

В общем, выбирайте, у Вас четыре варианта:

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

2. побираться по форумум "дайте наработки" - время как повезёт, а в случае если в наработке понадобится "букву 'а' на 'б' заменить", снова идти побираться.

3. заказать за деньги.

4. бросить это дело.

Других вариантов нет. Есть только комбинации этих.

5N62V
Offline
Зарегистрирован: 25.02.2016

Dark113 пишет:

Можете поделится наработками?

Могу. Если кто подскажет как сделать лучше - буду признателен. Косяк такого решения - дискретность в 60 рпм. Обусловлено временем измерения  кол-ва приходящих импульсов  - 1сек .

устройство измеряет рпм и температуру охлаждающей жидкости, и по запросу о центрального микропроцессора скидывает инфу по i2c, если кому вдруг не ясно :)

#include <Wire.h>
#define SLAVE_ADDR 25

volatile unsigned long pulses = 0;      

int rpm = -1;
int temp = -1;

unsigned long time;         

int ledPin = 7;           

bool led = LOW;
    byte buffer[4];


void setup()
{
  Serial.begin(9600);  
  pinMode  (4, OUTPUT);
  digitalWrite(4, HIGH);

  Wire.begin(SLAVE_ADDR);
  Wire.onReceive(slaveRX);
  Wire.onRequest(slaveTX);
  attachInterrupt(0, rpm_event, RISING); 
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  time = millis(); 
  pulses=0; 
do{}while(millis()-time<1000); // время измерения


 rpm = 60 * pulses;
    temp = analogRead(A0);
 
    temp = map(temp, 0, 760, 150, 20);
  buffer[0] = (rpm) >> 8;
  buffer[1] = (rpm) & 0xff;
  buffer[2] = (temp) >> 8;
  buffer[3] = (temp) & 0xff;
 Serial.print(rpm); Serial.print(" ");   Serial.println(temp);
  }

void rpm_event()
{
  pulses++;
  led = !led;
  digitalWrite(ledPin, led);
}

void slaveTX() {  Wire.write(buffer, 4);}


void slaveRX(int bytes) {  }

 

Andrey12
Andrey12 аватар
Offline
Зарегистрирован: 26.12.2014

Мне одному кажется что 

do{}while(millis()-time<1000); = delay(1000);

Тогда лучше уж delay(1000) ставить, код читабельнее. Хотя хозяин барин!

ЕвгенийП тема переполнения миллис вечна! У вас в примерах я такого ирспользование не видел. :-)

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

Andrey12 пишет:

Мне одному кажется что 

do{}while(millis()-time<1000); = delay(1000);

Тогда лучше уж delay(1000) ставить, код читабельнее. Хотя хозяин барин!

ЕвгенийП тема переполнения миллис вечна! У вас в примерах я такого ирспользование не видел. :-)

это не тема переполнения, это как заменить delay на код с миллис :) - просто вставить пустые циклв на нужное число миллисекунд :) было уже такое и не раз....

5N62V
Offline
Зарегистрирован: 25.02.2016

Andrey12 пишет:

Тогда лучше уж delay(1000) ставить, код читабельнее. Хотя хозяин барин!

Не поверите: в коде стояло delay(1000), убрал чтоб не клевали :) Вечная, вечная. У Вас ведь двигатель как правило не менее пары недель включенным работает. :)

 

ПС. в плане улучшения предложенного мной решения измерения рпм: ежу понятно, что ставь измерение 2сек, и вот тебе дискретность не 60, а 30. Но тут важен баланс между апрейдрейт, и дискретностью. Реже раз в 1 сек обновлять данные рпм не есьт гуд, конкретно в моем случае.

evgta
Offline
Зарегистрирован: 02.09.2016
word pwmA = 320; // 50% duty (0-320 = 0-100% duty cycle)
word pwmB = 100; // 90% duty (0-320 = 0-100% duty cycle)
int oborpin = 2;
int yyy = 0;
unsigned long obor1;
unsigned long obor2;
unsigned long obor3;
unsigned long obor4;
unsigned long obor5;



unsigned long xxx1;
unsigned long xxx2;
unsigned long xxx3;


void setup() {
  Serial.begin(9600);
  pinMode(oborpin, INPUT);
  pinMode(9, OUTPUT);  //pwmA
  pinMode(10, OUTPUT); //pwmB
attachInterrupt(0, prer, RISING );


aaaa();
}

void loop() {
xxx2=millis()-xxx1;
if (xxx2>500) {
  obor4=30000000/obor3;
  
  
 if (obor4<2500){pwmA=pwmA+10; if(pwmA<20){pwmA=20;} if(pwmA>320){pwmA=320;} aaaa();} 
 if (obor4>2550){pwmA=pwmA-10; if(pwmA<20){pwmA=20;} if(pwmA>320){pwmA=320;} aaaa();} 
  
  Serial.println(obor4);
  Serial.println(pwmA);
  
  xxx1=millis();
  } 








}

void prer(){
obor2=micros()-obor1;
if (obor2>30){obor3=obor2;}
obor1=micros();

  
}

void aaaa() {
detachInterrupt(0);

  TCCR1A = 0;            //clear timer registers
  TCCR1B = 0;
  TCNT1 = 0;

  TCCR1B |= _BV(CS10);   //no prescaler
  ICR1 = 320;            //PWM mode counts up 320 then down 320 counts (25kHz)

  OCR1A = pwmA;          //0-320 = 0-100% duty cycle
  TCCR1A |= _BV(COM1A1); //output A clear rising/set falling

  OCR1B = pwmB;          //0-320 = 0-100% duty cycle
  TCCR1A |= _BV(COM1B1); //output B clear rising/set falling

  TCCR1B |= _BV(WGM13);  //PWM mode with ICR1 Mode 10
  TCCR1A |= _BV(WGM11);  //WGM13:WGM10 set 1010
  attachInterrupt(0, prer, RISING );
}

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

5N62V
Offline
Зарегистрирован: 25.02.2016

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