From e66efbbe8df2dd4e7de0a1e9bd129cf92e00f92f Mon Sep 17 00:00:00 2001 From: vikle012 Date: Wed, 11 Sep 2019 13:57:14 +0200 Subject: Initializes repo. --- Kod/bilbana/IOFunctions/config_IOs.m | 191 ++++++++++++++++++ Kod/bilbana/IOFunctions/get_car_position.m | 81 ++++++++ Kod/bilbana/IOFunctions/get_manual_speed.m | 279 ++++++++++++++++++++++++++ Kod/bilbana/IOFunctions/initialize_counters.m | 217 ++++++++++++++++++++ Kod/bilbana/IOFunctions/set_car_speed.m | 56 ++++++ Kod/bilbana/IOFunctions/start_race.m | 56 ++++++ Kod/bilbana/IOFunctions/terminate.m | 83 ++++++++ 7 files changed, 963 insertions(+) create mode 100644 Kod/bilbana/IOFunctions/config_IOs.m create mode 100644 Kod/bilbana/IOFunctions/get_car_position.m create mode 100644 Kod/bilbana/IOFunctions/get_manual_speed.m create mode 100644 Kod/bilbana/IOFunctions/initialize_counters.m create mode 100644 Kod/bilbana/IOFunctions/set_car_speed.m create mode 100644 Kod/bilbana/IOFunctions/start_race.m create mode 100644 Kod/bilbana/IOFunctions/terminate.m (limited to 'Kod/bilbana/IOFunctions') diff --git a/Kod/bilbana/IOFunctions/config_IOs.m b/Kod/bilbana/IOFunctions/config_IOs.m new file mode 100644 index 0000000..0a84d2a --- /dev/null +++ b/Kod/bilbana/IOFunctions/config_IOs.m @@ -0,0 +1,191 @@ +function [] = config_IOs() +%cCONFIG_IOS Configurates the input and output digital channels +% +% Starts tasks for 5 digital channels, 3 output and 2 input channels. +% There is one channel per task. +% +% These channels corresponds to: +% +% Output channels: +% SCLK - Serial Clock Input. +% CS_INV - Active-Low Chip Select. Data will not be clocked into DIN +% unless CS is low. When CS is high, DOUT is high impedance. +% DIN - Digital Serial Input. Data is clocked in at the rising edge of +% SCLK. +% +% Input channels: +% SSTRB - Serial Strobe Output. In internal clock mode, SSTRB goes low +% when the MAX186/MAX188 begin the A/D conversion and goes high +% when the conversion is done. In external clock mode, SSTRB +% pulses high for one clock period before the MSB decision. High +% impedance when CS is high (external mode). +% DOUT - Serial Data Output. Data is clocked out at the falling edge of +% SCLK. High impedance when CS is high. +% +% These channels corresponds to pin 19 - 15 on the ADC MAXIM MAX186 chip. +% +% Tobias Lindell - 2013-02-12 + +global mytaskh +global lib + +DAQmx_Val_ChanPerLine =0; % One Channel For Each Line +DAQmx_Val_ChanForAllLines =1; %#ok % One Channel For All Lines + +if isempty(lib) + lib = 'myni'; % library alias + if ~libisloaded(lib) + disp('Matlab: Load nicaiu.dll') + funclist = loadlibrary('c:\windows\system32\nicaiu.dll','C:\Program Files (x86)\National Instruments\Shared\ExternalCompilerSupport\C\include\nidaqmx.h','alias',lib); %#ok + %if you do NOT have nicaiu.dll and nidaqmx.h + %in your Matlab path,add full pathnames or copy the files. + %libfunctions(lib,'-full') % use this to show the... + %libfunctionsview(lib) % included function + disp('Matlab: Nicaiu.dll loaded!') + end +end + +% DOlines = {'Dev1/port0/line0','Dev1/port0/line1','Dev1/port0/line2'}; +lineGrouping = DAQmx_Val_ChanPerLine; % One Channel For Each Line +mytaskh.DO_SCLK = DAQmxCreateDOChan(lib,'Dev1/port0/line0',lineGrouping); +mytaskh.DO_CS_INV = DAQmxCreateDOChan(lib,'Dev1/port0/line1',lineGrouping); +mytaskh.DO_DIN = DAQmxCreateDOChan(lib,'Dev1/port0/line2',lineGrouping); + +% DIlines = {'Dev1/port0/line3','Dev1/port0/line4'}; +mytaskh.DI_SSTRB = DAQmxCreateDIChan(lib,'Dev1/port0/line3',lineGrouping); +mytaskh.DI_DOUT = DAQmxCreateDIChan(lib,'Dev1/port0/line4',lineGrouping); + +end + +function taskh = DAQmxCreateDIChan(lib,lines,lineGrouping) +% function taskh = DAQmxCreateDIChan(lib,lines,lineGrouping) +% +% this function creates a task and adds digital output line(s) to the task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% lines - line(s) to add to task +% 1 line example: 'Dev1/port0/line0' +% 2 lines example: {'Dev1/port0/line0','Dev1/port0/line1'} +% passing as .../line0-1 probably also works, but I didn't test +% lineGrouping - either DAQmx_Val_ChanPerLine or DAQmx_Val_ChanForAllLines +% +% +% C functions used: +% int32 DAQmxCreateTask (const char taskName[],TaskHandle *taskHandle); +% int32 DAQmxCreateDIChan (TaskHandle taskHandle,const char lines[],const char nameToAssignToLines[],int32 lineGrouping); +% int32 DAQmxTaskControl (TaskHandle taskHandle,int32 action); +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + + +% create task +taskh = []; +name_task = ''; % recommended to avoid problems +[err,~,taskh] = calllib(lib,'DAQmxCreateTask',name_task,uint32(taskh)); +DAQmxCheckError(lib,err); + +% % check whether done +% [err,b,istaskdone] = calllib(lib,'DAQmxIsTaskDone',(taskh),0); +% DAQmxCheckError(lib,err); + +% create DI channel(s) and add to task +% numchan = numel(lines); +name_line = ''; % recommended to avoid problems +if ~iscell(lines) % just 1 channel + [err,~,~,~] = calllib(lib,'DAQmxCreateDIChan',taskh,lines,name_line,lineGrouping); + DAQmxCheckError(lib,err); +else % more than 1 channel to add to task + for m = 1:numel(lines) % loop to add channels + [err,~,~,~] = calllib(lib,'DAQmxCreateDIChan',taskh,lines{m},name_line,lineGrouping); + DAQmxCheckError(lib,err); + end +end + +% verify everything OK +DAQmx_Val_Task_Verify =2; % Verify +[err,~] = calllib(lib,'DAQmxTaskControl',taskh,DAQmx_Val_Task_Verify); +DAQmxCheckError(lib,err); +end + +function taskh = DAQmxCreateDOChan(lib,lines,lineGrouping) +% function taskh = DAQmxCreateDOChan(lib,lines,lineGrouping) +% +% this function creates a task and adds digital output line(s) to the task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% lines - line(s) to add to task +% 1 line example: 'Dev1/port0/line0' +% 2 lines example: {'Dev1/port0/line0','Dev1/port0/line1'} +% passing as .../line0-1 probably also works, but I didn't test +% lineGrouping - either DAQmx_Val_ChanPerLine or DAQmx_Val_ChanForAllLines +% +% +% C functions used: +% int32 DAQmxCreateTask (const char taskName[],TaskHandle *taskHandle); +% int32 DAQmxCreateDOChan (TaskHandle taskHandle,const char lines[],const char nameToAssignToLines[],int32 lineGrouping); +% int32 DAQmxTaskControl (TaskHandle taskHandle,int32 action); +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + + +% create task +taskh = []; +name_task = ''; % recommended to avoid problems +[err,~,taskh] = calllib(lib,'DAQmxCreateTask',name_task,uint32(taskh)); +DAQmxCheckError(lib,err); + +% % check whether done +% [err,b,istaskdone] = calllib(lib,'DAQmxIsTaskDone',(taskh),0); +% DAQmxCheckError(lib,err); + +% create DO channel(s) and add to task +name_line = ''; % recommended to avoid problems +if ~iscell(lines) + [err,~,~,~] = calllib(lib,'DAQmxCreateDOChan',taskh,lines,name_line,lineGrouping); + DAQmxCheckError(lib,err); +else % more than 1 channel to add to task + for m = 1:numel(lines) + [err,~,~,~] = calllib(lib,'DAQmxCreateDOChan',taskh,lines{m},name_line,lineGrouping); + DAQmxCheckError(lib,err); + end +end + +% verify everything OK +DAQmx_Val_Task_Verify = 2; % Verify +[err,~] = calllib(lib,'DAQmxTaskControl',taskh,DAQmx_Val_Task_Verify); +DAQmxCheckError(lib,err); +end + +function DAQmxCheckError(lib,err) +% function DAQmxCheckError(lib,err) +% +% read error code +% zero means no error - does nothing +% nonzero - find out error string and generate error +% +% inputs: +% lib = .dll or alias (ex. 'myni') +% err = DAQmx error +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + +if err ~= 0 + % find out how long the error string is + [numerr,~] = calllib(lib,'DAQmxGetErrorString',err,'',0); + + % get error string + errstr = char(1:numerr); % have to pass dummy string of correct length + [~,errstr] = calllib(lib,'DAQmxGetErrorString',err,errstr,numerr); + + % matlab error + error(['DAQmx error - ',errstr]) +end +end \ No newline at end of file diff --git a/Kod/bilbana/IOFunctions/get_car_position.m b/Kod/bilbana/IOFunctions/get_car_position.m new file mode 100644 index 0000000..ef68fc2 --- /dev/null +++ b/Kod/bilbana/IOFunctions/get_car_position.m @@ -0,0 +1,81 @@ +function [add_lap,add_check_point,elapsed_time_check_point] = get_car_position(track) +%GET_CAR_POSITION Reads the current values of the lap and check point +%counters, and resets them if they are not equal to zero. +% +% Tobias Lindell 2013-02-13 + +global mytaskh +global lib + +switch nargin + case 1 + add_lap = []; + add_check_point = []; + elapsed_time_check_point = []; + + if isempty(mytaskh) + disp(['User needs to initialize counters for track ',num2str(track),' before getting car position!']) + clearvars -global mytaskh lib + return + end + + switch track + case 1 + if isfield(mytaskh,'ctr_1') + add_check_point = DAQmxReadCounterScalarU32(lib,mytaskh.ctr_1); + add_lap = DAQmxReadCounterScalarU32(lib,mytaskh.ctr_2); + read_ticks = DAQmxReadCounterScalarU32(lib,mytaskh.ctr_3); + else + disp(['User needs to initialize counters for track ',num2str(track),' before getting car position!']) + return + end + case 2 + if isfield(mytaskh,'ctr_5') + add_check_point = DAQmxReadCounterScalarU32(lib,mytaskh.ctr_5); + add_lap = DAQmxReadCounterScalarU32(lib,mytaskh.ctr_6); + read_ticks = DAQmxReadCounterScalarU32(lib,mytaskh.ctr_7); + else + disp(['User needs to initialize counters for track ',num2str(track),' before getting car position!']) + return + end + + otherwise + disp('Wrong track number sent to get_car_position!') + return + end + + if add_check_point || add_lap + elapsed_time_check_point = read_ticks / 100; + start_race(track); + clear read_ticks + end + otherwise + disp('Wrong number of input arguments sent to get_car_position(track)! Should be 1!') +end +end + +function Data = DAQmxReadCounterScalarU32(lib,taskh) +% function taskh = DAQmxReadCounterScalarU32(lib,taskh) +% +% this function reads a counter value from previously setup task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% taskh - taskhandle of analog inputs +% +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + +DAQmx_Val_WaitInfinitely = -1.0; + +reserved = []; +reserved_ptr = libpointer('uint32Ptr',reserved); +Data = 1; +data_ptr = libpointer('uint32Ptr',Data); +calllib(lib,'DAQmxReadCounterScalarU32',taskh,DAQmx_Val_WaitInfinitely,data_ptr,reserved_ptr); +counter = get(data_ptr); +Data = counter.Value; +end + diff --git a/Kod/bilbana/IOFunctions/get_manual_speed.m b/Kod/bilbana/IOFunctions/get_manual_speed.m new file mode 100644 index 0000000..04af0ae --- /dev/null +++ b/Kod/bilbana/IOFunctions/get_manual_speed.m @@ -0,0 +1,279 @@ +function [manual_speed] = get_manual_speed(track) +%GET_MANUAL_SPEED Reads input from gas handle and returns converted value. +% Uses digital in/out functions to get and set values on the channels set +% up by the function config_IOs. +% +% Output channels: +% SCLK - Serial Clock Input. +% CS_INV - Active-Low Chip Select. Data will not be clocked into DIN +% unless CS is low. When CS is high, DOUT is high impedance. +% DIN - Digital Serial Input. Data is clocked in at the rising edge of +% SCLK. +% +% Input channels: +% SSTRB - Serial Strobe Output. In internal clock mode, SSTRB goes low +% when the MAX186/MAX188 begin the A/D conversion and goes high +% when the conversion is done. In external clock mode, SSTRB +% pulses high for one clock period before the MSB decision. High +% impedance when CS is high (external mode). +% DOUT - Serial Data Output. Data is clocked out at the falling edge of +% SCLK. High impedance when CS is high. +% +% User needs to manually clock the serial clock of the analog/digital +% converter to read or write data. +% +% Tobias Lindell - 2013-02-12 + +global mytaskh +global lib + +switch nargin + case 1 + manual_speed = []; + + if isempty(mytaskh) + disp('User needs to initialize IO before getting manual car speed!') + clearvars -global mytaskh lib + return + else + if ~isfield(mytaskh,'DO_SCLK') + disp('User needs to initialize IO before getting manual car speed!') + return + end + end + + switch track + case 1 + control_bit = 0; + case 2 + control_bit = 1; + otherwise + disp('Wrong track number sent to get_manual_speed!') + return + end + + % Channels: + % mytaskh.DO_SCLK + % mytaskh.DO_CS_INV + % mytaskh.DO_DIN + % mytaskh.DI_SSTRB + % mytaskh.DI_DOUT + + DAQmx_Val_ChanPerLine =0; %#ok<*NASGU> % One Channel For Each Line + DAQmx_Val_ChanForAllLines =1; % One Channel For All Lines + DAQmx_Val_GroupByChannel = 0; % Group by Channel + DAQmx_Val_GroupByScanNumber =1; % Group by Scan Number + + numSampsPerChan = 1; + timeout = 1; + fillMode = DAQmx_Val_GroupByChannel; % Group by Channel + % fillMode = DAQmx_Val_GroupByScanNumber; % Group by Scan Number + dataLayout = DAQmx_Val_GroupByChannel; % Group by Channel + % dataLayout = DAQmx_Val_GroupByScanNumber; % Group by Scan Number + numchanDI = 1; % DI lines + numsample = 1; + + + + % Setup outports + DAQmxWriteDigitalLines(lib,mytaskh.DO_CS_INV,... + numSampsPerChan,timeout,dataLayout,1); + DAQmxWriteDigitalLines(lib,mytaskh.DO_SCLK,... + numSampsPerChan,timeout,dataLayout,0); + DAQmxWriteDigitalLines(lib,mytaskh.DO_DIN,... + numSampsPerChan,timeout,dataLayout,0); + DAQmxWriteDigitalLines(lib,mytaskh.DO_CS_INV,... + numSampsPerChan,timeout,dataLayout,0); + + % Send controll byte : "100x1110", där x är kontrollbiten. + set_ADC_bit(1); + set_ADC_bit(0); + set_ADC_bit(0); + set_ADC_bit(control_bit); + set_ADC_bit(1); + set_ADC_bit(1); + set_ADC_bit(1); + set_ADC_bit(0); + + pause(0.005) + + DAQmxWriteDigitalLines(lib,mytaskh.DO_SCLK,... + numSampsPerChan,timeout,dataLayout,1); + + ADC = zeros(1,12); + for i=1:12 + ADC(13-i) = get_ADC_bit(); + end + get_ADC_bit(); + get_ADC_bit(); + get_ADC_bit(); + get_ADC_bit(); + DAQmxWriteDigitalLines(lib,mytaskh.DO_CS_INV,... + numSampsPerChan,timeout,dataLayout,1); + + x1=ADC(12)*128+ADC(11)*64+ADC(10)*32+ADC(9)*16+ADC(8)*8+ADC(7)*4+ADC(6)*2+ADC(5)*1-128; + manual_speed = min(max(x1,0),127); + otherwise + disp('Wrong number of arguments sent to get_manual_speed(track)! Should be 1!'); +end +end + +function [] = set_ADC_bit(valueDO) +global mytaskh +global lib + +DAQmx_Val_ChanPerLine =0; % One Channel For Each Line +DAQmx_Val_ChanForAllLines =1; % One Channel For All Lines +DAQmx_Val_GroupByChannel = 0; % Group by Channel +DAQmx_Val_GroupByScanNumber =1; % Group by Scan Number + +numSampsPerChan = 1; +timeout = 1; +dataLayout = DAQmx_Val_GroupByChannel; % Group by Channel +% dataLayout = DAQmx_Val_GroupByScanNumber; % Group by Scan Number + +DAQmxWriteDigitalLines(lib,mytaskh.DO_DIN,... + numSampsPerChan,timeout,dataLayout,valueDO); + +DAQmxWriteDigitalLines(lib,mytaskh.DO_SCLK,... + numSampsPerChan,timeout,dataLayout,1); +DAQmxWriteDigitalLines(lib,mytaskh.DO_SCLK,... + numSampsPerChan,timeout,dataLayout,0); +end + +function [valueDI] = get_ADC_bit() +global mytaskh +global lib + +DAQmx_Val_ChanPerLine =0; % One Channel For Each Line +DAQmx_Val_ChanForAllLines =1; % One Channel For All Lines +DAQmx_Val_GroupByChannel = 0; % Group by Channel +DAQmx_Val_GroupByScanNumber =1; % Group by Scan Number + +numSampsPerChan = 1; +timeout = 1; +fillMode = DAQmx_Val_GroupByChannel; % Group by Channel +% fillMode = DAQmx_Val_GroupByScanNumber; % Group by Scan Number +dataLayout = DAQmx_Val_GroupByChannel; % Group by Channel +% dataLayout = DAQmx_Val_GroupByScanNumber; % Group by Scan Number +numchanDI = 1; % DI lines +numsample = 1; + +DAQmxWriteDigitalLines(lib,mytaskh.DO_SCLK,... + numSampsPerChan,timeout,dataLayout,0); +DAQmxWriteDigitalLines(lib,mytaskh.DO_SCLK,... + numSampsPerChan,timeout,dataLayout,1); +valueDI = DAQmxReadDigitalLines(lib,mytaskh.DI_DOUT,numSampsPerChan,timeout,fillMode,numchanDI,numsample); +end + +function sampsPerChanWritten = DAQmxWriteDigitalLines(lib,taskh,numSampsPerChan,timeout,dataLayout,DOvalue) +% function sampsPerChanWritten = DAQmxWriteDigitalLines(lib,taskh,numSampsPerChan,timeout,dataLayout,DOvalue) +% +% this function writes digital outputs from previously setup task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% taskh - taskhandle of analog inputs +% numSampsPerChan = ? +% timeout - in seconds +% dataLayout - DAQmx_Val_GroupByChannel or DAQmx_Val_GroupByScanNumber +% DOvalue - value to write (0 or 1) +% 1 channel example: 0 +% 2 channel example: [0,0] +% +% C functions: +% int32 DAQmxReadDigitalLines ( +% TaskHandle taskHandle,int32 numSampsPerChan,float64 timeout,bool32 fillMode, +% uInt8 readArray[],uInt32 arraySizeInBytes,int32 *sampsPerChanRead,int32 *numBytesPerSamp,bool32 *reserved); +% int32 DAQmxStopTask (TaskHandle taskHandle); +% int32 DAQmxWriteDigitalLines ( +% TaskHandle taskHandle,int32 numSampsPerChan,bool32 autoStart,float64 timeout,bool32 dataLayout, +% uInt8 writeArray[],int32 *sampsPerChanWritten,bool32 *reserved); +% int32 DAQmxStopTask (TaskHandle taskHandle); +% +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + +autoStart = 1; + + +[err,sampsPerChanWritten,empty] = calllib(lib,'DAQmxWriteDigitalLines',... + taskh,numSampsPerChan,autoStart,timeout,dataLayout,... + DOvalue,0,[]); +DAQmxCheckError(lib,err); +end + +function data = DAQmxReadDigitalLines(lib,taskh,numSampsPerChan,timeout,fillMode,numchan,numsample) +% function data = DAQmxReadDigitalLines(lib,taskh,numSampsPerChan,timeout,fillMode,numchan,numsample) +% +% this function reads digital inputs from previously setup task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% taskh - taskhandle of analog inputs +% numSampsPerChan = ? +% timeout - in seconds +% fillMode - DAQmx_Val_GroupByChannel or DAQmx_Val_GroupByScanNumber +% numchan - number of digital channels to read +% numsample - number of samples to read +% +% C functions: +% int32 DAQmxReadDigitalLines ( +% TaskHandle taskHandle,int32 numSampsPerChan,float64 timeout,bool32 fillMode, +% uInt8 readArray[],uInt32 arraySizeInBytes,int32 *sampsPerChanRead,int32 *numBytesPerSamp,bool32 *reserved); +% int32 DAQmxStopTask (TaskHandle taskHandle); +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + + +% make some pointers +% readarray1=ones(numchan,numsample); readarray1_ptr=libpointer('doublePtr',readarray1); +readarray1=ones(numchan,numsample); readarray1_ptr=libpointer('uint8Ptr',readarray1); +sampread=1; sampread_ptr=libpointer('int32Ptr',sampread); +bytespersamp=1; bytespersamp_ptr=libpointer('int32Ptr',bytespersamp); +empty=[]; empty_ptr=libpointer('uint32Ptr',empty); + +arraylength=numsample*numchan; % more like 'buffersize' + +[err,~,sampread,~,empty]=calllib(lib,'DAQmxReadDigitalLines',... + taskh,numSampsPerChan,timeout,fillMode,... + readarray1_ptr,arraylength,sampread_ptr,bytespersamp_ptr,empty_ptr); +DAQmxCheckError(lib,err); + +% err = calllib(lib,'DAQmxStopTask',taskh); +% DAQmxCheckError(lib,err); + +data = sampread; +end + +function DAQmxCheckError(lib,err) +% function DAQmxCheckError(lib,err) +% +% read error code +% zero means no error - does nothing +% nonzero - find out error string and generate error +% +% inputs: +% lib = .dll or alias (ex. 'myni') +% err = DAQmx error +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + +if err ~= 0 + % find out how long the error string is + [numerr,~] = calllib(lib,'DAQmxGetErrorString',err,'',0); + + % get error string + errstr = char(1:numerr); % have to pass dummy string of correct length + [~,errstr] = calllib(lib,'DAQmxGetErrorString',err,errstr,numerr); + + % matlab error + error(['DAQmx error - ',errstr]) +end +end \ No newline at end of file diff --git a/Kod/bilbana/IOFunctions/initialize_counters.m b/Kod/bilbana/IOFunctions/initialize_counters.m new file mode 100644 index 0000000..27e76ac --- /dev/null +++ b/Kod/bilbana/IOFunctions/initialize_counters.m @@ -0,0 +1,217 @@ +function [] = initialize_counters(track) +%INITIALIZE_COUNTERS Creates counter tasks by calling the new driver NIDAQmx. +% +% There are one task associated with each counter. The handles of these +% tasks are stored in global struct mytaskh. The tasks are not started +% by this function, the user needs to call set_car_speed and/or +% start_race to arm any counters. +% +% Track 1/track 2: +% ctr_0/ctr_4 - Pulse train signal, representing car speed. +% ctr_1/ctr_5 - Check point counter. +% ctr_2/ctr_6 - Lap counter. +% ctr_3/ctr_7 - Time counter, counts at 100kHz. +% +% Tobias Lindell - 2013-02-12 + +global mytaskh +global lib + +switch nargin + case 1 + lib = 'myni'; % library alias + if ~libisloaded(lib) + disp('Matlab: Loading nicaiu.dll. Please wait!') + funclist = loadlibrary('c:\windows\system32\nicaiu.dll','C:\Program Files (x86)\National Instruments\Shared\ExternalCompilerSupport\C\include\nidaqmx.h','alias',lib); %#ok + %if you do NOT have nicaiu.dll and nidaqmx.h + %in your Matlab path,add full pathnames or copy the files. + %libfunctions(lib,'-full') % use this to show the... + %libfunctionsview(lib) % included function + disp('Matlab: Nicaiu.dll loaded!') + end + + disp(['Initializing track ',num2str(track),' please wait!']) + + %%% NIconstants + DAQmx_Val_Hz = 10373; % Hz + + % DAQmx_Val_High = 10192; % High + DAQmx_Val_Low = 10214; % Low + + % DAQmx_Val_FiniteSamps = 10178; % Finite Samples + DAQmx_Val_ContSamps = 10123; % Continuous Samples + % DAQmx_Val_HWTimedSinglePoint = 12522; % Hardware Timed Single Point + + DAQmx_Val_Rising = 10280; % Rising + % DAQmx_Val_Falling = 10171; % Falling + + DAQmx_Val_CountUp = 10128; % Count Up + % DAQmx_Val_CountDown = 10124; % Count Down + % DAQmx_Val_ExtControlled = 10326; % Externally Controlled + + + + % Track 1 + switch track + case 1 + %%% Car speed counter + mytaskh.ctr_0 = DAQmxCreateCOPulseChanFreq(lib,'Dev1/ctr0',DAQmx_Val_Hz,DAQmx_Val_Low,2.5e-08,100,0.001); + calllib(lib,'DAQmxCfgImplicitTiming',mytaskh.ctr_0,DAQmx_Val_ContSamps,1000); + + %%% Sensor counters + + % Check points + % Starting count edges counter, detecting rising edges + mytaskh.ctr_1 = DAQmxCreateCICountEdgesChan(lib,'Dev1/ctr1',DAQmx_Val_Rising,DAQmx_Val_CountUp); + % Setting up terminal and filter + calllib(lib,'DAQmxSetCICountEdgesTerm',mytaskh.ctr_1,'Dev1/ctr1','PFI35'); + calllib(lib,'DAQmxSetCICountEdgesDigFltrEnable',mytaskh.ctr_1,'Dev1/ctr1',1); + calllib(lib,'DAQmxSetCICountEdgesDigFltrMinPulseWidth',mytaskh.ctr_1,'Dev1/ctr1',5e-6); + + % Lap counter + mytaskh.ctr_2 = DAQmxCreateCICountEdgesChan(lib,'Dev1/ctr2',DAQmx_Val_Rising,DAQmx_Val_CountUp); + calllib(lib,'DAQmxSetCICountEdgesTerm',mytaskh.ctr_2,'Dev1/ctr2','PFI31'); + calllib(lib,'DAQmxSetCICountEdgesDigFltrEnable',mytaskh.ctr_2,'Dev1/ctr2',1); + calllib(lib,'DAQmxSetCICountEdgesDigFltrMinPulseWidth',mytaskh.ctr_2,'Dev1/ctr2',5e-6); + + %%% Timer counter + mytaskh.ctr_3 = DAQmxCreateCICountEdgesChan(lib,'Dev1/ctr3',DAQmx_Val_Rising,DAQmx_Val_CountUp); + calllib(lib,'DAQmxSetCICountEdgesTerm',mytaskh.ctr_3,'Dev1/ctr3','/Dev1/100kHzTimebase'); + + case 2 + %%% Car speed counter + mytaskh.ctr_4 = DAQmxCreateCOPulseChanFreq(lib,'Dev1/ctr4',DAQmx_Val_Hz,DAQmx_Val_Low,2.5e-08,100,0.001); + calllib(lib,'DAQmxCfgImplicitTiming',mytaskh.ctr_4,DAQmx_Val_ContSamps,1000); + + %%% Sensor counters + % Check points + mytaskh.ctr_5 = DAQmxCreateCICountEdgesChan(lib,'Dev1/ctr5',DAQmx_Val_Rising,DAQmx_Val_CountUp); + calllib(lib,'DAQmxSetCICountEdgesTerm',mytaskh.ctr_5,'Dev1/ctr5','PFI19'); + calllib(lib,'DAQmxSetCICountEdgesDigFltrEnable',mytaskh.ctr_5,'Dev1/ctr5',1); + calllib(lib,'DAQmxSetCICountEdgesDigFltrMinPulseWidth',mytaskh.ctr_5,'Dev1/ctr5',5e-6); + + % Lap counter + mytaskh.ctr_6 = DAQmxCreateCICountEdgesChan(lib,'Dev1/ctr6',DAQmx_Val_Rising,DAQmx_Val_CountUp); + calllib(lib,'DAQmxSetCICountEdgesTerm',mytaskh.ctr_6,'Dev1/ctr6','PFI15'); + calllib(lib,'DAQmxSetCICountEdgesDigFltrEnable',mytaskh.ctr_6,'Dev1/ctr6',1); + calllib(lib,'DAQmxSetCICountEdgesDigFltrMinPulseWidth',mytaskh.ctr_6,'Dev1/ctr6',5e-6); + + %%% Timer counter + mytaskh.ctr_7 = DAQmxCreateCICountEdgesChan(lib,'Dev1/ctr7',DAQmx_Val_Rising,DAQmx_Val_CountUp); + calllib(lib,'DAQmxSetCICountEdgesTerm',mytaskh.ctr_7,'Dev1/ctr7','/Dev1/100kHzTimebase'); + + otherwise + disp('Wrong track number sent to initialize_counters!') + return + end + disp(['Track ',num2str(track),' initialized!']) + otherwise + disp('Wrong number of input arguments sent to initialize_counters(track)! Should be 1!') +end +end + +function DAQmxCheckError(lib,err) +% function DAQmxCheckError(lib,err) +% +% read error code +% zero means no error - does nothing +% nonzero - find out error string and generate error +% +% inputs: +% lib = .dll or alias (ex. 'myni') +% err = DAQmx error +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + +if err ~= 0 + % find out how long the error string is + [numerr,~] = calllib(lib,'DAQmxGetErrorString',err,'',0); + + % get error string + errstr = char(1:numerr); % have to pass dummy string of correct length + [~,errstr] = calllib(lib,'DAQmxGetErrorString',err,errstr,numerr); + + % matlab error + error(['DAQmx error - ',errstr]) +end +end + +function taskh = DAQmxCreateCICountEdgesChan(lib,ctrs,edge,direction) +% function taskh = DAQmxCreateCICountEdgesChan(lib,ctrs,edge,direction) +% +% this function creates a task and adds counter input channel(s) to the task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% ctrs - channel(s) to add to task +% 1 channel example: 'Dev1/ctr0' +% 2 channels example: {'Dev1/ctr0','Dev1/ctr1'} +% passing as .../ctr0-1 probably also works, but I didn't test +% edge - which edge that is detected/counted ('rising' or 'falling') +% direction - direction to count ('increment' or 'decrement') +% +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + +taskh = []; +name_task = ''; % recommended to avoid problems +[err,~,taskh] = calllib(lib,'DAQmxCreateTask',name_task,uint32(taskh)); +DAQmxCheckError(lib,err); + +name_line = ''; % recommended to avoid problems +[err,~,~,~] = calllib(lib,'DAQmxCreateCICountEdgesChan',taskh,ctrs,name_line,edge,0,direction); +DAQmxCheckError(lib,err); + +% verify everything OK +DAQmx_Val_Task_Verify = 2; % Verify +[err,~] = calllib(lib,'DAQmxTaskControl',taskh,DAQmx_Val_Task_Verify); +DAQmxCheckError(lib,err); + +end + +function taskh = DAQmxCreateCOPulseChanFreq(lib,ctrs,units,idleState,initialDelay,freq,dutyCycle) +% function taskh = DAQmxCreateCOPulseChanFreq(lib,ctrs,units,idleState,initialDelay,freq,dutyCycle) +% +% this function creates a task and adds counter input channel(s) to the task +% +% inputs: +% lib - .dll or alias (ex. 'myni') +% ctrs - channel(s) to add to task +% 1 channel example: 'Dev1/ctr0' +% 2 channels example: {'Dev1/ctr0','Dev1/ctr1'} +% passing as .../ctr0-1 probably also works, but I didn't test +% units - The units in which to specify freq. (DAQmx_Val_Hz = hertz) +% idleState - The resting state of the output terminal. +% DAQmx_Val_High - High state. +% DAQmx_Val_Low - Low state. +% initialDelay - The amount of time in seconds to wait before generating the first pulse. +% freq - The frequency at which to generate pulses. +% dutyCycle - The width of the pulse divided by the pulse period. +% +% +% written by Tobias Lindell +% inspired by Nathan Tomlin (nathan.a.tomlin@gmail.com) +% v0 - 1302 + + +taskh = []; +name_task = ''; % recommended to avoid problems +[err,~,taskh] = calllib(lib,'DAQmxCreateTask',name_task,uint32(taskh)); +DAQmxCheckError(lib,err); + +name_line = ''; % recommended to avoid problems +[err,~,~,~] = calllib(lib,'DAQmxCreateCOPulseChanFreq',taskh,ctrs,name_line,units,idleState,initialDelay,freq,dutyCycle); +DAQmxCheckError(lib,err); + +% verify everything OK +DAQmx_Val_Task_Verify = 2; % Verify +[err,~] = calllib(lib,'DAQmxTaskControl',taskh,DAQmx_Val_Task_Verify); +DAQmxCheckError(lib,err); + +end + + diff --git a/Kod/bilbana/IOFunctions/set_car_speed.m b/Kod/bilbana/IOFunctions/set_car_speed.m new file mode 100644 index 0000000..3aab1db --- /dev/null +++ b/Kod/bilbana/IOFunctions/set_car_speed.m @@ -0,0 +1,56 @@ +function [] = set_car_speed(track,speed) +%SET_CAR_SPEED Sets the specified car (track) to a specified speed. +% Changes the duty cycle of counter 0 and 4 to change speed of car on +% track 1 and track 2 respectively. Valid values of the duty cycle are +% between 0 and 1, the input speed of the cars are defined as percent. +% +% Tobias Lindell 2013-02-12. + +global mytaskh +global lib + +switch nargin + case 2 + % Check if _any_ counters been initilized, stop program if not + if isempty(mytaskh) + disp(['User needs to initialize counters for track ',num2str(track),' before setting car speed!']) + clearvars -global mytaskh lib + return + end + + % Setting duty cycle, with limits + speed = min(99, speed); + speed = max(0.1,speed); + duty_cycle = speed / 100; + + switch track + case 1 + % Check if track 1 counter has been initialized, stop program if not + if isfield(mytaskh,'ctr_0') + % Stop task (necessary to change duty cycle) + calllib(lib,'DAQmxStopTask',mytaskh.ctr_0); + % Set new duty cycle + calllib(lib,'DAQmxSetCOPulseDutyCyc',mytaskh.ctr_0,'Dev1/ctr0',duty_cycle); + % Restart task + calllib(lib,'DAQmxStartTask',mytaskh.ctr_0); + else + disp(['User needs to initialize counters for track ',num2str(track),' before setting car speed!']) + return + end + case 2 + if isfield(mytaskh,'ctr_4') + calllib(lib,'DAQmxStopTask',mytaskh.ctr_4); + calllib(lib,'DAQmxSetCOPulseDutyCyc',mytaskh.ctr_4,'Dev1/ctr4',duty_cycle); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_4); + else + disp(['User needs to initialize counters for track ',num2str(track),' before setting car speed!']) + return + end + otherwise + disp('Wrong track number sent to set_car_speed!') + return + end + otherwise + disp('Wrong number of arguments sent to set_car_speed(track,speed)! Should be 2!') +end +end diff --git a/Kod/bilbana/IOFunctions/start_race.m b/Kod/bilbana/IOFunctions/start_race.m new file mode 100644 index 0000000..5e51017 --- /dev/null +++ b/Kod/bilbana/IOFunctions/start_race.m @@ -0,0 +1,56 @@ +function [] = start_race(track) +%START_RACE Stops, resets and starts all counters associated with specified +%track. +% All counters, except the pulse train speed counters, associated with a +% specified track are stopped and restarted. This resets the current +% values of the counters to the initial value (0 for all counters). +% +% At first call the counters just starts, the extra stopping of counters +% that are not running does nothing. +% +% Tobias Lindell - 2013-02-12 + +global mytaskh +global lib + +switch nargin + case 1 + % Check if _any_ counters been initilized, stop program if not + if isempty(mytaskh) + disp(['User needs to initialize counters for track ',num2str(track),' before setting car speed!']) + clearvars -global mytaskh lib + return + end + + switch track + case 1 + if ~isfield(mytaskh,'ctr_1') + disp(['User needs to initialize counters for track ',num2str(track),' before setting car speed!']) + return + end + calllib(lib,'DAQmxStopTask',mytaskh.ctr_1); + calllib(lib,'DAQmxStopTask',mytaskh.ctr_2); + calllib(lib,'DAQmxStopTask',mytaskh.ctr_3); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_1); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_2); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_3); + case 2 + if ~isfield(mytaskh,'ctr_5') + disp(['User needs to initialize counters for track ',num2str(track),' before setting car speed!']) + return + end + calllib(lib,'DAQmxStopTask',mytaskh.ctr_5); + calllib(lib,'DAQmxStopTask',mytaskh.ctr_6); + calllib(lib,'DAQmxStopTask',mytaskh.ctr_7); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_5); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_6); + calllib(lib,'DAQmxStartTask',mytaskh.ctr_7); + otherwise + disp('Wrong track number sent to start_race!') + return + end + otherwise + disp('Wrong number of arguments sent to start_race(track)! Should be 1!') +end +end + diff --git a/Kod/bilbana/IOFunctions/terminate.m b/Kod/bilbana/IOFunctions/terminate.m new file mode 100644 index 0000000..26a43f2 --- /dev/null +++ b/Kod/bilbana/IOFunctions/terminate.m @@ -0,0 +1,83 @@ +function [] = terminate(track) +%TERMINATE Stops all counters associated with specified track. +% Stops all counters associated with a specified track, and clears the +% resources. +% +% If both tracks are terminated as a result of a call on terminate() all +% resources, including the global variables, will be cleared and the +% PCI6602 card will be reset to original state. +% +% Tobias Lindell 2013-02-12 + +global mytaskh +global lib + +switch nargin + case 1 + if isempty(mytaskh) + disp('User needs to initialize counters before terminating!') + clearvars -global mytaskh lib + return + end + + + switch track + case 1 + % Check if track 1 counter has been initialized, stop program if not + if isfield(mytaskh,'ctr_0') + % Clear counters of selcted track + calllib(lib,'DAQmxClearTask',mytaskh.ctr_0); + calllib(lib,'DAQmxClearTask',mytaskh.ctr_1); + calllib(lib,'DAQmxClearTask',mytaskh.ctr_2); + calllib(lib,'DAQmxClearTask',mytaskh.ctr_3); + clear mytaskh.ctr_0 + clear mytaskh.ctr_1 + clear mytaskh.ctr_2 + clear mytaskh.ctr_3 + mytaskh = rmfield(mytaskh,'ctr_0'); + mytaskh = rmfield(mytaskh,'ctr_1'); + mytaskh = rmfield(mytaskh,'ctr_2'); + mytaskh = rmfield(mytaskh,'ctr_3'); + % Check to see if counters of other track are cleared, if so + % reset card to original state and clear global variables + if ~isfield(mytaskh,'ctr_4') + disp('Everything terminated. Device will reset!') + calllib(lib,'DAQmxResetDevice','Dev1'); + clearvars -global mytaskh lib + end + + else + disp(['User needs to initialize counters for track ',num2str(track),' before terminating!']) + return + end + case 2 + if isfield(mytaskh,'ctr_4') + calllib(lib,'DAQmxClearTask',mytaskh.ctr_4); + calllib(lib,'DAQmxClearTask',mytaskh.ctr_5); + calllib(lib,'DAQmxClearTask',mytaskh.ctr_6); + calllib(lib,'DAQmxClearTask',mytaskh.ctr_7); + clear mytaskh.ctr_4 + clear mytaskh.ctr_5 + clear mytaskh.ctr_6 + clear mytaskh.ctr_7 + mytaskh = rmfield(mytaskh,'ctr_4'); + mytaskh = rmfield(mytaskh,'ctr_5'); + mytaskh = rmfield(mytaskh,'ctr_6'); + mytaskh = rmfield(mytaskh,'ctr_7'); + if ~isfield(mytaskh,'ctr_0') + disp('Everything terminated. Device will reset!') + calllib(lib,'DAQmxResetDevice','Dev1'); + clearvars -global mytaskh lib + end + else + disp(['User needs to initialize counters for track ',num2str(track),' before terminating!']) + return + end + otherwise + disp('Wrong track argument sent to terminate(track)! Should be 1 or 2!') + end + otherwise + disp('Wrong number of arguments sent to terminate(track)! Should be 1!') +end +end + -- cgit v1.2.1