Замер скорости

Lightning_Eva
Lightning_Eva аватар
Offline
Зарегистрирован: 04.06.2019

Всем привет! Помогите, пожалуйста с кодом. Делаю стенд, точнее пишу код для этого стенда. Стенд представляет собой колесо с магнитами и датчик Холла. Колесо крутится и программа выдает скорость вращения колеса.

//Speedometr


unsigned long previousMillis = 0; 
unsigned long currentMillis = 0;
volatile float millis_temp = 0.0;  
volatile float frequency = 0.0;      //частота импульсов 
volatile float Time1 = 0.0; 
volatile float Time2 = 0.0;
volatile float speed = 0.00;         //скорость

int timeout = 1400;                       // (миллисекунд) максимальное время ожидания
unsigned int Magnets = 2;            // Количество магнитов на колесе
unsigned int Distance = 204;         // Расстояние между магнитами

void setup() 
  {
  Serial.begin(9600);
  pinMode(INT0, INPUT); 
  attachInterrupt(INT0, sp_metr, RISING); //INT0
   }

void loop()
   {
         if((millis() - millis_temp) > timeout) //Задержка до обнуления
           { 
         frequency=0;
           }
           else 
           {  
        frequency = (1000 / Time1); //Частота, Гц
           }
           
    speed = (frequency / Magnets)*(PI * Distance / 1000); // Вычисление скорости вращения     
   
    Serial.print("millis_temp = ");
    Serial.print(millis_temp);
    Serial.print("  Time1 = ");
    Serial.print(Time1);
    Serial.print("  Time2 = ");
    Serial.print(Time2);
    Serial.print("  frequency = ");
    Serial.print(frequency);
    Serial.print("  speed = ");
    Serial.println(speed);
    }
    
void sp_metr() //Обработка прерывания
    {                 
    
    Time2 = millis();
    Time1 =  Time2 - millis_temp;
    millis_temp = Time2; 
   
    }

В результате получается вот что:

millis_temp = 86177.00  Time1 = 160.00  Time2 = 86177.00  frequency = 6.25  speed = 2.00
millis_temp = 86177.00  Time1 = 159.00  Time2 = 86336.00  frequency = 6.25  speed = 2.00
millis_temp = 86336.00  Time1 = 159.00  Time2 = 86336.00  frequency = 6.29  speed = 2.02
millis_temp = 86497.00  Time1 = 161.00  Time2 = 86497.00  frequency = 6.21  speed = 1.99
millis_temp = 86497.00  Time1 = 161.00  Time2 = 86497.00  frequency = 6.21  speed = 1.99
millis_temp = 86656.00  Time1 = 159.00  Time2 = 86656.00  frequency = 6.29  speed = 2.02
millis_temp = 86656.00  Time1 = 0.00  Time2 = 86816.00  frequency = 6.29  speed = 2.02
millis_temp = 86816.00  Time1 = 0.00  Time2 = 86816.00  frequency = inf  speed = inf
millis_temp = 86975.00  Time1 = 0.00  Time2 = 86975.00  frequency = inf  speed = inf
millis_temp = 86975.00  Time1 = 0.00  Time2 = 86975.00  frequency = inf  speed = inf
millis_temp = 87136.00  Time1 = 161.00  Time2 = 87136.00  frequency = 6.21  speed = 1.99
millis_temp = 87136.00  Time1 = 161.00  Time2 = 87136.00  frequency = 6.21  speed = 1.99
millis_temp = 87294.00  Time1 = 158.00  Time2 = 87294.00  frequency = 6.33  speed = 2.03
millis_temp = 87294.00  Time1 = 161.00  Time2 = 87455.00  frequency = 6.33  speed = 2.03

Почему-то метка во времени оказывается больше текущего времени.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Lightning_Eva пишет:

метка во времени оказывается больше текущего времени.

Так патентуй машину времени, пока кто-нить не стырил.

