Gyro/Mpu_Calibration "ESP8266"

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Gyro/Mpu_Calibration "ESP8266"

Post by Roberthh » Mon Apr 22, 2019 3:51 pm

I updated the code. in one of my posts above. But here it is again:

Code: Select all

import machine
class accel():

    def __init__(self, i2c, addr=0x68):

        self.iic = i2c
        self.addr = addr
        self.iic.writeto(self.addr, bytearray([107, 0]))

    def get_raw_values(self):

        a = self.iic.readfrom_mem(self.addr, 0x3B, 14)
        return a

    def get_ints(self):

        b = self.get_raw_values()
        c = []
        for i in b:
            c.append(i)
        return c

    def bytes_toint(self, firstbyte, secondbyte):

        if not firstbyte & 0x80:
            return firstbyte << 8 | secondbyte
        return - (((firstbyte ^ 255) << 8) | (secondbyte ^ 255) + 1)

    def get_values(self):

        raw_ints = self.get_raw_values()
        vals = {}

        vals["AcX"] = self.bytes_toint(raw_ints[0], raw_ints[1])
        vals["AcY"] = self.bytes_toint(raw_ints[2], raw_ints[3])
        vals["AcZ"] = self.bytes_toint(raw_ints[4], raw_ints[5])
        vals["Tmp"] = self.bytes_toint(raw_ints[6], raw_ints[7]) / 340.00 + 36.53
        vals["GyX"] = self.bytes_toint(raw_ints[8], raw_ints[9])
        vals["GyY"] = self.bytes_toint(raw_ints[10], raw_ints[11])
        vals["GyZ"] = self.bytes_toint(raw_ints[12], raw_ints[13])

        return vals  # returned in range of Int16

        # -32768 to 32767

    def get_smoothed_values(self, n_samples=10):

        result = self.get_values()
        for _ in range(0, n_samples - 1):
            data = self.get_values()
            for key in data.keys():
                result[key] += data[key]
        for key in data.keys():
            result[key] /= n_samples
        return result

    def calibrate(self, threshold=50, n_samples=100):

        while True:
            v1 = self.get_smoothed_values(n_samples)
            v2 = self.get_smoothed_values(n_samples)
        # Check all consecutive measurements are within
        # the threshold. We use abs() so all calculated
        # differences are positive.
            if all(abs(v1[key] - v2[key]) < threshold for key in v1.keys()):
                return v1  # Calibrated.

    # ONLY FOR TESTING! Also, fast reading sometimes crashes IIC
    def val_test(self):
        from time import sleep
        while 1:
            print(self.get_values())
            sleep(0.05)

samerou
Posts: 38
Joined: Mon Feb 11, 2019 12:51 pm

Re: Gyro/Mpu_Calibration "ESP8266"

Post by samerou » Mon Apr 22, 2019 4:15 pm

Roberthh wrote:
Mon Apr 22, 2019 3:51 pm
I updated the code. in one of my posts above. But here it is again:

Code: Select all

