Отслеживание принудительной остановки двигателя(на валу-неодим. магниты, на неподв.части-датчик). Голову ломаю 3 месяц О_о

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Всем привет!

Может подскажет кто из знающих...Суть вот в чем...Программировать кое-как умею. Скетч писал сам.

Но он не работает как надо. 

ДАНО: маленький эл.двигатель. На его вал насажены 2 неодимовых плоских магнита(как пропеллер расположены, но плоский пропеллер). Эти магниты пролетают мимо стационарно расположенного цифрового датчика Холла: https://umnyjdomik.ru/ky-003-datchik-holla-na-baze-44e-dlya-arduino.html

ЧТО НУЖНО: Если происходит внешний принудительный тормоз двигателя - ардуино это понимает и отключает двигатель(чтобы не молотил впустую), подождав n-миллисекунд.

Ломаю голову уже 3 месяц. Вроде ерунда- но что то упускаю мелкое и не работает в итоге...

Вот ссылка на скетч: 

 

 

mu_ssina
Offline
Зарегистрирован: 30.08.2013

скетч: https://drive.google.com/file/d/14e9MKG0lfQCbSBs95qdo1yLQFhBYEnoq/view?usp=sharing 

P.S. в нем написано, что если есть внешнее торможение двигателя- включить реверс. Но это не суть. Можно или реверс или остановку просто. Суть не в этом-а в том, что не работает корректное чтение датчика. Датчик видится, все читается-но где то в коде я косячу....

 

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018
MaksVV
Offline
Зарегистрирован: 06.08.2015

внешним прерыванием считывать фронт от датчика и в обработчике сбрасывать таймер. Как только таймер натикает определенное время =>вал остановлен {делай что там нужно}

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

mu_ssina - если хотите, чтобы кто-то посмотрел ваш скетч - вставте код в сообщение, лезть на гугл-драйв ради помощи неизвестному пацаку - это слишком

vlad072
Offline
Зарегистрирован: 01.08.2017

Да ещё и распакуй, там 4 каких то скетча, разберись какой нужный, открой... пц

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Ок, понял! Кидаю прямо сюда!

Любому совету буду рад!

Итак, как выглядит программа (принтскрин вкладок-чтобы общая суть понятна была, далее будет код):

Код вкладок:

Вкладка "3":


// wired connections

#define HG7881_B_IA 10 // D10 --> Motor B Input A --> MOTOR B +
#define HG7881_B_IB 11 // D11 --> Motor B Input B --> MOTOR B -

// functional connections

#define MOTOR_B_PWM HG7881_B_IA // Motor B PWM Speed
#define MOTOR_B_DIR HG7881_B_IB // Motor B Direction

// the actual values for "fast" and "slow" depend on the motor
#define PWM_SLOW 130  // arbitrary slow speed PWM duty cycle
#define PWM_FAST 250 // arbitrary fast speed PWM duty cycle
#define DIR_DELAY 1000 // brief delay for abrupt motor changes


int direction_random = 0; //генератор случайных чисел, какое направление( 1 или 2 - CW или CCW)
int position_random = 0; //генератор случайных чисел, для времени работы 


int hallPin = 12 ; // назначение пина датчика
int digital_hall_sensor;
int digital_hall_sensor2;
int digital_hall_sensor3;
int digital_hall_sensor4;
unsigned long alarm_Millis = 1000; //минипериоды, через которые мы проверяем что там с датчиком-есть ли смена значений(т.е. крутится ли вал)
unsigned long currentMillis; 
unsigned long currentMillis2;
unsigned long currentMillis3;  
boolean new_period;
boolean new_period2; 
boolean new_period3;
int random1 = random(1, 3); //генератор случайных чисел 





void setup()
{

Serial.begin( 2000000 );

pinMode( MOTOR_B_DIR, OUTPUT );
pinMode( MOTOR_B_PWM, OUTPUT );
digitalWrite( MOTOR_B_DIR, LOW );
digitalWrite( MOTOR_B_PWM, LOW );
pinMode (hallPin, INPUT);


} //setup



void loop()
{
  Motor_B (2, 2);


  
  sensor_master();
  if (!sensor_master())
{
  
   Serial.println ("нет удержания");
}
else
{
   Hard_stopper(3);
   Serial.println ("удержание!");
  Motor_B (2, 1);

}   

}

Вкладка "Hall_Sensor":


//---------------------------------СЛЕЖЕНИЕ ЗА ЗНАЧЕНИЕМ ДАТЧИКА ХОЛЛА НА АРДУИНЕ----------------------------------------