А код, можно словами, внятно пояснить что там и зачем делается?

anatoli_nik
Offline
Зарегистрирован: 17.01.2019

Вот код который я использовал для замера скорости вращения PMSM двигателя стиральной машинки LG

#define N 1U	//количество магнитов
#define True	0xFF
#define False 	0
volatile char flagTim1Ovf, motorRun;
volatile unsigned int speedCounter;
unsigned int speed;
int main()
{
	//***********************INIT PCINT 0 ***//тут висит датчик холла
	PCICR = (1<<PCIE0);
	PCMSK0 = (1<<PCINT0);
	//*************************INIT Timer 1 измерение частоты вращения*
	//prescaller 256, normal mode, overflow interrupt, 1 tic = 1/62500sec
        //переполнение через 1 с
	TCCR1A = 0;
	TCCR1B = (1<<CS12);	 
	TIMSK1 = (1<<TOIE1);
	//***************************************************************
   while(1)
  {
	ifmotorRun
	{
		spead=(3750000UL/N)/speedCounter;    //расчет частоты вращения об/мин
	}
  }
return(0);
}

//прерывания********************************************
ISR(PCINT0_vect)		//обработчик перрывания датчика скорости
 {	 
	 
		 if((!flagTim1Ovf)&&(PINB&(1<<0)))	//меряем по высокому уровню
		 {
			 speedCounter = TCNT1;
			 TCNT1 = 0;
			 motorRun = True;
		 }
		 else
		 {
			 flagTim1Ovf = False;
			 motorRun = False;
		 }
	
 }
 ISR(TIMER1_OVF_vect)	//если будет прерывание значит мотор стоит
 {
	flagTim1Ovf = True; 
 }

 

Pyotr
Offline
Зарегистрирован: 12.03.2014

"...Почему-то метка во времени оказывается больше текущего времени."

Происходит прерывание пока делаются расчеты и вывод в сериал.

 

Lightning_Eva
Lightning_Eva аватар
Offline
Зарегистрирован: 04.06.2019

Замеряется время между прерываниями, но основании этого вычисляется частота вращение и из нее уже скорость.

Lightning_Eva
Lightning_Eva аватар
Offline
Зарегистрирован: 04.06.2019

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

Lightning_Eva
Lightning_Eva аватар
Offline
Зарегистрирован: 04.06.2019

Ох! Тут так просто точно не разобраться..))

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Lightning_Eva пишет:

Ох! Тут так просто точно не разобраться..))

Читайте про атомарное чтение: https://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html

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

Не совсем понятно, правда, зачем делать МК и себе плохо, закидывая время выполнения во float...

Schwarz78
Offline
Зарегистрирован: 19.01.2019

И ещё деление на ноль, не все согласны, что нельзя, но результат врядли предсказуем. Хотя 0.0 и не совсем ноль, скорее всего. ТС надо определиться с типами, он(а) явно тут забил.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Schwarz78 пишет:

И ещё деление на ноль, не все согласны, что нельзя, но результат врядли предсказуем. Хотя 0.0 и не совсем ноль, скорее всего. ТС надо определиться с типами, он(а) явно тут забил.

О! Не я один заметил, что ТС некоторые текстовые обороты пишет как он, а некоторые как она )))

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Lightning_Eva пишет:

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

Вам правильное решение уже привели, делать не на миллис, а на таймере...

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

Lightning_Eva пишет:

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

Вообще-то очень странно во время обработки прерывания другие прерывания должны быть автоматически запрещены до окончания обработчика. Возможно проблема с тем что для времени сохраняется во флоат.

А на какой ардуине все это делается?

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

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

ua6em пишет:

Вам правильное решение уже привели, делать не на миллис, а на таймере...

А какая разница? Миллис тоже использует таймер. Такие короткие прерывания с интервалом в более 100 мс на работу millis не влияют.  Если точности в 1 одну миллисикунду достаточно, то большого смысла работать напрямую с таймерами нет.

