toweroff 1 29 мая, 2012 Опубликовано 29 мая, 2012 · Жалоба ' что это было? и, главное, зачем? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kosta 0 31 мая, 2012 Опубликовано 31 мая, 2012 · Жалоба что это было? и, главное, зачем? приношу свои извинения - сообщение было не слишком информативно, а удалить его никакой возможности нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
udineze 0 31 мая, 2012 Опубликовано 31 мая, 2012 (изменено) · Жалоба понял, что с самого начала сильно заблуждался насчет задержки. посмотрите на вложенный рисунок: имеем объект с запаздыванием, модель и передаточная функция на рисунке. изначальная программа неверна, суть объекта с задержкой в сдвиге поступающего сигнала на величину задержки. то есть: 1. по истечении 20 секунд задержка выключается 2. первые 20 секунд нужно запоминать рассчитанные значения и выводить их по истечению 20 секунд. то есть алгоритм такой: 1.поступает сигнал 2. пропускаем его через регулятор 3. проверяем, если задержка не кончилась, то запоминаем результат если задержка кончилась, то выводим запомненный результат я так понимаю при такте 0.01 и задержке 20 секунд надо запомнить 20/0.01=2000 значений, которые по истечении 20 секунд надо выводить но! пока выводим эти 2000 значений накопится новые 2000 значений еще смущает вопрос: 20 секунд задержка - значит первые 20 секунд система должна выводить на выход 0 и заниматься только запоминанием? еще момент: формирование такта квантования при помощи таймера с прерыванием теряет смысл...но блин, как то его надо формировать ну и вопрос на миллион, как это все реализовать то? массив как то надо делать и сдвигать его, с трудом представляю это стоп! этот алгоритм в подпрограмму обработки прерывания и вставим - и будет мне такт 0,01 подскажите как массив задать так чтоли: dalay[2000]=[0 0 0 0 ... 0] или каждый элемент прописывать dalay[1]=0 dalay[2]=0 ... dalay[2000]=0 Изменено 1 июня, 2012 пользователем 7tudent Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 1 июня, 2012 Опубликовано 1 июня, 2012 · Жалоба я так понимаю при такте 0.01 и задержке 20 секунд надо запомнить 20/0.01=2000 значений, которые по истечении 20 секунд надо выводить стоп! этот алгоритм в подпрограмму обработки прерывания и вставим - и будет мне такт 0,01 Ура. Ещё чуть-чуть - и алгоритм наконец родится! По поводу того, что я говорил о 20000 значений - это я что-то неправильное говорил... Для начала предлагаю обдумать задержку на 0.05 секунд и расписать на бумажке, какие значения запоминаются, а какие - выводятся. Десятка тактов для понимания должно хватить. подскажите как массив задать Учебник языка Си. Классика - Керниган и Ричи (спрашивать в гугле), но это описано в ЛЮБОМ учебнике. Заполнение нулями - либо вызовом memset (см. гугл) либо организацией цикла. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
udineze 0 2 июня, 2012 Опубликовано 2 июня, 2012 · Жалоба переписал #include "lpc214x.h" void TMR_IRQ (void) __irq; int main(void); float xR; // x[k] для 1/R[z]; float yR; // y[k] для 1/R[z]; float yR_1; // y[k-1] для 1/R[z] float yR_2; // y[k-2] для 1/R[z] float xRC; // x[k] для R[z]/C[z] float xRC_1; // x[k-1] для R[z]/C[z] float xRC_2; // x[k-2] для R[z]/C[z] float yRC; // y[k] для R[z]/C[z] float yRC_1; // y[k-1] для R[z]/C[z] float yRC_2; // y[k-2] для R[z]/C[z] float yRC_3; // y[k-3] для R[z]/C[z] float xH; // x[k] для H[z] float yH; // y[k] для H[z] float yH_1; // y[k-1] для H[z] float yH_2; // y[k-2] для H[z] float yHD; // y[k] после звена запаздывания float ADC; // сигнал от АЦП float yHD_ADC; // разность сигналов от АЦП и модели float ySUM; // сигнал обратной связи float delay[2000]; // массив из 2000 значений сигнала для формирования задержки int tau; // количество тактов задержки int main(void) { PINSEL1=0x05080000; xR=0; //задаём начальные значения для переменных yR=0; yR_1=0; yR_2=0; xRC=0; xRC_1=0; xRC_2=0; yRC=0; yRC_1=0; yRC_2=0; yRC_3=0; xH=0; yH=0; yH_1=0; yH_2=0; yHD=0; ADC=0; yHD_ADC=0; ySUM=0; tau=0; delay[2000]={0 0 0 0 0 … 0}; AD0CR=0x00200006; //Включаем АЦП 0 и выбираем 1 и 2 каналы T0TCR=0x00000002; //Сброс регистров таймера T0CTCR=0x00000001; //Выбираем режим таймера T0MCR=0x00000003; //Таймер будет генерировать прерывание при совпадении //значений в регистрах TC и MR0. T0MR0=0x0003A980; //Запись значения при котором должно генерироваться // прерывание а регистр MR0 T0TCR=0x00000001; //Включение таймера VICVectAddr0=TMR_IRQ; //Указатель на функцию обработки прерывания VICVectCnt0=0x00000024; //Установка источника прерывания VICIntEnable=0x00000010; //Разрешение прерывания while (1); return 0; } void TMR_IRQ (void) __irq { T0IR|=0x00000001; //Обнуление регистра прерывания таймера tau++; //переопределение переменных для блока 1/R[z] yR_2=yR_1; // y[k-1]→y[k-2] yR_1=yR; // y[k]→y[k-1] ADGSR=0x01000000; //Запуск АЦ преобразования while ((ADC0STAT&0x00000002)==0); //Ожидание завершения преобразования //сигнала задания xR=(AD0DR1>>6)&0x3FF; //Получение сигнала задания // расчет текущего значения y[k] регулятора 1/R[z] yR=0.0012*xR+1.9913*yR_1-0.9913*yR_2; // расчет входного параметра регулятора R[z]/C[z] xRC=7.6*(yR-0.1316*ySUM); //переопределение переменных для регулятора R[z]/C[z] xRC_2=xRC_1; // x[k-1]→x[k-2] xRС_1=xRC; // x[k]→x[k-1] yRС_3=yRC_2; //y[k-2]→y[k-3] yRС_2=yRC_1; //y[k-1]→y[k-2] yRС_1=yRC; //y[k]→y[k-1] //расчет текущего значения y[k] регулятора R[z]/С[z] yRC=0.0084*xRC-0.0167*xRC_1+0.0084*xRC_2+2.9341*yRC_1-2.8698*yRC_2+0.9357*yRC_3; DACR=yRC<<6; //Запись управляющего сигнала в регистр ЦАП //переопределение переменных для H[z] yH_2=yH_1; //y[k-1]→y[k-2] yH_1=yH; //y[k]→y[k-1] //расчет текущего значения y[k] для H[z] yH=0.0136*yRC+1.992*yH_1-0.9921*yH_2; //организация звена запаздывания if(tau<=1999){ dalay[1999-tau]=yH; ySUM=yH;} else{ yHD=dalay[1998]; for(i=1998;i<=1;i--){ dalay[i]=dalay[i-1];} // организация сдвига массива dalay[0]=yH; ADC=(AD0DR2>>6)&0x3FF; //Получение сигнала с выхода объекта yHD_ADC=ADC-yHD; ySUM=yH+yHD_ADC;} VICVectAddr=0x00000000; //Завершение обработки прерывания } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
esaulenka 7 3 июня, 2012 Опубликовано 3 июня, 2012 · Жалоба Ну вот, уже теплее :-) Некоторые проблемы: - код не компилируется из-за опечаток. Ай-ай, ну надо ж хоть проверять. Благо это можно сделать совершенно бесплатно (и довольно интересно, надо заметить). - таймер и АЦП по-прежнему не работают (описывал проблемы выше). Это тоже можно проверить. - название переменной ADC похоже на название регистра. Это не проблема, это просто некрасиво, на мой взгляд. - вот это неизвестный мне язык: delay[2000]={0 0 0 0 0 … 0}; Инициализацию нулями (если уж хочется) проще сделать в цикле. - алгоритм сдвига вроде б рабочий (один только вопрос: что будет, если tau переполнится?), но гораздо лучше ничего никуда не двигать. Более правильным является алгоритм кольцевого буфера: берём индекс i (можно тау :) ), считываем i-ый элемент (это будет выходом алгоритма), записываем на это же место входное значение. Увеличиваем i на единицу, проверяем, если оно вышло за пределы массива, сбрасываем его в ноль (т.е. в начало массива). Итого при минимальных действиях получаем то же самое поведение - входной сигнал попадёт на выход только после того, как i совершит полный "круг" и второй раз окажется в той же ячейке. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
udineze 0 4 июня, 2012 Опубликовано 4 июня, 2012 · Жалоба Ну вот, уже теплее :-) Некоторые проблемы: - код не компилируется из-за опечаток. Ай-ай, ну надо ж хоть проверять. Благо это можно сделать совершенно бесплатно (и довольно интересно, надо заметить). - таймер и АЦП по-прежнему не работают (описывал проблемы выше). Это тоже можно проверить. - название переменной ADC похоже на название регистра. Это не проблема, это просто некрасиво, на мой взгляд. - вот это неизвестный мне язык: delay[2000]={0 0 0 0 0 … 0}; Инициализацию нулями (если уж хочется) проще сделать в цикле. - алгоритм сдвига вроде б рабочий (один только вопрос: что будет, если tau переполнится?), но гораздо лучше ничего никуда не двигать. Более правильным является алгоритм кольцевого буфера: берём индекс i (можно тау :) ), считываем i-ый элемент (это будет выходом алгоритма), записываем на это же место входное значение. Увеличиваем i на единицу, проверяем, если оно вышло за пределы массива, сбрасываем его в ноль (т.е. в начало массива). Итого при минимальных действиях получаем то же самое поведение - входной сигнал попадёт на выход только после того, как i совершит полный "круг" и второй раз окажется в той же ячейке. так: for(i=0; i<=1999; i++){ delay[i]=0}; переполнение tau: else{ yHD=dalay[1999]; for(i=1999;i<=1;i--){ dalay[i]=dalay[i-1];} // организация сдвига массива dalay[0]=yH; ADC=(AD0DR2>>6)&0x3FF; //Получение сигнала с выхода объекта yHD_ADC=ADC-yHD; ySUM=yH+yHD_ADC; [b]tau--[/b];} насчет другого способа, спасибо, но наверно поздно...пошел печатать) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
toweroff 1 4 июня, 2012 Опубликовано 4 июня, 2012 · Жалоба каждый раз сдвигать 2000 элементов... бррр... ужас какой :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться