Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Glove #371

Open
wants to merge 37 commits into
base: main
Choose a base branch
from
Open

Glove #371

Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6dcb209
Add calibration reading commands for BNO08X
Eirenliel Aug 5, 2024
796c52f
Disable accelerometer calibration 1 minute after start up on BNO08X
Eirenliel Aug 5, 2024
b5c26f4
Work on new sensor interface to abstract I2C hardware
Eirenliel Aug 6, 2024
0f0e9de
Fix compile errors
Eirenliel Aug 6, 2024
d6a935d
Abstract int pin and add multiplexer libraries
Eirenliel Aug 28, 2024
832f182
Update IMU list to use new interfaces
Eirenliel Aug 28, 2024
6b412d0
Make other IMUs definable, not only BNOx
Eirenliel Aug 28, 2024
0529f0f
Fix build for ESP32
Eirenliel Aug 28, 2024
5f0e244
Add TPS tracking code
Eirenliel Aug 30, 2024
7cbc873
Add PCA9546A support & glove imus list
Eirenliel Aug 30, 2024
beab567
WIP use pointers properly
Eirenliel Sep 3, 2024
4447266
I love C++ <3
Eirenliel Sep 5, 2024
0eb1d55
c++ is magic
Eirenliel Sep 5, 2024
e5b3041
Fix build error because of typo
Eirenliel Sep 5, 2024
d4e2fc1
Fix warnings
Eirenliel Sep 5, 2024
9d58899
Fix pinouts and some other issues
Eirenliel Sep 25, 2024
7acbd48
Fix I2C with multiplexer
Eirenliel Oct 8, 2024
c5fdc7c
Implement sending bone position
Eirenliel Oct 9, 2024
2464200
Add tracker type to the protocol
Eirenliel Oct 9, 2024
40086f8
Work on analog sensors support
Eirenliel Oct 9, 2024
01527df
Fix build errors
Eirenliel Oct 9, 2024
4995aa4
Fix rebase conflict
Eirenliel Nov 15, 2024
845e468
Apply formatting
Eirenliel Nov 15, 2024
be8472a
Update protocol to match server
Eirenliel Nov 18, 2024
f6e5988
Fix thumb bone names
Eirenliel Nov 25, 2024
df7b64d
Add an important comment
Eirenliel Nov 25, 2024
8898819
Fix protocol compatibility
Eirenliel Dec 7, 2024
0a8676e
Update defines for default configuration
Eirenliel Dec 7, 2024
add0035
Minor comments and cleanups
Eirenliel Dec 7, 2024
1f87604
Format defines
Eirenliel Dec 7, 2024
9642b38
Formatting
Eirenliel Dec 7, 2024
b1a29dd
Merge branch 'main' into glove
Eirenliel Dec 10, 2024
3bb0293
Formatting with proper clang
Eirenliel Dec 19, 2024
2c5aea5
Merge branch 'main' into glove
Eirenliel Dec 19, 2024
2800d39
Fucking clang
Eirenliel Dec 19, 2024
9fc58c5
Merge branch 'main' into glove
Eirenliel Jan 2, 2025
62f27c5
Minor fixes after merge
Eirenliel Jan 9, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 66 additions & 21 deletions lib/bno080/BNO080.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@

//Attempt communication with the device
//Return true if we got a 'Polo' back from Marco
boolean BNO080::begin(uint8_t deviceAddress, TwoWire &wirePort, uint8_t intPin)
boolean BNO080::begin(uint8_t deviceAddress, TwoWire &wirePort, PinInterface* intPin)
{
_deviceAddress = deviceAddress; //If provided, store the I2C address from user
_i2cPort = &wirePort; //Grab which port the user wants us to use
_int = intPin; //Get the pin that the user wants to use for interrupts. By default, it's 255 and we'll not use it in dataAvailable() function.
if (_int != 255)
if (_int != nullptr)
{
pinMode(_int, INPUT_PULLUP);
_int->pinMode(INPUT_PULLUP);
}

//We expect caller to begin their I2C port, with the speed of their choice external to the library
Expand Down Expand Up @@ -99,7 +99,7 @@ boolean BNO080::begin(uint8_t deviceAddress, TwoWire &wirePort, uint8_t intPin)
return tBoardInfoReceived;
}