Schwarz78
Offline
Зарегистрирован: 19.01.2019

asam пишет:

Вообще-то очень странно во время обработки прерывания другие прерывания должны быть автоматически запрещены до окончания обработчика. Возможно проблема с тем что для времени сохраняется во флоат.

А на какой ардуине все это делается?

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

Если приоритеты одинаковы - да.

Не важно.

Если что-то сравниваете - позаботьтесь о типизации. Сравнивать float например с целым нулём - некорректно, как и сравнивать целое с нецелым. Девушке можно простить непонимание арифметики, мальчику - нельзя. Как и делить на Time1, которое инициализировано 0.0.

Ну, и что такое infinity тоже желательно знать.

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

Schwarz78 пишет:

asam пишет:

Вообще-то очень странно во время обработки прерывания другие прерывания должны быть автоматически запрещены до окончания обработчика. Возможно проблема с тем что для времени сохраняется во флоат.

А на какой ардуине все это делается?

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

Если приоритеты одинаковы - да.

Нет. Начнем с того что у AVR нету прерываний с одинаковым приоритетом. Все разные. При любом прерывании запрещаются все прерывания. Из даташита - When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. 

Цитата:
Не важно.

Важно. У ардуин с не AVR контроллером прерывания обслуживаются по другому (STP32, ESP etc)

Цитата:
Если что-то сравниваете - позаботьтесь о типизации. Сравнивать float например с целым нулём - некорректно, как и сравнивать целое с нецелым. Девушке можно простить непонимание арифметики, мальчику - нельзя. Как и делить на Time1, которое инициализировано 0.0.

Ну, и что такое infinity тоже желательно знать.

Это вообще как относится к тому что я писал?

 

Schwarz78
Offline
Зарегистрирован: 19.01.2019

Всегда надо смотреть на оранжевые сообщения компилятора. Он обычно на неявные приведения типов именно так и реагирует. Это предупреждение (warning). И это повод для беспокойства. Идеально - когда компилятор молчит.

Schwarz78
Offline
Зарегистрирован: 19.01.2019

asam пишет:

Нет. Начнем с того что у AVR нету прерываний с одинаковым приоритетом. Все разные. При любом прерывании запрещаются все прерывания. Из даташита - When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. 

Но потом прерывание будет выполнено, не так ли? То есть прерывания с одинаковым приоритетом откладывают друг-друга, а прерывания с более высоким приоритетом могут прерывать прерывания с более низким, но потом всё равно будут выполнены?

asam пишет:

Важно. У ардуин с не AVR контроллером прерывания обслуживаются по другому (STP32, ESP etc)

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

А последнее - вы не смотрели код, который вам предложили, либо ничего в коде не понимаете.

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

Schwarz78 пишет:

asam пишет:

Нет. Начнем с того что у AVR нету прерываний с одинаковым приоритетом. Все разные. При любом прерывании запрещаются все прерывания. Из даташита - When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. 

Но потом прерывание будет выполнено, не так ли? То есть прерывания с одинаковым приоритетом откладывают друг-друга, а прерывания с более высоким приоритетом могут прерывать прерывания с более низким, но потом всё равно будут выполнены?

Еще раз для тех кто в танке - у AVR нету прерываний с одинаковым приоритетом. Если началась обработка прерывания, то все остальные запрещены. И не важно какой у них приоритет. Пока текущее прерывание не закончится (или внутри него программистом явно не будут разрешены глобальные прерывания) никаие другие прерывания его прервать не смогут. Приориет определят какие прерывания будут обслужены первыми если события произошли одновременно или в то время пока прерывания были запрещены. 

Цитата:
Цитата:
Важно. У ардуин с не AVR контроллером прерывания обслуживаются по другому (STP32, ESP etc)

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

