卒研の成果物
を以前公開するよと予告したので、今日思い立って公開します。ソースコードだけ。
700行程度、タートル工業社製のUSB AD/DAコンバータをVBを使って制御する参考例です。
'_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 'Program name:DA-AD-converter 'Date:2011/04/04(Program start) 'Name:raiden(E-mail address:gozen3.25(at)gmail.com) 'Status:During an experimet 'Purpuse:新型リニアボールガイド実験用プログラム 'Note:TUSB-0216ADMH and TUSB-0212DAMA '2011/08/25 フィードバック制御対応(比例制御のみ、積分、微分は随時対応予定) '2011/11/22 高精度時間制御対応(フィードバック制御と実行時間の高精度化) '2011/12/14 1[ms]でのフィードバック対応。ただし、AD変換データがない場合は ' フィードバック処理がされない。 '_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ Imports System Imports System.Diagnostics Imports System.Threading Public Class Form1 'ローカル変数 Private flag As Byte = 0 '実行時間終了フラグ Private adid As Byte '= adcid.SelectedItem 'adcのID Dim daid As Byte '= dacid.SelectedItem 'dacのID Private data2(100000) As integer 'adcから取得したデータ 'メイン関数関連変数 Dim err As Byte = 0 'エラーフラグ Dim wave As String '= outputwave.SelectedItem '出力波形 Dim Kp, Ti, voltage, voltrange, goal As Single Dim time As Integer = 1 '実行時間 Dim daerr As Byte = 0 'dacのエラー Dim aderr As Byte = 0 'adcのエラー Dim outputdata As Short = 0 Dim signal As Byte = 2 Dim channel As Integer = 0 Dim range As Integer = 0 Dim n As Integer = 0 Dim data1(8200) As Integer 'dacから出力する正弦波のデータ8200 Dim leng As Long Dim cerr As Integer 'フィードバックエラー回数 Dim ad_enable As Byte = 0 Dim da_enable As Byte = 0 Dim path As String Dim kouseikeisu As Single = 0.2086 Dim fcnt As Integer = 0 Dim voltage1 As Single = 0 Dim initvolt As Single = 0 Dim volt As Single = 0 '関数宣言 Declare Function timeGetTime Lib "winmm.dll" Alias "timeGetTime" () As Long '現在の時刻を取得 Declare Function timeBeginPeriod Lib "winmm.dll" Alias "timeBeginPeriod" (ByVal uPeriod As Long) As Long '時間精度を高くする Declare Function timeEndPeriod Lib "winmm.dll" Alias "timeEndPeriod" (ByVal uPeriod As Long) As Long Private Sub Wait(ByVal waittime As Long) 'waittime m秒待つ、timeGetTimeの精度は約1ms Dim starttime As Long 'Dim mmresult As Integer 'timeGetTime関数の精度をあげるためにはtimeBeginPeriod関数を使うが有効になるまでに時間がかかる。 'mmresult = timeBeginPeriod(1) starttime = timeGetTime() '現在の時刻を取得 Do While timeGetTime() - starttime < waittime '現在の時刻-starttimeが待ち時間を上回ったらループからぬける Application.DoEvents() Loop 'timeGetTime関数の使用後はただちにtimeEndPriod関数を使う 'mmresult = timeEndPeriod(1) End Sub 'dacエラーチェック関数 dacerrchk(dacerr) Private Sub dacerrchk(ByVal dacerr As Integer) Select Case dacerr Case Is = 1 MessageBox.Show("DACエラー! コード1:オープンされていません。") Case Is = 2 MessageBox.Show("DACエラー! コード2:失敗しました。") Case Is = 3 MessageBox.Show("DACエラー! コード3:設定値が不正です。") End Select End Sub 'adcエラーチェック関数 adcerrchk(adcerr) Private Sub adcerrchk(ByVal adcerr As Integer) Select Case adcerr Case Is = 1 MessageBox.Show("ADCエラー! コード1:IDが異なっています。") Case Is = 2 MessageBox.Show("ADCエラー! コード2:ドライバが正常にインストールされていません。") Case Is = 4 MessageBox.Show("ADCエラー! コード4:接続台数が多すぎます。") Case Is = 5 MessageBox.Show("ADCエラー! コード5:デバイスをオープンできませんでした。") Case Is = 6 MessageBox.Show("ADCエラー! コード6:指定のデバイスが見つかりません。") Case Is = 7 MessageBox.Show("ADCエラー! コード7:指定のデバイスはオープンされていません。") Case Is = 8 MessageBox.Show("ADCエラー! コード8:指定パラメータのエラーです。") Case Is = 9 MessageBox.Show("ADCエラー! コード9:USB通信エラーです。") Case Is = 10 MessageBox.Show("ADCエラー! コード10:メモリが確保できません。") Case Is = 11 MessageBox.Show("ADCエラー! コード11:連続取り込み動作中です") Case Is = 12 MessageBox.Show("ADCエラー! コード12:連続取り込みデータはありません。") Case Is = 13 MessageBox.Show("ADCエラー! コード13:連続取り込みが開始されていません。") Case Is = 14 MessageBox.Show("ADCエラー! コード14:メモリがオーバーフローしました。") Case Is = 15 MessageBox.Show("ADCエラー! コード15:データ列順エラーです。") Case Is = 99 MessageBox.Show("ADCエラー! コード99:その他のエラーです。") End Select End Sub '機能制限関数 function_enable_da(),function_enablead(),function_disable_da(),function_disable_ad() Private Sub function_enable_da() 'オープン、ID選択可 dacopen.Enabled = True dacid.Enabled = True dacclose.Enabled = False End Sub Private Sub function_disable_da() 'オープン、ID選択不可 dacopen.Enabled = False dacid.Enabled = False dacclose.Enabled = True End Sub Private Sub function_enable_ad() 'オープン、ID選択可 adcopen.Enabled = True adcid.Enabled = True adcclose.Enabled = False End Sub Private Sub function_disable_ad() 'オープン、ID選択不可 adcopen.Enabled = False adcid.Enabled = False adcclose.Enabled = True End Sub private sub execute_enable() '実行ボタンを押せるようにする。 If da_enable = 1 Then If ad_enable = 1 Then da_enable = 0 ad_enable = 0 Button1.Enabled = True 'Button5.Enabled = True 'Button2.Enabled = True End If Else Button1.Enabled = False 'Button5.Enabled = False 'Button2.Enabled = False End If End Sub '設定入力関数 settings() Private Sub settings() cerr = 0 time = Val(TextBox5.Text) voltage = Val(TextBox2.Text) goal = voltage Kp = Val(TextBox3.Text) Ti = Val(TextBox4.Text) leng = 1048576 wave = outputwave.SelectedItem 'ラジオボタンチェック If RadioButton1.Checked Then 'ユニポーラに設定 signal = 0 ElseIf RadioButton2.Checked Then 'バイポーラに設定 signal = 1 Else err = 1 MessageBox.Show("エラー3(出力方法が設定されていません。)") End If 'チャンネルチェック If usech.SelectedItem = "OUT1" Then channel = 1 ElseIf usech.SelectedItem = "OUT2" Then channel = 2 Else err = 1 MessageBox.Show("エラー19(チャンネルが設定されていません。)") End If '出力電圧レベルチェック If RadioButton3.Checked Then Select Case signal 'バイポーラ設定 Case Is = 1 If voltage <= 5 Then range = 0 voltrange = 5 '電圧をデジタル値に変換 If voltage <= 2.5 Then outputdata = voltage / (2.5 / 2048) ElseIf voltage <= 5 Then outputdata = (voltage - 2.5) / ((4.999 - 2.5) / 2047) + 2047 End If Else err = 1 MessageBox.Show("エラー21(設定に不正があります。)") End If 'ユニポーラ設定 Case Is = 0 If voltage <= 2.5 Then range = 0 voltrange = 2.5 outputdata = voltage / (2.5 / 2047) + 2048 'outputdata = voltage / (2.5 / 4095) Else err = 1 MessageBox.Show("エラー21(設定に不正があります。)") End If Case Is = 2 err = 1 End Select ElseIf RadioButton4.Checked Then Select Case signal 'バイポーラ設定 Case Is = 1 If voltage <= 10 Then range = 1 voltrange = 10 If voltage <= 5 Then outputdata = voltage / (2.5 / 2048) ElseIf voltage <= 10 Then outputdata = (voltage - 5) / ((9.996 - 5) / 2047) + 2046 End If Else err = 1 MessageBox.Show("エラー21(設定に不正があります。)") End If 'ユニポーラ設定 Case Is = 0 If voltage <= 5 Then range = 1 voltrange = 5 outputdata = voltage / (5 / 2047) + 2048 'outputdata = voltage / (5 / 4095) Else err = 1 MessageBox.Show("エラー21(設定に不正があります。)") End If Case Is = 2 err = 1 End Select ElseIf RadioButton5.Checked Then Select Case signal 'バイポーラ設定 Case Is = 1 err = 1 MessageBox.Show("エラー21(設定に不正があります。)") 'ユニポーラ設定 Case Is = 0 If voltage <= 10 Then range = 2 voltrange = 10 outputdata = voltage / (9.995 / 2047) + 2047 'outputdata = voltage / (9.995 / 4095) Else err = 1 MessageBox.Show("エラー21(設定に不正があります。)") End If Case Is = 2 err = 1 End Select Else err = 1 MessageBox.Show("エラー20(出力電圧レベルが設定されていません。)") End If 'ADクロック設定(クロック1MHz) メモリに格納されるデータ数=本来のデータ数/平均化回数 aderr = Tusbadmh_Clock_Select(adid, 0, 199, 8) If aderr <> 0 Then 'aderr = Tusbadmh_Clock_Select(adid, 0, 49, 8) adcerrchk(aderr) err = 1 Tusbadmh_Unload() End If 'アナログトリガ設定 aderr = Tusbadmh_ThLevel_Set(adid, 32767, 800) If aderr <> 0 Then 'aderr = Tusbadmh_ThLevel_Set(adid, 32767, 800) adcerrchk(aderr) err = 1 Tusbadmh_Unload() End If End Sub 'DA設定関数 sin_set(fcnt) Private Sub sin_set(ByVal fcnt As Integer) For i = 1 To 10 Step 1 '2048*電圧/出力電圧レベル=振幅 data1(i) = 2048 * (voltage / 5) * Math.Sin(2 * Math.PI * (i + 10 * fcnt) / 1700) + 2048 + 2048 * (voltage1 / 5) 'data1(i) = 2048 * (voltage / 2.5) * Math.Sin(2 * Math.PI * (i + 10 * fcnt) / 2000) + 2048 + 2048 * (voltage1 / 2.5) If data1(i) > 4095 Then data1(i) = 4095 ElseIf data1(i) < 0 Then data1(i) = 0 End If Next daerr = Tusbdam_Set_Memory(daid, channel, 10, data1(1)) If daerr <> 0 Then 'エラー dacerrchk(daerr) err = 1 console.Text &= "エラーが発生したため実行を中断します..." & vbCrLf Tusbadmh_Unload() Tusbdam_Device_Close(daid) Exit Sub End If End Sub 'feedback関数 Private Sub feedback() Dim D1 As Single '目標値 Dim D2 As Single '変換データ If Tusbadmh_Data_Get(adid, 0, data2(1), leng) <> 0 Then '***DLL関数の実行 MessageBox.Show("DLL関数の実行に失敗しました。デバイスをクローズします。") '***書きこみに失敗 Tusbadmh_Unload() err = 1 End If If leng <> 0 Then D1 = goal * Math.Sin(2 * Math.PI * (10 + 10 * fcnt) / 1700) D2 = (((data2(leng) - 32768) / 32768) / kouseikeisu) - initvolt 'フィードバック volt = D1 - D2 If voltage1 > voltrange Then voltage1 = voltrange End If Else cerr = cerr + 1 End If leng = 1048576 End Sub 'DA出力関数 output() Private Sub output() console.Text &= Now & vbCrLf & "機器設定" & vbCrLf & "実行時間(秒):" & time & vbTab & vbTab & vbCrLf & "条件設定" & vbCrLf & "電圧:" & voltage & vbTab & "比例ゲインKp:" & Kp & vbTab & "積分時間Ti:" & Ti & vbTab & "出力波形:" & wave & vbCrLf Select Case wave Case Is = "step" '出力波形:ステップ(step) Timer1.Enabled = True Timer1.Interval = time * 1000 Timer1.Start() 'ad変換設定 daerr = Tusbdam_Single_Out(daid, channel, outputdata) If daerr <> 0 Then 'エラー 'daerr = Tusbdam_Single_Out(daid, channel, outputdata) dacerrchk(daerr) err = 1 console.Text &= "エラーが発生したため実行を中断します..." & vbCrLf Tusbadmh_Unload() Tusbdam_Device_Close(daid) Exit Sub End If console.Text &= "実行します..." & vbCrLf Do Until flag = 1 My.Application.DoEvents() '実行中に発生する他の処理を可能にする If err = 1 Then Timer1.Stop() Timer1.Enabled = False flag = 0 Exit Do End If Loop '終了処理 Timer1.Stop() Timer1.Enabled = False 'Timer2.Stop() 'Timer2.Enabled = False Tusbdam_Stop(daid) 'console.Text &= time & "秒経過しました。" & vbCrLf Case Is = "sin" '出力波形:正弦波(sin) daerr = Tusbdam_Clock_Set(daid, 1, 2) 'da内部クロック、2MHz(最高) If daerr <> 0 Then 'エラー 'daerr = Tusbdam_Clock_Set(daid, 1, 2) '内部クロック dacerrchk(daerr) err = 1 console.Text &= "エラーが発生したため実行を中断します..." & vbCrLf Tusbadmh_Unload() Tusbdam_Device_Close(daid) Exit Sub End If fcnt = 0 'sin_set(fcnt) '正弦波の設定 daerr = Tusbdam_Cycle_Set(daid, 10) 'daデータ数と同じにする If daerr <> 0 Then 'エラー 'daerr = Tusbdam_Cycle_Set(daid, 1000) dacerrchk(daerr) err = 1 console.Text &= "エラーが発生したため実行を中断します..." & vbCrLf Tusbadmh_Unload() Tusbdam_Device_Close(daid) Exit Sub End If aderr = Tusbadmh_InputType(adid, 0, 0) If aderr <> 0 Then 'エラー 'aderr = Tusbadmh_InputType(adid, 0, 0) adcerrchk(aderr) err = 1 console.Text &= "エラーが発生したため実行を中断します..." & vbCrLf Tusbadmh_Unload() Tusbdam_Device_Close(daid) Exit Sub End If console.Text &= "実行を開始します..." & vbCrLf aderr = Tusbadmh_Adc_Start(adid, 100000, 0, 3, 0, 0) '1:ユニポーラ,0:バイポーラ,1トリガあたりの取り込み長 If aderr <> 0 Then 'エラー adcerrchk(aderr) err = 1 console.Text &= "エラーが発生したため実行を中断します..." & vbCrLf Tusbadmh_Unload() Tusbdam_Device_Close(daid) Exit Sub End If 'ソフトウェアトリガ aderr = Tusbadmh_Trigger(adid) If aderr <> 0 Then adcerrchk(aderr) err = 1 console.Text &= "エラーが発生したため実行を中断します..." & vbCrLf Tusbadmh_Unload() Tusbdam_Device_Close(daid) Exit Sub End If '初期電圧を測定する Wait(10) If Tusbadmh_Data_Get(adid, 0, data2(1), leng) <> 0 Then '***DLL関数の実行 MessageBox.Show("DLL関数の実行に失敗しました。デバイスをクローズします。") '***書きこみに失敗 Tusbadmh_Unload() err = 1 End If initvolt = ((data2(leng) - 32768) / 32768) / kouseikeisu console.Text &= initvolt & vbCrLf & "取り込みデータ長=" & leng & vbCrLf leng = 1048576 'HIOKIと同期 Tusbdam_Set_Memory(daid, channel, 10, 4095) Tusbdam_Start(daid, 2) 'wait(10) 'Tusbdam_Set_Memory(daid, 2, 1, 2184) 'Tusbdam_Start(daid, 2) 'Tusbdam_stop(adid) 'Dim stopWatch As New Stopwatch() 'timer1:時間計測 Timer1.Enabled = True Timer1.Interval = time * 1000 'Timer2.Enabled = True 'Timer2.Interval = 1 'Timer2.Start() Timer1.Start() 'stopWatch.Start() 'フィードバック用スレッド BackgroundWorker1.RunWorkerAsync() Do Until flag = 1 My.Application.DoEvents() '実行中に発生する他の処理を可能にする If err = 1 Then Timer1.Stop() Timer1.Enabled = False flag = 0 'Timer2.Stop() 'Timer2.Enabled = False Exit Do End If Select Case signal 'ユニポーラ Case Is = 0 MessageBox.Show("エラー21(設定に不正があります。)") flag = 0 Timer1.Stop() Timer1.Enabled = False 'Timer2.Stop() 'Timer2.Enabled = False err = 1 Exit Do 'バイポーラ Case Is = 1 'fcntは100000なら1データあたり1000であれば1000*fcntを足すからfcnt=99にすればよい For i = 0 To 169 Step 1 sin_set(fcnt) daerr = Tusbdam_Start(daid, 0) If daerr <> 0 Then dacerrchk(daerr) err = 1 console.Text &= "エラーが発生したため実行を中断します..." & vbCrLf Tusbadmh_Unload() Tusbdam_Device_Close(daid) Exit Sub End If 'フィードバックされたデータを反映 If volt <> voltage1 Then voltage1 = volt End If fcnt = fcnt + 1 '時間経過か緊急停止ボタン(エラー)が押されたらexit doで終了する If flag = 1 Or err = 1 Then Exit Do End If Next fcnt = 0 End Select Loop '出力終了 'stopWatch.Stop() Timer1.Stop() Timer1.Enabled = False 'Timer2.Stop() 'Timer2.Enabled = False Tusbdam_Stop(daid) Tusbadmh_Adc_Stop(adid) 'console.Text &= stopWatch.ElapsedMilliseconds & "ミリ秒経過しました。" & vbCrLf End Select End Sub '終了処理関数 shutdown() Private Sub shutdown() Select Case wave Case Is = "step" '0Vを出力しなおす Select Case signal Case Is = 0 'ユニポーラ Tusbdam_Single_Out(daid, channel, 0) Case Is = 1 'バイポーラ Tusbdam_Single_Out(daid, channel, 2048) End Select flag = 0 Case Is = "sin" '0Vを出力しなおす Select Case signal Case Is = 0 Tusbdam_Single_Out(daid, channel, 0) Case Is = 1 Tusbdam_Single_Out(daid, channel, 2048) End Select flag = 0 End Select End Sub 'エラーチェック関数 errorcheck() Private Sub errorcheck() 'adcが使用できるか? aderr = Tusbadmh_Chk(adid) If aderr <> 0 Then 'aderr = Tusbadmh_Chk(adid) adcerrchk(aderr) err = 1 Tusbadmh_Unload() End If 'If (voltrange = 2.5 & signal = 0) Then 'err = 1 'console.Text = "エラーが発生したため実行を中断します..." & vbCrLf 'Tusbadmh_Unload() 'Tusbdam_Device_Close(daid) 'End If '出力電圧レベル設定 daerr = Tusbdam_Range_Set(daid, channel, signal, range) If daerr <> 0 Then err = 1 'daerr = Tusbdam_Range_Set(daid, channel, signal, range) dacerrchk(daerr) Tusbdam_Device_Close(daid) End If 'エラーチェック If wave = "" Then MessageBox.Show("エラー2(出力波形が設定されていません。)") err = 1 End If End Sub 'メイン関数 Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click '実行ルーチン '緊急停止ボタン以外を使用不可にする Button1.Enabled = False Button2.Enabled = False Button3.Enabled = False Button4.Enabled = False '高精度時間制御を可能にする Call timeBeginPeriod(1) err = 0 path = "" console.Text &= "実行準備中..." & vbCrLf settings() errorcheck() 'エラーが発生した場合実行しない If err = 0 Then Dim result As DialogResult = MessageBox.Show("実行します。可能な限り変位センサを0Vに近づけて、OKをクリックしてください。" ,"注意" , MessageBoxButtons.OKCancel) If result = DialogResult.OK Then 'console.Text &= "測定値,設定値,目標値" & vbCrLf shutdown() output() shutdown() console.Text &= "フィードバックエラー回数:" & cerr & vbCrLf MessageBox.Show(time & "秒経過しました。") ElseIf result = DialogResult.Cancel Then MessageBox.Show("実行を中止しました。") shutdown() End If ElseIf err = 1 Then shutdown() MessageBox.Show("エラーが発生したため実行を中止します。") Tusbdam_Device_Close(daid) Tusbadmh_Unload() End If '高精度時間制御を不可にする Call timeEndPeriod(1) 'ボタン有効化 Button1.Enabled = True Button2.Enabled = True Button3.Enabled = True Button4.Enabled = True 'For i = 1 To 100 Step 1 'Next 'shutdown() End Sub '終了 Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click End End Sub '保存 Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click '保存ルーチン Dim sfd As New SaveFileDialog() sfd.Filter = "テキストファイル(*.log)|*.log|全てのファイル(*.*)|*.*" '[ファイルの種類]ではじめに '「テキストファイル」が選択されているようにする sfd.FilterIndex = 1 'タイトルを設定する sfd.Title = "保存先のファイルを選択してください。" 'ダイアログボックスを閉じる前に現在のディレクトリを復元するようにする sfd.RestoreDirectory = True '既に存在するファイル名を指定したとき警告する 'デフォルトでTrueなので指定する必要はない sfd.OverwritePrompt = True '存在しないパスが指定されたとき警告を表示する 'デフォルトでTrueなので指定する必要はない sfd.CheckPathExists = True 'ダイアログを表示する If sfd.ShowDialog() = DialogResult.OK Then Dim Writer As New IO.StreamWriter(sfd.FileName, True, System.Text.Encoding.GetEncoding("Shift-JIS")) Writer.Write(console.Text) Writer.Close() MessageBox.Show("保存しました。") End If End Sub 'textboxクリア Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click 'messageboxクリア処理 console.Text = "" End Sub 'Form1を閉じたとき Private Sub Form1_Closed(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Closed If Timer2.Enabled Then 'タイマー2が動作中であれば Timer2.Enabled = False End If If Timer1.Enabled Then Timer1.Enabled = False 'タイマー1を停止します End If 'デバイスのクローズ Tusbdam_Device_Close(daid) Tusbadmh_Unload() End Sub '実行時間の計測 Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick 'タイマー終了フラグを1にする flag = 1 err = 1 Timer1.Enabled = False Timer1.Stop() Timer2.Enabled = False Timer2.Stop() shutdown() End Sub '割り込み処理(AD変換データの書き込み) Private Sub Timer2_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer2.Tick 'マルチスレッド 'BackgroundWorker1.RunWorkerAsync() End Sub 'マルチスレッド Private Sub backgroundworker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork ' BackgroundWorkerの取得(スレッドを作成したオブジェクト) Dim objWorker As System.ComponentModel.BackgroundWorker = CType(sender, System.ComponentModel.BackgroundWorker) '出力開始まで待機 wait(2) 'フィードバック Do Until err = 1 Wait(10) feedback() Loop End Sub Private Sub backgroundworker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted '何もしない End Sub 'DACオープン Private Sub dacopen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dacopen.Click Dim dacerr As Integer daid = dacid.SelectedItem console.Text &= "DAコンバータをオープンします..." dacerr = Tusbdam_Device_Open(daid) If dacerr = 0 Then console.Text &= "使用できる状態になりました。" & vbCrLf function_disable_da() da_enable = 1 Else 'エラーの場合 dacerrchk(dacerr) End If execute_enable() End Sub 'ADCオープン Private Sub adcopen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles adcopen.Click Dim i As Integer = 0 Dim adcerr As Integer adid = adcid.SelectedItem console.Text &= "ADコンバータをオープンします..." Tusbadmh_Load() While i < 10 Wait(500) '500ms待つ adcerr = Tusbadmh_Chk(adid) If Tusbadmh_Chk(adid) = 0 Then 'エラーチェック i = 10 'ループをぬける function_disable_ad() console.Text &= "使用できる状態になりました。" & vbCrLf ad_enable = 1 End If i = i + 1 End While If adcerr <> 0 Then 'エラーの場合 adcerrchk(adcerr) End If execute_enable() End Sub 'DACクローズ Private Sub dacclose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dacclose.Click Tusbdam_Device_Close(dacid.SelectedItem) function_enable_da() da_enable = 0 execute_enable() End Sub 'ADCクローズ Private Sub adcclose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles adcclose.Click Tusbadmh_Unload() function_enable_ad() ad_enable = 0 execute_enable() End Sub '起動時の処理 Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load function_enable_da() function_enable_ad() execute_enable() 'Button2.Enabled = false '保存ボタン無効 End Sub '緊急停止 Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click '緊急停止 Timer1.Stop() Timer1.Enabled = False Timer2.Stop() Timer2.Enabled = False Tusbdam_Stop(daid) Tusbadmh_Adc_Stop(adid) shutdown() err=1 Messagebox.show("実行を中断しました。") 'ボタン有効化 Button1.Enabled = True Button2.Enabled = True Button3.Enabled = True Button4.Enabled = True End Sub End Class
卒研の成果物(C/C++ version)
一応、C/C++でも作ってあるので、そちらも公開しておかないと、と思い今更ながら公開。
動作未検証です。簡単なデバックはしていますが、動作保証しませんので。
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //Program name:DA-AD-Converter //Date:2011/12/17(Programing start) //Name:raiden(E-mail address:gozen3.25(at)gmail.com) //Status:During as experiment //Purpuse:Control program for the linear guide //Version:0.1 //Note:TUSB-0216ADMH and TUSB-0212DAM // //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ #include <stdio.h> #include "stdafx.h" #include <math.h> #include <conio.h> //画面のクリアするヘッダー #include <stdlib.h> //割り込み関連のヘッダー //参考URL:http://www.mint.se.ritsumei.ac.jp/contest/text/6/VCtimer.html #include <windows.h> #include <mmsystem.h> #pragma comment(lib, "winmm.lib") //TUSB-0216ADMHのヘッダーファイル //#include <TUSBADMH.h> //TUSB-0212DAMのヘッダーファイル //#include <TUSBDAM.h> //グローバル変数設定 double voltage = 0; //double voltage1 = 0; int channel = 1; double Kp = 0; double Ti = 0; int time = 0; int type = 0; int cerr = 0; //定数宣言 const double kouseikeisu = 0.2086; //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //タイマー割り込み(実行時間計測) // //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ void CALLBACK timerProc(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dummy1, DWORD dummy2){ // タイマー割り込みの処理 (*(int*)dwUser)++; return; } //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //タイマー割り込み(フィードバック) // //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ void CALLBACK timerFeedback(UINT uTimerID, UINT uMsg, DWORD dwUser, DWORD dummy1, DWORD dummy2){ // タイマー割り込みの処理 //feedback(); return; } //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //DAコンバータエラーチェック関数 //daerrchk(int dacerr) //引数1:dacerr daのエラー //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ int daerrchk(int dacerr){ switch(dacerr){ case 1: printf("DA converter error! Code1:Is not open.\n"); break; case 2: printf("DA converter error! Code2:Has failed.\n"); break; case 3: printf("DA converter error! Code3:Setting is incorrect.\n"); break; } return 0; } //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //ADコンバータエラーチェック関数 //aderrchk(int adcerr) //引数1:adcerr adのエラー //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ int aderrchk(int adcerr){ switch(adcerr){ case 1: printf("DA converter error! Code1:Is not open.\n"); break; case 2: printf("DA converter error! Code2:No drivers are installed correctly.\n"); break; case 4: printf("DA converter error! Code4:Too many connections number.\n"); break; case 5: printf("DA converter error! Code5:Could not open the device.\n"); break; case 6: printf("DA converter error! Code6:Can not find the specified device.\n"); break; case 7: printf("DA converter error! Code7:The specified device is not opened.\n"); break; case 8: printf("DA converter error! Code8:Error of the specified parameter.\n"); break; case 9: printf("DA converter error! Code9:Communication error USB.\n"); break; case 10: printf("DA converter error! Code10:Unable to allocate memory.\n"); break; case 11: printf("DA converter error! Code11:Continuous runnig capture.\n"); break; case 12: printf("DA converter error! Code12:Data acquisition is not continuous.\n"); break; case 13: printf("DA converter error! Code13:Continuous uptake has not been started.\n"); break; case 14: printf("DA converter error! Code14:Memory overflow.\n"); break; case 15: printf("DA converter error! Code15:The first column of data error.\n"); break; case 99: printf("DA converter error! Code99:Other error.\n"); break; } return 0; } //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //shutdown関数 //shutdown() // //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ int shutdown(){ switch(type){ case 0: //sin //Tusbdam_Single_Out(daid, channel, 2048); break; case 1: //step //Tusbdam_Single_Out(daid, channel,0); break; } return 0; } //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //設定関数 //settings(daid, adid) //引数1:daid DAコンバータのID //引数2:adid ADコンバータのID //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ int settings(int daid, int adid){ int err = 0; //int type = 0; int dacerr = 0; int adcerr = 0; //出力波形設定 printf("What is output type?(0=sin,1=step):"); scanf("%d", &type); while(1){ if(type == 0){ printf("Output type:sin\n"); break; }else if(type == 1){ printf("Output type:step\n"); break; }else{ printf("Error!\nWhat is output type?(0=sin,1=step):"); scanf("%d", &type); } } //チャンネル設定 printf("DA converter output channels?(1 or 2):"); scanf("%d", &channel); while(1){ if(channel == 1){ break; }else if(channel == 2){ break; }else{ printf("Error!\nDA converter output channels?(1 or 2):"); scanf("%d", &channel); } } printf("channel:%d\n", channel); //電圧設定 if(type == 1){ //step printf("How much voltage?(0-5[V]):"); scanf("%lf", &voltage); while(voltage > 5){ printf("Error!\nHow much voltage?(0-5[V]):"); scanf("%lf", &voltage); } printf("%lf[V]\n", voltage); }else if(type == 0){ //sin printf("How much voltage?(0-2.5[V]):"); scanf("%lf", &voltage); while(voltage > 2.5){ printf("Error!\nHow much voltage?(0-2.5[V]):"); scanf("%lf", &voltage); } printf("%lf[V]\n", voltage); }else{ err=1; } //実行時間設定 printf("How much run time?(0-100[s]):"); scanf("%d", &time); while(1){ if(time > 0){ if(time < 100){ break; }else{ printf("Error!\nHow much run time?(0-100[s])"); scanf("%d", &time); } }else{ printf("Error!\nHow much run time?(0-100[s])"); scanf("%d", &time); } } printf("%d[s]\n", time); //比例ゲイン設定 printf("How much proportional gain(Kp)?:"); scanf("%lf", &Kp); printf("%lf\n", Kp); //積分時間設定 printf("How much integration time(Ti)?:"); scanf("%lf", &Ti); printf("%lf\n", Ti); /*//ADクロック設定 adcerr = Tusbadmh_Clock_Select(adid, 0, 49, 8); //DAクロック設定 dacerr = Tusbdam_Clock_Set(daid, 1, 2); //DAデータの出力回数 dacerr = Tusbdam_Cycle_Set(daid, 10); //ADの入力タイプ switch(channel){ case 1:{ adcerr = Tusbadmh_InputType(daid, type, 0); break; } case 2:{ adcerr = Tusbadmh_InputType(daid, 0, type); break; } default :{ err = 1; break; } }*/ if(err == 1){ //エラー printf("Error!:Some errors were detected.\n"); return 1; }else if(err == 0){ return 0; } } //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //ADコンバータオープン関数 //adopen(int adid) //引数1:adid ADコンバータのID //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ int adopen(int adid){ int adcerr = 0; //printf("What is the ID of the AD converter?(0-15):"); //scanf("%d", &adid); printf("AD converter ID is %d.It is open to the AD converter...", adid); //Tusbadmh_Load(); //adcerr = Tusbadmh_Chk(daid); if(adcerr == 0){ //ループを抜ける printf("Can be used.\n"); return 0; }else{ //エラー aderrchk(adcerr); return 1; } } //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //DAコンバータオープン関数 //daopen(int daid) //引数1:daid DAコンバータのID //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ int daopen(int daid){ int dacerr = 0; //printf("What is the ID of the DA converter?(0-15):"); //scanf("%d", &daid); printf("DA converter ID is %d.It is open to the DA converter...", daid); //dacerr = Tusbdam_Device_Open(daid); if(dacerr == 0){ printf("Can be used.\n"); return 0; }else{ //エラー daerrchk(dacerr); return 1; } } //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //波形生成関数 //sin(int fcnt) //引数1:fcnt 正弦波分割数 //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ int sin_set(int fcnt){ int data[10]; int i = 0; //int dacerr = 0; for(i = 0 ; i < 10; i++){ data[i] = 2048 * (voltage / 2.5) * sin(2 * 3.14159265 * (i+10 * fcnt) / 1700) + 2048; //+ 2048 * (voltage1/2.5); if(data[i] > 4095){ data[i] = 4095; }else if(data[i] < 0){ data[i] = 0; } } //dacerr = Tusbdam_Set_Memory(daid, channel, 10, data[i]); return 0; } //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //フィードバック関数 //feedback() // //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ int feedback(){ //D1:目標値 //D2:変位センサからの出力 double D1, D2 = 0; int data[1048576]; int leng = 1048576; int err = 0; /*if(Tusbadmh_Data_Get(daid, 0, data[1], leng) != 0){ err = 1; printf("Failed to execute the function DLL.Close the device.\n"); Tusbadmh_Unload(); } if(leng <> 0){ D1 = 2.5 * Sin(2 * 3.141592 * (10 + 10 * fcnt) / 1700); D2 = ((data[leng] - 32768) / 32768) - initvolt; //フィードバック volt = D1 - D2; if(volt > 2.5){ volt = 2.5 } }else{ cerr = cerr + 1; }*/ if(err == 1){ return 1; }else if(err == 0){ return 0; } } //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //出力関数 //output() // //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ int output(){ int err = 0; //int dacerr = 0; //int adcerr = 0; switch(type){ case 0:{ //sin //da内部クロック,2MHz(最高) /*dacerr = Tusbdam_Clock_Set(daid, 1, 2); if(dacerr != 0){ //エラー daerrchk(dacerr); err = 1; printf("Some errors were detected.\n"); //終了処理 Tusbadmh_Unload(); Tusbdam_Device_Close(daid); break; } fcnt = 0; //daデータ数と同じにする dacerr = Tusbdam_Cycle_Set(daid, 10); if(dacerr != 0){ //エラー dacerrchk(dacerr); err = 1; printf("Some errors were detected.\n"); Tusbadmh_Unload(); Tusbdam_Device_Close(daid); break; } adcerr = Tusbadmh_InputType(daid, 0, 0); if(adcerr != 0){ adcerrchk(adcerr); err = 1; printf("Some errors were detedted.\n"); Tusbadmh_Unload(); Tusbdam_Device_Close(daid); break; } //実行開始 printf("start the run...\n"); adcerr = Tusbadmh_Adc_Start(daid, 100000, 0, 3, 0, 0); if(adcerr != 0){ //エラー adcerrchk(adcerr); err = 1; printf("Some errors were detected.\n"); Tusbadmh_Unload(); Tusbdam_Device_Close(daid); break; } //ソフトウェアトリガ adcerr = Tusbadmh_Trigger(adid); if(adcerr != 0){ adcerrchk(adcerr); err = 1; printf("Some errors were detected.\n"); Tusbadmh_Unload(); Tusbdam_Device_Close(daid); break; } //初期電圧を測定する //10msの遅延 int data[1048576]; int leng = 1048576; if(Tusbadmh_Data_Get(daid, 0, data[1], leng) != 0){ //エラー printf("Some errors were detected.\n"); Tusbadmh_Unload(); err = 1; } initvolt = ((data[leng] - 32768)/32768)/kouseikeisu; */ //count:1[s]カウンタ int count = 0; MMRESULT timerID1 = timeSetEvent(1000, // 間隔[ms] 0, // 分解能 timerProc, // 割り込み関数 (DWORD)&count, // ユーザーパラメータ TIME_PERIODIC | TIME_CALLBACK_FUNCTION // 動作フラグ ); if( !timerID1 ){ printf("Failed to register a timer.\n"); return -2; } MMRESULT timerID2 = timeSetEvent(12, // 間隔[ms] 0, // 分解能 timerFeedback, // 割り込み関数 (DWORD)&count, // ユーザーパラメータ TIME_PERIODIC | TIME_CALLBACK_FUNCTION // 動作フラグ ); if(!timerID2){ printf("Failed to register a timer.\n"); return -2; } while(count < time){ //実行中のループ printf("%d ",count); } // タイマー割り込み関数の登録抹消 timeKillEvent(timerID1); timeKillEvent(timerID2); break; } case 1:{ //step /*outputdata = 2048 * voltage / 2.5 + 2047; dacerr = Tusbdam_Single_Out(daid, channel, outputdata); if(dacerr != 0){ daerrchk(dacerr); err = 1; printf("Some errors were detected.\n"); //終了処理 break; } while(1){ if(flag == 1){ break; } } */ break; } } if(err == 1){ return 1; }else{ return 0; } } //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ //main関数 //main() // //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ int main(int argc, char *argv[]){ int err = 0; int daid = 0; int adid = 0; char cmd; int fcnt = 0; int i = 0; //forのための変数 //画面のクリア system("cls"); printf("Control program for the linear guide. Version 0.1\n"); printf("Please press key one of the following key.(s:start,e:exit,c:clear)"); //メインメニュー while(1){ //cmd = getchar(); scanf("%c", &cmd); switch(cmd){ case 's':{ printf("Prepare for execution...\n"); //adコンバータオープン printf("What is the ID of the AD converter?(0-15):"); scanf("%d", &adid); if(adopen(adid) == 1){ err = 1; printf("An error was detected in adopen(). Will cease...\n"); //exit(); break; } //daコンバータオープン printf("What is the ID of the DA converter?(0-15):"); scanf("%d", &daid); if(daopen(daid) == 1){ err = 1; printf("An error was detected in daopen(). Will cease...\n"); //exit(); break; } if(settings(daid, adid) == 1){ err = 1; printf("An error was detected in settings(). Will cease...\n"); //exit(); break; } //出力開始 if(output()==1){ err=1; printf("An error was detected in output(). Will cease...|n"); break; } //出力終了 printf("Please press key one of the following key.(s:start,e:exit,c:clear)"); scanf("%c", &cmd); break; } case 'e':{ printf("Exit...\n"); return 0; } case 'c':{ //画面のクリア system("cls"); printf("Please press key one of the following key.(s:start,e:exit,c:clear)"); scanf("%c", &cmd); break; } //想定外の文字をタイプした場合 default :{ printf("Invaild Input\nPlease press key one of the following key.(s:start,e:exit,c:clear)"); scanf("%c", &cmd); break; } } } //エラー return 1; }