import machine
class accel():

    def __init__(self, i2c, addr=0x68):

        self.iic = i2c
        self.addr = addr
        self.iic.writeto(self.addr, bytearray([107, 0]))

    def get_raw_values(self):

        a = self.iic.readfrom_mem(self.addr, 0x3B, 14)
        return a

    def get_ints(self):

        b = self.get_raw_values()
        c = []
        for i in b:
            c.append(i)
        return c

    def bytes_toint(self, firstbyte, secondbyte):

        if not firstbyte & 0x80:
            return firstbyte << 8 | secondbyte
        return - (((firstbyte ^ 255) << 8) | (secondbyte ^ 255) + 1)

    def get_values(self):

        raw_ints = self.get_raw_values()
        vals = {}

        vals["AcX"] = self.bytes_toint(raw_ints[0], raw_ints[1])
        vals["AcY"] = self.bytes_toint(raw_ints[2], raw_ints[3])
        vals["AcZ"] = self.bytes_toint(raw_ints[4], raw_ints[5])
        vals["Tmp"] = self.bytes_toint(raw_ints[6], raw_ints[7]) / 340.00 + 36.53
        vals["GyX"] = self.bytes_toint(raw_ints[8], raw_ints[9])
        vals["GyY"] = self.bytes_toint(raw_ints[10], raw_ints[11])
        vals["GyZ"] = self.bytes_toint(raw_ints[12], raw_ints[13])

        return vals  # returned in range of Int16

        # -32768 to 32767

    def get_smoothed_values(self, n_samples=10):

        result = self.get_values()
        for _ in range(0, n_samples - 1):
            data = self.get_values()
            for key in data.keys():
                result[key] += data[key]
        for key in data.keys():
            result[key] /= n_samples
        return result

    def calibrate(self, threshold=50, n_samples=100):

        while True:
            v1 = self.get_smoothed_values(n_samples)
            v2 = self.get_smoothed_values(n_samples)
        # Check all consecutive measurements are within
        # the threshold. We use abs() so all calculated
        # differences are positive.
            if all(abs(v1[key] - v2[key]) < threshold for key in v1.keys()):
                return v1  # Calibrated.

    # ONLY FOR TESTING! Also, fast reading sometimes crashes IIC
    def val_test(self):
        from time import sleep
        while 1:
            print(self.get_values())
            sleep(0.05)
I followed your instruction see below
Image

Code: Select all

import machine
class accel():

    def __init__(self, i2c, addr=0x68):

        self.iic = i2c
        self.addr = addr
        self.iic.writeto(self.addr, bytearray([107, 0]))

    def get_raw_values(self):

        a = self.iic.readfrom_mem(self.addr, 0x3B, 14)
        return a

    def get_ints(self):

        b = self.get_raw_values()
        c = []
        for i in b:
            c.append(i)
        return c

    def bytes_toint(self, firstbyte, secondbyte):

        if not firstbyte & 0x80:
            return firstbyte << 8 | secondbyte
        return - (((firstbyte ^ 255) << 8) | (secondbyte ^ 255) + 1)

    def get_values(self):

        raw_ints = self.get_raw_values()
        vals = {}

        vals["AcX"] = self.bytes_toint(raw_ints[0], raw_ints[1])
        vals["AcY"] = self.bytes_toint(raw_ints[2], raw_ints[3])
        vals["AcZ"] = self.bytes_toint(raw_ints[4], raw_ints[5])
        vals["Tmp"] = self.bytes_toint(raw_ints[6], raw_ints[7]) / 340.00 + 36.53
        vals["GyX"] = self.bytes_toint(raw_ints[8], raw_ints[9])
        vals["GyY"] = self.bytes_toint(raw_ints[10], raw_ints[11])
        vals["GyZ"] = self.bytes_toint(raw_ints[12], raw_ints[13])

        return vals  # returned in range of Int16

        # -32768 to 32767

    def get_smoothed_values(self, n_samples=10):

        result = self.get_values()
        for _ in range(0, n_samples - 1):
            data = self.get_values()
            for key in data.keys():
                result[key] += data[key]
        for key in data.keys():
            result[key] /= n_samples
        return result

    def calibrate(self, threshold=50, n_samples=100):

        while True:
            v1 = self.get_smoothed_values(n_samples)
            v2 = self.get_smoothed_values(n_samples)
        # Check all consecutive measurements are within
        # the threshold. We use abs() so all calculated
        # differences are positive.
            if all(abs(v1[key] - v2[key]) < threshold for key in v1.keys()):
                return v1  # Calibrated.

    # ONLY FOR TESTING! Also, fast reading sometimes crashes IIC
    def val_test(self):
        from time import sleep
        while 1:
            print(self.get_values())
            sleep(0.05)


samerou
Posts: 38
Joined: Mon Feb 11, 2019 12:51 pm

Re: Gyro/Mpu_Calibration "ESP8266"

Post by samerou » Mon Apr 22, 2019 4:39 pm

@Roberthh , it workedd thank you and the values aren't weird but it need to get more stable

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Gyro/Mpu_Calibration "ESP8266"

Post by Roberthh » Mon Apr 22, 2019 7:36 pm

You can activate the built-in lowpass filter, by writing a value between b'\x00' and b'\x06' to memory address 0x1a, e.g.

