написание скетча для управления оборотами двигателя

Pavlo
Offline
Зарегистрирован: 18.12.2013
нужно добавить задержку примерно на 2 мин только когда подал напряжение на плату
это время необходимо чтоб инвертор успел загрузиться и установиться в рабочий режим
 
 
 
#define rele 10 
volatile unsigned long time = 0;        //Время срабатывания датчика
volatile unsigned long time_old = 0;             //предыдущее время
int speeed = 0;
 
void setup(){
  Serial.begin(9600);
  attachInterrupt(0, impuls, RISING);   //Прерывание по нарастающему фронту на D2
  pinMode(rele, OUTPUT);
  digitalWrite(rele, LOW);
  //delay(30000); //подождем 5 сек в начальном этам на всякий случай
void loop(){ 
  speeed = 60000/(time-time_old);          //вычисляем скорость в об/мин
  if(speeed >= 250){ 
    digitalWrite(rele, HIGH); 
    //delay(30000); 
  } 
  else{ 
    digitalWrite(rele, LOW); 
  } 
  Serial.println(speeed);
}
void impuls(){ // сработал датчик 
  time_old = time; 
  time = millis(); 
}
jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013
#define rele 10 
volatile unsigned long time = 0;        //Время срабатывания датчика
volatile unsigned long time_old = 0;             //предыдущее время
int speeed = 0;
 
void setup(){
  Serial.begin(9600);
  attachInterrupt(0, impuls, RISING);   //Прерывание по нарастающему фронту на D2
  pinMode(rele, OUTPUT);
  digitalWrite(rele, LOW);
  delay(120000); //подождем 2 мин на начальном этапе
} 
void loop(){ 
  speeed = 60000/(time-time_old);          //вычисляем скорость в об/мин
  if(speeed >= 250){ 
    digitalWrite(rele, HIGH); 
    //delay(30000); 
  } 
  else{ 
    digitalWrite(rele, LOW); 
  } 
  Serial.println(speeed);
}
void impuls(){ // сработал датчик 
  time_old = time; 
  time = millis(); 
}

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

Pavlo
Offline
Зарегистрирован: 18.12.2013

нет изменений. подключаю питание через несколько сек подаеться питание на реле и оно включаеться.

ждет 2 мин и после начинает нервно пульсировать доли сек +-+-+-+-+.

плата сгорела гдето провод коротнул пошел покупать новую

 

maksim
Offline
Зарегистрирован: 12.02.2012

Задержку перенесите в начало функции setup.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

да кстати лучше перенести в начало задержку

Pavlo
Offline
Зарегистрирован: 18.12.2013

поставил датчик на двигатель с плавной регулировкой оборотов на границе 250+-10 оборотов реле начинает пульсировать и задержка 30 сек не действует. время задержки при запуске работает хорошо

#define rele 10 
volatile unsigned long time = 0;        //Время срабатывания датчика
volatile unsigned long time_old = 0;             //предыдущее время
int speeed = 0;
 
void setup(){
  delay(120000); //подождем 2 мин на начальном этапе
  Serial.begin(9600);
  attachInterrupt(0, impuls, RISING);   //Прерывание по нарастающему фронту на D2
  pinMode(rele, OUTPUT);
  digitalWrite(rele, LOW);
  
void loop(){ 
  speeed = 60000/(time-time_old);          //вычисляем скорость в об/мин
  if(speeed >= 250){ 
    digitalWrite(rele, HIGH); 
//delay(30000);
       } 
  else{ 
    digitalWrite(rele, LOW); 
    
  } 
  Serial.println(speeed);
}
void impuls(){ // сработал датчик 
  time_old = time; 
  time = millis(); 
}
maksim
Offline
Зарегистрирован: 12.02.2012

Так она (задержка) же у вас //закомментирована...

Pavlo
Offline
Зарегистрирован: 18.12.2013

надо чтоб реле сработало на 250 об, увело актуатор и ждало 30 сек после этого делало проверку сколько оборотов если меньше 250 возврашало реле в начальное положение

в данный момент когда обороты 250-260 реле пульсирует меняет полярность

как это убрать

maksim
Offline
Зарегистрирован: 12.02.2012

Ну я же вам написал выше. Надо раскоментировать задержку. А именно:

//delay(30000);

заменить на

delay(30000);

то есть убрать две палочки.

И почитайте  Вставка программного кода в тему/комментарий.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

павел я же писал. надо раскоментировать задержку когда протестите

Pavlo
Offline
Зарегистрирован: 18.12.2013

я не програмист и терминологии не знаю

раскоментировал задержку реле не включилось (не сработало) осталось в начальном положении

закоментировал обратно работает но на границе оборотов реле начинает пульсировать

может надо вставить время в эту строку?

digitalWrite(rele, LOW ....  время);

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013
#define rele 10 
volatile unsigned long time = 0;        //Время срабатывания датчика
volatile unsigned long time_old = 0;             //предыдущее время
int speeed = 0;
 
void setup(){
  delay(120000); //подождем 2 мин на начальном этапе
  Serial.begin(9600);
  attachInterrupt(0, impuls, RISING);   //Прерывание по нарастающему фронту на D2
  pinMode(rele, OUTPUT);
  digitalWrite(rele, HIGH);
  
} 
void loop(){ 
  speeed = 60000/(time-time_old);          //вычисляем скорость в об/мин
  if(speeed >= 250){ 
    digitalWrite(rele, LOW); 
    delay(30000); 
  } 
  else{ 
    digitalWrite(rele, HIGH); 
  } 
  Serial.println(speeed);
}
void impuls(){ // сработал датчик 
  time_old = time; 
  time = millis(); 
}

пробуйте

Pavlo
Offline
Зарегистрирован: 18.12.2013

при достижении 250-300об реле не сработало

Pavlo
Offline
Зарегистрирован: 18.12.2013

после подключения ждет 2 мин потом каждые 30 сек посылает одиночный сигнал на реле один щелчок 

при повышении оборотов довел до 600 реле не срабатыват.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

проверьте подключение датчика

в терминале ардуины скорость показывает?

Pavlo
Offline
Зарегистрирован: 18.12.2013

выводит скорость раз в 30 сек

Pavlo
Offline
Зарегистрирован: 18.12.2013

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

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

если раз в 30 сек значит считает что скорость постоянно выше 250об

 

Pavlo
Offline
Зарегистрирован: 18.12.2013

показывает что меньше

Pavlo
Offline
Зарегистрирован: 18.12.2013

показывает постоянную скорость (двигатель зафиксирован на 380 об поднял для удобства регулировки а в проге установил порог 450) примерно через определенный период происходит скачек380.... -1....5000.....15000......-5000....-5500.....380 этот скачек длительностью примерно 3-5 сек

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

а минусы это такие показания в терминале?

так давайте поконкретнее. скорость в терминале показывает правильно или нет?

maksim
Offline
Зарегистрирован: 12.02.2012

Минусы могут быть по одной причине - переполнения переменной int speeed, обьявите ее тоже как unsigned long.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

не может быть у него быть больше 32000 оборотов. стало быть может ошибка в монтаже, или пин не тот подключил и это наводки (у себя проверял когда хронометр делал на наводки хорошо реагирует ардуина)

надо проверять монтаж

Pavlo
Offline
Зарегистрирован: 18.12.2013

Да скорость показывает правильно

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

давайте все уточним:

1. схему не меняли? пины подключены туда же куда и ранее? датчик на 2 (D2), а реле на 10

2. землю датчика подключили?

3. датчик не меняли?

4. Показания вашего тахометра соответствуют показаниям в терминале, он же монитор порта

5. эти значения "380.... -1....5000.....15000......-5000....-5500.....380" были в терминале? если да то "Да скорость показывает правильно" не может быть верно, если конечно ваш тахометр не показывает тоже самое, что врядли. или вы тут писали о тахометре. впреть попрошу конкретнее писать, а то непонятно кто именно правильно показывает скорость

6. питание тоже? то есть внешнее питание подаете на Vin?

Pavlo
Offline
Зарегистрирован: 18.12.2013

Схема подключения без изменений. Сравнивал табло датчика и данные с монитором и ручным измерителем скорости все показывают точное число оборотов отклонения показаний +- 3 оборота между всеми измерителями

а скачки показывает только терминал компа и в это время реле начинает трещать

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

Pavlo пишет:

Схема подключения без изменений. Сравнивал табло датчика и данные с монитором и ручным измерителем скорости все показывают точное число оборотов отклонения показаний +- 3 оборота между всеми измерителями

а скачки показывает только терминал компа и в это время реле начинает трещать

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

volatile unsigned long time = 0;        //Время срабатывания датчика
volatile unsigned long time_old = 0;             //предыдущее время
int speeed = 0;
 
void setup(){
  delay(120000); //подождем 2 мин на начальном этапе
  Serial.begin(9600);
  attachInterrupt(0, impuls, RISING);   //Прерывание по нарастающему фронту на D2
} 
void loop(){ 
  speeed = 60000/(time-time_old);          //вычисляем скорость в об/мин
  Serial.println(speeed);
  delay(200);
}
void impuls(){ // сработал датчик 
  time_old = time; 
  time = millis(); 
}

 

Pavlo
Offline
Зарегистрирован: 18.12.2013

показания датчика тахометра, монитора и дигитального датчика скорости идентичны разброс +-3 оборота

за период проверки на мониторе(терминале) было 2 одиночных скачка один 3000 второй 5000 после идет стабильно проверка идет уже 5 мин

Pavlo
Offline
Зарегистрирован: 18.12.2013

произошел еще скачек 2307..-1...-1...495...-5536..-1...2727...стабилизировался

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

странно. у меня пока возникают мысли о некачественных контактах. вы можете их исключить? 

Pavlo
Offline
Зарегистрирован: 18.12.2013

скачки разовые через большой промежуток

сейчас переберу все соединения на пайку

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

а промежуток между ошибками одинаковый или случайный?

Pavlo
Offline
Зарегистрирован: 18.12.2013

случайный

Pavlo
Offline
Зарегистрирован: 18.12.2013

время      ошибка

5 с            15000

2с                 -1

2 с                -1

3 с               20000

8с           -1...800...1300

3,41 мин       8500

0,42               7500

5,27               15000

0,24                1428

время - срабатывание между ошибками

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Я бы попробовал изменить строку 11 из сообщения #77 http://arduino.ru/forum/ishchu-ispolnitelya/napisanie-sketcha-dlya-upravleniya-oborotami-dvigatelya?page=1#comment-52982

Т.е. перед ней запретить прерывания, после неё - разрешить. Предполагаю, что это избавит от резких изменений.

Дело в том, что при вычислении выражения, возникающие прерывания могут сильно попортить значения, учитывая, что значения 4 байтовые.

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

 

maksim
Offline
Зарегистрирован: 12.02.2012

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

maksim
Offline
Зарегистрирован: 12.02.2012
#define rele 10
volatile unsigned long count = 0; 
unsigned int speeed = 0;

void setup()
{
  delay(120000); //подождем 2 мин на начальном этапе
  Serial.begin(9600);
  digitalWrite(rele, HIGH);
  digitalWrite(2, 1);
  attachInterrupt(0, impuls, RISING);   //Прерывание по нарастающему фронту на D2
} 

void loop()
{ 
  static unsigned long millis_prev = 0; 
  unsigned long time = millis() - millis_prev;
  unsigned int speeed = count/(60000UL/time);     //вычисляем скорость в об/мин
  count = 0;
  Serial.println(speeed);
  if(speeed >= 250)
  {
    digitalWrite(rele, LOW);
    delay(30000);
  }
  else digitalWrite(rele, HIGH);

  delay(200);
}

void impuls() // сработал датчик 
{ 
  count++;
}

И, кстати, так и не ясно digitalWrite(rele, HIGH) - это реле включено и двигатель раскручивается или наоборот останавливается?

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013
volatile unsigned int  number = 0;      //количество импульсов
unsigned long time = 0;                 //Время начала измерения
int speeed = 0;
 
void setup(){
  delay(120000); //подождем 2 мин на начальном этапе
  Serial.begin(9600);
  attachInterrupt(0, impuls, RISING);   //Прерывание по нарастающему фронту на D2
  time = millis();
} 
void loop(){ 
  if (millis() >= (time+6000)){         //здесь для точности можно будет внести корректировку
                                        //измерять будем каждые 6 секунд
    speeed = number*10;
    time = millis();
    number = 0;
  }
  
  Serial.println(speeed);
}
void impuls(){ // сработал датчик 
  number++; 
}

попробуйте скорость корректно считает или нет

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

максим не совсем понял каким образом у вас посчитается количество импульсов? за 200мс при максимальных 300об/мин (5об/с) посчитается 1 импульс, при меньших не факт вообще что поймает

maksim
Offline
Зарегистрирован: 12.02.2012

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

Pavlo
Offline
Зарегистрирован: 18.12.2013

да при HIGH реле включено двигатель работает

при LOW реле выключено двигатель должен остановиться

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

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

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

см. ниже

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

соберу все программы в кучу. попробуйте 1 чисто для теста

1. считаем обороты за еденицу времени

volatile unsigned int  number = 0;      //количество импульсов
unsigned long time = 0;                 //Время начала измерения
int speeed = 0;
 
void setup(){
  delay(120000); //подождем 2 мин на начальном этапе
  Serial.begin(9600);
  attachInterrupt(0, impuls, RISING);   //Прерывание по нарастающему фронту на D2
  time = millis();
} 
void loop(){ 
  if (millis() >= (time+6000)){         //здесь для точности можно будет внести корректировку
                                        //измерять будем каждые 6 секунд
    speeed = number*10;
    time = millis();
    number = 0;
  }
  
  Serial.println(speeed);
}
void impuls(){ // сработал датчик 
  number++; 
}

2. предложение kisoft

volatile unsigned long time = 0;        //Время срабатывания датчика
volatile unsigned long time_old = 0;             //предыдущее время
int speeed = 0;
 
void setup(){
  delay(120000); //подождем 2 мин на начальном этапе
  Serial.begin(9600);
  attachInterrupt(0, impuls, RISING);   //Прерывание по нарастающему фронту на D2
} 
void loop(){ 
  detachInterrupt(0);
  speeed = 60000/(time-time_old);          //вычисляем скорость в об/мин
  attachInterrupt(0, impuls, RISING);
  Serial.println(speeed);
  delay(200);
}
void impuls(){ // сработал датчик 
  time_old = time; 
  time = millis(); 
}

3. отключаем прерывания в момент передачи в serial (возможно это изза прерываний приходит белеберда) а также считаем в прерываниях скорость

volatile unsigned long time = 0;        //Время срабатывания датчика
volatile unsigned long time_old = 0;    //предыдущее время
volatile unsigned int speeed = 0;
 
void setup(){
  delay(120000);                        //подождем 2 мин на начальном этапе
  Serial.begin(9600);
  attachInterrupt(0, impuls, RISING);   //Прерывание по нарастающему фронту на D2
} 
void loop(){ 
  detachInterrupt(0);
  Serial.println(speeed);
  attachInterrupt(0, impuls, RISING);
  delay(200);
}
void impuls(){ // сработал датчик 
  time_old = time; 
  time = millis(); 
  speeed = 60000/(time-time_old);          //вычисляем скорость в об/мин
}
потестируйте и скажите что выдает в терминал
jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

немного доработал 3 вариант. убрал одно приравнивание для уменьшения времени обработки прерывания

volatile unsigned long time = 0;        //Время срабатывания датчика
volatile unsigned int speeed = 0;
 
void setup(){
  delay(120000);                        //подождем 2 мин на начальном этапе
  Serial.begin(9600);
  attachInterrupt(0, impuls, RISING);   //Прерывание по нарастающему фронту на D2
} 
void loop(){ 
  detachInterrupt(0);
  Serial.println(speeed);
  attachInterrupt(0, impuls, RISING);
  delay(200);
}
void impuls(){ // сработал датчик 
  speeed = 60000/(millis() - time);     //вычисляем скорость в об/мин
  time = millis(); 
}

 

Pavlo
Offline
Зарегистрирован: 18.12.2013

установил двигатель на постоянные обороты 330 об.мин погрешность 330-350 на дисплее ардуино

уменьшил обороты двигателя до 300 об.мин на дисплее 290-310 иногда выскакивает 380 об.мин

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

это в каком варианте?

вот может исправит если 3 вариант

volatile unsigned long time = 0;        //Время срабатывания датчика
volatile unsigned int speeed = 0;
 
void setup(){
  delay(120000);                        //подождем 2 мин на начальном этапе
  Serial.begin(9600);
  attachInterrupt(0, impuls, RISING);   //Прерывание по нарастающему фронту на D2
} 
void loop(){ 
  detachInterrupt(0);
  Serial.println(speeed);
  delay(200);
  attachInterrupt(0, impuls, RISING);
}
void impuls(){ // сработал датчик 
  speeed = 60000/(millis() - time);     //вычисляем скорость в об/мин
  time = millis(); 
}

 

Pavlo
Offline
Зарегистрирован: 18.12.2013

в последнем варианте стабильные обороты 297-300 за 8 мин проверки было 4-5 одиночных скачков вниз до 149 об

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

из 97 поста или 95?

Pavlo
Offline
Зарегистрирован: 18.12.2013

в сообщении 88 погрешность +0+20 об.   скачки разовые 380об

в сообщении 94 (первый вариант) погрешность +-10 об.    скачки разовые 350 об

 в сообщении 94 (вариант 2) погрешность оборотов +-3 об      разовые скачки 555 об.

в сообщении 95 скачки до 65535 примерно каждые 2 мин

в сообщении 97 погрешность +-2 об. разовые скачки вниз на 149 об