Arduino 開発環境のはじめの一歩

Arduinoで動くプログラミング言語は、C++をベースとした「Arduino 言語」というものです。

専用のIDEがあり、「Arduino IDE」と呼ばれます。

今回は、そのセットアップと、ごくごく簡単な、Arduino Uno のボードにあるLEDを光らせてみます。

(GPIOにLEDや抵抗を接続せずとも、ボードにLEDがついていいるので、お試しがすごくやりやすいのもすごくうれしい点です)

 

 

  1. Arduino IDE のインストール(Linux系)

    嬉しいことに、いろいろなOS向けの開発環境が用意されています。

    今回は、Windowsでも、MacOSでもなく、Linux(Mint Linux)で環境を構築します。
    まずは、本家サイトにて、「Arduino  IDE」をダウンロードします。
    WindowsLinuxMac OS X 向けのリンクがあります。
    私の環境では、「Linux 64 bits」となります。
    リンク先にて金銭を要求されているような画面になりますが「JUST DOWNLOAD」リンクで無料ダウンロードできます。
    お金を払ってもいい、という方は、お好みの金額をどうぞ(未確認)

    www.arduino.cc

    バージョン1.8.19では123MBでした。

  2. ダウンロードファイルの解凍
    ダウンロードできたら適当なフォルダ(自分はユーザーフォルダ内のドキュメント)に解凍します。
    解凍できたら「install.sh」を(端末で)実行します。
    すると、メニューの「プログラミング」の下に「Arduino IDE」が増えています。
    起動!!!!
  3. Arduino  IDE の動作確認
    起動すると「sketch_***」なるタブが開かれます。
    Arduino  IDE では、プログラムを「letch」と呼ぶようです。
    購入したArduino Uno をUSBに接続します。
    そして、「Arduino IDE」の「ツール」メニューから、「シリアルボード」で、何か(環境によって変わると思います)を選択しましょう。
    「ボード」で「Arduino Uno」が選択されているのも確認しましょう。

    たくさんサンプルプログラムが用意されていますので、ボードだけで確認できるものを動かしましょう。
    「ファイル」メニューで「スケッチ例」から「01.Nasics」→「Blink」を選びましょう。
    ソースコード(大半がコメント)を見ると何となくわかるかと思いますが、
    ・「setup」メソッドで初期設定:ビルトインのLEDを出力とする
    ・「loop」メソッドで繰り返し実行される処理:1000ミリ秒ごとにビルトインのLEDをON(high)、OFF(low)を実行、繰り返す
    ようなプログラムです。

    では、実行しましょう。
    Arduino  IDE の左上の「✓」アイコンをクリックします。「検証」です。これでコンパイルが実行されます。

    次に、そのとなり、「→」アイコンをクリックします。「マイコンボードに書き込む」です。クリックすると、何か選択しろ、のようなダイアログが出るのでOK。これでプログラムが…あれ?動きません
  4. エラーの確認
    画面下部にエラーメッセージが出ています。
    「Permmission denied」
    どうやら、Arduino Uno に書き込むことができないようです。

  5. バイスへの書き込み権限の設定
    以下のコマンドをターミナルで実行します。
    $ sudo chmod o+r /dev/ttyACM0
    $ sudo chmod o+w /dev/ttyACM0
    ※「/dev/ttyACM0」は、表示されたエラーメッセージを参照してください。

  6. 今度こそ、実行
    上記コマンドで権限を設定したら、「→」を再度クリックします。
    きっと何事もなく、「Arduino Uno」のLEDが、1秒ごとに光る、消えるを繰り返します。


ということで、いわゆる「Hello World」的な、「Lチカ」ができたかと思います。

自分で書かずとも、サンプルがあるので感動も少ないですが、内容を少しいじることで、点滅間隔を変更できたりします。

半導体高騰中

いろいろな世の中の不安定な情勢により、半導体が高騰しております

大好きなRaspberry Pi も、久しぶりに販売価格を見るとびっくりします

 

そこで、比較的安価で購入できる、「Arduino Nano」を購入しました

(互換機ですが)

 

 

Raspberry Pi に比べて安価な分、以下の機能が無かったりします

