-
АвторТема
-
15.09.2016 в 12:03 #50264
1. Исходя из блок схемы в 230-м модуле максимальная частота опроса каждого одного канала
зависит от количества включенных каналов, это так? Если зависит то это означает что
каналы опрашиваются не синхронно?2. Если имеются несколько 230-х модулей, каким образом можно их синхронизировать
(одновременное начало сбора данных и синхронный опрос)?3. Вопрос по работе с Zadc.dll. Что будет в случае если необходимая для помещения в буфер
(полученный с помощью ZGetBufferADC) порция данных размером больше области оставшейся до конца буфера?4. Количество включенных каналов можно получить с помощью ZGetNumberInputADC. А каким образом можно
узнать номера включенных каналов? -
АвторТема
-
АвторОтветы
-
15.09.2016 в 12:04 #50265
Здравствуйте, Виталий!
1. Частота дискретизации АЦП в ZET 230 не зависит от количества включенных каналов, соответственно, сколько бы ни было включено каналов, данные опрашиваются всегда синхронно.
2. Синхронизовать модули ZET 230 можно через цифровой порт этих устройств. При этом одно из устройств будет мастером, а остальные слейвом. Кто мастер, а кто слейв настраивается через «Диспетчер устройств» на вкладке «Синхронизация». При таком подходе цифровые порты устройств должны быть физически соединены. Более подробно написано здесь.
3) Поскольку буфер циклический, то указатель на текущий элемент заполнения буфера просто перейдет в начало и все продолжется.
4) Узнать номера включенных каналов можно в цикле по всем каналам функцией ZGetInputADC. Для включенных каналов в параметре enable будет возвращаться значение 1, а для выключенных 0.
Удачи!15.09.2016 в 12:04 #50266Спасибо!
Только по 3-му вопросу, осталось не понятным, часть данных будет записана в конце буфера, а часть в начале или же указатель перейдет на начало и данные полностью запишутся начиная с 0-го адреса?15.09.2016 в 12:04 #50267Здравствуйте, Виталий!
Часть данных запишется в конец буфера, а оставшаяся часть в начало буфера.
Удачи!15.09.2016 в 12:05 #50268Здравствуйте!
Для работы с модулями через библиотеку Zadc.dll используются константы typeDevice, определяющие тип устройства. (Например в функции ZOpen(typeDevice, numberDSP); ).
Не подскажете число typeDevice для 230-го модуля?15.09.2016 в 12:05 #50270Добрый день!
1)typeDevice для 230-го модуля равен 17
2)В документе ZETLabStudio.pdf в главе 12 содержится информация по интересующему вас вопросу.
Документ поставляется на дисках к приборам или в Doc.rar на ftp находится всегда последняя версия.15.09.2016 в 12:05 #50271Добрый день. Есть код, основанный на Вашем с++ примере, который нормально читает данные с 210-го модуля (подключается
по USB), при попытке использования этого же кода для чтения с 230-го модуля(подключение по Ethernet). При этом единственное
изменение в коде — замена типа устройства с 10 на 17.В наличии 3 библиотеки(версия 2012.9.3.0 идет с ПО ZetLab), функция ZOpen возвращает разные значения в зависимости
от передаваемого ей типа устройства (10 для 210 модуля, 17 — для 230-го)см. таблицу:Версия длл Тип устройства Результат ZOpen
2012.9.3.0 10 0xA00
2012.9.3.0 17 0xC002011.12.2.0 10 0 (OK)
2011.12.2.0 17 0x9005.1.0.0 10 0 (OK)
5.1.0.0 17 0x900Т.е. ни одна из длл не работает с 230-м модулем, подключенным по Ethernet. Жду помощи.
версия ПО ZetLab — 06.09.2012
Windows XP SP315.09.2016 в 12:05 #50272Добрый день!
Ошибка 0xA00 — устройство с данным numberDSP не подключено (надо проверить значение numberDSP — для Ethernet оно скорее всего начинается с номера 67)
Ошибка 0xC00 (для 230) это ошибка несовпадения версий15.09.2016 в 12:05 #50273Спасибо за разъяснения. Действительно, для Ethernet numberDSP начинается с 67.
15.09.2016 в 12:06 #50274Добрый день. Никак не можем разобраться с синхронизацией двух (и более) 230-х модулей. Есть необходимость получать данные с всех каналов двух модулей синхронно (т.е. отсчеты должны сниматься одновременно с каналов обоих модулей).
Пытаемся читать самописной программой (которая функционально собственно почти полностью содрана с Вашего примера)
При установке режимов ведущий и ведомый, соединения 8-го пина цифрового порта и подаче на все каналы синусоиды в 1000 Гц частотой:
1) снимаемые отсчеты стартуют не синхронно (возможно тут необходимо учитывать порядок вызова ZStartADC для ведущего и ведомого модулей, подскажите как тут быть)
2) по характеру снимаемых с двух модулей синусоид видно, что частота дискретизации у них немного разная (в следствии чего синусоиды, построенные только по отсчетам то сходятся то расходятся с большим периодом)
Как решение этих проблем вижу установку одного из модулей «Задатчиком синхронизации», и организация дискретизации с одной частотой. Но в документе ZET 2xx Base.pdf в п.4.2.3 есть описание старого интерфейса настройки, а в новом пункта «Задатчик синхронизации» нет.
Заранее спасибо за ответ.15.09.2016 в 12:06 #50275Добрый день!
Единственное, что нужно, чтобы устройства все были одного типа.
1)Порядок вызова ZStartADC: сначала запускаются ведомые устройства (в режиме ожидания внешнего сигнала запуска), затем запускается ведущее устройство, которое подает сигнал ведомым.
2)Соединять нужно несколько ножек. Их функции описаны:
в пункте 4.2.3 описана цифровая ножка 8 как источник управления — то есть это сигнал внешнего запуска. Помимо этого в пп. 4.2.3.1 и 4.2.3.2 описаны еще цифровые ножки 7 и 6 — по ним передается внешняя частота дискретизации АЦП и ЦАП.
Если используется Диспетчере устройств, то во вкладке «Синхронизация» выставить в задатчике флажок Ведущий, а в остальных — Ведомый
3) Настройка синхронизации по цифровому порту:
Код
// проверка значения err после каждого вызова опущена для краткости
long err;// настройка задатчика синхронизации
err = ZSetEnableExtStartADC(typeDSP, numberDSP, 1);
err = ZSetEnableExtFreqADC(typeDSP, numberDSP, 1);
err = ZSetMasterSynchr(typeDSP, numberDSP, 1);// получаем частоту с задатчика
double freq;
err = ZGetExtFreqADC(typeDSP, numberDSP, &freq);// настройка ведомых устройств
err = ZSetEnableExtStartADC(typeDSP, numberDSP, 1);
err = ZSetEnableExtFreqADC(typeDSP, numberDSP, 1);
err = ZSetExtFreqADC(typeDSP, numberDSP, freq);
err = ZSetMasterSynchr(typeDSP, numberDSP, 0),потом ZStartADC в указанном порядке. Вот такой пример должен работать.
Сообщите еще, пожалуйста, какой пример Вы используйте?15.09.2016 в 12:07 #50276Используемый пример — Пример работы с драйвером с использованием библиотеки ZADC.dll. Программа написана на Microsoft Visual С++ 6.0. со страницы Программирование с вашего сайта. Т.е. с этого адреса https://www.zetms.ru/support/programming/index.php
15.09.2016 в 12:07 #50277Описание приведенных Вами функций отсутствует в имеющемся в примере модуле Zadc_int.h. После внесения их в *.h-файл, линкер выдает unresolved external symbol. Скажите, как у Вас можно получить актуальные версии Zadc_int.h и Zadc.lib. Если не трудно можете выслать мне на адрес k1981ua@mail.ru
С уважением, Виталий.15.09.2016 в 12:07 #50278Добрый день!
Файлы высланы.15.09.2016 в 12:07 #50279Спасибо!
15.09.2016 в 12:08 #50281Добрый день! Скопилось еще несколько вопросов:
1) функция ZGetExtFreqADC(typeDSP, numberDSP, &freq) в параметре частоты всегда(на разных частотах 2500, 25000 и 50000Гц)
возвращает 12800000. Это так и должно быть?
2) есть ли способ получения данных с 230-х модулей напрямую, т.е. без Zadc.dll? Их протокол обмена открытый?
3) При считывании данных с приборов они идут пачками по несколько тысяч сэмплов, иногда при частоте дискретизации
25000 Гц пачки составляют 20-30 тыс. сэмплов (т.е. 160-1400 тыс. байт ( *4 канала*2байта)). Такое поведение нормально?
По ощущениям ЗетЛаб считывает данные меньшими порциями.Заранее спасибо за ответы.
15.09.2016 в 12:08 #50283Добрый день!
1) да, это опорная частота, затем данные проходят через фильтр, чтобы исключить возможные помехи и получить требуемую частоту
2) нет, единственный способ это работа через интерфейс Zadc.dll
Протокол обмена между драйвером и ПО может быть в любой момент изменен, в связи с чем его сопровождение за пределами компании сильно затруднено
3) это связанно с особенностями протокола USB: передача данных от устройства происходит пакетами одинакового размера; драйвер же (в целях производительности) буферизует эти данные в своей внутренней памяти, а внешний буфер заполняет после получения нескольких пакетов.15.09.2016 в 12:08 #50284Добрый день!
А если 3-й вопрос касается Ethernet-модулей, такое поведение нормально? сейчас подключено два 230-х модуля, если их подключить восемь, они смогут нормально передавать все данные без потерь и больших задержек?
Может посоветуете как следует организовывать Ethernet-сеть для гарантированного обеспечения нормальной работы?
С уважением, Виталий15.09.2016 в 12:08 #50285Добрый вечер!
При работе по интерфейсу Ethernet данные также буферизуются пакетами (разве что размеры и количество пакетов во внутреннем буфере могут отличаться от USB). Данные передаются по TCP/IP и не должны теряться, однако при увеличении частоты увеличиваются также и возможные задержки.
15.09.2016 в 12:09 #50286Добрый день!
Возник вопрос касающийся генерации сигнала на выходе «Генератор 1» модуля 230-го (или 220-го). Откомпилировав и запустив последний пример Test_DAC, установив нужные typeDevice и numberDSP (17 и 67 соответственно, у нас Ethernet-модуль) видим что ZOpen и вобщем-то остальные функции отрабатываю нормально. Стартует, доходит до цикла генерации, входит в него, но ничего на выходе Генератора 1 нет. Пробовали забить буфер DAC значениями вручную — все равно ничего нет. Скажите может есть другой пример или мы что-то делаем не так? Какой алгоритм работы для генерирования напряжения на выходе Генератора 1? Может мы что-то не учитываем?15.09.2016 в 12:09 #50287Здравствуйте, Виталий!
Очередной раз проверил пример Test_DAC для ZET230 при подключении его и по USB и по Ethernet — все работает так, как и заложено. Ваши проблемы могут быть связаны со следующими факторами:
1) При работе с устройством самостоятельно через драйвер не рекомендуется использовать программы из пакета ZETLab, поскольку при этом запускается сервер данных ZETLab, который самостоятельно конфигурирует устройства, а следовательно, может остановить ЦАП или АЦП, настроить другие параметры и т.д., что приведет к сбою в работе Test_DAC.
2) Если же вы все-таки решите использовать устройство в режиме работы с драйвером и при этом пользоваться программами из пакета ZETLab, то в программе, работающей через драйвер необходимо предусмотреть дополнительные возможности для отслеживания останова ЦАП, АЦП и других изменений в устройстве, поскольку сервер данных ZETLab может их изменять.
3) Нужно проверить то, с какого контакты вы смотрите сигнал генератора (это на всякий случай).
Удачи!15.09.2016 в 12:09 #50288Спасибо за ответ!
По ходу работы возник еще вопрос: заметили что показания напряжения на входе 230-го модуля, рассчитанное нашей программой, работающей через zadc.dll отличается от показаний программ комплекса ЗетЛаб примерно на 6-7% (меряем величины порядка 450 мВ). Наша программа показывает больше на 30мВ.
Перепроверено неоднократно.
Рассчитываем по формуле,заимствованной из примеров:
volt0 = resolutionADC * (pBuffer32ADC[pointerADC/numWordsADC]) / amplifyADC0
Скажите, в чем может быть проблема? Есть ли еще какие-нибудь параметры, влияющие на рассчет напряжения?
Заранее спасибо за ответ.15.09.2016 в 12:09 #50289Здравствуйте, Виталий!
На расчет напряжения могут влиять параметры чувствительности и смещения, настроенные через «Диспетчер устройств»
Удачи!15.09.2016 в 12:09 #50290Скажите пожалуйста, могу ли я получить эти параметры (чувствительность и смещение) через zadc.dll, как например получаю вес младшего разряда с помощью функции ZGetDigitalResolChanADC и рассчитать значение напряжения используя только функции предоставляемые zadc.dll.
Заранее спасибо за ответ!15.09.2016 в 12:09 #50291Здравствуйте, Виталий!
Эти параметры в zadc.dll не имеют места быть, поэтому вы их оттуда никак не возьмете. Эти параметры есть только в ZETServer. В zadc.dll предоставлена возможность работать только с исходными данными. Все их преобразование в измеряемую величину осуществляется в ZETServer.
Удачи!15.09.2016 в 12:10 #50292В очередной раз перепроверили:
показания Зетлаба = 432 мВ.
Снимаем данные:
младший разряд АЦП=0.00000000488944351673
код АЦП = 95070036
коэфф. усиления = 1
Пожалуйста объясните как из этих данных получается 432 мВ?
Заранее спасибо за ответ.15.09.2016 в 12:10 #50293Здравствуйте, Виталий!
Из тех данных, что вы предоставили, никак не получается 432 мВ. Для большей информативности прошу вас прислать на почту настройки вашего измерительного канала в ZETLab и желательно запись сигнала, который вы измеряете.
Удачи!
15.09.2016 в 12:10 #50294Здравствуйте!
Я знаю что не получается, но тем не менее вольтметр Зетлаб показывает именно это значение. Вы не могли бы уточнить алгоритм перевода кода АЦП в напряжение?
Сообщите на какой е-мэйл выслать скриншоты и запись сигнала.
Заранее спасибо за ответ!15.09.2016 в 12:11 #50295Здравствуйте, Виталий!
Формула перевода приведена в примере, и она ничем не отличаетя от той, что в ZETLAB. Почта info@zetlab.com или zetlab@zetlab.com.
Удачи!
15.09.2016 в 12:11 #50296Здравствуйте, Антон!
Файлы отправил.15.09.2016 в 12:11 #50297Здравствуйте!
Модули мы не путаем, просто Зетлаб показывает одно — правильное значение, а при обращении к библиотеке получаем код АЦП, вес младшего разряда и коэффициент усиления — при их перемножении получается другое значение, погрешность относительная, не абсолютная.15.09.2016 в 12:11 #50298Здравствуйте, Виталий!
Скажите, данный эффект проявляется только на одном канале конкретного модуля или это проявляется на всех каналах всех модулей?
Удачи!
15.09.2016 в 12:13 #50303Здравствуйте!
Сдалали тестовую программку для измерения напряжения на канале, ее код (ничего лишнего, только опрос)://==========================================================================================
#include «stdafx.h»
#include <Windows.h>
#include «Zadc_int.h»
#include <stdio.h>
#include <conio.h>class Z230Device
{
public:
long err;
long typeDevice;
long numberDSP;
long numChannelsADC; // Кол-во включенных каналов АЦП
long numWordsADC; // Кол-во слов (по два байта) в одном отсчете АЦП
void *pBuffer; // Указатель на начало буфера драйвера типа void
short *pBuffer16ADC; // Указатель на начало буфера драйвера для АЦП с разрядностью не более 16 бит
long *pBuffer32ADC; // Указатель на начало буфера драйвера для АЦП с разрядностью более 16 бит
long sizeBufferADC; // Размер буфера драйвера в словах
long pointerADC; // Указатель на текущий элемент заполнения буфера драйвера (кратен 2)
long pointerADC_old; // Предыдущее значение указателя на буфер драйвера
double amplifyADC[4];// Коэф. усиления по каналам
double resolutionADC; // Вес младшего разряда АЦП
double volt[4]; // Мгновенное текущее значение АЦП (в Вольтах)
double freq; //частота задатчика синхронизации
};
//==============================================================================
HINSTANCE dllHandle=NULL;
Z230Device devs[1];
//——————————————————————-
int numDev=0;
//===================================================================
long Init230(long numDev,long typeDev, long number_DSP, long err)
{
devs[numDev].typeDevice=typeDev;
devs[numDev].numberDSP=number_DSP;dllHandle = LoadLibrary(L»zadc.dll» 😉 ;
// подключиться к драйверу (обязательно)
err = ZOpen(devs[numDev].typeDevice, devs[numDev].numberDSP);// опросить коэф. усиления по каналу АЦП
err = ZGetAmplifyADC(devs[numDev].typeDevice, devs[numDev].numberDSP, 0, &devs[numDev].amplifyADC[0] 😉 ;
err = ZGetAmplifyADC(devs[numDev].typeDevice, devs[numDev].numberDSP, 0, &devs[numDev].amplifyADC[1] 😉 ;
err = ZGetAmplifyADC(devs[numDev].typeDevice, devs[numDev].numberDSP, 0, &devs[numDev].amplifyADC[2] 😉 ;
err = ZGetAmplifyADC(devs[numDev].typeDevice, devs[numDev].numberDSP, 0, &devs[numDev].amplifyADC[3] 😉 ;// опросить вес младшего разряда АЦП
err = ZGetDigitalResolutionADC(devs[numDev].typeDevice, devs[numDev].numberDSP, &devs[numDev].resolutionADC);// опросить кол-во слов в одном отсчете АЦП
err = ZGetWordsADC(devs[numDev].typeDevice, devs[numDev].numberDSP, &devs[numDev].numWordsADC);// запросить буфер АЦП
err = ZGetBufferADC(devs[numDev].typeDevice, devs[numDev].numberDSP, &devs[numDev].pBuffer, &devs[numDev].sizeBufferADC);// Проинициализировать локальные указатели для конкретных типов данных
devs[numDev].pBuffer16ADC = (short*) devs[numDev].pBuffer;
devs[numDev].pBuffer32ADC = (long*) devs[numDev].pBuffer;return 0;
}
//=========================================================================
double getValueCh(long numDev,long numCh, long err, long *CodeADC, double *ResolADC,double *AmplifADC, long *pointer)
{// запросить указатель на текущий элемент буфера
err = ZGetPointerADC(devs[numDev].typeDevice, devs[numDev].numberDSP, &devs[numDev].pointerADC);
if(err != 0) return -1;*pointer=devs[numDev].pointerADC;
// перейти на отсчет первого включенного канала последнего кадра АЦП
if(devs[numDev].pointerADC — devs[numDev].numWordsADC * devs[numDev].numChannelsADC < 0)
devs[numDev].pointerADC = devs[numDev].sizeBufferADC + devs[numDev].pointerADC — devs[numDev].numWordsADC * devs[numDev].numChannelsADC;
else
devs[numDev].pointerADC = devs[numDev].pointerADC — devs[numDev].numWordsADC * devs[numDev].numChannelsADC;*CodeADC=devs[numDev].pBuffer32ADC[devs[numDev].pointerADC/devs[numDev].numWordsADC + numCh];
*ResolADC=devs[numDev].resolutionADC;
*AmplifADC=devs[numDev].amplifyADC[numCh];// вычислить из целого значения отсчета АЦП вещественное значение отсчета (в Вольтах)
if(devs[numDev].numWordsADC == 1)
devs[numDev].volt[numCh] = devs[numDev].resolutionADC * (devs[numDev].pBuffer16ADC[devs[numDev].pointerADC + numCh] 😉 / devs[numDev].amplifyADC[numCh];
else
devs[numDev].volt[numCh] = devs[numDev].resolutionADC * (devs[numDev].pBuffer32ADC[devs[numDev].pointerADC/devs[numDev].numWordsADC + numCh] 😉 / devs[numDev].amplifyADC[numCh];return devs[numDev].volt[numCh];
}
//——————————————————————int _tmain(int argc, _TCHAR* argv[] 😉
{
long CodeADC;
long pointer;
double ResolADC;
double AmplifADC;
long err;err=Init230(0,17,67,0);
err=ZStartADC(devs[0].typeDevice,devs[0].numberDSP);while(!kbhit())
{
Sl eep(1000);
double val=getValueCh(0,0,0,&CodeADC,&ResolADC,&AmplifADC,&pointer);
printf(«%i %i %.14f %.5f %.8f\n»,pointer,CodeADC,ResolADC,AmplifADC,val);
}ZRemBufferADC(devs[0].typeDevice, devs[0].numberDSP,&(devs[0].pBuffer));
ZClose(devs[0].typeDevice, devs[0].numberDSP);
FreeLibrary(dllHandle);
dllHandle = NULL;return 0;
}
//===========================================================================================Запускаем ее, и потом Вольтметр постоянного тока Зетлаб, их скрины:
формат вывода программы: указатель на элемент буфера, код АЦП, вес мл. разряда. коэфф. усиления, значение в Вольтах
Запускали много раз, ошибка воспроизводима и постоянна. По другим каналам этого модуля то же самое. Объясните пожалуйста как из кода АЦП=90358324 и веса мл.разряда 0,00000000488944
получить то что показывает вольтметр Зетлаба.Очень рассчитываю на помощь.
15.09.2016 в 12:13 #50304Здравствуйте, Виталий!
Функция ZGetDigitalResolutionADC предназначена для запроса веса младшего разряда АЦП. Однако при настройке устройств данный параметр проходит калибровку и становится для каждого канала свой, поэтому запрашивать нужно откалиброванный вес младшего разряда АЦП фукнцией ZGetDigitalResolChanADC, которая уже привязана к конкретному каналу.
Удачи!
15.09.2016 в 12:14 #50306Спасибо за ответ, будем пробовать.
-
АвторОтветы
Для ответа в этой теме необходимо авторизоваться.