генерация значений от 0 до 360 каждые 10 секунд
- Войдите на сайт для отправки комментариев
Ср, 28/05/2014 - 20:11
Есть необходимость в генерации значений от 0 до 360 за 10 секунд и заново. Задержки и ++ не вариант т.к. тормозится вся программа. пробовал с привязкой к переменной millis();
void loop()
{
time = millis();
if(time%100 == 0)
{
alfa_grad = alfa_grad + 3.6;
}
if( time%10000 == 0) alfa_grad = 0;
где альфа это угол. Не получается, значения плавают, через монитор порта видно что даже не от 0 до 9 значения в последовательностях. Что можно исправить, или другие способы реализации?
Не очень понял задачу, если нужно задать значение с высокой точностью интервала, можно воспользоваться прерыванием настроив соответствующий таймер, например:
void setup(){ TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; OCR1A = 15624; TCCR1B |= (1 << WGM12); TCCR1B |= (1 << CS10); TCCR1B |= (0 << CS11); TCCR1B |= (1 << CS12); TIMSK1 |= (1 << OCIE1A); } ISR(TIMER1_COMPA_vect){ if(alfa_grad != 360){ alfa_grad += 3.6; }else{ alfa_grad = 0; } } viod loop(){ //do something; }Только нужно правильно установить регистр TCCR1B, и прескалер OCR1A, а то я сейчас на глаз посчитал
Не очень понял задачу, если нужно задать значение с высокой точностью интервала, можно воспользоваться прерыванием настроив соответствующий таймер, например:
void setup(){ TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; OCR1A = 15624; TCCR1B |= (1 << WGM12); TCCR1B |= (1 << CS10); TCCR1B |= (0 << CS11); TCCR1B |= (1 << CS12); TIMSK1 |= (1 << OCIE1A); } ISR(TIMER1_COMPA_vect){ if(alfa_grad != 360){ alfa_grad += 3.6; }else{ alfa_grad = 0; } } viod loop(){ //do something; }Только нужно правильно установить регистр TCCR1B, и прескалер OCR1A, а то я сейчас на глаз посчитал
не могу найти понятного руководства по их настройке.
Вы взяли OCR1A = 15624 это столько отсчетов пройдет за 10 секунд и таймер обнулится, верно?
а растет tcnt1?
как проводить рассчеты?
15624 это 1 секунда, расчет: 16000000 (16MHz частота) / 1024 (прескалер)/ 15625 (размер счетчика)
TCNT1 это регистр счетчика - да.
Я так понял, что каждую секунду нужно увеличивать значение на +3.6 в течении 10 секунд, затем сбрасывать и по новой.
да, верно
Я там в первом сообщении допустил ошибку, нужно поменять местами слова "регистр" и "прескалер". Прескалер задается битами CS10,CS11,CS12 в регистре TCCR1B, а регистр OCR1A это значение по которому происходит прерывание.
спасибо, я догадался когда начал гуглить. Только что то не хочет обнуляться, дальше гонит за 360. Ошибок что-то не видно
alfa_grad у вас глобальная volatile?
#include <EEPROM.h>/ byte x = 0; byte x_1 = 0; byte x_2 = 0; int ramX_1 = 0; int ramX_2 = 0; int ramX = 0; int modul; int modul_1; int modul_2; volatile float alfa_grad = 0; float alfa_rad = 0; int myArray[256] = {127,130,133,136,140,143,146,149,152,155,158, 161,164,167,170,173,176,179,182,185,187,190, 193,195,198,201,203,206,208,211,213,215,217, 220,222,224,226,228,230,232,233,235,237,238, 240,241,242,244,245,246,247,248,249,250,251, 252,252,253,253,254,254,254,254,254,254,254, 254,254,254,253,253,252,252,251,250,250,249, 248,247,246,244,243,242,240,239,237,236,234, 232,231,229,227,225,223,221,219,216,214,212, 209,207,204,202,199,197,194,191,189,186,183, 180,177,175,172,169,166,163,160,157,154,150, 147,144,141,138,135,132,129,125,122,119,116, 113,110,107,104,100,97,94,91,88,85,82,79,77, 74,71,68,65,63,60,57,55,52,50,47,45,42,40,38, 35,33,31,29,27,25,23,22,20,18,17,15,14,12,11, 10,8,7,6,5,4,4,3,2,2,1,1,0,0,0,0,0,0,0,0,0,0, 1,1,2,2,3,4,5,6,7,8,9,10,12,13,14,16,17,19,21, 22,24,26,28,30,32,34,37,39,41,43,46,48,51,53, 56,59,61,64,67,69,72,75,78,81,84,87,90,93,96, 99,102,105,108,111,114,118,121,124,127}; void setup(){ pinMode(3, OUTPUT); //pcint19 pinMode(5, OUTPUT); //pcint21 pinMode(6, OUTPUT); //pcint22 Serial.begin(115200); // connect to the serial port Serial.println("PWM Test"); TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; OCR1A = 15625; // Верхняя граница счета. Диапазон от 0 до 65535 // Частота прерываний будет = Fclk/(N*(1+OCR1A)) // где N - коэф. предделителя (1, 8, 64, 256 или 1024) TCCR1B |= (1 << WGM12); TCCR1B |= (1 << CS10); TCCR1B |= (0 << CS11); TCCR1B |= (1 << CS12); TIMSK1 |= (1 << OCIE1A); // Разрешить прерывание по совпадению } ISR(TIMER1_COMPA_vect){ if(alfa_grad != 360) { alfa_grad += 3.6; } else { alfa_grad = 0; } } void loop() { alfa_rad = (float)alfa_grad*3.14/180; if (x <= 255) { x_1 = x + 85; x_2 = x + 170; analogWrite(3, myArray[x]); ramX = myArray[x]-127; ramX_1 = myArray[x_1]-127; ramX_2 = myArray[x_2]-127; modul = map (((float)ramX*sin(alfa_rad))*100,-12700,12700,-127,127) + 127; modul_1 = map ((ramX_1*sin(alfa_rad))*100,-12700,12700,-127,127) + 127; modul_2 = map ((ramX_2*sin(alfa_rad))*100,-12700,12700,-127,127) + 127; analogWrite (3,modul); analogWrite (5,modul_1); analogWrite (6,modul_2); x++; Serial.print(modul); Serial.print(" "); Serial.print(modul_1); Serial.print(" "); Serial.println(alfa_grad); } else x=0; }весь код, даже когда исправил пишет значения выше 360
Условие сброса в прерывании нужно переписать, у вас в loop значние a_r меняется произвольно.
Или в loop не нужно переопределять a_r, а использовать для вычислений другую переменную.
И учтите, что loop будет выполнятся со скоростью исполнения кода, а прерывание вызываться строго каждую 1 секунду. То ли это, что вы хотели получить?
это как раз то, что надо. Этот код для эмуляции синусоиды. а так на вход напряжение приходит и оцифровывается и скорость там ни к чему.
не добился я пока эффекта
альфа нужен чтобы промодулировать синусоиду
Ага, я не увидел разницы между alfa_rad и alfa_grad. Теперь вижу что с этим все впорядке.
Думаю тут дело в типе float, который не будет равен точно 360. Попробуйте привести типы перед сравнением, если не поможет можно попробовать округлить или отбросить дробную часть или сравнить не точно а > или <.
никакими операторами не обнуляется, либо пишет нули вообще
Хмм, ну так то полюбому должно сработать: if(alfa_grad > 359 && alfa_grad < 361)... да и даже if(alfa_grad > 359) будет достаточно
а не может ли быть дело в том что обработчик запускается и выполняется бесконечно, не может снуляться? луп осуществляет циклы
Прерывание прерывает исполнение loop на время исполнения обработчика, т.е. если бы обработчки выполнялся бесконечно, то весь loop бы просто завис
отставить,
alfa_grad += 3.6; if(alfa_grad > 359 && alfa_grad < 361) {alfa_grad = 0;}дало эффект.
Бесконечно благодарен за помощь. Знаний как видите маловато еще у меня)
не исключено что по времени это дольше чем 10 секунд, проверю завтра на реальном железе с осциллографом