Изменения цвета ргб от частоты.

Belcik
Offline
Зарегистрирован: 28.02.2017

Всем здравия. Заранее извиняюсь, если сей вопрос уже был на данном форуме. Глазами пробежался, не узрел.

Суть в чем: вращается пропеллер с магнитом, датчик холла считывает, передает на плату, на экран компьютера выводится частота вращения. - Это был стандартный код, найденый мною в интернете.

// read RPM

volatile int rpmcount = 0;//see http://arduino.cc/en/Reference/Volatile
int rpm = 0;
unsigned long lastmillis = 0;

void setup(){
Serial.begin(9600);
attachInterrupt(0, rpm_fan, FALLING);//interrupt cero (0) is on pin two(2).
}

void loop(){

if (millis() - lastmillis == 1000){ /*Uptade every one second, this will be equal to reading frecuency (Hz).*/

detachInterrupt(0); //Disable interrupt when calculating

rpm = rpmcount * 60; /* Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use rpmcount * 30.*/

Serial.print("RPM =\t"); //print the word "RPM" and tab.
Serial.print(rpm); // print the rpm value.
Serial.print("\t Hz=\t"); //print the word "Hz".
Serial.println(rpmcount); /*print revolutions per second or Hz. And print new line or enter.*/

rpmcount = 0; // Restart the RPM counter
lastmillis = millis(); // Uptade lasmillis
attachInterrupt(0, rpm_fan, FALLING); //enable interrupt
}
}

void rpm_fan(){ /* this code will be executed every time the interrupt 0 (pin2) gets low.*/
rpmcount++;
}

Что пытаюсь сделать я: три разных выхода с платы на три лапки ргб-диода, и что бы в разном диапазоне частот горели разные цвета. Диапазоны пока в качестве эксперемента 1-9; 10-16; 17-29 об/сек.

// read RPM

volatile int rpmcount = 0;//see http://arduino.cc/en/Reference/Volatile
int rpm = 0;
unsigned long lastmillis = 0;

void setup(){
Serial.begin(9600);
attachInterrupt(0, rpm_fan, FALLING);//interrupt cero (0) is on pin two(2).
}

void loop(){

if (millis() - lastmillis == 1000){ /*Uptade every one second, this will be equal to reading frecuency (Hz).*/

detachInterrupt(0); //Disable interrupt when calculating

rpm = rpmcount * 60; /* Convert frecuency to RPM, note: this works for one interruption per full rotation. For two interrups per full rotation use rpmcount * 30.*/

Serial.print("RPM =\t"); //print the word "RPM" and tab.
Serial.print(rpm); // print the rpm value.
Serial.print("\t Hz=\t"); //print the word "Hz".
Serial.println(rpmcount); /*print revolutions per second or Hz. And print new line or enter.*/

rpmcount = 0; // Restart the RPM counter
lastmillis = millis(); // Uptade lasmillis
attachInterrupt(0, rpm_fan, FALLING); //enable interrupt
}
int led1 = 8;
int led2 = 9;
int led3 = 10;
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);

if ( rpmcount>1&&rpmcount<9 )
{
  digitalWrite(led1,HIGH); 
  digitalWrite(led2,LOW); 
  digitalWrite(led3,LOW);
}
else if ( rpmcount>10&&rpmcount<16 )
{
  digitalWrite(led1,LOW); 
  digitalWrite(led2,HIGH); 
  digitalWrite(led3,LOW);
}
else if ( rpmcount>17&&rpmcount<29 )
{
  digitalWrite(led1,LOW); 
  digitalWrite(led2,LOW); 
  digitalWrite(led3,HIGH);
}
else 
{
  digitalWrite(led1,LOW); 
  digitalWrite(led2,LOW); 
  digitalWrite(led3,LOW);
  }
}
}

void rpm_fan(){ /* this code will be executed every time the interrupt 0 (pin2) gets low.*/
rpmcount++;
}

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

Кто подскажет, в чем моя ошибка?

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

В том. что Вы не разобрались в найденном в сети коде (кстати, я не понял каким именно ГОСТом он утверждён в качестве "стандартного"?).