self.iic.writeto_mem(self.addr, 0x1a, b'\x06')

06 gives the strongest filter, slowing indeed responses. Using this setting, I captured some data sets with get_values(). The effect on reducing the variance is obvious.

Code: Select all

{'GyZ': -39, 'GyY': -20, 'GyX': -288, 'Tmp': 30.0506, 'AcZ': -736, 'AcY': 34, 'AcX': 8204}
{'GyZ': -38, 'GyY': -18, 'GyX': -296, 'Tmp': 30.0535, 'AcZ': -738, 'AcY': 33, 'AcX': 8210}
{'GyZ': -40, 'GyY': -16, 'GyX': -291, 'Tmp': 30.0476, 'AcZ': -740, 'AcY': 25, 'AcX': 8202}
{'GyZ': -35, 'GyY': -20, 'GyX': -291, 'Tmp': 30.0594, 'AcZ': -741, 'AcY': 27, 'AcX': 8210}
{'GyZ': -37, 'GyY': -16, 'GyX': -288, 'Tmp': 30.0535, 'AcZ': -737, 'AcY': 27, 'AcX': 8205}
{'GyZ': -36, 'GyY': -18, 'GyX': -292, 'Tmp': 30.0565, 'AcZ': -738, 'AcY': 27, 'AcX': 8201}
{'GyZ': -37, 'GyY': -17, 'GyX': -291, 'Tmp': 30.0565, 'AcZ': -740, 'AcY': 28, 'AcX': 8207}
{'GyZ': -38, 'GyY': -15, 'GyX': -287, 'Tmp': 30.03, 'AcZ': -745, 'AcY': 29, 'AcX': 8203}
{'GyZ': -34, 'GyY': -16, 'GyX': -289, 'Tmp': 30.03, 'AcZ': -733, 'AcY': 22, 'AcX': 8201}
{'GyZ': -36, 'GyY': -18, 'GyX': -294, 'Tmp': 30.0241, 'AcZ': -735, 'AcY': 34, 'AcX': 8216}
{'GyZ': -41, 'GyY': -15, 'GyX': -288, 'Tmp': 30.0124, 'AcZ': -729, 'AcY': 34, 'AcX': 8206}
{'GyZ': -40, 'GyY': -17, 'GyX': -297, 'Tmp': 30.0006, 'AcZ': -738, 'AcY': 32, 'AcX': 8202}
{'GyZ': -35, 'GyY': -18, 'GyX': -291, 'Tmp': 30.0035, 'AcZ': -742, 'AcY': 27, 'AcX': 8204}
{'GyZ': -41, 'GyY': -18, 'GyX': -296, 'Tmp': 30.0006, 'AcZ': -735, 'AcY': 28, 'AcX': 8209}
{'GyZ': -40, 'GyY': -18, 'GyX': -292, 'Tmp': 29.9947, 'AcZ': -736, 'AcY': 39, 'AcX': 8212}
{'GyZ': -39, 'GyY': -13, 'GyX': -288, 'Tmp': 30.0065, 'AcZ': -743, 'AcY': 31, 'AcX': 8206}
{'GyZ': -39, 'GyY': -15, 'GyX': -292, 'Tmp': 30.0094, 'AcZ': -733, 'AcY': 34, 'AcX': 8200}
{'GyZ': -36, 'GyY': -18, 'GyX': -288, 'Tmp': 30.0006, 'AcZ': -744, 'AcY': 28, 'AcX': 8212}
{'GyZ': -54, 'GyY': -15, 'GyX': -294, 'Tmp': 30.0094, 'AcZ': -736, 'AcY': 27, 'AcX': 8229}
{'GyZ': -39, 'GyY': -12, 'GyX': -291, 'Tmp': 30.0094, 'AcZ': -729, 'AcY': 32, 'AcX': 8206}
{'GyZ': -38, 'GyY': -16, 'GyX': -289, 'Tmp': 30.0035, 'AcZ': -742, 'AcY': 35, 'AcX': 8210}
{'GyZ': -39, 'GyY': -18, 'GyX': -292, 'Tmp': 30.0035, 'AcZ': -728, 'AcY': 37, 'AcX': 8206}
{'GyZ': -38, 'GyY': -18, 'GyX': -290, 'Tmp': 30.0153, 'AcZ': -732, 'AcY': 28, 'AcX': 8213}
{'GyZ': -36, 'GyY': -15, 'GyX': -293, 'Tmp': 30.0065, 'AcZ': -743, 'AcY': 32, 'AcX': 8215}
{'GyZ': -43, 'GyY': -17, 'GyX': -293, 'Tmp': 30.0094, 'AcZ': -726, 'AcY': 30, 'AcX': 8205}
{'GyZ': -36, 'GyY': -16, 'GyX': -296, 'Tmp': 30.03, 'AcZ': -729, 'AcY': 31, 'AcX': 8206}
{'GyZ': -38, 'GyY': -16, 'GyX': -288, 'Tmp': 30.0212, 'AcZ': -732, 'AcY': 32, 'AcX': 8209}
{'GyZ': -37, 'GyY': -18, 'GyX': -292, 'Tmp': 30.0212, 'AcZ': -739, 'AcY': 34, 'AcX': 8205}
{'GyZ': -37, 'GyY': -16, 'GyX': -294, 'Tmp': 30.0329, 'AcZ': -728, 'AcY': 32, 'AcX': 8210}
{'GyZ': -36, 'GyY': -17, 'GyX': -293, 'Tmp': 30.0329, 'AcZ': -741, 'AcY': 30, 'AcX': 8214}

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Gyro/Mpu_Calibration "ESP8266"

