Monitoring auto sensor data with the Raspberry Pi


A boot-up script, performs all necessary steps when the Rasp Pi starts up:

ifconfig can0 up
/home/pi/can-utils/jr_candump can0 -D &

The first line of the script activates the network interface of the CAN adapter, and then jr_candump starts. This is the modified Candump program with its accompanying parameters. It was modified so that the received data can be written to a database via the -D option. After the program starts, jr_candump creates a database, builds a table in the database with the SQL statement from line  1 of Listing  5, then prepares the SQL statement from line  2 to store the data.

Listing 5

Storing Data in the Database

CREATE TABLE IF NOT EXISTS candata(id FLOAT, timestamp FLOAT, yawrate VARCHAR(4), \
  accy VARCHAR(4), rollrate VARCHAR(4), accx VARCHAR(4), accz VARCHAR(4), \
  fueltemp VARCHAR(4), watertemp VARCHAR(4), oilpressure VARCHAR(4), \
INSERT INTO candata (id, timestamp, yawrate, accy, \
  rollrate, accx, accz, fueltemp, watertemp, oilpressure, oiltemp) \
  VALUES (?,?,?,?,?,?,?,?,?,?,?)

As shown at the end of line 1, the database resides in the central memory of the Rasp Pi. The data cannot be saved directly onto the SD card because it arrives too fast. In the final step, the jr_candump utility connects the correct variables with the corresponding placeholders in the INSERT statement from line  2. After the preparation of the database, jr_candump calls a function to interpret each received CAN message. The basic structure can be seen in Listing 6.

Listing 6

Interpreting CAN Messages

01 switch (frame.can_id) {
02   case 0x713:
03     sprintf(fueltemp,    "%02x",[4]);
04     sprintf(watertemp,   "%02x",[7]);
05     sprintf(oilpressure, "%02x",[0]);
06     sprintf(oiltemp,     "%02x",[5]);
07     InsertCANframe();
08     break;
09   /* next CAN-ID ... */
10 }

The interpretation routine determines the CAN ID of an incoming message via a switch statement and then writes the current data received to the appropriate variables. This is followed by a call to the InsertCANframe() function, which increases the ID counter that numbers the individual records in the database and uses the previously prepared INSERT statement to write the variable values to the database.

Visualizing the Data

The Apache web server that is running on the Rasp Pi reads the data from the database and then makes it available online with the help of a small PHP application.

In the process, the data stream is constantly updated via Ajax (asynchronous JavaScript and XML). And, at the same time, the data is visualized via jqPlot  [6] by means of the jQuery framework  [7] (see Figure  6).

Figure 6: Displaying telemetry data in a web browser.

Here, a web application uses JavaScript to gather new data continuously from the server and display it on a website. As a result, the team receives online access to all relevant parameters.

A PHP script called by Ajax at three-second intervals is responsible for loading measurements from the database. The script delivers the data as a JSON file (JavaScript Object Notation, a compact, text-based and easy-to-read (via eval()) data exchange format for humans and computers.

Listing  7 shows a somewhat abbreviated version of this script. You can see that the code delivers the most recently received ID, ($maxID) each time the script is called up, so only the new data is retrieved.

Listing 7

Loading Data from the Database

01      <?php
02      $maxID   = $_GET['maxID'];
03      $sqlhost = 'localhost';
04      $sqluser = 'user';
05      $sqlpwd  = '*****';
06      $sqldb   = 'jr_data';
08      $dbh = new PDO("mysql:host=$sqlhost;dbname=$sqldb", $sqluser, $sqlpwd);
09      $sth = $dbh->prepare('SELECT * FROM candata WHERE id > ?;');
10      $sth->execute(array($maxID));
11      $cnt = 0;
12      while ($row = $sth->fetch(PDO::FETCH_OBJ)) {
13          $ID[$cnt]          = $row->id;
14          $TIMEST[$cnt]      = $row->timestamp;
15          $FUELTEMP[$cnt]    = hexdec($row->fueltemp);
16          $WATERTEMP[$cnt]   = hexdec($row->watertemp);
17          $OILPRESSURE[$cnt] = hexdec($row->oilpressure);
18          $OILTEMP[$cnt]     = hexdec($row->oiltemp);
19          $cnt++;
20      }
21      $result = array(
22          'NEWid'          => $ID,
23          'NEWtime'        => $TIMEST,
24          'NEWfueltemp'    => $FUELTEMP,
25          'NEWwatertemp'   => $WATERTEMP,
26          'NEWoilpressure' => $OILPRESSURE,
27          'NEWoiltemp'     => $OILTEMP
28      );
29      echo trim(json_encode($result));
30      ?>

As a result, the current data values appear on the website with three to five seconds of lag time. Here, jqPlot offers wide ranging possibilities. Listing  8 and Figure  7 illustrate a simple example for the display of a JavaScript array.

Listing 8

Displaying a JavaScript Array

01 <?xml version="1.0" encoding="UTF-8"?>
02 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
03       "">
04 <html xmlns="">
05 <head>
06   <title>Oil Temperature Plot</title>
07   <script type="text/javascript" src="jquery.min.js"></script>
08   <script type="text/javascript" src="jquery.jqplot.min.js"></script>
09   <link rel="stylesheet" type="text/css" href="jquery.jqplot.css" />
10 </head>
12 <body>
13 <div id="chartdiv" style="height:200px;width:500px;"></div>
14 <script type="text/javascript">
16 // An example, the values of the array are updated
17 // using AJAX in reality:
18 var oiltemp = [50, 53, 55, 50, 52, 60, 60, 50, 53, 50];
19 $.jqplot('chartdiv', [oiltemp], {
20     axes: {
21         xaxis: { label: 'Time' },
22         yaxis: { label: 'Oil Temperature' }
23     }
24 });
25 </script>
26 </body>
27 </html>
Figure 7: A simple plot of the data from a JavaScript array by means of jqPlot.

Buy this article as PDF

Express-Checkout as PDF

Pages: 8

Price $2.95
(incl. VAT)

Buy Raspberry Pi Geek

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content