Форум ZETLAB

Архив обсуждений, технических вопросов и ответов по оборудованию, программному обеспечению и внедрению измерительных систем.

Страницы: 1
RSS
Работа с драйвером Zadc.dll
 
Добрый день, использую вашу продукцию (ZET 210) для дипломного проекта. Возник вопрос по функциям: long ZGetBufferADC(long typeDevice, long numberDSP, void **buffer, long *size) long ZGetMaxInterruptADC(long typeDevice, long numberDSP, long * size) При каждом запуске тестовой программы Test_Zadc.сpp размеры буферов меняются, принимая нулевые или отрицательные значения. Данные значения являются нормальными для функционирования? Также при увеличении частоты дискретизации частота обновления значений в буфере не увеличивается. Как можно решить данный вопрос?
 
Проблема с буферами ушла: ошибочно интерпретировали данные. Возник другой вопрос : при увеличении частоты дискретизации частота обновления значений в буфере не увеличивается. Как можно решить данный вопрос?
 
Добрый день! Есть несколько моментов, которые нужно учитывать при использовании устройств, подробно они описаны в статье по ссылке: https://zetlab.com/programmirovanie-ustroystv-s-ispolzovaniem-biblioteki-zadc-dll/napisanie-programmnyx-prilozhenij-dlya-kontrollera-zetlab/. Проверьте пожалуйста учтены ли данные рекомендации, и если да то опишите проблему подробнее.
 
Да данные моменты учитывались при использовании 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, &amplifyADC0);
   // Если опрос выполнился с ошибкой
   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, &amplifyADC1);
      // Если опрос выполнился с ошибкой
      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;
}
 
Добрый день! Во-первых, Вы в бесконечном цикле считываете значения, поступившие в буфер АЦП и не используете Sleep, что будет приводить к тому, что ваша программа будет зависать. Во-вторых, в файл Вы выводите одно единственное значение, полученное, когда указатель в буфере АЦП меняет свое значение. Указатель буфера изменяет свое значение не на один отсчет за раз, а на гораздо большее число. Это означает, что за одно изменение указателя в буфере появляется не одно новое значение, а много. Таким образом, чтобы получить в файле синус, Вам нужно писать туда все новые пришедшие отсчеты. Все новые пришедшие отсчеты хранятся в буфере с индекса pointerADC_old до индекса pointerADC (естественно нужно учитывать количество каналов и количество слов в одном отсчете АЦП).
Страницы: 1
Читают тему