・基本性能が低い
 Raspberry Pi は安価、性能の低めなPCとして使えますが、Arduino Nano は「マイコン」なので、基本性能はかなり低い

・OSが乗らない

 「マイコン」なので、PC的な使用はできません。簡単に言うと、マウスやキーボード、モニタを接続してネットサーフィン、など

WifiBlueTooth、さらにはカメラが無い

 正確には、USB接続して頑張れば、USBで接続可能な様々な機能が利用できますが、OSやボードの機能として、これらは搭載されていません。カメラ専用の接続端子もありません

 

逆に、安価でシンプルな分、使い方によっては利点もあります

・何より、安い

 しかし、サイズは意外と大きいです。Raspberry Pi (4)と変わらず。乗っている部品点数は少ないですが

・起動が早い

 Raspberry Pi は起動はすなわちOSの起動でしたが、Arduino は電源On直後にプログラムが動き出します

 

Raspberry Pi をPCの劣化版、ArduinoRaspberry Pi の劣化版ととらえてはいけません。

それぞれ、目的などがあってのハードとなっています。

 

以前、Raspberry Pi Zero でドラレコを作ってみました。

画質はそれなりでしたが、起動時間以外は、案外使用できていました。(既製品に置き換えてしまいましたが…)

もしかすると、Arduino を使用することで、起動時間という問題を解決できるかもしれません。

少しずつですが、Arduino でできることを増やしつつ、ドラレコ作成を目標として学習、ご紹介できることを目指していこうと思います。

センサー購入

いろいろと、こまごまとセンサーを購入していましたが、いくつかのセンサーが複数乗っている商品を見つけたので購入してみました

 

 

温度、湿度、気圧と照明センサーがついています

人感センサーもついているようで、このセンサー付近で動きを察知すると、5秒間ほどLEDが光ります(この、光っている間は、付近に動くものがいるという情報が取得できます)

 

Raspberry Pi Zero にてサンプルプログラムを走らせ、動作確認してみましたが、特に不具合もなく使えました

ただし、使用していたケースは使用できなくなります

Raspberry Pi 4 などで、ファンを使用している、もしくはファンが付いたケースを使用する場合は注意が必要と思います(基本、ケースもファンもそのままでは使えない)


GPIOに差し込むだけの簡単設計で、GPIOに指した後も、このボードからピンが伸びているのでとても親切

 

ただ、LEDはちょっとまぶしすぎるかな…(電源のLEDと、人感センサーのLED。ともに真っ赤で目に刺さる明るさです)

OpenCVのインストール(2022/02)

以前にもOpenCVのインストールについて書きましたが、現状、コマンド(インストールするライブラリ)が異なるようで、最新版です。

 

$ pip3 install opencv-python

 

インストールが終わりません

2時間(くらいかな)待った後、エラーとなりました

どうやら、ビルドできないらしい

なので、以下コマンドで

 

$ sudo apt update
$ sudo apt install python3-opencv

 

LCDディスプレイへの各種情報の表示

かなり前にも書きましたが、I2C接続の2行表示のディスプレイに、手持ちのセンサーなどから取得した情報を表示してみます

表示する情報は以下の内容

  • 現在の日付、時間
  • CPU使用率と温度、メモリの使用量と全量
  • ホスト名
  • IPアドレスと、それを保持するインターフェース名
  • 温度と大気圧
  • 温度と湿度


使用した機器です(本体、Raspberry Pi は除く)

 

LCDディスプレイ

いろいろと似たようなものがありますが、手持ちのものと同じものです

 

温度・湿度センサー

手持ちのものと同じものが見つかりませんでしたが、I2C接続できる「SHT3X」という型番で探しました。たぶん、大丈夫

 

温度・大気圧センサー

上の温度センサーの値と、この温度センサーの値が、ちょっと異なるんですよね。1℃くらい。

 

ソースコード

情報を1秒ごとに表示します

以前の内容から、少し変えています

 

from time import sleep
import smbus