Любезный, вы будете удивлены, но даже "родные" платы от Ардуино базируются не только на АВР, а уж какое разнообразие поддерживает среда Ардуино.... В том числи и на STM32 и на ESP и другие. 

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

Цитата:
А последнее - вы не смотрели код, который вам предложили, либо ничего в коде не понимаете.

Мне никакого кода не предлагали. 

nik182
Offline
Зарегистрирован: 04.05.2015

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

Schwarz78
Offline
Зарегистрирован: 19.01.2019

asam пишет:

Еще раз для тех кто в танке - у AVR нету прерываний с одинаковым приоритетом. Если началась обработка прерывания, то все остальные запрещены. И не важно какой у них приоритет. Пока текущее прерывание не закончится (или внутри него программистом явно не будут разрешены глобальные прерывания) никаие другие прерывания его прервать не смогут. Приориет определят какие прерывания будут обслужены первыми если события произошли одновременно или в то время пока прерывания были запрещены. 

Любезный, вы будете удивлены, но даже "родные" платы от Ардуино базируются не только на АВР, а уж какое разнообразие поддерживает среда Ардуино.... В том числи и на STM32 и на ESP и другие. 

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

Да я тут даже и не спорил. Если прерывание возникло во время другого прерывания - оно выполнится по завершении того прерывания, вот и всё. И этот приоритет - полная херня, с моей точки зрения, поскольку возникновение двух аппаратных прерываний одновременно - 1/2 в хренотысячной степени вероятность.

Да что мы друг-другу голову морочим. Я не знаю, может у AVR не так, но у 51-х контроллеров были вложенные прерывания, одно могло прервать другое (правда не знаю, зачем). У 86-х вроде тоже.

Любезный мой, я более 20 лет занимаюсь эмбеддингом профессионально, и Ардуино мне просто нравится.

И расскажите, а лучше напишите статью про контроллеры прерываний в разных микроконтроллерах. Вот это будет интересно. А то нам и не представить.

Schwarz78
Offline
Зарегистрирован: 19.01.2019

nik182 пишет:

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

Ну вот ведь. И во всех контроллерах так, зачем делать по-другому?

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

nik182 пишет:

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

Если это ответ на мой пост #18 так я же ровно то же самое и написал. 

Schwarz78
Offline
Зарегистрирован: 19.01.2019

asam пишет:

Если это ответ на мой пост #18 так я же ровно то же самое и написал. 

Прочтите себя, и удостоверьтесь что нет. Я полагаю это не потому, что вы не понимали. Просто неправильно выразились.

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

Schwarz78 пишет:

Прочтите себя, и удостоверьтесь что нет. Я полагаю это не потому, что вы не понимали. Просто неправильно выразились.

Перечитал свое

 

Цитата:
Если началась обработка прерывания, то все остальные запрещены. И не важно какой у них приоритет. Пока текущее прерывание не закончится (или внутри него программистом явно не будут разрешены глобальные прерывания) никаие другие прерывания его прервать не смогут. Приориет определят какие прерывания будут обслужены первыми если события произошли одновременно или в то время пока прерывания были запрещены.

Перечитал Ника

Цитата:
Прерывания в avr могут прервать другое прерывание, если ему руками это разрешить, и приоритет здесь вообще не при делах. После прерывания, через 1 такт будет вызвано стоящее в очереди прерывание с наибольшем приоритетом и так далее, пока очередь прерываний не кончится.

 

Принципиальных отличий не нашел. Может поясните вашу точку зрения?

 

Schwarz78
Offline
Зарегистрирован: 19.01.2019

asam пишет:

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

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

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

Schwarz78 пишет:

 И этот приоритет - полная херня, с моей точки зрения, поскольку возникновение двух аппаратных прерываний одновременно - 1/2 в хренотысячной степени вероятность.

