Guest User

Untitled

a guest
Aug 20th, 2018
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.44 KB | None | 0 0
  1. import pyftdi as F
  2. from pyftdi import i2c
  3.  
  4. from ctypes import c_short
  5.  
  6. from time import sleep
  7.  
  8. import atexit
  9.  
  10. ### Some utility functions
  11. # These both assume the second byte is the higher bits.
  12.  
  13. # Concat two adacent bytes to a signed short
  14. def getShort(data, index):
  15. return c_short((data[index+1] << 8) + data[index]).value
  16.  
  17. # Concat two adacent bytes to an unsigned short
  18. def getUShort(data, index):
  19. return (data[index+1] << 8) + data[index]
  20.  
  21. ### Important register addresses
  22. # See the datasheet.
  23.  
  24. # i2c adress.
  25. BME_ADDR = 0x76
  26.  
  27. # Register that contains raw measurement values (ro).
  28. REG_DATA = 0xF7
  29.  
  30. # Controls for oversampling and power options (rw).
  31. REG_CONTROL = 0xF4
  32.  
  33. # Controls sampling rate, filter coefficients and interface (rw, but
  34. # writes may be ignored unless the device is in sleep mode).
  35. # I will be leaving this as the default settings, it's just here for reference.
  36. REG_CONFIG = 0xF5
  37.  
  38. # Calibration data registers (ro)
  39. REG_CAL1 = 0x88
  40. REG_CAL2 = 0xA1 # Not used (is for the BME280)
  41.  
  42. # Reset register, writing the value 0xB6 will trigger a soft reset.
  43. REG_RESET = 0xE0
  44.  
  45.  
  46. ### Calculate the values for configuration.
  47. # I will use forced mode, where it takes one measurement and then goes
  48. # to sleep. You can also put it in free-run mode, where it constantly
  49. # takes measurements, but forced mode is more appropriate here.
  50. #
  51. # You need to write the control register every time
  52. # you want a new measurement in this mode.
  53. OVERSAMPLE_TEMP = 2 # 2x oversampling (0b010)
  54. OVERSAMPLE_PRES = 2 # 2x oversampling (0b010)
  55. MODE = 1 # Forced mode, take one measurement then sleep (0b1)
  56.  
  57. control = OVERSAMPLE_TEMP << 5 | OVERSAMPLE_PRES << 2 | MODE
  58. # 0b01000000 0b00001000 0b00000001
  59. # --------------------------------------------------------
  60. # = 0b01001001
  61.  
  62.  
  63. ### Set up i2c.
  64.  
  65. # Same deal as the SPI example
  66. ctrl = i2c.I2cController()
  67. ctrl.configure('ftdi://ftdi:232h/1')
  68.  
  69. atexit.register(ctrl.terminate)
  70.  
  71. # Port here automatically prepends the i2c slave address to all transactions.
  72. port = ctrl.get_port(BME_ADDR)
  73.  
  74. ### Now let's start talking to the chip!
  75.  
  76. # Force a reset to start fresh. Device will start in sleep mode (not taking
  77. # measurements.
  78. port.write_to(REG_RESET, [0xB6])
  79.  
  80. # Read the chip id, you can use this to distinguish between different chips
  81. # in the line. All the chips have the same interface, but some have more
  82. # sensors. E.g. the BMP280 is pressure and temperature, BME280 is the same thing
  83. # but also humidity. Reading pressure and temperature is exactly the same
  84. # between the two.
  85. # If you adapt this code for the BME280, you need to change the i2c address
  86. # and add code to also read the humidity.
  87. chip_id = port.read_from(0xD0, 1) # Should be 0x58 == 88 for production BMP280.
  88.  
  89. # Set oversampling and activate forced mode.
  90. port.write_to(REG_CONTROL, [control])
  91.  
  92. ### Read values and do the conversion
  93. # The following procedure just comes from the datasheet, we're just reading
  94. # out register values and converting them.
  95.  
  96. # Read calibration. This is fixed and only needs to be done once.
  97. cal1 = port.read_from(REG_CAL1, 24)
  98. cal2 = port.read_from(REG_CAL2, 1) # Not used, will be zero
  99.  
  100. # Convert the raw bytes to the calibration coefficients. Ditto, only
  101. # needs to be done once.
  102. dig_T1 = getUShort(cal1, 0)
  103. dig_T2 = getShort(cal1, 2)
  104. dig_T3 = getShort(cal1, 4)
  105.  
  106. dig_P1 = getUShort(cal1, 6)
  107. dig_P2 = getShort(cal1, 8)
  108. dig_P3 = getShort(cal1, 10)
  109. dig_P4 = getShort(cal1, 12)
  110. dig_P5 = getShort(cal1, 14)
  111. dig_P6 = getShort(cal1, 16)
  112. dig_P7 = getShort(cal1, 18)
  113. dig_P8 = getShort(cal1, 20)
  114. dig_P9 = getShort(cal1, 22)
  115.  
  116. # Sleep long enough for a measurement to complete. You can calculate
  117. # the minimum wait time using a formula in the datasheet or you can also
  118. # look at the status register if you want. Here I'm just sleeping for
  119. # a relatively long time.
  120. # The actual sampling time depends on oversampling settings.
  121. sleep(0.100)
  122.  
  123. # Read the raw measurement data from the device. These are in the form
  124. # of raw ADC readings, which must be converted using the device-specific
  125. # calibration and the procedure in the datasheet.
  126. data = port.read_from(REG_DATA, 8)
  127.  
  128. # Cat together the bytes to get the raw integer pressure and temp readings.
  129. pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
  130. temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
  131.  
  132. # Formulas... first calculate the temperature.
  133. var1 = ((((temp_raw >> 3) - (dig_T1 << 1))) * (dig_T2)) >> 11
  134. var2 = (((((temp_raw >> 4) - (dig_T1)) * ((temp_raw >> 4) - (dig_T1))) >> 12) * (dig_T3)) >> 14
  135. t_fine = var1 + var2
  136. temperature = float(((t_fine * 5) + 128) >> 8);
  137.  
  138. # Now calculate some values that are used to compensate the pressure reading
  139. # for temperature.
  140. var1 = t_fine / 2.0 - 64000.0
  141. var2 = var1 * var1 * dig_P6 / 32768.0
  142. var2 = var2 + var1 * dig_P5 * 2.0
  143. var2 = var2 / 4.0 + dig_P4 * 65536.0
  144. var1 = (dig_P3 * var1 * var1 / 524288.0 + dig_P2 * var1) / 524288.0
  145. var1 = (1.0 + var1 / 32768.0) * dig_P1
  146.  
  147. # Use the above values to compensate the base pressure reading for
  148. # temperature.
  149. if var1 == 0:
  150. pressure = 0 # An error occurred with the reading so skip this.
  151. else:
  152. pressure = 1048576.0 - pres_raw
  153. pressure = ((pressure - var2 / 4096.0) * 6250.0) / var1
  154. var1 = dig_P9 * pressure * pressure / 2147483648.0
  155. var2 = pressure * dig_P8 / 32768.0
  156. pressure = pressure + (var1 + var2 + dig_P7) / 16.0
  157.  
  158. # Print out the readings.
  159. print("id: 0x{:x}".format(chip_id[0]))
  160. print("temp: {0:.2f}C".format(temperature / 100.0))
  161. print("pressure: {0:.2f}hPa".format(pressure / 100.0))
Add Comment
Please, Sign In to add comment