class i2c:
    ''' i2cクラス '''
    # i2c オブジェクト
    i2c = None
    # i2c アドレス
    ADR = None
    
    def __init__(self, adr, bus = 1) -> None:
        ''' コンストラクタ '''
        self.ADR = adr
        self.i2c = smbus.SMBus(bus)
    
    def readS8(self, register):
        ''' 符号あり8ビット読込 '''
        result = self.i2c.read_byte_data(self.ADR, register)
        if result > 127:
            # 符号算出
            result -= 256
        return result

    def readS16(self, register):
        ''' 符号あり16ビット読込(アドレス値は指定8ビット と 指定8ビット + 1) '''
        hi = self.readS8(register)
        lo = self.readU8(register+1)
        return (hi << 8) + lo

    def readU8(self, register):
        ''' 符号なし8ビット読込 '''
        result = self.i2c.read_byte_data(self.ADR, register)
        return result

    def readU16(self, register):
        ''' 符号なし16ビット読込(アドレス値は指定8ビット と 指定8ビット + 1) '''
        hi = self.readU8(register)
        lo = self.readU8(register+1)
        return (hi << 8) + lo

    def readBlockData(self, register, blocks):
        ''' 指定ブロック読込 '''
        block = self.i2c.read_i2c_block_data(self.ADR, register, blocks)
        return block
    
    def write8(self, register, value):
        ''' 8ビット書込 '''
        self.i2c.write_byte_data(self.ADR, register, value)
    
    def writeByte(self, value):
        ''' 8ビット書込 '''
        self.i2c.write_byte(self.ADR, value)
    
class SHT3X:
    ''' 温度・湿度センサー '''
    SHT3X_FREQ_MSB           = 0x23
    SHT3X_FREQ_LSB           = 0x34
    SHT3X_READ_MSB           = 0xe0
    SHT3X_READ_LSB           = 0x00
    SHT3X_READ_ADR           = 0x00
    I2C_ADR                  = 0x44
    i2c                      = None   
    
    def __init__(self) -> None:
        ''' コンストラクタ '''
        # i2cオブジェクト
        self.i2c = i2c(self.I2C_ADR)
    
    def calcTemperatureHumidity(self):
        ''' 温度と湿度を算出 '''
        # 測定頻度の設定
        self.i2c.write8(self.SHT3X_FREQ_MSB, self.SHT3X_FREQ_LSB)
        sleep(0.5)
        # 測定値の読出し
        self.i2c.write8(self.SHT3X_READ_MSB, self.SHT3X_READ_LSB)
        sleep(0.5)

        # 6バイト取得
        d = self.i2c.readBlockData(self.SHT3X_READ_ADR, 6)

        # 0~1バイトが温度
        # 測定データ(生データ)を取得
        t = ((d[0]) << 8) | (d[1])
        # 換算する
        t = -45 + (175 * t / 65535)

        # 3~4バイトが湿度
        # 測定データ(生データ)を取得
        h = ((d[3]) << 8) | (d[4])
        # 換算する
        h = 100 * h / 65535

        # 結果を返却
        return t, h

