Последние записи
- Преобразовать массив байт в вещественное число (single)
- TChromium (CEF3), сохранение изображений
- Как в Delphi XE обнулить таймер?
- Изменить цвет шрифта TextBox на форме
- Ресайз PNG без потери прозрачности
- Вывод на печать графического файла
- Взаимодействие через командную строку
- Перенести программу из Delphi в Lazarus
- Определить текущую ОС
- Автоматическая смена языка (раскладки клавиатуры)
Интенсив по Python: Работа с API и фреймворками 24-26 ИЮНЯ 2022. Знаете Python, но хотите расширить свои навыки?
Slurm подготовили для вас особенный продукт! Оставить заявку по ссылке - https://slurm.club/3MeqNEk
Online-курс Java с оплатой после трудоустройства. Каждый выпускник получает предложение о работе
И зарплату на 30% выше ожидаемой, подробнее на сайте академии, ссылка - ttps://clck.ru/fCrQw
26th
Авг
Энкодер датчика pdf на плис. Часть 2
Posted by Chas under Журнал, Статьи
Итак, сегодня мы с вами продолжим наш материал по промышленной автоматизации, рассмотрим реализацию алгоритма энкодера на ПЛИС, особенности прошивки модулей Faswell UNIOxx-5 и создадим тестовую утилиту визуализации состояния шифратора приращений.
Продолжение. Начало цикла смотрите в четвертом выпуске журнала…
Сергей Бадло
by raxp http://raxp.radioliga.com
Согласно требований из прошлого материала [1], приведем реализацию алгоритма энкодера на ПЛИС в среде Xilinx Foundation 3.1i [2] (см. рисунки 2…8).
Каждая микросхема FPGA обрабатывает сигналы от двух датчиков. По каждому четвертому сигналу чтения READ и нулевому адресу (битовая последовательность А0…А2) передаются: младшие 8- бит 11-ти разрядной последовательности, содержащей информацию о текущем количес- тве импульсов поступивших с канала А (угловом положении). По первому адресу (А0…А2) переда- ются (с младшего по старший бит DO0…DO7): старшие 3- бита 11-ти разрядной информации о текущем количес- тве импульсов поступивших с канала А, признак отказа канала А (в течении длитель- ности стробирую- щего импульса (одного оборота), признак отказа канала В (в течении длитель ности стробирую- щего импульса (одного оборота)), признак направления вращения (определяется с началом стробирующего импульса по приходу сигналов с канала А и В (в течении одного оборота)), признак отказа канала строба О. По второму и третьему адресу (А0…А2) передаются (с младшего по старший бит DO0…DO7) 16- бит информации о количестве оборотов. По четвертому и пятому адресу (А0…А2) передаются (с младшего по старший бит DO0…DO7) 16- бит информации о количестве ТИ за длительность строба (относительной* скорости).
Рис. 1. Тестируемый пациент
Рис. 2. Общая схема энкодера (дешифратор адреса, формирователь кода схемы, генератор ТИ, 2 канала энкодера, 16 каналов дискретного ввода-вывода)
Рис. 3. Схема одного канала энкодера (антидребезг, задатчик идентификатора схемы, реверсивный счетчик импульсов, узел формирования выходного пакета данных)
Каждая из схем энкодера (алгоритм) осуществляет:
- измерение относительного углового положения датчика (по количеству импульсов поступивших с канала A);
- индикацию в соответствующем бите признака наличия импульсов (исправность A, B, Q);
- подсчет числа оборотов (количества импульсов строба), максимальное ограничено величиной 215, далее осуществляется сброс, и счет начинается заново;
- измерение относительной скорости*, т.е. подсчета количества ТИ, поступивших за длительность строба (погрешность ограничена длительностью ТИ и нестабильностью тактового генератора).
Рис. 4. Модуль задержки на 8 тактов встроенного генератора
Информация о текущей скорости определяется сразу же по истечении импульса строба, т.е. после первого оборота и далее по каждому последующему стробу.
где: 4 – коэффициент, учитывающий соотношение длительности строба и длительности канальных (информационных импульсов); 2048 – максимальное количество импульсов по любому из каналов; V – фактическая скорость, об/cек; Nти – количество ТИ за строб; Tти – период ТИ, поступающих с внешнего генератора (равен 20 нс), сек.
Рис. 5. Схема определения направлени вращения ротора датчика PDF
Рис. 6. Схемы нарезки сигналов A/B
Рис. 7. Схема регулирования (СР) ширины ЗИ
Рис. 8. Внутренняя схема узла адресации СР
Рис. 9. Реализация RS-триггера
Запустим наш проект на компиляцию. После проверки схемы, среда создаст битовый файл прошивки (файлы bitstream фирмы XILINX), который нужно прошить в соответствующую матрицу FPGA. Как это сделать?
Программирование платы UNIOхх-5
Обычно, для загрузки конфигурационной информации в ПЛИС используется JTAG интерфейс [3]. При этом последовательность действий следующая. Откройте приложение «JTAG Programmer» пакета Xilinx Foundation Series 3.1i. В меню «Edit» выберите пункт «Add Device», после чего появиться вспомогательное окно, в котором необходимо отыскать наш файл прошивки и открыть его. В меню «Operations» выберите пункт «Program». В появившемся окне нажмите кнопку «OK». После удачной загрузки, должна появиться фраза «Programming completed successfully». На этом программирование завершено (см. рисунок 10):
Рис. 10. Загрузка прошивки через JTAG
Однако этот способ не лишен недостатков: требуется наличие JTAG программатора практически все время «под рукой».
Второй способ, получивший название ISP (In System Programming), более удобен, так как не требует извлечения микросхемы конфигурационного ПЗУ (или самой ПЛИС) из платы или наличия дополнительного разъема на плате под ПЛИС. Программирование каждой матрицы FPGA1…FPGA4 модуля UNIOxx-5 осуществляется с помощью программ: <isp.exe> (загрузка схемы с записью в EEPROM), <isl.exe> (загрузка схемы без записи в EEPROM). Программы позволяют осуществить загрузку файлов схем *.bit матриц FPGA. Рассмотрим на примере…
Для записи схемы и загрузки в модуль необходимо запустить программу <isp.exe> с указанием Базового Адреса (Hex) модуля и кодов схем матриц FPGA, например (см. рисунок 11):
Рис. 11. Результат
Рис. 11. Окно командной строки. Запуск утилиты ISP
Питание и установка
Модуль с прошивкой энкодера устанавливается в слот (ISA) промышленного компьютера и запитан от напряжения ±5В. При этом требуется обеспечить стабильность питающего напряжения с пульсациями не более 200 мВ. Выходной сигнал – однополярное напряжение (цифровая последовательность) с током нагрузки до 10 мА. Максимальная длина шлейфа, соединяющая выход модуля энкодера (платы UNIOxx-5) к входному разъему до 1.5 м. Проверка прошитой платы UNIOxx-5 производится на рабочем месте следующим образом. Земли шасси, платы UNIOxx-5, осциллографа, генератора импульсов и генератора сигналов высокочастотного должны быть объединены (заземлены) в одной точке проводником минимальной длины сечением не менее 2 мм2 (см. рисунок 12):
Рис. 12. Схема проверки платы UNIOxx-5 с прошивкой энкодера
Плата UNIOxx-5 при выключенном питании шасси вставляется в ISA слот. С помощью соединительного шлейфа присоединяют выход датчиков с соответствующими входами модулей гальванической развязки или модулей связи, сигнал с которых подан на вход платы UNIOxx-5. Далее производится включение промышленного шасси и загрузка обслуживающей прошивки. Осциллографом контролируют наличие напряжения питания (+5 В) на плате модуля UNIOxx-5. С помощью осциллографа производится контроль ТИ с тактового генератора платы. Включив генератор импульсов с заранее выставленными выходными уровнями сигналов, подают импульсы по входу строба для каждой из матрицы модуля (поочередно), контролируя одновременно с помощью программы обслуживания (или осциллографом) наличие признака строба в последовательности (бит DO7 при втором адресе А0…А2).
Кроме того, тестирование прошивки энкодера желательно провести в условиях, приближенных к «реальным». Для этого необходимо, подключить шифратор приращений через наш модуль связи, используя несколько десятков метров кабеля UTP 5-й категории обмотанного вокруг работающего частотного привода под нагрузкой. Для визуализации положения ротора и подсчета количества импульсов с датчика приращений, реализуем на языке С простейшую утилиту приема данных с платы UNIO по шине ISA…
Реализация тестовой утилиты приема данных с энкодера и визуализация
Прежде всего, на основе схемы (алгоритма) энкодера составим таблицу распределения его выходных сигналов (см. таблицу). Для упрощения написания программы можно воспользоваться библиотечными функциями языка С. В качестве примера рассмотрим фрагмент программы, осуществляющей тестовое считывание данных с контроллера и вывод графического отображения положения ротора датчика PDF. В начале программы необходимо определить адрес считывания, согласно таблице (см. листинг 1):
Таблица. Расшифровка выходных сигналов энкодера
код:
…
int f_dba(int dba,int d[16])
{
int i,PA;
for (i=0;i<16;i++) { PA=inp(BA+dba+i); d[i]=PA; } } // dba- адрес FPGA, d- данные
Адрес считывания по ISA = BA+BAx+Ar, где BA – базовый адрес платы UNIOxx (выставлен 0x110), BAx – базовый адрес матрицы FPGA:
- для FPGA-1 (BAx=0xA000)
- для FPGA-2 (BAx=0xA400)
- для FPGA-3 (BAx=0xA800)
- для FPGA-4 (BAx=0xAC00)
Рассмотрим подробнее…
Запустим среду Turbo C++ IDE ver.3.0 от Borland и создадим пустой проект. Далее необходимо провести инициализацию графического режима через InitGraph() и зациклить опрос порта INP(). Причем предусмотреть выход из цикла по нажатию определенной комбинации клавиш во время опроса, к примеру, использованием функций Kbhit() и Getch(). В основном цикле необходимо осуществить считывание двухбайтного кода идентификатора схемы, положения ротора, признаков отказа и направления вращения. После чего, произвести отображение выделенных параметров в графическом виде. Оптимальным с точки зрения наблюдения – является имитация положения ротора датчика приращений с выводом дополнительной служебной информации. Реализация подобного подхода представлена в листинге 2:
код:
…
#include «dos.h»
#include «string.h»
#include
#include
#include
#include
#define BA 0xA110
#define pi 3.14159
int f_dba(int dba,int d[16]);
void main(long int argc, char *argv[])
{
// переменные порта
int dba;int d[16];
// переменные данных
int FL,ugc,ugc2,FL1,FL2;
// служебные переменные
int s,pd,i,nomer,d1,d2;
long int k,KT,KT2;
float ugol,ugol2,ug,n,ug2,ug1,KTT,vm,ug_1,ug_2;
double v,ng1,ng2,nn;
int gdriver = DETECT, gmode, errorcode;
char msg[80];
int x,x2,y,y2,ns,nc,ugg,ugg2,xr,xr2,yr,yr2,wr,wr2,hr,hr2;
char nbuf[25];
char kbuf[25];
char ubuf[25];
char ibuf[25];
char sbuf[25];
char pbuf[25];
clrscr();
if(argc>1) // проверка параметров командной строки
{
printf(«argc=%d\n»,argc);
for(i=0;i
{ // выдаем описание
printf(«Program driver encoder\n»);
}else if (strcmp(argv[1],»indtest») == 0){}
}
//
clrscr();
k = 1;
puts(«Расчитывать параметры по FPGA-?»);
puts(«Количество импульсов с датчика PDF-?»);
scanf(«%d %d», &s, &pd); // считываем номер FPGA
if (s == 1) {dba = 0x0;} // задаем базовый адрес
if (s == 2) {dba = 0x400;}
if (s == 3) {dba = 0x800;}
if (s == 4) {dba = 0xC00;}
/*Инициализация графического режима*/
initgraph(&gdriver, &gmode, «»);
errorcode = graphresult();
if (errorcode != grOk)
{
printf(«Graphics error: %s\n», grapherrormsg(errorcode));
printf(«Press any key to halt:»);
getch();
}
/*Параметры рисунка*/
xr=180; // положение 1-го графика
yr=250;
xr2=470; // положение 2-го графика
yr2=250;
wr=100; // размеры 1-го графика
hr=100;
wr2=wr; // размеры 2-го графика
hr2=hr;
//
setfillstyle(1,BLUE);
fillellipse(xr, yr, wr, hr);
fillellipse(xr2, yr2, wr2, hr2); // 2-канал
setcolor(GREEN);
outtextxy(0,10, «Count:»); // количество импульсов
outtextxy(0,30, «Angle, deg:»); // угол поворота ротора
outtextxy(0,41, «Speed, r/s:»); // скорость
outtextxy(0,52, «HB:»); // направление вращения
outtextxy(0,63, «delta:»);
// градусы
outtextxy(xr+wr+15,yr-5,»0″);
outtextxy(xr2+wr2+15,yr2-5,»0″);
outtextxy(xr-wr-40,yr-5,»180″);
outtextxy(xr2-wr2-40,yr2-5,»180″);
outtextxy(xr-5,yr-hr-25,»90″);
outtextxy(xr2-5,yr2-hr2-25,»90″);
outtextxy(xr-10,yr+hr+15,»270″);
outtextxy(xr2-10,yr2+hr2+15,»270″);
do {
f_dba(dba,d);
printf(«Опрос:%d», k);
if (k>1)
{
setcolor(BLACK);
outtextxy(90,10, kbuf);
}
setcolor(RED);
itoa(k, kbuf, 10); // конвертируем в текст (max =10 символов)
outtextxy(90,10, kbuf);
/*FPGA_1*/
printf(«Идентификатор схемы= %c», d[14]); // см. схему
алгоритма на ПЛИС
//
n = ((d[3]<<8)|d[2]);
if (n < 0) {nn = 65535 + n - 32768;}
if (n > 0) {nn = n;}
printf(«Оборот: %7.1f», n);
if (k>1)
{
setcolor(BLACK);
outtextxy(5,90,nbuf);
}
nn=165001;
setcolor(RED);
itoa(nn,nbuf,25);
outtextxy(5,90,nbuf);
// формируем из двух байт значение положения (см. схему)
KT = ((d[1]<<8)|d[0]);
KT2 = ((d[6]<<8)|d[5]);
ugol = KT;
ugol2 = KT2;
// пересчитываем в угловые коорд.положение ротора-1 и ротора-2
ug = ugol*360/pd;
ug2 = ugol2*360/pd;
ugc = ug/360;
ugc2 = ug2/360;
ug = 360*(ugc-(ug/360));
ug2 = 360*(ugc2-(ug2/360));
ugg = 90-ug;
ugg2 = 90-ug2;
if (k>1)
{
setcolor(BLACK);
outtextxy(90,32, ubuf);
outtextxy(130,32, ibuf);
}
setcolor(RED);
itoa(ug,ubuf,10);
itoa(ugol,ibuf,10);
outtextxy(90,32,ubuf);
outtextxy(130,32,ibuf);
//
FL=d[4]&0x04; // определяем направление вращения
if (k>1)
{
if (FL == 0x04) {setcolor(BLACK);outtextxy(90,53,»left»);}
else {setcolor(BLACK);outtextxy(90,53,»rigth»);}
}
if (FL==0x04)
{
setcolor(BLACK);outtextxy(90,53,»rigth»);
setcolor(RED);outtextxy(90,53,»left»);
}
else
{
setcolor(BLACK);outtextxy(90,53,»left»);
setcolor(RED);outtextxy(90,53,»rigth»);
}
// значение разницы
if (k>1)
{
setcolor(BLACK);
outtextxy(90,63,pbuf);
}
setcolor(RED);
if (k == 1) {d1 = ug;d2 = ug2;}
itoa((ug-ug2)*pd/360,pbuf,10);
outtextxy(90,63, pbuf);
// скорость вращения
if (k==1) {ug_1=ug;ng1=ugc;}
ug_2=ug;ng2=ugc;
vm = ((ng2-ng1)*360-ug_1+ug_2)/(360*(125e-3));
printf(«Vm, об/c= %8.6f\n»,vm);
if (k>1)
{
setcolor(BLACK);
outtextxy(90,43,sbuf);
}
setcolor(RED);
itoa(vm,sbuf,10);
outtextxy(90,43,sbuf);
ug1=ug2; ng1=ng2;
// маркер (вектор на графике)
if (k>1)
{
setcolor(BLUE); // 1-канал
line(x,y,xr,yr);
line(x2,y2,xr2,yr2);
}
setcolor(RED);
line(xr-wr-10,yr,xr+wr+10,yr); // ось-x
line(xr2-wr2-10,yr2,xr2+wr2+10,yr2); // ось-x 2-канал
line(xr,yr+hr+10,xr,yr-hr-10); // ось-y
line(xr2,yr2+hr2+10,xr2,yr2-hr2-10); // ось-y 2-канал
x=xr+(wr*sin(ugg*pi/180)); x2=xr2+(wr2*sin(ugg2*pi/180));
y=yr+(hr*cos(ugg*pi/180)); y2=yr2+(hr2*cos(ugg2*pi/180));
setcolor(RED); // 1-канал
line(xr,yr,x,y);
line(xr2,yr2,x2,y2);
// конец маркер
k+ = 1;
delay(100);
if (!kbhit()) s=getch(); // перехватываем нажатую клавишу для
// останова программы
if (s==0x9) break;
} while (s!=0x13);
closegraph();
textmode(LASTMODE);
return;
}
// опрос порта по базовому адресу + смещение
int f_dba(int dba,int d[16])
{
int i,PA;
for (i=0; i<16; i++)
{
PA = inp(BA + dba + i);
d[i] = PA;
}
}
Запустим проект на компиляцию и выполнение командой <Ctrl>+<F9>. При этом, появится экран с запросом параметров считывания (см.рисунок 13). Задав номер FPGA = 3 и максимальное количество импульсов для подключенного датчика = 2048 (для нашего датчика RV-58N), нажмем <ENTER> и получим экран с визуализацией состояний двух энкодеров (см. рисунок 14-15). На рисунке 14 представлен экран состояния датчиков приращений при удаленном просмотре через сеть TCP/IP, но это уже тема отдельной статьи…
Рис. 13. Экран задания параметров считывания
Рис. 14. Удаленный просмотр датчиков приращений
Рис. 15. Экран визуализации состояний двух датчиков PDF
Заключение
Вот в принципе и все. Наслаждаемся аппаратным декодированием состояния шифратора приращений и визуальным просмотром…
Рассматриваемые в данной статье прошивка энкодера для ПЛИС в пакете XILINX 3.1, исходники и компиляция тестовой утилиты визуализации состояния датчика приращений и загрузчик ISP полностью приведены в виде ресурсов в теме «Журнал клуба программистов. Пятый выпуск» или непосредственно в архиве с журналом [4].
Ресурсы
- С. Бадло. Энкодер датчика PDF на ПЛИС. – ПРОграммист, Клуб ПРОграммистов, 2010, №4, с.40 http://raxp.radioliga.com/cnt/s.php?p=pro4.pdf
- Сайт производителя Xilinx http://www.xilinx.com
- С. Бадло. JTAG.Xilinx программатор. – Радиолюбитель, Минск, 2008, №7, с.38 http://raxp.radioliga.com/cnt/s.php?p=jtag.pdf
- Модули и проекты, использованные в статье http://raxp.radioliga.com/cnt/s.php?p=pro5.pdf
Статья из пятого выпуска журнала «ПРОграммист».
Скачать этот номер можно по ссылке.
Ознакомиться со всеми номерами журнала.
Обсудить на форуме – Энкодер датчика pdf на плис. Часть 2
Похожие статьи
Купить рекламу на сайте за 1000 руб
пишите сюда - alarforum@yandex.ru
Да и по любым другим вопросам пишите на почту
пеллетные котлы
Пеллетный котел Emtas
Наши форумы по программированию:
- Форум Web программирование (веб)
- Delphi форумы
- Форумы C (Си)
- Форум .NET Frameworks (точка нет фреймворки)
- Форум Java (джава)
- Форум низкоуровневое программирование
- Форум VBA (вба)
- Форум OpenGL
- Форум DirectX
- Форум CAD проектирование
- Форум по операционным системам
- Форум Software (Софт)
- Форум Hardware (Компьютерное железо)