ADコンバータ(SX8725C)をRaspberry Pi PicoWで動かすコードをChatGPTに修正してもらった

[以前書いたADコンバータを動かすやつ](https://qiita.com/pinkych24/items/cb6e353adf2e33d29a99)の使い勝手が悪かったので直すついでにChatGPTに添削してもらいました。

# 書いたやつ
```SX8725C.py
import machine,math,utime

class SX8725C:
    def __init__(self, i2c_addr=0x48, i2c_id=0, sda_pin=0, scl_pin=1, freq=100000):
        self.id = i2c_id
        self.sda = sda_pin
        self.scl = scl_pin
        self.i2c = machine.I2C(id=i2c_id, sda=machine.Pin(sda_pin), scl=machine.Pin(scl_pin), freq=freq)
        self.addr = i2c_addr
        self.reg_map = [0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x70]
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        
        # Default settings
        self.set_adc = "on"
        self.set_pga1 = "on"
        self.set_pga2 = "on"
        self.set_pga3 = "off"
        self.set_pga1_gain = 10 # 1, 10
        self.set_pga2_gain = 5 # 1, 2, 5, 10
        self.set_pga3_gain = 12 # 0/12 to 32/12
        self.analog_input_VinP = "AC2"
        self.analog_input_VinN = "AC3"
        self.sampling_param_fs = 500
        self.sampling_param_osr = 1024
        self.sampling_param_nelconv = 8
        self.reg_mode_chopper = "Nelconv"
        self.reg_mode_MultForceOn = "off"
        self.reg_mode_MultForceOff = "off"
        self.vref_Vmux = "Vbgd1"
        self.vref_VrefD0Out = "off"
        self.vref_VrefD1In = "off"
        self.vref_vref = 1.22
        self.start_cont_start = 1
        self.start_cont_cont = 1
        self.o2_zero = 0.0
        self.o2_span_air = 0.0
        self.o2_span_o2 = 0.0
        # Initialize
        self._load_calibration_values()
        self._initialize_device()
        
        
    def _load_calibration_values(self):
        self.o2_zero = self._read_calibration_file('o2_zero.txt', self.o2_zero)
        self.o2_span_air = self._read_calibration_file('o2_span_air.txt', self.o2_span_air)
        self.o2_span_o2 = self._read_calibration_file('o2_span_o2.txt', self.o2_span_o2)
    
    @staticmethod
    def _read_calibration_file(filename, default):
        try:
            with open(filename) as f:
                return float(f.read())
        except:
            return default
    
    def _initialize_device(self):
        self.enable_adc_pga(adc=self.set_adc, pga1=self.set_pga1, pga2=self.set_pga2, pga3=self.set_pga3)
        self.set_analog_input(VinP=self.analog_input_VinP, VinN=self.analog_input_VinN)
        self.set_pga_gain(pga1=self.set_pga1_gain, pga2=self.set_pga2_gain, pga3=self.set_pga3_gain)
        self.set_sampling_params(fs=self.sampling_param_fs, osr=self.sampling_param_osr, nelconv=self.sampling_param_nelconv)
        self.set_reg_mode(chopper=self.reg_mode_chopper, MultForceOn=self.reg_mode_MultForceOn, MultForceOff=self.reg_mode_MultForceOff)
        self.set_vref(Vmux=self.vref_Vmux, VrefD0Out=self.vref_VrefD0Out, VrefD1In=self.vref_VrefD1In, Vref=self.vref_vref)
        self.set_start_cont(start=self.start_cont_start, cont=self.start_cont_cont)
        
    
    def load_reg_params(self):
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        dict_str = {hex(reg):'{:08b}'.format(value[0]) for reg, value in sx8725c.reg_params.items()}
        return dict_str
    
    @staticmethod
    def view_8bit(value_bytes):
        value_bytes = int.from_bytes(value, "big")
        print("raw: ",value, type(value))
        value = '{:08b}'.format(value)
        print("8bit: ",value, type(value))
    
    @staticmethod
    def set_bit(byte_value, bit_position, bit_value):#e.g. self.set_bit(RegACCfg1, 0, 1)
        byte_list = bytearray(byte_value)
        if bit_value:
            byte_list[0] |= (1 << bit_position)
        else:
            byte_list[0] &= ~(1 << bit_position)
        return bytes(byte_list)
    
    @staticmethod
    def set_bit_range(byte_value, start_bit, end_bit, new_value):#e.g. self.set_bit_range(RegACCfg5,1,5,0b10001)
        mask = ((1 << (end_bit - start_bit + 1)) - 1) << start_bit
        new_value &= ((1 << (end_bit - start_bit + 1)) - 1)
        return bytes([(byte_value[0] & ~mask) | (new_value << start_bit)])
    
    def enable_adc_pga(self, adc="on", pga1="off", pga2="off", pga3="off"):
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        RegACCfg1 = self.reg_params[0x53]

        if adc == "on":
            RegACCfg1 = self.set_bit(RegACCfg1, 0, 1)
        elif adc == "off":
            RegACCfg1 = self.set_bit(RegACCfg1, 0, 0)
            
        if pga1 == "on":
            RegACCfg1 = self.set_bit(RegACCfg1, 1, 1)
        elif pga1 == "off":
            RegACCfg1 = self.set_bit(RegACCfg1, 1, 0)
            
        if pga2 == "on":
            RegACCfg1 = self.set_bit(RegACCfg1, 2, 1)
        elif pga2 == "off":
            RegACCfg1 = self.set_bit(RegACCfg1, 2, 0)
            
        if pga3 == "on":
            RegACCfg1 = self.set_bit(RegACCfg1, 3, 1)
        elif pga3 == "off":
            RegACCfg1 = self.set_bit(RegACCfg1, 3, 0)

        self.i2c.writeto_mem(self.addr, 0x53, RegACCfg1)
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        self.set_adc = adc
        self.set_pga1 = pga1
        self.set_pga2 = pga2
        self.set_pga3 = pga3
    
    def set_pga_gain(self,pga1=1,pga2=1,pga3=12):
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        RegACCfg2 = self.reg_params[0x54]
        RegACCfg3 = self.reg_params[0x55]
        
        if pga1 == 1:
            RegACCfg3 = self.set_bit(RegACCfg3, 7, 0)
            self.pga1_gain = 1
        elif pga1 == 10:
            RegACCfg3 = self.set_bit(RegACCfg3, 7, 1)
            self.pga1_gain = 10
        
        if pga2 == 1:
            RegACCfg2 = self.set_bit_range(RegACCfg2,4,5,0b00)
            self.pga2_gain = 1
        elif pga2 == 2:
            RegACCfg2 = self.set_bit_range(RegACCfg2,4,5,0b01)
            self.pga2_gain = 2
        elif pga2 == 5:
            RegACCfg2 = self.set_bit_range(RegACCfg2,4,5,0b10)
            self.pga2_gain = 5
        elif pga2 == 10:
            RegACCfg2 = self.set_bit_range(RegACCfg2,4,5,0b11)
            self.pga2_gain = 10
        
        if 0 <= pga3 <= 32:
            RegACCfg3 = self.set_bit_range(RegACCfg3,0,6,pga3)
            self.pga3_gain = pga3
        
        self.i2c.writeto_mem(self.addr, 0x54, RegACCfg2)
        self.i2c.writeto_mem(self.addr, 0x55, RegACCfg3)
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        self.set_pga1_gain = pga1
        self.set_pga2_gain = pga2
        self.set_pga3_gain = pga3
    
    def set_analog_input(self,VinP="AC3",VinN="AC2"):
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        RegACCfg5 = self.reg_params[0x57]
        
        if VinP == "AC3":
            if VinN == "AC2":
                RegACCfg5 = self.set_bit_range(RegACCfg5,1,5,0b00001)
            elif VinN == "AC0":
                RegACCfg5 = self.set_bit_range(RegACCfg5,1,5,0b10011)
        elif VinP == "AC2":
            if VinN == "AC3":
                RegACCfg5 = self.set_bit_range(RegACCfg5,1,5,0b01001)
            elif VinP == "AC0":
                RegACCfg5 = self.set_bit_range(RegACCfg5,1,5,0b10010)
        elif VinP == "AC1":
            if VinN == "AC0":
                RegACCfg5 = self.set_bit_range(RegACCfg5,1,5,0b10001)
        
        self.i2c.writeto_mem(self.addr, 0x57, RegACCfg5)
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        self.analog_input_VinP = VinP
        self.analog_input_VinN = VinN
    
    def set_sampling_params(self,fs=62.5,osr=32,nelconv=2):
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        RegACCfg0 = self.reg_params[0x52]
        RegACCfg2 = self.reg_params[0x54]
        
        if fs == 62.5:
            RegACCfg2 = self.set_bit_range(RegACCfg2,6,7,0b00)
        elif fs == 125:
            RegACCfg2 = self.set_bit_range(RegACCfg2,6,7,0b01)
        elif fs == 250:
            RegACCfg2 = self.set_bit_range(RegACCfg2,6,7,0b10)
        elif fs == 500:
            RegACCfg2 = self.set_bit_range(RegACCfg2,6,7,0b11)
        
        if isinstance(osr, int) and 0 < osr and (osr & (osr - 1)) == 0:
            if 8 <= osr <= 1024:
                reg = int(math.log2(osr))-3
                RegACCfg0 = self.set_bit_range(RegACCfg0,2,4,reg)
        
        if isinstance(nelconv, int) and 0 < nelconv and (nelconv & (nelconv - 1)) == 0:
            if 1 <= nelconv <= 8:
                reg = int(math.log2(nelconv))
                RegACCfg0 = self.set_bit_range(RegACCfg0,5,6,reg)
        
        self.i2c.writeto_mem(self.addr, 0x52, RegACCfg0)
        self.i2c.writeto_mem(self.addr, 0x54, RegACCfg2)
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        self.sampling_param_fs = fs
        self.sampling_param_osr = osr
        self.sampling_param_nelconv = nelconv
        
    def set_reg_mode(self,chopper="state1",MultForceOn="off",MultForceOff="off"):
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        RegMode = self.reg_params[0x70]
        
        if chopper == "state0":
            RegMode = self.set_bit_range(RegMode,4,5,0b00)
        elif chopper == "state1":
            RegMode = self.set_bit_range(RegMode,4,5,0b01)
        elif chopper == "Nelconv":
            RegMode = self.set_bit_range(RegMode,4,5,0b10)
        elif chopper == "Nelconv/2":
            RegMode = self.set_bit_range(RegMode,4,5,0b11)
        
        if MultForceOn == "off":
            RegMode = self.set_bit(RegMode,3,0)
        elif MultForceOn == "on":
            RegMode = self.set_bit(RegMode,3,1)
        
        if MultForceOff == "off":
            RegMode = self.set_bit(RegMode,2,0)
        elif MultForceOff == "on":
            RegMode = self.set_bit(RegMode,2,1)
        
        self.i2c.writeto_mem(self.addr, 0x70, RegMode)
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        self.reg_mode_chopper = chopper
        self.reg_mode_MultForceOn = MultForceOn
        self.reg_mode_MultForceOff = MultForceOff
    
    def set_vref(self,Vmux="Vbgd1",VrefD0Out="off",VrefD1In="off",Vref=1.22):
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        RegACCfg5 = self.reg_params[0x57]
        RegMode = self.reg_params[0x70]
                
        if Vmux == "Vbgd1":
            RegACCfg5 = self.set_bit(RegACCfg5,0,1)
        elif Vmux == "Vbatt":
            RegACCfg5 = self.set_bit(RegACCfg5,0,0)
        if VrefD0Out == "off":
            RegMode = self.set_bit(RegMode,1,0)
        elif VrefD0Out == "on":
            RegMode = self.set_bit(RegMode,1,1)
        if VrefD1In == "off":
            RegMode = self.set_bit(RegMode,0,0)
        elif VrefD1In == "on":
            RegMode = self.set_bit(RegMode,0,1)
        
        self.i2c.writeto_mem(self.addr, 0x57, RegACCfg5)
        self.i2c.writeto_mem(self.addr, 0x70, RegMode)
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        self.vref_Vmux = Vmux
        self.vref_VrefD0Out = VrefD0Out
        self.vref_VrefD1In = VrefD1In
        self.vref_vref = Vref
    
    def set_start_cont(self,start=1,cont=1):
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        RegACCfg0 = self.reg_params[0x52]
        
        if start == 0:
            RegACCfg0 = self.set_bit(RegACCfg0,7,0)
        elif start == 1:
            RegACCfg0 = self.set_bit(RegACCfg0,7,1)
        if cont == 0:
            RegACCfg0 = self.set_bit(RegACCfg0,1,0)
        elif cont == 1:
            RegACCfg0 = self.set_bit(RegACCfg0,1,1)
        
        self.i2c.writeto_mem(self.addr, 0x52, RegACCfg0)
        self.reg_params = {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
    
    def read_raw(self):
        lsb = self.i2c.readfrom_mem(self.addr,0x50,1)
        msb = self.i2c.readfrom_mem(self.addr,0x51,1)
        x = (msb[0]<<8)|lsb[0]
        x = (-(x&32768)|(x&32767))
        return x
    
    def read(self):
        # convert to mV
        val = self.read_raw()
        val = val * 1000 * (self.vref_vref/65535)
        if self.set_pga1 == "on":
            val = val/self.set_pga1_gain
        if self.set_pga2 == "on":
            val = val/self.set_pga2_gain
        if self.set_pga3 == "on":
            val = val/(self.set_pga3_gain/12)
        
        return val
    
    # convert value
    def conv_o2_val(self,buf):
        if self.o2_span_air > buf:
            val = round(((20.95-0)/(self.o2_span_air-self.o2_zero))*(buf-self.o2_zero)+0,2)
        else:
            val = round(((100-20.95)/(self.o2_span_o2-self.o2_span_air))*(buf-self.o2_span_air)+20.95,2)
        return val
    
    def read_o2(self):
        buf = self.read()
        val = self.conv_o2_val(buf)
        return val



### TEST CODE ###
# SX8725Cのインスタンス化
sx8725c = SX8725C(i2c_id=1, sda_pin=18, scl_pin=19)
print("Register parameters:")
[print(hex(reg), ":", '{:08b}'.format(value[0])) for reg, value in sx8725c.reg_params.items()]
print("_______________________________________________________________")

print("start test roop")
try:
    raw = 0
    val = 0
    conv = 0
    while True:
        raw = sx8725c.read_raw()
        val = sx8725c.read()
        conv = sx8725c.read_o2()
        print(raw,val,conv)
        utime.sleep(2)
except KeyboardInterrupt:
    pass
```

ChatGPTによる指摘が以下
> # 問題点
>1. デフォルト設定の論理:
>* self.set_adc, self.set_pga1, self.set_pga2, self.set_pga3 などの変数が設定されているが、実際にこれらの変数がどのように使用されるかが曖昧です。
>* デフォルトの設定が enable_adc_pga メソッドで初期化されていますが、インスタンスの生成時にこれが実際に適用されることが保証されていないように見えます。
>2. メソッドの一貫性:
>* メソッドの名前や引数が一貫していないため、理解しにくくなっています。
>* 例えば、set_pga_gain メソッドで self.pga1_gain と self.set_pga1_gain が混在しています。
>3. I2C通信のエラーハンドリング:
>* I2C通信時のエラーハンドリングが不足しているため、エラーが発生した場合に適切に対応できません。
>4. 計算ロジックの一貫性:
>* read メソッドの計算ロジックが複雑で、一貫していないように見えます。
>* 例えば、PGAの設定に応じて計算が異なるが、その処理が明確でない。
> # 改善点
>1. デフォルト設定の適用:
>* インスタンス生成時にデフォルト設定が確実に適用されるように、初期化メソッドで呼び出す。
>2. メソッドの一貫性と明確化:
>* メソッドの名前や引数を一貫させ、コードの可読性を向上させる。
>3. I2C通信のエラーハンドリング追加:
>* I2C通信時のエラーハンドリングを追加し、エラー発生時に適切に対応できるようにする。
>4. 計算ロジックの明確化:
>* 計算ロジックを明確にし、コメントを追加して処理内容を理解しやすくする。
>以下は、改善されたコードです：

```SX8725C.py
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/271465/a5ce22cd-1416-2b96-af31-1708c6ae466f.png)
import machine, math, utime

class SX8725C:
    def __init__(self, i2c_addr=0x48, i2c_id=0, sda_pin=0, scl_pin=1, freq=100000):
        self.id = i2c_id
        self.sda = sda_pin
        self.scl = scl_pin
        self.i2c = machine.I2C(id=i2c_id, sda=machine.Pin(sda_pin), scl=machine.Pin(scl_pin), freq=freq)
        self.addr = i2c_addr
        self.reg_map = [0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x70]
        self.reg_params = self._load_reg_params()
        
        # Default settings
        self.adc_enabled = "on"
        self.pga1_enabled = "on"
        self.pga2_enabled = "on"
        self.pga3_enabled = "off"
        self.pga1_gain = 10 # 1, 10
        self.pga2_gain = 5 # 1, 2, 5, 10
        self.pga3_gain = 12 # 0/12 to 32/12
        self.analog_input_vinp = "AC2"
        self.analog_input_vinn = "AC3"
        self.sampling_fs = 500
        self.sampling_osr = 1024
        self.sampling_nelconv = 8
        self.reg_mode_chopper = "Nelconv"
        self.reg_mode_multforceon = "off"
        self.reg_mode_multforceoff = "off"
        self.vref_vmux = "Vbgd1"
        self.vref_vrefd0out = "off"
        self.vref_vrefd1in = "off"
        self.vref_value = 1.22
        self.start_continuous = 1
        self.start_enabled = 1
        self.o2_zero = 0.0
        self.o2_span_air = 0.0
        self.o2_span_o2 = 0.0

        # Initialize
        self._load_calibration_values()
        self._initialize_device()

    def _load_calibration_values(self):
        self.o2_zero = self._read_calibration_file('o2_zero.txt', self.o2_zero)
        self.o2_span_air = self._read_calibration_file('o2_span_air.txt', self.o2_span_air)
        self.o2_span_o2 = self._read_calibration_file('o2_span_o2.txt', self.o2_span_o2)

    @staticmethod
    def _read_calibration_file(filename, default):
        try:
            with open(filename) as f:
                return float(f.read())
        except Exception as e:
            print(f"Error reading {filename}: {e}")
            return default

    def _initialize_device(self):
        self.enable_adc_pga(adc=self.adc_enabled, pga1=self.pga1_enabled, pga2=self.pga2_enabled, pga3=self.pga3_enabled)
        self.set_analog_input(vinp=self.analog_input_vinp, vinn=self.analog_input_vinn)
        self.set_pga_gain(pga1=self.pga1_gain, pga2=self.pga2_gain, pga3=self.pga3_gain)
        self.set_sampling_params(fs=self.sampling_fs, osr=self.sampling_osr, nelconv=self.sampling_nelconv)
        self.set_reg_mode(chopper=self.reg_mode_chopper, multforceon=self.reg_mode_multforceon, multforceoff=self.reg_mode_multforceoff)
        self.set_vref(vmux=self.vref_vmux, vrefd0out=self.vref_vrefd0out, vrefd1in=self.vref_vrefd1in, vref=self.vref_value)
        self.set_start_continuous(start=self.start_enabled, cont=self.start_continuous)

    def _load_reg_params(self):
        try:
            return {reg: self.i2c.readfrom_mem(self.addr, reg, 1) for reg in self.reg_map}
        except Exception as e:
            print(f"Failed to load register parameters: {e}")
            return {reg: bytes([0]) for reg in self.reg_map}

    def load_reg_params(self):
        self.reg_params = self._load_reg_params()
        dict_str = {hex(reg): '{:08b}'.format(value[0]) for reg, value in self.reg_params.items()}
        return dict_str

    @staticmethod
    def set_bit(byte_value, bit_position, bit_value):
        byte_list = bytearray(byte_value)
        if bit_value:
            byte_list[0] |= (1 << bit_position)
        else:
            byte_list[0] &= ~(1 << bit_position)
        return bytes(byte_list)

    @staticmethod
    def set_bit_range(byte_value, start_bit, end_bit, new_value):
        mask = ((1 << (end_bit - start_bit + 1)) - 1) << start_bit
        new_value &= ((1 << (end_bit - start_bit + 1)) - 1)
        return bytes([(byte_value[0] & ~mask) | (new_value << start_bit)])

    def enable_adc_pga(self, adc="on", pga1="off", pga2="off", pga3="off"):
        self.reg_params = self._load_reg_params()
        reg_accfg1 = self.reg_params[0x53]

        reg_accfg1 = self.set_bit(reg_accfg1, 0, adc == "on")
        reg_accfg1 = self.set_bit(reg_accfg1, 1, pga1 == "on")
        reg_accfg1 = self.set_bit(reg_accfg1, 2, pga2 == "on")
        reg_accfg1 = self.set_bit(reg_accfg1, 3, pga3 == "on")

        self.i2c.writeto_mem(self.addr, 0x53, reg_accfg1)
        self.reg_params = self._load_reg_params()
        self.adc_enabled = adc
        self.pga1_enabled = pga1
        self.pga2_enabled = pga2
        self.pga3_enabled = pga3

    def set_pga_gain(self, pga1=1, pga2=1, pga3=12):
        self.reg_params = self._load_reg_params()
        reg_accfg2 = self.reg_params[0x54]
        reg_accfg3 = self.reg_params[0x55]

        reg_accfg3 = self.set_bit(reg_accfg3, 7, pga1 == 10)
        self.pga1_gain = 10 if pga1 == 10 else 1

        reg_accfg2 = self.set_bit_range(reg_accfg2, 4, 5, self._gain_to_bits(pga2))
        self.pga2_gain = pga2

        if 0 <= pga3 <= 32:
            reg_accfg3 = self.set_bit_range(reg_accfg3, 0, 6, pga3)
            self.pga3_gain = pga3

        self.i2c.writeto_mem(self.addr, 0x54, reg_accfg2)
        self.i2c.writeto_mem(self.addr, 0x55, reg_accfg3)
        self.reg_params = self._load_reg_params()
        self.pga1_gain = pga1
        self.pga2_gain = pga2
        self.pga3_gain = pga3

    def set_analog_input(self, vinp="AC3", vinn="AC2"):
        self.reg_params = self._load_reg_params()
        reg_accfg5 = self.reg_params[0x57]

        reg_accfg5 = self.set_bit_range(reg_accfg5, 1, 5, self._analog_input_to_bits(vinp, vinn))

        self.i2c.writeto_mem(self.addr, 0x57, reg_accfg5)
        self.reg_params = self._load_reg_params()
        self.analog_input_vinp = vinp
        self.analog_input_vinn = vinn

    def set_sampling_params(self, fs=62.5, osr=32, nelconv=2):
        self.reg_params = self._load_reg_params()
        reg_accfg0 = self.reg_params[0x52]
        reg_accfg2 = self.reg_params[0x54]

        reg_accfg2 = self.set_bit_range(reg_accfg2, 6, 7, self._fs_to_bits(fs))
        reg_accfg0 = self.set_bit_range(reg_accfg0, 2, 4, self._osr_to_bits(osr))
        reg_accfg0 = self.set_bit_range(reg_accfg0, 5, 6, self._nelconv_to_bits(nelconv))

        self.i2c.writeto_mem(self.addr, 0x52, reg_accfg0)
        self.i2c.writeto_mem(self.addr, 0x54, reg_accfg2)
        self.reg_params = self._load_reg_params()
        self.sampling_fs = fs
        self.sampling_osr = osr
        self.sampling_nelconv = nelconv

    def set_reg_mode(self, chopper="state1", multforceon="off", multforceoff="off"):
        self.reg_params = self._load_reg_params()
        reg_mode = self.reg_params[0x70]

        reg_mode = self.set_bit_range(reg_mode, 4, 5, self._chopper_to_bits(chopper))
        reg_mode = self.set_bit(reg_mode, 3, multforceon == "on")
        reg_mode = self.set_bit(reg_mode, 2, multforceoff == "on")

        self.i2c.writeto_mem(self.addr, 0x70, reg_mode)
        self.reg_params = self._load_reg_params()
        self.reg_mode_chopper = chopper
        self.reg_mode_multforceon = multforceon
        self.reg_mode_multforceoff = multforceoff

    def set_vref(self, vmux="Vbgd1", vrefd0out="off", vrefd1in="off", vref=1.22):
        self.reg_params = self._load_reg_params()
        reg_accfg5 = self.reg_params[0x57]
        reg_mode = self.reg_params[0x70]

        reg_accfg5 = self.set_bit(reg_accfg5, 0, vmux == "Vbgd1")
        reg_mode = self.set_bit(reg_mode, 1, vrefd0out == "on")
        reg_mode = self.set_bit(reg_mode, 0, vrefd1in == "on")

        self.i2c.writeto_mem(self.addr, 0x57, reg_accfg5)
        self.i2c.writeto_mem(self.addr, 0x70, reg_mode)
        self.reg_params = self._load_reg_params()
        self.vref_vmux = vmux
        self.vref_vrefd0out = vrefd0out
        self.vref_vrefd1in = vrefd1in
        self.vref_value = vref

    def set_start_continuous(self, start=1, cont=1):
        self.reg_params = self._load_reg_params()
        reg_accfg0 = self.reg_params[0x52]

        reg_accfg0 = self.set_bit(reg_accfg0, 7, start)
        reg_accfg0 = self.set_bit(reg_accfg0, 1, cont)

        self.i2c.writeto_mem(self.addr, 0x52, reg_accfg0)
        self.reg_params = self._load_reg_params()
        self.start_enabled = start
        self.start_continuous = cont

    def read_raw(self):
        try:
            lsb = self.i2c.readfrom_mem(self.addr, 0x50, 1)
            msb = self.i2c.readfrom_mem(self.addr, 0x51, 1)
            x = (msb[0] << 8) | lsb[0]
            x = (-(x & 32768) | (x & 32767))
            return x
        except Exception as e:
            print(f"Failed to read raw value: {e}")
            return 0

    def read(self):
        val = self.read_raw()
        val = val * 1000 * (self.vref_value / 65535)
        if self.pga1_enabled == "on":
            val /= self.pga1_gain
        if self.pga2_enabled == "on":
            val /= self.pga2_gain
        if self.pga3_enabled == "on":
            val /= (self.pga3_gain / 12)
        return val

    def conv_o2_val(self, buf):
        if self.o2_span_air > buf:
            val = round(((20.95 - 0) / (self.o2_span_air - self.o2_zero)) * (buf - self.o2_zero) + 0, 2)
        else:
            val = round(((100 - 20.95) / (self.o2_span_o2 - self.o2_span_air)) * (buf - self.o2_span_air) + 20.95, 2)
        return val

    def read_o2(self):
        buf = self.read()
        val = self.conv_o2_val(buf)
        return val

    @staticmethod
    def _gain_to_bits(gain):
        return {
            1: 0b00,
            2: 0b01,
            5: 0b10,
            10: 0b11,
        }.get(gain, 0b00)

    @staticmethod
    def _analog_input_to_bits(vinp, vinn):
        return {
            ("AC3", "AC2"): 0b00001,
            ("AC3", "AC0"): 0b10011,
            ("AC2", "AC3"): 0b01001,
            ("AC2", "AC0"): 0b10010,
            ("AC1", "AC0"): 0b10001,
        }.get((vinp, vinn), 0b00001)

    @staticmethod
    def _fs_to_bits(fs):
        return {
            62.5: 0b00,
            125: 0b01,
            250: 0b10,
            500: 0b11,
        }.get(fs, 0b00)

    @staticmethod
    def _osr_to_bits(osr):
        if isinstance(osr, int) and osr & (osr - 1) == 0 and 8 <= osr <= 1024:
            return int(math.log2(osr)) - 3
        return 0

    @staticmethod
    def _nelconv_to_bits(nelconv):
        if isinstance(nelconv, int) and nelconv & (nelconv - 1) == 0 and 1 <= nelconv <= 8:
            return int(math.log2(nelconv))
        return 0

    @staticmethod
    def _chopper_to_bits(chopper):
        return {
            "state0": 0b00,
            "state1": 0b01,
            "Nelconv": 0b10,
            "Nelconv/2": 0b11,
        }.get(chopper, 0b01)

# # ### TEST CODE ###
# sx8725c = SX8725C(i2c_id=1, sda_pin=18, scl_pin=19)
# print("Register parameters:")
# [print(hex(reg), ":", '{:08b}'.format(value[0])) for reg, value in sx8725c.reg_params.items()]
# print("_______________________________________________________________")
# 
# print("Start test loop")
# try:
#     while True:
#         raw = sx8725c.read_raw()
#         val = sx8725c.read()
#         conv = sx8725c.read_o2()
#         print(raw, val, conv)
#         utime.sleep(2)
# except KeyboardInterrupt:
#     pass
```

編集画面がやたら重いのでここまで。