С точки зрения микроконтроллера "одновременно" это в течении одного такта. Что для всяких Ун и Нан составляет 62 наносекунды для 16МГц и 125 наносекунд для 8МГц. И вероятность что два события произойдут в этот интервал хоть и не очень велика, но намного выше "1/2 в хренотысячной степени" . И это вполне случаемое событие. Плюс если события вызывающие прерывания случились когда прерывания запрещены, а за это время могут произойти много таких событий,  то они после разрешения будут обслуживаться в порядке приоритета.

Цитата:
Да что мы друг-другу голову морочим. Я не знаю, может у AVR не так, но у 51-х контроллеров были вложенные прерывания, одно могло прервать другое (правда не знаю, зачем). У 86-х вроде тоже.

Любезный мой, я более 20 лет занимаюсь эмбеддингом профессионально, и Ардуино мне просто нравится.

А вот АВР это по другому. Что же это вы, дорогой мой, за 20 лет работы профессионально в эмбеддед не развили приывычку читать даташиты? 

 

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

Schwarz78 пишет:

asam пишет:

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

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

Похоже вы просто читать не умеете. Где там указано про "Прерывание с более высоким приоритетом прервёт ваше прерывание" ? И вообще посмотрите даташит наконец

When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. The user software can write logic one to the I-bit to enable nested interrupts. All enabled interrupts can then interrupt the current interrupt routine. The I-bit is automatically set when a Return from Interrupt instruction – RETI – is executed. There are basically two types of interrupts. The first type is triggered by an event that sets the Interrupt Flag. For these interrupts, the Program Counter is vectored to the actual Interrupt Vector in order to execute the interrupt handling routine, and hardware clears the corresponding Interrupt Flag. Interrupt Flags can also be cleared by writing a logic one to the flag bit position(s) to be cleared. If an interrupt condition occurs while the corresponding interrupt enable bit is cleared, the Interrupt Flag will be set and remembered until the interrupt is enabled, or the flag is cleared by software. Similarly, if one or more interrupt conditions occur while the Global Interrupt Enable bit is cleared, the corresponding Interrupt Flag(s) will be set and remembered until the Global Interrupt Enable bit is set, and will then be executed by order of priority. The second type of interrupts will trigger as long as the interrupt condition is present. These interrupts do not necessarily have Interrupt Flags. If the interrupt condition disappears before the interrupt is enabled, the interrupt will not be triggered. When the AVR exits from an interrupt, it will always retur

Schwarz78
Offline
Зарегистрирован: 19.01.2019

asam пишет:

С точки зрения микроконтроллера "одновременно" это в течении одного такта. Что для всяких Ун и Нан составляет 62 наносекунды для 16МГц и 125 наносекунд для 8МГц. И вероятность что два события произойдут в этот интервал хоть и не очень велика, но намного выше "1/2 в хренотысячной степени" . И это вполне случаемое событие. Плюс если события вызывающие прерывания случились когда прерывания запрещены, а за это время могут произойти много таких событий,  то они после разрешения будут обслуживаться в порядке приоритета.

А вот АВР это по другому. Что же это вы, дорогой мой, за 20 лет работы профессионально в эмбеддед не развили приывычку читать даташиты? 

Всё это мне известно, но на практике пользоваться таблицей приоритетов прерываний не приходилось почему-то. Боюсь, потому что она бесполезна.

Каюсь, даташиты читаю лишь по мере необходимости. Я был неправ, по умолчанию вложенные прерывания запрещены: "The user software can write logic one to the I-bit to enable nested interrupts". Но они есть, и об этом вы не упомянули.

Дело в том, что я никогда не программировал AVR, а вы, видимо, профессионал. И вы не знали про nested interrupts.

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

Schwarz78 пишет:

Всё это мне известно, но на практике пользоваться таблицей приоритетов прерываний не приходилось почему-то. Боюсь, потому что она бесполезна.

Странно слышать это от человека с "20 летним опытом в эмбеддед"

Цитата:
Я был неправ, по умолчанию вложенные прерывания запрещены: "The user software can write logic one to the I-bit to enable nested interrupts". Но они есть, и об этом вы не упомянули.

