$programmer = 22 'ARDUINO (using stk500v1 protocol) ' ' ************************************* ' * Arduino LCD Keypad Shield * ' * 初期設定 Ver. 0.01 * ' * * ' * AVR is ATmega328P * ' * Basic Compiler is BASCOM-AVR * ' * Copyright O-Family 2018. 9.18 * ' ************************************* ' $regfile = "m328pdef.dat" '使用するAVRを設定。 $crystal = 16000000 'AVRクロックを設定。 ' $hwstack = 64 'ハードウェア・スタックの容量を設定。 $swstack = 10 'ソフトウェア・スタックの容量を設定。 $framesize = 24 'フレーム領域の容量を設定。 ' ' * ポート名の定義 * ' Lcd_bkl Alias Portb.2 'LCDのバックライト制御の接続ポート。 ' ' * 変数の宣言 * ' Dim Keydata As Byte 'キー(スイッチ)の入力データ。(押された場合にコードが入る) Dim Keyadcode As Byte 'キー(スイッチ)をA/D変換したコード。(押されている状態のコードが入る) Dim Keystat As Byte , Keyw1 As Word 'キー(スイッチ)の検出状態フラグ。内部で使用する変数。 ' ' * ポートの初期設定 * ' Config Lcd_bkl = Output 'LCDのバックライト制御の接続ポートを出力に設定する。 Set Lcd_bkl 'LCDのバックライトを点灯する。 ' ' * LCDの初期設定 * ' Config Lcdmode = Port 'LCDを4ビットのポートモードに設定。 Config Lcdbus = 4 'LCDデータバスを4bitに設定。 Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 'LCDのポート割り当て。 Config Lcdpin = Pin , Db6 = Portd.6 , Db7 = Portd.7 Config Lcdpin = Pin , E = Portb.1 , Rs = Portb.0 Config Lcd = 16 * 2 'LCD表示を16文字2行に設定。 Cls 'LCD表示をすべて消去。 ' ' * A/Dコンバータの初期設定 * ' Config Adc = Single , Prescaler = Auto , Reference = Avcc 'A/Dコンバータの設定。 Start Adc 'A/Dコンバータに電源を供給する。 Didr0 = &B0011_1111 'デジタル入力禁止レジスタの設定。(アナログ入力ピンをデジタル入力禁止にする) ' ' * シリアルポートの設定 * ' Config Com1 = 9600 , Parity = None , Stopbits = 1 , Databits = 8 'ハードウェアUARTの設定。 '-------------------------------------------------------------------------------------------------- ' ' ****************************************** ' * HX711 (24bit A/Dコンバータ) + * ' * ロードセル 20kg [SC133-20kg] 重量計 * ' * Arduino LCD Keypad Shield 版 * ' * Copyright O-Family 2018. 9.28 * ' ****************************************** ' ' Ver A0.01 初回公開バージョン。 2018. 9.28 ' Ver A2.01 20Kgの[SC133]用に変更。 2021.11.25 Const Prgver = "A2.01" 'プログラム・バージョン。 ' ' * ポート名の定義 * ' Hx711_clk Alias Portd.2 'HX711の[PD_SCK]ピンの接続ポート。 Hx711_dat Alias Pind.3 'HX711の[DOUT]ピンの接続ポート。 ' ' * 変数の宣言 * ' Dim Hx711ad As Long 'HX711から取り出した生のA/Dデータ。 Dim Hx711avg As Long 'HX711のA/D値を移動平均した値。 Dim Hx711count As Byte 'HX711のA/Dデータ取り出しカウンター。 Dim Average(16) As Long '移動平均用バッファー。 Dim Avgpoi As Byte '移動平均のポインター。 Dim Avgsum As Long '移動平均の合計値。 Dim Zeroadj As Long 'ゼロ調整の差分値。 Dim Stablecount As Byte '安定マーク表示までのカウント数。 Dim Lastvalue As Long '前回の測定値。 Dim Sensorcal As Long 'ロードセル・センサーからグラム換算する校正値。 ' Dim Temp1 As Byte '汎用テンポラリ変数 Byte型 No.1 Dim Temp2 As Byte '汎用テンポラリ変数 Byte型 No.2 Dim Templ1 As Long '汎用テンポラリ変数 Long型 No.1 Dim Tempstr As String * 40 '汎用テンポラリ変数 String型 ' Dim Dummy As Eram Long 'EEPROM 4バイトのダミーエリア。 Dim Eepprgid As Eram Long 'EEPROM プログラムのID。 Dim Eepsensorcal As Eram Long 'EEPROM ロードセル・センサーからグラム換算する校正値。 ' ' * ポートの初期設定 * ' Config Hx711_clk = Output 'HX711の[PD_SCK]ピンの接続ポートを出力に設定する。 Reset Hx711_clk 'HX711の[PD_SCK]ピンを[L]にする。(通常動作モードにする) Config Hx711_dat = Input 'HX711の[DOUT]ピンの接続ポートを入力に設定する。 ' ' * EEPROMのデータを確認する * ' If Eepprgid <> &H32375848 Then 'If EEPROMが初期値か? Then Eepprgid = &H32375848 'EEPROM プログラムのID。[HX72] Eepsensorcal = 10737 'EEPROM ロードセル・センサーからグラム換算する校正値。 End If Sensorcal = Eepsensorcal ' ' * 20回の測定を行い、ゼロ調整用の差分を用意する * ' Cursor Off 'LCDのカーソルをオフにする。 Avgpoi = 1 '移動平均のポインターを初期化する。 Locate 1 , 1 'ゼロ調整中の表示。 Lcd "Zero Adjustment" ' For Temp1 = 1 To 20 '20回の測定を行い移動平均する。 Do Loop Until Hx711_dat = 0 'HX711の[DOUT]ピンが[L]になった(変換終了)か? ' Gosub Hx711get 'HX711のチャンネルAから128の利得でA/Dデータを取り出す。 Gosub Hx711movavg 'HX711のA/D変換データを移動平均する。 Locate 2 , 1 Lcd Hex(hx711avg) 'A/Dの平均値をLCDに表示する。 Next Temp1 ' Zeroadj = 0 - Hx711avg '現在の測定値からゼロ調整の差分を計算する。 Stablecount = 0 '安定マークの表示カウント数を初期化する。 Lastvalue = 0 '前回の測定値を初期化する。 Cls 'LCD表示をすべて消去する。 Temp2 = 0 'シリアル・ターミナルへの送信時間タイマー。 ' ' ******************* ' * メイン ルーチン * ' ******************* ' Main: ' ' * 重量の測定 * ' If Hx711_dat = 0 Then 'If HX711の[DOUT]ピンが[L]になった(変換終了)か? Then Gosub Hx711get 'HX711のチャンネルAから128の利得でA/Dデータを取り出す。 Locate 1 , 1 Lcd Hex(hx711ad) 'HX711の生のA/D値をLCDに表示する。 ' Gosub Hx711movavg 'HX711のA/D変換データを移動平均する。 Locate 2 , 1 Lcd Hex(hx711avg) 'A/Dの平均値をLCDに表示する。 ' Templ1 = Hx711avg + Zeroadj 'ゼロ調整の差分を計算する。 ' Templ1 = Templ1 * 100 'グラム換算の小数点桁上げのために100倍する。 Templ1 = Templ1 / Sensorcal 'ロードセル・センサーのA/D値からグラム換算する。 ' Temp2 = Temp2 + 1 '100mSタイマーを加算する。 If Temp2 > 10 Then 'If 1秒経過したか? Then Temp2 = 0 End If ' Locate 2 , 10 Tempstr = Str(templ1) '数値変数を文字変数に変換する。 If Templ1 < 0 Then 'If 表示値がマイナスか? Then Lcd Format(tempstr , " 0") ; "g" 'マイナスの重量をLCDに表示する。 If Temp2 = 0 Then 'If 1秒経過したか? Then Print Format(tempstr , " 0") ; "g" 'マイナスの重量をターミナルに表示する。 End If Else 'プラスの場合。 Lcd Format(tempstr , " 0") ; "g" 'プラスの重量をLCDに表示する。 If Temp2 = 0 Then 'If 1秒経過したか? Then Print Format(tempstr , " 0") ; "g" 'プラスの重量をターミナルに表示する。 End If End If ' ' * 安定マーク[*]の表示 * ' Locate 1 , 10 If Templ1 = Lastvalue Then 'If 前回の測定値との差が無いか? Then Stablecount = Stablecount + 1 '安定マーク表示までのカウント数を加算する。 If Stablecount > 5 Then 'If 安定マーク表示のカウント数に達したか? Then Stablecount = 5 Lcd "*" '安定マーク[*]を表示する。 End If Else '前回の測定値から変化している場合。 Lastvalue = Templ1 '現在の測定値を保管する。 Stablecount = 0 '安定マークの表示カウント数を初期化する。 Lcd " " '安定マーク[*]を消去する。 End If End If ' ' * スイッチの処理 * ' Gosub Getkey 'キー(スイッチ)を検出する。 If Keydata = 1 Then Goto Sw1on 'If [SELECT]が押されたか? Then If Keydata = 2 Then Goto Sw2on 'If [LEFT]が押されたか? Then Keydata = 0 'キー(スイッチ)の入力をクリアする。 Goto Main '-------------------------------------------------------------------------------------------------- ' ' ****************** ' * [SW1] ゼロ調整 * ' ****************** ' Sw1on: Zeroadj = 0 - Hx711avg '現在の測定値を[0.0g]にする。 Stablecount = 0 '安定マークの表示カウント数を初期化する。 Keydata = 0 'キー(スイッチ)の入力をクリアする。 Goto Main '-------------------------------------------------------------------------------------------------- ' ' ******************************** ' * [SW2] センサーの出力誤差調整 * ' ******************************** ' Sw2on: Cls 'LCD表示をすべて消去する。 Lcd "Calibration" Do Gosub Getkey 'キー(スイッチ)を検出する。 Loop Until Keyadcode = 0 '[LEFT]が離されるまで待つ。 Waitms 30 'チャタリングを除去する待ち時間。 Keydata = 0 'キー(スイッチ)の入力をクリアする。 Temp1 = 0 'スイッチ長押し検出カウンター。 ' Sw2on1: Gosub Getkey 'キー(スイッチ)を検出する。 If Keydata = 2 Then Goto Calsw1on 'If [LEFT]が押されたか? Then If Keydata = 4 Then Goto Calsw2on 'If [UP]が押されたか? Then If Keydata = 3 Then Goto Calsw3on 'If [DOWN]が押されたか? Then Keydata = 0 'キー(スイッチ)の入力をクリアする。 ' If Hx711_dat = 0 Then 'If HX711の[DOUT]ピンが[L]になった(変換終了)か? Then If Keyadcode = 3 Or Keyadcode = 4 Then 'If [UP]か[DOWN]が押されているか? Then Temp1 = Temp1 + 1 If Temp1 > 10 Then '[UP]か[DOWN]が押されてから1秒経過したか? Then Temp1 = 10 If Keyadcode = 4 Then 'If [UP]が押されているか? Then If Sensorcal < 21000 Then 'If 上限ではないか? Then Sensorcal = Sensorcal + 10 'ロードセル・センサーのグラム換算値を加算する。 End If Else If Sensorcal > 1000 Then 'If 下限ではないか? Then Sensorcal = Sensorcal - 10 'ロードセル・センサーのグラム換算値を減算する。 End If End If End If End If ' Gosub Hx711get 'HX711のチャンネルAから128の利得でA/Dデータを取り出す。 Gosub Hx711movavg 'HX711のA/D変換データを移動平均する。 Templ1 = Hx711avg + Zeroadj 'ゼロ調整の差分を計算する。 ' Templ1 = Templ1 * 100 'グラム換算の小数点桁上げのために100倍する。 Templ1 = Templ1 / Sensorcal 'ロードセル・センサーのA/D値からグラム換算する。 ' Locate 2 , 3 Tempstr = Str(templ1) '数値変数を文字変数に変換する。 If Templ1 < 0 Then 'If 表示値がマイナスか? Then Lcd Format(tempstr , " 0") ; "g" 'マイナスの重量をLCDに表示する。 Else 'プラスの場合。 Lcd Format(tempstr , " 0") ; "g" 'プラスの重量をLCDに表示する。 End If ' Tempstr = Str(sensorcal) '数値変数を文字変数に変換する。 Locate 2 , 12 'ロードセル・センサーのグラム換算値を表示する。 Lcd Format(tempstr , " 0") End If Goto Sw2on1 ' ' * [LEFT]校正終了 * ' Calsw1on: Eepsensorcal = Sensorcal 'EEPROMに保管する。 Stablecount = 0 '安定マークの表示カウント数を初期化する。 Cls 'LCD表示をすべて消去する。 Keydata = 0 'キー(スイッチ)の入力をクリアする。 Goto Main ' ' * [UP]校正値を加算 * ' Calsw2on: If Sensorcal < 21000 Then 'If 上限ではないか? Then Sensorcal = Sensorcal + 1 'ロードセル・センサーのグラム換算値を加算する。 End If Temp1 = 0 'スイッチ長押し検出カウンターを初期化する。 Keydata = 0 'キー(スイッチ)の入力をクリアする。 Goto Sw2on1 ' ' * [DOWN]校正値を減算 * ' Calsw3on: If Sensorcal > 1000 Then 'If 下限ではないか? Then Sensorcal = Sensorcal - 1 'ロードセル・センサーのグラム換算値を減算する。 End If Temp1 = 0 'スイッチ長押し検出カウンターを初期化する。 Keydata = 0 'キー(スイッチ)の入力をクリアする。 Goto Sw2on1 '================================================================================================== ' ' ******************************************************************** ' * HX711のチャンネルAから128の利得でA/Dデータを取り出すサブルーチン * (Hx711ad = 2の補数形式24bit) ' ******************************************************************** ' Hx711get: Hx711ad = 0 For Hx711count = 23 To 0 Step -1 '24bitのデータを取り出す。 Set Hx711_clk 'HX711の[PD_SCK]ピンを[H]にする。 Waitus 1 '[H]の期間。(T3=1uS) Hx711ad.hx711count = Hx711_dat 'HX711の[DOUT]ピンのデータを各ビットに配置する。 Reset Hx711_clk 'HX711の[PD_SCK]ピンを[L]にする。 Waitus 1 '[L]の期間。(T4=1uS) Next Hx711count ' ' * 25個目のクロックパルスを送る (次回の変換をチャンネルA・利得を128に設定する) * ' Set Hx711_clk 'HX711の[PD_SCK]ピンを[H]にする。 Waitus 1 '[H]の期間。(T3=1uS) Reset Hx711_clk 'HX711の[PD_SCK]ピンを[L]にする。 Waitus 1 '[L]の期間。(T4=1uS) ' If Hx711ad.23 = 1 Then 'A/Dの24bit値がマイナス値か? Then Hx711ad = Hx711ad Or &HFF000000 '32bitのマイナス値にする。 End If Return '--------------------------------------------------------------------------------------------------- ' ' ************************************************** ' * HX711のA/D変換データを移動平均するサブルーチン * (Hx711avg = 16個の移動平均) ' ************************************************** ' Hx711movavg: Avgsum = Avgsum - Average(avgpoi) '一番古いデータを減算する。 Average(avgpoi) = Hx711ad '移動平均バッファーに格納する。 Avgsum = Avgsum + Hx711ad '新しいデータを合算する。 ' Avgpoi = Avgpoi + 1 '移動平均ポインターを更新する。 If Avgpoi > 16 Then 'If ポインターが上限か? Then Avgpoi = 1 End If ' Hx711avg = Avgsum Shift Hx711avg , Right , 4 , Signed '16個の移動平均を取る。 Return '################################################################################################## ' ' *********************************************************** メイン・ルーチンで定期的に呼び続けること。 ' * キー(スイッチ)を検出するサブルーチン (抵抗値のA/D変換) * Keydata = キー(スイッチ)の入力データ。(押された場合にコードが入る) ' *********************************************************** Keyadcode = キー(スイッチ)をA/D変換したコード。(押されている状態のコードが入る) ' (0:押されていない, 1:[SELECT] , 2:[LEFT], 3:[DOWN], 4:[UP], 5:[RIGHT]キー) Getkey: Gosub Keyadconv 'キー(スイッチ)の分圧抵抗値をA/D変換する。 If Keyadcode <> 0 Then 'If いずれかのキーが押されているか? Then If Keystat = 0 Then 'If キー入力の検出中か? Then Waitms 30 'チャタリングを除去する待ち時間。 Gosub Keyadconv 'キー(スイッチ)の分圧抵抗値をA/D変換する。 If Keyadcode <> 0 Then 'If いずれかのキーが押されているか? Then Keydata = Keyadcode 'キーが押されたことを通知する。 Keystat = 1 'キーの解放待ちにする。 End If End If Else 'キーが押されていない場合。 If Keystat <> 0 Then 'If キーの解放待ちか? Then Waitms 30 'チャタリングを除去する待ち時間。 Gosub Keyadconv 'キー(スイッチ)の分圧抵抗値をA/D変換する。 If Keyadcode = 0 Then 'If キーが離されているか? Then Keystat = 0 'キー入力の検出中にする。 End If End If End If Return ' ' * キー(スイッチ)の分圧抵抗値をA/D変換するサブルーチン * ' Keyadconv: Keyw1 = Getadc(0) 'キー(スイッチ)の分圧抵抗値をA/D変換する。 Select Case Keyw1 '分圧抵抗のA/D値から押されたキーを判別する。 Case Is > 950 : Keyadcode = 0 'キーが押されていない場合。 Case Is < 50 : Keyadcode = 5 '[RIGHT] キー。 Case Is < 195 : Keyadcode = 4 '[UP] キー。 Case Is < 380 : Keyadcode = 3 '[DOWN] キー。 Case Is < 555 : Keyadcode = 2 '[LEFT] キー。 Case Else : Keyadcode = 1 '[SELECT] キー。 End Select Return ' ' End