class BMP085:
    ''' 温度・大気圧センサー '''
    BMP085_CAL_AC1           = 0xAA
    BMP085_CAL_AC2           = 0xAC
    BMP085_CAL_AC3           = 0xAE
    BMP085_CAL_AC4           = 0xB0
    BMP085_CAL_AC5           = 0xB2
    BMP085_CAL_AC6           = 0xB4
    BMP085_CAL_B1            = 0xB6
    BMP085_CAL_B2            = 0xB8
    BMP085_CAL_MB            = 0xBA
    BMP085_CAL_MC            = 0xBC
    BMP085_CAL_MD            = 0xBE
    BMP085_CONTROL           = 0xF4
    BMP085_TEMPDATA          = 0xF6
    BMP085_PRESSUREDATA      = 0xF6
    BMP085_READTEMPCMD       = 0x2E
    BMP085_READPRESSURECMD   = 0x34 
    MODE                     = 3
    WAIT_TIME                = [0.005, 0.014, 0.008, 0.026]
    I2C_ADR                  = 0x77
    i2c                      = None   
    
    def __init__(self) -> None:
        ''' コンストラクタ '''
        # i2cオブジェクト
        self.i2c = i2c(self.I2C_ADR)
    def calibration(self):
        ''' キャリブレーション '''
        # キャリブレーションデータ読込
        self.cal_AC1 = self.i2c.readS16(self.BMP085_CAL_AC1)
        self.cal_AC2 = self.i2c.readS16(self.BMP085_CAL_AC2)
        self.cal_AC3 = self.i2c.readS16(self.BMP085_CAL_AC3)
        self.cal_AC4 = self.i2c.readU16(self.BMP085_CAL_AC4)
        self.cal_AC5 = self.i2c.readU16(self.BMP085_CAL_AC5)
        self.cal_AC6 = self.i2c.readU16(self.BMP085_CAL_AC6)
        self.cal_B1 =  self.i2c.readS16(self.BMP085_CAL_B1)
        self.cal_B2 =  self.i2c.readS16(self.BMP085_CAL_B2)
        self.cal_MB =  self.i2c.readS16(self.BMP085_CAL_MB)
        self.cal_MC =  self.i2c.readS16(self.BMP085_CAL_MC)
        self.cal_MD =  self.i2c.readS16(self.BMP085_CAL_MD)

    def readUncpmpensatedTemp(self):
        ''' センサーから温度を取得 '''
        self.i2c.write8(self.BMP085_CONTROL, self.BMP085_READTEMPCMD)
        sleep(0.026)
        raw = self.i2c.readU16(self.BMP085_TEMPDATA)
        return raw

    def readUncpmpensatedPressure(self):
        ''' センサーから気圧を取得 '''
        self.i2c.write8(self.BMP085_CONTROL, self.BMP085_READPRESSURECMD + (self.MODE << 6))
        sleep(self.WAIT_TIME[self.MODE])
        msb = self.i2c.readU8(self.BMP085_PRESSUREDATA)
        lsb = self.i2c.readU8(self.BMP085_PRESSUREDATA+1)
        xlsb = self.i2c.readU8(self.BMP085_PRESSUREDATA+2)
        raw = ((msb << 16) + (lsb << 8) + xlsb) >> (8 - self.MODE)
        return raw
    
    def calcTemperaturePressure(self):
        ''' 温度と気圧を算出 '''
        UT = self.readUncpmpensatedTemp()
        UP = self.readUncpmpensatedPressure()

        X1 = ((UT - self.cal_AC6) * self.cal_AC5) / 32768
        X2 = (self.cal_MC * 2048) / (X1 + self.cal_MD)
        B5 = X1 + X2
        B6 = B5 - 4000
        X1 = (self.cal_B2 * (B6 * B6) / 4096) / 2048
        X2 = (self.cal_AC2 * B6) / 2048
        X3 = X1 + X2

        # 温度を算出しておく
        temp = (B5 + 8) / 16 / 10

        B3 = (((self.cal_AC1 * 4 + X3) * ( 2 ** self.MODE)) + 2) / 4
        X1 = (self.cal_AC3 * B6) / 8192
        X2 = (self.cal_B1 * ((B6 * B6) / 4096)) / 65536
        X3 = ((X1 + X2) + 2) / 4
        B4 = (self.cal_AC4 * (X3 + 32768)) / 32768
        B7 = (UP - B3) * (50000 >> self.MODE)

        if (B7 < 0x80000000):
            press = int((B7 * 2) / B4)
        else:
            press = int((B7 / B4) * 2)
       
        X1 = (press / 256 ) * (press / 256)
        X1 = (X1 * 3038) / 65536
        X2 = (-7357 * press)  / 65536

        press = press + ((X1 + X2 + 3791) / 16)

        return temp, press

