Тахометр на оптике HELP!!!!!
- Войдите на сайт для отправки комментариев
Вс, 12/11/2017 - 11:52
Здравствуйте, уважаемые форумчане!Нуждаюсь в помощи!Имеется задумка создания тахометра.Принцип заключается в считывании количества импульсов с оптопары и выводе на светодиодную шкалу.Начало было положено!Начал с програмной части.Имеется скетч, но при совершении оборота диском загораются все светодиоды.Не могу понять в чём причина!В програмировании новичок по этому не судите строго.Буду благодарен за ваши отзывы и предложения!
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);
}
А надо как?
Нужно, чтобы по мере возростания оборотов загорались соответствующие светодиоды.Например: при 1500 об/мин загорались первй, второй и третий светодиоды.
Нужно, чтобы по мере возростания оборотов загорались соответствующие светодиоды.Например: при 1500 об/мин загорались первй, второй и третий светодиоды.
Так может у Вас всегда выполняется условие (PRM>level)
Кстати, я делал проект тахометра на арду, работает. Но я подсчитывал импульсы с фототранзистора по прерыванию. Как Вы собираетесь синхронизировать основной луп с приходом импульсов в широком диапазоне рпм, мне - не понятно.
[/quote]
Так может у Вас всегда выполняется условие (PRM>level)
[/quote]
Возможно.Каким образом это можно исправить?
Кстати, я делал проект тахометра на арду, работает.
Можете поделится наработками?
так промониторьте состояние переменной PRM и level
Этот код может Вам показать только цену на прошлогодняй овёс, но никак не обороты.
Сразу отвечаю на вопрос "как исправить?" - никак, выбросить и писать заново, для начала прочитав какую-ниюбудь книжку по языку программирования.
В общем, выбирайте, у Вас четыре варианта:
1. начать изучать программирование и, по ходу изучения, переписать скетч - время порядка полугода, в итоге сделаете и получите новые знания.
2. побираться по форумум "дайте наработки" - время как повезёт, а в случае если в наработке понадобится "букву 'а' на 'б' заменить", снова идти побираться.
3. заказать за деньги.
4. бросить это дело.
Других вариантов нет. Есть только комбинации этих.
Можете поделится наработками?
Могу. Если кто подскажет как сделать лучше - буду признателен. Косяк такого решения - дискретность в 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) { }Мне одному кажется что
do{}while(millis()-time<1000); = delay(1000);Тогда лучше уж delay(1000) ставить, код читабельнее. Хотя хозяин барин!
ЕвгенийП тема переполнения миллис вечна! У вас в примерах я такого ирспользование не видел. :-)
Мне одному кажется что
do{}while(millis()-time<1000); = delay(1000);Тогда лучше уж delay(1000) ставить, код читабельнее. Хотя хозяин барин!
ЕвгенийП тема переполнения миллис вечна! У вас в примерах я такого ирспользование не видел. :-)
это не тема переполнения, это как заменить delay на код с миллис :) - просто вставить пустые циклв на нужное число миллисекунд :) было уже такое и не раз....
Тогда лучше уж delay(1000) ставить, код читабельнее. Хотя хозяин барин!
ПС. в плане улучшения предложенного мной решения измерения рпм: ежу понятно, что ставь измерение 2сек, и вот тебе дискретность не 60, а 30. Но тут важен баланс между апрейдрейт, и дискретностью. Реже раз в 1 сек обновлять данные рпм не есьт гуд, конкретно в моем случае.
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 ); }чтобы было побыстрей можно не кол-во импульсов за время считать, а время между двумя импульсами
ну наверное да. Тогда надо точно вычислить время исполняемого кода, чтобы вычесть из измерения. Ну и обязательно применить таймаут, чтоб не зависнуть.