Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed CROTUS_XBee mbed-rtos Crotus_Com
Diff: Magneto.cpp
- Revision:
- 0:28d5622d1a3e
- Child:
- 1:3591e7df4ff4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Magneto.cpp Sun Mar 12 14:58:06 2017 +0000 @@ -0,0 +1,169 @@ +#include "Magneto.h" + +#define PI 3.14159265358979323f + +namespace { + char cmd[2]; + char buffer[6]; + + Ticker calibrationTicker; + + int16_t minX = OR_MAX_VALUE; // The maximum value is put in the min so real values will always be smaller + int16_t maxX = OR_MIN_VALUE; // The minimum value is put in the max so real values will always be bigger + int16_t minY = OR_MAX_VALUE; // The maximum value is put in the min so real values will always be smaller + int16_t maxY = OR_MIN_VALUE; // The minimum value is put in the max so real values will always be bigger + + int16_t offsetX = 0; + int16_t offsetY = 0; + + int16_t scaleX = 0; + int16_t scaleY = 0; + + void _UpdateScaleAndOffset(){ + offsetX = (maxX + minX)/2; + scaleX = maxX - offsetX; + + offsetY = (maxY + minY)/2; + scaleY = maxY - offsetY; + } + + void _UpdateCalibration(int16_t x, int16_t y){ + bool changed = false; + + if (x < minX){ + minX = x; + changed = true; + } + if (x > maxX){ + maxX = x; + changed = true; + } + + if (y < minY){ + minY = y; + changed = true; + } + if (y > maxY){ + maxY = y; + changed = true; + } + + if(changed || true){ + _UpdateScaleAndOffset(); + } + } + + LocalFileSystem local("local"); + + void _LoadCalibration(){ + FILE *fp = fopen("/local/magneto.cfg", "r"); // Open "out.txt" on the local file system for writing + // File doesn't exist + if (fp == 0){ + printf("File doesn't exist!!\r\n"); + return; + } + + fscanf(fp,"%04X %04X %04X %04X", &minX, &maxX, &minY, &maxY); + fclose(fp); + + _UpdateScaleAndOffset(); + } + + void _SaveCalibration(){ + FILE *fp = fopen("/local/magneto.cfg", "w"); // Open "out.txt" on the local file system for writing + fprintf(fp, "%04X %04X %04X %04X", minX & 0xFFFF, maxX & 0xFFFF, minY & 0xFFFF, maxY & 0xFFFF); + fclose(fp); + } +}; + +Magneto::Magneto(I2C & i2c) : +_i2c(&i2c) +{ + _LoadCalibration(); + + // Every 10 minutes + calibrationTicker.attach(_SaveCalibration, 6); +} + +bool Magneto::Test(){ + cmd[0] = MAGNETO_RA_ID_A; + + _i2c->write(MAGNETO_ADDRESS, cmd, 1, true); + _i2c->read(MAGNETO_ADDRESS, buffer, 3); + + return (buffer[0] == IR_A_VALUE) && + (buffer[1] == IR_B_VALUE) && + (buffer[2] == IR_C_VALUE); +} + +void Magneto::ActivateDevice(){ + cmd[0] = MAGNETO_RA_CONFIG_A; + cmd[1] = (CRA_SAMPLE_AVG_8 << CRA_SAMPLE_AVG_BIT) | (CRA_DATA_RATE_15 << CRA_DATA_RATE_BIT); + + _i2c->write(MAGNETO_ADDRESS, cmd, 2, false); + + cmd[0] = MAGNETO_RA_CONFIG_B; + cmd[1] = CRB_GAIN_130 << CRB_GAIN_BIT; + + _i2c->write(MAGNETO_ADDRESS, cmd, 2, false); + + cmd[0] = MAGNETO_RA_MODE; + cmd[1] = MR_MODE_CONTINUOUS << MR_MODE_BIT; + + _i2c->write(MAGNETO_ADDRESS, cmd, 2, false); +} + +void Magneto::ReadXZY(int16_t* raw){ + cmd[0] = MAGNETO_RA_X_MSB; + + _i2c->write(MAGNETO_ADDRESS, cmd, 1, true); + _i2c->read(MAGNETO_ADDRESS, buffer, 6); + + for(int i = 0; i < 6; i += 2){ + int16_t value = buffer[i]; + value = (value << 8) | buffer[i+1]; + raw[i >> 1] = value; + } +} + +int16_t Magneto::GetHeadingXY(){ + int16_t data[3] = {0}; + + ReadXZY(data); + + int16_t x = data[0]; + int16_t y = data[2]; + + _UpdateCalibration(x, y); + + if (scaleX == 0 || scaleY == 0){ + return HEADING_ERROR; + } + + float scaledX = (float)(x - offsetX) / (float) scaleX; // Scaled value between -1 and 1 + float scaledY = (float)(y - offsetY) / (float) scaleY; // Scaled value between -1 and 1 + + int16_t heading = atan2(scaledY, scaledX) * 180.0f / PI; + + if (heading < 0) { + heading += 360; + } else if (heading > 360) { + heading -= 360; + } + + return heading; +} + + +void Magneto::ResetDevice(){ + minX = OR_MAX_VALUE; + maxX = OR_MIN_VALUE; + minY = OR_MAX_VALUE; + maxY = OR_MIN_VALUE; + + offsetX = 0; + offsetY = 0; + + scaleX = 0; + scaleY = 0; +}