class LCD1602:
    ''' LCD '''
    LCD_LINES       = [0x80, 0xC0]
    # LCDの1行目のアドレス
    LCD_LINE_1      = 0x80
    # LCDの2行目のアドレス
    LCD_LINE_2      = 0xC0
    # 1行あたりの文字数
    LCD_WIDTH       = 16
    # バックライトのON/OFF(ON:0X08, OFF:0X00を指定)
    LCD_BACKLIGHT   = 0X08
    LCD_CHR         = 1
    LCD_CMD         = 0
    ENABLE          = 0b00000100
    E_PULSE         = 0.0005
    E_DELAY         = 0.0005
    I2C_ADR         = 0x27
    i2c             = None
    
    def __init__(self) -> None:
        ''' コンストラクタ '''
        # i2cオブジェクト
        self.i2c = i2c(self.I2C_ADR)
    
    def calibration(self):
        ''' キャリブレーション '''
        self.writeByte(0x33, self.LCD_CMD)
        self.writeByte(0x32, self.LCD_CMD)
        self.writeByte(0x06, self.LCD_CMD)
        self.writeByte(0x0C, self.LCD_CMD)
        self.writeByte(0x28, self.LCD_CMD)
        self.writeByte(0x01, self.LCD_CMD)
        sleep(self.E_DELAY)

    def writeByte(self, bits, mode):
        ''' LCDへの書き込み '''
        bits_high = mode | (bits & 0xF0) | self.LCD_BACKLIGHT
        bits_low =  mode | ((bits << 4) & 0xF0) |  self.LCD_BACKLIGHT
        self.i2c.writeByte(bits_high)
        self.writeByteSub(bits_high)
        self.i2c.writeByte(bits_low)
        self.writeByteSub(bits_low)

    def writeByteSub(self, bits):
        ''' LCDへの書き込み(サブ) '''
        sleep(self.E_DELAY)
        self.i2c.writeByte(bits | self.ENABLE)
        sleep(self.E_DELAY)
        self.i2c.writeByte(bits & ~self.ENABLE)
        sleep(self.E_DELAY)
    
    def dispString(self, message: str, dispLine):
        ''' LCDへの文字の表示(半角文字列のみ) '''
        # 表示対象行の初期化
        self.writeByte(self.LCD_LINES[dispLine], self.LCD_CMD)
        # 文字列を1行あたりの文字数に調整
        message = message.ljust(self.LCD_WIDTH)
        # 表示処理
        for dispIndex in range(self.LCD_WIDTH):
            self.writeByte(ord(message[dispIndex]), self.LCD_CHR)

import socket
import psutil
import datetime

class RaspiInfo:
    ''' RaspberryPi情報 '''
    @staticmethod
    def getMemoryInfo():
        ''' メモリ情報(使用量[MB]、総量[MB])の取得 '''
        mem = psutil.virtual_memory()
        mem_used = round(mem.used / 1024 / 1024)
        mem_total = round(mem.total / 1024 / 1024)
        return mem_used, mem_total
    
    @staticmethod
    def getCpuTemp():
        ''' CPU温度の取得 '''
        f = open("/sys/class/thermal/thermal_zone0/temp","r")
        cpu_temp = 0
        for t in f:
            cpu_temp = t[:2]
            # 小数点以下2桁まで表示する場合
            # cpu_temp = t[:2]+"."+t[2:3]
        f.close()
        return cpu_temp

    @staticmethod
    def getCpupercent():
        ''' CPU使用率の取得 '''
        cpu_percent = psutil.cpu_percent(interval=0)
        return round(cpu_percent)
    
    @staticmethod
    def getHostName():
        ''' ホスト名の取得 '''
        host_name = socket.gethostname()
        return host_name

    @staticmethod
    def getIP():
        ''' IPアドレスとインターフェース名を取得 '''
        for interface, snics in psutil.net_if_addrs().items():
            for snic in snics:
                if snic.address != '127.0.0.1' and snic.family == socket.AF_INET:
                    return snic.address, interface
        return "none", "none"

# メイン処理

# LCDの初期化
lcd = LCD1602()
lcd.calibration()

# インスタンス生成
bmp = BMP085()
sht3x = SHT3X()

# 初期化
bmp.calibration()

