Welcome to the Pycom forum Forum
    • \[\[global:header.categories\]\]
    • \[\[global:header.recent\]\]
    • \[\[global:header.tags\]\]
    • \[\[global:header.popular\]\]
    • Login

    Explore Pybytes | Official Documentation | Report a Firmware Bug/Issue | GitHub

    GY-87 micropython library

    Scheduled Pinned Locked Moved Discussion
    micropythongy-80lopy4
    32 Posts 4 Posters 5.2k Views 4 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • T Offline
      tttadam @robert-hh
      last edited by tttadam

      @robert-hh
      First of all sorry for the long delay.
      I just checked, and seems like no, the last sensor didn't show up on i2c.scan()
      I checked the documentation and the MPU6050 is has some kind of mode/option, where it's connected to other I2c devices, and gather data from them. Maybe the compass is connected to the mpu6050?

      >>> from machine import I2C
      >>> i2c = I2C(0, I2C.MASTER, baudrate=400000)
      >>> i2c.scan()
      [64, 104, 119]
      >>>
      
      robert-hhR 1 Reply Last reply Reply Quote 0
      • robert-hhR Offline
        robert-hh @tttadam
        last edited by

        @tttadam I justz received a sample of the board that you have linked. Three observations:

        • the HMC5883 does not show up in the i2c.scan(), even if the address is ping'ed.
        • the bmp180 returns nonsense-values.
        • the pull-up resistor values on the board are pretty low,
          effectively 1.1kOhm. I will look tonight into the signals with an oscilloscope to verify the signal quality.

        So all-in-all, the board might just be crap.

        T 1 Reply Last reply Reply Quote 1
        • T Offline
          tttadam @robert-hh
          last edited by

          @robert-hh ohhh, I didn't even thought about that. But could be. Can you recommend some other sensor?
          pytrack has built-in gyro. what i need pressure, and compass.
          (The weather ballon will have a camera, and when it took a picture, I would like to know the direction)

          robert-hhR 1 Reply Last reply Reply Quote 0
          • robert-hhR Offline
            robert-hh @tttadam
            last edited by

            @tttadam So, looking at the device and the wiring it seems clear why the HMC5883 is not visible in the scan: it is connected to the MBU6050 slave interface. Still, according to the MPU6050 data sheet, it should be visible, because at start-up the MPU6050 connects the main I2C interface to the aux interface.
            The I2C signals are fine.

            However, on the board I have the BMP180 is broken. The temperature sensor always returns 229.3°C. At least that helped me to find a signed/unsigned bug in my driver.

            T 1 Reply Last reply Reply Quote 0
            • T Offline
              tttadam @robert-hh
              last edited by

              @robert-hh said in GY-87 micropython library:

              BMP180

              I just checked the bmp18. It's seems something off with the altitude...
              (1028 is the current QNH in Budapest)

              >>> bmp.sealevel = 1028
              >>> bmp.altitude
              51.46274
              >>> bmp.pressure
              1021.34
              >>> bmp.temperature
              24.2
              >>> si7021.readTemp()
              22.92749
              >>> my_gps.altitude
              120.3
              

              So you have any guess how Can I get the compass data?

              robert-hhR 2 Replies Last reply Reply Quote 0
              • robert-hhR Offline
                robert-hh @tttadam
                last edited by

                @tttadam The altitude is calculated from the actual pressure and what you enter as sea level pressure, roughly 8.5m/hPa. You can see it in the python script.
                The compass chip should be available when the I2C-bus is set to pass-through. I'm trying it at the moment.

                1 Reply Last reply Reply Quote 0
                • robert-hhR Offline
                  robert-hh @tttadam
                  last edited by

                  @tttadam So I found a way to talk to the compass, with the following sequence:

                  from machine import I2C
                  i2c=I2C()
                  i2c.writeto_mem(104, 107, 128) # reset MPU6050
                  i2c.writeto_mem(104, 107, 0) # disable sleep
                  i2c.writeto_mem(104, 55, 2)   # enable I2C passthru
                  i2c.scan()
                  

                  The scan should show you another I2C address. In my case it is 13, which deviates from the HMV5883 data sheet.

                  T 1 Reply Last reply Reply Quote 0
                  • T Offline
                    tttadam @robert-hh
                    last edited by

                    @robert-hh It's working for me too! :)
                    Awsome! :)
                    Now I just need to find a correct library for it.
                    I will start with this

                    Can you give me some explonation what happend?
                    What your overall expression of the board?

                    robert-hhR 1 Reply Last reply Reply Quote 0
                    • robert-hhR Offline
                      robert-hh @tttadam
                      last edited by

                      @tttadam When you do the i2c.scan(), which address is reported for the HMC5883? It puzzles me that my device reports 13 instead of 30, which is the address in all examples.
                      Besides that, I have the impression that in normal operation the HMC5883 is controlled by the MCU6050 for its own purpose. So you might get the information you need through the MCU6050.
                      If you ask me about what I did to find that way: I looked at the circuit, read the data sheets and looked at some code examples for the MCU6050.

                      T 1 Reply Last reply Reply Quote 0
                      • T Offline
                        tttadam @robert-hh
                        last edited by

                        @robert-hh

                        This is what I see. So same for me.

                        >>> from machine import I2C
                        >>> i2c = I2C(1)
                        >>> i2c.scan()
                        [64, 104, 119]
                        >>> i2c.writeto_mem(104, 107, 128) # reset MPU6050
                        >>> i2c.writeto_mem(104, 107, 0) # disable sleep
                        >>> i2c.writeto_mem(104, 55, 2)   # enable I2C passthru
                        >>> i2c.scan()
                        [13, 64, 104, 119]
                        >>>
                        
                        
                        robert-hhR 3 Replies Last reply Reply Quote 0
                        • robert-hhR Offline
                          robert-hh @tttadam
                          last edited by

                          @tttadam So let's see if that is a bug or an intended address trabslation (but why?)

                          1 Reply Last reply Reply Quote 0
                          • robert-hhR Offline
                            robert-hh @tttadam
                            last edited by

                            @tttadam A short google search gave an answer:
                            The chip in the board is not a HMC5883, but a QMC5883. See https://github.com/nodemcu/nodemcu-firmware/issues/2187
                            The QMC5883 server for the same purpose, but has different programming interface.

                            1 Reply Last reply Reply Quote 0
                            • robert-hhR Offline
                              robert-hh @tttadam
                              last edited by robert-hh

                              @tttadam I found a RasPi driver for the QMC5883 and adapted it to pycom MP:

                              #
                              # ported from http://nobytes.blogspot.com/2018/03/qmc5883-magnetic-field-sensor.html
                              #
                              
                              import time
                              import struct
                              from machine import idle
                              
                              class QMC5883:
                                  #Default I2C address
                                  ADDR = 0x0D
                              
                                  #QMC5883 = Register = numbers
                                  X_LSB = 0
                                  X_MSB = 1
                                  Y_LSB = 2
                                  Y_MSB = 3
                                  Z_LSB = 4
                                  Z_MSB = 5
                                  STATUS = 6
                                  T_LSB = 7
                                  T_MSB = 8
                                  CONFIG = 9
                                  CONFIG2 = 10
                                  RESET = 11
                                  CHIP_ID = 13
                              
                                  #Bit values for the STATUS register
                                  STATUS_DRDY = 1
                                  STATUS_OVL = 2
                                  STATUS_DOR = 4
                              
                                  #Oversampling values for the CONFIG register
                                  MC5883L_CONFIG_OS512 = 0b00000000
                                  CONFIG_OS256 = 0b01000000
                                  CONFIG_OS128 = 0b10000000
                                  CONFIG_OS64  = 0b11000000
                              
                                  #Range values for the CONFIG register
                                  CONFIG_2GAUSS = 0b00000000
                                  CONFIG_8GAUSS = 0b00010000
                              
                                  #Rate values for the CONFIG register
                                  CONFIG_10HZ = 0b00000000
                                  CONFIG_50HZ = 0b00000100
                                  CONFIG_100HZ = 0b00001000
                                  CONFIG_200HZ = 0b00001100
                              
                                  #Mode values for the CONFIG register
                                  CONFIG_STANDBY = 0b00000000
                                  CONFIG_CONT = 0b00000001
                              
                              
                                  def __init__(self, i2c):
                                      self.i2c = i2c
                                      self.oversampling = QMC5883.CONFIG_OS64
                                      self.range = QMC5883.CONFIG_2GAUSS
                                      self.rate = QMC5883.CONFIG_100HZ
                                      self.mode = QMC5883.CONFIG_CONT
                                      self.reset()
                              
                                  def reconfig(self):
                                      print("{0:b}".format(self.oversampling | self.range | self.rate | self.mode))
                                      self.i2c.writeto_mem(QMC5883.ADDR, QMC5883.CONFIG, self.oversampling | self.range | self.rate | self.mode);
                              
                                  def reset(self):
                                      self.i2c.writeto_mem(QMC5883.ADDR, QMC5883.RESET, 0x01)
                                      time.sleep(0.1)
                                      self.reconfig()
                                      time.sleep(0.01)
                              
                                  def setOversampling(self, x):
                                      self.oversampling = x
                                      self.reconfig()
                              
                                  def setRange(x):
                                      self.range = x
                                      self.reconfig()
                              
                                  def setSamplingRate(self, x):
                                      self.rate = x
                                      self.reconfig()
                              
                                  def ready(self):
                                      status = self.i2c.readfrom_mem(QMC5883.ADDR, QMC5883.STATUS, 1)[0]
                              
                                      # prevent hanging up here.
                                      # Happens when reading less bytes then then all 3 axis and will end up in a loop.
                                      # So, return any data but avoid the loop.
                                      if (status == QMC5883.STATUS_DOR):
                                          print("fail")
                                          return QMC5883.STATUS_DRDY
                              
                                      return status & QMC5883.STATUS_DRDY
                              
                                  def readRaw(self):
                                      while not self.ready():
                                          idle()
                                          pass
                              
                                      # Python performs a wrong casting at read_i2c_block_data.
                                      # The filled buffer has to be onverted afterwards by mpdule Struct
                                      register = self.i2c.readfrom_mem(QMC5883.ADDR, QMC5883.X_LSB, 9);
                              
                                      # Convert the axis values to signed Short before returning
                                      x, y, z, status, t = struct.unpack('<hhhBh', register)
                              
                                      return (x, y, z, t)
                              

                              and a short test code:

                              import time
                              
                              from qmc5883 import QMC5883
                              
                              from machine import I2C
                              i2c=I2C()
                              i2c.writeto_mem(104, 107, 128) # reset MPU6050
                              i2c.writeto_mem(104, 107, 0) # disable sleep
                              i2c.writeto_mem(104, 55, 2)   # enable I2C passthru
                              
                              print(i2c.scan())
                              time.sleep(1)
                              
                              qmc = QMC5883(i2c)
                              
                              while True:
                                  print(qmc.readRaw())
                                  time.sleep(1)
                              
                              T 2 Replies Last reply Reply Quote 0
                              • T Offline
                                tttadam @robert-hh
                                last edited by

                                @robert-hh thank you, it's looks useful, but after some time it's produce an OSError. Line 17 in my code is this : print(qmc.readRaw())
                                and the line 99 is this. register = self.i2c.readfrom_mem(QMC5883.ADDR, QMC5883.X_LSB, 9)
                                I think there were an ; which is not needed.
                                But something else is still not alright. I didn't find it yet.

                                (6967, -4882, -7620, -1943)
                                (4742, -7337, -7950, -1923)
                                Traceback (most recent call last):
                                  File "main2.py", line 17, in <module>
                                  File "/flash/lib/qmc5883.py", line 99, in readRaw
                                OSError: I2C bus error
                                
                                robert-hhR 1 Reply Last reply Reply Quote 0
                                • T Offline
                                  tttadam @robert-hh
                                  last edited by

                                  @robert-hh

                                  This is the error what i get now. Maybe tomorrow with fresh eye I will see something :)

                                  [13, 64, 104, 119]
                                  11001001
                                  Traceback (most recent call last):
                                    File "main2.py", line 17, in <module>
                                    File "/flash/lib/qmc5883.py", line 95, in readRaw
                                    File "/flash/lib/qmc5883.py", line 81, in ready
                                  OSError: I2C bus error
                                  
                                  1 Reply Last reply Reply Quote 0
                                  • K Offline
                                    kuqizz
                                    last edited by

                                    This post is deleted!
                                    1 Reply Last reply Reply Quote 0
                                    • robert-hhR Offline
                                      robert-hh @tttadam
                                      last edited by

                                      @tttadam No, the ; is not needed (probably a left-over from an initial C-Code file), but it also does not hurt. There is another one in reconfig(). The OSError is probably caused by a I2C communication problem to the device. I did not let it run for longer than about 20 minutes or 1000 measurement. If you enclose that into a try/except clause, does the device recover?
                                      The temperature reading has an offset. That is also told in the data sheet. If I add 4900 to the value, it is almost OK. The value seems to be scaled as °C*100.

                                      T 1 Reply Last reply Reply Quote 0
                                      • T Offline
                                        tttadam @robert-hh
                                        last edited by

                                        @robert-hh Okay, So I try-catch block for OSError for

                                        status = self.i2c.readfrom_mem(QMC5883.ADDR, QMC5883.STATUS, 1)[0]
                                        

                                        and

                                        return QMC5883.STATUS_DRDY
                                        

                                        lines. Looks like it's not recovering.

                                        Something went wrongI2C bus error
                                        Traceback (most recent call last):
                                          File "main2.py", line 17, in <module>
                                          File "/flash/lib/qmc5883.py", line 110, in readRaw
                                          File "/flash/lib/qmc5883.py", line 97, in ready
                                        NameError: local variable referenced before assignment.
                                        

                                        Did you used this library for porting?
                                        Because it's mention something about readraw blocking.
                                        Where did you find the desription about these four values? What are does mean?

                                        The whole code looks like this, but it is the same, only thing I added, that I moved a i2c magic into the init method from main:

                                        #
                                        # ported from http://nobytes.blogspot.com/2018/03/qmc5883-magnetic-field-sensor.html
                                        #
                                        
                                        import time
                                        import struct
                                        from machine import idle
                                        
                                        class QMC5883:
                                            #Default I2C address
                                            ADDR = 0x0D
                                        
                                            #QMC5883 = Register = numbers
                                            X_LSB = 0
                                            X_MSB = 1
                                            Y_LSB = 2
                                            Y_MSB = 3
                                            Z_LSB = 4
                                            Z_MSB = 5
                                            STATUS = 6
                                            T_LSB = 7
                                            T_MSB = 8
                                            CONFIG = 9
                                            CONFIG2 = 10
                                            RESET = 11
                                            CHIP_ID = 13
                                        
                                            #Bit values for the STATUS register
                                            STATUS_DRDY = 1
                                            STATUS_OVL = 2
                                            STATUS_DOR = 4
                                        
                                            #Oversampling values for the CONFIG register
                                            MC5883L_CONFIG_OS512 = 0b00000000
                                            CONFIG_OS256 = 0b01000000
                                            CONFIG_OS128 = 0b10000000
                                            CONFIG_OS64  = 0b11000000
                                        
                                            #Range values for the CONFIG register
                                            CONFIG_2GAUSS = 0b00000000
                                            CONFIG_8GAUSS = 0b00010000
                                        
                                            #Rate values for the CONFIG register
                                            CONFIG_10HZ = 0b00000000
                                            CONFIG_50HZ = 0b00000100
                                            CONFIG_100HZ = 0b00001000
                                            CONFIG_200HZ = 0b00001100
                                        
                                            #Mode values for the CONFIG register
                                            CONFIG_STANDBY = 0b00000000
                                            CONFIG_CONT = 0b00000001
                                        
                                        
                                            def __init__(self, i2c):
                                                self.i2c = i2c
                                                self.i2c.writeto_mem(104, 107, 128) # reset MPU6050
                                                self.i2c.writeto_mem(104, 107, 0) # disable sleep
                                                self.i2c.writeto_mem(104, 55, 2)   # enable I2C passthru
                                                self.oversampling = QMC5883.CONFIG_OS64
                                                self.range = QMC5883.CONFIG_2GAUSS
                                                self.rate = QMC5883.CONFIG_100HZ
                                                self.mode = QMC5883.CONFIG_CONT
                                                self.reset()
                                        
                                            def reconfig(self):
                                                print("{0:b}".format(self.oversampling | self.range | self.rate | self.mode))
                                                self.i2c.writeto_mem(QMC5883.ADDR, QMC5883.CONFIG, self.oversampling | self.range | self.rate | self.mode)
                                        
                                            def reset(self):
                                                self.i2c.writeto_mem(QMC5883.ADDR, QMC5883.RESET, 0x01)
                                                time.sleep(0.1)
                                                self.reconfig()
                                                time.sleep(0.01)
                                        
                                            def setOversampling(self, x):
                                                self.oversampling = x
                                                self.reconfig()
                                        
                                            def setRange(x):
                                                self.range = x
                                                self.reconfig()
                                        
                                            def setSamplingRate(self, x):
                                                self.rate = x
                                                self.reconfig()
                                        
                                            def ready(self):
                                                try:
                                                    status = self.i2c.readfrom_mem(QMC5883.ADDR, QMC5883.STATUS, 1)[0]
                                                except OSError as e:
                                                    print("Something went wrong"+str(e))
                                                    #TODO: Tune it a little   
                                        
                                                # prevent hanging up here.
                                                # Happens when reading less bytes then then all 3 axis and will end up in a loop.
                                                # So, return any data but avoid the loop.
                                                if (status == QMC5883.STATUS_DOR):
                                                    print("fail")
                                                    try:
                                                        return QMC5883.STATUS_DRDY
                                                    except OSError as e:
                                                        print("Something went wrong"+str(e))
                                                        #TODO: Tune it a little   
                                        
                                                return status & QMC5883.STATUS_DRDY
                                        
                                            def readRaw(self):
                                                while not self.ready():
                                                    idle()
                                                    pass
                                        
                                                # Python performs a wrong casting at read_i2c_block_data.
                                                # The filled buffer has to be onverted afterwards by mpdule Struct
                                                register = self.i2c.readfrom_mem(QMC5883.ADDR, QMC5883.X_LSB, 9)
                                        
                                                # Convert the axis values to signed Short before returning
                                                x, y, z, status, t = struct.unpack('<hhhBh', register)
                                        
                                                return (x, y, z, t)
                                        
                                        robert-hhR 1 Reply Last reply Reply Quote 0
                                        • robert-hhR Offline
                                          robert-hh @tttadam
                                          last edited by

                                          @tttadam
                                          Thanks for the error log. But that only happens if you catch the error, print a message and then continue. The the symbol status is not defined, raising a new exception. So you would either add:
                                          status = 0
                                          or
                                          return 0
                                          after the print statements.

                                          Did you used this library for porting?

                                          No. I found Python code, which in turn might have been ported from that web side. See http://nobytes.blogspot.com/2018/03/qmc5883-magnetic-field-sensor.html with a link to another interesting port, of which I might carry over the calibration part.

                                          I did intentionally not include that I2C magic, because that is only relevant for this GY87 board.

                                          T 1 Reply Last reply Reply Quote 0
                                          • T Offline
                                            tttadam @robert-hh
                                            last edited by

                                            @robert-hh I found the issue.
                                            GY-87 is on breadboard and and from the breadboard connected to the pytrack via dupont cables.
                                            It was a contact issue. Sorry for the false alarm.
                                            Can you help me out what are those 4 numbers mean, or where do I find a some info about that? My guess is that the last one is related to the temperature somehow but I am not sure.

                                            (-925, -2192, -8705, -2071)
                                            
                                            robert-hhR 2 Replies Last reply Reply Quote 0

                                            Hello! It looks like you're interested in this conversation, but you don't have an account yet.

                                            Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.

                                            With your input, this post could be even better 💗

                                            Register Login
                                            • 1
                                            • 2
                                            • 1 / 2
                                            • First post
                                              Last post

                                            Pycom on Twitter

                                            Pycom