All,
I'm attempting to use Python and DAQmx Base to record analog input and generate analog output from my USB 6009 device. I've been using a wrapper I found and have been able to get AI but am struggling with AO.
There is a base class NITask which handles task generation etc. The class i'm calling is below. The function throws an error when I try to configure the clock. When I do not there is no error but nor is there voltage generated on the output. Any help would be appreciated.
Thanks!
class AOTask(NITask):
def __init__(self, min=0.0, max=5.0,
channels=["Dev1/ao0"],
timeout=10.0):
NITask.__init__(self)
self.min = min
self.max = max
self.channels = channels
self.timeout = timeout
self.clockSource ="OnboardClock"
sampleRate=100
self.sampleRate = 100
self.timeout = timeout
self.samplesPerChan = 1000
self.numChan = chanNumber(channels)
if self.numChan is None:
raise ValueError("Channel specification is invalid")
chan = ", ".join(self.channels)
self.CHK(self.nidaq.DAQmxBaseCreateTask("",ctypes.byref(self.taskHandle)))
self.CHK(self.nidaq.DAQmxBaseCreateAOVoltageChan(self.taskHandle, "Dev1/ao0", "", float64(self.min), float64(self.max), DAQmx_Val_Volts, None))
self.CHK(self.nidaq.DAQmxBaseCfgSampClkTiming(self.taskHandle, "", float64(self.sampleRate), DAQmx_Val_Rising, DAQmx_Val_FiniteSamps, uInt64(self.samplesPerChan)))
"""Data needs to be of type ndarray"""
def write(self, data):
nWritten = int32()
# data = numpy.float64(3.25)
data = data.astype(numpy.float64)
self.CHK(self.nidaq.DAQmxBaseWriteAnalogF64(self.taskHandle,
int32(1000), 0,float64(-1),DAQmx_Val_GroupByChannel,
data.ctypes.data,None,None))
# if nWritten.value != self.numChan:
# print "Expected to write %d samples!" % self.numChan
Your question covers two problems:
Why does DAQmxBaseCfgSampClkTiming return an error?
Without using that function, why isn't any output generated?
1. Hardware vs Software Timing
rjb3 wrote:
The function throws an error when I try to configure the clock. When I do not there is no error but nor is there voltage generated on the output.
Your program receives the error because the USB 600x devices do not support hardware-timed analog output [1]:
The NI USB-6008/6009 has two independent analog output channels that can generate outputs from 0 to 5 V. All updates of analog output channels are software-timed. GND is the ground-reference signal for the analog output channels.
"Software-timed" means a sample is written on demand by the program whenever DAQmxBaseWriteAnalogF64 is called. If an array of samples is written, then that array is written one at a time. You can learn more about how NI defines timing from the DAQmx help [2]. While that document is for DAQmx, the same concepts apply to DAQmx Base since the behavior is defined by the devices and not their drivers. The differences are in how much of the hardware's capabilities are implemented by the driver -- DAQmx implements everything, while DAQmx Base is a small select subset.
2. No Output When Software Timed
rjb3 wrote:
When I do not there is no error but nor is there voltage generated on the output.
I am not familiar with the Python bindings for the DAQmx Base API, but I can recommend two things:
Try using the installed genVoltage.c C example and confirm that you can see voltage on the ao channel.
Examples are installed here: /Applications/National Instruments/NI-DAQmx Base/examples
If you see output, you've confirmed that the device and driver are working correctly, and that the bug is likely in the python file.
If you don't see output, then the device or driver has a problem, and the best place to get help troubleshooting is the NI discussion forums at http://forums.ni.com.
Try porting genVoltage.c using the python bindings. At first glance, I would try:
Use DAQmxBaseStartTask before DAQmxBaseWriteAnalogF64
Or set the autostart parameter in your call to DAQmxBaseWriteAnalogF64 to true.
References
[1] NI USB-6008/6009 User Guide And Specifications :: Analog Output (page 16)
http://digital.ni.com/manuals.nsf/websearch/CE26701AA052E1F0862579AD0053BE19
[2] Timing, Hardware Versus Software
http://zone.ni.com/reference/en-XX/help/370466V-01/TOC11.htm
Related
As part of a project I'm comparing the effectiveness of different wireless communication methods for measuring distance. I am using RSSI for all forms (I'm aware it's imprecise but the extent of which is the point of the project). I'm planning on comparing Bluetooth Trad, BLE, Wi-Fi and ESP-NOW.
Currently Wi-Fi and ESP-NOW are working and I'm working on Bluetooth trad. I'm able to use the inbuilt examples to find my device and print it to the console. However, how can I access the data stored within BTScanResults.
For example the pseudo would be:
if name == "ESP32test":
Serial print rssi of name:
delay(1s)
The reason it needs to be in this format is the serial output is being taken directly into Microsoft Excel for data formatting and there will be thousands of data points so manual recording is not feasible.
Thanks for any help, Matt
I had made a little program to log all Blutooth devices advertised in the vicinity. To find the name and the RSSI I used:
String(advertisedDevice.getName().c_str()); to get the name
and
advertisedDevice.getRSSI(); to get the RSSI.
Below is how it looks in the actual code, with only the essentials left in for brevity. BleLog[] is just a struct array that holds a table of results.
It works in general but for some reason the RSSI is reported most of the time but not always.
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
{
void onResult(BLEAdvertisedDevice advertisedDevice)
{
printResult(advertisedDevice);
parseResult(advertisedDevice);
.............
}
};
void parseResult(BLEAdvertisedDevice advertisedDevice)
{
......................
// Fill in the data for the log entry
BleLog[foundAddress].occurences = oldBleLog[foundAddress].occurences+1;
BleLog[foundAddress].lastRssi = advertisedDevice.getRSSI();
BleLog[foundAddress].lastSeen = millis();
BleLog[foundAddress].deviceName = String(advertisedDevice.getName().c_str());
BleLog[foundAddress].addressType = advertisedDevice.getAddressType();
...................
}
I'm working on a project for a real-time communication between my computer and an external server. The communication between my computer and the server works well. I send a request from my C++ - code to the server and get a response in C++.
The problems are the sending of the matlab data to the C++ - code and the evaluation of the server data in Matlab/Simulink. For that I have to transfer data in real-time between Matlab/Simulink and a C++ project in Visual Studio. I felt that I have read the whole internet in the last days, but I didn't find a perfect answer for my problem.
Here are some solutions that could work:
Creating a mex-File in Matlab and save it in a specific folder. Then let my C++ - Code search for new file in this folder and get the data from the file. After the response of the server the C++ - Code should create a new mex-File and save it in an other specific folder. Meanwhile Matlab would search for a new file and would load it into the workspace.
I don't think that this would provide a real-time data transfer, but maybe works quite well.
Creating a TCP/IP-Connection between Matlab and Visual Studio to exchange data directly.
I have no clue, whether it is even possible nor I know how to write a socket.
I hope, that someone may have some experience with my problem and could help me to find the best way to handle it. I'm thankful for every answer!
I'm using Matlab/Simulink R2017a and Visual Studio 2017 Enterprise on Windows 10.
This is a frequent requirement for me, and I use your second option, sockets for real-time communication. Below is a function I wrote for real-time display of signal data. Although some code in the original function has been elided, it should give you a good idea of how to use TCP sockets in Matlab to read real-time data. My requirements are to be able to read multi-channel audio in real-time, and the function below performs well enough for this on my desktop machine.
function [ sig ] = liveplot( host, port, signal_info, Fs, window_size_secs )
%LIVEPLOT Plot live data from the signal processing engine
% The signal processing engine will send out data as a multiplexed stream
% of N double-precision values.
% The 'signal_info' argument should be a logical matrix of length N, where N is the
% number of channels that are being multiplexed. if signal_info(K) is
% true, then that channel will be plotted.
MAX_SESSION_TIME_SECS = 60;
FRAMES_PER_SESSION = MAX_SESSION_TIME_SECS * Fs;
FRAMES_PER_WINDOW = window_size_secs * Fs;
REFRESH_TIME_SECS = 0.05;
SAMPLE_DURATION=1/Fs;
N = length(signal_info);
FRAME_SZ = N * 8; % sizeof(double)
conn = tcpip(host, port);
conn.InputBufferSize = 1024 * FRAME_SZ;
conn.BytesAvailableFcnCount = conn.InputBufferSize;
conn.BytesAvailableFcnMode = 'byte';
conn.BytesAvailableFcn = #bytesavailablecallback;
conn.readAsyncMode = 'continuous';
seconds_read = 0;
asyncread_tic = tic;
% bytesavailablecallback(conn);
% time window: incremented buy SAMPLE_DURATION each frame
num_frames = 0;
%Set up Plot
% plot objects, one for each N stream in frame
h = figure;
hold on %hold on makes sure all of the channels are plotted
% Start the async read thread
fopen(conn);
last_refresh = tic;
while ishandle(h) %Loop when Plot is Active will run until plot is closed
try
% if (toc(last_refresh) > REFRESH_TIME_SECS)
if (seconds_read < window_size_secs)
seconds_read = window_size_secs;
end
xlim([seconds_read-window_size_secs seconds_read]);
% refreshdata(h, 'caller');
% fprintf('Refresh took %f seconds.\n', toc(last_refresh));
drawnow limitrate
last_refresh = tic;
catch ME
break
end
% end
end
fclose(conn);
delete(conn);
function bytesavailablecallback(conn, ~)
% initiate another read immediately to fill the buffer
% readasync(conn, conn.InputBufferSize-conn.BytesAvailable);
n_frames_available = floor(conn.BytesAvailable / (N * 8));
if (n_frames_available > 0)
[frames_read, nread] = fread(conn, N * n_frames_available, 'double');
num_frames_read = nread / N;
if (num_frames_read ~= n_frames_available)
throw(MException('assert',sprintf('%d frames expected, but %d read',n_frames_available,num_frames_read )));
end
% need the following line when only partial read - fread fails to
% reshape the return value if nread < FRAMES_PER_READ
sig(:, 1+num_frames:num_frames+num_frames_read) = reshape(frames_read, N, []);
num_frames = num_frames + num_frames_read;
seconds_read = num_frames * SAMPLE_DURATION;
for i=1:N
ph = plots(i);
if (ph ~= 0)
set(ph, 'Ydata', sig(i,:));
end
end
async_read_time = toc(asyncread_tic);
asyncread_tic = tic;
fprintf('Read %d frames in %f seconds, rate is %d fps\n', num_frames_read, async_read_time, round(num_frames_read / async_read_time));
end
end
end
I suggest you review the advice in the MATLAB help topic: MATLAB->Advanced Software Development -> External Programming Interfaces
This essentially gives you three options for calling C/C++ code:
calling functions in MEX files (Help topic: Call Mex-Files)
connecting to a COM or ActiveX server (Help topic: COM interface)
calling functions in a .dll (Help topic: C Shared Libraries)
Over the years I have used the last two options.
The real hassle when using MATLAB to drive communications comes when you need callbacks and events. This is because general-purpose MATLAB code all runs in the Event Dispatch Tread of Java Swing.
MATLAB also gives you the option to work the other way: you can call MATLAB functions from other languages. See the the help topic:
Application Programming Interfaces to MATLAB: Write programs in other languages, for example C/C++ and Fortran, to interface with MATLAB functionality
As it happens, I have never used this.
I can not advise on whether the Parallel Processing Toolbox is helpful in dealing with asynchronous communications. Neither can I advise on using sockets, pipes, HTTP or the like.
I wish you success with your project.
I am using Pyserial (+Python 2.7) to read in eye-tracking coordinates taken from an eye-tracker (CRS Live-Track set as serial port). Using the code below I am able to successfully start the tracker, read/save a line of coordinates, stop the tracker, and close. My problem is I need to continuously read in the coordinates whilst carrying out other tasks such as stimuli display. As it stands, I can't do anything whilst I'm reading in data ('trial1 = ser.readline'). I have to wait until I've read in the data before I continue. Is there a way to read in the data from the serial port continuously whilst I am displaying stimuli/collecting responses etc.?
I need to turn the tracker on, collect the data for the duration of the trial, and then tracker off.
import serial, time
ser = serial.Serial(
port='COM3',
baudrate=9600,
parity=serial.PARITY_ODD,
stopbits=serial.STOPBITS_TWO,
bytesize=serial.SEVENBITS,
)
x = ser.is_open #check port is open
if x:
print "port is open"
print "port name is: %s" %(ser.name) #check which port
ser.flushInput()
ser.flushOutput()
running = True
while running:
ser.write('$Raw\r') #start eye-tracker
trial1 = ser.readline() #read a line
###i need to do stuff here###
ser.write('$Stop\r') #stop eye-tracker
running = False
ser.flushInput()
ser.flushOutput()
print trial1 #print coordinates output
ser.close()
Cheers,
Steve
ioHub by Sol Simpson provides asynchronous device monitoring from within PsychoPy. i.e it operates on an entirely separate process so you don't have to pause while monitoring the port in the main PsychoPy thread.
Serial port documentation in ioHub seems scarce but there is a demo here: https://github.com/psychopy/psychopy/blob/master/psychopy/demos/coder/iohub/serial/customparser.py
Another option would be to try threads. You could put your eye tracker in one thread and the rest of your code in another. There is a stack overflow answer about multithreading (not using psychopy and eye trackers) from 2010. If you scroll down you will see that someone links to a blog post about an updated approach that they think is easier.
I'm trying to create an DHT11-based temperature/humidity sensor with Intel Edison and mraa via Python:
The documentation for Python's mraa package was a bit thin on example code.
There's a lookup table to associate physical pins to mraa pin numbers. The GP44 pin on the breakout board is mraa pin 31:
>>> import mraa
>>> mraa.INTEL_EDISON_GP44
31
The gp44 port was configured as an ouput port:
>>> gp44_pin = mraa.Gpio(31)
>>> gp44_pin.dir(mraa.DIR_OUT)
When I read from the gp44 pin it returns zero:
>>> gp44_pin.read()
0
Looking at the C examples, it seems that the DHT11 sensor returns a byte array that can be deciphered. I stumbled across some more specific instructions to decode the bytes but, undfortunately, the code examples were specific to the Raspberry Pi and I'm working with Intel Edison.
Ideally, I'd like to call methods that return temperature and humidity, but a byte array would would also work since I have the 'decoder ring'. Can you see what needs to be done in order to return the temperature/humidity (or byte array)?
A sample C code for DHT11 with Intel Edison is there in one of the links you already shared. One of the section "The Software" describes in detail how the sample program is designed to read the data.
Also there is a discussion on this thread on issues with DHT11 sensor or any other sensor that uses one wire with Edison or similar boards.
I tried creating a simple libtorrent python client (for magnet uri), and I failed, the program never continues past the "downloading metadata".
If you may help me write a simple client it would be amazing.
P.S. When I choose a save path, is the save path the folder which I want my data to be saved in? or the path for the data itself.
(I used a code someone posted here)
import libtorrent as lt
import time
ses = lt.session()
ses.listen_on(6881, 6891)
params = {
'save_path': '/home/downloads/',
'storage_mode': lt.storage_mode_t(2),
'paused': False,
'auto_managed': True,
'duplicate_is_error': True}
link = "magnet:?xt=urn:btih:4MR6HU7SIHXAXQQFXFJTNLTYSREDR5EI&tr=http://tracker.vodo.net:6970/announce"
handle = lt.add_magnet_uri(ses, link, params)
ses.start_dht()
print 'downloading metadata...'
while (not handle.has_metadata()):
time.sleep(1)
print 'got metadata, starting torrent download...'
while (handle.status().state != lt.torrent_status.seeding):
s = handle.status()
state_str = ['queued', 'checking', 'downloading metadata', \
'downloading', 'finished', 'seeding', 'allocating']
print '%.2f%% complete (down: %.1f kb/s up: %.1f kB/s peers: %d) %s %.3' % \
(s.progress * 100, s.download_rate / 1000, s.upload_rate / 1000, \
s.num_peers, state_str[s.state], s.total_download/1000000)
time.sleep(5)
What happens it is that the first while loop becomes infinite because the state does not change.
You have to add a s = handle.status (); for having the metadata the status changes and the loop stops. Alternatively add the first while inside the other while so that the same will happen.
Yes, the save path you specify is the one that the torrents will be downloaded to.
As for the metadata downloading part, I would add the following extensions first:
ses.add_extension(lt.create_metadata_plugin)
ses.add_extension(lt.create_ut_metadata_plugin)
Second, I would add a DHT bootstrap node:
ses.add_dht_router("router.bittorrent.com", 6881)
Finally, I would begin debugging the application by seeing if my network interface is binding or if any other errors come up (my experience with BitTorrent download problems, in general, is that they are network related). To get an idea of what's happening I would use libtorrent-rasterbar's alert system:
ses.set_alert_mask(lt.alert.category_t.all_categories)
And make a thread (with the following code) to collect the alerts and display them:
while True:
ses.wait_for_alert(500)
alert = lt_session.pop_alert()
if not alert:
continue
print "[%s] %s" % (type(alert), alert.__str__())
Even with all this working correctly, make sure that torrent you are trying to download actually has peers. Even if there are a few peers, none may be configured correctly or support metadata exchange (exchanging metadata is not a standard BitTorrent feature). Try to load a torrent file (which doesn't require downloading metadata) and see if you can download successfully (to rule out some network issues).