while True:
    # 現在日時
    now = datetime.datetime.now()
    lcd.dispString(f'date: {now.strftime("%Y/%m/%d")}', 0)
    lcd.dispString(f'time: {now.strftime("%H:%M:%S")}', 1)
    sleep(1)

    # 「CPU温度」「CPU使用率」と「メモリ情報」
    mem_info = RaspiInfo.getMemoryInfo()
    lcd.dispString(f'cpu : {RaspiInfo.getCpuTemp()}\337C {RaspiInfo.getCpupercent()}%', 0)    
    lcd.dispString(f'mem : {mem_info[0]}/{mem_info[1]}MB', 1)
    sleep(1)

    # ホスト名
    hostName = RaspiInfo.getHostName()
    lcd.dispString(f'host:', 0)
    lcd.dispString(f' {hostName}', 1)
    sleep(1)

    # IPアドレス
    ip = RaspiInfo.getIP()
    lcd.dispString(f'ip  :', 0)
    lcd.dispString(f'{str(ip[1])}:', 0)
    lcd.dispString(f' {ip[0]}', 1)
    sleep(1)

    # 温度と大気圧(次の取得処理中でスリープしているので、ここでの表示後のスリープはしない)
    tempPress = bmp.calcTemperaturePressure()
    lcd.dispString(f'temp: {str(tempPress[0])[:5]}\337C', 0)
    lcd.dispString(f'prss: {str(tempPress[1] / 100.0 )[:6]} hPa', 1)

    # 温度と湿度
    ht = sht3x.calcTemperatureHumidity()
    lcd.dispString(f'temp: {str(ht[0])[:5]}\337C', 0)
    lcd.dispString(f'humi: {str(ht[1])[:5]}%', 1)
    sleep(1)

大気圧センサー(BMP180)

工具箱をあさったら、I2C接続で使用できる大気圧センサーを見つけたので使用してみようかと思います

 

まずはモノ。単品でも、キットに付属でも入手できそうです



データシートです

これをある程度読み取れれば、使用可能です

https://www.sparkfun.com/datasheets/Components/General/BST-BMP085-DS000-05.pdf

 

サンプルプログラムです。

公式(?)のものも見つかりますが、動かなかったので手を入れています

このセンサーは温度センサーもついており、大気圧の算出に、その温度センサーの値も使用します

1秒ごとにセンサーから読み取り、温度と気圧をprintしてみているだけです

なお、1クラス1ファイルにする慣習があるようですが、このサンプルは2クラスと実行ルーチンを1ファイルにしてしまっています(適宜分けてもOK)

from time import sleep
import smbus

''' i2cクラス '''
class i2c:
    # i2c オブジェクト
    i2c = None
    # i2c アドレス
    ADR = None
    
    ''' コンストラクタ '''
    def __init__(self, adr, bus = 1) -> None:
        self.ADR = adr
        self.i2c = smbus.SMBus(bus)

    ''' 符号あり8ビット読込 '''
    def readS8(self, register):
        result = self.i2c.read_byte_data(self.ADR, register)
        if result > 127:
            # 符号算出
            result -= 256
        return result

    ''' 符号あり16ビット読込(アドレス値は指定8ビット と 指定8ビット + 1) '''
    def readS16(self, register):
        hi = self.readS8(register)
        lo = self.readU8(register+1)
        return (hi << 8) + lo

    ''' 符号なし8ビット読込 '''
    def readU8(self, register):
        result = self.i2c.read_byte_data(self.ADR, register)
        return result

    ''' 符号なし16ビット読込(アドレス値は指定8ビット と 指定8ビット + 1) '''
    def readU16(self, register):
        hi = self.readU8(register)
        lo = self.readU8(register+1)
        return (hi << 8) + lo

    ''' 指定ブロック読込 '''
    def readBlockData(self, register, blocks):
        block = self.i2c.read_i2c_block_data(self.ADR, register, blocks)
        return block

    ''' 8ビット書込 '''
    def write8(self, register, value):
        self.i2c.write_byte_data(self.ADR, register, value)

    ''' 8ビット書込 '''
    def writeByte(self, value):
        self.i2c.write_byte(self.ADR, value)
    