boolean sensor_master() // Датчик на модуле с ардуиной
{
 
      if (new_period=false)
      {
               digital_hall_sensor = digitalRead (hallPin) ; // чтение значения с датчика
               currentMillis = millis();
               new_period=true;
         
      }
     
      if ((millis() - currentMillis)>alarm_Millis)
      {
        digital_hall_sensor2 = digitalRead(hallPin);
        currentMillis2 = millis();
        
        if (digital_hall_sensor2 == digital_hall_sensor)//первая проверка на равенство
           {
          while ((millis() - currentMillis2)<alarm_Millis-(alarm_Millis/3))//вычитаем некое неровное число, чтобы проверять через разные интервалы
              {
                //ничего не делаем-ждем
              }
             
                 digital_hall_sensor3 = digitalRead(hallPin);
                 currentMillis3 = millis();

                 while ((millis() - currentMillis3)<alarm_Millis-(alarm_Millis/2,5))//вычитаем некое неровное число, чтобы проверять через разные интервалы
                    {
                      //ничего не делаем-ждем
                    }

                 digital_hall_sensor4 = digitalRead(hallPin);
                 
                 if (digital_hall_sensor4 == digital_hall_sensor)//первая проверка на равенство
                   {
                  
                      return true;
                      new_period=false;
                   }

                 
          
           }
       
      }

   
}

Вкладка "Motor_B":


//------------------------------ ФУНКЦИЯ ВРАЩЕНИЯ ДВИГАТЕЛЯ B ---------------------

void Motor_B (int speed_, int direction_)
{
 

   if (speed_=1)//низкая скорость
   {
    if (direction_=1)//CW
       {
          digitalWrite( MOTOR_B_DIR, LOW ); // direction = reverse
          analogWrite( MOTOR_B_PWM, PWM_SLOW ); // PWM speed = slow
       }

    else if (direction_=2)//CCW
       {
          digitalWrite( MOTOR_B_DIR, HIGH); // direction = forward
          analogWrite( MOTOR_B_PWM, 255-PWM_SLOW ); // PWM speed = slow
       }
   }
   else if (speed_=2)//высокая скорость
   {
    if (direction_=1)//CW
       {
          digitalWrite( MOTOR_B_DIR, LOW ); // direction = reverse      
          analogWrite( MOTOR_B_PWM, PWM_FAST ); // PWM speed = fast  
       }

    else if (direction_=2)//CCW
       {
          digitalWrite( MOTOR_B_DIR, HIGH ); // direction = forward
          analogWrite( MOTOR_B_PWM, 255-PWM_FAST ); // PWM speed = fast
       }
   }
 
}

Вкладка "Tormoza":


//---------------------------------ФУНКЦИИ ТОРМОЖЕНИЯ ДВИГАТЕЛЕЙ--------------------------------------


void Motors_stopper() //функция, которая тормозит все двигатели перед сменой направления вращения
{
//digitalWrite( MOTOR_A_DIR, LOW );
//digitalWrite( MOTOR_A_PWM, LOW );
digitalWrite( MOTOR_B_DIR, LOW );
digitalWrite( MOTOR_B_PWM, LOW );
delay( DIR_DELAY );
}


void Soft_stopper(int what_motor) //функция медленной остановки двигателей
{
if (what_motor==1)
{
//digitalWrite( MOTOR_A_DIR, LOW );
//digitalWrite( MOTOR_A_PWM, LOW );
}

else if (what_motor==2)
{
digitalWrite( MOTOR_B_DIR, LOW );
digitalWrite( MOTOR_B_PWM, LOW );
}
else if (what_motor==3)
{
//digitalWrite( MOTOR_A_DIR, LOW );
//digitalWrite( MOTOR_A_PWM, LOW );
digitalWrite( MOTOR_B_DIR, LOW );
digitalWrite( MOTOR_B_PWM, LOW );
}

}

