r-owen / microBlocksXRP

microBlocks code to run the wheels on the XRP robot kit
2 stars 1 forks source link

Library Dev for XRP IMU for Gyro Sensor #1

Open scspaeth opened 2 months ago

scspaeth commented 2 months ago

I tried to add the MicroBlocks program that you requested as an attachment to this issue. GitHub refused to accept it because they don't support that file type. I'll try another way.

scspaeth commented 2 months ago

GP Scripts depends 'PicoW-XRP_v1.1'

spec 'r' 'LSM6DSOX_gyro' 'LSM6DSOX _' 'auto' 10 to LSM6DSOX_gyro i2c_get_block { comment 'LSM6DSOX is an i2c device that senses acceleration and gyroscopic motion. This block takes an i2c_get_block with address and register parameters described in the datasheet. IMUs in this family are used on other platforms so Acc data are part of the basic sensors library. Gyroscopes are less frequently used on platforms so we need this Gyro library. The LSM6DSOX has additional functions but they are not developed in this library.' local 'val' 0 val = i2c_get_block if (val >= 128) { val = (val - 256) } else { val = val } if (val < -127) { val = -127 } val = ((val * 200) / 127) return val }

script 1271 103 { comment 'LSM6DSOX https://www.st.com/en/mems-and-sensors/lsm6dsox.html' comment 'XRP''s solder jumper IMU_ADR controls the IMU address. Default value is 0X6B (107). NOTE: differs from the Clue address which is 0X6A.0X Can be changed semi-permanently to 0X6A by cutting the jumper. Ref: https://docs.sparkfun.com/SparkFun_XRP_Controller/hardware_overview/#solde6B' comment '23-10-11: verified that these scripts work for reading Clue Acc and Gyr. Determined that XRP uses the alternate IMU address(107). Substituted the XRP_IMU_adr and tested scripts for both Acc and Gyr Did not work for either Acc or Gyr. Tried using the H/L alternate registers. Neither of them worked.' comment 'Try getting accXRaw data out and only get 0 responses. Then set the accelerometer device register 0x10 to 0x80 for 1660 Hz rate Try to get accXRaw data out after initializing. Success for Clue but not for XRP with a RPiPicoW vm! Switched vm to Pico.ed and now it works for getting IMU data but other XRP functions that work for PicoW.vm no longer work. TODO: need to create a XRP.vm that leaves the PicoW functionality intack and accomodates the pin assignments for the IMU that Pico.ed uses. ' comment '23-10-13: i2c get device reports error codes indicating no i2c devices connected. Found pin assignments for XRP i2c are sda:19, scl: 18. Clue uses a different pair So it makes sense that (i2c get device) won''t find data from the IMU. These i2c pin assignments are made in the platform specific vm firmware: https://bitbucket.org/john_maloney/smallvm /src/88d530121f450a22cb4c42cd593b243dd6a5b923/vm/sensorPrims.cpp#lines-23:27 Coincidentally, the designers of the Electfreaks pico-ed board chose the same pair of pins for their design. So, I am testing the possibility that using the pico-ed firmware will make it possible to read the XRP''s IMU. Of course, other functions of the XRP will not work properly but I will know whether it is worth the time and effort to create a platform specific firmware for the XRP. Result: YES the pico-ed firmware allows Microblocks to address the XRP''s IMU and pull acc and gyro data from it. With success in getting data out of the IMU, I now have confidence to create the platform specific vm using PlatformIO. I took an existing vm and simply tried to build it and load onto bare RPiPico-W. Commented out the m5stack+ envioronment because it gave error messages for non-conformance. Needed to save the file to get PlatformIO to accept my changes. Results: pico-w SUCCESS 00:04:34.951 The OSX finder complained that the device was removed unexpectedly. The Microblocks IDE connected to the board and ran the [set user LED (Or)] as intended! ' }

script 1332 783 (i2cGet XRP_IMUadr (hexToInt '2'))

script 458 2085 { to LSM6DSOX_gyro i2c_get_block {} }

