I2C bus error / Board not detected: I2C bus error



  • Hi,

    We have multiple PyCom FiPy's with PyTrack's & PySense ... and on one of them (FiPY + PyTrack) ... we are getting these two alternative I2C bus error's

    Sometimes A, sometimes B ... and sometimes C ... it run ... and all we do is "reset" it and let it run the exact same pice of code (and yeah, we are runnig the exact same code on all of our boards ... and we only have the issue on one of them ... (and it kinda rules out that there is something wrong with our code :-) ...)

    A) - OSError: I2C bus error

    LOG: Define py()
    Traceback (most recent call last):
      File "main_NB-IOT.py", line 131, in <module>
      File "/flash/lib/pytrack.py", line 8, in __init__
      File "/flash/lib/pycoproc.py", line 105, in __init__
      File "/flash/lib/pycoproc.py", line 161, in mask_bits_in_memory
      File "/flash/lib/pycoproc.py", line 155, in magic_write_read
      File "/flash/lib/pycoproc.py", line 114, in _write
      File "/flash/lib/pycoproc.py", line 126, in _wait
    OSError: I2C bus error
    Pycom MicroPython 1.18.1.r7 [v1.8.6-849-d1c5ea9] on 2018-12-17; FiPy with ESP32
    

    B) - Exception: Board not detected: I2C bus error

    LOG: Define py()
    Traceback (most recent call last):
      File "main_NB-IOT.py", line 131, in <module>
      File "/flash/lib/pytrack.py", line 8, in __init__
      File "/flash/lib/pycoproc.py", line 93, in __init__
      File "/flash/lib/pycoproc.py", line 93, in __init__
    Exception: Board not detected: I2C bus error
    Pycom MicroPython 1.18.1.r7 [v1.8.6-849-d1c5ea9] on 2018-12-17; FiPy with ESP32
    

    Yes, we have:

    • Updated the firmware on the PyTrack, multiple times (dfu-util -D pytrack_0.0.8.dfu)

    • Updated the firmware on the FiPy to 1.18.1.r7 ... and every other stable and development version currently out there

    • We have used both, the latest stable version of "Pycom Firmware Update.app" and the development version "Pycom Firmware Update_1.15.2.b1.app"

    • We have updated the firmware to on the LTE-NB1 to the latest (NB1-40343)

    • We have os.mkfs('/flash') ... and re-uploaded the sources ... here we'd also like to ask if there is a "Parameter" one could pass to os.mkfs to "securle wipe" all of the data in the flash ... as we are thinking there might be an issue with flash-corruption ... as in the begining os.mkfs did solve the issue ... and we see that if we upload "BIG" changes in the code ... it runs as normal ... and with "small changes" we getthe I2C bus error

    • We have also seen that in the code when we read the battery voltage - it errors out with the same I2C bus error:

     BATTERY_LEVEL=py.read_battery_voltage()
    
    • Also noticed that if we remove the USB-cable from the Computer, it still errors out with the same I2C Bus Error ... thought if we remove the mini-USB-side-of-the-cable from the PyTrack ... the code runs smoothly without any error ...


  • @crumble said in I2C bus error / Board not detected: I2C bus error:

    Before 1.20.rc4 I ran somtimes into i2c errors in setup_sleep. So I blamed it on i2c problems without an exception. Without the i2c error it happens really seldome. Board does not go to sleep and script stops. But I can't remember if I was really able to use the REPL

    it depends .... on what board we use ... some almost never do ... like take days before it happens ... others ... do it every 2nd -- 3rd time around ....

    I will try to run them all on the latest developmente verision ... and see if it happens there too

    IIRC, i think there is a thread here talking about "py.go_to_sleep()" not always working ...

    The watchdog shall help you to get out of this state.

    Yeah, it does. It reboots it ... and we happen to get two close data points / intervalls next to each other ...

    But this to is fixable ... just have to re-structure the app to become event-state driven ... and use NVRAM to store where it is .... so if WDT restes ... we can try again from last event-state .... ergo if we've come to the last event (go_to_deep_sleep) it would then just try to put the board in DS-mode ...

    Fixable ... but not as neat if it worked out-of-the-box :-)



  • @combaindeft

    • But I found that for some reason py.setup_sleep() & py.go_to_sleep() don't always work ... they don't always put the PyTrack or PySense into DeeepSleep :-( ... working on figuring it out ...

    Before 1.20.rc4 I ran somtimes into i2c errors in setup_sleep. So I blamed it on i2c problems without an exception. Without the i2c error it happens really seldome. Board does not go to sleep and script stops. But I can't remember if I was really able to use the REPL

    The watchdog shall help you to get out of this state.



  • @Paul-Thornton &
    @crumble said in I2C bus error / Board not detected: I2C bus error:

    On boot time you have to wait a long time until the pytrack is ready. On my setup it is 5+sec (Plus because it failed once since then).
    Place your init stuff not related to i2c in front of the pytrack init. Measure the time for this and sleep until you reached at least 2secs. Increase wait time when an i2c error pops up. Test this in a loop over night. You will see that wait time has to be much longer than the recommanded 2secs. You will find time slots where you can init the pytrack and where it fails. The slot seems to vary depending on the firmware version of my LoPy. So I recommand wait times above 2sec, even if you find a reliable slot in your version.

    I have almost solved all the issues in pycoproc.py

    • All I2C Bus Error's are gone .... and it doesn't crash the code ... and YES @crumble , it had some timing issue ... as it was written to Explicitly expect correct answers ... while in real world ... you sometime must adapt and wait ... so I added in the right place "Wait_4_IT-while-loops" (If you've seen How I Meet Your Mother ... you know the reference ...)

    • But I found that for some reason py.setup_sleep() & py.go_to_sleep() don't always work ... they don't always put the PyTrack or PySense into DeeepSleep :-( ... working on figuring it out ...

    Code so far for: pycoproc.py

    from machine import Pin
    from machine import I2C
    import machine
    import time
    import pycom
    
    __version__ = '0.0.2_DEft_I2C_BUS_ERROR_RESOLVED'
    
    """ PIC MCU wakeup reason types """
    WAKE_REASON_ACCELEROMETER = 1
    WAKE_REASON_PUSH_BUTTON = 2
    WAKE_REASON_TIMER = 4
    WAKE_REASON_INT_PIN = 8
    
    # Colors
    off = 0x000000
    gray = 0x121212
    white = 0xffffff
    red = 0xff0000
    green = 0x00ff00
    blue = 0x0000ff
    purple = 0x800080
    orange = 0xFFA500
    # DEft Colors
    dTorq = 0x00CED1
    dPink = 0xFF1493
    dRed = 0xFF4500
    dMag = 0xFF00FF
    dViol = 0x9400D3
    dLime = 0x32CD32
    dOlive = 0x808000
    dTeal = 0x008080
    dCyan = 0x00FFFF
    dBrown = 0xA52A2A
    dChoco = 0xD2691E
    dAzure = 0xF0FFFF
    dSgray = 0x708090
    
    class Pycoproc:
        """ class for handling the interaction with PIC MCU """
    
        #I2C_SLAVE_ADDR = const(8)
        I2C_SLAVE_ADDR = const(0x08)
    
        CMD_PEEK = const(0x0)
        CMD_POKE = const(0x01)
        CMD_MAGIC = const(0x02)
        CMD_HW_VER = const(0x10)
        CMD_FW_VER = const(0x11)
        CMD_PROD_ID = const(0x12)
        CMD_SETUP_SLEEP = const(0x20)
        CMD_GO_SLEEP = const(0x21)
        CMD_CALIBRATE = const(0x22)
        CMD_BAUD_CHANGE = const(0x30)
        CMD_DFU = const(0x31)
    
        REG_CMD = const(0)
        REG_ADDRL = const(1)
        REG_ADDRH = const(2)
        REG_AND = const(3)
        REG_OR = const(4)
        REG_XOR = const(5)
    
        ANSELA_ADDR = const(0x18C)
        ANSELB_ADDR = const(0x18D)
        ANSELC_ADDR = const(0x18E)
    
        ADCON0_ADDR = const(0x9D)
        ADCON1_ADDR = const(0x9E)
    
        IOCAP_ADDR = const(0x391)
        IOCAN_ADDR = const(0x392)
    
        INTCON_ADDR = const(0x0B)
        OPTION_REG_ADDR = const(0x95)
    
        _ADCON0_CHS_POSN = const(0x02)
        _ADCON0_ADON_MASK = const(0x01)
        _ADCON1_ADCS_POSN = const(0x04)
        _ADCON0_GO_nDONE_MASK = const(0x02)
    
        ADRESL_ADDR = const(0x09B)
        ADRESH_ADDR = const(0x09C)
    
        TRISC_ADDR = const(0x08E)
    
        PORTA_ADDR = const(0x00C)
        PORTC_ADDR = const(0x00E)
    
        WPUA_ADDR = const(0x20C)
    
        WAKE_REASON_ADDR = const(0x064C)
        MEMORY_BANK_ADDR = const(0x0620)
    
        PCON_ADDR = const(0x096)
        STATUS_ADDR = const(0x083)
    
        EXP_RTC_PERIOD = const(7000)
    
        FIRMWARE_VERSION = None
    
        def __init__(self, i2c=None, sda='P22', scl='P21'):
            if i2c is not None:
                #print("BEBUG: @Pycoproc :: __init__ :: I2C is not None")
                #self.i2c = i2c
                #self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl))
                self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl), baudrate=115200)
                #self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl), baudrate=230400)
                #self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl), baudrate=460800)
            else:
                #print("DEBUG :: @Pycoproc :: __init__ :: I2C is None")
                #self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl))
                self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl), baudrate=115200)
                #self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl), baudrate=230400)
                #self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl), baudrate=460800)
                
    
            #print("DEBUG :: @After :: Define Variables")
            self.sda = sda
            self.scl = scl
            self.clk_cal_factor = 1
            self.reg = bytearray(6)
            self.wake_int = False
            self.wake_int_pin = False
            self.wake_int_pin_rising_edge = True
    
            # Make sure we are inserted into the
            # correct board and can talk to the PIC
            try:
                #print("DEBUG :: @Read FW Version")
                Wait_4_IT=True
                while Wait_4_IT:
                    time.sleep_us(100)
                    try: 
                        FIRMWARE_VERSION = self.read_fw_version()
                        Wait_4_IT = False
                    except Exception as e:
                        print('DEBUG :: @FIRMWARE_VERSION = self.read_fw_version() :: Exception: ' + str(e))
                        #pass
                #print("DEBUG :: @Read FW Version :: After: " + str(FIRMWARE_VERSION))
            except Exception as e:
                print('DEBUG :: @Read FW Version :: Exception: ' + str(e))
                #print("DEBUG :: Setting FIRMWARE_VERSION = 8")
                #FIRMWARE_VERSION = 8
                raise Exception('Board not detected: {}'.format(e))
    
            try:
                #print("DEBUG :: @init the ADC for the battery measurements")
                # init the ADC for the battery measurements
                #value = 
                self.poke_memory(ANSELC_ADDR, 1 << 2)
                #print("DEBUG ::   self.poke_memory(ANSELC_ADDR, 1 << 2): " + str(value))
                #value = 
                self.poke_memory(ADCON0_ADDR, (0x06 << _ADCON0_CHS_POSN) | _ADCON0_ADON_MASK)
                #print("DEBUG ::   self.poke_memory(ADCON0_ADDR, (0x06 << _ADCON0_CHS_POSN) | _ADCON0_ADON_MASK): " + str(value))
                #value = 
                self.poke_memory(ADCON1_ADDR, (0x06 << _ADCON1_ADCS_POSN))
                #print("DEBUG ::   self.poke_memory(ADCON1_ADDR, (0x06 << _ADCON1_ADCS_POSN)): " + str(value))
            except Exception as e:
                print('DEBUG :: @init the ADC for the battery measurements :: Exception: ' + str(e))
                pycom.rgbled(red)
                machine.idle()
    
            try: 
                #print("DEBUG :: @enable the pull-up on RA3")
                # enable the pull-up on RA3
                self.poke_memory(WPUA_ADDR, (1 << 3))
            except Exception as e:
                print('DEBUG :: @enable the pull-up on RA3 :: Exception: ' + str(e))
                pycom.rgbled(red)
                machine.idle()
            
            try:
                #print("DEBUG :: @make RC5 an input")
                # make RC5 an input
                self.set_bits_in_memory(TRISC_ADDR, 1 << 5)
            except Exception as e:
                print('DEBUG :: @make RC5 an input :: Exception: ' + str(e))
                pycom.rgbled(red)
                machine.idle()
    
            try: 
                #print("DEBUG :: @set RC6 and RC7 as outputs and enable power to the sensors and the GPS")
                # set RC6 and RC7 as outputs and enable power to the sensors and the GPS
                #value = 
                self.mask_bits_in_memory(TRISC_ADDR, ~(1 << 6))
                #print("DEBUG ::   self.mask_bits_in_memory(TRISC_ADDR, ~(1 << 6): " + str(value))
                #value = 
                self.mask_bits_in_memory(TRISC_ADDR, ~(1 << 7))
                #print("DEBUG ::   mask_bits_in_memory(TRISC_ADDR, ~(1 << 7): " + str(value))
            except Exception as e:
                #print('DEBUG :: @set RC6 and RC7 as outputs and enable power :: Exception: ' + str(e))
                pycom.rgbled(red)
                machine.idle()
    
            #print("DEBUG :: @END-OF the ADC :: for the battery measurements")
    
            try:
                #print("DEBUG :: @Read FW Version")
                if FIRMWARE_VERSION < 6:
                    raise ValueError('Firmware out of date - Update Board Firmware to version 0.0.8\!')
            except Exception as e:
                print('DEBUG :: @Read FW Version :: Exception: ' + str(e))
                pycom.rgbled(red)
                machine.idle()
    
        def _wait(self):
            #print('DEBUG :: @_wait(self)')
            #print('DEBUG ::   I2C_SLAVE_ADDR: ' + str(I2C_SLAVE_ADDR))
            count = 0
            time.sleep_us(10)
            #print('DEBUG :: wait_value = self.i2c.readfrom(I2C_SLAVE_ADDR, 2)')
            Wait_4_IT=True
            while Wait_4_IT:
                time.sleep_us(100)
                try: 
                    #wait_value = self.i2c.readfrom(I2C_SLAVE_ADDR, 1)[0]
                    wait_value = self.i2c.readfrom(I2C_SLAVE_ADDR, 2)
                    Wait_4_IT = False
                except Exception as e:
                    #print('DEBUG :: @wait_value = self.i2c.readfrom(I2C_SLAVE_ADDR, 2) :: Exception: ' + str(e))
                    pass
            #print('DEBUG ::   wait_value: ' + str(wait_value))
            try:
                wait_value = wait_value[0]
                #print('DEBUG ::   wait_value: ' + str(wait_value))
            except Exception as e:
                 print('DEBUG :: @wait_value = wait_value[0] :: Exception: ' + str(e))
            #print('DEBUG ::   wait_value: ' + str(wait_value))
            #while wait_value != 0xFF:
            #print('DEBUG :: @_wait(self) - While Wait_value :: wait_value: ' + str(wait_value))
            while count < 255:
                #wait_value = self.i2c.readfrom(I2C_SLAVE_ADDR, 1)[0]
                #print('DEBUG ::   value: ' + str(count))
                time.sleep_us(100)
                count += 1
                if (count > 500):  # timeout after 50ms
                    raise Exception('Board timeout')   
            #print('DEBUG :: @_wait(self) :: END')         
            
        def _write(self, data, wait=True):
            #print('DEBUG :: @_write(self, data, wait=True)')
            #print('DEBUG ::   self: ' + str(self))
            #print('DEBUG ::   I2C_SLAVE_ADDR: ' + str(I2C_SLAVE_ADDR))
            #print('DEBUG ::   data: ' + str(data))
            #print('DEBUG ::   wait: ' + str(wait))
    
            Wait_4_IT=True
            while Wait_4_IT:
                time.sleep_us(100)
                try:
                    #print('DEBUG :: @self.i2c.writeto(I2C_SLAVE_ADDR, data)')
                    #value = 
                    self.i2c.writeto(I2C_SLAVE_ADDR, data)
                    #print('DEBUG ::   value: ' + str(value))
                    Wait_4_IT = False
                except Exception as e:
                    #print('DEBUG :: @self.i2c.writeto(I2C_SLAVE_ADDR, data) :: Exception: ' + str(e))
                    pass
    
            if wait == True:
                #print('DEBUG :: @self._wait()')
                self._wait()
    
        def _read(self, size):
            #print('DEBUG :: @_read(self, size)')
            #print('DEBUG ::   self: ' + str(self))
            #print('DEBUG ::   size: ' + str(size))
            #print('DEBUG ::   I2C_SLAVE_ADDR: ' + str(I2C_SLAVE_ADDR))
            #print('DEBUG ::   Devices: ' + str(self.i2c.scan()))
            #print('DEBUG ::   size + 1: ' + str(size + 1))
            #print('DEBUG :: @vself.i2c.readfrom(I2C_SLAVE_ADDR, size + 1)')
            Wait_4_IT=True
            while Wait_4_IT:
                time.sleep_us(100)
                try: 
                    #value = self.i2c.readfrom(I2C_SLAVE_ADDR, size + 1)[1:(size + 1)]
                    value = self.i2c.readfrom(I2C_SLAVE_ADDR, size + 1)
                    Wait_4_IT = False
                except Exception as e:
                    #print('DEBUG :: @value = self.i2c.readfrom(I2C_SLAVE_ADDR, size + 1) :: Exception: ' + str(e))
                    pass
            #print('DEBUG ::   value: ' + str(value))
            try:
                value = value[1:(size + 1)]
                #print('DEBUG ::   value[1:(size + 1)]: ' + str(value))
            except Exception as e:
                 print('DEBUG :: @value = value[1:(size + 1)] :: Exception: ' + str(e))
            #print('DEBUG ::   value: ' + str(value))
            return value
    
        def _send_cmd(self, cmd):
            #print('DEBUG :: @_send_cmd(self, cmd)')
            #print('DEBUG :: @_write(bytes([cmd]))')
            #print('DEBUG ::   [cmd]: ' + str([cmd]))
    
            Wait_4_IT=True
            while Wait_4_IT:
                time.sleep_us(100)
                try: 
                    value = self._write(bytes([cmd]))
                    Wait_4_IT = False
                except Exception as e:
                    print('DEBUG :: @value = self._write(bytes([cmd])) :: Exception: ' + str(e))
                    #pass
            #print('DEBUG :: @_write(bytes([cmd])) :: After')
            #print('DEBUG ::   [cmd]: ' + str(value))
    
        def read_hw_version(self):
            self._send_cmd(CMD_HW_VER)
            d = self._read(2)
            return (d[1] << 8) + d[0]
    
        def read_fw_version(self):
            #print('DEBUG :: @read_fw_version()')
            #print('DEBUG ::   CMD_FW_VER: ' + str(CMD_FW_VER))
            #print('DEBUG :: @_send_cmd(CMD_FW_VER)')
            self._send_cmd(CMD_FW_VER)
            #print('DEBUG :: @_send_cmd(CMD_FW_VER) :: After')
            #print('DEBUG :: @d = self._read(2)')
            d = self._read(2)
            #print('DEBUG :: @d = self._read(2) :: After')
            #print('DEBUG ::   d: ' + str(d))
            #print('DEBUG :: @return (d[1] << 8) + d[0]')
            #print('DEBUG ::   d[1]: ' + str(d[1]))
            #print('DEBUG ::   d[0]: ' + str(d[0]))
            return (d[1] << 8) + d[0]
    
        def read_product_id(self):
            self._send_cmd(CMD_PROD_ID)
            d = self._read(2)
            return (d[1] << 8) + d[0]
    
        def peek_memory(self, addr):
            self._write(bytes([CMD_PEEK, addr & 0xFF, (addr >> 8) & 0xFF]))
            return self._read(1)[0]
    
        def poke_memory(self, addr, value):
            self._write(bytes([CMD_POKE, addr & 0xFF, (addr >> 8) & 0xFF, value & 0xFF]))
    
        def magic_write_read(self, addr, _and=0xFF, _or=0, _xor=0):
            self._write(bytes([CMD_MAGIC, addr & 0xFF, (addr >> 8) & 0xFF, _and & 0xFF, _or & 0xFF, _xor & 0xFF]))
            return self._read(1)[0]
    
        def toggle_bits_in_memory(self, addr, bits):
            self.magic_write_read(addr, _xor=bits)
    
        def mask_bits_in_memory(self, addr, mask):
            self.magic_write_read(addr, _and=mask)
    
        def set_bits_in_memory(self, addr, bits):
            self.magic_write_read(addr, _or=bits)
    
        def get_wake_reason(self):
            """ returns the wakeup reason, a value out of constants WAKE_REASON_* """
            return self.peek_memory(WAKE_REASON_ADDR)
    
        def get_sleep_remaining(self):
            """ returns the remaining time from sleep, as an interrupt (wakeup source) might have triggered """
            c3 = self.peek_memory(WAKE_REASON_ADDR + 3)
            c2 = self.peek_memory(WAKE_REASON_ADDR + 2)
            c1 = self.peek_memory(WAKE_REASON_ADDR + 1)
            time_device_s = (c3 << 16) + (c2 << 8) + c1
            # this time is from PIC internal oscilator, so it needs to be adjusted with the calibration value
            try:
                self.calibrate_rtc()
            except Exception as e:
                print('DEBUG :: @get_sleep_remaining - self.calibrate_rtc() :: Exception: ' + str(e))
                #pass
            time_s = int((time_device_s / self.clk_cal_factor) + 0.5) # 0.5 used for round
            return time_s
    
        def setup_sleep(self, time_s):
            print('DEBUG :: @setup_sleep(self, time_s)')
            Wait_4_IT=True
            while Wait_4_IT:
                time.sleep_us(100)
                try: 
                    self.calibrate_rtc()
                    Wait_4_IT = False
                except Exception as e:
                    print('DEBUG :: @self.calibrate_rtc() :: Exception: ' + str(e))
                    #passs
                time.sleep_us(900)
            #print('DEBUG :: @time_s = int((time_s * self.clk_cal_factor) + 0.5)')
            time_s = int((time_s * self.clk_cal_factor) + 0.5)  # round to the nearest integer
            #print('DEBUG ::   time_s: ' + str(time_s))
            if time_s >= 2**(8*3):
                time_s = 2**(8*3)-1
                #print('DEBUG ::   time_s: ' + str(time_s))
            #print('DEBUG :: @self._write(bytes([CMD_SETUP_SLEEP, time_s & 0xFF, (time_s >> 8) & 0xFF, (time_s >> 16) & 0xFF]))')
            Wait_4_IT=True
            while Wait_4_IT:
                time.sleep_us(100)
                try:
                    print('\nDEBUG ::   CMD_SETUP_SLEEP: ' + str(CMD_SETUP_SLEEP))
                    setup_sleep_write_data = bytes([CMD_SETUP_SLEEP, time_s & 0xFF, (time_s >> 8) & 0xFF, (time_s >> 16) & 0xFF])
                    print('DEBUG ::   write_data: ' + str(setup_sleep_write_data))
                    self._write(setup_sleep_write_data, wait=False)
                    Wait_4_IT = False
                except Exception as e:
                    print('DEBUG :: @self._write(bytes([CMD_SETUP_SLEEP, time_s & 0xFF, (time_s >> 8) & 0xFF, (time_s >> 16) & 0xFF])) :: Exception: ' + str(e))
                    #pass
                time.sleep_us(900)
         
        def go_to_sleep(self, gps=True):
            #print('DEBUG :: @go_to_sleep(self, gps=True)')
            #print('DEBUG ::   gps: ' + str(gps))
            # enable or disable back-up power to the GPS receiver
            if gps:
                #print('DEBUG :: @self.set_bits_in_memory(PORTC_ADDR, 1 << 7)')
                self.set_bits_in_memory(PORTC_ADDR, 1 << 7)
            else:
                #print('DEBUG :: @self.mask_bits_in_memory(PORTC_ADDR, ~(1 << 7))')
                self.mask_bits_in_memory(PORTC_ADDR, ~(1 << 7))
    
            #print('DEBUG :: @self.poke_memory(ADCON0_ADDR, 0)')
            # disable the ADC
            self.poke_memory(ADCON0_ADDR, 0)
    
            if self.wake_int:
                #print('DEBUG :: @self.wake_int)')
                # Don't touch RA3, RA5 or RC1 so that interrupt wake-up works
                self.poke_memory(ANSELA_ADDR, ~((1 << 3) | (1 << 5)))
                self.poke_memory(ANSELC_ADDR, ~((1 << 6) | (1 << 7) | (1 << 1)))
            else:
                #print('DEBUG :: @self.wake_int) :: Else')
                # disable power to the accelerometer, and don't touch RA3 so that button wake-up works
                self.poke_memory(ANSELA_ADDR, ~(1 << 3))
                self.poke_memory(ANSELC_ADDR, ~(1 << 7))
    
            #print('DEBUG :: @self.poke_memory(ANSELB_ADDR, 0xFF)')
            self.poke_memory(ANSELB_ADDR, 0xFF)
    
            # check if INT pin (PIC RC1), should be used for wakeup
            if self.wake_int_pin:
                #print('DEBUG :: @self.wake_int_pin')
                if self.wake_int_pin_rising_edge:
                    #print('DEBUG :: @self.set_bits_in_memory(OPTION_REG_ADDR, 1 << 6)')
                    self.set_bits_in_memory(OPTION_REG_ADDR, 1 << 6) # rising edge of INT pin
                else:
                    #print('DEBUG :: @self.wake_int_pin :: Else')
                    self.mask_bits_in_memory(OPTION_REG_ADDR, ~(1 << 6)) # falling edge of INT pin
                
                #print('DEBUG :: @self.mask_bits_in_memory(ANSELC_ADDR, ~(1 << 1))')
                self.mask_bits_in_memory(ANSELC_ADDR, ~(1 << 1)) # disable analog function for RC1 pin
                self.set_bits_in_memory(TRISC_ADDR, 1 << 1) # make RC1 input pin
                self.mask_bits_in_memory(INTCON_ADDR, ~(1 << 1)) # clear INTF
                self.set_bits_in_memory(INTCON_ADDR, 1 << 4) # enable interrupt; set INTE)
    
            #print('DEBUG :: @self._write(bytes([CMD_GO_SLEEP]), wait=False)')
            self._write(bytes([CMD_GO_SLEEP]), wait=True)
            # kill the run pin
            #print('DEBUG :: @Pin(\'P3\', mode=Pin.OUT, value=0)')
            Wait_4_IT=0
            while Wait_4_IT < 3:
                try: 
                    Pin('P3', mode=Pin.OUT, value=0)
                except Exception as e:
                    print('DEBUG :: @Pin(\'P3\', mode=Pin.OUT, value=0) :: Exception: ' + str(e))
                    #pass
                Wait_4_IT = Wait_4_IT + 1
                time.sleep_us(1000)
    
        def calibrate_rtc(self):
            print('DEBUG :: @calibrate_rtc()')
            # the 1.024 factor is because the PIC LF operates at 31 KHz
            # WDT has a frequency divider to generate 1 ms
            # and then there is a binary prescaler, e.g., 1, 2, 4 ... 512, 1024 ms
            # hence the need for the constant
            print('DEBUG ::   CMD_CALIBRATE: ' + str(CMD_CALIBRATE))
            Wait_4_IT=True
            while Wait_4_IT:
                time.sleep_us(100)
                try:
                    self._write(bytes([CMD_CALIBRATE]), wait=False)
                    self.i2c.deinit()
                    Pin('P21', mode=Pin.IN)
                    pulses = pycom.pulses_get('P21', 100)
                    Wait_4_IT = False
                except Exception as e:
                    print('DEBUG :: @@calibrate_rtc() :: Getting Pulses :: Exception: ' + str(e))
                    #pass
                time.sleep_us(900)
            print('DEBUG ::   pulses: ' + str(pulses))
            #self.i2c.init(mode=I2C.MASTER, pins=(self.sda, self.scl))
            #self.i2c.init(mode=I2C.MASTER, pins=(self.sda, self.scl), baudrate=115200)
            self.i2c = I2C(0, mode=I2C.MASTER, pins=(self.sda, self.scl), baudrate=115200)
            idx = 0
            for i in range(len(pulses)):
                if pulses[i][1] > EXP_RTC_PERIOD:
                    idx = i
                    break
            try:
                period = pulses[idx][1] - pulses[(idx - 1)][1]
            except:
                period = 0
            if period > 0:
                self.clk_cal_factor = (EXP_RTC_PERIOD / period) * (1000 / 1024)
            if self.clk_cal_factor > 1.25 or self.clk_cal_factor < 0.75:
                self.clk_cal_factor = 1
    
        def button_pressed(self):
            button = self.peek_memory(PORTA_ADDR) & (1 << 3)
            return not button
    
        def read_battery_voltage(self):
            #print('DEBUG :: @read_battery_voltage(self)')
            #print('DEBUG ::   ADCON0_ADDR: ' + str(ADCON0_ADDR))
            #print('DEBUG ::   _ADCON0_GO_nDONE_MASK: ' + str(_ADCON0_GO_nDONE_MASK))        
            value = self.set_bits_in_memory(ADCON0_ADDR, _ADCON0_GO_nDONE_MASK)
            #print('DEBUG ::   self.set_bits_in_memory(ADCON0_ADDR, _ADCON0_GO_nDONE_MASK): ' + str(value))
            time.sleep_us(50)
            #print('DEBUG :: @while self.peek_memory((ADCON0_ADDR) & _ADCON0_GO_nDONE_MASK)')
            while self.peek_memory((ADCON0_ADDR) & _ADCON0_GO_nDONE_MASK):
                #print('DEBUG ::   ADCON0_ADDR: ' + str(ADCON0_ADDR))
                #print('DEBUG ::   _ADCON0_GO_nDONE_MASK: ' + str(_ADCON0_GO_nDONE_MASK))                
                time.sleep_us(100)
            #print('DEBUG :: @adc_val = (self.peek_memory(ADRESH_ADDR) << 2) + (self.peek_memory(ADRESL_ADDR) >> 6)')
            adc_val = (self.peek_memory(ADRESH_ADDR) << 2) + (self.peek_memory(ADRESL_ADDR) >> 6)
            #print('DEBUG ::   adc_val: ' + str(adc_val))
            #print('DEBUG :: @value = (((adc_val * 3.3 * 280) / 1023) / 180) + 0.01')
            value = (((adc_val * 3.3 * 280) / 1023) / 180) + 0.01
            #print('DEBUG ::   value: ' + str(value))
            #return (((adc_val * 3.3 * 280) / 1023) / 180) + 0.01    # add 10mV to compensate for the drop in the FET
            return value
    
        def setup_int_wake_up(self, rising, falling):
            """ rising is for activity detection, falling for inactivity """
            wake_int = False
            if rising:
                self.set_bits_in_memory(IOCAP_ADDR, 1 << 5)
                wake_int = True
            else:
                self.mask_bits_in_memory(IOCAP_ADDR, ~(1 << 5))
    
            if falling:
                self.set_bits_in_memory(IOCAN_ADDR, 1 << 5)
                wake_int = True
            else:
                self.mask_bits_in_memory(IOCAN_ADDR, ~(1 << 5))
            self.wake_int = wake_int
    
        def setup_int_pin_wake_up(self, rising_edge = True):
            """ allows wakeup to be made by the INT pin (PIC -RC1) """
            self.wake_int_pin = True
            self.wake_int_pin_rising_edge = rising_edge
    


  • @crumble @Paul-Thornton

    Yeah, I've added a "Waiting time.time() > 10 sec" while-statement ... to start playing around with the timing ...

    I have also, re-arranged all of my "Import ..." ... spread them around in the code and importing them just when I need them ... instead of doing it the old-school C-style way of importing everything in the beginning ...

    (HINT: it's been a benefit too, as it's running a little bit faster not having to import so much at the same time in the beginning ... )

    LOG: Below is a list of all the I2C Bus Error's I've seen so far ...

    rst:0x7 (TG0WDT_SYS_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:1
    load:0x3fff8028,len:8
    load:0x3fff8030,len:1728
    load:0x4009fa00,len:0
    load:0x4009fa00,len:14592
    entry 0x400a059c
    -----------------------------------------------------------------------------
    DEBUG :: START-UP                                 :: @ 3  :: FREE MEM 2516144
    -----------------------------------------------------------------------------
    DEBUG :: ENABLE GC                                :: @ 3  :: FREE MEM 2515808
    DEBUG :: IMPORT SYS                               :: @ 3 :: FREE MEM 2515472
    -----------------------------------------------------------------------------
    DEBUG :: IMPORT MACHINE                           :: @ 3 :: FREE MEM 2515136
    LOG: @Waiting time.time() > 10 sec : Ok
    -----------------------------------------------------------------------------
    DEBUG :: IMPORT PyTrack                           :: @ 11 :: FREE MEM 2504544
    LOG: @Waiting time.time() > 20 sec : Ok
    DEBUG :: IMPORT WDT                               :: @ 20 :: FREE MEM 2504192
    LOG: Define py()
    DEBUG: @Pycoproc :: __init__ :: I2C is None
    DEBUG: @After :: Define Variables
    DEBUG: @Read FW Version :: I2C bus error
    DEBUG: @Define py() :: Exception : Board not detected: I2C bus error
    
    rst:0x7 (TG0WDT_SYS_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:1
    load:0x3fff8028,len:8
    load:0x3fff8030,len:1728
    load:0x4009fa00,len:0
    load:0x4009fa00,len:14592
    entry 0x400a059c
    -----------------------------------------------------------------------------
    DEBUG :: START-UP                                 :: @ 3  :: FREE MEM 2516144
    -----------------------------------------------------------------------------
    DEBUG :: ENABLE GC                                :: @ 3  :: FREE MEM 2515808
    DEBUG :: IMPORT SYS                               :: @ 3 :: FREE MEM 2515472
    -----------------------------------------------------------------------------
    DEBUG :: IMPORT MACHINE                           :: @ 3 :: FREE MEM 2515136
    LOG: @Waiting time.time() > 10 sec : Ok
    -----------------------------------------------------------------------------
    DEBUG :: IMPORT PyTrack                           :: @ 11 :: FREE MEM 2504544
    LOG: @Waiting time.time() > 20 sec : Ok
    DEBUG :: IMPORT WDT                               :: @ 20 :: FREE MEM 2504192
    LOG: Define py()
    DEBUG: @Pycoproc :: __init__ :: I2C is None
    DEBUG: @After :: Define Variables
    DEBUG: @Read FW Version :: 8
    DEBUG: @init the ADC for the battery measurements
    
    rst:0x7 (TG0WDT_SYS_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:1
    load:0x3fff8028,len:8
    load:0x3fff8030,len:1728
    load:0x4009fa00,len:0
    load:0x4009fa00,len:14592
    entry 0x400a059c
    -----------------------------------------------------------------------------
    DEBUG :: START-UP                                 :: @ 3  :: FREE MEM 2516144
    -----------------------------------------------------------------------------
    DEBUG :: ENABLE GC                                :: @ 3  :: FREE MEM 2515808
    DEBUG :: IMPORT SYS                               :: @ 3 :: FREE MEM 2515472
    -----------------------------------------------------------------------------
    DEBUG :: IMPORT MACHINE                           :: @ 3 :: FREE MEM 2515136
    LOG: @Waiting time.time() > 10 sec : Ok
    -----------------------------------------------------------------------------
    DEBUG :: IMPORT PyTrack                           :: @ 11 :: FREE MEM 2504544
    LOG: @Waiting time.time() > 20 sec : Ok
    DEBUG :: IMPORT WDT                               :: @ 20 :: FREE MEM 2504192
    LOG: Define py()
    DEBUG: @Pycoproc :: __init__ :: I2C is None
    DEBUG: @After :: Define Variables
    DEBUG: @Read FW Version :: 8
    DEBUG: @init the ADC for the battery measurements
    DEBUG: @enable the pull-up on RA3
    DEBUG: @make RC5 an input
    DEBUG: @Define py() :: Exception : the requested operation is not possible
    
    rst:0x7 (TG0WDT_SYS_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:1
    load:0x3fff8028,len:8
    load:0x3fff8030,len:1728
    load:0x4009fa00,len:0
    load:0x4009fa00,len:14592
    entry 0x400a059c
    -----------------------------------------------------------------------------
    DEBUG :: START-UP                                 :: @ 3  :: FREE MEM 2516144
    -----------------------------------------------------------------------------
    DEBUG :: ENABLE GC                                :: @ 3  :: FREE MEM 2515808
    DEBUG :: IMPORT SYS                               :: @ 3 :: FREE MEM 2515472
    -----------------------------------------------------------------------------
    DEBUG :: IMPORT MACHINE                           :: @ 3 :: FREE MEM 2515136
    LOG: @Waiting time.time() > 10 sec : Ok
    -----------------------------------------------------------------------------
    DEBUG :: IMPORT PyTrack                           :: @ 11 :: FREE MEM 2504544
    LOG: @Waiting time.time() > 20 sec : Ok
    DEBUG :: IMPORT WDT                               :: @ 20 :: FREE MEM 2504192
    LOG: Define py()
    DEBUG: @Pycoproc :: __init__ :: I2C is None
    DEBUG: @After :: Define Variables
    DEBUG: @Read FW Version :: 8
    DEBUG: @init the ADC for the battery measurements
    DEBUG: @enable the pull-up on RA3
    DEBUG: @make RC5 an input
    DEBUG: @set RC6 and RC7 as outputs and enable power to the sensors and the GPS
    
    rst:0x7 (TG0WDT_SYS_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
    configsip: 0, SPIWP:0xee
    clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
    mode:DIO, clock div:1
    load:0x3fff8028,len:8
    load:0x3fff8030,len:1728
    load:0x4009fa00,len:0
    load:0x4009fa00,len:14592
    entry 0x400a059c
    -----------------------------------------------------------------------------
    DEBUG :: START-UP                                 :: @ 3  :: FREE MEM 2516144
    -----------------------------------------------------------------------------
    DEBUG :: ENABLE GC                                :: @ 3  :: FREE MEM 2515808
    -----------------------------------------------------------------------------
    DEBUG :: IMPORT MACHINE                           :: @ 3  :: FREE MEM 2515472
    LOG: @Waiting time.time() > 10 sec : Ok
    -----------------------------------------------------------------------------
    DEBUG :: IMPORT PyTrack                           :: @ 11 :: FREE MEM 2504880
    LOG: @Waiting time.time() > 20 sec : Ok
    DEBUG :: IMPORT WDT                               :: @ 20 :: FREE MEM 2504528
    LOG: Define py()
    DEBUG: @Pycoproc :: __init__ :: I2C is None
    DEBUG: @After :: Define Variables
    DEBUG: @Read FW Version :: 8
    DEBUG: @init the ADC for the battery measurements
    DEBUG: @enable the pull-up on RA3
    DEBUG: @Define py() :: Exception : the requested operation is not possible
    


  • @Paul-Thornton @crumble

    LOG:

    LOG: Define py()
    DEBUG: @Pycoproc :: __init__ :: I2C is None
    DEBUG: @After :: Define Variables
    DEBUG: @Read FW Version ::
    

    In file: pycoproc.py

     self.read_fw_version()
    
    # ... some lines below ...
        def read_fw_version(self):
            self._send_cmd(CMD_FW_VER)
            d = self._read(2)
            return (d[1] << 8) + d[0]
    

    -----------
    OR
    _______

    LOG:

    LOG: Define py()
    DEBUG: @Pycoproc :: __init__ :: I2C is None
    DEBUG: @After :: Define Variables
    DEBUG: @Read FW Version :: 8
    DEBUG: @init the ADC for the battery measurements
    

    CODE:

     # init the ADC for the battery measurements
     self.poke_memory(ANSELC_ADDR, 1 << 2)
     self.poke_memory(ADCON0_ADDR, (0x06 << _ADCON0_CHS_POSN) | _ADCON0_ADON_MASK)
     self.poke_memory(ADCON1_ADDR, (0x06 << _ADCON1_ADCS_POSN))
    


  • @combaindeft

    Thios is quite normal. For some reason the communication between your *Py and pytrack fails.

    At best pycom finds and removes this issue. But this problem is there for a while and it seems that they cannot fix it in the near future.

    • On boot time you have to wait a long time until the pytrack is ready. On my setup it is 5+sec (Plus because it failed once since then).
      Place your init stuff not related to i2c in front of the pytrack init. Measure the time for this and sleep until you reached at least 2secs. Increase wait time when an i2c error pops up. Test this in a loop over night. You will see that wait time has to be much longer than the recommanded 2secs. You will find time slots where you can init the pytrack and where it fails. The slot seems to vary depending on the firmware version of my LoPy. So I recommand wait times above 2sec, even if you find a reliable slot in your version.
    • Don't use i2c calls to the pytrack in parallel. Secure the calls by a lock, if you use threads
    • I had good luck by using 1.20.rc4 with this firmware the amount of i2c errors was reduced a lot.

    This reduced the amount of errors a lot. rc4 is out for a while. Would be nice to declare it as a stable branch, so developers can benefit from the better i2c implementation who cannot use an rc branch.

    5 secs seems to be a long time. But you have to wait for a GPS fix anyway.

    Sadly this problem seems to have a very low priority or they cannot locate the issue. All I can tell is, added a DTH-22 which seems to have no i2c problem and a switch with interal pullup. L76 can get a fix only in a certain timeframe.
    I am located next to a radio tower, but cannot wrap the pytrack into a foil without a GPS plug ;)

    Btw: can we simply remove this thing which looks like an antenna and replace it with a plug for an active antenna???



  • @crumble @Paul-Thornton

    Hi again,

    yeah, I implement a Try-catch or a WDT() when it makes sense ... like if it fails with an OSError | Exception ... I do a try-catch .... and only time I decided to use a WDT() is for when I do

    lte = LTE()
    

    as it doesn't exit with an OSError or other type of ERROR at all if it fails to be initiated ... either it gets stuck there forever ... or exits to repl one millennia later ... so a WDT() make sense there ...

    Lastly, I've been running the code for long-runs ... and now I got the same "I2C Bus Error" for doing

    py.get_wake_reason()
    

    LOG:

    LOG: PyTrack/PySense Get Wake-up Reason: Traceback (most recent call last):
      File "main_NB-IOT.py", line 180, in <module>
      File "/flash/lib/pycoproc.py", line 247, in get_wake_reason
      File "/flash/lib/pycoproc.py", line 226, in peek_memory
      File "/flash/lib/pycoproc.py", line 191, in _write
    OSError: I2C bus error
    Pycom MicroPython 1.18.1.r7 [v1.8.6-849-d1c5ea9] on 2018-12-17; FiPy with ESP32
    Type "help()" for more information.
    >>>
    

    CODE:

    # WAKE_REASON_ACCELEROMETER = 1 # Accelerometer activity/inactivity detection
    # WAKE_REASON_PUSH_BUTTON = 2   # Pytrack/Pysense reset buttom
    # WAKE_REASON_TIMER = 4         # Normal timeout of the sleep interval
    # WAKE_REASON_INT_PIN = 8       # INT pin
    print('\nLOG: PyTrack/PySense Get Wake-up Reason: ', end='')
    PS_LIST_WKUP_REAS=["POWERON_RESET", "WAKE_REASON_ACCELEROMETER", "WAKE_REASON_PUSH_BUTTON", "WAKE_REASON_3",  "WAKE_REASON_TIMER", "WAKE_REASON_5", "WAKE_REASON_6", "WAKE_REASON_7",  "WAKE_REASON_INT_PIN"]
    PS_WKUP_REAS=py.get_wake_reason()     ### LINE 180 ###
    print(str(PS_WKUP_REAS) + " : " + str(PS_LIST_WKUP_REAS[PS_WKUP_REAS]))
    


  • @combaindeft

    All you have done is chaning the time of your i2c call. If you play around with utime.sleep_ms you will find timeframes where it is more likely to fail. These frames depends on the firmware version.

    In the latest firmware you can reduce the amount of i2c errors a lot. But I ran once into it with 1.20.rc4. (Maybe because reduced the amount of test runs by increasing deepsleep time)

    Paul wanted you to use a watchdog. So your device will still crash, but not staying in this state for a long time. It is best practice to have a watchdog in a production system. There is allways a chance that your program gets into a state you never thought about. But you can set only one watchdog. So you have to design it well when using multiple threads.

    On a development system it is a nasty thing. It may reset the device while typing into the REPL.





  • @Paul-Thornton

    hmm ... I recalled that a long time ago ... last year, almost a year ago exactly ... I had the same "I2C Bus Error" issues with the GPS (L76GNSS.py) ... and I modified it a bit :-) ... to something like the below snippet of code ...

    In: pycoproc.py ... I changed a few lines in the the init declaration:

        def __init__(self, i2c=None, sda='P22', scl='P21'):
            if i2c is not None:
                print("BEBUG: @Pycoproc :: __init__ :: I2C is not None")
                #self.i2c = i2c
                self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl), baudrate=115200)
            else:
                print("DEBUG: @Pycoproc :: __init__ :: I2C is None")
                #self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl))
                self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl), baudrate=115200)
    

    It worked with the GPS I2C Bus Error's ... so I'm now testing to see if it'll work with the PyTrack.py/Pycoproc.py lib's too ...

    [Update]:

    • After initial test run ... I can now have my USB-cable attached to the "FiPy+PyTrack"-combo & to my Computer .... thumbs_up


  • @paul-thornton said in I2C bus error / Board not detected: I2C bus error:

    Alternatively you could try and wrap your code in a try/catch. catch the exception and reset using
    machine.reset()

    Yeah, I did that with try/catch(es) in the code.

    But it doesn't really solve the issue ...with the I2C Bus Error on the "FiPy+PyTrack" combo ...



  • @combaindeft Doesnt sound like a flash issue.

    Could try adding a watchdog to reboot the board if it detects its failing.

    In your setup code.

    from machine import WDT
    wdt = WDT(timeout=10000) #set up a watch dog that will reset the board after 10 seconds of not having feed() called.
    

    in your main loop call:

    wdt.feed()
    

    if wdt.feed() isnt called after 10 seconds the board will reset it self and try again. You'll have to adjust the timeout to match your application.
    Alternatively you could try and wrap your code in a try/catch. catch the exception and reset using

    machine.reset()
    


  • Wait. So If you unplug the pc end of the cable it fails. but if you unplug the board end of the cable everything is fine?! Sounds like it may have a damaged/failing connector that's coming loose.

    Yes, I did that. Leave the cable in the PyCom but remove it from the PC ... and it failed. And then I removed it from the PyCom ... and It ran ... and got data into the portal.

    I have tested running it solely on battery power ... and it runs for a few hours ... and then crashes and stops.

    Press the "reset" button on the FiPy ... and it boots up and runs ...

    Doesnt explain the i2c issues however. Do these always happen on the failing board at the same time (ie first time around the main loop after a reset) or is it spread sporadically? ie sometimes itll work a few times then fail ect.

    So yeah, the above doesn't explain the I2C Bus Error.

    And yes. A ... then B .... then A again or C (it runs) ... sometimes I can do A-->B in a long loop ... and then suddenly C

    But as metioned above, I've ran it on battery power ... and it runs for a few hours ... but always fails in the end ...

    Further more, we have 3 pcs running at the same time.

    • AA - Connected to a computer to get it's power ... it runs for a few hours ... and Fails

    • AB - Connected to an external raspberry Pi power supply ... just runs and runs ...

    • AC - This device - the one we have most issues with. Runs on battery power, but fails after a few hours.

    So mmm, there is some I2C Bus issue that we have. A thought is pure power supply is best ... but not to a computer that has the possibility for a data connection.

    I am also considering of putting the code on /sd and running it from there ... to rule out if it is a flash memory issue or not



  • @combaindeft said in I2C bus error / Board not detected: I2C bus error:

    Also noticed that if we remove the USB-cable from the Computer, it still errors out with the same I2C Bus Error ... thought if we remove the mini-USB-side-of-the-cable from the PyTrack ... the code runs smoothly without any error ...

    Wait. So If you unplug the pc end of the cable it fails. but if you unplug the board end of the cable everything is fine?! Sounds like it may have a damaged/failing connector that's coming loose.

    Doesnt explain the i2c issues however. Do these always happen on the failing board at the same time (ie first time around the main loop after a reset) or is it spread sporadically? ie sometimes itll work a few times then fail ect.


Log in to reply
 

Pycom on Twitter