void Hard_stopper(int what_motor) //функция жесткой остановки двигателей (int what_motor(1,2,3)
{

  if (what_motor==1)
  {
//        digitalWrite( MOTOR_A_DIR, HIGH );
//        digitalWrite( MOTOR_A_PWM, HIGH );
  }
  
  else if (what_motor==2)
  {
        digitalWrite( MOTOR_B_DIR, HIGH );
        digitalWrite( MOTOR_B_PWM, HIGH );
  }
  
  else if (what_motor==3)
  {
//        digitalWrite( MOTOR_A_DIR, HIGH );
//        digitalWrite( MOTOR_A_PWM, HIGH );
        digitalWrite( MOTOR_B_DIR, HIGH );
        digitalWrite( MOTOR_B_PWM, HIGH );
   }  
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

attachInterrupt() + перечитать #3

mu_ssina
Offline
Зарегистрирован: 30.08.2013

За совет спасибо! Изучу...

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

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

mu_ssina пишет:

За совет спасибо! Изучу...

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

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

Попытайтесь четко сформулировать:

1. Что такое "постоянно".

2. Что такое "отслеживание".

3. Что такое "состояние датчика".

4. Что такое "происходило".

mu_ssina
Offline
Зарегистрирован: 30.08.2013

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

sadman41
Offline
Зарегистрирован: 19.10.2016

При довольно больших оборотах кто угодно не успеет обсчитать код.

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Ну вот, давайте прикинем...Микродвигатель крутится на оборотах...сложно сказать на самом деле на каких. Предполагаю(по показателям из интернета) -в районе 10 000 об/мин.

P.S. сейчас сам написал и сам задумался- а какого черта я не замерил программно до сих пор еще? :-)

Вот такой код-будет ли успевать обсчитываться? По ощущениям не успевает, даже подключение Serial пришлось запустить на скорости 2 000 000(иначе все глючит в мониторе порта-кракозябры):

//---------------------------------СЛЕЖЕНИЕ ЗА ЗНАЧЕНИЕМ ДАТЧИКА ХОЛЛА НА АРДУИНЕ----------------------------------------

boolean sensor_master() // Датчик на модуле с ардуиной
{
 
      if (new_period=false)
      {
               digital_hall_sensor = digitalRead (hallPin) ; // чтение значения с датчика
               currentMillis = millis();
               new_period=true;
         
      }
     
      if ((millis() - currentMillis)>alarm_Millis)
      {
        digital_hall_sensor2 = digitalRead(hallPin);
        currentMillis2 = millis();
        
        if (digital_hall_sensor2 == digital_hall_sensor)//первая проверка на равенство
           {
          while ((millis() - currentMillis2)<alarm_Millis-(alarm_Millis/3))//вычитаем некое неровное число, чтобы проверять через разные интервалы
              {
                //ничего не делаем-ждем
              }
             
                 digital_hall_sensor3 = digitalRead(hallPin);
                 currentMillis3 = millis();

                 while ((millis() - currentMillis3)<alarm_Millis-(alarm_Millis/2,5))//вычитаем некое неровное число, чтобы проверять через разные интервалы
                    {
                      //ничего не делаем-ждем
                    }

                 digital_hall_sensor4 = digitalRead(hallPin);
                 
                 if (digital_hall_sensor4 == digital_hall_sensor)//первая проверка на равенство
                   {
                  
                      return true;
                      new_period=false;
                   }

                 
          
           }
       
      }

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

почитать зачем нужны прерывания и перечитать #7 

mu_ssina
Offline
Зарегистрирован: 30.08.2013

MaksVV пишет:

 и перечитать #7 

 

Вот это не понял. Седьмое-это что? Пункт правил, строка в программе и т.д. Не понял вообще!

Ок. догадался-сообщение....отвык от местного стиля общения :-))))

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Сейчас бьюсь с этими millis();

Может кто объяснит мне, почему у меня в монитор порта выводит какое то длинное непонятное число, если я делаю так как ниже (написал счетчик оборотов в минуту, чтобы понимать скорость вращения двигателя).

В чем загвоздка: 

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

Serial.println (currentMillis3);

Сам код: 

void loop()
{
 Motor_B (2, 2); //запустили движок CW, обороты -высокие. 
//Далее -считаем, чтобы произошел полный оборот-датчик прошел значения последовательно: LOW-HIGH-LOW

 digital_hall_sensor =  digitalRead (hallPin);
 currentMillis = millis();

  
 if ((digital_hall_sensor == LOW)&&(!counter2)) 
  {
     counter1=true;
  }
  else if ((digital_hall_sensor == HIGH)&&(counter1))
  {
     counter2=true;
  }
   else if ((digital_hall_sensor == LOW)&&(counter2))
   {
    currentMillis2 = millis();

    currentMillis3 = 60000/(currentMillis2-currentMillis);
    counter1=false;
    counter2=false;
    oborotov++;

    Serial.println (currentMillis3);
   }
     }

 

mu_ssina
Offline
Зарегистрирован: 30.08.2013

В общем, сколько ни бьюсь-не получается...В чем проблема- не пойму...