Post by pythoncoder » Tue Apr 23, 2019 6:21 am

@samerou If you're using an MPU6050 you don't need the mpu9150 or mpu9250 modules. You need imu.py and vector3d.py only. MPU6050 is the base class for the more complex sensors, and is implemented in imu.py. You should be able to issue:

Code: Select all

import machine
from imu import MPU6050
i2c = machine.I2C(args_for_your_device)
mpu6050 = MPU6050(i2c)
If you still get import errors I suspect that the files haven't been correctly copied to your device. However if the above works you should be able to issue:

Code: Select all

accel = mpu6050.accel
gyro = mpu6050.gyro
print(accel.xyz)
print(gyro.xyz)
print(mpu6050.temperature)
I should review this library: the documentation could be improved and some examples for MPU6050 added.
Peter Hinch
Index to my micropython libraries.

samerou
Posts: 38
Joined: Mon Feb 11, 2019 12:51 pm

Re: Gyro/Mpu_Calibration "ESP8266"

Post by samerou » Tue Apr 23, 2019 8:21 pm

pythoncoder wrote:
Tue Apr 23, 2019 6:21 am
@samerou If you're using an MPU6050 you don't need the mpu9150 or mpu9250 modules. You need imu.py and vector3d.py only. MPU6050 is the base class for the more complex sensors, and is implemented in imu.py. You should be able to issue:

Code: Select all

import machine
from imu import MPU6050
i2c = machine.I2C(args_for_your_device)
mpu6050 = MPU6050(i2c)
If you still get import errors I suspect that the files haven't been correctly copied to your device. However if the above works you should be able to issue:

Code: Select all

accel = mpu6050.accel
gyro = mpu6050.gyro
print(accel.xyz)
print(gyro.xyz)
print(mpu6050.temperature)
I should review this library: the documentation could be improved and some examples for MPU6050 added.

@pythoncoder , the import imu worked for me when I did this

Code: Select all

from imu import MPU6050
.

but the problem is when I tried to execute this statement :

Code: Select all

mpu6050 = MPU6050(i2c)
see image below :


https://i.postimg.cc/7YKgsdhX/errorto.png

if you want to try my code here it is imu.py :

Code: Select all

from utime import sleep_ms
from machine import I2C
from vector3d import Vector3d


class MPUException(OSError):
   
    pass


def bytes_toint(msb, lsb):
   
    if not msb & 0x80:
        return msb << 8 | lsb  # +ve
    return - (((msb ^ 255) << 8) | (lsb ^ 255) + 1)