class BMP085:
    BMP085_CAL_AC1           = 0xAA
    BMP085_CAL_AC2           = 0xAC
    BMP085_CAL_AC3           = 0xAE
    BMP085_CAL_AC4           = 0xB0
    BMP085_CAL_AC5           = 0xB2
    BMP085_CAL_AC6           = 0xB4
    BMP085_CAL_B1            = 0xB6
    BMP085_CAL_B2            = 0xB8
    BMP085_CAL_MB            = 0xBA
    BMP085_CAL_MC            = 0xBC
    BMP085_CAL_MD            = 0xBE
    BMP085_CONTROL           = 0xF4
    BMP085_TEMPDATA          = 0xF6
    BMP085_PRESSUREDATA      = 0xF6
    BMP085_READTEMPCMD       = 0x2E
    BMP085_READPRESSURECMD   = 0x34
    MODE                     = 3
    WAIT_TIME                = [0.005, 0.014, 0.008, 0.026]
    I2C_ADR                  = 0x77
    i2c                      = None   

    ''' コンストラクタ '''
    def __init__(self) -> None:
        # i2cオブジェクト
        self.i2c = i2c(self.I2C_ADR)

    ''' キャリブレーション '''
    def calibration(self):
        # キャリブレーションデータ読込
        self.cal_AC1 = self.i2c.readS16(self.BMP085_CAL_AC1)
        self.cal_AC2 = self.i2c.readS16(self.BMP085_CAL_AC2)
        self.cal_AC3 = self.i2c.readS16(self.BMP085_CAL_AC3)
        self.cal_AC4 = self.i2c.readU16(self.BMP085_CAL_AC4)
        self.cal_AC5 = self.i2c.readU16(self.BMP085_CAL_AC5)
        self.cal_AC6 = self.i2c.readU16(self.BMP085_CAL_AC6)
        self.cal_B1 =  self.i2c.readS16(self.BMP085_CAL_B1)
        self.cal_B2 =  self.i2c.readS16(self.BMP085_CAL_B2)
        self.cal_MB =  self.i2c.readS16(self.BMP085_CAL_MB)
        self.cal_MC =  self.i2c.readS16(self.BMP085_CAL_MC)
        self.cal_MD =  self.i2c.readS16(self.BMP085_CAL_MD)

    ''' センサーから温度を取得 '''
    def readUncpmpensatedTemp(self):
        self.i2c.write8(self.BMP085_CONTROL, self.BMP085_READTEMPCMD)
        sleep(0.026)
        raw = self.i2c.readU16(self.BMP085_TEMPDATA)
        return raw

    ''' センサーから気圧を取得 '''
    def readUncpmpensatedPressure(self):
        self.i2c.write8(self.BMP085_CONTROL, self.BMP085_READPRESSURECMD + (self.MODE << 6))
        sleep(self.WAIT_TIME[self.MODE])
        msb = self.i2c.readU8(self.BMP085_PRESSUREDATA)
        lsb = self.i2c.readU8(self.BMP085_PRESSUREDATA+1)
        xlsb = self.i2c.readU8(self.BMP085_PRESSUREDATA+2)
        raw = ((msb << 16) + (lsb << 8) + xlsb) >> (8 - self.MODE)

        return raw

    ''' 温度と気圧を算出 '''
    def calcTemperaturePressure(self):
        UT = self.readUncpmpensatedTemp()
        UP = self.readUncpmpensatedPressure()

        X1 = ((UT - self.cal_AC6) * self.cal_AC5) / 32768
        X2 = (self.cal_MC * 2048) / (X1 + self.cal_MD)
        B5 = X1 + X2
        B6 = B5 - 4000
        X1 = (self.cal_B2 * (B6 * B6) / 4096) / 2048
        X2 = (self.cal_AC2 * B6) / 2048
        X3 = X1 + X2

        # 温度を算出しておく
        temp = (B5 + 8) / 16 / 10

        B3 = (((self.cal_AC1 * 4 + X3) * ( 2 ** self.MODE)) + 2) / 4
        X1 = (self.cal_AC3 * B6) / 8192
        X2 = (self.cal_B1 * ((B6 * B6) / 4096)) / 65536
        X3 = ((X1 + X2) + 2) / 4
        B4 = (self.cal_AC4 * (X3 + 32768)) / 32768
        B7 = (UP - B3) * (50000 >> self.MODE)

        if (B7 < 0x80000000):
            press = int((B7 * 2) / B4)
        else:
            press = int((B7 / B4) * 2)
       
        X1 = (press / 256 ) * (press / 256)
        X1 = (X1 * 3038) / 65536
        X2 = (-7357 * press)  / 65536

        press = press + ((X1 + X2 + 3791) / 16)

        return temp, press