В строках 36, 42 и 48 Вы сравниваете rpmcount с Вашими границами. А кто Вам собственно сказал, что количество оборотов находится именно в переменной rpmcount? Вот с чего Вы это взяли? В комментариях к коду написано совсем другое. В rpmcount находится сырое количество прерываний, а количество оборотов (частота вращения) живёт в другой переменной.

Разберитесь в какой переменной у Вас частота вращения и используйте эту переменную.

Ну, про мелочи, типа строк 29-34 зачем-то всунутых в loop я молчу. Само по себе диковато, но работать должно и так.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Евгений, как всегда, пытается заставить шевелить извилинами топикстартера и только при обнаружении малейшего движения поделится своими гениальными соображениями ))

29-34, насколько я понимаю, хотя мне до Евгения далеко и безнадёжно - им место в начале программы, до Setup().

Насчет дикости, это, скорее всего, в огород кучи "if"-ов, которые вполне можно заменить на switch - case.

Насчет переменных: не скажу, потому что не пойму принципа работы операторов в цикле Void loop() пока что.))))

 

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

В защиту "swith-case": когда мучался с обработкой IR-кодов с пульта (те же условия перехода по конкретному коду или диапазрну что и здесь, собственно), if-ы глючили - конкретно. А вот swith-case - то что доктор прописал.

Belcik
Offline
Зарегистрирован: 28.02.2017

Пересмотрел уже тысячу раз. Вроде бы именно rpmcount выдает частоту вращения в сек. Так и не понял, какая ещё переменная может за это отвечать. У меня же там всего 2 переменных, судя по коментариям кода rpmcount отвечает за об/сек, а rpm за об/мин. Тем более rpmcount зажигает диод нужным цветом, при нужном диапазоне. Проблема в том, что не тушит предыдущий цвет при переходе на другой диапазон.

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

arDubino
Offline
Зарегистрирован: 12.01.2017

ну избыточность в ифа точно есть.

зачем писать больше 1 и меньше 9. если и так понятно что будет меньше 9.и

в остальных условиях также. надо оставить просто меньше 9 меньше 16 меньше 29 и больше 29 и все.

arDubino
Offline
Зарегистрирован: 12.01.2017

аха у него еще и значения 9 10 16 17 идут в иначе может ради этого разве что

Belcik
Offline
Зарегистрирован: 28.02.2017

больше 1 и меньше 9 - чтоб на нуле не горел.

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

Belcik пишет:

Пересмотрел уже тысячу раз. Вроде бы именно rpmcount выдает частоту вращения в сек. Так и не понял, какая ещё переменная может за это отвечать. 

Смотрите в тысячу первый. Что, по-Вашему означает комментарий "Convert frecuency to RPM" в строке 18?

Belcik
Offline
Зарегистрирован: 28.02.2017

Перевод частоты из герц в "об/мин" 

 

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

Так, я уже эту мысль писал, но, видимо, как-то непонятно написал. Читайте внимательно

Что хранится в rpmcount? Там хранится количество пойманных прерываний. Это СЧЁТЧИК  Оно накапливается в течение секунды и только тогда (раз в секунду) становится частотой. В строках 14-28, ОДИН раз в секунду, накопленное число обрабатывается и счётчик сбрасывается в ноль (строка 25).

Таким образом, rpmcount каждую секунду сбрасывается в ноль и начинает новое суммирование количества прерываний. По истечени секунды там оказывается частота (количествоо прерываний в секунду). Она тут же снова обрабатывается и опять сбрасывается в ноль.

Реальная частота (только не в герцах, а в оборотах в минуту) хранится в rpm. А rpmcount  постоянно "гуляет" от 0 до частоты и тут же снова становится нулём.

Вместо того, чтобы пользоваться готовй rpm (ну или не делите на 60, просто сохраняйте, если Вам именно частот нужна) Вы используете переменную-счётчик rpmcount в качестве частоты. При этом Вы не знаете в какой момент Вы его (счётчик дернули). Может когда там уже готовая или почти готовая частота, а может как раз когда там свеженький нолик сидит. Вы попечатайте её в Serial уидите, что она постоянно плавает.

Так понятно?

 

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

Блин, даже я понял! Спасибо за разжовывание!