boolean BNO080::beginSPI(uint8_t user_CSPin, uint8_t user_WAKPin, uint8_t user_INTPin, uint8_t user_RSTPin, uint32_t spiPortSpeed, SPIClass &spiPort)
boolean BNO080::beginSPI(PinInterface* user_CSPin, PinInterface* user_WAKPin, PinInterface* user_INTPin, PinInterface* user_RSTPin, uint32_t spiPortSpeed, SPIClass &spiPort)
{
_i2cPort = NULL; //This null tells the send/receive functions to use SPI

Expand All @@ -114,18 +114,18 @@ boolean BNO080::beginSPI(uint8_t user_CSPin, uint8_t user_WAKPin, uint8_t user_I
_int = user_INTPin;
_rst = user_RSTPin;

pinMode(_cs, OUTPUT);
pinMode(_wake, OUTPUT);
pinMode(_int, INPUT_PULLUP);
pinMode(_rst, OUTPUT);
_cs->pinMode(OUTPUT);
_wake->pinMode(OUTPUT);
_int->pinMode(INPUT_PULLUP);
_rst->pinMode(OUTPUT);

digitalWrite(_cs, HIGH); //Deselect BNO080
_cs->digitalWrite(HIGH); //Deselect BNO080

//Configure the BNO080 for SPI communication
digitalWrite(_wake, HIGH); //Before boot up the PS0/WAK pin must be high to enter SPI mode
digitalWrite(_rst, LOW); //Reset BNO080
_wake->digitalWrite(HIGH); //Before boot up the PS0/WAK pin must be high to enter SPI mode
_rst->digitalWrite(LOW); //Reset BNO080
delay(2); //Min length not specified in datasheet?
digitalWrite(_rst, HIGH); //Bring out of reset
_rst->digitalWrite(HIGH); //Bring out of reset

//Wait for first assertion of INT before using WAK pin. Can take ~104ms
waitForSPI();
Expand Down Expand Up @@ -203,9 +203,9 @@ uint16_t BNO080::getReadings(void)
//If we have an interrupt pin connection available, check if data is available.
//If int pin is not set, then we'll rely on receivePacket() to timeout
//See issue 13: https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/issues/13
if (_int != 255)
if (_int != nullptr)
{
if (digitalRead(_int) == HIGH)
if (_int->digitalRead() == HIGH)
return 0;
}

Expand Down Expand Up @@ -256,6 +256,13 @@ uint16_t BNO080::parseCommandReport(void)
if (command == COMMAND_ME_CALIBRATE)
{
calibrationStatus = shtpData[5 + 0]; //R0 - Status (0 = success, non-zero = fail)
_calibrationResponseStatus = shtpData[5 + 0];
_accelCalEnabled = shtpData[6 + 0];
_gyroCalEnabled = shtpData[7 + 0];
_magCalEnabled = shtpData[8 + 0];
_planarAccelCalEnabled = shtpData[9 + 0];
_onTableCalEnabled = shtpData[10 + 0];
_hasNewCliabrationStatus = true;
}
return shtpData[0];
}
Expand Down Expand Up @@ -1381,6 +1388,7 @@ void BNO080::sendCalibrateCommand(uint8_t thingToCalibrate)

//Make the internal calStatus variable non-zero (operation failed) so that user can test while we wait
calibrationStatus = 1;
_hasNewCliabrationStatus = false;

//Using this shtpData packet, send a command
sendCommand(COMMAND_ME_CALIBRATE);
Expand All @@ -1404,7 +1412,7 @@ void BNO080::requestCalibrationStatus()
shtpData[x] = 0;

shtpData[6] = 0x01; //P3 - 0x01 - Subcommand: Get ME Calibration

_hasNewCliabrationStatus = false;
//Using this shtpData packet, send a command
sendCommand(COMMAND_ME_CALIBRATE);
}
Expand All @@ -1430,6 +1438,43 @@ void BNO080::saveCalibration()
sendCommand(COMMAND_DCD); //Save DCD command
}