class MPU6050(object):

    _I2Cerror = "I2C failure when communicating with IMU"
    _mpu_addr = (104, 105)  # addresses of MPU9150/MPU6050. There can be two devices
    _chip_id = 104

    def __init__(self, side_str, device_addr=None, transposition=(0, 1, 2), scaling=(1, 1, 1)):

        self._accel = Vector3d(transposition, scaling, self._accel_callback)
        self._gyro = Vector3d(transposition, scaling, self._gyro_callback)
        self.buf1 = bytearray(1)                # Pre-allocated buffers for reads: allows reads to
        self.buf2 = bytearray(2)                # be done in interrupt handlers
        self.buf3 = bytearray(3)
        self.buf6 = bytearray(6)

        sleep_ms(200)                           # Ensure PSU and device have settled
        if isinstance(side_str, str):           # Non-pyb targets may use other than X or Y
            self._mpu_i2c = I2C(side_str)
        elif hasattr(side_str, 'readfrom'):     # Soft or hard I2C instance. See issue #3097
            self._mpu_i2c = side_str
        else:
            raise ValueError("Invalid I2C instance")

        if device_addr is None:
            devices = set(self._mpu_i2c.scan())
            mpus = devices.intersection(set(self._mpu_addr))
            number_of_mpus = len(mpus)
            if number_of_mpus == 0:
                raise MPUException("No MPU's detected")
            elif number_of_mpus == 1:
                self.mpu_addr = mpus.pop()
            else:
                raise ValueError("Two MPU's detected: must specify a device address")
        else:
            if device_addr not in (0, 1):
                raise ValueError('Device address must be 0 or 1')
            self.mpu_addr = self._mpu_addr[device_addr]

        self.chip_id                     # Test communication by reading chip_id: throws exception on error
        # Can communicate with chip. Set it up.
        self.wake()                             # wake it up
        self.passthrough = True                 # Enable mag access from main I2C bus
        self.accel_range = 0                    # default to highest sensitivity
        self.gyro_range = 0                     # Likewise for gyro

    def _read(self, buf, memaddr, addr):        # addr = I2C device address, memaddr = memory location within the I2C device

        self._mpu_i2c.readfrom_mem_into(addr, memaddr, buf)

    def _write(self, data, memaddr, addr):

        self.buf1[0] = data
        self._mpu_i2c.writeto_mem(addr, memaddr, self.buf1)

    def wake(self):

        try:
            self._write(0x01, 0x6B, self.mpu_addr)  # Use best clock source
        except OSError:
            raise MPUException(self._I2Cerror)
        return 'awake'

    def sleep(self):

        try:
            self._write(0x40, 0x6B, self.mpu_addr)
        except OSError:
            raise MPUException(self._I2Cerror)
        return 'asleep'

    # chip_id
    @property
    def chip_id(self):
       
        try:
            self._read(self.buf1, 0x75, self.mpu_addr)
        except OSError:
            raise MPUException(self._I2Cerror)
        chip_id = int(self.buf1[0])
        if chip_id != self._chip_id:
            raise ValueError('Bad chip ID retrieved: MPU communication failure')
        return chip_id

    @property
    def sensors(self):
 
        return self._accel, self._gyro

    # get temperature
    @property
    def temperature(self):

        try:
            self._read(self.buf2, 0x41, self.mpu_addr)
        except OSError:
            raise MPUException(self._I2Cerror)
        return bytes_toint(self.buf2[0], self.buf2[1])/340 + 35  # I think

    # passthrough
    @property
    def passthrough(self):
       
        try:
            self._read(self.buf1, 0x37, self.mpu_addr)
            return self.buf1[0] & 0x02 > 0
        except OSError:
            raise MPUException(self._I2Cerror)

    @passthrough.setter
    def passthrough(self, mode):

        if type(mode) is bool:
            val = 2 if mode else 0
            try:
                self._write(val, 0x37, self.mpu_addr)  # I think this is right.
                self._write(0x00, 0x6A, self.mpu_addr)
            except OSError:
                raise MPUException(self._I2Cerror)
        else:
            raise ValueError('pass either True or False')

    # sample rate. Not sure why you'd ever want to reduce this from the default.
    @property
    def sample_rate(self):
  
        try:
            self._read(self.buf1, 0x19, self.mpu_addr)
            return self.buf1[0]
        except OSError:
            raise MPUException(self._I2Cerror)

    @sample_rate.setter
    def sample_rate(self, rate):

        if rate < 0 or rate > 255:
            raise ValueError("Rate must be in range 0-255")
        try:
            self._write(rate, 0x19, self.mpu_addr)
        except OSError:
            raise MPUException(self._I2Cerror)

    # Low pass filters. Using the filter_range property of the MPU9250 is
    # harmless but gyro_filter_range is preferred and offers an extra setting.
    @property
    def filter_range(self):

        try:
            self._read(self.buf1, 0x1A, self.mpu_addr)
            res = self.buf1[0] & 7
        except OSError:
            raise MPUException(self._I2Cerror)
        return res

    @filter_range.setter
    def filter_range(self, filt):

        # set range
        if filt in range(7):
            try:
                self._write(filt, 0x1A, self.mpu_addr)
            except OSError:
                raise MPUException(self._I2Cerror)
        else:
            raise ValueError('Filter coefficient must be between 0 and 6')

    # accelerometer range
    @property
    def accel_range(self):

        try:
            self._read(self.buf1, 0x1C, self.mpu_addr)
            ari = self.buf1[0]//8
        except OSError:
            raise MPUException(self._I2Cerror)
        return ari

    @accel_range.setter
    def accel_range(self, accel_range):

        ar_bytes = (0x00, 0x08, 0x10, 0x18)
        if accel_range in range(len(ar_bytes)):
            try:
                self._write(ar_bytes[accel_range], 0x1C, self.mpu_addr)
            except OSError:
                raise MPUException(self._I2Cerror)
        else:
            raise ValueError('accel_range can only be 0, 1, 2 or 3')

    # gyroscope range
    @property
    def gyro_range(self):

        try:
            self._read(self.buf1, 0x1B, self.mpu_addr)
            gri = self.buf1[0]//8
        except OSError:
            raise MPUException(self._I2Cerror)
        return gri

    @gyro_range.setter
    def gyro_range(self, gyro_range):

        gr_bytes = (0x00, 0x08, 0x10, 0x18)
        if gyro_range in range(len(gr_bytes)):
            try:
                self._write(gr_bytes[gyro_range], 0x1B, self.mpu_addr)  # Sets fchoice = b11 which enables filter
            except OSError:
                raise MPUException(self._I2Cerror)
        else:
            raise ValueError('gyro_range can only be 0, 1, 2 or 3')

    # Accelerometer
    @property
    def accel(self):

        return self._accel

    def _accel_callback(self):
 
        try:
            self._read(self.buf6, 0x3B, self.mpu_addr)
        except OSError:
            raise MPUException(self._I2Cerror)
        self._accel._ivector[0] = bytes_toint(self.buf6[0], self.buf6[1])
        self._accel._ivector[1] = bytes_toint(self.buf6[2], self.buf6[3])
        self._accel._ivector[2] = bytes_toint(self.buf6[4], self.buf6[5])
        scale = (16384, 8192, 4096, 2048)
        self._accel._vector[0] = self._accel._ivector[0]/scale[self.accel_range]
        self._accel._vector[1] = self._accel._ivector[1]/scale[self.accel_range]
        self._accel._vector[2] = self._accel._ivector[2]/scale[self.accel_range]

    def get_accel_irq(self):

        self._read(self.buf6, 0x3B, self.mpu_addr)
        self._accel._ivector[0] = bytes_toint(self.buf6[0], self.buf6[1])
        self._accel._ivector[1] = bytes_toint(self.buf6[2], self.buf6[3])
        self._accel._ivector[2] = bytes_toint(self.buf6[4], self.buf6[5])

    # Gyro
    @property
    def gyro(self):

        return self._gyro

    def _gyro_callback(self):
  
        try:
            self._read(self.buf6, 0x43, self.mpu_addr)
        except OSError:
            raise MPUException(self._I2Cerror)
        self._gyro._ivector[0] = bytes_toint(self.buf6[0], self.buf6[1])
        self._gyro._ivector[1] = bytes_toint(self.buf6[2], self.buf6[3])
        self._gyro._ivector[2] = bytes_toint(self.buf6[4], self.buf6[5])
        scale = (131, 65.5, 32.8, 16.4)
        self._gyro._vector[0] = self._gyro._ivector[0]/scale[self.gyro_range]
        self._gyro._vector[1] = self._gyro._ivector[1]/scale[self.gyro_range]
        self._gyro._vector[2] = self._gyro._ivector[2]/scale[self.gyro_range]

    def get_gyro_irq(self):

        self._read(self.buf6, 0x43, self.mpu_addr)
        self._gyro._ivector[0] = bytes_toint(self.buf6[0], self.buf6[1])
        self._gyro._ivector[1] = bytes_toint(self.buf6[2], self.buf6[3])
        self._gyro._ivector[2] = bytes_toint(self.buf6[4], self.buf6[5])
