Difference between revisions of "SparkFun: ITG-3200,Triple-Axis Gyro Display"

From eLinux.org
Jump to: navigation, search
(Sample C Code)
(Node.js Code)
 
(20 intermediate revisions by the same user not shown)
Line 7: Line 7:
 
== Overview ==
 
== Overview ==
  
The ITG-3200 is a three-axis gyro that can be purchased from [https://www.sparkfun.com/products/9801 SparkFun]. The [http://www.sparkfun.com/datasheets/Sensors/Gyro/PS-ITG-3200-00-01.4.pdf datasheet] describes it:
+
This project show how the ITG-3200, a three-axis gyro sensor, can read and displayed using the beagle bone, a web browser and node.js. This project expands upon what was documented in [[SparkFun:_ITG-3200,Triple-Axis_Gyro]].
 +
 
  
''The ITG-3200 is the world’s first single-chip, digital-output, 3-axis MEMS gyro IC optimized for gaming, 3D mice,
 
and 3D remote control applications.  The part features enhanced bias and sensitivity temperature stability, reducing the
 
need for user calibration.  Low frequency noise is lower than previous generation devices, simplifying  application
 
development and making for more-responsive remote controls.''
 
  
 
[[File:ITG3200Bone2.jpg|thumb|ITG-3200 breakout board pin-out]]
 
[[File:ITG3200Bone2.jpg|thumb|ITG-3200 breakout board pin-out]]
  
=== Inputs and Outputs ===
+
[[File:BoneGyroDemo1.png|thumb|Here's the first display screen you will see after entering the bones web address, go ahead and click on the Button Dox Demo link]]
  
The ITG-3200 takes a supply voltage (Vs) of 1.8-3.6 V. The analog outputs are scaled proportionally to the supply voltage; at Vs = 3.6 V, the output will change by 2x for the same acceleration as compared to Vs = 1.8 V. Although the output sensitivity is scaled proportionally to the input voltage, noise is not, so higher supply voltages are advisable to reduce the impact of noise.
+
[[File:BoneGyroDemo2.png|thumb|left|Once the script is up and running you will begin to see the sensor data rendered across the time axis plots with regards to each rotational direction of the gyroscope as well as its internal temperature]]
  
At all supply voltages, 0 g acceleration corresponds to an output voltage of Vs/2. At Vs = 3.6 V, the datasheet specs the typical sensitivity at 360 mV / g, with g as standard gravitational acceleration.
+
== Introduction ==
 +
The goal here is to add a web-based graphical display to the gyroscopic sensor. Using examples of node.js servers that display realtime data from the beagle, I have altered the example code to display specifically the three axes of rotation for the gyroscope as well as in addition the internal temperature of the sensor itself.
  
 +
; buttonBox.js, buttonBox.html
 +
: This is a bone-based example that reads a gpio port, analog in and an i2c device and displays the output in a web browser.These will be there two main files that will contain many of my alterations.
  
[[File:BoneGPIO.png|thumb|This setup is accurate for the Sample Code up to the point about the brackeout board pinout. Just adjust the pin to the ITG-3200 accordingly to by description below. See [[EBC Exercise 12 I2C]] for more detail]]
+
== Running the code ==
 +
First off, you'll need to download the code through the get hub repository onto a local directory within your Beagle bone. You will then need to navigate to:
 +
beagle$ '''cd ~/MiniProject04/node.js/realtime'''
 +
beagle$ '''opkg update'''
 +
beagle$ '''opkg install nodejs'''  (Don't install '''node''', it's not what you think.)
  
===Connecting to the Bone===
+
On the Bone:
 +
beagle$ '''node buttonBox.js'''
  
The Beagle Bone can be connected to the gyro via the I2C bus. Ground and Vcc on the breakout board should be connected to pins 1 and 2 respectively on the bone's P9 header, and the SCL and SDA pins should be connected to one of the I2C pairs on the bone. VIO should also be simply tied to Vcc, as this will be the same voltage the bone will use when acting as the master in the I2C buss. CLK should also be tied to ground unless you plan to use your own clock, grounding CLK will simply allow the device to use its own internal oscillator. Two 4.7kΩ resistors should used be connected between SCL and then Vcc and between SDA and Vcc. There are available resistor pads on the breakout board I you prefer to have surface mounts on the board instead of bread boarding them. I used I2C3 (P9, pins 19 and 20).
+
Simply press ‘CTRL’ + ‘C’ to quit the program.
The address of the magnetometer can be found by using the i2cdetect command from the shell. I get:
 
  
beagle$ '''i2cdetect -y -r 3'''
+
===Connecting to the Bone===
      0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
 
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
 
10: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- --
 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
 
50: -- -- -- -- UU UU UU UU -- -- -- -- -- -- -- --
 
60: -- -- -- -- -- -- -- -- -- 69 -- -- -- -- -- --
 
70: -- -- -- -- -- -- -- --
 
  
The address should be 0x69 (or 105 in decimal). This address can be changed by soldering an arrangement of resistors on the reserved pads on the breakout board.
+
Then point a browser to '''beaglebone.local:8081'''.  The default port is 8081. You can change it if you like.
  
== Code ==
+
== How it works ==
  
=== Node.js Code ===
+
The prior examples included the script within the HTML file that polled the server continuously for data updates. However I have altered the code within the HTML file as well as the .js file to allow the server to be so fully responsible for pushing the data to the client.
  
The code shown below is sample code to demonstrate reading the registers via I2C and using the library.Specifically the code sets up some peripherals like buttons and interrupts and the I2C buss. The code will also zero out the gyro to account for the internal bias the gyro might have just being stationary and level. Then with by pressing the button the code will toggle through and repetitively read different poll the gyro and print and display the results to the terminal. Simply press ‘CTRL’ + ‘C’ to quit the program.
+
Another alteration I have made is to alter the I2C function that is called to acquisition the sensor data. Using the source code within mini project two, I have made a stripped-down version that simply returns all the relevant registers within the sensor. This is interpreted as a string within the server's .js file and is streamed to the client browser where the script parses the relevant information to each specific axis and temperature variable. This is then plotted on the grass and rendered on-screen over time.
  
<pre>
+
[[File:BoneGPIO.png|thumb|This setup is accurate for the Sample Code up to the point about the brackeout board pinout. Just adjust the pin to the ITG-3200 accordingly to by description below. See [[EBC Exercise 12 I2C]] for more detail]]
/*
 
* MiniProject02.c
 
*
 
*  Created on: Sep 20, 2012
 
*      Author: Ruffin White
 
*/
 
  
#include "Header.h"
+
== Code ==
#include <stdio.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#include <unistd.h>
 
#include <fcntl.h>
 
#include <poll.h>
 
#include <signal.h>
 
#include "ITG-3200.h"
 
  
int loop=1;
+
=== Node.js Code ===
  
 +
The code shown below is part sample code to demonstrate reading the registers via I2C and displaying the data with node.js. The alteration that has been made is to specify a timeout period for the server, as well as an additional function that will execute the terminal commands required to poll the gyroscopic sensor in return its register values. The code will also zero out the gyro to account for the internal bias the gyro might have just being stationary and level.
  
void signal_handler(int sig)
+
One alteration you'll need to make is to change the path the exec function with in the pushMessage function calls the custom c program to read the I2C buss. Just change the path to point to the excusable you compile with gcc using available MiniProject02.c file within the same directory as the HTML and node.js files, all the necessary header files are included as well.
{
 
printf( "Ctrl-C pressed, cleaning up and exiting..\n" );
 
loop = 0;
 
}
 
  
int main(int argc, char** argv){
+
<pre>
 +
// From Getting Started With node.js and socket.io
 +
// http://codehenge.net/blog/2011/12/getting-started-with-node-js-and-socket-io-v0-7-part-2/
 +
"use strict";
  
//variable declarations
+
var http = require('http'),
struct pollfd fdset[1];
+
    url = require('url'),
int nfds = 1;
+
    fs = require('fs'),
int timeout = 100;
+
    exec = require('child_process').exec,
int rc;
+
    server,
char* buf[MAX_BUF];
+
    connectCount = 0; // Number of connections to server
int gpio1, gpio2;
 
int gpio1_fd, gpio2_fd;
 
int gpio2_value = 0;
 
int pattern =0;
 
int value =0;
 
  
int freq = 10;
+
server = http.createServer(function (req, res) {
int duty = 25;
+
// server code
 +
    var path = url.parse(req.url).pathname;
 +
    console.log("path: " + path);
 +
    switch (path) {
 +
    case '/':
 +
        res.writeHead(200, {'Content-Type': 'text/html'});
 +
        res.write('<h1>Hello!</h1>Try<ul><li><a href="/buttonBox.html">Button Box Demo</a></li></ul>');
  
short int gyroID, gyroTemp, gyroX, gyroY, gyroZ;
+
        res.end();
 +
        break;
  
// I2C Variables
+
    default: // This is so all the files will be sent.
char *end;
+
        fs.readFile(__dirname + path, function (err, data) {
int res, i2cbus, address, size, file;
+
            if (err) {return send404(res); }
int daddress;
+
//            console.log("path2: " + path);
 +
            res.write(data, 'utf8');
 +
            res.end();
 +
        });
 +
        break;
  
//check that at least two arguments are passed in
+
    }
if(argc < 4){
+
});
printf("Usage: %s <input-gpio> <output-gpio> <i2c-bus>\n", argv[0]);
 
printf("polls input-gpio, and writes value to output-gpio\n");
 
fflush(stdout);
 
return 1;
 
}
 
  
 +
var send404 = function (res) {
 +
    res.writeHead(404);
 +
    res.write('404');
 +
    res.end();
 +
};
  
//set signal handler for Ctrl + C
+
server.listen(8081);
if (signal(SIGINT, signal_handler) == SIG_ERR)
 
printf("\ncan't catch SIGINT\n");
 
  
//assign gpio values
+
// socket.io, I choose you
gpio1 = atoi(argv[1]);
+
var io = require('socket.io').listen(server);
gpio2 = atoi(argv[2]);
+
io.set('log level', 2);
  
 +
// on a 'connection' event
 +
io.sockets.on('connection', function (socket) {
 +
    var frameCount = 0; // Counts the frames from arecord
 +
    var lastFrame = 0; // Last frame sent to browser
 +
    console.log("Connection " + socket.id + " accepted.");
 +
//    console.log("socket: " + socket);
  
//assign I2C values
+
    // now that we have our connected 'socket' object, we can
i2cbus  = atoi(argv[3]);
+
    // define its event handlers
address  = ITG3200_I2C_ADDRESS;
 
file = initialize(i2cbus, address);
 
zeroGyro(file);
 
  
 +
    // Make sure some needed files are there
 +
    // The path to the analog devices changed from A5 to A6.  Check both.
 +
    var ainPath = "/sys/devices/platform/omap/tsc/";
 +
//    if(!fs.existsSync(ainPath)) {
 +
//        ainPath = "/sys/devices/platform/tsc/";
 +
//        if(!fs.existsSync(ainPath)) {
 +
//            throw "Can't find " + ainPath;
 +
//        }
 +
//    }
 +
    // Make sure gpio 7 is available.
 +
    exec("echo 7 > /sys/class/gpio/export");
 +
   
  
//argument 1 will be input
+
    // Send value every time a 'message' is received.
export_gpio(gpio1);
+
    socket.on('ain', function (ainNum) {
set_gpio_direction(gpio1, "in");
+
//        var ainPath = "/sys/devices/platform/omap/tsc/ain" + ainNum;
set_gpio_edge(gpio1, "falling");
+
        fs.readFile(ainPath + "ain" + ainNum, 'base64', function(err, data) {
gpio1_fd = gpio_fd_open(gpio1);
+
            if(err) throw err;
 +
            socket.emit('ain', data);
 +
//            console.log('emitted ain: ' + data);
 +
        });
 +
    });
  
//argument 2 will be output
+
    socket.on('gpio', function (gpioNum) {
export_gpio(gpio2);
+
        var gpioPath = "/sys/class/gpio/gpio" + gpioNum + "/value";
set_gpio_direction(gpio2, "out");
+
        fs.readFile(gpioPath, 'base64', function(err, data) {
set_gpio_value(gpio2, gpio2_value);
+
            if (err) throw err;
gpio2_fd = gpio_fd_open(gpio2);
+
            socket.emit('gpio', data);
 +
//            console.log('emitted gpio: ' + data);
 +
        });
 +
    });
  
set_mux_value("gpmc_a2",6);
+
    socket.on('i2c', function (i2cNum) {
 +
//        console.log('Got i2c request:' + i2cNum);
 +
        exec('i2cget -y 3 ' + i2cNum + ' 0 w',
 +
            function (error, stdout, stderr) {
 +
// The TMP102 returns a 12 bit value with the digits swapped
 +
                stdout = '0x' + stdout.substring(4,6) + stdout.substring(2,4);
 +
//                console.log('i2cget: "' + stdout + '"');
 +
                if(error) { console.log('error: ' + error); }
 +
                if(stderr) {console.log('stderr: ' + stderr); }
 +
                socket.emit('i2c', stdout);
 +
            });
 +
    });
  
 +
    socket.on('led', function (ledNum) {
 +
        var ledPath = "/sys/class/leds/beaglebone::usr" + ledNum + "/brightness";
 +
//        console.log('LED: ' + ledPath);
 +
        fs.readFile(ledPath, 'utf8', function (err, data) {
 +
            if(err) throw err;
 +
            data = data.substring(0,1) === "1" ? "0" : "1";
 +
//            console.log("LED%d: %s", ledNum, data);
 +
            fs.writeFile(ledPath, data);
 +
        });
 +
    });
  
while(loop){
+
  var updateInterval = 100;
memset((void*)fdset, 0, sizeof(fdset));
+
  function pushMessage() {
 +
//        console.log('Got i2c request:' + 6);
 +
        exec('/home/root/ECE497/MiniProject04/node.js/realtime/./a.out 0 0 ' + 3,
 +
            function (error, stdout, stderr) {
 +
console.log('stdout:' + stdout);
 +
//console.log('stdout:' + parseFloat(stdout.substring(51,58))/100.0);
 +
                if(error) { console.log('error: ' + error); }
 +
                if(stderr) {console.log('stderr: ' + stderr); }
 +
                socket.emit('i2c', stdout);
 +
            });
 +
        setTimeout(pushMessage, updateInterval);
 +
    }
 +
    pushMessage();
  
fdset[0].fd = gpio1_fd;
 
fdset[0].events = POLLPRI;
 
  
rc = poll(fdset, nfds, timeout);
+
    socket.on('disconnect', function () {
 +
        console.log("Connection " + socket.id + " terminated.");
 +
        connectCount--;
 +
        if(connectCount === 0) {
 +
        }
 +
        console.log("connectCount = " + connectCount);
 +
    });
  
if (rc < 0){
+
    connectCount++;
printf("\npoll() failed!\n");
+
    console.log("connectCount = " + connectCount);
}
+
});
  
if (rc == 0){
 
printf(".");
 
}
 
 
if((fdset[0].revents & POLLPRI) == POLLPRI) {
 
read(fdset[0].fd, buf, MAX_BUF);
 
printf("interrupt value=%c\n", buf[0]);
 
pattern++;
 
if(pattern == 4){
 
pattern = 0;
 
}
 
}
 
 
switch(pattern){
 
 
// blink led
 
case 0:
 
printf("Case 0\n");
 
value = read_ain("ain6");
 
printf("Voltage: %d\n",value);
 
set_pwm("ehrpwm.1:0",10,25);
 
if(gpio2_value){
 
gpio2_value = 0;
 
}
 
else{
 
gpio2_value = 1;
 
}
 
set_gpio_value(gpio2, gpio2_value);
 
break;
 
 
//PWM output
 
case 1:
 
printf("Case 1\n");
 
 
gyroID = readWhoAmI(file);
 
 
printf("gyroID: %6d\n", gyroID);
 
break;
 
 
//Read Gyro Temperature
 
case 2:
 
printf("Case 2\n");
 
 
gyroTemp = readTemp(file);
 
 
printf("gyroTemp: %6d\n", gyroTemp);
 
break;
 
 
//Read Gyro XYZ
 
case 3:
 
printf("Case 3\n");
 
 
gyroX = readX(file);
 
gyroY = readY(file);
 
gyroZ = readZ(file);
 
 
printf("gyroX: %6d\n", gyroX);
 
printf("gyroY: %6d\n", gyroY);
 
printf("gyroZ: %6d\n", gyroZ);
 
break;
 
 
default:
 
break;
 
}
 
}
 
close(file);
 
gpio_fd_close(gpio1_fd);
 
gpio_fd_close(gpio2_fd);
 
unexport_gpio(gpio1);
 
unexport_gpio(gpio2);
 
fflush(stdout);
 
return 0;
 
}
 
 
</pre>
 
</pre>
  
=== Header File ===
+
=== HTML Code ===
  
The code shown below is header file code used for using the gyro. This header file contains all the read and write functions to access all the applicable registers via I2C that exist on the Gyro. See the data sheet for more detail on what each register is for.
+
This file is altered from example code and contains all the necessary formatting for the user interface and data representation. A also contains the script necessary to parse the string containing the sensor data sent by the server.
  
 
<pre>
 
<pre>
/*
+
<!doctype html>
* ITG3200.h
+
<html>
*
+
  <head>
*  Created on: Sep 20, 2012
+
    <title>Gyro Demo</title>
*      Author: Ruffin White
 
*/
 
  
/**
+
    <script src="/json.js"></script> <!-- for ie -->
* Includes
+
    <script src="/socket.io/socket.io.js"></script>
*/
 
#include <errno.h>
 
#include "i2c-dev.h"
 
  
 +
    <link href="layout.css" rel="stylesheet" type="text/css">
 +
    <script src="jquery.js"></script>
 +
    <script src="jquery.flot.js"></script>
 +
    <script src="jquery.flot.navigate.js"></script>
 +
  </head>
 +
  <body>
 +
    <h1>Gyro Demo <a href="http://Rose-Hulman.edu" target="_blank">
 +
        <img src="RoseLogo96.png" width=200 style="float:right"></a></h1>
 +
    <button id="connect" onClick='connect()'/>Connect</button>
 +
    <button id="disconnect" onClick='disconnect()'>Disconnect</button>
 +
    <span style="position:relative; left:150px">
 +
    Analog: <input id="ainNum" type="text" value="" style="text-align: right; width:2em">
 +
    gpio: <input id="gpioNum" type="text" value="" style="text-align: right; width:2em">
 +
    i2c: <input id="i2cNum" type="text" value="" style="text-align: right; width:3em">
 +
    </span>
 +
<!--    <button id="send" onClick='send()'/>Send Message</button> -->
 +
<table>
 +
<tr>
 +
    <td><div id="plotTop" style="width:550px;height:300px;"></div>
 +
<center>samples</center></td>
 +
<td>
 +
    Update: <input id="updateTopInterval" type="text" value="" style="text-align: right; width:3em"> ms
 +
    <button id="zoomout" onClick='plotTop.zoomOut()'>Zoom Out</button>
 +
</td>
 +
</tr>
 +
<tr>
 +
    <td><div id="plotBot" style="width:550px;height:300px;"></div>
 +
<center>samples</center></td>
 +
<td>
 +
    Update: <input id="updateBotInterval" type="text" value="" style="text-align: right; width:3em"> ms
 +
    <button id="zoomout" onClick='plotBot.zoomOut()'>Zoom Out</button>
 +
</td>
 +
</tr>
 +
</table>
 +
<button id="led0" onClick='led(0)'/>LED 0</button>
 +
<button id="led1" onClick='led(1)'/>LED 1</button>
 +
<button id="led2" onClick='led(2)'/>LED 2</button>
 +
<button id="led3" onClick='led(3)'/>LED 3</button>
 +
<p>
  
/**
+
<b>Button Box demo from the <a href="http://elinux.org/index.php?title=Category:ECE497" target="_blank">32-bit Embedded Linux Class</a>.</b>
* Defines
+
In this demo, the beagle bone pushes it sensor data to the web browser. Try moving the gyro or touching it to change its temprature. Try double-clicking to zoom and click and dragging to pan.
*/
+
</p>
#define ITG3200_I2C_ADDRESS 0x69 //7-bit address that Gyro is originally configured by the break-out board
+
    <a href="http://beagleboard.org" target="_blank">
 +
        <img src="beagle-hd-logo.gif" width=200 align="right"></a>
 +
    <div><p id="status">Waiting for input</p></div>
 +
    <a href="http://www.ti.com/sitara" target="_blank">
 +
        <img src="hdr_ti_logo.gif" width=200 align="right"></a>
 +
    <div><p id="message">message</p></div>
 +
By <i>Ruffin White</i>
 +
<br/>
  
//-----------
+
     <script>
// Registers
 
//-----------
 
#define WHO_AM_I_REG    0x00
 
#define SMPLRT_DIV_REG  0x15
 
#define DLPF_FS_REG     0x16
 
#define INT_CFG_REG    0x17
 
#define INT_STATUS      0x1A
 
#define TEMP_OUT_H_REG  0x1B
 
#define TEMP_OUT_L_REG  0x1C
 
#define GYRO_XOUT_H_REG 0x1D
 
#define GYRO_XOUT_L_REG 0x1E
 
#define GYRO_YOUT_H_REG 0x1F
 
#define GYRO_YOUT_L_REG 0x20
 
#define GYRO_ZOUT_H_REG 0x21
 
#define GYRO_ZOUT_L_REG 0x22
 
#define PWR_MGM_REG    0x3E
 
  
//----------------------------
+
    var socket;
// Low Pass Filter Bandwidths
+
    var firstconnect = true,
//----------------------------
+
        fs = 8000,
#define LPFBW_256HZ 0x00
+
        Ts = 1/fs*1000,
#define LPFBW_188HZ 0x01
+
        samples = 100,
#define LPFBW_98HZ 0x02
+
        plotTop,
#define LPFBW_42HZ 0x03
+
        plotBot,
#define LPFBW_20HZ 0x04
+
        ainData = [],  iain = 0,
#define LPFBW_10HZ 0x05
+
        gpioData = [], igpio = 0,
#define LPFBW_5HZ  0x06
+
        i2cXData = [],  ii2cX = 0,
 +
        i2cYData = [],  ii2cY = 0,
 +
        i2cZData = [], ii2cZ = 0,
 +
        i2cTData = [], ii2cT = 0,
 +
        gpioNum = 7,
 +
        ainNum = 6,
 +
        i2cNum = "0x48";
 +
    ainData[samples] = 0;
 +
    gpioData[samples] = 0;
 +
    i2cXData[samples] = 0;
 +
    i2cYData[samples] = 0;
 +
    i2cZData[samples] = 0;
 +
    i2cTData[samples] = 0;
  
//-----------
+
    function connect() {
// Offsets
+
      if(firstconnect) {
//-----------
+
        socket = io.connect(null);
short int TEMP_OUT_OFFSET = 0;
 
short int GYRO_XOUT_OFFSET = 0;
 
short int GYRO_YOUT_OFFSET = 0;
 
short int GYRO_ZOUT_OFFSET = 0;
 
  
 +
        socket.on('message', function(data)
 +
            { status_update("Received: message");});
 +
        socket.on('connect', function()
 +
            { status_update("Connected to Server"); });
 +
        socket.on('disconnect', function()
 +
            { status_update("Disconnected from Server"); });
 +
        socket.on('reconnect', function()
 +
            { status_update("Reconnected to Server"); });
 +
        socket.on('reconnecting', function( nextRetry )
 +
            { status_update("Reconnecting in " + nextRetry/1000 + " s"); });
 +
        socket.on('reconnect_failed', function()
 +
            { message("Reconnect Failed"); });
  
 +
        socket.on('ain',  ain);
 +
        socket.on('gpio', gpio);
 +
        socket.on('i2c',  i2c);
  
 +
        firstconnect = false;
 +
      }
 +
      else {
 +
        socket.socket.reconnect();
 +
      }
 +
    }
  
//----------------
+
    function disconnect() {
// Read Functions
+
      socket.disconnect();
//----------------
+
    }
  
//This function is used to initialize the gyroscope. The function returns the -errno if an error accrues.
+
    function led(ledNum) {
short int initialize(int i2cbus, int address){
+
        socket.emit('led', ledNum);
 +
    }
  
char filename[20];
+
    // When new data arrived, convert it and plot it.
int file;
+
    function ain(data) {
sprintf(filename, "/dev/i2c-%d", i2cbus);
+
        data = atob(data)/4096 * 1.8;
file = open(filename, O_RDWR);
+
        data = isNaN(data) ? 0 : data;
if (file<0) {
+
//        status_update("ain: " + data);
return -errno;
+
        ainData[iain] = [iain, data];
}
+
        iain++;
 +
        if(iain >= samples) {
 +
            iain = 0;
 +
            ainData = [];
 +
        }
 +
        plotTop.setData([ ainData, gpioData ]);
 +
        plotTop.draw();
 +
    }
  
if (ioctl(file, I2C_SLAVE, address) < 0) {
+
    function gpio(data) {
return -errno;
+
        data = atob(data);
}
+
//        status_update("gpio: " + data);
return file;
+
        gpioData[igpio] = [igpio, data];
 +
        igpio++;
 +
        if(igpio >= samples) {
 +
            igpio = 0;
 +
            gpioData = [];
 +
        }
 +
        plotTop.setData([ ainData, gpioData ]);
 +
        plotTop.draw();
 +
    }
 +
//gyroX: -00026 gyroY: -00012 gyroZ: 000073 gyroTemp: 002602
  
}
+
    function i2c(data) {
 +
        Xdata = parseInt(data.substring(6,12));
 +
        Ydata = parseInt(data.substring(20,26));
 +
        Zdata = parseInt(data.substring(34,40));
 +
        Tdata = parseInt(data.substring(51,56));
 +
        i2cXData[ii2cX] = [ii2cX, Xdata];
 +
        i2cYData[ii2cY] = [ii2cY, Ydata];
 +
        i2cZData[ii2cZ] = [ii2cZ, Zdata];
 +
        i2cTData[ii2cT] = [ii2cT, Tdata];
 +
        ii2cX++;
 +
        if(ii2cX >= samples) {
 +
            ii2cX = 0;
 +
            i2cXData = [];
 +
        }
 +
        i2cXData[ii2cY] = [ii2cY, Xdata];
 +
        ii2cY++;
 +
        if(ii2cY >= samples) {
 +
            ii2cY = 0;
 +
            i2cYData = [];
 +
        }
 +
        i2cXData[ii2cZ] = [ii2cZ, Xdata];
 +
        ii2cZ++;
 +
        if(ii2cZ >= samples) {
 +
            ii2cZ = 0;
 +
            i2cZData = [];
 +
        }
 +
        i2cXData[ii2cT] = [ii2cT, Xdata];
 +
        ii2cT++;
 +
        if(ii2cT >= samples) {
 +
            ii2cT = 0;
 +
            i2cTData = [];
 +
        }
 +
        plotBot.setData([ i2cXData, i2cYData, i2cZData]);
 +
        plotBot.draw();
 +
        plotTop.setData([ i2cTData ]);
 +
        plotTop.draw();
 +
    }
  
//This function is used to initialize the gyroscope. The function returns the -errno if an error accrues.
+
    function status_update(txt){
short int zeroGyro(int file){
+
      document.getElementById('status').innerHTML = txt;
 +
    }
  
GYRO_XOUT_OFFSET = readX(file);
+
    function send(){
GYRO_YOUT_OFFSET = readY(file);
+
      socket.emit("ain", "Hello Server!");  
GYRO_ZOUT_OFFSET = readZ(file);
+
    };
  
}
+
    connect();
  
//This function is used to read the WHO_AM_I_REG of the gyroscope.
+
$(function () {
//Usage: int gyroID = readWhoAmI();
 
short int readWhoAmI(int file)
 
{
 
  short int data=0;
 
  data = i2c_smbus_read_byte_data(file, WHO_AM_I_REG);
 
  
  return data;
+
    function initPlotData() {
}
+
        // zip the generated y values with the x values
 +
        var result = [];
 +
        for (var i = 0; i <= samples; i++)
 +
            result[i] = [i, 0];
 +
        return result;
 +
    }
  
//This function is used to write the WHO_AM_I_REG of the gyroscope.
+
    // setup control widget
//Usage: data = readWhoAmI(data);
+
    $("#ainNum").val(ainNum).change(function () {
short int writeWhoAmI(int file, short int data)
+
        ainNum = $(this).val();
{
+
    });
  i2c_smbus_write_byte_data(file,WHO_AM_I_REG,data);
 
  
  return data;
+
    $("#gpioNum").val(gpioNum).change(function () {
}
+
        gpioNum = $(this).val();
 +
    });
  
 +
    $("#i2cNum").val(i2cNum).change(function () {
 +
        i2cNum = $(this).val();
 +
    });
  
//This function is used to read the SMPLRT_DIV_REG of the gyroscope.
+
    var updateTopInterval = 100;
short int readSmplrtDiv(int file)
+
    $("#updateTopInterval").val(updateTopInterval).change(function () {
{
+
        var v = $(this).val();
  short int data=0;
+
        if (v && !isNaN(+v)) {
  data = i2c_smbus_read_byte_data(file, SMPLRT_DIV_REG);
+
            updateTopInterval = +v;
 +
            if (updateTopInterval < 25)
 +
                updateTopInterval = 25;
 +
            if (updateTopInterval > 2000)
 +
                updateTopInterval = 2000;
 +
            $(this).val("" + updateTopInterval);
 +
        }
 +
    });
  
  return data;
+
    var updateBotInterval = 100;
}
+
    $("#updateBotInterval").val(updateBotInterval).change(function () {
 +
        var v = $(this).val();
 +
        if (v && !isNaN(+v)) {
 +
            updateBotInterval = +v;
 +
            if (updateBotInterval < 25)
 +
                updateBotInterval = 25;
 +
            if (updateBotInterval > 2000)
 +
                updateBotInterval = 2000;
 +
            $(this).val("" + updateBotInterval);
 +
        }
 +
    });
  
//This function is used to write the SMPLRT_DIV_REG of the gyroscope.
+
    // setup plot
short int writeSmplrtDiv(int file, short int data)
+
    var optionsTop = {
{
+
        series: {
  i2c_smbus_write_byte_data(file,SMPLRT_DIV_REG,data);
+
            shadowSize: 0, // drawing is faster without shadows
 +
            points: { show: false},
 +
            lines:  { show: true, lineWidth: 5},
 +
        },
 +
        yaxis: { min: 10, max: 35,
 +
                  zoomRange: [10, 256], panRange: [-128, 128] },
 +
        xaxis: { show: true,
 +
                  zoomRange: [10, 100], panRange: [0, 100] },
 +
        legend: { position: "sw" },
 +
        zoom: { interactive: true, amount: 1.1 },
 +
        pan: { interactive: true }
 +
    };
 +
    plotTop = $.plot($("#plotTop"),  
 +
        [
 +
          { data:  initPlotData(),
 +
            label: "GyroTemp" }
 +
        ],
 +
            optionsTop);
  
  return data;
+
    var optionsBot = {
}
+
        series: {
 +
            shadowSize: 0, // drawing is faster without shadows
 +
            points: { show: false},
 +
            lines:  { show: true, lineWidth: 5},
 +
            //color: 2
 +
        },
 +
        yaxis: { min: -100, max: 100,
 +
                  zoomRange: [10, 256], panRange: [60, 100] },
 +
        xaxis: { show: true,
 +
                  zoomRange: [10, 100], panRange: [0, 100] },
 +
        legend: { position: "sw" },
 +
        zoom: { interactive: true, amount: 1.1 },
 +
        pan: { interactive: true }
 +
    };
 +
    plotBot = $.plot($("#plotBot"),
 +
        [
 +
          { data:  initPlotData(),
 +
            label: "GyroX"},
 +
          { data:  initPlotData(),
 +
            label: "GyroY"},
 +
          { data:  initPlotData(),
 +
            label: "GyroZ"}
 +
        ],
 +
            optionsBot);
  
//This function is used to read the DLPF_FS_REG of the gyroscope.
+
    // Request data every updateInterval ms
short int readDlpfFs(int file)
+
    function updateTop() {
{
+
        socket.emit("ain",  ainNum);
  short int data=0;
+
        socket.emit("gpio", gpioNum);
  data = i2c_smbus_read_byte_data(file, DLPF_FS_REG);
+
        setTimeout(updateTop, updateTopInterval);
 +
    }
 +
    //updateTop();
  
  return data;
+
    function updateBot() {
}
+
        socket.emit("i2c",  i2cNum);
 +
        setTimeout(updateBot, updateBotInterval);
 +
    }
 +
    //updateBot();
 +
});
 +
</script>
  
//This function is used to write the DLPF_FS_REG of the gyroscope.
+
   </body>
short int writeDlpfFs(int file, short int data)
+
</html>
{
 
  i2c_smbus_write_byte_data(file,DLPF_FS_REG,data);
 
 
 
  return data;
 
}
 
 
 
//This function is used to read the INT_CFG_REG of the gyroscope.
 
short int readIntCfg(int file)
 
{
 
  short int data=0;
 
  data = i2c_smbus_read_byte_data(file, INT_CFG_REG);
 
 
 
  return data;
 
}
 
 
 
//This function is used to write the INT_CFG_REG of the gyroscope.
 
short int writeIntCfg(int file, short int data)
 
{
 
  i2c_smbus_write_byte_data(file,INT_CFG_REG,data);
 
 
 
  return data;
 
}
 
 
 
//This function is used to read the INT_STATUS of the gyroscope.
 
short int readIntStatus(int file)
 
{
 
  short int data=0;
 
  data = i2c_smbus_read_byte_data(file, INT_STATUS);
 
 
 
  return data;
 
}
 
 
 
 
 
//This function is used to read the temperature of the gyroscope.
 
//Usage: int gyroTemp = readTemp();
 
short int readTemp(int file)
 
{
 
  short int data=0;
 
  data = i2c_smbus_read_byte_data(file, TEMP_OUT_H_REG)<<8;
 
  data |= i2c_smbus_read_byte_data(file, TEMP_OUT_L_REG);
 
 
 
  return data;
 
}
 
 
 
//This function is used to read the X-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
 
//NOTE: This value is NOT in degrees per second.
 
//Usage: int xRate = readX();
 
short int readX(int file)
 
{
 
  short int data=0;
 
   data = i2c_smbus_read_byte_data(file, GYRO_XOUT_H_REG)<<8;
 
  data |= i2c_smbus_read_byte_data(file, GYRO_XOUT_L_REG);
 
 
 
  return data - GYRO_XOUT_OFFSET;
 
}
 
 
 
//This function is used to read the Y-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
 
//NOTE: This value is NOT in degrees per second.
 
//Usage: int yRate = readY();
 
short int readY(int file)
 
{
 
  short int data=0;
 
  data = i2c_smbus_read_byte_data(file, GYRO_YOUT_H_REG)<<8;
 
  data |= i2c_smbus_read_byte_data(file, GYRO_YOUT_L_REG);
 
 
 
  return data - GYRO_YOUT_OFFSET;
 
}
 
 
 
//This function is used to read the Z-Axis rate of the gyroscope. The function returns the ADC value from the Gyroscope
 
//NOTE: This value is NOT in degrees per second.
 
//Usage: int zRate = readZ();
 
short int readZ(int file)
 
{
 
  short int data=0;
 
  data = i2c_smbus_read_byte_data(file, GYRO_ZOUT_H_REG)<<8;
 
  data |= i2c_smbus_read_byte_data(file, GYRO_ZOUT_L_REG);
 
 
 
  return data - GYRO_ZOUT_OFFSET;
 
}
 
 
 
//This function is used to read the PWR_MGM_REG of the gyroscope.
 
short int readPwrMgm(int file)
 
{
 
  short int data=0;
 
  data = i2c_smbus_read_byte_data(file, PWR_MGM_REG);
 
 
 
  return data;
 
}
 
 
 
//This function is used to write the PWR_MGM_REG of the gyroscope.
 
short int writePwrMgm(int file, short int data)
 
{
 
  i2c_smbus_write_byte_data(file,PWR_MGM_REG,data);
 
 
 
  return data;
 
}
 
 
</pre>
 
</pre>
  
== Features ==
+
== Documents ==
 
 
Digital-output X-, Y-, and Z-Axis angular rate sensors (gyros) on one integrated circuit
 
Digitally-programmable low-pass filter
 
Low 6.5mA operating current consumption for long battery life
 
Wide VDD supply voltage range of 2.1V to 3.6V
 
Standby current: 5μA
 
Digital-output temperature sensor
 
Fast Mode I2C (400kHz) serial interface
 
Optional external clock inputs of 32.768kHz or 19.2MHz to synchronize with system clock
 
Pins broken out to a breadboard friendly 7-pin 0.1" pitch header
 
 
 
== Dimensions ==
 
  
0.70 x 0.55" (17.78 x 13.97mm)
+
[[SparkFun:_ITG-3200,Triple-Axis_Gyro]]
 
 
== Documents ==
 
  
 
[http://www.sparkfun.com/datasheets/Sensors/Gyro/ITG-3200-v10.pdf Schematic]
 
[http://www.sparkfun.com/datasheets/Sensors/Gyro/ITG-3200-v10.pdf Schematic]

Latest revision as of 09:27, 24 October 2012

thumb‎ Embedded Linux Class Ruffin White RHIT


Breakout board for InvenSense's ITG-3200

Overview

This project show how the ITG-3200, a three-axis gyro sensor, can read and displayed using the beagle bone, a web browser and node.js. This project expands upon what was documented in SparkFun:_ITG-3200,Triple-Axis_Gyro.


ITG-3200 breakout board pin-out
Here's the first display screen you will see after entering the bones web address, go ahead and click on the Button Dox Demo link
Once the script is up and running you will begin to see the sensor data rendered across the time axis plots with regards to each rotational direction of the gyroscope as well as its internal temperature

Introduction

The goal here is to add a web-based graphical display to the gyroscopic sensor. Using examples of node.js servers that display realtime data from the beagle, I have altered the example code to display specifically the three axes of rotation for the gyroscope as well as in addition the internal temperature of the sensor itself.

buttonBox.js, buttonBox.html
This is a bone-based example that reads a gpio port, analog in and an i2c device and displays the output in a web browser.These will be there two main files that will contain many of my alterations.

Running the code

First off, you'll need to download the code through the get hub repository onto a local directory within your Beagle bone. You will then need to navigate to:

beagle$ cd ~/MiniProject04/node.js/realtime
beagle$ opkg update
beagle$ opkg install nodejs  (Don't install node, it's not what you think.)

On the Bone:

beagle$ node buttonBox.js

Simply press ‘CTRL’ + ‘C’ to quit the program.

Connecting to the Bone

Then point a browser to beaglebone.local:8081. The default port is 8081. You can change it if you like.

How it works

The prior examples included the script within the HTML file that polled the server continuously for data updates. However I have altered the code within the HTML file as well as the .js file to allow the server to be so fully responsible for pushing the data to the client.

Another alteration I have made is to alter the I2C function that is called to acquisition the sensor data. Using the source code within mini project two, I have made a stripped-down version that simply returns all the relevant registers within the sensor. This is interpreted as a string within the server's .js file and is streamed to the client browser where the script parses the relevant information to each specific axis and temperature variable. This is then plotted on the grass and rendered on-screen over time.

This setup is accurate for the Sample Code up to the point about the brackeout board pinout. Just adjust the pin to the ITG-3200 accordingly to by description below. See EBC Exercise 12 I2C for more detail

Code

Node.js Code

The code shown below is part sample code to demonstrate reading the registers via I2C and displaying the data with node.js. The alteration that has been made is to specify a timeout period for the server, as well as an additional function that will execute the terminal commands required to poll the gyroscopic sensor in return its register values. The code will also zero out the gyro to account for the internal bias the gyro might have just being stationary and level.

One alteration you'll need to make is to change the path the exec function with in the pushMessage function calls the custom c program to read the I2C buss. Just change the path to point to the excusable you compile with gcc using available MiniProject02.c file within the same directory as the HTML and node.js files, all the necessary header files are included as well.

// From Getting Started With node.js and socket.io 
// http://codehenge.net/blog/2011/12/getting-started-with-node-js-and-socket-io-v0-7-part-2/
"use strict";

var http = require('http'),
    url = require('url'),
    fs = require('fs'),
    exec = require('child_process').exec,
    server,
    connectCount = 0;	// Number of connections to server

server = http.createServer(function (req, res) {
// server code
    var path = url.parse(req.url).pathname;
    console.log("path: " + path);
    switch (path) {
    case '/':
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.write('<h1>Hello!</h1>Try<ul><li><a href="/buttonBox.html">Button Box Demo</a></li></ul>');

        res.end();
        break;

    default:		// This is so all the files will be sent.
        fs.readFile(__dirname + path, function (err, data) {
            if (err) {return send404(res); }
//            console.log("path2: " + path);
            res.write(data, 'utf8');
            res.end();
        });
        break;

    }
});

var send404 = function (res) {
    res.writeHead(404);
    res.write('404');
    res.end();
};

server.listen(8081);

// socket.io, I choose you
var io = require('socket.io').listen(server);
io.set('log level', 2);

// on a 'connection' event
io.sockets.on('connection', function (socket) {
    var frameCount = 0;	// Counts the frames from arecord
    var lastFrame = 0;	// Last frame sent to browser
    console.log("Connection " + socket.id + " accepted.");
//    console.log("socket: " + socket);

    // now that we have our connected 'socket' object, we can 
    // define its event handlers

    // Make sure some needed files are there
    // The path to the analog devices changed from A5 to A6.  Check both.
    var ainPath = "/sys/devices/platform/omap/tsc/";
//    if(!fs.existsSync(ainPath)) {
//        ainPath = "/sys/devices/platform/tsc/";
//        if(!fs.existsSync(ainPath)) {
//            throw "Can't find " + ainPath;
//        }
//    }
    // Make sure gpio 7 is available.
    exec("echo 7 > /sys/class/gpio/export");
    

    // Send value every time a 'message' is received.
    socket.on('ain', function (ainNum) {
//        var ainPath = "/sys/devices/platform/omap/tsc/ain" + ainNum;
        fs.readFile(ainPath + "ain" + ainNum, 'base64', function(err, data) {
            if(err) throw err;
            socket.emit('ain', data);
//            console.log('emitted ain: ' + data);
        });
    });

    socket.on('gpio', function (gpioNum) {
        var gpioPath = "/sys/class/gpio/gpio" + gpioNum + "/value";
        fs.readFile(gpioPath, 'base64', function(err, data) {
            if (err) throw err;
            socket.emit('gpio', data);
//            console.log('emitted gpio: ' + data);
        });
    });

    socket.on('i2c', function (i2cNum) {
//        console.log('Got i2c request:' + i2cNum);
        exec('i2cget -y 3 ' + i2cNum + ' 0 w',
            function (error, stdout, stderr) {
//		The TMP102 returns a 12 bit value with the digits swapped
                stdout = '0x' + stdout.substring(4,6) + stdout.substring(2,4);
//                console.log('i2cget: "' + stdout + '"');
                if(error) { console.log('error: ' + error); }
                if(stderr) {console.log('stderr: ' + stderr); }
                socket.emit('i2c', stdout);
            });
    });

    socket.on('led', function (ledNum) {
        var ledPath = "/sys/class/leds/beaglebone::usr" + ledNum + "/brightness";
//        console.log('LED: ' + ledPath);
        fs.readFile(ledPath, 'utf8', function (err, data) {
            if(err) throw err;
            data = data.substring(0,1) === "1" ? "0" : "1";
//            console.log("LED%d: %s", ledNum, data);
            fs.writeFile(ledPath, data);
        });
    });

   var updateInterval = 100;
   function pushMessage() {
//        console.log('Got i2c request:' + 6);
        exec('/home/root/ECE497/MiniProject04/node.js/realtime/./a.out 0 0 ' + 3,
            function (error, stdout, stderr) {
		console.log('stdout:' + stdout);
		//console.log('stdout:' + parseFloat(stdout.substring(51,58))/100.0);
                if(error) { console.log('error: ' + error); }
                if(stderr) {console.log('stderr: ' + stderr); }
                socket.emit('i2c', stdout);
            });
        setTimeout(pushMessage, updateInterval);
    }
    pushMessage();


    socket.on('disconnect', function () {
        console.log("Connection " + socket.id + " terminated.");
        connectCount--;
        if(connectCount === 0) {
        }
        console.log("connectCount = " + connectCount);
    });

    connectCount++;
    console.log("connectCount = " + connectCount);
});

HTML Code

This file is altered from example code and contains all the necessary formatting for the user interface and data representation. A also contains the script necessary to parse the string containing the sensor data sent by the server.

<!doctype html>
<html>
  <head>
    <title>Gyro Demo</title>

    <script src="/json.js"></script> <!-- for ie -->
    <script src="/socket.io/socket.io.js"></script>

    <link href="layout.css" rel="stylesheet" type="text/css">
    <script src="jquery.js"></script>
    <script src="jquery.flot.js"></script>
    <script src="jquery.flot.navigate.js"></script>
  </head>
  <body>
    <h1>Gyro Demo <a href="http://Rose-Hulman.edu" target="_blank">
        <img src="RoseLogo96.png" width=200 style="float:right"></a></h1>
    <button id="connect" onClick='connect()'/>Connect</button>
    <button id="disconnect" onClick='disconnect()'>Disconnect</button>
    <span style="position:relative; left:150px">
    Analog: <input id="ainNum" type="text" value="" style="text-align: right; width:2em">
    gpio: <input id="gpioNum" type="text" value="" style="text-align: right; width:2em">
    i2c: <input id="i2cNum" type="text" value="" style="text-align: right; width:3em">
    </span>
<!--    <button id="send" onClick='send()'/>Send Message</button> -->
<table>
<tr>
    <td><div id="plotTop" style="width:550px;height:300px;"></div>
<center>samples</center></td>
<td>
    Update: <input id="updateTopInterval" type="text" value="" style="text-align: right; width:3em"> ms
    <button id="zoomout" onClick='plotTop.zoomOut()'>Zoom Out</button>
</td>
</tr>
<tr>
    <td><div id="plotBot" style="width:550px;height:300px;"></div>
<center>samples</center></td>
<td>
    Update: <input id="updateBotInterval" type="text" value="" style="text-align: right; width:3em"> ms
    <button id="zoomout" onClick='plotBot.zoomOut()'>Zoom Out</button>
</td>
</tr>
</table>
<button id="led0" onClick='led(0)'/>LED 0</button>
<button id="led1" onClick='led(1)'/>LED 1</button>
<button id="led2" onClick='led(2)'/>LED 2</button>
<button id="led3" onClick='led(3)'/>LED 3</button>
<p>

<b>Button Box demo from the <a href="http://elinux.org/index.php?title=Category:ECE497" target="_blank">32-bit Embedded Linux Class</a>.</b>
In this demo, the beagle bone pushes it sensor data to the web browser. Try moving the gyro or touching it to change its temprature. Try double-clicking to zoom and click and dragging to pan.
</p>
    <a href="http://beagleboard.org" target="_blank">
        <img src="beagle-hd-logo.gif" width=200 align="right"></a>
    <div><p id="status">Waiting for input</p></div>
    <a href="http://www.ti.com/sitara" target="_blank">
        <img src="hdr_ti_logo.gif" width=200 align="right"></a>
    <div><p id="message">message</p></div> 
By <i>Ruffin White</i>
<br/>

    <script>

    var socket;
    var firstconnect = true,
        fs = 8000,
        Ts = 1/fs*1000,
        samples = 100,
        plotTop,
        plotBot,
        ainData = [],  iain = 0, 
        gpioData = [], igpio = 0,
        i2cXData = [],  ii2cX = 0,
        i2cYData = [],  ii2cY = 0,
        i2cZData = [],  ii2cZ = 0,
        i2cTData = [],  ii2cT = 0,
        gpioNum = 7,
        ainNum  = 6,
        i2cNum  = "0x48";
    ainData[samples] = 0;
    gpioData[samples] = 0;
    i2cXData[samples] = 0;
    i2cYData[samples] = 0;
    i2cZData[samples] = 0;
    i2cTData[samples] = 0;

    function connect() {
      if(firstconnect) {
        socket = io.connect(null);

        socket.on('message', function(data)
            { status_update("Received: message");});
        socket.on('connect', function()
            { status_update("Connected to Server"); });
        socket.on('disconnect', function()
            { status_update("Disconnected from Server"); });
        socket.on('reconnect', function()
            { status_update("Reconnected to Server"); });
        socket.on('reconnecting', function( nextRetry )
            { status_update("Reconnecting in " + nextRetry/1000 + " s"); });
        socket.on('reconnect_failed', function()
            { message("Reconnect Failed"); });

        socket.on('ain',  ain);
        socket.on('gpio', gpio);
        socket.on('i2c',  i2c);

        firstconnect = false;
      }
      else {
        socket.socket.reconnect();
      }
    }

    function disconnect() {
      socket.disconnect();
    }

    function led(ledNum) {
        socket.emit('led', ledNum);
    }

    // When new data arrived, convert it and plot it.
    function ain(data) {
        data = atob(data)/4096 * 1.8;
        data = isNaN(data) ? 0 : data;
//        status_update("ain: " + data);
        ainData[iain] = [iain, data];
        iain++;
        if(iain >= samples) {
            iain = 0;
            ainData = [];
        }
        plotTop.setData([ ainData, gpioData ]);
        plotTop.draw();
    }

    function gpio(data) {
        data = atob(data);
//        status_update("gpio: " + data);
        gpioData[igpio] = [igpio, data];
        igpio++;
        if(igpio >= samples) {
            igpio = 0;
            gpioData = [];
        }
        plotTop.setData([ ainData, gpioData ]);
        plotTop.draw();
    }
//gyroX: -00026 gyroY: -00012 gyroZ: 000073 gyroTemp: 002602

    function i2c(data) {
        Xdata = parseInt(data.substring(6,12));
        Ydata = parseInt(data.substring(20,26));
        Zdata = parseInt(data.substring(34,40));
        Tdata = parseInt(data.substring(51,56));
        i2cXData[ii2cX] = [ii2cX, Xdata];
        i2cYData[ii2cY] = [ii2cY, Ydata];
        i2cZData[ii2cZ] = [ii2cZ, Zdata];
        i2cTData[ii2cT] = [ii2cT, Tdata];
        ii2cX++;
        if(ii2cX >= samples) {
            ii2cX = 0;
            i2cXData = [];
        }
        i2cXData[ii2cY] = [ii2cY, Xdata];
        ii2cY++;
        if(ii2cY >= samples) {
            ii2cY = 0;
            i2cYData = [];
        }
        i2cXData[ii2cZ] = [ii2cZ, Xdata];
        ii2cZ++;
        if(ii2cZ >= samples) {
            ii2cZ = 0;
            i2cZData = [];
        }
        i2cXData[ii2cT] = [ii2cT, Xdata];
        ii2cT++;
        if(ii2cT >= samples) {
            ii2cT = 0;
            i2cTData = [];
        }
        plotBot.setData([ i2cXData, i2cYData, i2cZData]);
        plotBot.draw();
        plotTop.setData([ i2cTData ]);
        plotTop.draw();
    }

    function status_update(txt){
      document.getElementById('status').innerHTML = txt;
    }

    function send(){
      socket.emit("ain", "Hello Server!");    
    };

    connect();

$(function () {

    function initPlotData() {
        // zip the generated y values with the x values
        var result = [];
        for (var i = 0; i <= samples; i++)
            result[i] = [i, 0];
        return result;
    }

    // setup control widget
    $("#ainNum").val(ainNum).change(function () {
        ainNum = $(this).val();
    });

    $("#gpioNum").val(gpioNum).change(function () {
        gpioNum = $(this).val();
    });

    $("#i2cNum").val(i2cNum).change(function () {
        i2cNum = $(this).val();
    });

    var updateTopInterval = 100;
    $("#updateTopInterval").val(updateTopInterval).change(function () {
        var v = $(this).val();
        if (v && !isNaN(+v)) {
            updateTopInterval = +v;
            if (updateTopInterval < 25)
                updateTopInterval = 25;
            if (updateTopInterval > 2000)
                updateTopInterval = 2000;
            $(this).val("" + updateTopInterval);
        }
    });

    var updateBotInterval = 100;
    $("#updateBotInterval").val(updateBotInterval).change(function () {
        var v = $(this).val();
        if (v && !isNaN(+v)) {
            updateBotInterval = +v;
            if (updateBotInterval < 25)
                updateBotInterval = 25;
            if (updateBotInterval > 2000)
                updateBotInterval = 2000;
            $(this).val("" + updateBotInterval);
        }
    });

    // setup plot
    var optionsTop = {
        series: { 
            shadowSize: 0, // drawing is faster without shadows
            points: { show: false},
            lines:  { show: true, lineWidth: 5},
        }, 
        yaxis:	{ min: 10, max: 35, 
                  zoomRange: [10, 256], panRange: [-128, 128] },
        xaxis:	{ show: true, 
                  zoomRange: [10, 100], panRange: [0, 100] },
        legend:	{ position: "sw" },
        zoom:	{ interactive: true, amount: 1.1 },
        pan:	{ interactive: true }
    };
    plotTop = $.plot($("#plotTop"), 
        [ 
          { data:  initPlotData(), 
            label: "GyroTemp" }
        ],
            optionsTop);

    var optionsBot = {
        series: { 
            shadowSize: 0, // drawing is faster without shadows
            points: { show: false},
            lines:  { show: true, lineWidth: 5},
            //color: 2
        }, 
        yaxis:	{ min: -100, max: 100, 
                  zoomRange: [10, 256], panRange: [60, 100] },
        xaxis:	{ show: true, 
                  zoomRange: [10, 100], panRange: [0, 100] },
        legend:	{ position: "sw" },
        zoom:	{ interactive: true, amount: 1.1 },
        pan:	{ interactive: true }
    };
    plotBot = $.plot($("#plotBot"), 
        [ 
          { data:  initPlotData(),
            label: "GyroX"},
          { data:  initPlotData(),
            label: "GyroY"},
          { data:  initPlotData(),
            label: "GyroZ"}
        ],
            optionsBot);

    // Request data every updateInterval ms
    function updateTop() {
        socket.emit("ain",  ainNum);
        socket.emit("gpio", gpioNum);
        setTimeout(updateTop, updateTopInterval);
    }
    //updateTop();

    function updateBot() {
        socket.emit("i2c",  i2cNum);
        setTimeout(updateBot, updateBotInterval);
    }
    //updateBot();
});
</script>

  </body>
</html>

Documents

SparkFun:_ITG-3200,Triple-Axis_Gyro

Schematic

Eagle Files

Quickstart Guide

ITG-3200 Datasheet

Code (ATmega328)

Example

Sparkfun

Github Repo




thumb‎ Embedded Linux Class Ruffin White RHIT