Должно работать -не работает. В смысле не срабатывает удержание.

MaksVV
Offline
Зарегистрирован: 06.08.2015

скачайте готовую библиотеку частотомера и переводите в обороты.  вроде назывались FreqMeasure и FreqCount. Одна для низких частот , другая для высоких. Сами выберете

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Спасибо! Неее..Основная проблема, о которой я говорю, - это та старая проблема: не реагирует на удержание вала двигателя....Что только не пробовал. Не могу понять в чем дело! И код переписывал по-разному...Чувствую, -какая то фундаментальная проблема! Что то вроде того, что не успевает обсчитывать и т.д.

Крутиться вал, дватаю его рукой, торможу до нуля. По идее должен выдать в серийный порт: "Удержание!", выключиться и включиться реверс. Хрен там!

Код вот такой -если кто поможет, буду премного благодарен! Какую то фундаментальную ошибку допускаю, чувствую...: 


// wired connections

#define HG7881_B_IA 10 // D10 --> Motor B Input A --> MOTOR B +
#define HG7881_B_IB 11 // D11 --> Motor B Input B --> MOTOR B -

// functional connections

#define MOTOR_B_PWM HG7881_B_IA // Motor B PWM Speed
#define MOTOR_B_DIR HG7881_B_IB // Motor B Direction

// the actual values for "fast" and "slow" depend on the motor
#define PWM_SLOW 130  // arbitrary slow speed PWM duty cycle
#define PWM_FAST 250 // arbitrary fast speed PWM duty cycle
#define DIR_DELAY 1000 // brief delay for abrupt motor changes


int direction_random = 0; //генератор случайных чисел, какое направление( 1 или 2 - CW или CCW)
int position_random = 0; //генератор случайных чисел, для времени работы 


int hallPin = 12 ; // назначение пина датчика

int digital_hall_sensor;
int digital_hall_sensor2;
int digital_hall_sensor3;
int digital_hall_sensor4;
unsigned long alarm_Millis = 1000; //минипериоды, через которые мы проверяем что там с датчиком-есть ли смена значений(т.е. крутится ли вал)
unsigned long currentMillis; 
unsigned long currentMillis2;
unsigned long currentMillis3;  
boolean new_period;
boolean new_period2; 
boolean new_period3;
int random1 = random(1, 3); //генератор случайных чисел 





void setup()
{

Serial.begin( 2000000 );

pinMode( MOTOR_B_DIR, OUTPUT );
pinMode( MOTOR_B_PWM, OUTPUT );
digitalWrite( MOTOR_B_DIR, LOW );
digitalWrite( MOTOR_B_PWM, LOW );
pinMode (hallPin, INPUT);


} //setup



void loop()
{
 Motor_B (1, 2);
 digital_hall_sensor =  digitalRead (hallPin);
 currentMillis = millis();

 digital_hall_sensor2 =  digitalRead (hallPin);
 currentMillis2 = millis();
 
 
 if ((digital_hall_sensor==LOW)&&(digital_hall_sensor2==LOW))
 {
  if (currentMillis2-currentMillis>alarm_Millis)
  {
    Serial.println ("Удержание!");
    Hard_stopper(2);
    Motor_B (1, 1);
     
  }
 }
  else if ((digital_hall_sensor==HIGH)&&(digital_hall_sensor2==HIGH))
  {
    if (currentMillis2-currentMillis>alarm_Millis)
  {
    Serial.println ("Удержание!");
    Hard_stopper(2);
    Motor_B (1, 1);
     
  }
  }

}

 

С разными вариациями, то что наверху- переписывыл миллион раз. Не работает...

sadman41
Offline
Зарегистрирован: 19.10.2016

После строки #67 и #77:

Serial.print("dT: "); Serial.println(currentMillis2-currentMillis);

MaksVV
Offline
Зарегистрирован: 06.08.2015

а где следование рекомендациям #3  ? 

MaksVV
Offline
Зарегистрирован: 06.08.2015

датчик повесить на пин 2. 

volatile uint32_t lasttime = 0;
volatile bool shaft_state = 1;

#define SENSOR_MIN_TIME 500 // время мс, через которое при отсутствии импульсов от датчика
                            // считается что вал остановлен


void setup()
{
Serial.begin(9600);
attachInterrupt(0, sensor_impulse, CHANGE);
}

void loop()
{
  
  if (shaft_state && millis() - lasttime > SENSOR_MIN_TIME){shaft_state = 0;}  

static bool lastshaft_state = 1;
     
     if (lastshaft_state!=shaft_state)
     {
       if (shaft_state) Serial.println("Shaft stop");
       else Serial.println ("Shaft start");
       lastshaft_state=shaft_state;
     }
}