# インスタンス生成
bmp = BMP085()
# 初期化
bmp.calibration()

while True:
    # 気温と気圧を取得
    tempPress = bmp.calcTemperaturePressure()

    # 表示
    print(f'temp: {str(tempPress[0])[:5]} C')
    print(f'prss: {str(tempPress[1] / 100.0 )[:6]} hPa')

    sleep(1)

Visual Studio Code でのリモート

恐らくは、以前書いた内容とほとんど変わらないと思いますが、Raspberry Pi OS を64bitのものにしたため、再度環境を構築しようと思います

結果、32bitともちょっと前で構築した順序とも変わりませんでした

 

 

WindowsPCにVisual Studio Code をインストール

公式ページからダウンロードします。無料。素晴らしい

azure.microsoft.com

インストールしたVisual Studio Code の設定

各設定を行います

日本語化

 Visual Studio Code を起動し、画面左の縦にアイコンが並んでいるうちの一番下(Extensions)をクリック、検索窓に「japanese」と入力して表示される「Japanese Language」をクリック、インストールします。インストール後、(Visual Studio Codeの)再起動(Restart)を促されるので、再起動、日本語化されます

f:id:kobatom5278:20220208094718j:plain

SSH接続 拡張機能などのインストール

これも同様。検索窓に「remote」と入力し、表示される「Remote Development」をインストールします

f:id:kobatom5278:20220208115937j:plain

SSH接続設定

あらかじめ、Raspberry Pi のほうはSSH接続を有効にしてください。
そのうえで、Visual Studio Code からSSH接続をします。

Visual Studio Code を起動、「F1」キーを押すと、画面上部中央に「コマンドパレット」が表示されます。ここから、「Remote - SSH: Connect To Host...」を選択します

f:id:kobatom5278:20220208101216j:plain

「+ Add New SSH Host...」を選択

f:id:kobatom5278:20220208101313j:plain

「Raspberry  Pi」のユーザー名 @ 「Raspberry  Pi」のホスト名を入力、「Enter」

コマンドラインなどからSSH接続をしたことがある場合は、設定ファイルを上書きするか聞かれます)

f:id:kobatom5278:20220208101419j:plain

成功すると、右下に通知が表示されます。「Connect」をクリックします

f:id:kobatom5278:20220208101635j:plain

新しいウィンドウが開き、OS種別を聞かれます。「Linux」でよいですね

f:id:kobatom5278:20220208101753j:plain

パスワードを聞かれますので、入力(指定したRaspberry Pi のユーザーのパスワードです)

f:id:kobatom5278:20220208101844j:plain

パスワードが正しければ、画面左のアイコン中の「リモート エクスプローラ」に、指定したホスト名が表示されているはずです

f:id:kobatom5278:20220208102013j:plain

SSH接続してみる

リモートエクスプローラから、Raspberry Pi を右クリック、「~Current Window」を選択します。パスワードを聞かれるので入力

f:id:kobatom5278:20220208103045j:plain

続いて、画面左のアイコンの一番上「エクスプローラ」をクリック、「フォルダーを開く」をクリック

f:id:kobatom5278:20220208103300j:plain

パスワードなどを聞かれるので適宜入力すると、Raspberry Pi 状のユーザーディレクトリが表示されます。これで接続は完了です

Python 拡張機能のインストール

Raspberry Pi のユーザーディレクトリ中に、中身は空でいいので拡張子が「.py」のファイルを作成、「F5」キーを押します

すると、拡張機能が無いとのエラーになります

f:id:kobatom5278:20220208104722j:plain

そこで、「Python 拡張機能」をインストールします
表示されたエラーメッセージの「Python 拡張機能の検索」をクリック
表示された「Python」をインストールします

f:id:kobatom5278:20220208104842j:plain

インストールが終了したら、先ほど作成した拡張子が「.py」に戻り、「F5」キーを押します。すると、「select a debug configulation」と聞かれるので、「Python File」を選択します

f:id:kobatom5278:20220208120838j:plain

エラーなければ正常です
内容が空であれば、何も起きません