Я не забыл : 

Цитата:
Пока текущее прерывание не закончится (или внутри него программистом явно не будут разрешены глобальные прерывания) никаие другие прерывания его прервать не смогут.

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

 

Schwarz78
Offline
Зарегистрирован: 19.01.2019

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

Schwarz78
Offline
Зарегистрирован: 19.01.2019

asam пишет:

Странно слышать это от человека с "20 летним опытом в эмбеддед"

Подскажите, как она может пригодиться? И "эмбеддед" слишком ваше поколение, я тупо разрабатывал микроконтроллерные системы.

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

Schwarz78 пишет:

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

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

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

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

Schwarz78 пишет:

Подскажите, как она может пригодиться? И "эмбеддед" слишком ваше поколение, я тупо разрабатывал микроконтроллерные системы.

1 Как может пригодится зависит от много. Давайте хоть с типом контроллера определимся. 

2. Про " я более 20 лет занимаюсь эмбеддингом " это не я писал

3. Интересно, а к какому поколению вы меня относите?

4 Насчет "тупо разрабатывал" это я уже понял.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

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

Lightning_Eva
Lightning_Eva аватар
Offline
Зарегистрирован: 04.06.2019

Всем спасибо за ответы.

Arduino NANO.

Получился такой код:

//Speedometr

unsigned long millis_temp = 0;  
unsigned long Time1 = 0; 
unsigned long Time2 = 0;

unsigned long frequency = 0;         //частота импульсов 
unsigned long speed = 0;             //скорость
unsigned int timeout = 1600;         // (миллисекунд) максимальное время ожидания
unsigned int Magnets = 2;            // Количество магнитов на колесе
unsigned int Distance = 204;         // Расстояние между магнитами

volatile float speed_fl = 0.00;      //скорость float


void setup() 
  {
  Serial.begin(9600);
  pinMode(INT0, INPUT); 
  attachInterrupt(INT0, sp_metr, RISING); //INT0
   }

void loop()
   {
         if((millis() - millis_temp) > timeout) //Задержка до обнуления
           { 
            frequency=0;
           }
           else 
           {  
             if(!Time1 == 0)
               {
                frequency = (100000 / Time1); //Частота, Гц
               }
           }
       
    speed = ( (frequency * 10) / Magnets)*((314 * Distance)) / 1000000; // Вычисление скорости вращения      
    speed_fl = speed / 100.0;

    Serial.print("millis_temp = ");
    Serial.print(millis_temp);
    Serial.print("  Time1 = ");
    Serial.print(Time1);
    Serial.print("  Time2 = ");
    Serial.print(Time2);
    Serial.print("  frequency = ");
    Serial.print(frequency);
    Serial.print("  speed = ");
    Serial.print(speed);
    Serial.print("  speed_fl = ");
    Serial.println(speed_fl);
  }
    
void sp_metr() //Обработка прерывания
    {                 
    cli();
    Time2 = millis();
    Time1 = Time2 - millis_temp;
    millis_temp = Time2; 
    sei(); 
    }

теперь работает, но из-за неидеальности расположения магнитов данные скорости "плавают".

