-
АвторТема
-
17.07.2018 в 11:53 #98569
Добрый день, использую вашу продукцию (ZET 210) для дипломного проекта. Возник вопрос по функциям:
long ZGetBufferADC(long typeDevice, long numberDSP, void **buffer, long *size)
long ZGetMaxInterruptADC(long typeDevice, long numberDSP, long * size)При каждом запуске тестовой программы Test_Zadc.сpp размеры буферов меняются, принимая нулевые или отрицательные значения. Данные значения являются нормальными для функционирования? Также при увеличении частоты дискретизации частота обновления значений в буфере не увеличивается. Как можно решить данный вопрос?
-
АвторТема
-
АвторОтветы
-
17.07.2018 в 15:49 #98575
Проблема с буферами ушла: ошибочно интерпретировали данные. Возник другой вопрос : при увеличении частоты дискретизации частота обновления значений в буфере не увеличивается. Как можно решить данный вопрос?
17.07.2018 в 17:54 #98585Добрый день!
Есть несколько моментов, которые нужно учитывать при использовании устройств, подробно они описаны в статье по ссылке: https://zetlab.com/programmirovanie-ustroystv-s-ispolzovaniem-biblioteki-zadc-dll/napisanie-programmnyx-prilozhenij-dlya-kontrollera-zetlab/.
Проверьте пожалуйста учтены ли данные рекомендации, и если да то опишите проблему подробнее.18.07.2018 в 12:18 #98614Да данные моменты учитывались при использовании Zet210. Включены два канала, частота дискретизации на каждом 200 кГц. При подаче на канал синуса с частотой 10 кГц, и записи полученных значений в файл. я получаю график сигнала отличный от синуса, хотя частота дискретизации на порядок превышает частоту `поданного сигнала.
Код программы:// Программа, включающая два канала АЦП устройства и отображающая мгновенное амплитудное значение по двум каналам два раза в секунду // © ЗАО "ЭТМС" 1992-2011. Все права защищены #include "stdafx.h" #include <windows.h> #include <conio.h> #include <stdio.h> #include <iostream> #include <fstream> #include "zadc_int.h" // Интерфейс библиотеки Zadc.dll using namespace std; #define MAX_TYPE_DSP 20 // Максимальное поддерживаемое количество типов устройств #define MAX_DEVICE_NAME 16 // Максимальное значение длины возвращаемого имени устройства int main(int argc, char* argv[]) { long typeDevice; // Тип устройства long numberDSP = 0; // Порядковый номер сигнального процессора long Err; // Код ошибки long enable; // Флаг поддерживается / не поддерживается long numChannelsADC; // Количество включенных каналов АЦП long numWordsADC; // Количество слов (по два байта) в одном отсчете АЦП short *pBuffer16ADC = NULL; // Указатель на начало буфера драйвера для АЦП с разрядностью не более 16 бит long *pBuffer32ADC = NULL; // Указатель на начало буфера драйвера для АЦП с разрядностью более 16 бит long sizeBufferADC; // Размер буфера драйвера в словах long pointerADC = 0; // Указатель на текущий элемент заполнения буфера драйвера (кратен 2) long pointerADC_old = 0; // Предыдущее значение указателя на буфер драйвера double amplifyADC0, amplifyADC1; // Коэффициент усиления по первым двум каналам double resolutionADC0, resolutionADC1; // Вес младшего разряда АЦП по первым двум каналам double volt0, volt1; // Мгновенное текущее значение АЦП (в вольтах) long serial; // Серийный номер устройства char deviceName[MAX_DEVICE_NAME]; // Имя устройства // Цикл подключения к первому поддерживаемому устройству for(typeDevice = 0; typeDevice < MAX_TYPE_DSP; typeDevice++) { // Подключение к драйверу устройства Err = ZOpen(typeDevice, numberDSP); // Если подключение прошло без ошибок if(Err == 0) { // Проверка поддержки устройством АЦП Err = ZGetEnableADC(typeDevice, numberDSP, &enable); // Если устройство поддерживает АЦП if(Err == 0 && enable != 0) { // Выход из цикла подключения break; } // Если устройство не поддерживает АЦП else { // Вывод информации об ошибке printf("ZGetEnableADC() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); } } } // Если не удалось подключиться к драйверу устройства if(typeDevice >= MAX_TYPE_DSP) { // Вывод информации об ошибке printf("Device not found! Error = 0x%X\n\r", Err); getch(); return 0; } // Если удалось подключиться к драйверу устройства else { // Вывод информации о том, что произошло подключение к драйверу устройства printf("Device found...\n\r"); } // Опрос имени устройства Err = ZGetNameDevice(typeDevice, numberDSP, deviceName, MAX_DEVICE_NAME); // Если опрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("ZGetNameDevice() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); getch(); return 0; } // Если опрос выполнился без ошибок else { // Вывод имени устройства printf("Device name: %s\n\r", deviceName); } // Опрос серийного номера устройства Err = ZGetSerialNumberDSP(typeDevice, numberDSP, &serial); // Если опрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("ZGetNameDevice() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); getch(); return 0; } // Если опрос выполнился без ошибок else { // Вывод серийного номера устройства printf("Serial number: %ld\n\r", serial); } // Опрос колличества каналов АЦП устройства Err = ZGetQuantityChannelADC(typeDevice, numberDSP, &numChannelsADC); // Если опрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("ZGetQuantityChannelADC() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); getch(); return 0; } // Если опрос выполнился без ошибок else { // Вывод количества каналов АЦП устройства printf("Quantity of ADC channel: %ld\n\r", numChannelsADC); } // Запрос на включение первого канала АЦП устройства Err = ZSetInputADC(typeDevice, numberDSP, 0, 1); // Если запрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("ZSetInputADC() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); getch(); return 0; } // Если запрос выполнился без ошибок else { // Вывод информации об успешном включении первого канала АЦП устройства printf("First channel activation is successful...\n\r"); } // Если количество каналов устройства больше одного if(numChannelsADC > 1) { // Запрос на включение второго канала АЦП устройства Err = ZSetInputADC(typeDevice, numberDSP, 1, 1); // Если запрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("ZSetInputADC() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); getch(); return 0; } // Если запрос выполнился без ошибок else { // Вывод информации об успешном включении первого канала устройства printf("Second channel activation is successful...\n\r"); } } // Опрос коэффициента усиления по первому каналу АЦП Err = ZGetAmplifyADC(typeDevice, numberDSP, 0, &lifyADC0); // Если опрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("ZGetAmplifyADC() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); getch(); return 0; } // Если опрос выполнился без ошибок else { // Вывод коэффициента усиления по первому каналу АЦП printf("First channel amplifier: %f\n\r", amplifyADC0); } // Если количество каналов устройства больше одного if(numChannelsADC > 1) { // Опрос коэффициента усиления по второму каналу АЦП Err = ZGetAmplifyADC(typeDevice, numberDSP, 1, &lifyADC1); // Если опрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("ZGetAmplifyADC() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); getch(); return 0; } // Если опрос выполнился без ошибок else { // Вывод коэффициента усиления по второму каналу АЦП printf("Second channel amplifier: %f\n\r", amplifyADC1); } } // Опрос веса младшего разряда АЦП первого канала устройства Err = ZGetDigitalResolChanADC(typeDevice, numberDSP, 0, &resolutionADC0); // Если опрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("ZGetDigitalResolChanADC() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); getch(); return 0; } // Если опрос выполнился без ошибок else { // Вывод веса младшего разряда АЦП первого канала устройства printf("First channel digital resolution: %f\n\r", resolutionADC0); } // Если количество каналов устройства больше одного if(numChannelsADC > 1) { // Опрос веса младшего разряда АЦП второго канала устройства Err = ZGetDigitalResolChanADC(typeDevice, numberDSP, 1, &resolutionADC1); // Если опрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("ZGetDigitalResolChanADC() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); getch(); return 0; } else { // Вывод веса младшего разряда АЦП второго канала устройства printf("Second channel digital resolution: %f\n\r", resolutionADC1); } } Err = ZSetInputADC(typeDevice, numberDSP, 0.0, 1); Err = ZSetInputADC(typeDevice, numberDSP, 1.0, 1); Err = ZSetInputADC(typeDevice, numberDSP, 2.0, 0); Err = ZSetInputADC(typeDevice, numberDSP, 3.0, 0); Err = ZSetInputADC(typeDevice, numberDSP, 4.0, 0); Err = ZSetInputADC(typeDevice, numberDSP, 5.0, 0); Err = ZSetInputADC(typeDevice, numberDSP, 6.0, 0); Err = ZSetInputADC(typeDevice, numberDSP, 7.0, 0); Err = ZSetInputADC(typeDevice, numberDSP, 8.0, 0); Err = ZSetInputADC(typeDevice, numberDSP, 9.0, 0); Err = ZSetInputADC(typeDevice, numberDSP, 10.0, 0); Err = ZSetInputADC(typeDevice, numberDSP, 11.0, 0); Err = ZSetInputADC(typeDevice, numberDSP, 12.0, 0); Err = ZSetInputADC(typeDevice, numberDSP, 13.0, 0); Err = ZSetInputADC(typeDevice, numberDSP, 14.0, 0); Err = ZSetInputADC(typeDevice, numberDSP, 15.0, 0); if (Err != 0) { // Вывод информации об ошибке printf("Function ZSetInputADC() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); _getch();; return 0; } // Опрос количества включенных каналов АЦП устройства Err = ZGetNumberInputADC(typeDevice, numberDSP, &numChannelsADC); // Если опрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("Function ZGetNumberInputADC() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); getch(); return 0; } // Если опрос выполнился без ошибок else { // Вывод количества включенных каналов АЦП устройства printf("Quantity of activated ADC channel: %ld\n\r", numChannelsADC); } // Опрос количества слов в одном отсчета АЦП устройства Err = ZGetWordsADC(typeDevice, numberDSP, &numWordsADC); // Если опрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("ZGetWordsADC() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); getch(); return 0; } // Если опрос выполнился без ошибок else { // Вывод количества слов в одном отсчете АЦП устройства printf("Quantity of words: %ld\n\r", numWordsADC); } //список возможных частот дискретизации long next = 0; double freqIn = 0; double freq = 0; printf("List of possible discret. freq "); while (1) //бесконечный цикл { Err = ZGetListFreqADC(typeDevice, numberDSP, next, &freq); //получить if (freq > freqIn && freq <250000.0) freqIn = freq; //значение частоты if (Err != 0) break; //если ошибка, то выход из цикла printf("%E Hz\n", freq); //распечатать значение частоты next = 1; //при следующем обращении, будет //считываться следующее значение частоты } double freqOut = 0; printf("MAX discret. freq"); printf("%E Hz\n", freqIn); Err = ZSetFreqADC(typeDevice, numberDSP, freqIn, &freqOut); if (Err != 0) { // Вывод информации об ошибке printf("Function ZSetFreqADC() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); _getch();; return 0; } printf("Setup discret. freq"); printf("%E Hz\n", freqOut); // Проверка переменных, чтобы избежать деления на ноль if(numWordsADC == 0 || amplifyADC0 == 0 || amplifyADC1 == 0) { // Вывод информации об ошибке printf("Error DAC parameters\n\r"); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); getch(); return 0; } // Запрос буфера АЦП Err = ZGetBufferADC(typeDevice, numberDSP, (void**) &pBuffer16ADC, &sizeBufferADC); // Если запрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("Function ZGetBufferADC() return Error = 0x%X\n\r", Err); // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); getch(); return 0; } pBuffer32ADC = (long*) pBuffer16ADC; // Запрос на останов АЦП Err = ZStopADC(typeDevice, numberDSP); // Запрос на запуск АЦП Err = ZStartADC(typeDevice, numberDSP); ofstream file; file.open("test.txt", ios_base::out); // Цикл чтения данных АЦП while(!kbhit()) { // Задержка обновления данных АЦП для отображения //Sleep(10); // Запрос указателя на текущий элемент буфера Err = ZGetPointerADC(typeDevice, numberDSP, &pointerADC); // Если запрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("Function ZGetPointerADC() return Error = 0x%X\n\r", Err); // Выход из цикла break; } // Если новые данные в буфер от АЦП не поступили, то перейти в начало цикла и подождать //if(pointerADC == pointerADC_old) //continue; // Обновление предыдущего значения указателя pointerADC_old = pointerADC; // Переход на отсчет первого включенного канала последнего кадра АЦП if(pointerADC - numWordsADC * numChannelsADC < 0) pointerADC = sizeBufferADC + pointerADC - numWordsADC * numChannelsADC; else pointerADC = pointerADC - numWordsADC * numChannelsADC; // Вычисление из целого значения отсчета АЦП вещественного значение отсчета (в вольтах) для первого канала //if(numWordsADC == 1) volt0 = resolutionADC0 * (pBuffer16ADC[pointerADC]) / amplifyADC0; //else //volt0 = resolutionADC0 * (pBuffer32ADC[pointerADC / numWordsADC]) / amplifyADC0; // Вывод мгновенного значения напряжения для первого канала printf("%+8.4f", volt0); // Если количество каналов устройства больше одного if(numChannelsADC > 1) { // Переход на следующий отсчет АЦП pointerADC += numWordsADC; // При выходе за границу буфера, осуществляется переход в начало if(pointerADC >= sizeBufferADC) pointerADC = pointerADC - sizeBufferADC; // Вычисление из целого значения отсчета АЦП вещественного значение отсчета (в вольтах) для второго канала //if(numWordsADC == 1) volt1 = resolutionADC1 * (pBuffer16ADC[pointerADC]) / amplifyADC1; //else //volt1 = resolutionADC1 * (pBuffer32ADC[pointerADC/numWordsADC]) / amplifyADC1; // Вывод мгновенного значения напряжения для второго канала printf("\t%+8.4f", volt1); } printf("\n\r"); file << volt0 << " " << volt1 << endl; } file.close(); // Запрос на останов АЦП Err = ZStopADC(typeDevice, numberDSP); // Если запрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("Function ZStopADC() return Error = 0x%X\n\r", Err); } // Запрос на освобождение буфера АЦП if(pBuffer16ADC != NULL) { Err = ZRemBufferADC(typeDevice, numberDSP, (void**) &pBuffer16ADC); // Если запрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("Function ZRemBufferADC() return Error = 0x%X\n\r", Err); } } // Отключение от драйвера устройства Err = ZClose(typeDevice, numberDSP); // Если запрос выполнился с ошибкой if(Err != 0) { // Вывод информации об ошибке printf("Function ZClose() return Error = 0x%X\n\r", Err); } if(!kbhit()) getch(); printf("Press any key for exit..."); getch(); return 0; }
18.07.2018 в 15:21 #98639Добрый день!
Во-первых, Вы в бесконечном цикле считываете значения, поступившие в буфер АЦП и не используете Sleep, что будет приводить к тому, что ваша программа будет зависать.
Во-вторых, в файл Вы выводите одно единственное значение, полученное, когда указатель в буфере АЦП меняет свое значение. Указатель буфера изменяет свое значение не на один отсчет за раз, а на гораздо большее число. Это означает, что за одно изменение указателя в буфере появляется не одно новое значение, а много. Таким образом, чтобы получить в файле синус, Вам нужно писать туда все новые пришедшие отсчеты. Все новые пришедшие отсчеты хранятся в буфере с индекса pointerADC_old до индекса pointerADC (естественно нужно учитывать количество каналов и количество слов в одном отсчете АЦП). -
АвторОтветы
Для ответа в этой теме необходимо авторизоваться.