mirror of
https://github.com/galera951/experiment-automation.git
synced 2026-07-11 03:53:28 +03:00
devices work
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
- [ ] Автоматическое подключение генератора
|
||||
- [ ] Автоматическая резонансная кривая (данные в файл)
|
||||
File diff suppressed because one or more lines are too long
+700000
-7000
File diff suppressed because it is too large
Load Diff
+700000
-7000
File diff suppressed because it is too large
Load Diff
@@ -1,14 +1,33 @@
|
||||
#include "Generator.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
Generator::Generator() : m_channel("C1")
|
||||
{
|
||||
std::string response = query("*IDN?");
|
||||
response.erase(0, response.find(',') + 1);
|
||||
response.erase(response.find(','));
|
||||
auto devices_path = files_path("/dev/usbtmc");
|
||||
bool success = false;
|
||||
|
||||
// name = response;
|
||||
for (auto const &device_path : devices_path)
|
||||
{
|
||||
m_root_path = device_path;
|
||||
std::string response = query("*IDN?");
|
||||
response.erase(0, response.find(',') + 1);
|
||||
response.erase(response.find(','));
|
||||
|
||||
if (response == "AKIP-3409-4")
|
||||
{
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success)
|
||||
throw std::runtime_error("Generator (AKIP-3409-4) is not available!");
|
||||
}
|
||||
|
||||
void Generator::command(std::string const &comm) const
|
||||
|
||||
@@ -1,10 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <filesystem>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
using port_t = std::size_t;
|
||||
using ind_t = std::size_t;
|
||||
|
||||
enum class channels
|
||||
{
|
||||
C1 = 1,
|
||||
C2 = 2
|
||||
};
|
||||
|
||||
using port_t = std::size_t;
|
||||
using ind_t = std::size_t;
|
||||
std::vector<std::string> files_path(std::string const &path)
|
||||
{
|
||||
size_t file_ind = path.find_last_of('/') + 1;
|
||||
std::string directory = path;
|
||||
directory.erase(file_ind);
|
||||
|
||||
auto directory_iterator = fs::directory_iterator(directory);
|
||||
std::vector<std::string> files_path;
|
||||
|
||||
for (const auto &directory_entry : directory_iterator)
|
||||
{
|
||||
auto filename = std::string(directory_entry.path());
|
||||
std::cout << filename << std::endl;
|
||||
if (!filename.find(path))
|
||||
files_path.push_back(filename);
|
||||
}
|
||||
|
||||
return files_path;
|
||||
}
|
||||
@@ -2,6 +2,12 @@
|
||||
#include "Oscilloscope.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
template <typename T>
|
||||
void func(T arg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
|
||||
Executable
+2
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
gcc gds.c -o gds -g
|
||||
Executable
+473
@@ -0,0 +1,473 @@
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/select.h>
|
||||
#include <sys/time.h>
|
||||
#include <getopt.h>
|
||||
|
||||
// Actually I don't know if oscilloscope tty is freely accessible by conventional users
|
||||
#define SETUID
|
||||
|
||||
#define GDS_BUFFER_LENGTH 1400026
|
||||
|
||||
char gds_buffer[GDS_BUFFER_LENGTH];
|
||||
int gds_buffer_length;
|
||||
|
||||
#define ERR_DEVICE_OPEN -1
|
||||
#define ERR_DEVICE_READ -2
|
||||
#define ERR_INP_FILE_OPEN -3
|
||||
#define ERR_OUT_FILE_OPEN -4
|
||||
#define ERR_INV_CHANNEL -5
|
||||
|
||||
struct record
|
||||
{
|
||||
char *keyword;
|
||||
char *value;
|
||||
};
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
#define GDS_OPT_HELP 'h'
|
||||
#define GDS_OPT_ASCII 'a'
|
||||
#define GDS_OPT_BINARY 'b'
|
||||
#define GDS_OPT_CONVERT 'c'
|
||||
#define GDS_OPT_ACQUIRE 'g'
|
||||
#define GDS_OPT_NO_HDR 'r'
|
||||
#define GDS_OPT_INPUT 'i'
|
||||
#define GDS_OPT_OUTPUT 'o'
|
||||
#define GDS_OPT_DEVICE 'd'
|
||||
#define GDS_OPT_CHANNEL 'n'
|
||||
|
||||
static const struct option gds_long_opt[] =
|
||||
{
|
||||
{"help", no_argument, NULL, GDS_OPT_HELP},
|
||||
{"ascii", no_argument, NULL, GDS_OPT_ASCII},
|
||||
{"binary", no_argument, NULL, GDS_OPT_BINARY},
|
||||
{"convert", no_argument, NULL, GDS_OPT_CONVERT},
|
||||
{"acquire", no_argument, NULL, GDS_OPT_ACQUIRE},
|
||||
{"no-hdr", no_argument, NULL, GDS_OPT_NO_HDR},
|
||||
{"input", required_argument, NULL, GDS_OPT_INPUT},
|
||||
{"output", required_argument, NULL, GDS_OPT_OUTPUT},
|
||||
{"device", required_argument, NULL, GDS_OPT_DEVICE},
|
||||
{"channel", required_argument, NULL, GDS_OPT_CHANNEL},
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
static const char* gds_opt_str = "abcghri:o:d:n:";
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
double gds_scan_double_key(char *str, struct record *keys, int max_keys)
|
||||
{
|
||||
int curr_key;
|
||||
double result;
|
||||
for (curr_key = 0; curr_key < max_keys; curr_key++)
|
||||
{
|
||||
if (!strcmp(keys[curr_key].keyword, str))
|
||||
{
|
||||
sscanf(keys[curr_key].value, "%lf", &result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
int gds_scan_int_key(char *str, struct record *keys, int max_keys)
|
||||
{
|
||||
int curr_key;
|
||||
int result;
|
||||
for (curr_key = 0; curr_key < max_keys; curr_key++)
|
||||
{
|
||||
if (!strcmp(keys[curr_key].keyword, str))
|
||||
{
|
||||
sscanf(keys[curr_key].value, "%d", &result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
int gds_acquire(char *dev_file_name, int channel_number)
|
||||
{
|
||||
int dev_fd;
|
||||
int error;
|
||||
#ifdef SETUID
|
||||
int old_uid, old_gid;
|
||||
int uid_changed = 0;
|
||||
#endif // SETUID
|
||||
struct termios old_dev_tio, new_dev_tio;
|
||||
|
||||
fd_set dev_read_fds;
|
||||
struct timeval dev_tv;
|
||||
|
||||
char *dev_cmd_read_request = (channel_number == 1) ? "C1:WF? DAT2\n" : "C2:WF? DAT2\n";
|
||||
|
||||
int dev_data_index = 0;
|
||||
int dev_read_len;
|
||||
|
||||
#ifdef SETUID
|
||||
if ((dev_fd = open(dev_file_name, O_RDWR | O_NOCTTY)) < 0) // check if we have permissions
|
||||
{
|
||||
old_uid = getuid(); old_gid = getgid();
|
||||
if (setuid(0) || setgid(0))
|
||||
{
|
||||
fprintf(stderr, "**Error**: You have no permissions to access \"%s\"\n"
|
||||
" Setting UID and GID to root failed\n", dev_file_name);
|
||||
return ERR_DEVICE_OPEN;
|
||||
}
|
||||
|
||||
uid_changed = 1;
|
||||
// already root:wheel
|
||||
if ((dev_fd = open(dev_file_name, O_RDWR | O_NOCTTY)) < 0)
|
||||
{
|
||||
fprintf(stderr, "**Error**: Error opening device \"%s\"\n", dev_file_name);
|
||||
setuid(old_uid); setgid(old_gid);
|
||||
return ERR_DEVICE_OPEN;
|
||||
}
|
||||
}
|
||||
#else // SETUID
|
||||
if ((dev_fd = open(dev_file_name, O_RDWR | O_NOCTTY)) < 0)
|
||||
{
|
||||
fprintf(stderr, "**Error**: Error opening device \"%s\"\n", dev_file_name);
|
||||
return ERR_DEVICE_OPEN;
|
||||
}
|
||||
#endif // SETUID
|
||||
|
||||
tcgetattr(dev_fd, &old_dev_tio);
|
||||
bzero(&new_dev_tio, sizeof(new_dev_tio));
|
||||
new_dev_tio.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
|
||||
new_dev_tio.c_iflag = IGNBRK | IXON | IXOFF;
|
||||
new_dev_tio.c_oflag = 0;
|
||||
new_dev_tio.c_lflag = 0;
|
||||
new_dev_tio.c_cc[VTIME] = 5;
|
||||
new_dev_tio.c_cc[VMIN] = 1;
|
||||
new_dev_tio.c_ispeed = 13;
|
||||
new_dev_tio.c_ospeed = 13;
|
||||
tcflush(dev_fd, TCIFLUSH);
|
||||
tcsetattr(dev_fd, TCSANOW, &new_dev_tio);
|
||||
|
||||
write(dev_fd, dev_cmd_read_request, strlen(dev_cmd_read_request));
|
||||
|
||||
FD_ZERO(&dev_read_fds);
|
||||
FD_SET(dev_fd, &dev_read_fds);
|
||||
|
||||
while (1)
|
||||
{
|
||||
dev_tv.tv_sec = 0;
|
||||
dev_tv.tv_usec = 200000;
|
||||
error = select(dev_fd + 1, &dev_read_fds, NULL, NULL, &dev_tv);
|
||||
switch(error)
|
||||
{
|
||||
case -1:
|
||||
fprintf(stderr, "**Error**: Error reading from device: select() failed with errorcode %d\n", error);
|
||||
close(dev_fd);
|
||||
return ERR_DEVICE_READ;
|
||||
case 0:
|
||||
close(dev_fd);
|
||||
gds_buffer_length = dev_data_index;
|
||||
#ifdef SETUID
|
||||
if (uid_changed) // reset uid/gid to create files belonging to current user but not root
|
||||
{
|
||||
setuid(old_uid);
|
||||
setgid(old_gid);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
default:
|
||||
dev_read_len = read(dev_fd, gds_buffer + dev_data_index, GDS_BUFFER_LENGTH - dev_data_index);
|
||||
dev_data_index += dev_read_len;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
int gds_save_binary_file(char *filename)
|
||||
{
|
||||
int out_fd;
|
||||
|
||||
if ((out_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC)) < 0)
|
||||
{
|
||||
fprintf(stderr, "**Error**: Error opening output file %s\n", filename);
|
||||
return ERR_OUT_FILE_OPEN;
|
||||
} else
|
||||
{
|
||||
fchmod(out_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); // set 644 mode
|
||||
write(out_fd, gds_buffer, gds_buffer_length);
|
||||
close(out_fd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
int gds_read_binary_file(char *filename)
|
||||
{
|
||||
int in_fd;
|
||||
|
||||
if ((in_fd = open(filename, O_RDONLY)) == 0)
|
||||
{
|
||||
fprintf(stderr, "**Error**: Error opening data file \"%s\"\n", filename);
|
||||
return ERR_INP_FILE_OPEN;
|
||||
} else
|
||||
{
|
||||
gds_buffer_length = read(in_fd, gds_buffer, GDS_BUFFER_LENGTH);
|
||||
close(in_fd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
int gds_save_ascii_file(char *filename, int header_flag)
|
||||
{
|
||||
#define MAX_KEYS 30
|
||||
struct record keys[MAX_KEYS];
|
||||
char *data_ptr;
|
||||
int i, header_length, curr_key, max_keys, max_key_len;
|
||||
double curr_time;
|
||||
FILE *out_file;
|
||||
|
||||
union {
|
||||
short s;
|
||||
char b[2];
|
||||
} short_val;
|
||||
|
||||
int Memory_Length;
|
||||
double Vertical_Scale;
|
||||
double Horizontal_Position;
|
||||
double Sampling_Period;
|
||||
|
||||
if (( out_file = fopen(filename, "wt")) == NULL)
|
||||
{
|
||||
printf("**Error**: Error opening output file \"%s\"\n", filename);
|
||||
return ERR_OUT_FILE_OPEN;
|
||||
} else
|
||||
{
|
||||
for(i = 0; i < GDS_BUFFER_LENGTH; i++)
|
||||
{
|
||||
if (gds_buffer[i] == 10)
|
||||
{
|
||||
gds_buffer[i] = 0;
|
||||
header_length = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (curr_key = 0; curr_key < MAX_KEYS; curr_key++)
|
||||
{
|
||||
keys[curr_key].keyword = NULL;
|
||||
keys[curr_key].value = NULL;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
for(curr_key = 0; curr_key < MAX_KEYS; curr_key++)
|
||||
{
|
||||
keys[curr_key].keyword = gds_buffer + i;
|
||||
for( ; ; i++)
|
||||
{
|
||||
if (gds_buffer[i] == 0)
|
||||
{
|
||||
max_keys = curr_key;
|
||||
goto keys_done;
|
||||
}
|
||||
if (gds_buffer[i] == ',')
|
||||
{
|
||||
keys[curr_key].value = gds_buffer + i + 1;
|
||||
gds_buffer[i] = 0;
|
||||
}
|
||||
if (gds_buffer[i] == ';')
|
||||
{
|
||||
keys[curr_key + 1].keyword = gds_buffer + i + 1;
|
||||
gds_buffer[i] = 0;
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
keys_done:
|
||||
|
||||
if (header_flag) // put header
|
||||
{
|
||||
max_key_len = 0;
|
||||
for (curr_key = 0; curr_key < max_keys; curr_key++)
|
||||
{
|
||||
if (strlen(keys[curr_key].keyword) > max_key_len)
|
||||
{
|
||||
max_key_len = strlen(keys[curr_key].keyword);
|
||||
}
|
||||
}
|
||||
|
||||
for (curr_key = 0; curr_key < max_keys; curr_key++)
|
||||
{
|
||||
fprintf(out_file, "# \"%s\" ", keys[curr_key].keyword);
|
||||
for (i = 0; i < max_keys - strlen(keys[curr_key].keyword); i++)
|
||||
{
|
||||
fprintf(out_file, " ");
|
||||
}
|
||||
fprintf(out_file, "\"%s\"\n", keys[curr_key].value ? keys[curr_key].value : "");
|
||||
}
|
||||
fprintf(out_file, "\n");
|
||||
}
|
||||
|
||||
Memory_Length = gds_scan_int_key ("Memory Length", keys, max_keys);
|
||||
Vertical_Scale = gds_scan_double_key("Vertical Scale", keys, max_keys);
|
||||
Horizontal_Position = gds_scan_double_key("Horizontal Position", keys, max_keys);
|
||||
Sampling_Period = gds_scan_double_key("Sampling Period", keys, max_keys);
|
||||
|
||||
curr_time = -(double)Memory_Length * Sampling_Period / 2.0 + Horizontal_Position;
|
||||
|
||||
data_ptr = gds_buffer + header_length + 10; // skip #72000000
|
||||
fprintf(out_file, "# Time, s\tReading, raw\tReading, V\n");
|
||||
for (i = 0; i < Memory_Length; i++)
|
||||
{
|
||||
short_val.b[0] = data_ptr[2*i+1];
|
||||
short_val.b[1] = data_ptr[2*i];
|
||||
fprintf(out_file, "%le\t%d\t\t%le\n", curr_time, short_val.s, short_val.s * Vertical_Scale * 10.0 / 256.0);
|
||||
curr_time += Sampling_Period;
|
||||
}
|
||||
|
||||
fclose(out_file);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
void usage(void)
|
||||
{
|
||||
#ifdef SETUID
|
||||
#define SETUID_STATE "SETUID"
|
||||
#else // SETUID
|
||||
#define SETUID_STATE
|
||||
#endif // SETUID
|
||||
printf("gds [-abcgh] [-i <filename>] [-o <filename>] [-d <devname>]\n"
|
||||
"GDS-72302 oscilloscope data retrieving program " SETUID_STATE "\n"
|
||||
"(C) S. Ambrozevich <s.ambrozevich@mail.ru>, LPI\n"
|
||||
"v. 0.3 compiled " __DATE__ " " __TIME__ "\n\n"
|
||||
"Options:\n"
|
||||
" -c, --convert - convert previously saved binary data to ASCII form\n"
|
||||
" -g, --acquire - gather data from oscilloscope (default)\n"
|
||||
" -r, --no-hdr - do not store header information in ASCII output\n"
|
||||
" -a, --ascii - generate output in ASCII form\n"
|
||||
" -b, --binary - generate output in binary form (raw data)\n"
|
||||
" -i, --input=file - input file to convert, default = stdin\n"
|
||||
" -o, --output=file - output file to store data, default = stdout\n"
|
||||
" -d, --device=dev - device tty to communicate with, default = /dev/ttyACM0\n"
|
||||
" -n, --channel=n - channel number <1|2> to acquire, default = 2\n"
|
||||
" -h, --help - prints this help\n\n"
|
||||
"NOTE: \"gds -cb\" will only copy input binary stream to output\n");
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int errorcode;
|
||||
int ascii_flag = 1;
|
||||
int convert_flag = 0;
|
||||
int header_flag = 1;
|
||||
int input_file_flag = 0;
|
||||
int output_file_flag = 0;
|
||||
int device_file_flag = 0;
|
||||
int channel_number = 2;
|
||||
int opt, opt_ind;
|
||||
|
||||
char *input_file;
|
||||
char *output_file;
|
||||
char *device_file;
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((opt = getopt_long(argc, argv, gds_opt_str, gds_long_opt, NULL)) != -1)
|
||||
{
|
||||
switch(opt)
|
||||
{
|
||||
case GDS_OPT_ASCII:
|
||||
ascii_flag = 1;
|
||||
break;
|
||||
|
||||
case GDS_OPT_BINARY:
|
||||
ascii_flag = 0;
|
||||
break;
|
||||
|
||||
case GDS_OPT_CONVERT:
|
||||
convert_flag = 1;
|
||||
break;
|
||||
|
||||
case GDS_OPT_ACQUIRE:
|
||||
convert_flag = 0;
|
||||
break;
|
||||
|
||||
case GDS_OPT_NO_HDR:
|
||||
header_flag = 0;
|
||||
break;
|
||||
|
||||
case GDS_OPT_DEVICE:
|
||||
device_file_flag = 1;
|
||||
device_file = optarg;
|
||||
break;
|
||||
|
||||
case GDS_OPT_INPUT:
|
||||
input_file_flag = 1;
|
||||
input_file = optarg;
|
||||
break;
|
||||
|
||||
case GDS_OPT_OUTPUT:
|
||||
output_file_flag = 1;
|
||||
output_file = optarg;
|
||||
break;
|
||||
|
||||
case GDS_OPT_CHANNEL:
|
||||
sscanf(optarg, "%d", &channel_number);
|
||||
if ((channel_number < 1) || (channel_number > 2))
|
||||
{
|
||||
fprintf(stderr, "**Error**: Invalid channel number %d\n", channel_number);
|
||||
return ERR_INV_CHANNEL;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (convert_flag)
|
||||
{ // convert
|
||||
if (errorcode = gds_read_binary_file(input_file_flag ? input_file : "/dev/stdin") != 0)
|
||||
{
|
||||
return errorcode;
|
||||
}
|
||||
} else
|
||||
{ // read
|
||||
if (errorcode = gds_acquire(device_file_flag ? device_file : "/dev/ttyACM0", channel_number) != 0)
|
||||
{
|
||||
return errorcode;
|
||||
}
|
||||
}
|
||||
|
||||
if (ascii_flag)
|
||||
{ // write ascii
|
||||
if (errorcode = gds_save_ascii_file(output_file_flag ? output_file : "/dev/stdout", header_flag) != 0)
|
||||
{
|
||||
return errorcode;
|
||||
}
|
||||
} else
|
||||
{ // write binary
|
||||
if (errorcode = gds_save_binary_file(output_file_flag ? output_file : "/dev/stdout") != 0)
|
||||
{
|
||||
return errorcode;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
# Time, s Reading, raw Reading, V
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
#works only for ascii files with headers
|
||||
#prints every 100th line
|
||||
cat $1 | sed '1,/Waveform/d' | awk '!(NR%100)||(NR==2)'> $2
|
||||
Reference in New Issue
Block a user