millis_temp = 396607  Time1 = 97  Time2 = 396607  frequency = 1030  speed = 329  speed_fl = 3.29
millis_temp = 396704  Time1 = 97  Time2 = 396704  frequency = 1030  speed = 329  speed_fl = 3.29
millis_temp = 396802  Time1 = 98  Time2 = 396898  frequency = 1020  speed = 326  speed_fl = 3.26
millis_temp = 396898  Time1 = 96  Time2 = 396996  frequency = 1041  speed = 333  speed_fl = 3.33
millis_temp = 396996  Time1 = 98  Time2 = 397092  frequency = 1020  speed = 326  speed_fl = 3.26
millis_temp = 397092  Time1 = 98  Time2 = 397190  frequency = 1041  speed = 333  speed_fl = 3.33
millis_temp = 397190  Time1 = 97  Time2 = 397287  frequency = 1020  speed = 326  speed_fl = 3.26
millis_temp = 397287  Time1 = 98  Time2 = 397385  frequency = 1030  speed = 329  speed_fl = 3.29
millis_temp = 397385  Time1 = 98  Time2 = 397483  frequency = 1020  speed = 326  speed_fl = 3.26
millis_temp = 397580  Time1 = 97  Time2 = 397580  frequency = 1020  speed = 326  speed_fl = 3.26
millis_temp = 397677  Time1 = 97  Time2 = 397677  frequency = 1030  speed = 329  speed_fl = 3.29
millis_temp = 397775  Time1 = 98  Time2 = 397775  frequency = 1030  speed = 329  speed_fl = 3.29

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

Pyotr
Offline
Зарегистрирован: 12.03.2014

Думаю, что все расчеты нужно делать когда пройдёт таймаут и дождетесь четного импульса == полное количество оборотов.
Снова замерить миллис и делать расчеты.

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

Атомизация чтения неправильно применена. Обработчик прерывания сам по себе атомарен, а вот loop() - нет. ATOMIC_BLOCK нужен именно там.

Всё, что изменяется в обработчике, должно быть volatile. 

Lightning_Eva
Lightning_Eva аватар
Offline
Зарегистрирован: 04.06.2019

Производить расчет в обработчике прерывания?

Pyotr
Offline
Зарегистрирован: 12.03.2014

Lightning_Eva пишет:

Производить расчет в обработчике прерывания?

Нет. В обработчике запомнить миллис при получении четного импульса и установить флаг, чтоб в лупе неторопливо все посчитать.

Lightning_Eva
Lightning_Eva аватар
Offline
Зарегистрирован: 04.06.2019

Получится как один магнит ( сейчас их два). А если четыре или семь? С одним магнитом и так все работает. Но нам надо больше.))

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

Lightning_Eva пишет:

Получится как один магнит ( сейчас их два).

Это плохо? На выходе имеете полный оборот, а не часть его.

 

Lightning_Eva пишет:

А если четыре или семь? С одним магнитом и так все работает. Но нам надо больше.))

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

Если не скорость невелика, то, то обработчик можно изобразить так:

volatile uint8_t interruptCount = 0x00;
const uint8_t magnitsNumber  = 7;
...
void sp_metr() {                  
  interruptCount++;
  if (interruptCount < magnitsNumber )  { return; } // ничего не делаем, пока оборот не завершён
  // В противном случае начинаем счёт сначала и занимаемся с millis()
  interruptCount = 0x00;
  Time2 = millis();
  ...
 }

В лупе, если будет приделана кнопка "Пуск/Останов", interruptCount обнулять, чтобы начинать счёт с начала круга.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Садман! А остальные магниты тогда зачем?

я бы делал на таймерах, там они как раз потребуются )))

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

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Может Ева знает?

Schwarz78
Offline
Зарегистрирован: 19.01.2019

ua6em пишет:

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

Согласен, приношу свои извинения ТС, повёлся на бой с военом.

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

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

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

ЕвгенийП пишет:

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

ТС считает, что расстояние между магнитами, если мерять по и против часовой стрелке, разное. В итоге если считать скорость\частоту по пол-оборота, то она слегка плавает в зависимости от того четный это или нечетный полуоборот.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Т.е. расстояния неодинаковы? А одинаковыми никак нельзя сделать?

Lightning_Eva
Lightning_Eva аватар
Offline
Зарегистрирован: 04.06.2019

Ворота пишет:

Т.е. расстояния неодинаковы? А одинаковыми никак нельзя сделать?

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

Lightning_Eva
Lightning_Eva аватар
Offline
Зарегистрирован: 04.06.2019

ЕвгенийП пишет:

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

Да, об этом и идет речь.