-
Тема
-
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
Подскажите, пожалуйста, как исправить программу, чтобы при количестве каналов более двух порядок вывода значений напряжения был правильным.
Для ответа в этой теме необходимо авторизоваться.