LRA1-Basic
すべてが正しいとは限りません。
コードのみで何の説明もありませんが、何かの参考になれば・・・。
2022/11/18 f.izawa
・2022/12/08 7SEG LED を追加
・2022/12/10 7SEG LED を更新(高速化)
・HC2_DP_TX3.zip 2022/11/17.1 (露点換算サンプルデータ+サンプルコード)
温度、湿度→露点温度換算と有機 E Lキャラクタディスプレイ (OLED) を使うサンプルコードです。
露点温度換算が以前のものより正確になったと思います。
※飽和水蒸気分圧のデータ (TetensKinji.bas) を送信する時は、行番号無しで送信して下さい。←重要です。
・TWO_WAY_DIO.zip 2022/10/15 (双方向 入力 4 点 + 出力 4 点 リモート I/O)
実用レベルには至っていません・・・。
・TWO_WAY_DIOEXP.zip 2022/10/29 (I/O エキスパンダ PCF8575 を使った双方向 入力 4 点 + 出力 4 点 リモート I/O)
デフォルト設定:CR=1(4/5), SF=10, BW=7 (125kHz) で 627ミリ秒、BW=8 (250kHz) にすると 332 ミリ秒周期で動きます。
受信タイムアウト時間 2000 msec は短くしたほうが違和感が少ないです。
実用レベルには至っていません・・・。
■ TM1637 ドライブ 4桁 7SEG LED
2022/12/10 サブルーチンをやめて、違和感の無い速さになりました
'' TM1637_7SEG2.bas 2022/12/10 '' 使用変数 = J, K '' 参考URL : https://kurobekoblog.com/tm1637 '' $44 '' Mode = 固定アドレスモード '' $C0 '' ADR = 1 桁目のアドレス '' $8F '' Dcont = $88 + 7(下位3bit) = $8F, PWM 調光 0~7 & ON($88) or OFF($80) I2cD[10] = 27 '' CLK PA27 (pin 5) I2cD[11] = 54 '' DIO PB22 (pin 6) 22+32 = 54 '' I2cD[12]~I2cD[13] は Sub 内部で使用 I2cD[14] = 0 ''小数点以下の桁数 '' I2cD[15]~I2cD[25] は Sub 内部で使用 Gosub _init7segLED 'Tick = 0 'Gosub _hide7segLED 'Print Tick ''77->15msec Tick = 0 ''表示データをセット ^ = Form("4", -123): Gosub _draw7segLED Print Tick ''566->117msec 'Tick = 0 'Gosub _show7segLED 'Print Tick ''77->15msec Delay 1000 'Gosub _hide7segLED ^ = "4567": Gosub _draw7segLED 'Gosub _show7segLED Delay 1000 Gosub _clear7segLED End _init7segLED '' 7 seg Data I2cD[15] = $3F ''0 I2cD[16] = $06 ''1 I2cD[17] = $5B ''2 I2cD[18] = $4F ''3 I2cD[19] = $66 ''4 I2cD[20] = $6D ''5 I2cD[21] = $7D ''6 I2cD[22] = $07 ''7 I2cD[23] = $7F ''8 I2cD[24] = $6F ''9 I2cD[25] = $40 ''- 'I2cD[25] = $77 ''A 'I2cD[26] = $7C ''b 'I2cD[27] = $58 ''c 'I2cD[28] = $5E ''d 'I2cD[29] = $79 ''E 'I2cD[30] = $71 ''F 'I2cD[31] = $40 ''- '' 固定アドレスモード '' startCondition outP I2cD[10], 1: I2cD[13] = inP(I2cD[11] | $200): outP I2cD[11], 0 I2cD[12] = $44: Gosub _writeByte '' stopCondition outP I2cD[11], 0: outP I2cD[10], 1 '' コントラストセット、表示 Gosub _show7segLED Return _show7segLED '' コントラストセット、表示 '' startCondition outP I2cD[10], 1: I2cD[13] = inP(I2cD[11] | $200): outP I2cD[11], 0 I2cD[12] = $8F:Gosub _writeByte '' stopCondition outP I2cD[11], 0: outP I2cD[10], 1 Return _hide7segLED '' コントラストセット、非表示 '' startCondition outP I2cD[10], 1: I2cD[13] = inP(I2cD[11] | $200): outP I2cD[11], 0 I2cD[12] = $87:Gosub _writeByte '' stopCondition outP I2cD[11], 0: outP I2cD[10], 1 Return _draw7segLED ''表示データをセット For j = 0 To 3 '' startCondition outP I2cD[10], 1: I2cD[13] = inP(I2cD[11] | $200): outP I2cD[11], 0 '' 表示位置(左が $C0) I2cD[12] = $C0 + j:Gosub _writeByte '' 表示データ IF ^[j] = $2D Then I2cD[12] = I2cD[25] '' マイナス ElseIf ^[j] >= $30 & ^[j] <= $39 Then I2cD[12] = I2cD[^[j] - $30 + 15] Else I2cD[12] = 0 EndIf '' 小数点 If I2cD[14] > 0 & I2cD[14] = 3 - j Then I2cD[12] = I2cD[12] | $80 EndIf:Gosub _writeByte '' stopCondition outP I2cD[11], 0: outP I2cD[10], 1 Next Return _clear7segLED Gosub _hide7segLED For j = 0 To 3 '' startCondition outP I2cD[10], 1: I2cD[13] = inP(I2cD[11] | $200): outP I2cD[11], 0 '' 表示位置(左が $C0) I2cD[12] = $C0 + j:Gosub _writeByte '' 表示データ I2cD[12] = 0:Gosub _writeByte '' stopCondition outP I2cD[11], 0: outP I2cD[10], 1 Next Gosub _show7segLED Return '' I2cD[12] Byteデータ _writeByte '' 1 バイトデータ For k = 0 To 7 '' CLK LOW データの送信はクロックが LOW の時に行う outP I2cD[10], 0 '' ビットセット If I2cD[12] & $01 Then I2cD[13] = inP(I2cD[11] | $200) Else outP I2cD[11], 0 EndIf '' CLK HIGH 1 ビットのデータの区切り outP I2cD[10], 1 I2cD[12] = I2cD[12] >> 1 Next '' ACK 信号待ち outP I2cD[10], 0 I2cD[13] = inP(I2cD[11] | $200) '' CLK を HIGH にすることで ACK 解除 outP I2cD[10], 1 '' read DIO If inP(I2cD[11]) = 0 Then outP I2cD[11], 0 Endif outP I2cD[10], 0 Return
■ 三菱 PLC FX3S 通信
'' FX3S 1C 形式4 チェックサム無し '' FXシリーズ ユーザーズマニュアル[通信制御編] JY997D13301 '' 計算機リンク機能 '' 7.1 BRコマンド以降(275/710ページあたり) Ubaud = 19200 While UInkey >= 0: Loop '' ビット読み出し------------------ ^ = Chr($05) '' ENQ ^ = ^; "00" '' 局番 ^ = ^; "FF" '' PC番号(FXの場合、固定) ^ = ^; "BR" '' コマンド(ビット読み出し) ^ = ^; "0" '' 伝文ウェイト(0~F = 0~150ms) ^ = ^; "X0000" '' 5桁で指示:X0000から ^ = ^; "10" '' HEX 2 桁で指示:16個読み出し Uprint ^ Delay 100 ^ = "" Do X = UInkey '' UART2 受信 If X >= 0 Then ^ = ^;Chr(X) Else Exit EndIf Loop '' ex:res= STX(02)+ "00FF" + "0000000000000000" + ETX(03) + CR(13)LF(10) Print ^[] '' 30 If ^[] = 8 + 16 Then For i = 0 To 15 Print Chr(^[5 + i]); Next Print "" EndIf '' ビット書き込み------------------ '' ※ RUN 中はプログラムで操作しているビットは操作できない ^ = Chr($05) '' ENQ ^ = ^; "00" '' 局番 ^ = ^; "FF" '' PC番号(FXの場合、固定) ^ = ^; "BW" '' コマンド(ビット書き込み) ^ = ^; "0" '' 伝文ウェイト(0~F = 0~150ms) ^ = ^; "Y0000" '' 5桁で指示:Y0000から ^ = ^; "08" '' HEX 2 桁で指示:8個書き込み ^ = ^; "11000000" '' 出力:左から Uprint ^ Delay 100 ^ = "" Do X = UInkey '' UART2 受信 If X >= 0 Then ^ = ^;Chr(X) Else Exit EndIf Loop '' ex:res= ACK06)+ "00FF" + CR(13)LF(10) Print ^[] '' 30 If ^[] = 7 Then For i = 0 To 6 Print ^[i] Next Print "" EndIf
■ Azbil CPL 通信
LRA1 ファームウェア 1.14c (2022/11/30) で、パリティの設定ができるようになりました。 アズビル SDC との通信は RS485 でなくスマートローダー経由で UART 通信ができます。 一時的な使用であれば問題無さそうです。 UBaud = 19202 //19200 bps + Even = 19202 |
'' SETUP C64 = 0 で CPL(デフォルト) UBaud = 19200 Do While UInkey >= 0: Loop '' ←必要 ^ = Chr($02) '' STX ^ = ^;"01" '' 機器アドレス ^ = ^;"00" '' サブアドレス(未使用) ^ = ^;"X" '' デバイス区別コード '' 小数点位置 + PV + SP + OUT + MFB + AUT/MAN + マニュアル操作量(MV) ^ = ^;"RU00";"1454";"3814";"3815";"3816";"3851";"3811";"3902" '' コマンド ^ = ^;Chr($03) '' ETX '' チェックサム S = 0 For i = 0 To ^[] - 1: S = S + ^[i]: Next ''Print "Sum=";S ''2002 S = S & $FF '' 加算結果の下位1バイト S = (- S & $FF) '' 2の補数 ''Print "checkSum=";Form("X02", S) ''2E ^ = ^;Form("X02", S) '' 送信文字列に追加 UPrint ^ '' UART2 送信 Delay 100 ^ = "" Do X = UInkey '' UART2 受信 If X >= 0 Then ^ = ^;Chr(X) Else Exit EndIf Loop If ^[] = 9 + 4 * 8 Then For i = 0 To 7 @[i] = ("$";Chr(^[8 + i * 4]);Chr(^[9 + i * 4]);Chr(^[10 + i * 4]);Chr(^[11 + i * 4])) Next Print "DIG = ";@[0] Print "PV = ";Int16(@[1]) / Pow(10, @[0]);".";Abs(Int16(@[1]) % Pow(10, @[0])) Print "SP = ";Int16(@[2]) / Pow(10, @[0]);".";Abs(Int16(@[2]) % Pow(10, @[0])) Print "OUT = ";Int16(@[3]) / Pow(10, @[0]);".";Abs(Int16(@[3]) % Pow(10, @[0])) Print "MFB = ";@[4] / Pow(10, @[0]);".";@[4] % Pow(10, @[0]) Print "A/M = ";@[5] Print "MAN = ";Int16(@[6]) / Pow(10, @[0]);".";Abs(Int16(@[6]) % Pow(10, @[0])) Print "----" EndIf Delay 500 Loop End
■ Modbus ASCII 通信
'' Azbil SDC15 RS485 type PV値取得 '' SETUP '' C64: 0=CPL(デフォルト), 1=ASCII, 2=RTU '' C65: 1~127= 機器アドレス '' C66: 2=19200(デフォルト) '' C67: 1=8 データビット(デフォルト) '' C68: 0=偶数(デフォルト), 1=奇数, 2=無し '' C69; 0=1 ストップビット(デフォルト) '' C70: 3msec '' C80: 2= データ受診時、SP値右下のドットを点滅 UBaud = 19200 Do While UInkey >= 0: Loop '' ←必要 '' 機器アドレス ^="01" '' 読み出しコマンド ^= ^;"03" '' 読み出し先頭アドレス $238D = PV ^=^;"238D" '' 読み出し数 $0001 ^=^;"0001" '' ChechSum 計算 S = 0 For i = 0 To ^[] / 2 S = S + ("$";Chr(^[i*2]);Chr(^[i*2+1])) Next S = S & $FF ''加算結果の下位1バイト S = (- S & $FF) ''2の補数 ^ = ^;Form("X02",S)'' それを 16進表記に変換して追加 ^ = ^;Chr($0D);Chr($0A)'' CR LF を追加 ^ = ":";^ '' 電文文字を先頭に追加 Print "send=";^ UPrint ^ '' 送信 ^ = UGets(100) '' 受信 Print "recv=";^ '':0103021130B9 If ^[3] = $30 && ^[4] = $33 Then '' 読み出しコマンド"03" であるか A = ("$";Chr(^[7]);Chr(^[8]);Chr(^[9]);Chr(^[10])) '' PV Print A '' 4400 = PV値(小数点位置は別に取得する必要がある) EndIf Delay 500 Loop
■ Modbus RTU 通信
'' Azbil SDC15 RS485 type PV,SP,MV値取得 + SP変更 '' SETUP '' C64: 2: 0=CPL(デフォルト), 1=ASCII, 2=RTU '' C65: 1: 1~127= 機器アドレス '' C66: 2=19200(デフォルト) '' C67: 1=8 データビット(デフォルト) '' C68: 2: 0=偶数(デフォルト), 1=奇数, 2=無し '' C69; 0=1 ストップビット(デフォルト) '' C70: 3msec '' C80: 2=データ受信時、SP値右下のドットを点滅 UBaud = 19200 Do While UInkey >= 0: Loop '' ←必要 '' 機器アドレス ^ = Chr($01) '' 読み出しコマンド ^ = ^;Chr($03) '' 読み出し先頭アドレス $238D = PV, $238E = SP, $2391 = MV ^ = ^;Chr($23);Chr($8D) '' 読み出し数 $0004 ^ = ^;Chr($00);Chr($05) '' CRC 追加 GoSub _AddCRC UPrint ^; '' ←;重要 CrLf 無し Delay 30 ^ = "" Do X = UInkey If X >= 0 Then ^ = ^;Chr(X) Else Exit EndIf Loop '' ex: res= 01 03 02 11 30 B4 00 (3番目の 02 はデータ数?2、最後の2つはエラーチェック) If ^[] >= 4 && ^[1] = $03 Then P = Int16(^[3] << 8 | ^[4]) Print "PV = ";P S = Int16(^[5] << 8 | ^[6]) Print "SP = ";S M = Int16(^[11] << 8 | ^[12]) Print "MV = ";M EndIf '' 機器アドレス ^ = Chr($01) '' 書き込みコマンド ^ = ^;Chr($10) '' 書き込み先頭アドレス $238E = SP ^ = ^;Chr($23);Chr($8E) '' 書き込み数 $0001 ^ = ^;Chr($00);Chr($01) '' 書き込み数 の2倍 ^ = ^;Chr($02) S = 3999 '' SP '' 書き込みデータ ^ = ^;Chr(S >> 8 & $FF);Chr(S & $FF) '' CRC 追加 GoSub _AddCRC UPrint ^; '' ←;重要 CrLf 無し Delay 500 Loop End _AddCRC '' CRC16 計算 @[10..13] を使用 '' Azbil CP-SP-1148 デジタル指示調節計 型C15 取扱説明書 詳細編 '' Modbus/RTU 「チェックサム(CRC)の作成方法」より @[10] = $FFFF For @[13] = 0 To ^[] - 1 @[10] = @[10] ^ ^[@[13]] For @[12] = 0 To 7 @[11] = @[10] & $0001 @[10] = @[10] >> 1 If @[11] = 1 Then @[10] = @[10] ^ $A001 EndIf Next Next @[13] = (@[10] >> 8) & $00FF @[10] = @[10] << 8 @[10] = (@[10] | @[13]) & $FFFF ''Print "crc = ";Form("X",@[10]) '' 最後に CRC を追加 ^ = ^;Chr(@[10] >> 8);Chr(@[10] & $00FF) Return
■ クランプ式交流電流センサー
'' SCT 013-010 + ADC ADS1115 による交流電流の超簡易測定 '' SCT 013-010 は、AC 0~10A に対して AC 0~1V が出力されるクランプ式電流センサー '' サンプリング数は、Arduino :1サイクル 200回程度に対して LRA1 + ADS1115 : 17回程度と、かなりの差がある '' 手軽に交流電流を測定できる I2cD[31] = $48 '' ADS1115 I2C_ADDRS (ADDR-GND:$48, ADDR-VDD:$49, ADDR-SDA:$4A, ADDR-SCL:$4B) '' 上位 8 ビット = OS[1bit] + MUX[3bit] + PGA[3bit] + MODE[1bit] '' OS [1bit] = 1 ' 変換する '' 入力ピン設定 '' MUX [3bit] = 0 (差動入力: 0 = AN0-AN1, 1 = AN0-AN3, 2 = AN1-AN3, 3 = AN2-AN3) '' (シングル入力: 4 = AN0-GND, 5 = AN1-GND, 6 = AN2-GND, 7 = AN3-GND) '' 測定レンジ設定 '' PGA [3bit] = 0 (0 = +/-6.144, 1 = +/-4.096, 2 = +/-2.048, 3 = +/-1.024, 4 = +/-0.512, 5 = +/-0.256 V) I2cD[2] = 2 '' 0~2V = 0~2000 '' ADS1115(16bit) '' 0.1875 mV/bit +/-6.144 V '' 0.125 mV/bit +/-4.096 V '' 0.0625 mV/bit +/-2.048 V '' 0.03125 mV/bit +/-1.024 V '' 0.015625 mV/bit +/-0.512 V '' 0.0078125 mV/bit +/-0.256 V '' 変換モード設定 '' MODE [1bit] = 0 (0 = 連続変換, 1 = シングルショット) '' 下位 8 ビット = DR[3bit] + COMP[5bit] '' データレート(samples per second)設定 '' DR [3bit] = 7 ''(ADS1115: 0 = 8, 1 = 16, 2 = 32, 3 = 64, 4 = 128, 5 = 250, 6 = 475, 7 = 860 SPS) '' COMP [5bit] = 3 (デフォルト値そのまま) '' 差動入力: 0 = AN0-AN1, +/-2.048V, 連続変換 I2cd[0] = 1 << 7 | 0 << 4 | I2cD[2] << 1 | 0 '' OS[1bit] + MUX[3bit] + PGA[3bit] + MODE[1bit] '' 860 SPS I2cd[1] = 7 << 5 | 3 '' DR[3bit] + COMP[5bit] I2cW I2cD[31], 1, 2 '' 設定レジスタに書き込み Delay 20 Do S = 0 Tick = 0 For j = 0 To 1 For i = 0 To 255 I2cR I2cD[31], 0, 2 '' 変換レジスタを読み込み @[i] = I2cD[0] << 8 | I2cD[1] Next For i = 0 To 255 A = Int16(@[i]) * 625 / 10000 '' 625 = 0.0625 mV/bit S = S + A * A Next Next Print "Tick= "; Tick '' 796 msec U = Sqrt(S / 512) '' 二乗平均平方根値(取りこぼしがあるため実効値より小さくなる) Print "RMS = ";U;" mA" Loop End
■ GPS
Ubaud=9600 Do UGps 10000,14 '' タイムアウト=10秒、HDOP(水平精度低下率)閾値= 1.4 @[0] = @[0] + 9 * 60 * 60 Print "N : "; @[1] / 1000000; "."; @[1] % 1000000 '' 緯度 Print "E : "; @[2] / 1000000; "."; @[2] % 1000000 '' 経度 Print "H : "; @[3] / 10; "."; @[3] % 10; "m" '' 標高 Print "HDOP : ";@[4]/10; "."; @[4] % 10 '' 水平精度低下率 DateTime @[0], 10 Print @[10];"/";Form("02",@[11]);"/";Form("02",@[12]);" ";Form("02",@[13]);":";Form("02",@[14]);":";Form("02",@[15]) Loop End
■ GPS リアルタイムクロック (自前で計算)
Ubaud=9600 Do ^ = UGets(200) Print ^ If ^[0] = $24 && ^[4] = $4D && ^[5] = $43 && ^[] > 13 Then I2cD[13] = (Chr(^[7]);Chr(^[8]))'' H I2cD[14] = (Chr(^[9]);Chr(^[10])) '' M" I2cD[15] = (Chr(^[11]);Chr(^[12])) '' S m = 0 For i = 13 To ^[] -1 If i + 6 < ^[] Then If ^[i] = $2C Then m = m + 1 EndIf If m = 8 && ^[] > i + 6 Then I2cD[12] = (Chr(^[i + 1]);Chr(^[i + 2])) '' D I2cD[11] = (Chr(^[i + 3]);Chr(^[i + 4])) '' M I2cD[10] = (Chr(^[i + 5]);Chr(^[i + 6])) '' Y Exit EndIf Else Exit EndIf Next Print I2cD[10];"/";Form("02",I2cD[11]);"/";Form("02",I2cD[12]);" ";Form("02",I2cD[13]);":";Form("02",I2cD[14]);":";Form("02",I2cD[15]) Gosub _UTCtoJST Print I2cD[10];"/";Form("02",I2cD[11]);"/";Form("02",I2cD[12]);" ";Form("02",I2cD[13]);":";Form("02",I2cD[14]);":";Form("02",I2cD[15]) EndIf Loop End _UTCtoJST I2cD[23] = I2cD[13] + 9 '' H I2cD[22] = I2cD[12] '' D I2cD[21] = I2cD[11] '' M I2cD[20] = I2cD[10] '' Y '' その月の日数 If I2cD[11] = 2 Then If I2cD[10] % 4 = 0 Then I2cD[24] = 29 ''閏年 Else I2cD[24] = 28 EndIf ElseIf I2cD[11] = 4 || I2cD[11] = 6 || I2cD[11] = 9 || I2cD[11] = 11 Then I2cD[24] = 30 Else I2cD[24] = 31 EndIf If I2cD[23] > 24 Then ''H I2cD[23] = I2cD[23] - 24 I2cD[22] = I2cD[22] + 1 ''D If I2cD[22] > I2cD[24] Then I2cD[22] = I2cD[22] - I2cD[24] I2cD[21] = I2cD[21] + 1 ''M If I2cD[21] > 12 Then I2cD[21] = I2cD[21] - 12 I2cD[20] = I2cD[20] + 1 ''Y EndIf EndIf EndIf I2cD[13] = I2cD[23] '' H I2cD[12] = I2cD[22] '' D I2cD[11] = I2cD[21] '' M I2cD[10] = I2cD[20] '' Y Return
■ RTC DS3231 リアルタイムクロック
Ubaud=9600 Do ^ = UGets(200) Print ^ If ^[0] = $24 && ^[4] = $4D && ^[5] = $43 && ^[] > 13 Then I2cD[13] = (Chr(^[7]);Chr(^[8]))'' H I2cD[14] = (Chr(^[9]);Chr(^[10])) '' M" I2cD[15] = (Chr(^[11]);Chr(^[12])) '' S m = 0 For i = 13 To ^[] -1 If i + 6 < ^[] Then If ^[i] = $2C Then m = m + 1 EndIf If m = 8 && ^[] > i + 6 Then I2cD[12] = (Chr(^[i + 1]);Chr(^[i + 2])) '' D I2cD[11] = (Chr(^[i + 3]);Chr(^[i + 4])) '' M I2cD[10] = (Chr(^[i + 5]);Chr(^[i + 6])) '' Y Exit EndIf Else Exit EndIf Next Print I2cD[10];"/";Form("02",I2cD[11]);"/";Form("02",I2cD[12]);" ";Form("02",I2cD[13]);":";Form("02",I2cD[14]);":";Form("02",I2cD[15]) Gosub _UTCtoJST Print I2cD[10];"/";Form("02",I2cD[11]);"/";Form("02",I2cD[12]);" ";Form("02",I2cD[13]);":";Form("02",I2cD[14]);":";Form("02",I2cD[15]) EndIf Loop End _UTCtoJST I2cD[23] = I2cD[13] + 9 '' H I2cD[22] = I2cD[12] '' D I2cD[21] = I2cD[11] '' M I2cD[20] = I2cD[10] '' Y '' その月の日数 If I2cD[11] = 2 Then If I2cD[10] % 4 = 0 Then I2cD[24] = 29 ''閏年 Else I2cD[24] = 28 EndIf ElseIf I2cD[11] = 4 || I2cD[11] = 6 || I2cD[11] = 9 || I2cD[11] = 11 Then I2cD[24] = 30 Else I2cD[24] = 31 EndIf If I2cD[23] > 24 Then ''H I2cD[23] = I2cD[23] - 24 I2cD[22] = I2cD[22] + 1 ''D If I2cD[22] > I2cD[24] Then I2cD[22] = I2cD[22] - I2cD[24] I2cD[21] = I2cD[21] + 1 ''M If I2cD[21] > 12 Then I2cD[21] = I2cD[21] - 12 I2cD[20] = I2cD[20] + 1 ''Y EndIf EndIf EndIf I2cD[13] = I2cD[23] '' H I2cD[12] = I2cD[22] '' D I2cD[11] = I2cD[21] '' M I2cD[10] = I2cD[20] '' Y Return
■ INA226 直流電流、電圧測定
I2cD[31] = $40 '' INA226PRC I2C_ADDRS '' Read Configuration Register '' デフォルトで、平均化なし、サンプリング周期 1.1msec、電圧/電流を交互に計測 I2cR I2cD[31], 0, 2 Print Form("X02", I2cD[0]); Form("X02", I2cD[1]) '' $4127 '' Write Caribration Register(シャント抵抗の補正値) '' 1.0 倍= 2048, '' シャント抵抗2mオームの時、1.25 倍 = 2048 x 1.25 = 2560($0A00) で電流値を直読できる '' I2cD[0] = $0A:I2cD[1] = $00 '' シャント抵抗25mオームの時は、1.0 倍 = 2048($0800) I2cD[0] = $08:I2cD[1] = $00 I2cW I2cD[31], 5, 2 Do '' Read Bus Voltage I2cR I2cD[31], 2, 2 v = I2cD[0] << 8 | I2cd[1] Print v * 125 / 100 ; " mV" ' 1.25mV/bit '' Read Current I2cR I2cD[31], 4, 2 i = I2cD[0] << 8 | I2cd[1] Print Int16(i) ; " x 0.1mA" ' 0.1mA/bit(レジスタ 5 での補正後の値) '' Read Power I2cR I2cD[31], 3, 2 p = I2cD[0] << 8 | I2cD[1] Print p * 25/10 " mW" ' mW Delay 500 Loop End
■ ADS1115 16 ビット アナログデジタルコンバータ
I2cD[31] = $48 '' ADS1115 I2C_ADDRS (ADDR-GND:$48, ADDR-VDD:$49, ADDR-SDA:$4A, ADDR-SCL:$4B) 'I2cR I2cD[31], 0, 2 '' 設定レジスタを読み込み 'Print Form("X02", I2cD[0]) '' 85 上位 'Print Form("X02", I2cD[1]) '' 83 下位 '' 設定レジスタのデフォルト値は、上位 8bit= $85, 下位 8bit = $83 '' 上位 8 ビット = OS[1bit] + MUX[3bit] + PGA[3bit] + MODE[1bit] '' OS [1bit] = 1 ' 変換する '' 入力ピン設定 '' MUX [3bit] = 0 (差動入力: 0 = AN0-AN1, 1 = AN0-AN3, 2 = AN1-AN3, 3 = AN2-AN3) '' (シングル入力: 4 = AN0-GND, 5 = AN1-GND, 6 = AN2-GND, 7 = AN3-GND) '' 測定レンジ設定 '' PGA [3bit] = 0 (0 = +-6.144, 1 = +-4.096, 2 = +-2.048, 3 = +-1.024, 4 = +-0.512, 5 = +-0.256 V) I2cD[2] = 1 '' ADS1115(16bit) @[0] = 1875 ' 0.1875 mV/bit @[1] = 1250 ' 0.125 mV/bit @[2] = 625 ' 0.0625 mV/bit @[3] = 3125 ' 0.03125 mV/bit @[4] = 15625 ' 0.015625 mV/bit @[5] = 78125 ' 0.0078125 mV/bit '' ADS1015(12bit) '@[0] = 3000 ' 3.0 mV/bit '@[1] = 2000 ' 2.0 mV/bit '@[2] = 1000 ' 1.0 mV/bit '@[3] = 0500 ' 0.5 mV/bit '@[4] = 0250 ' 0.25 mV/bit '@[5] = 0125 ' 0.125 mV/bit '' 変換モード設定 '' MODE [1bit] = 0 (0 = 連続変換, 1 = シングルショット) '' 下位 8 ビット = DR[3bit] + COMP[5bit] '' データレート(samples per second)設定 '' DR [3bit] = 4 (ADS1015: 0 = 128, 1 = 250, 2 = 490, 3 = 920, 4 = 1600, 5 = 2400, 6 = 3300 SPS) '' (ADS1115: 0 = 8, 1 = 16, 2 = 32, 3 = 64, 4 = 128, 5 = 250, 6 = 475, 7 = 860 SPS) '' COMP [5bit] = 3 (デフォルト値そのまま) Do I2cd[0] = 1 << 7 | 0 << 4 | I2cD[2] << 1 | 0 '' OS[1bit] + MUX[3bit] + PGA[3bit] + MODE[1bit] I2cd[1] = 4 << 5 | 3 '' DR[3bit] + COMP[5bit] I2cW I2cD[31], 1, 2 '' 設定レジスタに書き込み Delay 20 I2cR I2cD[31], 0, 2 '' 変換レジスタを読み込み @[6] = I2cD[0] << 8 | I2cD[1] '' If @[6] > $8000 Then @[6] = @[6] - $10000 EndIf @[6] = Int16(@[6]) Print "AN0-AN1 = ";@[6] * @[I2cD[2]] / 10000 I2cd[0] = 1 << 7 | 3 << 4 | I2cD[2] << 1 | 0 '' OS[1bit] + MUX[3bit] + PGA[3bit] + MODE[1bit] I2cd[1] = 4 << 5 | 3 '' DR[3bit] + COMP[5bit] I2cW I2cD[31], 1, 2 '' 設定レジスタに書き込み Delay 20 I2cR I2cD[31], 0, 2 '' 変換レジスタを読み込み @[6] = ((I2cD[0] + $80) % $100 - $80) * $100 + I2cD[1] Print "AN2-AN3 = ";@[6] * @[I2cD[2]] / 10000 Delay 500 Loop End
■ I/O エキスパンダ PCF8575 双方向リモート I/O
お互いに適当なタイミングで送受信しているため、受信のタイミングが合わないことがあります。
受信のタイムアウト時間は短く設定したほうが違和感が少なくなります。(2022/11/19)
「電波法上の制限により繰り返してデータを送信する場合、最低でも以下の間隔が必要です。
これよりも早い間隔でデータを送った場合、データは内部で捨てられます。
下側バンド:(各モードの送信時間[ms]+休止時間 50[ms]+10~20[ms])」
と、リファレンスにあるので何回かに1回は送信されない可能性があります。(2022/11/21)
'' 0.128 秒(SF=7, BW=7 125kHz) 周期(RX = 69 msec, TX=61 msec) '' 0.627 秒(SF=10, BW=7 125kHz), 0.332 秒(SF=10, BW=8 250kHz) 周期 '' デフォルト値:CR = 1(4/5), SF=10 BW=7(125kHz) '' MODEM=0 (FSK) で 64 msec 周期 ただしRead Timeout 値の調整が必要 '' SF=7, BW=7 '' 出力はアクティブロー I2cD[31] = $20 '' I2C_ADDR Do Tick = 0 I2cR I2cD[31],-1, 2 '' PCF8575 read '' スイッチ入力下位 4 ビット = P00 ~ P03 I2cD[2] = ~I2cD[0] & $0F '' I2cD[2] を汎用変数として使用 I2cD[0] = $FF '' 入力を H に戻す I2cD[1] = $00 '' 出力を初期化 F = 0 N = 0 For i= 0 To 0 '' リトライしない方が違和感が少ない Recv 100 '' ←実際の受信時間により調整 MODEM=0(FSK 64) / MODEM=1(LoRa 2000~100) If (Stat = 10) && (Rxd[7] >= 3) && (Rxd[8] = $24) Then '' 受信バイト数 >= 3 で $24("$") で始まる '' 受信データ(ex :"$13")を数値に変換 I2cD[1] = (Chr(Rxd[8]);Chr(Rxd[9]);Chr(Rxd[10])) ' Print "recv $";Form("X02",I2cD[1]) '' 送信用データ = 上位 4bit アンサーバック(相手先のスイッチ入力) + 下位 4bit 自機のスイッチ入力 I2cD[2] = I2cD[2] | ((I2cD[1] & $0F) << 4) '' Status LED 点灯 I2cD[0] = $7F '' P07 を L に F = 1 Exit Else N = N + 1 ' Print "Stat ";Stat EndIf ''N = N +1 Next If N > 0 Then Print N EndIf If F = 0 Then Print "Timeout Error "; N EndIf I2cD[1] = ~I2cD[1] & $FF '' P10 ~ P17 I2cW I2cD[31], -1, 2 '' PCF8575 write ' Print "send "; "$";Form("X02", I2cD[2]) ' 上位 4 bit はアンサーバック 'Tick = 0 Send "$";Form("X02", I2cD[2]) 'Print "Tick ";Tick If Stat >0 Then Print Stat EndIf Delay 10 '' ←要調整 Loop End
■ I/O エキスパンダ PCAL9555APW を使う
'' PCAL9555APW I2C GPIOエクスパンダ '' https://www.switch-science.com/products/2352 I2cD[31] = $20 '' PCAL9555APW I2C_ADDRS '' I/O 設定 '' Configration registor ($06, $07) I2cD[0] = $FF '' port0 = 入力(ハイインピーダンス) I2cD[1] = $00 '' port1 = 出力 I2cW I2cD[31], $06, 2 '' プルアップ設定 '' Pull-up/pull-down enable($46,$47) I2cD[0] = $FF '' プルアップ 、プルダウンを有効に I2cW I2cD[31], $46, 1 '' Pull-up / pull-down selection ($48,$49) I2cD[0] = $FF '' 入力をプルアップ I2cW I2cD[31], $48, 1 '' 出力設定 '' Output port configuration($4E, $4F) I2cD[0] = $FF '' オープンドレイン I2cW I2cD[31], $4F, 1 '' 反転設定 I2cD[0] = $FF '' port0 入力を反転 I2cW I2cD[31], $04, 1 Do For i = 0 To 7 '' Read Input I2cR I2cD[31], $00, 1 '' Read Output '' 反転設定済なのでそのまま表示 Print "in : ";I2cD[0]; ", out : ";1 << i '' Write output '' Port1 0 ~ 7 bit を順に ON(Low)に I2cD[0] = ~(1 << i) I2cW I2cD[31], $03, 1 '' Delay 200 Next Loop End
■ I/O エキスパンダ PCF8575 を使う
'' uses ^, X, Y '' PCF8575 I2C アドレス(I2cD[31] を汎用 Byte 変数として使用) I2cD[31] = $20 ''PCF8575 ADDR $20 .. $27 '' 電源投入後は、すべてのI/O は HIGH(プルアップ)で、すべてを入力として使用できる '' LOW に設定すると、出力になる '' Amazon で販売されている PCF8575 モジュールで LRA1 評価ボードの 3V3 を VCC として使う場合、 '' 基板裏面の VCC - VDD をハンダでショートすると VDD が 3.3V になる '' ショートしない場合は AVR が入るため、VDD は 2.3V程度 '' I/O 設定 I2cd[0] = $FF' P00 ..P07 = INPUT(PULLUP) x 8 I2cd[1] = $00' P10 ..P17 = OUTPUT x 8 I2cW I2cD[31],-1, 2 Do 'read I2cR I2cD[31],-1, 2 '' I2cD[2] :入力の反転値を保持 I2cD[2] = $FF - I2cD[0] '' 1, 2, 4, 8, 16, 32, 64, 128 の合計値 Print "IN=";I2cD[2];" OUT=";I2cD[1] ^ = "" For X = 7 To 0 Step - 1 Y = (I2cD[2] >> X) & 1 ^ = ^;Y Gosub _OutpPCF '' テストとして入力をそのまま出力 Next '' 右が下位のビット表示 "00000000" Print ^ Loop End _OutpPCF ''X = pinNo(0 ..8) Y = 1 or 0 I2cD[0] = $FF ''入力を H に戻す If Y = 1 Then I2cD[1] = I2cD[1] | (1 << X) Else I2cD[1] = I2cD[1] & ~(1 << X) EndIf I2cW I2cD[31], -1, 2 Return
■ OLED を使う
'' https://akizukidenshi.com/catalog/g/gP-08276/ '' https://akizukidenshi.com/download/ds/akizuki/so1602awgb-uc-wb-u_akizuki_manu.pdf '' uses: ^, A, B, I, K, N I2cD[31]=$3C Gosub _InitOled Gosub _ContrastMax Gosub _SetMyChars Do Recv 2000 Lclr Gosub _ClearOled If Stat = 10 Then Lprint Rxd Lpos = 64: Lprint "rssi"; Rssi If Rxd[7] > 10 Then i = 0: n = 0: ^ = "": A = $20: B = $20 For i = 0 To Rxd[7] - 1 If Rxd[i + 8] = $3A Then n = n + 1 If n = 1 Then ^ = ^; Chr($F2); "C ": Gosub _DrawText ElseIf n = 2 Then ^ = ^; "% ": Gosub _DrawText ElseIf n = 3 Then ^ = ^; Chr($F2);"CDP ": Gosub _DrawText2 ElseIf n = 4 Then I2cD(0) = ^[0]: Gosub _WriteData EndIf ^ = "" Else ^ = ^; Chr(Rxd[i + 8]) EndIf Next I2cD(0) = ^[0]: Gosub _WriteData Else ^ = "HC2": Gosub _DrawText1 ^ = "no response": Gosub _DrawText2 EndIf ^ = Rssi I2cD[1] = 12: I2cD[2] = 1: Gosub _SetCur: Gosub _DrawText I2cD[1] = 13: I2cD[2] = 0: Gosub _SetCur If Rssi < -130 Then I2cD[1] = 0 Else I2cD[1] = 9 - Abs(Rssi) / 15 EndIf Gosub _DrawAntLevel Else Lpos = 64: Lprint "error "; Stat I2cD[1] = 14: I2cD[2] = 0: Gosub _SetCur I2cD[1] = 0: Gosub _DrawAntLevel EndIf Send "OK" Delay 500 Loop End '' カーソル位置 _SetCur '' I2cD[1]=Col,I2cD[2]=Row [0 base] I2cD[0] = $80 + I2cD[2] * $20 + I2cD[1] Gosub _WriteCommand Return _DrawText For k = 0 To ^[]-1 I2cD[0] = ^[k]: Gosub _WriteData Next Return _DrawText1 I2cD[0] = $80: Gosub _WriteCommand For k = 0 To ^[] - 1 I2cD[0] = ^[k]: Gosub _WriteData Next Return _DrawText2 I2cD[0] = $80 + $20: Gosub _WriteCommand For k = 0 To ^[] - 1 I2cD[0] = ^[k]: Gosub _WriteData Next Return _ClearOled I2cD[0] = $01: Gosub _WriteCommand Return _WriteCommand I2cW I2cD[31],$00,1: Delay 10 Return _WriteData I2cW I2cD[31],$40, 1: Delay 1 Return _InitOled '' Clear Display I2cD[0] = $01: Gosub _WriteCommand '' Return Home I2cD[0] = $02: Gosub _WriteCommand '' Display ON + Cursor ON + Blink ON [8+4+2+1=16=$0F] 'I2cD[0] = $0F '' Display ON + Cursor OFF + Blink OFF [8+4+0+0=12=$0C] I2cD[0] = $0C: Gosub _WriteCommand '' Clear Display I2cD[0] = $01: Gosub _WriteCommand Return _ContrastMax I2cD[0] = $2A: Gosub _WriteCommand ''RE=1 I2cD[0] = $79: Gosub _WriteCommand ''SD=1 I2cD[0] = $81: Gosub _WriteCommand ''コントラストセット I2cD[0] = $FF: Gosub _WriteCommand ''輝度MAX ''標準=$7F I2cD[0] = $78: Gosub _WriteCommand ''SD を0にもどす I2cD[0] = $28: Gosub _WriteCommand ''2C=高文字 28=ノーマル Return _DrawAntLevel If I2cD[1] = 0 Then: I2cD[0] = 0: Gosub _WriteData ElseIf I2cD[1] = 1 Then I2cD[0] = 1: Gosub _WriteData Elseif I2cD[1] >= 2 Then I2cD[0] = 2: Gosub _WriteData If I2cD[1] = 3 Then I2cD[0] = 3: Gosub _WriteData ElseIf I2cD[1] >= 4 Then I2cD[0] = 4: Gosub _WriteData If I2cD[1] >= 5 Then I2cD[0] = 5: Gosub _WriteData EndIf EndIf EndIf Return '' 外字登録 _SetMyChars I2cD[0] = $40 | 0 * $08: Gosub _WriteCommand I2cD[0] = $1C '11100 I2cD[1] = $08 '01000 I2cD[2] = $08 '01000 I2cD[3] = $00 '00000 I2cD[4] = $00 '00000 I2cD[5] = $00 '00000 I2cD[6] = $00 '00000 I2cD[7] = $00 '00000 I2cW I2cD[31],$40, 8: Delay 1 I2cD[0] = $40 | 1 * $08: Gosub _WriteCommand I2cD[0] = $1C '11100 I2cD[1] = $08 '01000 I2cD[2] = $08 '01000 I2cD[3] = $00 '00000 I2cD[4] = $00 '00000 I2cD[5] = $0C '01100 I2cD[6] = $0C '01100 ' I2cD[7] = $00 '00000 I2cW I2cD[31],$40, 8: Delay 1 I2cD[0] = $40 | 2 * $08: Gosub _WriteCommand I2cD[0] = $1C '11100 I2cD[1] = $08 '01000 I2cD[2] = $08 '01000 I2cD[3] = $00 '00000 I2cD[4] = $03 '00011 I2cD[5] = $1B '11011 I2cD[6] = $1B '11011 ' I2cD[7] = $00 '00000 I2cW I2cD[31],$40, 8: Delay 1 I2cD[0] = $40 | 3 * $08: Gosub _WriteCommand I2cD[0] = $00 '00000 I2cD[1] = $00 '00000 I2cD[2] = $00 '00000 I2cD[3] = $18 '11000 I2cD[4] = $18 '11000 I2cD[5] = $18 '11000 I2cD[6] = $18 '11000 ' I2cD[7] = $00 '00000 I2cW I2cD[31],$40, 8: Delay 1 I2cD[0] = $40 | 4 * $08: Gosub _WriteCommand I2cD[0] = $00 '00000 I2cD[1] = $00 '00000 I2cD[2] = $03 '00011 I2cD[3] = $1B '11011 I2cD[4] = $1B '11011 I2cD[5] = $1B '11011 I2cD[6] = $1B '11011 ' I2cD[7] = $00 '00000 I2cW I2cD[31],$40, 8: Delay 1 I2cD[0] = $40 | 5 * $08: Gosub _WriteCommand I2cD[0] = $00 '00000 I2cD[1] = $18 '11000 I2cD[2] = $18 '11000 I2cD[3] = $18 '11000 I2cD[4] = $18 '11000 I2cD[5] = $18 '11000 I2cD[6] = $18 '11000 ' I2cD[7] = $00 '00000 I2cW I2cD[31],$40, 8: Delay 1 Return