sensortoy/app/js/device/CC2650/cc2650_accelerometer.js
2016-06-24 16:27:42 +01:00

572 lines
15 KiB
JavaScript

/**
*
* User: Martin Donnelly
* Date: 2016-05-20
* Time: 10:13
*
*/
/* global CAPABILITY, inheritsFrom, capabilityManager */
/* global ble */
/* jshint browser: true , devel: true*/
var CC2650_ACCEL;
CC2650_ACCEL = function(p) {
'use strict';
this.name = 'Accelerometer';
this.deviceID = p.deviceID || null;
this.target = p.target || null;
this.capabilityID = 'F000AA80-0451-4000-B000-000000000000';
this.serviceDef = {
service: 'F000AA80-0451-4000-B000-000000000000',
data: 'F000AA81-0451-4000-B000-000000000000', // Read/notify 3 bytes X : Y : Z
notification: 'F0002902-0451-4000-B000-000000000000',
configuration: 'F000AA82-0451-4000-B000-000000000000', // Read/write 1 byte
period: 'F000AA83-0451-4000-B000-000000000000' // Read/write 1 byte Period = [Input*10]ms
};
this.frames = {};
this.$id = {};
this.$result = {};
this.data = {
gyro: {x: [], y: [], z: []},
accel: {x: [], y: [], z: []},
mag: {x: [], y: [], z: []}
};
this.setFrame();
this.sensorMpu9250GyroConvert = function(data) {
return (data * 1.0) / (65536 / 500);
};
this.sensorMpu9250AccConvert = function(data) {
// Change /2 to match accel range...i.e. 16 g would be /16
return (data * 1.0) / (32768 / 2);
};
this.processData = function(data) {
var a = new Int16Array(data);
var calcData = {
gyro: {
x: this.sensorMpu9250GyroConvert(a[0]),
y: this.sensorMpu9250GyroConvert(a[1]),
z: this.sensorMpu9250GyroConvert(a[2])
}, accel: {
x: this.sensorMpu9250AccConvert(a[3]),
y: this.sensorMpu9250AccConvert(a[4]),
z: this.sensorMpu9250AccConvert(a[5])
}, mag: {
x: a[6], y: a[7], z: a[8]
}
};
return calcData;
};
this.onAccelerometerData = function(data) {
// Console.log(data);
var message;
var calcData;
function gString(v) {
return [v.toFixed(3),'G'].join('');
}
function aString(v) {
return [v.toFixed(3),'\'/s'].join('');
}
function mString(v) {
return [v.toFixed(3),'mT'].join('');
}
calcData = this.processData(data);
message = 'Gyro <br/>' + 'X: ' + calcData.gyro.x + '<br/>' + 'Y: ' + calcData.gyro.y + '<br/>' + 'Z: ' + calcData.gyro.z + '<br/>' + 'Accel <br/>' + 'X: ' + calcData.accel.x + '<br/>' + 'Y: ' + calcData.accel.y + '<br/>' + 'Z: ' + calcData.accel.z + '<br/>' + 'Mag <br/>' + 'X: ' + calcData.mag.x + '<br/>' + 'Y: ' + calcData.mag.y + '<br/>' + 'Z: ' + calcData.mag.z + '<br/>';
this.state = message;
this.$result[this.frames.gyroID + '-x'].text(gString(calcData.gyro.x));
this.$result[this.frames.gyroID + '-y'].text(gString(calcData.gyro.y));
this.$result[this.frames.gyroID + '-z'].text(gString(calcData.gyro.z));
this.$result[this.frames.accelID + '-x'].text(aString(calcData.accel.x));
this.$result[this.frames.accelID + '-y'].text(aString(calcData.accel.y));
this.$result[this.frames.accelID + '-z'].text(aString(calcData.accel.z));
this.$result[this.frames.magID + '-x'].text(mString(calcData.mag.x));
this.$result[this.frames.magID + '-y'].text(mString(calcData.mag.y));
this.$result[this.frames.magID + '-z'].text(mString(calcData.mag.z));
this.data.gyro.x = this.storeData(calcData.gyro.x, this.data.gyro.x);
this.data.gyro.y = this.storeData(calcData.gyro.y, this.data.gyro.y);
this.data.gyro.z = this.storeData(calcData.gyro.z, this.data.gyro.z);
this.data.accel.x = this.storeData(calcData.accel.x, this.data.accel.x);
this.data.accel.y = this.storeData(calcData.accel.y, this.data.accel.y);
this.data.accel.z = this.storeData(calcData.accel.z, this.data.accel.z);
this.data.mag.x = this.storeData(calcData.mag.x, this.data.mag.x);
this.data.mag.y = this.storeData(calcData.mag.y, this.data.mag.y);
this.data.mag.z = this.storeData(calcData.mag.z, this.data.mag.z);
// Console.log(JSON.stringify(this.data));
// Console.log(this.state);
};
this.startService = function() {
this.maxLength = 500;
if (this.deviceID !== null) {
console.log('Starting CC2650 Accelerometer Service on ', this.deviceID);
console.log(this.serviceDef);
this.setInternalID();
this.insertFrame('gyro');
this.insertFrame('accel');
this.insertFrame('mag');
ble.startNotification(this.deviceID,
this.serviceDef.service,
this.serviceDef.data,
this.onAccelerometerData.bind(this),
this.onError);
// Turn accelerometer on
var configData = new Uint16Array(1);
// Turn on gyro, accel, and mag, 2G range, Disable wake on motion
configData[0] = 0x007F;
ble.write(this.deviceID,
this.serviceDef.service,
this.serviceDef.configuration,
configData.buffer,
function() { console.log('Started accelerometer.'); },
this.onError);
var periodData = new Uint8Array(1);
periodData[0] = 0x0A;
ble.write(this.deviceID,
this.serviceDef.service,
this.serviceDef.period,
periodData.buffer,
function() { console.log('Configured accelerometer period.'); },
this.onError);
}
};
this.advancedGraphFFT = function(mode, data, subID) {
var xstep;
var scalePos;
var lm;
var ceiling;
var elm;
var text2ID;
var ceilingLimit;
var calcArray;
var floor;
var _subID;
var _data;
var text1ID;
var lineID;
var max;
var yscale = 125;
var height = 125;
var yOffset = 71;
var reducer = function(p, v) {
return (Math.abs(p) > Math.abs(v) ? Math.abs(p) : Math.abs(v));
};
var parts = ['x', 'y', 'z'];
var _newData = {x: [],y: [],z: []};
if (subID === 'gyro') {
height = 300;
yscale = 300;
}
_data = data || this.data;
_subID = subID || '';
// LineID = [this.frameID , _subID , '-line'].join('');
text1ID = [this.frameID, _subID, '-txt1'].join('');
text2ID = [this.frameID, _subID, '-txt2'].join('');
ceiling = 0;
if (_data.x.length > 0) {
max = 2;
for (var lineMode = 0; lineMode < parts.length; lineMode++) {
lm = parts[lineMode];
var data = new complex_array.ComplexArray(_data[lm]);
data.FFT();
data.forEach(function(c_value, i) {
ceiling = reducer(c_value.real ,ceiling);
_newData[lm].push(c_value.real);
});
//Ceiling = _data[lm].reduce(reducer);
console.log('ceiling:', ceiling);
}
if (ceiling > 500) {
max = (ceiling > max) ? (Math.ceil((Math.round(ceiling) + 1) / 50) * 50) : max;
} else {
max = (ceiling > max) ? (Math.ceil((Math.round(ceiling) + 1) / 10) * 10) : max;
}
ceiling = max;
floor = ceiling * -1;
ceilingLimit = ceiling;
console.log('ceiling:',ceiling);
scalePos = (yscale / 2) / ceiling;
xstep = (680 - 46) / this.maxLength;
yOffset = ((height - (14 + 12)) / 2) + 12;
//Var xstep = 2.34;
for (lineMode = 0; lineMode < parts.length; lineMode++) {
lm = parts[lineMode];
var startX = 46 + (this.maxLength - _newData[lm].length) * xstep;
calcArray = [];
lineID = this.frameID + _subID + '-' + lm + '-line';
for (var x = 0; x < _newData[lm].length; x++) {
calcArray.push((startX + (x * xstep)).toFixed(2) + ',' + (yOffset - ((_newData[lm][x]) * scalePos)).toFixed(
2));
}
elm = document.getElementById(lineID);
elm.setAttribute('points', calcArray.join(' '));
}
elm = document.getElementById(text1ID);
elm.textContent = ceilingLimit;
elm = document.getElementById(text2ID);
elm.textContent = floor;
}
this.previousCeil = ceiling;
};
this.advancedGraph = function(mode, data, subID) {
var xstep;
var scalePos;
var lm;
var ceiling;
var elm;
var text2ID;
var ceilingLimit;
var calcArray;
var floor;
var _subID;
var _data;
var text1ID;
var lineID;
var max;
var yscale = 125;
var height = 125;
var yOffset = 71;
var reducer = function(p, v) {
return (Math.abs(p) > Math.abs(v) ? Math.abs(p) : Math.abs(v));
};
var parts = ['x', 'y', 'z'];
_data = data || this.data;
_subID = subID || '';
// LineID = [this.frameID , _subID , '-line'].join('');
text1ID = [this.frameID, _subID, '-txt1'].join('');
text2ID = [this.frameID, _subID, '-txt2'].join('');
if (mode === 'gyro') {
height = 300;
yscale = 300;
}
if (_data.x.length > 0) {
max = 2;
for (var lineMode = 0; lineMode < parts.length; lineMode++) {
lm = parts[lineMode];
/*Ceiling = _data[lm].reduce(function(p, v) {
return (Math.abs(p) > Math.abs(v) ? Math.abs(p) : Math.abs(v));
});*/
ceiling = _data[lm].reduce(reducer);
if (ceiling > 500) {
max = (ceiling > max) ? (Math.ceil((Math.round(ceiling) + 1) / 50) * 50) : max;
} else {
max = (ceiling > max) ? (Math.ceil((Math.round(ceiling) + 1) / 10) * 10) : max;
}
}
ceiling = max;
floor = ceiling * -1;
ceilingLimit = ceiling;
scalePos = (yscale / 2) / ceiling;
xstep = (680 - 46) / this.maxLength;
yOffset = ((height - (14 + 12)) / 2) + 12;
//Var xstep = 2.34;
for (lineMode = 0; lineMode < parts.length; lineMode++) {
lm = parts[lineMode];
var startX = 46 + (this.maxLength - _data[lm].length) * xstep;
calcArray = [];
lineID = this.frameID + _subID + '-' + lm + '-line';
for (var x = 0; x < _data[lm].length; x++) {
calcArray.push((startX + (x * xstep)).toFixed(2) + ',' + (71 - ((_data[lm][x]) * scalePos)).toFixed(
2));
}
elm = document.getElementById(lineID);
elm.setAttribute('points', calcArray.join(' '));
}
elm = document.getElementById(text1ID);
elm.textContent = ceilingLimit;
elm = document.getElementById(text2ID);
elm.textContent = floor;
}
this.previousCeil = ceiling;
};
this.animateGraph = function() {
// Nothing to animate yet
// return -1;
this.advancedGraphFFT(0, this.data.gyro, 'gyro');
this.advancedGraph(0, this.data.accel, 'accel');
this.advancedGraph(0, this.data.mag, 'mag');
// This.simpleGraph(this.data.temp, 'temp');
// this.simpleGraph(this.data.pressure, 'pressure');
};
this.generateBlankGraphBase = function(subID, settings) {
var _subID = subID || '';
var xmlns = 'http://www.w3.org/2000/svg';
var svgID = this.frameID + _subID + '-svg';
var text1ID = this.frameID + _subID + '-txt1';
var text2ID = this.frameID + _subID + '-txt2';
var _width = settings.width || 300;
var _height = settings.height || 150;
var _fill = settings.fill || 'blue';
var viewbox = [0,0,_width, _height].join(' ');
var svg = document.createElementNS(xmlns, 'svg');
svg.setAttribute('id', svgID);
// Svg.setAttribute(xmlns, 'version', '1.1');
svg.setAttribute('width', _width.toString());
svg.setAttribute('height', _height.toString());
svg.setAttribute('fill', _fill);
svg.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', 'http://www.w3.org/1999/xlink');
svg.setAttributeNS(xmlns, 'viewBox', viewbox);
// Svg.setAttributeNS(xmlns, 'style', 'width:700px;height:150px;');
svg = this.graphAddXAxis(svg, {y: 12, x2: 680, colour: '#004c6d', id: text1ID});
svg = this.graphAddXAxis(svg, {y: _height - 14, x2: 680, colour: '#004c6d', id: text2ID});
svg = this.graphAddXAxis(svg, {y: ((_height - (14 + 12)) / 2) + 12, x2: 680, colour: '#004c6d', text: '0'});
return svg;
};
this.generateBlankGraph = function(subID, height) {
var _height = height || 150;
var _subID = subID || '';
var xlineID = this.frameID + _subID + '-x-line';
var ylineID = this.frameID + _subID + '-y-line';
var zlineID = this.frameID + _subID + '-z-line';
var svg = this.generateBlankGraphBase(_subID,{width: '700',height: height});
svg = this.graphAddLine(svg, xlineID, 'rgba(255,0,99,1)');
svg = this.graphAddLine(svg, ylineID, 'rgba(46,255,0,1)');
svg = this.graphAddLine(svg, zlineID, 'rgba(0,191,255,1)');
return svg;
};
this.startCalibrate = function() {
console.log('Start calibrate');
alert('Mag Calibration: Wave device in a figure eight until done!');
};
this.insertFrame = function(mode) {
var _graph;
var row;
var button;
var elm;
var frame;
var title;
var modeID = mode + 'ID';
var height = 150;
this.frames[modeID] = this.frameID + '-' + mode;
var titles = {
gyro: 'Gyroscope', accel: 'Accelerometer', mag: 'Magnetometer'
};
console.log('FrameID: ', this.frames[modeID]);
title = [titles[mode], ' - ', this.deviceID].join(' ');
frame = $('<div />', {
class: 'mui-panel', id: this.frames[modeID]
});
if (mode === 'gyro') {
height = 300;
}
if (mode === 'mag') {
elm = $('<div />', {class: 'mui-row'});
button = $('<button />', {
class: 'mui-btn mui-btn--raised',
id: modeID + '-cal',
text: 'Calibrate',
click: this.startCalibrate.bind(this)
});
elm.append($('<div />', { class: 'mui-col-xs-8 mui--text-title mui-ellipsis-2', text: title}));
// Elm.append($('<div />', {class: 'mui-col-xs-4 mui--text-right'}).append(button));
frame.append(elm);
} else {
$('<div />', {class: 'mui-row'}).append($('<div />', {
class: 'mui-col-xs-12 mui--text-title mui-ellipsis-2', text: title
})).appendTo(frame);
}
this.$frame.append(frame);
this.$id[modeID] = $('#' + this.frames[modeID]);
// Call the parent displayForm first...
row = $('<div />', {class: 'mui-row'});
$('<div />', {
class: 'mui-col-xs-4 mui--text-accent mui--text-center', text: 'X'
}).appendTo(row);
$('<div />', {
class: 'mui-col-xs-4 mui--text-accent mui--text-center', text: 'Y'
}).appendTo(row);
$('<div />', {
class: 'mui-col-xs-4 mui--text-accent mui--text-center', text: 'Z'
}).appendTo(row);
this.$id[modeID].append(row);
row = $('<div />', {class: 'mui-row'});
$('<div />', {
class: 'mui-col-xs-4 mui--text-light mui--text-center',
text: '--',
id: this.frames[modeID] + '-x'
}).appendTo(row);
$('<div />', {
class: 'mui-col-xs-4 mui--text-light mui--text-center',
text: '--',
id: this.frames[modeID] + '-y'
}).appendTo(row);
$('<div />', {
class: 'mui-col-xs-4 mui--text-light mui--text-center',
text: '--',
id: this.frames[modeID] + '-z'
}).appendTo(row);
this.$id[modeID].append(row);
this.$result[this.frames[modeID] + '-x'] = $('#' + this.frames[modeID] + '-x');
this.$result[this.frames[modeID] + '-y'] = $('#' + this.frames[modeID] + '-y');
this.$result[this.frames[modeID] + '-z'] = $('#' + this.frames[modeID] + '-z');
row = $('<div />', {class: 'mui-row'});
_graph = this.generateBlankGraph(mode, height);
row.append($('<div>', {class: 'mui-col-sm-12'}).append(_graph));
this.$id[modeID].append(row);
};
};
inheritsFrom(CC2650_ACCEL, CAPABILITY);
capabilityManager.register({id: 'F000AA80-0451-4000-B000-000000000000', module: CC2650_ACCEL});