and vector 3d is the same as Github

@Roberthh , thank you for the line and I did the update according to this but I did'nt get the same stability of values as yours .

This my code as you mentionned ( see code below ):

Code: Select all

import machine
class accel():

    def __init__(self, i2c, addr=0x68):

        self.iic = i2c
        self.addr = addr
        #self.iic.writeto(self.addr, bytearray([107, 0]))
        self.iic.writeto_mem(self.addr, 0x1a, b'\x06')

    def get_raw_values(self):

        a = self.iic.readfrom_mem(self.addr, 0x3B, 14)
        return a

    def get_ints(self):

        b = self.get_raw_values()
        c = []
        for i in b:
            c.append(i)
        return c

    def bytes_toint(self, firstbyte, secondbyte):

        if not firstbyte & 0x80:
            return firstbyte << 8 | secondbyte
        return - (((firstbyte ^ 255) << 8) | (secondbyte ^ 255) + 1)

    def get_values(self):

        raw_ints = self.get_raw_values()
        vals = {}

        vals["AcX"] = self.bytes_toint(raw_ints[0], raw_ints[1])
        vals["AcY"] = self.bytes_toint(raw_ints[2], raw_ints[3])
        vals["AcZ"] = self.bytes_toint(raw_ints[4], raw_ints[5])
        vals["Tmp"] = self.bytes_toint(raw_ints[6], raw_ints[7]) / 340.00 + 36.53
        vals["GyX"] = self.bytes_toint(raw_ints[8], raw_ints[9])
        vals["GyY"] = self.bytes_toint(raw_ints[10], raw_ints[11])
        vals["GyZ"] = self.bytes_toint(raw_ints[12], raw_ints[13])

        return vals  # returned in range of Int16

        # -32768 to 32767

    def get_smoothed_values(self, n_samples=10):

        result = self.get_values()
        for _ in range(0, n_samples - 1):
            data = self.get_values()
            for key in data.keys():
                result[key] += data[key]
        for key in data.keys():
            result[key] /= n_samples
        return result

    def calibrate(self, threshold=50, n_samples=100):

        while True:
            v1 = self.get_smoothed_values(n_samples)
            v2 = self.get_smoothed_values(n_samples)
        # Check all consecutive measurements are within
        # the threshold. We use abs() so all calculated
        # differences are positive.
            if all(abs(v1[key] - v2[key]) < threshold for key in v1.keys()):
                return v1  # Calibrated.

    # ONLY FOR TESTING! Also, fast reading sometimes crashes IIC
    def val_test(self):
        from time import sleep
        while 1:
            print(self.get_values())
            sleep(0.05)


