Any suggestions for software to use with Tsunami to capture and plot frequency response data?
hrh1818
Haven't tried, but I would assume the sketch at [1], some terminal program to capture the output, and any spreadsheet/graphing program (like LibreOffice Calc) to import the resulting CSV file should work...
[1] - https://www.kickstarter.com/projects/nickjohnson/tsunami/posts/1171611
I am doing it like this:
1.) On ubuntu, deinstall modemmanager.
2.) Install the Frequency Generator Example, check that it works.
3.) Install Scilab, gcc for C++ on your host PC
I am then doing a sweep & record with this unfinished, half-baked piece of code:
#include <iostream>
#include <fstream>
#include <stdio.h> // standard input / output functions
#include <stdlib.h>
#include <string.h> // string function definitions
#include <unistd.h> // UNIX standard function definitions
#include <fcntl.h> // File control definitions
#include <errno.h> // Error number definitions
#include <termios.h> // POSIX terminal control definitions
#include <math.h>
#define NO_PERIODS 10
#define MINIMUM_TIME 500000
#define SWEEP_FROM 250
#define SWEEP_TO 22000
#define STEP 1.01
using namespace std;
extern int setfreq (int USB, float freq);
extern int setamp (int USB, float amp);
extern int readresponse (int USB);
extern float measurephase (int USB);
ofstream ofs;
int
main ()
{
ofs.open ("log.txt", ofstream::out);
cout << "starting" << endl;
int USB = open ("/dev/ttyACM0", O_RDWR | O_NOCTTY);
if (USB < 0)
{
cout << "Geht nicht auf" << endl;
}
struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);
/* Error Handling */
if (tcgetattr (USB, &tty) != 0)
{
cout << "Error " << errno << " from tcgetattr: " << strerror (errno) <<
endl;
}
/* Save old tty parameters */
tty_old = tty;
/* Set Baud Rate */
cfsetospeed (&tty, (speed_t) B115200);
cfsetispeed (&tty, (speed_t) B115200);
/* Setting other Port Stuff */
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;
tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_cc[VMIN] = 1; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
/* Make raw */
cfmakeraw (&tty);
/* Flush Port, then applies attributes */
tcflush (USB, TCIFLUSH);
if (tcsetattr (USB, TCSANOW, &tty) != 0)
{
cout << "Error " << errno << " from tcsetattr" << endl;
}
char cmd[161];
float i;
float f;
int d;
setamp (USB, 6);
readresponse (USB);
for (i = log (SWEEP_FROM); i < log (SWEEP_TO); i *= STEP)
{
f = exp (i);
setfreq (USB, f);
ofs << f << " ";
d = (1000000 / f) * NO_PERIODS;
d = (d < MINIMUM_TIME) ? MINIMUM_TIME : d;
usleep (d);
readresponse (USB);
measurephase (USB);
}
setamp (USB, 0.0);
readresponse (USB);
close (USB);
ofs.close ();
}
int
setfreq (int USB, float freq)
{
char cmd[161];
cout << "Setting freq to: " << freq << endl;
sprintf (cmd, "freq %f\r\n", freq);
int n_written = 0;
int spot = 0;
do
{
n_written = write (USB, &cmd[spot], 1);
spot += n_written;
}
while (cmd[spot - 1] != '\n' && n_written > 0);
return (0);
}
int
setamp (int USB, float amp)
{
char cmd[161];
sprintf (cmd, "amp %f\r\n", amp);
int n_written = 0, spot = 0;
do
{
n_written = write (USB, &cmd[spot], 1);
spot += n_written;
}
while (cmd[spot - 1] != '\n' && n_written > 0);
return (0);
}
int
readresponse (int USB)
{
int n = 0, spot = 0;
char buf[10];
/* Whole response*/
char response[1024];
memset (response, '\0', sizeof response);
do
{
n = read (USB, buf, 1);
response[spot] = buf[0];
spot += n;
}
while (buf[0] != '\r' && n > 0);
if (n < 0)
{
cout << "Error reading: " << strerror (errno) << endl;
}
else if (n == 0)
{
cout << "Read nothing!" << endl;
}
else
{
cout << "Response: " << response << endl;
}
}
float
measurephase (int USB)
{
char cmd[161];
sprintf (cmd, "measure\r\n");
int n_written = 0, spot = 0;
do
{
n_written = write (USB, &cmd[spot], 1);
spot += n_written;
}
while (cmd[spot - 1] != '\n' && n_written > 0);
int n = 0;
spot = 0;
char buf[10];
/* Whole response*/
char response[1024];
memset (response, '\0', sizeof response);
do
{
n = read (USB, buf, 1);
response[spot] = buf[0];
spot += n;
}
while (buf[0] != '\r' && n > 0);
if (n < 0)
{
cout << "Error reading: " << strerror (errno) << endl;
}
else if (n == 0)
{
cout << "Read nothing!" << endl;
}
else
{
cout << "Response: " << response << endl;
char xxx[128];
float e1, e2, e3;
sscanf (response, "%s %f %f %f", xxx, &e1, &e2, &e3);
ofs << e1 << " " << e2 << " " << e3 << endl;
}
}
This generates a file "log.txt" which is easy to load into scilab, once you have that only your mathematical abilites are the limit.
Example code for doing a bode plot:
expect=2300;
M=fscanfMat("~/measure_sihs/log.txt");
M=M';
for i=size(M,2):-1:1
devi=M(1,i)/M(2,i);
if( devi > 1.05 | devi < 0.95 | isnan(devi)) then
M(:,i)=[];
end
end
freqs=M(1,:);
phi=M(3,:);
mag=M(4,:);
mag=10*log10((mag/expect));
clf();
bode(freqs, mag, phi);
Beware: Some things are pretty weird with this.
e.g.
1.) Why 10*log10?
It should be 20 for Volts, but then it is not as it is in the simulation.
2.) for an RC highpass, the phase goes from 1 to 0. Simulation= 90° to 0°. Nick says 1=180°???
Enjoy!
Hello Henni,
Thank you for your reply.
Because I am a Python fan I an going to try using PYserial and Matplotlib to capture and plot the data. And use your method for back up.
hrh1818