' $prog &HFF , &HE2 , &HDC , &HFF 'CKDIV8 = 1 , BODLEVEL = 4.3V ' ' ********************************************** ' * * ' * マイコン用 可変電源 プログラム * ' * * ' * AVR is using ATtiny861A * ' * Basic Compiler is BASCOM-AVR * ' * Copyright By O-Family 2013. 6.26 * ' ********************************************** ' ' Ver 1.01 初回公開バージョン。 2013. 4. 2 ' Ver 1.11 電流の最大値表示を追加。 2013. 6.26 ' ' Const Prgver = " 1.11" 'プログラム・バージョン。 ' ' $regfile = "ATtiny861.DAT" '使用するAVRを設定。 $crystal = 8000000 'AVRクロックを設定。 ' $hwstack = 64 'ハードウェア・スタックの容量を設定。 $swstack = 10 'ソフトウェア・スタックの容量を設定。 $framesize = 24 'フレーム領域の容量を設定。 Open "comB.0:9600,8,N,1" For Output As #1 'シリアル出力用のポートと通信フォーマットを設定する。 ' ' * ポート名の定義 * ' Sw_1 Alias Pina.7 'スイッチ[1]の接続ポート。 Sw_1pu Alias Porta.7 'スイッチ[1]の接続ポート(プルアップ用)。 Sw_2 Alias Pina.6 'スイッチ[2]の接続ポート。 Sw_2pu Alias Porta.6 'スイッチ[2]の接続ポート(プルアップ用)。 Sw_3 Alias Pina.5 'スイッチ[3]の接続ポート。 Sw_3pu Alias Porta.5 'スイッチ[3]の接続ポート(プルアップ用)。 Rl_range Alias Porta.4 '電流レンジ切換リレーの接続ポート。 ' Ad_voltage Alias 0 '電圧測定用のA/Dチャネル番号。 Ad_current1 Alias 1 '電流[低レンジ]測定用のA/Dチャネル番号。 Ad_current2 Alias 2 '電流[高レンジ]測定用のA/Dチャネル番号。 ' ' * 変数の宣言 * ' Dim Advoltage As Word '電圧のA/D変換値。 Dim Adcurrent As Word '電流のA/D変換値。 Dim Voltage As Word '電圧の計測値。 Dim Tempvoltage As Word '電圧の保管値。 Dim Current As Word '電流の計測値。 Dim Maxcurrent As Word '電流の最大値。 Dim Refvolt As Word 'AVRの内部基準電圧較正値。 Dim Time100ms As Byte '100mSカウンター。 Dim Vdisp500ms As Byte '電圧表示500mSカウンター。 Dim Time1s As Byte '1秒カウンター。 Dim Currentrange As Byte '電流レンジの状態フラグ。(0:高レンジ , 1:低レンジ) Dim Blinkflag As Byte '表示の点滅フラグ。 Dim Maxdispf As Byte '電流の最大値表示フラグ。 Dim Txinterval As Byte 'シリアル出力の送信間隔。 Dim Txtime As Word '送信間隔の設定時間。 Dim Txtimecount As Word '送信間隔のカウンター。 Dim Strvoltage As String * 6 '電圧値の文字列。 Dim Strcurrent As String * 6 '電流値の文字列。 Dim Strcurrent2 As String * 6 '電流値の文字列。(最大値用) ' Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Tempw1 As Word '汎用テンポラリ変数 Word型 No.1 Dim Tempi1 As Integer '汎用テンポラリ変数 Integer型 No.1 Dim Templ1 As Long '汎用テンポラリ変数 Long型 No.1 Dim Tempstr As String * 10 '汎用テンポラリ変数 String型 Dim Tempstr2 As String * 10 '汎用テンポラリ変数 String型 No.2 ' Dim Dummy As Eram Long 'EEPROM 4バイトのダミーエリア。 Dim Eeptxinterval As Eram Byte 'EEPROM シリアル出力の送信間隔。 Dim Eeprefvolt As Eram Word 'EEPROM AVRの内部基準電圧較正値。 Dim Eeposccal As Eram Byte 'EEPROM AVR内ぞう発振器の校正値。 ' ' * ポートの初期設定 * ' Set Sw_1pu 'スイッチ[1]の接続ポートをプルアップする。 Set Sw_2pu 'スイッチ[2]の接続ポートをプルアップする。 Set Sw_3pu 'スイッチ[3]の接続ポートをプルアップする。 Config Rl_range = Output '電流レンジ切換リレーの接続ポートを出力に設定する。 ' Didr0 = &B0000_0111 'デジタル入力禁止レジスタの設定。 ' ' * LCDの初期設定 * ' Config Lcdmode = Port 'LCDを4ビットのポートモードに設定。 Config Lcdbus = 4 'LCDデータバスを4bitに設定。 Config Lcdpin = Pin , Db4 = Portb.6 , Db5 = Portb.3 'LCDのポート割り当て。 Config Lcdpin = Pin , Db6 = Portb.5 , Db7 = Portb.4 Config Lcdpin = Pin , E = Portb.2 , Rs = Portb.1 Config Lcd = 16 * 2 'LCD表示を16文字2行に設定。 Cls 'LCD表示をすべて消去。 Cursor Off 'LCDのカーソルをオフにする。 Deflcdchar 1 , &H1D , &H19 , &H15 , &H0D , &H00 , &H1D , &H1D , &H1F 'カスタム文字[反転4]をLCDへ書き込む。 Deflcdchar 2 , &H19 , &H17 , &H0F , &H01 , &H0E , &H0E , &H11 , &H1F 'カスタム文字[反転6]をLCDへ書き込む。 ' ' * Timerの設定 * ' Tccr0a = &B0000_0001 'Timer0 = 8bit Timer動作 , Clear Timer = 1 Tccr0b = &B0000_0101 'Prescale = 1024 (8,000,000Hz / 1,024 = 7,812.5Hz) Ocr0a = 78 - 1 '7,812.5Hz / 78 = 100Hz(10mS) ' Tccr1d = &B0000_0000 'Config Timer1 = Timer (標準動作) Tccr1b = &B0000_1011 'Prescale = 1,024 (8,000,000Hz / 1,024 = 7,812.5Hz) Tccr1a = &B0000_0000 Tccr1c = &B0000_0000 Tc1h = &H03 '7,812.5Hz / 781カウント = 10Hz(100mS) [780]カウントを比較器C に書き込む。 Ocr1c = &H0C ' ' * A/Dコンバーターの設定 * ' Config Adc = Single , Prescaler = Auto , Reference = Internal_2.56_extcap 'A/Dコンバータの設定。 Config Aci = Off 'アナログ比較器の電源を切る。 ' ' * EEPROMのデータを確認する * ' If Eeptxinterval > 10 Then 'If EEPROMが初期値か? Then Eeptxinterval = 0 'EEPROM シリアル出力の送信間隔。 Eeprefvolt = 2560 'EEPROM AVRの内部基準電圧較正値。 Temp1 = Osccal Eeposccal = Temp1 'AVR内ぞう発振器の校正値。 End If Txinterval = Eeptxinterval Refvolt = Eeprefvolt Temp1 = Eeposccal Osccal = Temp1 ' ' * 較正モードのチェック * ' If Sw_2 = 0 Then Goto Refset 'If AVR内部基準電圧の校正か? Then If Sw_3 = 0 Then Goto Oscset 'If AVR内ぞう発振器の校正か? Then ' If Sw_1 = 0 Then 'If プログラムバージョンの表示か? Then Locate 1 , 1 'プログラム・バージョンを表示。 Lcd "Prg.Ver." Locate 2 , 2 Lcd "V." ; Prgver Bitwait Sw_1 , Set 'スイッチ1が離されるまで待つ。 Waitms 30 'チャタリング・タイマー。 Cls End If ' ' * 動作の初期設定 * ' Gosub Currangeset '電流レンジの表示とリレーの設定。 Txtime = Lookup(txinterval , Txtimetable) '送信間隔の設定時間を読み込む。 Txtimecount = 0 '送信間隔のカウンターを初期化する。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: ' ' * 電流値のA/D変換 * ' If Currentrange = 0 Then 'If 電流レンジが[高レンジ]か? Then Adcurrent = Getadc(ad_current2) '[高レンジ]電流をA/D変換する。 Else Adcurrent = Getadc(ad_current1) '[低レンジ]電流をA/D変換する。 If Adcurrent = 1023 Then 'If 電流が測定上限を超えたか? Then Currentrange = 0 Reset Rl_range '電流レンジ切換リレーを[OFF]にする。 Locate 2 , 1 Lcd "H" Maxdispf = 0 '電流の最大値表示フラグをクリアする。 Maxcurrent = 0 '電流の最大値を初期化する。 Adcurrent = Getadc(ad_current2) '[高レンジ]電流をA/D変換する。 End If End If ' Templ1 = Refvolt * Adcurrent '2.560V(較正値)÷1024×1000000×[A/D値]÷1000 Shift Templ1 , Right , 8 , Signed '式を変えて 2.560V(較正値)×1000×[A/D値]÷1024×4倍(抵抗分割分) Tempw1 = Templ1 Current = Tempw1 / 10 '最下位桁を切り捨てる。 ' If Current < 6 Then 'If OPアンプの最低出力電圧以下か? Then Current = 0 End If ' If Current > Maxcurrent Then 'If 計測した電流値が最大値を超えたか? Then Maxcurrent = Current '電流の最大値を更新する。 End If ' ' * 100mS間隔の処理 * ' If Tifr.tov1 = 1 Then 'If 100m経過したか? Then Set Tifr.tov1 ' ' * 電圧のA/D変換 * ' Advoltage = Getadc(ad_voltage) '電圧をA/D変換する。 Templ1 = Refvolt * Advoltage '2.560V(較正値)÷1024×1000000×[A/D値]÷1000 Shift Templ1 , Right , 8 , Signed '式を変えて 2.560V(較正値)×1000×[A/D値]÷1024×4倍(抵抗分割分) Tempw1 = Templ1 Voltage = Tempw1 / 10 '小数点以下を2桁にする。 ' Tempi1 = Tempvoltage - Voltage '前回の電圧値との差分を求める。 Tempw1 = Abs(tempi1) Tempvoltage = Voltage If Tempw1 > 10 Then '前回の測定値と100mV以上の差があるか? Thn Vdisp500ms = 0 Temp1 = 1 Else '前回との差が100mV以下の場合。 Vdisp500ms = Vdisp500ms + 1 If Vdisp500ms > 4 Then 'If 500mS経過したか? Then Vdisp500ms = 0 Temp1 = 1 Else Temp1 = 0 End If End If ' ' * LCDに電圧と電流を表示する ' If Temp1 = 1 Then 'If 表示を更新するか? Then ' ' * [電圧]の表示 * ' Locate 1 , 2 '[電圧]の表示。 If Advoltage = 1023 Then 'If 測定の上限値か? Then Lcd "-OVER-V" Strvoltage = " OVER" Else Tempstr = Str(voltage) Strvoltage = Format(tempstr , " 0.00") Lcd Strvoltage ; " V" End If ' ' * [電流]の表示 * ' Locate 2 , 3 If Adcurrent = 1023 Then 'If 測定の上限値か? Then Lcd "-OVER-A" Strcurrent = "OVER" Strcurrent2 = "OVER" Else Temp1 = 0 '単位フラグ。(0 = [mA] , 1 = [A]) Tempstr = Str(current) '現在の電流値。 If Currentrange = 0 Then 'If 電流レンジが[高レンジ]か? Then Strcurrent = Format(tempstr , " 0") '[XXXXmA]に変換する。 If Current > 999 Then 'If [1A]以上か? Then Tempstr2 = Left(tempstr , 3) Temp1 = 1 '[0.00A]表示にする。 End If Else '[低レンジ]の場合。 If Current > 999 Then 'If [10mA]以上か? Then Tempstr = Left(tempstr , 3) Strcurrent = Format(tempstr , " 0.0") '[10.0mA〜10.9mA] Else Strcurrent = Format(tempstr , "0.00") '[100uA〜9.99mA] End If End If ' If Maxdispf = 0 Then 'If 電流値は測定値表示か? Then If Temp1 = 0 Then 'If [1A]未満か? Then Lcd Strcurrent ; "mA" Else Lcd Format(tempstr2 , "0.00") ; " A" End If End If ' ' Temp1 = 0 '単位フラグ。(0 = [mA] , 1 = [A]) Tempstr = Str(maxcurrent) '電流の最大値。 If Currentrange = 0 Then 'If 電流レンジが[高レンジ]か? Then Strcurrent2 = Format(tempstr , " 0") '[XXXXmA]に変換する。 If Maxcurrent > 999 Then 'If [1A]以上か? Then Tempstr2 = Left(tempstr , 3) Temp1 = 1 '[0.00A]表示にする。 End If Else '[低レンジ]の場合。 If Maxcurrent > 999 Then 'If [10mA]以上か? Then Tempstr = Left(tempstr , 3) Strcurrent2 = Format(tempstr , " 0.0") '[10.0mA〜10.9mA] Else Strcurrent2 = Format(tempstr , "0.00") '[100uA〜9.99mA] End If End If ' If Maxdispf <> 0 Then 'If 電流値は最大値表示か? Then If Temp1 = 0 Then 'If [1A]未満か? Then Lcd Strcurrent2 ; "mA" Else Lcd Format(tempstr2 , "0.00") ; " A" End If End If End If End If ' ' * マイコン用電圧の注意表示 * ' Locate 1 , 1 Select Case Voltage Case Is < 400 : '4V未満の場合。 Lcd " " Blinkflag = 0 Case Is < 600 : '4V以上6V未満の場合。 Lcd Chr(1) Blinkflag = 0 Case Else : '6V以上の場合。 Blinkflag = 1 End Select ' ' * 500mSと1S毎の処理 * ' Time1s = Time1s + 1 Select Case Time1s Case 5 : '500mS経過。 If Blinkflag = 1 Then 'If 点滅処理が有るか? Then Locate 1 , 1 Lcd " " End If If Maxdispf <> 0 Then 'If 電流値が最大値表示か? Then Locate 2 , 1 Lcd " " End If Case 10 : '1秒経過。 Time1s = 0 If Blinkflag = 1 Then 'If 点滅処理が有るか? Then Locate 1 , 1 Lcd Chr(2) End If If Maxdispf <> 0 Then 'If 電流値が最大値表示か? Then Locate 2 , 1 Lcd "P" End If ' ' * シリアル送信 * ' Txtimecount = Txtimecount + 1 If Txtimecount >= Txtime Then 'If シリアルの送信時間か? Then Txtimecount = 0 Print #1 , Strvoltage ; " " ; Strcurrent ; " " ; Strcurrent2 'シリアル出力へ電圧と電流値を出力する。 End If End Select End If ' ' スイッチの確認 * ' Debounce Sw_1 , 0 , Sw1on , Sub 'If 電流レンジ切換スイッチが押されたか? Then Debounce Sw_2 , 0 , Sw2on , Sub 'If スイッチ[2]が押されたか? Then Debounce Sw_3 , 0 , Sw3on , Sub 'If スイッチ[3]が押されたか? Then ' Temp1 = Sw_2 Or Sw_3 If Temp1 = 0 Then Gosub Opsetsub 'If 機能設定モードか? Then Goto Main ' ' * 電流レンジ切換スイッチ * ' Sw1on: Toggle Currentrange.0 Gosub Currangeset '電流レンジの表示とリレーの設定。 Maxdispf = 0 '電流の最大値表示フラグをクリアする。 Maxcurrent = 0 '電流の最大値を初期化する。 Return ' ' * スイッチ[2] 電流の最大値表示 * ' Sw2on: Toggle Maxdispf.0 If Maxdispf = 0 Then 'If 電流値は測定値表示か? Then Gosub Currangeset '電流レンジの表示とリレーの設定。 Else '電流の最大値表示の場合。 Locate 2 , 1 Lcd "P" End If Return ' ' * スイッチ[3] 電流の最大値を初期化 * ' Sw3on: Maxcurrent = 0 Return ' ' ********************************** ' * 電流レンジの表示とリレーの設定 * ' ********************************** ' Currangeset: Locate 2 , 1 If Currentrange = 0 Then 'If 電流レンジが[高レンジ]か? Then Reset Rl_range '電流レンジ切換リレーを[OFF]にする。 Lcd "H" Else Set Rl_range '電流レンジ切換リレーを[ON]にする。 Lcd "L" End If Return ' ' ************************* ' * AVR内部基準電圧の校正 * ' ************************* ' Refset: Cls Lcd "Ref.Volt" Locate 2 , 8 Lcd "V" ' Waitms 30 'チャタリングの待ち時間。 Bitwait Sw_2 , Set 'スイッチ[2]が離されるまで待つ。 Bitwait Sw_3 , Set 'スイッチ[3]が離されるまで待つ。 Waitms 30 'チャタリングの待ち時間。 Lcdcmd &B0000_1111 'LCDのカーソルをオン・点滅にする ' Refset4: Locate 2 , 2 Tempstr = Str(refvolt) Lcd Format(tempstr , "0.000") ' Refset5: Debounce Sw_1 , 0 , Refset1 'If スイッチ[1]が押されたか? Then Debounce Sw_2 , 0 , Refset2 'If スイッチ[2]が押されたか? Then Debounce Sw_3 , 0 , Refset3 'If スイッチ[3]が押されたか? Then Goto Refset5 ' ' Refset1: Eeprefvolt = Refvolt Waitms 30 'チャタリングの待ち時間。 Bitwait Sw_1 , Set 'スイッチ[1]が離されるまで待つ。 Waitms 30 'チャタリングの待ち時間。 Goto 0 ' Refset2: If Refvolt < 2800 Then 'If 上限ではないか? Then Refvolt = Refvolt + 1 End If Goto Refset4 ' Refset3: If Refvolt > 2300 Then 'If 下限ではないか? Then Refvolt = Refvolt - 1 End If Goto Refset4 ' ' ************************* ' * AVR内ぞう発振器の校正 * (PB0から100KHzを出力) ' ************************* ' Oscset: Cls Lcd "OSC Cali" ' Waitms 30 'チャタリングの待ち時間。 Bitwait Sw_2 , Set 'スイッチ[2]が離されるまで待つ。 Bitwait Sw_3 , Set 'スイッチ[3]が離されるまで待つ。 Waitms 30 'チャタリングの待ち時間。 Lcdcmd &B0000_1111 'LCDのカーソルをオン・点滅にする。 ' Tccr1d = &B0000_0000 'Config Timer1 = Timer (標準動作) Tccr1b = &B0000_0001 'Prescale = 1 (8,000,000Hz / 1 = 8,000,000Hz) Tccr1a = &B0000_0000 Tccr1c = &B0000_0000 Tc1h = &H00 Ocr1c = 40 - 1 '8,000,000Hz / 40カウント = 200,000Hz On Timer1 Tintovf Nosave 'オーバーフロー割り込みルーチンのラベルを設定。 Enable Timer1 'オーバーフロー割り込みを許可。 Enable Interrupts 'すべての割り込みを許可。 Temp1 = Eeposccal ' Oscset4: Locate 2 , 5 Tempstr = Str(temp1) Lcd Format(tempstr , " 0") Osccal = Temp1 ' Oscset5: Debounce Sw_1 , 0 , Oscset1 'If スイッチ[1]が押されたか? Then Debounce Sw_2 , 0 , Oscset2 'If スイッチ[2]が押されたか? Then Debounce Sw_3 , 0 , Oscset3 'If スイッチ[3]が押されたか? Then Goto Oscset5 ' ' Oscset1: Disable Timer1 'オーバーフロー割り込みを禁止。 Disable Interrupts 'すべての割り込みを禁止。 Eeposccal = Temp1 Waitms 30 'チャタリングの待ち時間。 Bitwait Sw_1 , Set 'スイッチ[1]が離されるまで待つ。 Waitms 30 'チャタリングの待ち時間。 Goto 0 ' Oscset2: If Temp1 <> 255 Then 'If 上限ではないか? Then Temp1 = Temp1 + 1 End If Goto Oscset4 ' Oscset3: If Temp1 <> 0 Then 'If 下限ではないか? Then Temp1 = Temp1 - 1 End If Goto Oscset4 ' ' * Timer1 オーバーフロー割り込み * ' Tintovf: $asm SBI PINB,0 '[PB0]を反転する。 $end Asm Return ' ' **************** ' * 機能設定処理 * ' **************** ' Opsetsub: Cls '[シリアル送信間隔]の設定。 Lcd "TxInterv" ' Waitms 30 'チャタリングの待ち時間。 Bitwait Sw_2 , Set 'スイッチ[2]が離されるまで待つ。 Bitwait Sw_3 , Set 'スイッチ[3]が離されるまで待つ。 Waitms 30 'チャタリングの待ち時間。 Lcdcmd &B0000_1111 'LCDのカーソルをオン・点滅にする。 ' Txiset4: Tempstr = Lookupstr(txinterval , Txtimechr) '送信間隔の文字列を読み込む。 Locate 2 , 2 Lcd Tempstr ' Txiset5: Debounce Sw_1 , 0 , Txiset1 'If スイッチ[1]が押されたか? Then Debounce Sw_2 , 0 , Txiset2 'If スイッチ[2]が押されたか? Then Debounce Sw_3 , 0 , Txiset3 'If スイッチ[3]が押されたか? Then Goto Txiset5 ' ' Txiset2: Txinterval = Txinterval + 1 If Txinterval > 4 Then 'If 上限か? Then Txinterval = 0 End If Goto Txiset4 ' Txiset3: Txinterval = Txinterval - 1 If Txinterval = 255 Then 'If 下限か? Then Txinterval = 4 End If Goto Txiset4 ' Txiset1: Eeptxinterval = Txinterval Txtime = Lookup(txinterval , Txtimetable) '送信間隔の設定時間を読み込む。 Txtimecount = 0 '送信間隔のカウンターを初期化する。 Lcdcmd &B0000_1100 'LCDのカーソルをオフ・点滅なしにする。 Waitms 30 'チャタリングの待ち時間。 Bitwait Sw_1 , Set 'スイッチ[1]が離されるまで待つ。 Waitms 30 'チャタリングの待ち時間。 Maxdispf = 0 '電流の最大値表示フラグをクリアする。 Maxcurrent = 0 '電流の最大値を初期化する。 Cls Gosub Currangeset '電流レンジの表示とリレーの設定。 Return ' ' End ' ' * 送信間隔のテーブル * ' Txtimetable: Data 1% , 10% , 60% , 600% , 3600% ' Txtimechr: Data " 1 Sec" , "10 Sec" , " 1 Min" , "10 Min" , "60 Min"