void BNO080::saveCalibrationPeriodically(bool save)
{
/*shtpData[3] = 0; //P0 - Enable/Disable Periodic DCD Save
shtpData[4] = 0; //P1 - Reserved
shtpData[5] = 0; //P2 - Reserved
shtpData[6] = 0; //P3 - Reserved
shtpData[7] = 0; //P4 - Reserved
shtpData[8] = 0; //P5 - Reserved
shtpData[9] = 0; //P6 - Reserved
shtpData[10] = 0; //P7 - Reserved
shtpData[11] = 0; //P8 - Reserved*/

for (uint8_t x = 3; x < 12; x++) //Clear this section of the shtpData array
shtpData[x] = 0;
shtpData[3] = save ? 1 : 0;

//Using this shtpData packet, send a command
sendCommand(COMMAND_DCD_PERIOD_SAVE); //Save DCD command
}

bool BNO080::hasNewCliabrationStatus()
{
return _hasNewCliabrationStatus;
}

void BNO080::getCalibrationStatus(uint8_t &calibrationResponseStatus, uint8_t &accelCalEnabled, uint8_t &gyroCalEnabled, uint8_t &magCalEnabled, uint8_t &planarAccelCalEnabled, uint8_t &onTableCalEnabled)
{
_hasNewCliabrationStatus = false;
calibrationResponseStatus = _calibrationResponseStatus;
accelCalEnabled = _accelCalEnabled;
gyroCalEnabled = _gyroCalEnabled;
magCalEnabled = _magCalEnabled;
planarAccelCalEnabled = _planarAccelCalEnabled;
onTableCalEnabled = _onTableCalEnabled;
}