script 454 96 { comment 'Open the Graph Display. Start this script. Change the pitch, roll and yaw to see responses as scaled angular velocities.' '_xrp_init_pins' XRP_IMU_adr = (hexToInt '6B') sayIt 'Setting IMU adr Clue:6A, XRP:6B' waitMillis 1000 i2cSet XRP_IMU_adr (hexToInt '10') (hexToInt '80') sayIt 'Initializing the gyro registers of the IMU' waitMillis 1000 comment 'Reference: https://www.st.com/resource/en/datasheet/lsm6dsl.pdf p.61

Try getting gyrXRaw data out and only get 0 responses. Then set the accelerometer/gyro device register 0x11 to 0x80 for 1660 Hz rate Try to get gyrXRaw data out after initializing. Success! The initialization activates the gyro data registers for XY and Z Now I need to understand the scaling algorithm to get positive and negative angular velocities out.' i2cSet XRP_IMU_adr (hexToInt '11') (hexToInt '80') comment 'Plot gyrX,Y,Z of the XRP IMU' repeat 1000 { printIt (LSM6DSOX_gyro (i2cGet XRP_IMU_adr (hexToInt '23'))) (LSM6DSOX_gyro (i2cGet XRP_IMU_adr (hexToInt '25'))) (LSM6DSOX_gyro (i2cGet XRP_IMU_adr (hexToInt '27'))) waitMillis 100 } }

script 477 812 { comment 'Historical development and credit to prior work:' comment 'John Maloney provides an algorithm for transforming accel raw data into MB tilts: https://bitbucket.org/john_maloney/smallvm/ src/1d8e7b664850a1fcd41f88e5900a57f947f6c994/vm/sensorPrims.cpp ?at=master#lines-692 He uses the short form of an if else statement.

x = (condition) ? (value_if_true) : (value_if_false); https://cplusplus.com/forum/beginner/32292/#msg174367

I may be able to construct an equivalent expression in MB.

Yes, apparently so. I created the equivalent script in MB to the C++ in Maloney. It produces gyrX patterns similar to what I expect for typical gyro data. TODO: Reflect on this experiment and consolidate and improve it for sharing.' repeat 1000 { gyrXRaw = (i2cGet XRP_IMU_adr (hexToInt '23')) gyrXCal = gyrXRaw if (gyrXCal >= 128) { gyrXCal = (gyrXCal - 256) } else { gyrXCal = gyrXCal } if (gyrXCal < -127) { gyrXCal = -127 } gyrXCal = ((gyrXCal * 200) / 127) printIt gyrXCal waitMillis 100 } return gyrXCal }

scspaeth commented 2 months ago

Let me know if you'd prefer another option.

scspaeth commented 2 months ago

Yet another representation:

XRPGyroLibDev

scspaeth commented 2 months ago

Previous pic did not include all scripts in the file: XRPGyroLibDev

r-owen commented 2 months ago

This all looks great. Thank you very much!

scspaeth commented 2 months ago

I'm looking forward to using your work. Thank you.

r-owen commented 2 months ago

It works! Here is my simplified version.

module 'XPRGyro'
author SCSpaeth
version 1 0 
description 'Read XRP LSM6DSOX gyroscope rates'

spec ' ' 'read_gyro_speed' 'read_gyro_speed'
spec 'r' 'scale_gyro_speed' 'scale gyro raw speed _' 'num' 10

to read_gyro_speed {
    comment 'Open the Graph Display.
Start this script.
Change the pitch, roll and yaw to see responses as scaled angular velocities.'
    local 'XRP_IMU_addr' (hexToInt '6B')
    comment 'Set the accelerometer/gyro device register 0x11 to 0x80 for 1660 Hz rate
        This activates the gyro data registers for X, Y and Z.
        Reference: https://www.st.com/resource/en/datasheet/lsm6dsl.pdf p.61'
    i2cSet XRP_IMU_addr (hexToInt '11') (hexToInt '80')
    comment 'Plot gyrX,Y,Z of the XRP IMU'
    repeat 300 {
        printIt (
            scale_gyro_speed (i2cGet XRP_IMU_addr (hexToInt '23'))) (
            scale_gyro_speed (i2cGet XRP_IMU_addr (hexToInt '25'))) (
            scale_gyro_speed (i2cGet XRP_IMU_addr (hexToInt '27'))
        )
        waitMillis 100
    }
}

to scale_gyro_speed speed {
    comment 'Scale raw LSM6DSOX gyroscope speed data (to what units?).
Valid raw speed values are between 0 and 255, inclusive,
with the following unusual subranges:
* 0-127 represents positive values 0 through 127,
* 128-255 represents negative values -128 through -1.'
    comment 'Handle negative values.'
    if (speed >= 128) {
        speed = (speed - 256)
    }
    comment 'Scale the result to unknown units'
    speed = ((speed * 200) / 127)
    return speed
}
scspaeth commented 2 months ago

I'm pleased to see that this helped your work. I'll try to find time for some testing.