Сигнал определенной длины на выходе, при входящем сигнале HIGH/

hanapy
Offline
Зарегистрирован: 11.04.2017

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

Есть двигатель, к нему подключены цифровые датчики Холла (3 шт) - это будут входные сигналы. При вращении двигателя, в каждую единицу времени на входной пин (2,, 3,  4) поступает сигнал HIGH, нужно при входном HIGH сформировать сигнал длиной 300 мкс и затем отключиться до следующего сигнала HIGH. В моем искетче я пытаюсь сделать это для одного из входных сигналов, потом повторить его и для других 2. Я Пытался сделать их с помощью delayMicroseconds, но тщетно.  Посидев в форумах я пришел к тому что его надо делать через таймер. но реализовать его так и не получается. 

#define button 2
#define button2 3
#define led 5
#define led2 6
#define delayTime 300
int prevValue = 0;
int prevValue2 = 0;
long previousMicros = 0;



void setup() 
{
pinMode(led, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(button, INPUT);
pinMode(button2, INPUT);
}

  void loop()
{
 
  if (prevValue == LOW && digitalRead(button) == HIGH)
  {
    unsigned long currentMicros = micros();
  if (currentMicros - previousMicros < 300)
  {
    previousMicros = currentMicros; 
   digitalWrite(led, HIGH);
//digitalWrite(led, HIGH);
//delayMicroseconds(1000); 
//digitalWrite(led, LOW);
//delayMicroseconds(2); 
//digitalWrite(led2, LOW);
prevValue = LOW;
}
}
}
//if ((prevValue2 == LOW) && (digitalRead(button2) == HIGH))
//{

//digitalWrite(led2, HIGH);
//delayMicroseconds(100);
//digitalWrite(led2, LOW);
//delayMicroseconds(2);  
//delayMicroseconds(2000); 

//prevValue2= LOW;
//}
//}

 

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

А что не так с delayMicroseconds или с micros? В чём проблема-то?

hanapy
Offline
Зарегистрирован: 11.04.2017
Если использовать только половину программы, т.е. только пин 2 - вход и 5 выход, программа вроде бы работает, но при добавление в обработку еще 2 пары пинов входа и выхода, "глюки" появляются. 


 #define button 2
#define button2 3
#define led 5
#define led2 6
#define delayTime 500
int prevValue = 0;
int prevValue2 = 0;
long previousMicros = 0;



void setup() 
{
pinMode(led, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(button, INPUT);
pinMode(button2, INPUT);
}

  void loop()
{
 
  if (prevValue == LOW && digitalRead(button) == HIGH)
  {
    
   digitalWrite(led, HIGH);
digitalWrite(led, HIGH);
delayMicroseconds(delayTime); 
digitalWrite(led, LOW);
delayMicroseconds(2000); 
prevValue = LOW;
}

if ((prevValue2 == LOW) && (digitalRead(button2) == HIGH))
{

digitalWrite(led2, HIGH);
delayMicroseconds(delayTime);
digitalWrite(led2, LOW);
delayMicroseconds(2000); 

prevValue2= LOW;
}

}

 

hanapy
Offline
Зарегистрирован: 11.04.2017

Двигатель крутится примерно 5000 об/мин, при 3 даттчиках холла которые установлены относительно друг от друга в 120 градусах, идет быстрый опрос. Думаю из-за задержек delayMicroseconds()  или неправильного подбора 

42 digitalWrite(led2, LOW);
43 delayMicroseconds(2000);

  получается "наскок" , т.е. когда программе нужно опрашивать пин 3 для второго датчика, она еще в задерже delayMicroseconds(2000); Это мое объяснение всему этому. 

 

hanapy
Offline
Зарегистрирован: 11.04.2017

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

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

hanapy пишет:

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

Ничего не понял. Где пытаетесь? Почему нет кода с таймером?

hanapy
Offline
Зарегистрирован: 11.04.2017
#define button 2
#define button2 3
#define led 5
#define led2 6
#define delayTime 1000
int prevValue = 0;
int prevValue2 = 0;
long previousMicros = 0;



void setup() 
{
pinMode(led, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(button, INPUT);
pinMode(button2, INPUT);
}

  void loop()
{
 
  if (prevValue == LOW && digitalRead(button) == HIGH)
  {
    unsigned long currentMicros = micros();
  if (currentMicros - previousMicros < delayTime)
  {
    previousMicros = currentMicros; 
   digitalWrite(led, HIGH);
  }

prevValue = LOW;
}
else 
{
  digitalWrite(led, HIGH);
}
}

 

hanapy
Offline
Зарегистрирован: 11.04.2017

в этом случае он постоянно горит в HIGH.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

и правильно делает !

в какой строке вы его в LOW уводите  ?

hanapy
Offline
Зарегистрирован: 11.04.2017
если перевожу сюда, тоже не меняется.


#define button 2
#define button2 3
#define led 5
#define led2 6
#define delayTime 1000
int prevValue = 0;
int prevValue2 = 0;
long previousMicros = 0;



void setup() 
{
pinMode(led, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(button, INPUT);
pinMode(button2, INPUT);
}

  void loop()
{
 unsigned long currentMicros = micros();
  if (prevValue == LOW && digitalRead(button) == HIGH)
  {
      if (currentMicros - previousMicros < delayTime)
  {
    previousMicros = currentMicros; 
   digitalWrite(led, HIGH);
  }
else 
{
  digitalWrite(led, LOW);
}
prevValue = LOW;
}

}

 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

внимательно на 28 строку взгляните

hanapy
Offline
Зарегистрирован: 11.04.2017
#define button 2
#define button2 3
#define led 5
#define led2 6
#define delayTime 2000
int prevValue = 0;
int prevValue2 = 0;
long previousMicros = 0;
 
 
 
void setup() 
{
pinMode(led, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(button, INPUT);
pinMode(button2, INPUT);
}
 
  void loop()
{
 unsigned long currentMicros = micros();
  if (prevValue == LOW && digitalRead(button) == HIGH)
  {
      if (micros() - previousMicros > delayTime)
  {
    previousMicros = currentMicros; 
   digitalWrite(led, HIGH);
  }
else 
{
  digitalWrite(led, LOW);
}
prevValue = LOW;
}
 
}
hanapy
Offline
Зарегистрирован: 11.04.2017

может таймер нужно вынести перед 

if (prevValue == LOW && digitalRead(button) == HIGH)?

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

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

про 28 строку я имел ввиду переменную previousMicros.

hanapy
Offline
Зарегистрирован: 11.04.2017

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

 

#define button 2
#define button2 3
#define led 5
#define led2 6
#define delayTime 5000
int prevValue = 0;
int prevValue2 = 0;
long previousMicros = 0;



void setup() 
{
pinMode(led, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(button, INPUT);
pinMode(button2, INPUT);
}

  void loop()
{
 unsigned long currentMicros = micros();
  if (prevValue == LOW && digitalRead(button) == HIGH)
  {
      if (micros() - currentMicros < delayTime)
  {
    previousMicros = currentMicros; 
   digitalWrite(led, HIGH);
  }
else 
{
  digitalWrite(led, LOW);
  previousMicros=0;
}
prevValue = LOW;
}

}

 

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015
если перевожу сюда, тоже не меняется.


#define button 2
#define button2 3
#define led 5
#define led2 6
#define delayTime 1000
int prevValue = 0;
int prevValue2 = 0;
long previousMicros = 0;



void setup()
{
  pinMode(led, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(button, INPUT);
  pinMode(button2, INPUT);
}

void loop()
{
  unsigned long currentMicros = micros();
  if (prevValue == LOW && digitalRead(button) == HIGH)
  {
    if (currentMicros - previousMicros < delayTime)
    {
      previousMicros = currentMicros;
      digitalWrite(led, HIGH);
    }
    else
    {
      digitalWrite(led, LOW);
    }
    prevValue = LOW;
  }
}

вы думаете, наобум вставляя переменные и фукции, заработает ? нет !

я вам намекал что условие в 28 строке у вас не сработает ни разу !

потому что previousMicros не проинациализирована должным образом.

и это только первый "косяк".

nik182
Онлайн
Зарегистрирован: 04.05.2015

Фо́рум (лат. forum — арх. преддверие гробницы; площадка в давильне для подлежащего обработке винограда; рыночная площадь, городской рынок; торжище, центральная площадь):

Форум (площадь) — типология общественного пространства в древнеримском градостроительстве; центральная городская площадь, где проходила городская жизнь, заключались сделки, велись переговоры.

Из вики. Определение. Где тут слова о ПОМОЩИ? И что понимать под помощью? Написать за вас программу? Или хватит подсказок? Например у вас 3 фазы и казалось бы должны быть три переменные которым присваивается значение времени при появлении сигнала на соответствующем пине и поднимается выход. Проверять три раза время и если где-то оно истекло выход снимать. Но если входной сигнал будет длиннее 300 мс что произойдёт? А если полный цикл будем меньше 900 мс что будет? Как избежать таких ситуаций?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

hanapy пишет:
да если бы я все знал, вряд ли писал  в форумах. Наверное форумы для этого и созданы, чтобы помогать друг другу, а не упрекать человека что он чего-то не знает. ))
  Вот здесь и проявляются двойные стандарты. Если Вы что-то знаете, то на форумы не заходите и другим не помогаете. А вот если не знаете, то спасите- помогите я этого не знаю и этого не умею.  Так что мой Вам совет, почаще заходите на форумы, в которых Вы всеже что-то знаете. Должны же быть такие форумы.

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

hanapy пишет:

Наверное форумы для этого и созданы, чтобы помогать

Это Вы так думаете. На самом же деле жизнь устроена по-другому. Вот недавно такому как Вы давали вот эту ссылку. Там в третьем абзаце чётко и понятно написано, что на самом деле (а не в Вашем воображении) происходит, когда человек заходит на форум и требует написать ему код.

А что касается упрёков, так Вам сначала сказали "посмотрите на 28-ю" строку. Вы, вместо того, чтобы посмотреть и решить проблему (или хотя бы спросить "что с ней не так?") начали постить какие-то другие коды и возмущаться. что Вам не помогли. А решение Вам дали  - Вы его проигнорировали.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Регулятор BLDC мотора на датчиках Холла - ТАК не делается. В сети полно готовых прошивок для мег, но они все "на ассемблере" .. догадаетесь "почему"? :)

В целом, не майтесь. купите готовый контроллер мотора - это дешевле и проще.

hanapy
Offline
Зарегистрирован: 11.04.2017

я Вас понял....

hanapy
Offline
Зарегистрирован: 11.04.2017

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

#define button 2
#define button2 3
#define led 5
#define led2 6
#define delayTime 500
int prevValue = 0;
int prevValue2 = 0;
uint32_t timeRising;


void setup() 
{
pinMode(led, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(button, INPUT);
pinMode(button2, INPUT);
//previousMicros = micros();
}

  void loop()
{
    if (prevValue == LOW && digitalRead(button) == HIGH)
  {
      digitalWrite(led, HIGH);
      timeRising = micros();
      
  }
      if ((micros() - timeRising)< delayTime)
  {
    digitalWrite(led, LOW);
    prevValue = LOW;
}
}

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Может так

#define button 2
#define button2 3
#define led 5
#define led2 6
#define delayTime 500
bool prevValue = 0;
int prevValue2 = 0;
uint32_t timeRising;



void setup() 
{
  pinMode(led, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(button, INPUT);
  pinMode(button2, INPUT);
  //previousMicros = micros();
}

void loop()
{
  if (prevValue == LOW && digitalRead(button) == HIGH)
  {
    digitalWrite(led, HIGH);
    timeRising = micros();
    prevValue = 1;

  }
  if (prevValue == 1 && (micros() - timeRising)>= delayTime)
  {
    digitalWrite(led, LOW);
  }
  if (digitalRead(button)== LOW) prevValue = 0;
}

 

SLKH
Offline
Зарегистрирован: 17.08.2015

hanapy пишет:

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

#define button 2
#define button2 3
#define led 5
#define led2 6
#define delayTime 500
int prevValue = 0;
int prevValue2 = 0;
uint32_t timeRising;


void setup() 
{
pinMode(led, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(button, INPUT);
pinMode(button2, INPUT);
//previousMicros = micros();
}

  void loop()
{
    if (prevValue == LOW && digitalRead(button) == HIGH)
  {
      digitalWrite(led, HIGH);
      timeRising = micros();
      
  }
      if ((micros() - timeRising)< delayTime)
  {
    digitalWrite(led, LOW);
    prevValue = LOW;
}
}

 

реагирует, просто вы не видите погасание диода на единицы микросекунд. 

hanapy
Offline
Зарегистрирован: 11.04.2017

оооо получилось. Спасибо огромное всем!!!

hanapy
Offline
Зарегистрирован: 11.04.2017

я на осциллографе смотрю. видно))

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Чуть подправил

#define button 2
#define button2 3
#define led 5
#define led2 6
#define delayTime 500
bool prevValue = 0;
int prevValue2 = 0;
uint32_t timeRising;



void setup() 
{
  pinMode(led, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(button, INPUT);
  pinMode(button2, INPUT);
  //previousMicros = micros();
}

void loop()
{
  if (prevValue == LOW && digitalRead(button) == HIGH)
  {
    digitalWrite(led, HIGH);
    timeRising = micros();
    prevValue = 1;

  }
  if (prevValue == 1 && (micros() - timeRising)>= delayTime)
  {
    digitalWrite(led, LOW);
  }
  if (digitalRead(button)== LOW && digitalRead(led)== LOW ) prevValue = 0;
}

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Давайте сначала малость ускорим:

Строка 22 if (prevValue == LOW && (PIND&B00000100==B00000100))

Строка 24 PORTD!=B00100000

Строка 30 ....

Строка 32 ....

Строка 34 .... не нужна нулите в 32

 

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

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

1. При поступлении сигнала включаем выход и считываем значение времени

2. При прохождении 300мс выключаем выход.

По хорошему - это будет работать и при интервалах входных сигналов менее 300мс. Просто выход не будет выключаться.

Где-то так

void loop() {
if (digitalRead(button) == HIGH){
digitalWrite(led, HIGH);
timeRising = micros();
}
if ( (micros() - timeRising)>= delayTime) digitalWrite(led, LOW);
}

 

SLKH
Offline
Зарегистрирован: 17.08.2015

mykaida пишет:

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

1. При поступлении сигнала включаем выход и считываем значение времени

2. При прохождении 300мс выключаем выход.

По хорошему - это будет работать и при интервалах входных сигналов менее 300мс. Просто выход не будет выключаться.

Где-то так

void loop() {
if (digitalRead(button) == HIGH){
digitalWrite(led, HIGH);
timeRising = micros();
}
if ( (micros() - timeRising)>= delayTime) digitalWrite(led, LOW);
}

 

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

 

nik182
Онлайн
Зарегистрирован: 04.05.2015

Судя по программе delayTime будет осчитываться от момента когда button упадёт в LOW? А если он милисекунд 200 продержится, то на выходе импульс будет 300+200 = 500 мс? 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

nik182 пишет:

Судя по программе delayTime будет осчитываться от момента когда button упадёт в LOW? А если он милисекунд 200 продержится, то на выходе импульс будет 300+200 = 500 мс? 

Уел :)

Правда атор поста не указывал, по какому фронту начинать отсчет и я принял время прохождения датчика несущественным. Но можно ковырнуть и так:

void loop() {
if (!prevValue && digitalRead(button)){
digitalWrite(led, HIGH);
prevValue=TRUE;
timeRising = micros();
}
if ( (micros() - timeRising)>= delayTime){
 digitalWrite(led, LOW);
prevValue=FALSE;
}
}

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014
mykaida
На мой взгляд Ваш код будет работать коректно при условии что входящий импульс будет короче исходящего в противном случае нет
mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

vosara пишет:

mykaida
На мой взгляд Ваш код будет работать коректно при условии что входящий импульс будет короче исходящего в противном случае нет

Согласен - будет срабатывать как попало, но тогда вся эта шняга смысла не имеет.

Кстати можно еще ускорить для более точного определения интервала, убрав операцию чтения во время подсчета времени:

void loop() {
if (!prevValue){
if (digitalRead(button)){
digitalWrite(led, HIGH);
prevValue=TRUE;
timeRising = micros();
}
}
if ( (micros() - timeRising)>= delayTime){
 digitalWrite(led, LOW);
prevValue=FALSE;
}
}

 

nik182
Онлайн
Зарегистрирован: 04.05.2015

Никого  я не ел. Это ж элементарная логика из стартового сообщения:  нужно при входном HIGH сформировать сигнал длиной 300 мкс...

А теперь ещё два таких же блока для ещё двух входов и что будет, если длительность loop будет больше входного импульса?  

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Скетч в #26 (http://arduino.ru/forum/programmirovanie/signal-opredelennoi-dliny-na-vy...) посту будет работать коректно при импульсе любой длины, но mykaida прав, при работе с микрос желательно переходить на управление портом на прямую!