$prog &HFF , &HE2 , &HDF , &HFF 'ヒューズ設定。 CKDIV8 = 1 ' ' **************************************************** ' * A1324LUA-T 磁束密度計(ガウスメータ) プログラム * ' * (Ver. 1.01) * ' * * ' * AVR is using ATtiny85-20PU * ' * Basic Compiler is BASCOM-AVR * ' * Copyright By O-Family 2014. 6. 6 * ' **************************************************** ' ' Ver 0.01 テスト・バージョン。 2014. 5.24 ' Ver 1.01 初回公開バージョン。 2014. 6. 6 ' ' Const Prgver = " 1.01" 'プログラム・バージョン。 ' ' $regfile = "ATtiny85.DAT" '使用するAVRを設定。 $crystal = 8000000 'AVRクロックを設定。 ' $hwstack = 64 'ハードウェア・スタックの容量を設定。 $swstack = 10 'ソフトウェア・スタックの容量を設定。 $framesize = 24 'フレーム領域の容量を設定。 ' ' * ポート名の定義 * ' Sw_1 Alias Pinb.2 'スイッチ[1]の接続ポート。 Sw_1pu Alias Portb.2 'スイッチ[1]の接続ポート(プルアップ用)。 Lcd_power Alias Portb.3 'LCDの電源接続ポート。 Ad_a1324 Alias 2 'A1324のA/Dコンバータのチャネル番号。 ' ' * 変数の宣言 * ' Dim Magdensity As Word '磁束密度値。 Dim Offset As Integer 'センサーのオフセット誤差値。 Dim Polarity As Byte '磁場の極性。(0:磁束密度[0G] , 1:[S極] , 2:[N極] , 3:[AC交流]) Dim Magunit As Byte '磁束密度の単位。(0:G , 1:mT) Dim Tempmagden As Word '磁束密度の保管値。 Dim Average(32) As Word '移動平均用バッファー。 Dim Avgpoi As Byte '移動平均のポインター。 Dim Avgsum As Word '移動平均の合計値。 Dim Magpeak As Word '磁束密度のピーク値。 Dim Lcdcount As Byte 'LCDの数値表示時間間隔カウンター。 Dim Dispcycle As Byte '磁束密度値の表示周期。(5〜10)(x100mS) Dim Dispmode As Byte 'LCDの表示モード。(0:バーグラフ , 1:ピーク値) ' Dim Swoffchf As Byte 'スイッチOFFチェックフラグ。 Dim Sw100mscun As Byte 'SW用100mS経過カウンター。 Dim Pw100mscun As Byte '電源用100mS経過カウンター。 Dim Atptime As Byte '自動電源OFFの設定時間。(x10秒) Dim Atpowcun As Byte '自動電源OFFカウンター。(x10秒) ' Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Temp2 As Byte '汎用テンポラリ変数 Byte型 No.2 Dim Temp3 As Byte '汎用テンポラリ変数 Byte型 No.3 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型 No.1 ' Dim Dummy As Eram Long 'EEPROM 4バイトのダミーエリア。 Dim Eepmagunit As Eram Byte 'EEPROM 磁束密度の単位。(0:G , 1:mT) Dim Eepcontrast As Eram Byte 'EEPROM LCDのコントラスト値。(1〜20) Dim Eepatptime As Eram Byte 'EEPROM 自動電源OFFの設定時間。(0 , 1〜10 分) Dim Eepdispcycle As Eram Byte 'EEPROM 磁束密度値の表示周期。(5〜10)(x100mS) ' ' * A/Dコンバータの初期設定 * ' Config Adc = Single , Prescaler = Auto , Reference = Avcc 'A/Dコンバータの設定。 Start Adc 'A/Dコンバータに電源を供給。 Config Aci = Off 'アナログ比較器の電源を切る。 ' ' * ハードウェアの初期設定 * ' Didr0 = &B0001_0000 'デジタル入力禁止レジスタの設定。(ADC2) Prr = &B0000_0110 '未使用回路の電力削減。(Timer0 , USI) Set Sw_1pu 'スイッチ[1]の接続ポートをプルアップする。 Config Lcd_power = Output 'LCDとセンサーの電源接続ポートを出力に設定する。 Waitms 500 'AVR起動の安定待ち時間。 Set Lcd_power 'LCDとセンサーの電源をONにする。 Waitms 100 'LCDの起動待ち時間。 ' Config Scl = Portb.1 'I2CバスのSCLラインを接続するポートピンを設定。 Config Sda = Portb.0 'I2CバスのSDAラインを接続するポートピンを設定。 I2cinit 'I2Cバスを初期化する。 ' Const Aqm0802a_vdd = 5 '[AQM0802A]の電源電圧。(3.5V以下 = 3 , 3.5V以上 = 5) $lib "Lcd_AQM0802A.lib" 'I2C-LCD [AQM0802A]用のライブラリ。 Gosub Lcdiniset 'LCDを初期化してカスタム文字を書き込む。 ' Pcmsk = &B0000_0100 'スイッチ[1]のピン変化割り込みを許可する。 On Pcint0 Intsw1 'スイッチ[1]のピン変化割り込みルーチンを設定。 ' ' * Timerの設定 * ' Config Timer1 = Timer , Prescale = 4096 'Timer0の設定。8,000,000Hz / 4,096 = 1953.125Hz Set Tccr1.pwm1a 'Timer1 = PWM Ocr1c = 195 - 1 '1953Hz / 10Hz(100mS) = 約195カウント ' ' * EEPROMのデータを確認する * ' If Eepmagunit > 1 Then 'If EEPROMが初期値か? Then Eepmagunit = 0 'EEPROM 磁束密度の単位。(0:G , 1:mT) Eepcontrast = 20 'EEPROM LCDのコントラスト値。(1〜20) Eepatptime = 1 'EEPROM 自動電源OFFの設定時間。(0 , 1〜10 分) Eepdispcycle = 5 'EEPROM 磁束密度値の表示周期。(5〜10)(x100mS) End If Magunit = Eepmagunit '磁束密度の単位。(0:G , 1:mT) _temp1 = Eepcontrast 'LCDのコントラスト値。(1〜20) !CALL _LCD_CONTRAST 'コントラスト設定ルーチン。 Temp1 = Eepatptime '自動電源OFFの設定時間。(0 , 1〜10 分) Atptime = Temp1 * 6 '10秒単位に換算する。 Dispcycle = Eepdispcycle '磁束密度値の表示周期。(5〜10)(x100mS) ' ' * 機能設定モードの確認 * ' If Sw_1 = 0 Then Goto Setmode 'If 機能設定モードか? Then ' ' * センサーのオフセット誤差を検出する * ' Avgsum = 0 For Temp1 = 1 To 32 Tempw1 = Getadc(ad_a1324) 'A1324LUA-Tの出力をA/D変換する。 Average(temp1) = Tempw1 Avgsum = Avgsum + Tempw1 Next Temp1 ' Tempw1 = Avgsum Shift Tempw1 , Right , 5 '32個の平均を取る。 Offset = Tempw1 - 512 'オフセット誤差値を計算する。 Shift Avgsum , Right , 2 '8個の合計値にする。(メインプログラムでは8個の移動平均) ' ' * 変数を初期化する * ' Polarity = 0 '磁場の極性を[0G]にする。 Magdensity = 0 '磁束密度を初期化する。 Avgpoi = 1 '移動平均のポインターを初期化する。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: Gosub Magdenmeasure '磁束密度を測定する。 Gosub Swcheck 'スイッチ入力処理。 Gosub Atpower '電源の自動管理処理。 Goto Main ' ' ********************** ' * 磁束密度を測定する * ' ********************** ' Magdenmeasure: Tempw1 = Getadc(ad_a1324) 'A1324LUA-Tの出力をA/D変換する。 ' ' * 磁束密度値の移動平均を行う * ' Avgsum = Avgsum - Average(avgpoi) '一番古いデータを減算する。 Average(avgpoi) = Tempw1 '移動平均バッファーに格納する。 Avgsum = Avgsum + Tempw1 '新しいデータを合算する。 ' Avgpoi = Avgpoi + 1 '移動平均ポインターを更新する。 If Avgpoi > 8 Then 'If ポインターが上限か? Then Avgpoi = 1 End If ' Tempi1 = Avgsum Shift Tempi1 , Right , 3 '8個の移動平均を取る。 Tempi1 = Tempi1 - Offset 'センサーのオフセット誤差を相殺する。 ' ' * 磁場の極性を調べる * ' Tempi1 = Tempi1 - 512 'センサーの静止電圧からの差分を求める。 Select Case Tempi1 '磁場の極性による判別。 Case Is > 1 : '磁場が[S極]方向の場合。 Select Case Polarity Case 0 : Polarity = 1 '極性を[S極]にする。 Case 2: Polarity = 3 '極性を[AC交流]にする。 End Select ' Case Is < -1 : '磁場が[N極]方向の場合。 Tempi1 = Abs(tempi1) '絶対値を求める。 Select Case Polarity Case 0 : Polarity = 2 '極性を[N極]にする。 Case 1: Polarity = 3 '極性を[AC交流]にする。 End Select ' Case Else : '磁束がない場合。 Tempi1 = 0 '±1G以内を0Gに丸める。 End Select ' ' * 磁束密度を計算する * ' Templ1 = 1000 * Tempi1 ' (5V÷5mV)÷1024×[A/D値] Shift Templ1 , Right , 10 '式を変えて (5V÷5mV)×[A/D値]÷1024 Tempw1 = Templ1 'Word変数に変換する。 ' ' * 磁束密度の最大値を求める * ' If Magdensity < Tempw1 Then 'If 100mS間の最大値を超えたか? Then Magdensity = Tempw1 End If ' ' * LCDへの表示 * ' If Tifr.tov1 = 1 Then 'If 100m経過したか? Then Set Tifr.tov1 'Timer1 オーバーフロー・フラグをクリアする。 Sw100mscun = Sw100mscun + 1 'SW用100mS経過カウンターを更新する。 Pw100mscun = Pw100mscun + 1 '電源用100mS経過カウンターを更新する。 ' ' * 極性の表示 * ' Locate 1 , 1 Select Case Polarity Case 1 : Lcd "S" '[S極]の場合。 Case 2 : Lcd "N" '[N極]の場合。 Case 3 : Lcd "A" '[AC交流]の場合。 Case Else : Lcd " " '[0G]の場合。 End Select ' ' * LCD下段の表示 (バーグラフ/ピーク値) * ' If Dispmode = 0 Then 'If LCDの表示モードが[バーグラフ]か? Then Locate 2 , 1 If Polarity = 0 Then 'If [0G]か? Then Lcd Chr(0) ; Spc(7) 'バーグラフをすべて消す。 ' Else '[0G]ではない場合。 Tempw1 = Magdensity If Tempw1 > 399 Then 'If バーグラフの上限を超えているか? Then Tempw1 = 399 End If ' Tempw1 = Tempw1 / 10 'バーグラフのドット数を求める。(1dot=10G , 0〜40dot) Temp1 = Tempw1 'Byte変数に変換する。 Temp2 = Temp1 / 5 '塗りつぶしキャラクターの数を求める。(0〜8) Temp3 = Temp2 * 5 Temp1 = Temp1 + 1 Temp3 = Temp1 - Temp3 '塗りつぶし後の端数のドット数を求める。(0〜4) ' Temp1 = 1 '塗りつぶしパターンの処理。 While Temp2 <> 0 'If 塗りつぶしが有るか? Then Locate 2 , Temp1 Lcd Chr(5) ; '塗りつぶしのパターン。 Temp1 = Temp1 + 1 'カーソル位置を1つ進める。 Temp2 = Temp2 - 1 Wend ' Locate 2 , Temp1 '端数のドットを表示する。 Lcd Chr(temp3) ' Temp1 = Temp1 + 1 '残りスペースを消去する。 Temp2 = 9 - Temp1 If Temp2 <> 0 Then 'If 残りスペースが有るか? Then Locate 2 , Temp1 Lcd Spc(temp2) End If End If Else 'If LCDの表示モードが[ピーク値]の場合。 If Magpeak < Magdensity Then 'If ピーク値を超えたか? Then Magpeak = Magdensity End If End If ' ' * 磁束密度値の表示 * ' Tempi1 = Tempmagden - Magdensity '前回の値との差分を求める。 Tempw1 = Abs(tempi1) Tempmagden = Magdensity If Tempw1 > 20 Then '前回の測定値と±20G以上の差があるか? Thn Lcdcount = 0 'LCDの数値表示時間間隔カウンターをクリアする。 Atpowcun = 0 '自動電源OFFカウンターをクリアする。 Pw100mscun = 0 '電源用100mS経過カウンターをリセットする。 Temp1 = 1 '表示を更新する。 Else '前回との差が±20G以内の場合。 Lcdcount = Lcdcount + 1 If Lcdcount >= Dispcycle Then 'If 磁束密度値の表示周期か? Then Lcdcount = 0 'LCDの数値表示時間間隔カウンターをクリアする。 Temp1 = 1 '表示を更新する。 Else Temp1 = 0 '表示を更新しない。 End If End If ' If Temp1 = 1 Then 'If 磁束密度値の表示を更新するか? Then Locate 1 , 3 'LCDに磁束密度値を表示する。 If Magdensity > 420 Then 'If 磁束密度の上限値を超えたか? Then Lcd "-Over-" Else Tempstr = Str(magdensity) '数値変数を文字変数に変換する。 If Magunit = 0 Then 'If 磁束密度の単位が[ガウス]か? Then Lcd Format(tempstr , " 0") ; " G" 'ガウス表示。 Else Lcd Format(tempstr , " 0.0") ; "mT" 'テスラ表示。 End If End If ' If Dispmode <> 0 Then 'If LCDの表示モードが[ピーク値]か? Then Locate 2 , 3 'LCDに磁束密度値を表示する。 If Magpeak > 420 Then 'If 磁束密度の上限値を超えたか? Then Lcd "-Over-" Else Tempstr = Str(magpeak) '数値変数を文字変数に変換する。 If Magunit = 0 Then 'If 磁束密度の単位が[ガウス]か? Then Lcd Format(tempstr , " 0") ; " G" 'ガウス表示。 Else Lcd Format(tempstr , " 0.0") ; "mT" 'テスラ表示。 End If End If End If End If ' Polarity = 0 '極性を[0G]にする。 Magdensity = 0 '磁束密度を初期化する。 End If Return ' ' ******************** ' * スイッチ入力処理 * ' ******************** ' Swcheck: If Swoffchf <> 0 Then Goto Swoffchk 'If スイッチのOFF確認中か? Then If Sw_1 = 0 Then Goto Sw1on 'If [SW1]が押されたか? Then Return ' ' * [SW1]が押された場合 * ' Sw1on: Waitms 30 'チャタリング除去の待ち時間。 If Dispmode = 0 Then 'If LCDの表示モードが[バーグラフ]か? Then Dispmode = 1 '[ピーク値]に変更する。 Magpeak = 0 Locate 2 , 1 Lcd "P" ; Spc(7) Else Dispmode = 0 '[バーグラフ]に変更する。 End If ' Swoffchf = 1 'スイッチが離されるのを待つ。 Sw100mscun = 0 'SW用100mS経過カウンターをリセットする。 Atpowcun = 0 '自動電源OFFカウンターをクリアする。 Pw100mscun = 0 '電源用100mS経過カウンターをリセットする。 Return ' ' * スイッチが離されるのを待つ * ' Swoffchk: If Sw_1 = 1 Then 'If [SW1]が離されたか? Then Waitms 30 'チャタリング除去の待ち時間。 Swoffchf = 0 ' Else '[SW1]が長押しの場合。 If Swoffchf = 1 Then 'If スイッチの長押し計測中か? Then If Sw100mscun >= 10 Then 'If 1秒経過したか? Then Swoffchf = 2 '長押し後のスイッチが離されるのを待つ。 Toggle Magunit.0 '磁束密度の単位を変更する。(0:G , 1:mT) Eepmagunit = Magunit 'EEPROMに保管する。 Waitms 10 'EEPROM書き込みノイズの待ち時間。(tWD_EEPROM 最低4.0ms) Lcdcount = 250 '磁束密度値を強制表示させる。 End If End If End If Atpowcun = 0 '自動電源OFFカウンターをクリアする。 Pw100mscun = 0 '電源用100mS経過カウンターをリセットする。 Return ' ' ********************** ' * 電源の自動管理処理 * ' ********************** ' Atpower: If Atptime <> 0 Then 'If 自動電源OFFが有りか? Then If Pw100mscun >= 100 Then 'If 10秒経過したか? Then Pw100mscun = 0 Atpowcun = Atpowcun + 1 '自動電源OFFカウンターを更新する。 If Atpowcun = Atptime Then 'If 自動電源OFF時間か? Then Reset Lcd_power 'LCDとA1324の電源をOFFにする。 Stop Adc 'A/Dコンバータの電源を切る。 Config Portb.0 = Output 'I2C接続ポートを[L]にする。 Reset Portb.0 Config Portb.1 = Output Reset Portb.1 Reset Gifr.pcif 'ピン変化割り込みフラグをリセットする。 Enable Pcint0 'ピン変化割り込みを許可する。 Enable Interrupts 'すべての割り込みを許可する。 ' Power Powerdown 'AVRをパワーダウン・モードに移行する。([SW1]で再起動する) ' Disable Interrupts 'すべての割り込みを禁止する。 Waitms 30 'チャタリング除去の待ち時間。 Bitwait Sw_1 , Set '[SW1]が離されるまで待つ。 Waitms 30 'チャタリング除去の待ち時間。 Goto _reset 'AVRの再起動。 ' End If End If End If Return ' ' ***************************************** ' * LCDを初期化してカスタム文字を書き込む * ' ***************************************** ' Lcdiniset: Initlcd 'LCDを初期化する。 ' Deflcdchar 0 , &H00 , &H00 , &H00 , &H00 , &H00 , &H10 , &H10 , &H10 'バーグラフ用のカスタム文字をLCDへ書き込む。 Deflcdchar 1 , &H00 , &H00 , &H00 , &H10 , &H10 , &H10 , &H10 , &H10 Deflcdchar 2 , &H00 , &H00 , &H00 , &H18 , &H18 , &H18 , &H18 , &H18 Deflcdchar 3 , &H00 , &H00 , &H00 , &H1C , &H1C , &H1C , &H1C , &H1C Deflcdchar 4 , &H00 , &H00 , &H00 , &H1E , &H1E , &H1E , &H1E , &H1E Deflcdchar 5 , &H00 , &H00 , &H00 , &H1F , &H1F , &H1F , &H1F , &H1F Return ' ' ****************** ' * 機能設定モード * ' ****************** ' Setmode: Locate 1 , 1 'プログラム・バージョンの表示。 Lcd "Ver" ; Prgver Temp1 = 0 ' Setmode1: Locate 2 , 1 Select Case Temp1 Case 0 : Lcd "Contrast" Case 1 : Lcd "AutPower" Case Else : Lcd "DispCycl" End Select Temp2 = 0 ' Setmode2: If Sw_1 = 1 Then Goto Setmode3 'If [SW1]が放されたか? Then If Tifr.tov1 = 0 Then Goto Setmode2 'If 100m経過していないか? Then Set Tifr.tov1 'Timer1 オーバーフロー・フラグをクリアする。 Temp2 = Temp2 + 1 If Temp2 < 30 Then Goto Setmode2 'If 3秒経過していないか? Then Temp1 = Temp1 + 1 '表示項目を変更する。 If Temp1 > 2 Then Temp1 = 0 End If Goto Setmode1 ' ' Setmode3: '[SW1]が放された場合。 Cls 'LCD表示をすべて消去。 If Temp1 = 1 Then Goto Atpowerset 'If 自動電源OFF時間の設定か? Then If Temp1 = 2 Then Goto Dispcycleset 'If 磁束密度値の表示周期の設定か? Then ' ' ******************************* ' * LCDのコントラスト設定モード * ' ******************************* ' Contrastset: Locate 1 , 1 'タイトルを表示する。 Lcd "Contrast" Locate 2 , 1 Lcd "set:" Cursor On Blink 'LCDのカーソルを表示する。 ' Contrastset1: _temp1 = Eepcontrast 'LCDのコントラスト値。(1〜20) !CALL _LCD_CONTRAST 'コントラスト設定ルーチン。 Temp2 = Eepcontrast Locate 2 , 6 '現在の設定値を表示する。 Tempstr = Str(temp2) Lcd Format(tempstr , " 0") Locate 2 , 8 Waitms 30 'チャタリング除去の待ち時間。 Bitwait Sw_1 , Set '[SW1]が離されるまで待つ。 Waitms 30 'チャタリング除去の待ち時間。 ' Contrastset2: If Sw_1 = 0 Then Goto Contrastset3 'If [SW1]が押されたか? Then Goto Contrastset2 ' ' Contrastset3: '[SW1]が押された場合。 Temp2 = Temp2 + 1 If Temp2 > 20 Then 'If 設定値の上限か? Then Temp2 = 1 End If Eepcontrast = Temp2 'EEPROMに格納する。 Goto Contrastset1 ' ' ******************************* ' * 自動電源OFF時間の設定モード * ' ******************************* ' Atpowerset: Locate 1 , 1 'タイトルを表示する。 Lcd "AutPower" Locate 2 , 1 Lcd "OFF:" Cursor On Blink 'LCDのカーソルを表示する。 ' Atpowerset1: Temp2 = Eepatptime Locate 2 , 6 '現在の設定値を表示する。 Tempstr = Str(temp2) Lcd Format(tempstr , " 0") Locate 2 , 8 Waitms 30 'チャタリング除去の待ち時間。 Bitwait Sw_1 , Set '[SW1]が離されるまで待つ。 Waitms 30 'チャタリング除去の待ち時間。 ' Atpowerset2: If Sw_1 = 0 Then Goto Atpowerset3 'If [SW1]が押されたか? Then Goto Atpowerset2 ' ' Atpowerset3: '[SW1]が押された場合。 Temp2 = Temp2 + 1 If Temp2 > 10 Then 'If 設定値の上限か? Then Temp2 = 0 End If Eepatptime = Temp2 'EEPROMに格納する。 Goto Atpowerset1 ' ' *********************************** ' * 磁束密度値の表示周期 設定モード * ' *********************************** ' Dispcycleset: Locate 1 , 1 'タイトルを表示する。 Lcd "DispCycl" Locate 2 , 4 Lcd "00mS" Cursor On Blink 'LCDのカーソルを表示する。 ' Dispcycleset1: Temp2 = Eepdispcycle Locate 2 , 2 '現在の設定値を表示する。 Tempstr = Str(temp2) Lcd Format(tempstr , " 0") Locate 2 , 8 Waitms 30 'チャタリング除去の待ち時間。 Bitwait Sw_1 , Set '[SW1]が離されるまで待つ。 Waitms 30 'チャタリング除去の待ち時間。 ' Dispcycleset2: If Sw_1 = 0 Then Goto Dispcycleset3 'If [SW1]が押されたか? Then Goto Dispcycleset2 ' ' Dispcycleset3: '[SW1]が押された場合。 Temp2 = Temp2 + 1 If Temp2 > 10 Then 'If 設定値の上限か? Then Temp2 = 5 End If Eepdispcycle = Temp2 'EEPROMに格納する。 Goto Dispcycleset1 ' ' ************************************ ' * スイッチ入力割り込み処理ルーチン * ' ************************************ ' Intsw1: Return '何も処理しない。 ' ' End