ZetLab ZET 220 с интерфейсом USB нужно использовать как многоканальный АЦП (количество подключенных каналов не менее 8). Я взял пример с сайта ZetLab Test_Zadc_C++ и немного его переделал:
| Код |
|---|
#include <windows.h>
#include <conio.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <sstream>
#include "zadc_int.h"
using namespace std;
int ErrorMessage(std::string MessageError)
{
std::cout << MessageError << std::endl;
std::cin.get();
exit(EXIT_FAILURE);
}
template<typename T, long n>
inline long arraySize(const T(&arr)[n])
{
return n;
}
template<typename T>
inline string NumToStr(T num)
{
ostringstream stream;
stream << num;
string str = stream.str();
return str;
}
int main(int argc, char* argv[])
{
setlocale(LC_ALL, "");
long numChannelsOn[] = {1, 4, 15}; // 2, 5 и 16 каналы
//long numChannelsOn[] = {1, 15}; // программа работает правильно
long typeDevice = 16; // Тип устройства
long numberDSP = 0; // Порядковый номер сигнального процессора
long enable; // Флаг поддерживается / не поддерживается
long numChannelsADC; // Количество включенных каналов АЦП
long numWordsADC; // Количество слов (по два байта) в одном отсчете АЦП
short *pBuffer16ADC = NULL; // Указатель на начало буфера драйвера для АЦП с разрядностью не более 16 бит
long *pBuffer32ADC = NULL; // Указатель на начало буфера драйвера для АЦП с разрядностью более 16 бит
long sizeBufferADC; // Размер буфера драйвера в словах
long pointerADC = 0; // Указатель на текущий элемент заполнения буфера драйвера (кратен 2)
long pointerADC_old = 0; // Предыдущее значение указателя на буфер драйвера
// Открытие устройства
if(ZOpen(typeDevice, numberDSP) != 0 )
ErrorMessage("Не удалось открыть АЦП");
// Проверка возможности АЦП
if(ZGetEnableADC(typeDevice, numberDSP, &enable) != 0 && enable != 0)
ErrorMessage("Устройство не может работать как АЦП");
std::cout << "Устройство может работать как АЦП" << std::endl;
// Определение количества каналов
if(ZGetQuantityChannelADC(typeDevice, numberDSP, &numChannelsADC) != 0)
ErrorMessage("Не удалось определить общее количество каналов: " + NumToStr(numChannelsADC));
std::cout << "АЦП имеет " + NumToStr(numChannelsADC) + " каналов" << std::endl;
// Отключение всех каналов
enable = 0;
for(long i = 0; i < numChannelsADC; i++)
{
if(ZSetInputADC(typeDevice, numberDSP, i, enable) != 0)
std::cout << "Не удалось отключить канал: " + NumToStr(i) << std::endl;
}
long NumChannelsOn = arraySize(numChannelsOn); // число включенных каналов
// включение нужных каналов
enable = 1;
for(long i = 0; i < NumChannelsOn; i++)
{
if(ZSetInputADC(typeDevice, numberDSP, numChannelsOn[i], 1) != 0)
ErrorMessage("Не удалось включить канал: " + NumToStr(numChannelsOn[i]));
else
std::cout << "Включен канал: " + NumToStr(numChannelsOn[i] + 1) << std::endl;
}
// проверка правильности определения количества включенных каналов
if(ZGetNumberInputADC(typeDevice, numberDSP, &numChannelsADC) != 0)
ErrorMessage("Не удалось определить количество включенных каналов");
if(NumChannelsOn != numChannelsADC)
ErrorMessage("Количество нужных каналов " + NumToStr(NumChannelsOn) + " не соответствует "
+ NumToStr(numChannelsADC) + " включенным каналам");
std::cout << "Количество заданных каналов " + NumToStr(NumChannelsOn) +
" равно " + NumToStr(numChannelsADC) + " - результату выполнения функции ZGetNumberInputADC " << std::endl;
double *ardAmpl = new double[NumChannelsOn];
for (long i = 0; i < NumChannelsOn; i++)
{
if (ZGetAmplifyADC(typeDevice, numberDSP, numChannelsOn[i], &ardAmpl[i]) != 0)
ErrorMessage("Не удалось определить усиление канала: " + NumToStr(numChannelsOn[i]));
else
std::cout << "Усиление канала " + NumToStr(numChannelsOn[i] + 1) + " равно " + NumToStr(ardAmpl[i]) << std::endl;
}
// Опрос веса младшего разряда АЦП включенных каналов устройства
double *ardResol = new double[numChannelsADC];
for (long i = 0; i < NumChannelsOn; i++)
{
if (ZGetDigitalResolChanADC(typeDevice, numberDSP, numChannelsOn[i], &ardResol[i]) != 0)
ErrorMessage("Не удалось определить разрешение канала: " + NumToStr(i));
else
std::cout << "Разрешение канала " + NumToStr(numChannelsOn[i] + 1) + " равно " + NumToStr(ardResol[i]) << std::endl;
}
// Опрос количества слов в одном отсчета АЦП устройства
if (ZGetWordsADC(typeDevice, numberDSP, &numWordsADC) != 0)
ErrorMessage("Не удалось определить количество слов в одном отсчете АЦП");
else
std::cout << "В одном отсчета АЦП " + NumToStr(numWordsADC) + " слова" << std::endl;
// Запрос буфера АЦП
if (ZGetBufferADC(typeDevice, numberDSP, (void**) &pBuffer16ADC, &sizeBufferADC) != 0)
ErrorMessage("Не удалось определить буфер устройства");
pBuffer32ADC = (long*) pBuffer16ADC;
std::cout << "Указатель на буфер pBuffer32ADC равен " + NumToStr(pBuffer32ADC) << std::endl;
//Запрос на останов АЦП
if(ZStopADC(typeDevice, numberDSP) != 0)
ErrorMessage("Не удалось остановить устройство");
//Запрос на запуск АЦП
if(ZStartADC(typeDevice, numberDSP) != 0)
ErrorMessage("Не удалось запустить устройство");
double *volt = new double[numChannelsADC];
std::cout.setf(ios::fixed);
std::cout.width(10); // задает ширину поля
std::cout.precision(5); // задает количество знаков после десятичной точки
// Цикл чтения данных АЦП
while(!_kbhit())
{
// Задержка обновления данных АЦП для отображения
Sleep(500);
// Запрос указателя на текущий элемент буфера
if(ZGetPointerADC(typeDevice, numberDSP, &pointerADC) != 0)
ErrorMessage("Не удалось получить указатель на буфер устройства");
// Если новые данные в буфер от АЦП не поступили, то перейти в начало цикла и подождать
if(pointerADC == pointerADC_old)
continue;
// Обновление предыдущего значения указателя
pointerADC_old = pointerADC;
//Переход на отсчет первого включенного канала последнего кадра АЦП
if(pointerADC - numWordsADC * numChannelsADC < 0)
pointerADC = sizeBufferADC + pointerADC - numWordsADC * numChannelsADC;
else
pointerADC = pointerADC - numWordsADC * numChannelsADC;
volt[0] = ardResol[0] * (pBuffer32ADC[pointerADC / numWordsADC]) / ardAmpl[0];
cout << volt[0] << endl;
for(long i = 1; i < NumChannelsOn; i++)
{
//Переход на следующий отсчет АЦП
pointerADC += numWordsADC;
//При выходе за границу буфера, осуществляется переход в начало
if(pointerADC >= sizeBufferADC)
pointerADC = pointerADC - sizeBufferADC;
volt[i] = ardResol[i] * (pBuffer32ADC[pointerADC / numWordsADC]) / ardAmpl[i];
cout << volt[i] << endl;
} // for
cout << " ---------------------------------------------" << endl;
} // while
// Запрос на останов АЦП
if (ZStopADC(typeDevice, numberDSP) != 0)
ErrorMessage("Не удалось остановить устройство");
// Запрос на освобождение буфера АЦП
if(pBuffer16ADC != NULL)
{
if(ZRemBufferADC(typeDevice, numberDSP, (void**) &pBuffer16ADC) != 0)
ErrorMessage("Не удалось освободить буфер устройства");
}
// Отключение от драйвера устройства
if(ZClose(typeDevice, numberDSP) != 0)
ErrorMessage("Не удалось отключить устройство");
delete [] volt;
delete [] ardResol;
delete [] ardAmpl;
if(!_kbhit())
_getch();
std::cout << "Press any key for exit..." << std::endl;
_getch();
return 0;
} |
Проверку правильности работы программы я сделал на 3 каналах: второй канал подключил к одной батарейке (1,5 В), 5 и 16 каналы - соотвественно к 2 и 4 батарейкам (3 и 6 В). Значения напряжение определяются правильно, но вывод значений не соответствует порядку каналов:
| Код |
|---|
6.53385
1.45083
3.19009
---------------------------------------------
3.20306
6.51513
1.44911
---------------------------------------------
1.45500
3.19388
6.50739
---------------------------------------------
6.53386
1.45084
3.19009
---------------------------------------------
3.20306
6.51515
1.44911
---------------------------------------------
1.45500
3.19388
6.50740 |
Мне нужно строить графики и при таком выводе это невозможно. Если использовать только 2 канала (2 и 15) вместо трех, то вывод идет нормально:
| Код |
|---|
1.45499
6.47789
---------------------------------------------
1.45494
6.47786
---------------------------------------------
1.45501
6.47784
---------------------------------------------
1.45497
6.47788 |
Подскажите, пожалуйста, как исправить программу, чтобы при количестве каналов более двух порядок вывода значений напряжения был правильным.