Ардуино не правильно вычисляет. (баг?)
- Войдите на сайт для отправки комментариев
Вс, 13/08/2017 - 12:02
Здравствуйте.
При расчете времени поворота синусоиды на 1гр. по формуле: ( t / f ) / 360, где t - 1 сек в микросекундах, f - задаваемая частота в Гц, 360 - период синуса в углах, столкнулся с интересным моментом:
если расчет вести по выделенной формуле, то при задаваемых частотах f < 185 ардуино вычисляет значения верно:

но, если значение задаваемых частот f > 185, то начинается что-то для меня не понятное (должно получиться 14,62, с округлением до 15):

если же расчет вести по формуле, которая закомментирована, то ардуино вычисляет все как положенно и таких глюков не наблюдаю.
Весь код скетча:
byte mask_p = (1 << 7) | (1 << 4) | (1 <<2); //маска пинов фаз 2, 4, 7
const uint8_t deg_max=90, //угол первого максимума
deg=120, //угол сдвига фаз
p_value=75, //длительность 1/4 периода фазы в эл.углах
motor_deg=4;//4 периода синуса = 1 обороту
const uint32_t sec=1000000;//сек в микросек
unsigned long _time, //время работы ардуино
p1_str, p1_stp, p2_str, //время начала и конца
p2_stp, p3_str, p3_stp; //положительного полупериаода фаз
uint16_t f, //частота фазы
deg_val; //1 эл.гр. в мкс
uint8_t p_rise, //угол начала фазы
p_dawn; //угол конца фазы
void setup() {
Serial.begin(9600);
DDRD |= mask_p; //пины 2, 4, 7 OUTPUT
PORTD &= ~mask_p; //пины 2, 4, 7 LOW
f = 190;
_time = micros();
/*deg_val = (sec/f)/360;*/ deg_val = sec/(f*360);
Serial.println(deg_val);
p_rise = 90-p_value;
p_dawn = 90+p_value;
p1_str = _time + deg_val*p_rise;
p1_stp = p1_str + deg_val*p_value*2;
p2_str = _time + deg_val*(p_rise+120);
p2_stp = p2_str + deg_val*p_value*2;
p3_str = _time + deg_val*(p_rise+240);
p3_stp = _time + deg_val*((330+p_value)-360);
}
void loop() {
while (1) {
_time = micros();
if (_time>=p1_str) { //ждем время нарастания фазы 1
PORTD |= (1<<2);
p1_str = p3_str + deg_val*120;}
else {
if (_time>=p3_stp) { //ждем время спада фазы 3
PORTD &= ~(1<<7);
p3_stp = p3_str + deg_val*p_value*2;}
else {
if (_time>=p2_str) { //ждем время нарастания фазы 2
PORTD |= (1<<4);
p2_str = p1_str + deg_val*120;}
else {
if (_time>=p1_stp) { //ждем время спада фазы 1
PORTD &= ~(1<<2);
p1_stp = p1_str + deg_val*p_value*2;}
else {
if (_time>=p3_str) { //ждем время нарастания фазы 3
PORTD |= (1<<7);
p3_str = p2_str + deg_val*120;}
else {
if (_time>=p2_stp) { //ждем время спада фазы 2
PORTD &= ~(1<<4);
p2_stp = p2_str + deg_val*p_value*2;}
}
}
}
}
}
}
}
Ваша f имеет тип uint16_t, произведение f*360 будет такого же типа. Переполнение случилось, и Ваши секунды делятся уже совсем не на то, что Вы думаете.
Не знал о такой особенности, спасибо
Мне Ваш комментарий очень помог в дальнейших расчетах =) еще раз спасибо
Не по теме, но ник больно уж у автора прикольный.
https://ru.wikipedia.org/wiki/Викернес,_Варг
Я уже думал о манхейм забыли =) да и ссылку тогда уж на Эйстейна Ошета надо был давать ;-)