User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Gyro/Mpu_Calibration "ESP8266"

Post by Roberthh » Wed Apr 24, 2019 5:42 am

The statement:

Code: Select all

self.iic.writeto(self.addr, bytearray([107, 0]))
is required to initialize the device, so please do not skip it.

samerou
Posts: 38
Joined: Mon Feb 11, 2019 12:51 pm

Re: Gyro/Mpu_Calibration "ESP8266"

Post by samerou » Wed Apr 24, 2019 7:11 am

Roberthh wrote:
Wed Apr 24, 2019 5:42 am
The statement:

Code: Select all

self.iic.writeto(self.addr, bytearray([107, 0]))
is required to initialize the device, so please do not skip it.
Thank you Roberthh as a result I get this

Code: Select all

{'GyZ': 103.6, 'GyY': 129.3, 'GyX': -90.9, 'Tmp': 42.5949, 'AcZ': -3004.8, 'AcY': -41.2, 'AcX': 16510.4}
{'GyZ': 102.2, 'GyY': 129.1, 'GyX': -90.7, 'Tmp': 42.597, 'AcZ': -3028.0, 'AcY': -31.2, 'AcX': 16490.4}
{'GyZ': 101.0, 'GyY': 131.5, 'GyX': -91.2, 'Tmp': 42.5947, 'AcZ': -3041.2, 'AcY': -13.6, 'AcX': 16505.6}
{'GyZ': 100.2, 'GyY': 132.2, 'GyX': -92.0, 'Tmp': 42.5985, 'AcZ': -3047.2, 'AcY': -29.6, 'AcX': 16487.6}
{'GyZ': 102.1, 'GyY': 133.9, 'GyX': -94.8, 'Tmp': 42.6091, 'AcZ': -3060.0, 'AcY': -37.2, 'AcX': 16482.8}
{'GyZ': 101.2, 'GyY': 134.0, 'GyX': -92.9, 'Tmp': 42.6079, 'AcZ': -3051.2, 'AcY': -45.2, 'AcX': 16501.6}
{'GyZ': 100.9, 'GyY': 134.7, 'GyX': -88.6, 'Tmp': 42.6085, 'AcZ': -3042.8, 'AcY': -38.8, 'AcX': 16505.2}
{'GyZ': 102.8, 'GyY': 129.7, 'GyX': -87.3, 'Tmp': 42.6053, 'AcZ': -3043.6, 'AcY': -3.2, 'AcX': 16467.6}
{'GyZ': 102.0, 'GyY': 129.3, 'GyX': -89.6, 'Tmp': 42.6044, 'AcZ': -3018.0, 'AcY': -42.0, 'AcX': 16492.8}
{'GyZ': 98.3, 'GyY': 130.1, 'GyX': -87.1, 'Tmp': 42.5961, 'AcZ': -3040.0, 'AcY': -17.6, 'AcX': 16503.2}