void sensor_impulse()
{
lasttime = millis();
 shaft_state = 1; 
}

 

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Премного благодарен! Отпишусь позже, что вышло!

MaksVV
Offline
Зарегистрирован: 06.08.2015

там старт и стоп только  я перепутал

Kakmyc
Offline
Зарегистрирован: 15.01.2018

#include <avr/interrupt.h>
volatile boolean check_flag,stop_flag;

void stop(){//что то делаем
}
void work_count(){
check_flag=0;}

ISR(TIMER1_COMPA_vect){
cli();
TCNT1=0;
if(check_flag)stop_flag=1;
check_flag=1;
sei();
}

void setup(){
attachInterrupt(0,work_count,RISING);//или FALLING, ваще похеру
TCCR1A=0;
TCCR1B=0;
TCCR1B =(1<<CS00)|(1<<CS01);
TIMSK1|=(1<<OCIE1A);
OCR1A=25000;
sei();
}

void loop(){
if(stop_flag)stop();
}

Тс, тебе атмел три таймера (с вачдогом 4) аппаратных в МК старался, пихал, а ты выдумываешь всякие непотребства.

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

Запускаем таймер, по достижении которого поднимаем флаг проверки.

Если было внешнее прерывание(вал вращался), то флаг проверки опускаем. если прошел интервал таймера , а оборота не было поднимаем флаг остановки.

 

Множители и значения от балды выставлял

sadman41
Offline
Зарегистрирован: 19.10.2016

Давайте, парни, работайте за других башкой, пока те пиво пьют вместо вас. На ICR overflow еще посадите реверс - вообще волшебно будет.

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Долго терпел, но не выдержал.
555 - наше всё:
http://nauchebe.net/2012/08/sxema-indikatora-propadaniya-impulsov-lm555/

MaksVV
Offline
Зарегистрирован: 06.08.2015

sadman41 пишет:

Давайте, парни, работайте за других башкой, пока те пиво пьют вместо вас. 

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

mu_ssina
Offline
Зарегистрирован: 30.08.2013

сегодня начал что то пытаться делать наконец :-)

Вопросы появились по вашему коду..А почему датчик на 2 пин нужно? Могу я оставить его на 12 пине(как сейчас)?

P.S. вопрос снят, прочитал описание attachInterrupt(interrupt, function, mode).

 
mu_ssina
Offline
Зарегистрирован: 30.08.2013

Для MaksVV: Работает! Спасибо огромное!!! Не совсем верно работает -но работает! :-)

Моя принципиальная ошибка была в том, что я не знал про отслеживание прерываний с помощью специального пина и всю голову изломал: если сделаю цикл while скажем-чтобы постоянно следить за прерыванием, - то как программа будет все остальное делать?! Она же будет сидеть в цикле постоянно...В общем всю голову сломал и 3 месяца убил :-)))))

Для Kakmyc:  Спасибо за основательный глубокий совет! Но для меня это пока сложновато будет...Решил идти простым путем- мне в эту программу еще много что встроить надо...И внешнее прерывание-это микро кирпичик только. А если я не понимаю всех тонкостей этого кирпичика-мне сложно будет писать все остальное. Но -спасибо!

 

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

mu_ssina пишет:
Не совсем верно работает -но работает! :-)

Это имеется ввиду?

MaksVV пишет:
Там старт и стоп только я перепутал

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Вроде бы да(насколько я понял по выводу). Но главное не это. Главное-я открыл для себя с вашей помощью attachInterrupt -для меня это реальный прорыв. Думаю, дальше все пойдет как по маслу. Я понял как мне крутить этот параллельный цикл(attachInterrupt -следит за датчиком, параллельно с программой).

mu_ssina
Offline
Зарегистрирован: 30.08.2013

MaksVV пишет:

датчик повесить на пин 2. 

volatile uint32_t lasttime = 0;
volatile bool shaft_state = 1;

#define SENSOR_MIN_TIME 500 // время мс, через которое при отсутствии импульсов от датчика
                            // считается что вал остановлен


void setup()
{
Serial.begin(9600);
attachInterrupt(0, sensor_impulse, CHANGE);
}

void loop()
{
  
  if (shaft_state && millis() - lasttime > SENSOR_MIN_TIME){shaft_state = 0;}  

static bool lastshaft_state = 1;
     
     if (lastshaft_state!=shaft_state)
     {
       if (shaft_state) Serial.println("Shaft stop");
       else Serial.println ("Shaft start");
       lastshaft_state=shaft_state;
     }
}