//Wait a certain time for incoming I2C bytes before giving up
//Returns false if failed
boolean BNO080::waitForI2C()
Expand Down Expand Up @@ -1460,7 +1505,7 @@ boolean BNO080::waitForSPI()
{
for (uint8_t counter = 0; counter < 125; counter++) //Don't got more than 255
{
if (digitalRead(_int) == LOW)
if (_int->digitalRead() == LOW)
return (true);
if (_printDebug == true)
_debugPort->println(F("SPI Wait"));
Expand All @@ -1478,15 +1523,15 @@ boolean BNO080::receivePacket(void)
{
if (_i2cPort == NULL) //Do SPI
{
if (digitalRead(_int) == HIGH)
if (_int->digitalRead() == HIGH)
return (false); //Data is not available

//Old way: if (waitForSPI() == false) return (false); //Something went wrong

//Get first four bytes to find out how much data we need to read

_spiPort->beginTransaction(SPISettings(_spiPortSpeed, MSBFIRST, SPI_MODE3));
digitalWrite(_cs, LOW);
_cs->digitalWrite(LOW);

//Get the first four bytes, aka the packet header
uint8_t packetLSB = _spiPort->transfer(0);
Expand Down Expand Up @@ -1521,7 +1566,7 @@ boolean BNO080::receivePacket(void)
shtpData[dataSpot] = incoming; //Store data into the shtpData array
}

digitalWrite(_cs, HIGH); //Release BNO080
_cs->digitalWrite(HIGH); //Release BNO080

_spiPort->endTransaction();
printPacket();
Expand Down Expand Up @@ -1627,7 +1672,7 @@ boolean BNO080::sendPacket(uint8_t channelNumber, uint8_t dataLength)
//BNO080 has max CLK of 3MHz, MSB first,
//The BNO080 uses CPOL = 1 and CPHA = 1. This is mode3
_spiPort->beginTransaction(SPISettings(_spiPortSpeed, MSBFIRST, SPI_MODE3));
digitalWrite(_cs, LOW);
_cs->digitalWrite(LOW);

//Send the 4 byte packet header
_spiPort->transfer(packetLength & 0xFF); //Packet length LSB
Expand All @@ -1641,7 +1686,7 @@ boolean BNO080::sendPacket(uint8_t channelNumber, uint8_t dataLength)
_spiPort->transfer(shtpData[i]);
}

digitalWrite(_cs, HIGH);
_cs->digitalWrite(HIGH);
_spiPort->endTransaction();
}
else //Do I2C
Expand Down
24 changes: 16 additions & 8 deletions lib/bno080/BNO080.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@

#include <Wire.h>
#include <SPI.h>
#include <memory>
#include "PinInterface.h"

//The default I2C address for the BNO080 on the SparkX breakout is 0x4B. 0x4A is also possible.
#define BNO080_DEFAULT_ADDRESS 0x4B
Expand Down Expand Up @@ -150,8 +152,8 @@ struct BNO080Error {
class BNO080
{
public:
boolean begin(uint8_t deviceAddress = BNO080_DEFAULT_ADDRESS, TwoWire &wirePort = Wire, uint8_t intPin = 255); //By default use the default I2C addres, and use Wire port, and don't declare an INT pin
boolean beginSPI(uint8_t user_CSPin, uint8_t user_WAKPin, uint8_t user_INTPin, uint8_t user_RSTPin, uint32_t spiPortSpeed = 3000000, SPIClass &spiPort = SPI);
boolean begin(uint8_t deviceAddress = BNO080_DEFAULT_ADDRESS, TwoWire &wirePort = Wire, PinInterface* intPin = nullptr); //By default use the default I2C addres, and use Wire port, and don't declare an INT pin
boolean beginSPI(PinInterface* user_CSPin, PinInterface* user_WAKPin, PinInterface* user_INTPin, PinInterface* user_RSTPin, uint32_t spiPortSpeed = 3000000, SPIClass &spiPort = SPI);

void enableDebugging(Stream &debugPort = Serial); //Turn on debug printing. If user doesn't specify then Serial will be used.

Expand Down Expand Up @@ -237,11 +239,13 @@ class BNO080
float getMagY();
float getMagZ();
uint8_t getMagAccuracy();

void endCalibration();
void saveCalibration();
void requestCalibrationStatus(); //Sends command to get status
boolean calibrationComplete(); //Checks ME Cal response for byte 5, R0 - Status
bool calibrationComplete(); //Checks ME Cal response for byte 5, R0 - Status
bool hasNewCliabrationStatus();
void getCalibrationStatus(uint8_t &calibrationResponseStatus, uint8_t &accelCalEnabled, uint8_t &gyroCalEnabled, uint8_t &magCalEnabled, uint8_t &planarAccelCalEnabled, uint8_t &onTableCalEnabled);

uint8_t getTapDetector();
bool getTapDetected();
Expand Down Expand Up @@ -270,6 +274,7 @@ class BNO080
void setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports, uint32_t specificConfig);
void sendCommand(uint8_t command);
void sendCalibrateCommand(uint8_t thingToCalibrate);
void saveCalibrationPeriodically(bool save);

//Metadata functions
int16_t getQ1(uint16_t recordID);
Expand Down Expand Up @@ -308,10 +313,10 @@ class BNO080

SPIClass *_spiPort; //The generic connection to user's chosen SPI hardware
unsigned long _spiPortSpeed; //Optional user defined port speed
uint8_t _cs; //Pins needed for SPI
uint8_t _wake;
uint8_t _int;
uint8_t _rst;
PinInterface* _cs; //Pins needed for SPI
PinInterface* _wake;
PinInterface* _int;
PinInterface* _rst;

//These are the raw sensor values (without Q applied) pulled from the user requested Input Report
uint16_t rawAccelX, rawAccelY, rawAccelZ, accelAccuracy;
Expand Down Expand Up @@ -344,4 +349,7 @@ class BNO080
int16_t gyro_Q1 = 9;
int16_t magnetometer_Q1 = 4;
int16_t angular_velocity_Q1 = 10;

bool _hasNewCliabrationStatus = false;
uint8_t _calibrationResponseStatus, _accelCalEnabled, _gyroCalEnabled, _magCalEnabled, _planarAccelCalEnabled, _onTableCalEnabled;
};
37 changes: 37 additions & 0 deletions lib/bno080/PinInterface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
SlimeVR Code is placed under the MIT license
Copyright (c) 2024 Eiren Rain & SlimeVR contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _H_PIN_INTERFACE_
#define _H_PIN_INTERFACE_

#include <Arduino.h>

class PinInterface
{
public:
virtual int digitalRead();
virtual void pinMode(uint8_t mode);
virtual void digitalWrite(uint8_t val);

};

#endif // _H_PIN_INTERFACE_
2 changes: 2 additions & 0 deletions platformio-tools.ini
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
lib_deps=
https://github.com/SlimeVR/CmdParser.git
https://github.com/SlimeVR/base64_arduino.git
https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library.git
https://github.com/hideakitai/PCA9547.git
monitor_speed = 115200
framework = arduino
build_flags =
Expand Down
5 changes: 4 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ build_cache_dir = cache
lib_deps=
https://github.com/SlimeVR/CmdParser.git
https://github.com/SlimeVR/base64_arduino.git
https://github.com/adafruit/Adafruit-MCP23017-Arduino-Library.git
https://github.com/hideakitai/PCA9547.git
monitor_speed = 115200
monitor_echo = yes
monitor_filters = colorize
Expand Down Expand Up @@ -109,6 +111,7 @@ upload_speed = 921600
; ${env.build_flags}
; -DESP32C3
;board = lolin_c3_mini
;monitor_filters = colorize, esp32_exception_decoder

; If you want to use a ESP32C6, you can use this (experimental)
;[env:esp32c6]
Expand All @@ -118,4 +121,4 @@ upload_speed = 921600
; ${env.build_flags}
; -DESP32C6
; -DARDUINO_USB_MODE=1
; -DARDUINO_USB_CDC_ON_BOOT=1
; -DARDUINO_USB_CDC_ON_BOOT=1
16 changes: 14 additions & 2 deletions src/consts.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ enum class ImuID {
LSM6DSV,
LSM6DSO,
LSM6DSR,
ADC_RESISTANCE,
Empty = 255
};

Expand Down Expand Up @@ -83,9 +84,10 @@ enum class ImuID {
#define BOARD_MOCOPI 15 // Used by mocopi/moslime
#define BOARD_WEMOSWROOM02 16
#define BOARD_XIAO_ESP32C3 17
#define BOARD_HARITORA 18 // Used by Haritora/SlimeTora
#define BOARD_HARITORA 18 // Used by Haritora/SlimeTora
#define BOARD_ES32C6DEVKITC1 19
#define BOARD_DEV_RESERVED 250 // Reserved, should not be used in any release firmware
#define BOARD_GLOVE_IMU_SLIMEVR_DEV 20 // IMU Glove
#define BOARD_DEV_RESERVED 250 // Reserved, should not be used in any release firmware

#define BAT_EXTERNAL 1
#define BAT_INTERNAL 2
Expand Down Expand Up @@ -143,6 +145,14 @@ enum class ImuID {
#define MCU_HARITORA 8 // Used by Haritora/SlimeTora
#define MCU_DEV_RESERVED 250 // Reserved, should not be used in any release firmware

#define SENSOR_DATATYPE_ROTATION 0
#define SENSOR_DATATYPE_FLEX_RESISTANCE 1
#define SENSOR_DATATYPE_FLEX_ANGLE 2

#define TRACKER_TYPE_SVR_ROTATION 0
#define TRACKER_TYPE_SVR_GLOVE_LEFT 1
#define TRACKER_TYPE_SVR_GLOVE_RIGHT 1

#ifdef ESP8266
#define HARDWARE_MCU MCU_ESP8266
#elif defined(ESP32)
Expand All @@ -153,4 +163,6 @@ enum class ImuID {

#define CURRENT_CONFIGURATION_VERSION 1

#include "sensors/sensorposition.h"

#endif // SLIMEVR_CONSTS_H_
2 changes: 1 addition & 1 deletion src/debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
// Not recommended for production
#define ENABLE_INSPECTION false

#define PROTOCOL_VERSION 18
#define PROTOCOL_VERSION 19

#ifndef FIRMWARE_VERSION
#define FIRMWARE_VERSION "UNKNOWN"
Expand Down
Loading
Loading