Jump to content

towa

Members
  • Posts

    3
  • Joined

  • Last visited

towa's Achievements

Newbie

Newbie (1/4)

0

Reputation

  1. Thanks @attila! I have updated the software to b'3.22.23'. Thanks for sending me the code, I corrected my code based on it, but I have additional three questions. ① In each loop, I want to measure only the latest value of the maximum in the sensor voltage readings for 28 microseconds. Am I correct in understanding that if I use filterMinMax, the acquisition frequency should be set based on the following equation? Acquisition frequency = ADC frequency / N = 10,000,000 / 1400 = 71,429 Hz ② Since I only need to measure the latest maximum value, I set the buffer to the minimum value of 16. However, when I run the following code, it takes about 1.3 ms to execute FDwfAnalogInStatus. What is the problem? ③ I would like to create a code to find the maximum value in the most recent 28 microsecond sensor voltage measurement by processing filterMinMax and then quickly read that single data on a PC using FDwfAnalogInStatusData etc. What code is needed to perform the above process at high speed? Also, which should I use with respect to ACQMODE, acqmodeRecord or acqmodeScanShift, to achieve this objective? from ctypes import * import time import numpy as np dwf = cdll.dwf hdwf = c_int() dwf.FDwfDeviceOpen(-1, byref(hdwf)) if hdwf.value == 0: print("failed to open device") szerr = create_string_buffer(512) dwf.FDwfGetLastErrorMsg(szerr) print(szerr.value) quit() dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(0)) # Parameters f_start = 28.24e03 V_gen = 2.5 # Voltage amplitude 0-p runtime_gen = 2 K_p = 0.8 # Amplitude Data Acquisition Frequency adc_frequency = 100e06 # AD conversion frequency [Hz] cycle = 28e-6 N = cycle / (1/adc_frequency) / 2 acquisition_frequency = adc_frequency / N # Buffer min: 16 buffer_size = 16 # Target V (0-p) = a*A (p-p) + b a = 0.4712 b = -0.2923 A_target = 5 # p-p V_target = a*A_target + b # 0-p # Generate 1:hdwf 2:channel 3:node dwf.FDwfAnalogOutNodeEnableSet(hdwf, 0, 0, 1) dwf.FDwfAnalogOutNodeEnableSet(hdwf, 0, 2, 0) # Disable AM modulation dwf.FDwfAnalogOutNodeFunctionSet(hdwf, 0, 0, c_ubyte(1)) dwf.FDwfAnalogOutNodeFrequencySet(hdwf, 0, 0, c_double(f_start)) dwf.FDwfAnalogOutNodeAmplitudeSet(hdwf, 0, 0, c_double(V_gen)) dwf.FDwfAnalogOutNodeOffsetSet(hdwf, 0, 0, c_double(0)) dwf.FDwfAnalogOutNodeSymmetrySet(hdwf, 0, 0, c_double(50)) dwf.FDwfAnalogOutRunSet(hdwf, 0, c_double(runtime_gen)) dwf.FDwfAnalogOutWaitSet(hdwf, 0, c_double(0)) # Waiting time before start dwf.FDwfAnalogOutRepeatSet(hdwf, 0, c_int(100000)) dwf.FDwfAnalogOutConfigure(hdwf, 0, 1) # Scope dwf.FDwfAnalogInChannelEnableSet(hdwf, 0, 1) dwf.FDwfAnalogInChannelOffsetSet(hdwf, 0, 0) dwf.FDwfAnalogInFrequencySet(hdwf, c_double(acquisition_frequency)) dwf.FDwfAnalogInChannelRangeSet(hdwf, 0, c_double(50)) # Maximum measurable voltage: -25~25V dwf.FDwfAnalogInAcquisitionModeSet(hdwf, c_int(3)) # [3:record 1:shift] dwf.FDwfAnalogInRecordLengthSet(hdwf, c_double(-1)) # Record data for an infinite time dwf.FDwfAnalogInChannelFilterSet(hdwf, 0, c_int(2)) # filterMinMax: Return the maximum and minimum values inside the buffer dwf.FDwfAnalogInBufferSizeSet(hdwf, c_int(buffer_size)) dwf.FDwfAnalogInConfigure(hdwf, 1, 1) # Apply new settings if the second argument is 1 time.sleep(1) sts = c_int() # Status cAvailable = c_int() # Number of available samples t1 = time.perf_counter_ns() dwf.FDwfAnalogInStatus(hdwf, 0, byref(sts)) t2 = time.perf_counter_ns() print((t2-t1)/1e6) dwf.FDwfDeviceCloseAll()
  2. Thanks @attila! ↓ I used this code but every time I change the frequency, I lose voltage. Is the only way to dynamically change the frequency to use "dwf.FDwfDeviceAutoConfigureSet(hdwf, c_int(3))" at the expense of speed? ↓ After implementing this code, the time of the loop “measure the output voltage of the ultrasonic transducer's pickup sensor 28 µs at 100 MHz sampling frequency, calculate the peak amplitude Vmax, and update the driving frequency based on the difference between Vmax and the target value of amplitude” was reduced to about 6 ms. Thanks. But I would like to reduce this time to less than 1 ms, is there any other way to reduce the time?
  3. Hi Everyone, I have a question regarding Analog Discovery 2. I am currently developing a system that uses Analog Discovery 2 to control the frequency of an ultrasonic transducer and keep its vibration amplitude constant. Specific objectives and implementation details are as follows: The following process is based on the “Getting Started with WaveForms SDK” website. 1. Drive an ultrasonic transducer with a resonant frequency of 28.24kHz at approximately 28.3kHz using the generate() function. 2. Measure the output voltage of the ultrasonic transducer's pickup sensor using the AD2 oscilloscope function at a sampling frequency of 100MHz for 28µs, and calculate the peak amplitude Vmax using the record() function. 3. Calculate the difference e(t) between the target sensor voltage value Vtarget (proportional to the target vibration amplitude value) and Vmax, apply a proportional gain to this difference to obtain Δf, and update the drive frequency using the FDwfAnalogOutNodeFrequencySet() function 4. Repeat steps 2 and 3 to control the amplitude consistently. Our goal is to get the frequency control period to 40 µs (or at least within 1 ms). However, currently the FDwfAnalogInStatus and FDwfAnalogInStatusData functions take a considerable amount of time, resulting in a control cycle period of approximately 10ms. Is it possible to implement a solution such as calculating the peak sensor output voltage in the FPGA to achieve the desired processing time? If there are any other ways to reduce the processing time, I would appreciate any suggestions. Additionally, do I need to purchase an FPGA board for this purpose? I apologize for my poor English and limited knowledge, but I would appreciate your response. The files below are what I used: import time # To handle timing operations import ctypes # To use C libraries in Python from sys import platform, path # To handle system path operations import numpy as np # Load the Digilent WaveForms SDK shared library using ctypes dwf = ctypes.cdll.dwf #------------------------------------------------------------------------------------------------------------------------ # Device connection and disconnection class Data: # Variables used in the script handle = ctypes.c_int(0) name = "" # Scope settings sampling_frequency = 100e06 buffer_size = 2801 # Generator settings gen_frequency = 28.3e03 amplitude = 2.5 run_time = 2 # Control time vibrating_time = 2 def device_open(): # Open the first connected device # Specify the address of the connected device (initial value is integer) device_handle = ctypes.c_int() # Connect to the first available device by passing -1 as the argument, storing the handle in device_handle dwf.FDwfDeviceOpen(ctypes.c_int(-1), ctypes.byref(device_handle)) Data.handle = device_handle return Data def device_close(device_data): # Close the device result = dwf.FDwfDeviceClose(device_data.handle) if result != 1: print(f"Failed to close device. Error code: {result}") return result #------------------------------------------------------------------------------------------------------------------------ # Oscilloscope settings def scope_open(device_data, sampling_frequency=Data.sampling_frequency, buffer_size=Data.buffer_size, offset=0, amplitude_range=50): # Enable channel 0 dwf.FDwfAnalogInChannelEnableSet(device_data.handle, ctypes.c_int(0), ctypes.c_bool(True)) # Set offset voltage dwf.FDwfAnalogInChannelOffsetSet(device_data.handle, ctypes.c_int(0), ctypes.c_double(offset)) # Set maximum voltage dwf.FDwfAnalogInChannelRangeSet(device_data.handle, ctypes.c_int(0), ctypes.c_double(amplitude_range)) # Set buffer size dwf.FDwfAnalogInBufferSizeSet(device_data.handle, ctypes.c_int(buffer_size)) # Set sampling frequency (Hz) dwf.FDwfAnalogInFrequencySet(device_data.handle, ctypes.c_double(sampling_frequency)) # Disable averaging to use raw data dwf.FDwfAnalogInChannelFilterSet(device_data.handle, ctypes.c_int(-1), ctypes.c_int(0)) return def scope_record(device_data, channel=1): # Record voltage dwf.FDwfAnalogInAcquisitionModeSet(device_data.handle, ctypes.c_int(0)) dwf.FDwfAnalogInConfigure(device_data.handle, ctypes.c_bool(False), ctypes.c_bool(True)) # Store the buffer status status = ctypes.c_byte() while True: # Check acquisition status, 2: keep reading data, 3: store status in the status variable dwf.FDwfAnalogInStatus(device_data.handle, ctypes.c_bool(True), ctypes.byref(status)) # End when status becomes 2 (data acquisition starts and data is stored in buffer) if status.value == ctypes.c_ubyte(2).value: break # Copy the data stored in the buffer # Create an empty buffer, with the number of significant digits * buffer size array (all elements initialized to 0) buffer = (ctypes.c_double * Data.buffer_size)() # Copy the acquired data array to the buffer dwf.FDwfAnalogInStatusData(device_data.handle, ctypes.c_int(channel - 1), buffer, ctypes.c_int(Data.buffer_size)) # Convert data to floating point numbers, put them in the buffer list, and get the maximum value np_buffer = np.ctypeslib.as_array(buffer) V_sensor = np.max(np.abs(np_buffer)) return V_sensor def scope_close(device_data): result = dwf.FDwfAnalogInReset(device_data.handle) return #------------------------------------------------------------------------------------------------------------------------ def generate(device_data, channel=1, function=ctypes.c_ubyte(1), offset=0, gen_frequency=Data.gen_frequency, amplitude=Data.amplitude, symmetry=50, wait=0, run_time=Data.run_time, repeat=100000): # Enable the channel (channel 1 is 0) channel = ctypes.c_int(channel - 1) # Enable the carrier wave dwf.FDwfAnalogOutNodeEnableSet(device_data.handle, channel, ctypes.c_int(0), ctypes.c_bool(True)) # Disable the signal wave (2) dwf.FDwfAnalogOutNodeEnableSet(device_data.handle, channel, ctypes.c_int(2), ctypes.c_bool(False)) # Set the waveform dwf.FDwfAnalogOutNodeFunctionSet(device_data.handle, channel, ctypes.c_int(0), function) # Set the frequency dwf.FDwfAnalogOutNodeFrequencySet(device_data.handle, channel, ctypes.c_int(0), ctypes.c_double(gen_frequency)) # Set the voltage amplitude 0-p dwf.FDwfAnalogOutNodeAmplitudeSet(device_data.handle, channel, ctypes.c_int(0), ctypes.c_double(amplitude)) # Set the offset dwf.FDwfAnalogOutNodeOffsetSet(device_data.handle, channel, ctypes.c_int(0), ctypes.c_double(offset)) # Set the symmetry dwf.FDwfAnalogOutNodeSymmetrySet(device_data.handle, channel, ctypes.c_int(0), ctypes.c_double(symmetry)) # Set the waveform generation time (seconds) dwf.FDwfAnalogOutRunSet(device_data.handle, channel, ctypes.c_double(run_time)) # Set the waiting time before starting dwf.FDwfAnalogOutWaitSet(device_data.handle, channel, ctypes.c_double(wait)) # Set the number of repetitions dwf.FDwfAnalogOutRepeatSet(device_data.handle, channel, ctypes.c_int(repeat)) # Start dwf.FDwfAnalogOutConfigure(device_data.handle, channel, ctypes.c_bool(True)) return def generate_close(device_data, channel=0): channel = ctypes.c_int(channel - 1) dwf.FDwfAnalogOutReset(device_data.handle, channel) return #------------------------------------------------------------------------------------------------------------------------ # Parameters # Target amplitude (p-p) [μm] A = 5 # Sensor voltage to amplitude conversion formula parameters V (voltage 0-p) = aA (amplitude p-p) + b a = # Values are entered when driven b = # Values are entered when driven # Target voltage [V] V_target = a * A + b print(V_target) # Gain K_p = 1 #------------------------------------------------------------------------------------------------------------------------ # Create object, connect to device, and configure oscilloscope device_data = Data() device_open() # Device configuration 2: initialize device parameters (False: do not initialize) 3: continuously acquire specified range data # Start sampling scope_open(device_data) # Start generator operation generate(device_data) f_now = device_data.gen_frequency time.sleep(1) # Start time t_start = time.time() # Constant amplitude control while True: # Measure the maximum value and calculate the error V_sensor = scope_record(device_data) e = V_target - V_sensor print(e) # Update amplitude df = K_p * e f_new = f_now - df print(f_new) dwf.FDwfDeviceAutoConfigureSet(device_data.handle, ctypes.c_int(3)) dwf.FDwfAnalogOutNodeFrequencySet(device_data.handle, 0, ctypes.c_int(0), ctypes.c_double(f_new)) f_now = f_new if time.time() - t_start >= 2: break # Disconnect the device generate_close(device_data) scope_close(device_data) device_close(device_data)
×
×
  • Create New...