void sensor_impulse()
{
lasttime = millis();
 shaft_state = 1; 
}

 

 

В общем, сейчас протестировал многократно.Никак не мог поначалу понять, что не так...И потом дошло в чем дело: При вращении вала, мимо цифрового датчика Холла много раз в секунду пролетают 2 неодимовых магнита(как я говорил раньше, на вал насажен условно говоря воздушный винт, в каждой лопасти-неодимовый магнит). Так вот: значение  LOW-HIGH на датчике МЕНЯЕТСЯ МНОГОКРАТНО В СЕКУНДУ.  

А attachInterrupt реагирует на смену значения на датчике: attachInterrupt(0, sensor_impulse, CHANGE). 

Таким образом, получается, что attachInterrupt работает неправильно! Я то не понял поначалу-почему в Serial постоянно выводится "Shaft stop" -"Shaft start"  - в непрерывном режиме, хотя вал крутится....

Вот такая новая беда...И что с этим можно поделать, на ваш взгляд?

Ладно, пока сам тоже думаю, если глупость на сонную голову написал-извиняйте...

 

sadman41
Offline
Зарегистрирован: 19.10.2016

MaksVV пишет:

sadman41 пишет:

Давайте, парни, работайте за других башкой, пока те пиво пьют вместо вас. 

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

Тогда я тебе подмогну: во-первых тебе нужен ATOMIC_BLOCK, во-вторых - достаточно анализировать shaft_state на true/false, а прерывание дёргать только по одному фронту.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

mu_ssina пишет:

А attachInterrupt реагирует на смену значения на датчике: attachInterrupt(0, sensor_impulse, CHANGE). 

attachInterrupt лишь присоединяет обработчик к прерыванию. Она не может реагировать на что-либо. Реагирует - та функция, которую Вы присоединили при помощи attachInterrupt.

Цитата:

Таким образом, получается, что attachInterrupt работает неправильно!

Нет, она работает правильно, это Вы не понимаете, как она должна работать.

Цитата:

Я то не понял поначалу-почему в Serial постоянно выводится "Shaft stop" -"Shaft start"  - в непрерывном режиме, хотя вал крутится....

Вот такая новая беда...И что с этим можно поделать, на ваш взгляд?

Ладно, пока сам тоже думаю, если глупость на сонную голову написал-извиняйте...

Где-то у Вас ошибка: либо в скетче, либо в схеме, либо в конструкции.

Вы понимаете, как работает датчик Холла? Он реагирует на магнитное поле. На любое. В частности, на магнитное поле Земли и на сетевую наводку. Другое дело, что его обвязка должна быть настроена так, чтобы все ненужные влияния отсекать. 

Для начала просто посмотрите осциллографом, что у Вас выдает датчик Холла при отсутствии магнитов.

MaksVV
Offline
Зарегистрирован: 06.08.2015

mu_ssina пишет:
Никак не мог поначалу понять, что не так....

Так вот: значение  LOW-HIGH на датчике МЕНЯЕТСЯ МНОГОКРАТНО В СЕКУНДУ.  

....

Таким образом, получается, что attachInterrupt работает неправильно! Я то не понял поначалу-почему в Serial постоянно выводится "Shaft stop" -"Shaft start"  - в непрерывном режиме, хотя вал крутится....

собственно, вы неправильно поняли , почему некорректно работает.  По задумке скетча, когда сигнал на датчике МЕНЯЕТСЯ МНОГОКРАТНО В СЕКУНДУ , каждый раз должен просто сбрасываться таймер на 0. поэтому, когда вал крутится , таймер не может дотикать до конца и переменная статус вала при этом  всегда находится в положении true ("вал вращается") . Если импульсы от датчика прекратились, таймер доходит до конца и переменная становится false (вал остановлен). 

может у меня есть ошибки в скетче, а может у вас в аппаратной части, из за этого и косяки. Попробуйте последовать рекомендациям #33. еще в строке 4 можно попробовать значение увеличить, например до 1000 (вдруг вы вал медленно просто крутите)

 

mu_ssina
Offline
Зарегистрирован: 30.08.2013

MaksVV пишет:

