- 上学期有一门团队项目课程,就是做一辆智能跟踪避障的车。老师上来的时候把它拿走了arduino给树莓派等高性能芯片ban所以我们选择了OpenMV实现这个项目。
- OpenMV库和例程都很好,PID我直接使用程序。
- 关于QMC5883L如果的介绍datasheet不想看,可以看https://blog.csdn.net/sandwich_iot/article/details/116587230介绍,这里的连接方式和主要寄存器都很清楚。
-
from pyb import I2C import math RATES = { 10: 0, 50: 1, 100: 2, 200: 3, } OSR = { 64: 3, 128: 2, 256: 1, 512: 0, } #register address REG_OUT_X_LSB = 0x00 REG_OUT_X_MSB = 0x01 REG_OUT_Y_LSB = 0x02 REG_OUT_Y_MSB = 0x03 REG_OUT_Z_LSB = 0x04 REG_OUT_Z_MSB = 0x05 REG_CONF_1 = 0x09 REG_CONF_2 = 0x0a REG_RST_PERIOD = 0x0b REG_CHIP_ID = 0x0d TEMP_CORR = 47 # Just a first value class QMC5883L(object): def __init__(self, adress=13, cont_mode=True, rate=200, full_scale=True, over_sampling_rate=512, interupt=True, pointer_roll=False, restore=False ): if over_sampling_rate in OSR: self.over_sampling_rate = OSR.get(over_sampling_rate) else: raise ValueError('oversampling rate is not a allwed value') # verify oversampling rate if rate in RATES: self.rate = RATES.get(rate) else: raise ValueError('rate is not a allowed value') # verify rate self.bus = I2C(2, I2C.MASTER) self.adress = adress self.full_scale = full_scale self.interupt = interupt self.pointer_roll = pointer_roll self.restore = restore self.cont_mode = cont_mode if self.bus.read_byte_data(self.adress, REG_CHIP_ID) != 0xff: print("Wrong Chip ID, are you shure this is the correct Chip?") # verify chip address self.set_config() # mode options def set_config(self): if self.cont_mode: self.cntrl_reg1 = 1 if self.full_scale: self.cntrl_reg1 = self.cntrl_reg1 1 * (2**2) self.cntrl_reg1 = self.cntrl_reg1 self.over_sampling_rate * (2**4) self.cntrl_reg1 = self.cntrl_reg1 self.rate * (2**6) self.cntrl_reg2 = self.interupt self.cntrl_reg2 = self.cntrl_reg2 self.pointer_roll * (2 ** 6) self.cntrl_reg2 = self.cntrl_reg2 self.restore * (2 ** 7) self.bus.mem_write(self.cntrl_reg1, self.adress, REG_CONF_1) self.bus.mem_write(self.cntrl_reg2, self.adress, REG_CONF_2) # binary data operation def _convert_data(self, data, offset): if self.full_scale: max_mag = 8 else: max_mag = 2 magval = ((data[offset 1] << 8) data[offset]) if magval > (2 ** 15) - 1: magval = magval - (2 ** 16) magval = magval * max_mag / 2 ** 15 return magval # angle reading def get_magnet(self): data = self.bus.mem_read(6, self.adress, REG_OUT_X_LSB) x = self._convert_data(data, REG_OUT_X_LSB) y = self._convert_data(data, REG_OUT_Y_LSB) z = self._convert_data(data, REG_OUT_Z_LSB) Heading = math.atan2(y-0.9, x-0.52)# offset mearsued on the spot if Heading < 0: Heading = 2*math.pi if Heading > 2*math.pi: Heading -= 2*math.pi heading = Heading*180/math.pi degrees = round(heading) return degrees
当然,如果只用最大采样效率来做可以简化一大部分代码。
-
from pyb import I2C import math # register REG_OUT_X_LSB = 0x00 REG_OUT_X_MSB = 0x01 REG_OUT_Y_LSB = 0x02 REG_OUT_Y_MSB = 0x03 REG_OUT_Z_LSB = 0x04 REG_OUT_Z_MSB = 0x05 REG_CONF_1 = 0x09 REG_CONF_2 = 0x0a REG_RST_PERIOD = 0x0b REG_CHIP_ID = 0x0d TEMP_CORR = 47 # Just a first value class QMC5883L(object): def __init__(self, adress=13, rate=200, over_sampling_rate=512, full_scale = True ): self.bus = I2C(2, I2C.MASTER) self.adress = adress self.full_scale = full_scale def set_config_on(self): self.bus.mem_write(0x1d, 13, REG_CONF_1) def set_config_off(self): self.bus.mem_write(0x00, 13, REG_CONF_1) def _convert_data(self, data, offset): if self.full_scale: max_mag = 8 else: max_mag = 2 magval = ((data[offset 1] << 8) data[offset]) if magval > (2 ** 15) - 1: magval = magval - (2 ** 16) magval = magval * max_mag / 2 ** 15 return magval def get_magnet(self): data = self.bus.mem_read(memaddr = REG_OUT_X_LSB, addr = 13, data = 6) x = self._convert_data(data, REG_OUT_X_LSB) y = self._convert_data(data, REG_OUT_Y_LSB) z = self._convert_data(ata, REG_OUT_Z_LSB) Heading = math.atan2(y-0.95, x-0.501)// if Heading < 0: Heading += 2*math.pi if Heading > 2*math.pi: Heading -= 2*math.pi heading = Heading*180/math.pi degrees = round(heading) return degrees
主函数里面就直接调用这个get_magnet就可以了,因为设置的持续采样模式,所以在主函数里面可以from time import sleep,然后用sleep来设置采样间隙。
-
在实际上用OpenMV驱动QMC5883L的时候,我们老是得到EIO这样的错误,检查了连线没有问题又换了好几块同样的传感器,后来换了HMC5883L这个问题得到了解决。所以我猜想是否因为QMC5883L和OpenMV不兼容?或者我们这个问题只是个例,这个东西我们不得而知。