I think it's a more logic , just a question is it difficult to add formulas in order to make just a really exact values when the device is not Moving ?

B.Regards
Last edited by samerou on Wed Apr 24, 2019 9:29 am, edited 1 time in total.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Gyro/Mpu_Calibration "ESP8266"

Post by pythoncoder » Wed Apr 24, 2019 7:16 am

@samerou The "bad chip ID" indicates that your chip is not a genuine InvenSense MPU-6050. This chip has been obsolete for a long time: even the MPU-9150 is obsolete with only the MPU-9250 currently manufactured.

So I would question exactly what hardware you are using. This may be affecting your other results.

If you want to live dangerously you could comment out line 105 in imu.py:

Code: Select all

        self.chip_id                     # Test communication by reading chip_id: throws exception on error
This would disable the check. But with an unknown device all bets of decent results are off.
Peter Hinch
Index to my micropython libraries.

samerou
Posts: 38
Joined: Mon Feb 11, 2019 12:51 pm

Re: Gyro/Mpu_Calibration "ESP8266"

Post by samerou » Wed Apr 24, 2019 8:38 am

pythoncoder wrote:
Wed Apr 24, 2019 7:16 am
@samerou The "bad chip ID" indicates that your chip is not a genuine InvenSense MPU-6050. This chip has been obsolete for a long time: even the MPU-9150 is obsolete with only the MPU-9250 currently manufactured.

So I would question exactly what hardware you are using. This may be affecting your other results.

If you want to live dangerously you could comment out line 105 in imu.py:

Code: Select all

        self.chip_id                     # Test communication by reading chip_id: throws exception on error
This would disable the check. But with an unknown device all bets of decent results are off.
I'm using " MPU6050 - GY521 ACCELEROMETRE ET GYROSCOPE 3 AXES" and UPYcraft as plateform for developpment

Post Reply