собственно, вы неправильно поняли , почему некорректно работает.  По задумке скетча, когда сигнал на датчике МЕНЯЕТСЯ МНОГОКРАТНО В СЕКУНДУ , каждый раз должен просто сбрасываться таймер на 0. поэтому, когда вал крутится , таймер не может дотикать до конца и переменная статус вала при этом  всегда находится в положении true ("вал вращается") . Если импульсы от датчика прекратились, таймер доходит до конца и переменная становится false (вал остановлен). 

может у меня есть ошибки в скетче, а может у вас в аппаратной части, из за этого и косяки. Попробуйте последовать рекомендациям #33. еще в строке 4 можно попробовать значение увеличить, например до 1000 (вдруг вы вал медленно просто крутите)

 

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

mu_ssina
Offline
Зарегистрирован: 30.08.2013

В общем...Всю голову сломал опять-не работал как надо ваш скетч...Неделю его мучал и так и сяк...И заставил работать как надо только что!!!! :-)

Сделал вот что: урезал код до минимума, чтобы просто пока в Serial писало состояние вала-остановлен или работает. То есть, чтобы докопаться до самой сути-в чем ошибка...

Заработало только вот в таком виде: 

//было так:
if ((shaft_state) && (millis() - lasttime > SENSOR_MIN_TIME))


//стало так:
if (millis() - lasttime > SENSOR_MIN_TIME)

Логически(на первый взгляд)-ваше гораздо более верно. Но не работало. А так- сразу заработало! :-)

 

Вот я и думаю-в чем может быть причина...Дребезг контактов? Или логическая ошибка....Пока вот только что обнаружил работоспособную комбинацию-но не успел проанализировать.

sadman41
Offline
Зарегистрирован: 19.10.2016

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

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

Ошибка с этой цифре: 9600
Меняйте на как минимум 115200

mu_ssina
Offline
Зарегистрирован: 30.08.2013

у меня с 9600 и не работало никогда -я об этом выше писал ;-). Кракозябры в serial-е. Стабильно работает на Serial.begin( 2000000 );

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

MaksVV
Offline
Зарегистрирован: 06.08.2015

так ? 

volatile uint32_t lasttime = 0;
volatile bool shaft_state = 1;


#define SENSOR_MIN_TIME 500 // время мс, через которое при отсутствии импульсов от датчика
                            // считается что вал остановлен

void sensor_impulse()
{
lasttime = millis();
 shaft_state = 1; 
}


void setup()
{
Serial.begin(115200);
attachInterrupt(0, sensor_impulse, FALLING);
}

void loop()
{
 detachInterrupt(0);
  if (shaft_state && millis() - lasttime > SENSOR_MIN_TIME){shaft_state = 0;}  
 attachInterrupt(0, sensor_impulse, FALLING);
static bool lastshaft_state = 1;
     
     if (lastshaft_state!=shaft_state)
     {
       if (shaft_state) Serial.println("Shaft start");
       else Serial.println ("Shaft stop");
       lastshaft_state=shaft_state;
     }
}


 

mu_ssina
Offline
Зарегистрирован: 30.08.2013

пишет "ошибка компиляции для платы Arduino Nano".

Сейчас попробую поэкспериментировать с тем кодом, который я привел выше. Если все будет ок по результатам тестов-отпишусь сегодня ;-). Но уже то, что я вижу в serial-е - меня безумно радует! Похоже конец моим 4-х почти уже месячным мытарствам!

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Компилируется:

Цитата:
Скетч использует 1924 байт (13%) памяти устройства. Всего доступно 14336 байт.
Глобальные переменные используют 220 байт (21%) динамической памяти, оставляя 804 байт для локальных переменных. Максимум: 1024 байт.

Arduino Nano v2 (ATmega168)

sadman41
Offline
Зарегистрирован: 19.10.2016

Полагаю, что этого хватит для прекращения массовых мучений?

В железку не заливал. Основной принцип: как только будет зафиксировано, что lastCatchTime перестал "догонять" millis(), значит прерывания не происходят, а следовательно - вал остановился.

#include <util/atomic.h>

const uint8_t alarmPin = 13;
const uint8_t interruptPin = 2; // or 3

const uint32_t sensorTimeout = 500;

volatile uint32_t lastCatchTime;


void sensor_impulse() {
  lastCatchTime = millis();
}

void setup() {
//  Serial.begin(115200);
  pinMode(alarmPin, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(interruptPin), sensor_impulse, FALLING); // or RISING
}

void loop() {
  uint32_t snapCatchTime;

  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    snapCatchTime = lastCatchTime;
  }

  if (millis() - snapCatchTime > sensorTimeout) {
    digitalWrite(alarmPin, HIGH); // No interrupts catched for `sensorTimeout` ms
  } else {
    digitalWrite(alarmPin, LOW);  // All OK
  }
}

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

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

volatile uint16_t tik = 0;

bool shaft_state = 1;

#define SENSOR_TIMOUT 500 // время мс, через которое при отсутствии импульсов от датчика
                          // считается что вал остановлен

void sensor_impulse()
{
tik++;
}

void setup()
{
Serial.begin(115200);
attachInterrupt(0, sensor_impulse, FALLING);
}

void loop()
{
uint32_t currtime = millis();
static uint32_t lasttime = 0;

  if (currtime - lasttime > SENSOR_TIMOUT)
    { 
    detachInterrupt(0);
    if   (tik <= 2) shaft_state = 0;
    else  shaft_state = 1;
    attachInterrupt(0, sensor_impulse, FALLING);
    tik = 0;
    lasttime = currtime;
    }  
 
static bool lastshaft_state = 1;
     
     if (lastshaft_state!=shaft_state)
     {
       if (shaft_state) Serial.println("Shaft start");
       else Serial.println ("Shaft stop");
       lastshaft_state=shaft_state;
     }
}

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

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Для MaksVV: Пытался и предыдущий ваш код и последний перед этим постом...Ошибку выдает. Причем, если в чистую вкладку все залить-проблем нет. В мой код вставляю-глючит...Видимо где то, что то пропустил-голова квадратная под вечер, не понимаю уже...

Вот код в целом:

 



// wired connections

#define HG7881_B_IA 10 // D10 --> Motor B Input A --> MOTOR B +
#define HG7881_B_IB 11 // D11 --> Motor B Input B --> MOTOR B -

// functional connections

#define MOTOR_B_PWM HG7881_B_IA // Motor B PWM Speed
#define MOTOR_B_DIR HG7881_B_IB // Motor B Direction

// the actual values for "fast" and "slow" depend on the motor
#define PWM_SLOW 130  // arbitrary slow speed PWM duty cycle
#define PWM_FAST 250 // arbitrary fast speed PWM duty cycle
#define DIR_DELAY 1000 // brief delay for abrupt motor changes


int hallPin = 2 ; // назначение пина датчика

volatile uint16_t tik = 0;
bool shaft_state = 1;
#define SENSOR_TIMOUT 500 // время мс, через которое при отсутствии импульсов от датчика
                          // считается что вал остановлен
void setup()
{

Serial.begin( 115200);

pinMode( MOTOR_B_DIR, OUTPUT );
pinMode( MOTOR_B_PWM, OUTPUT );
digitalWrite( MOTOR_B_DIR, LOW );
digitalWrite( MOTOR_B_PWM, LOW );
pinMode (hallPin, INPUT);
attachInterrupt(0, sensor_impulse, FALLING);

//Motor_B (2, 1); //метод, запускающий двигатель по часовой стрелке на большой скорости


} //setup



void loop()
{
uint32_t currtime = millis();
static uint32_t lasttime = 0;

  if (currtime - lasttime > SENSOR_TIMOUT)
    { 
    detachInterrupt(0);
    if   (tik <= 2) shaft_state = 0;
    else  shaft_state = 1;
    attachInterrupt(0, sensor_impulse, FALLING);
    tik = 0;
    lasttime = currtime;
    }  
 
static bool lastshaft_state = 1;
     
     if (lastshaft_state!=shaft_state)
     {
       if (shaft_state) Serial.println("Shaft start");
       else Serial.println ("Shaft stop");
       lastshaft_state=shaft_state;
     }
}

void sensor_impulse()
{
tik++;
}

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

я хз все компилируется. переставил обработчик до сетап, так правильней. Может из за этого . Пробуйте код как есть, и скажите как он работает. 

mu_ssina
Offline
Зарегистрирован: 30.08.2013

ок...щас малесь передохну и ближе к полуночи еще буду пробовать...

mu_ssina
Offline
Зарегистрирован: 30.08.2013

Приветствую! Добрался таки до проб...Сегодня все запускается! :-) Работает ваш код! По крайней мере вот этот-#91  :-)

Сейчас буду пробовать другую часть кода(переделывать ваш)...В случае удержания -подождать маленько и включить реверс (метод Motor_B (2, 1) - запускает по часовой стрелке, Motor_B (2, 2)-против часовой).

P.S. Я заметил, что у меня почему то через какое то время начинает глючить IDE.... Перезапуск видимо нужен. Забываю про это и бьюсь, борюсь с труднообъяснимыми ошибками -а там все просто было...