element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
BeagleBoard
  • Products
  • Dev Tools
  • Single-Board Computers
  • BeagleBoard
  • More
  • Cancel
BeagleBoard
Blog BeagleBone Web Server - Temperature Sensor
  • Blog
  • Forum
  • Documents
  • Quiz
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join BeagleBoard to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: oneleggedredcow
  • Date Created: 24 Nov 2013 12:17 AM Date Created
  • Views 4282 views
  • Likes 1 like
  • Comments 21 comments
Related
Recommended

BeagleBone Web Server - Temperature Sensor

oneleggedredcow
oneleggedredcow
24 Nov 2013

Table of Contents

Setup

LED Blinking

MySQL Installation

Temperature Sensor

Introduction

In the previous articles, we set up the BeagleBone to have a MySQL database and a web server.  We also wrote a simple web site to control the LEDs on the BeagleBone.

 

In this article, we are going to tie all of the pieces together and create a web site that displays the temperature of the room that the BeagleBone is in.  We are going to do this by taking temperature measurements using the analog input on the BeagleBone and storing the measured values in the database.  We will then create a PHP page that will query the data out of the database and display it to the user in a google chart.

 

Preparing the Database

The first step is to create a new MySQL database:

 

CREATE DATABASE TempDB;

 

Next, we should probably create a new user to log into the database with.  This isn’t strictly necessary, but it is a good idea to not log in as root every time.  Here’s how to create a new user:

 

CREATE USER bone@localhost IDENTIFIED BY ‘bone’;

 

Then we need to give the new user (bone) permissions on the newly created database:

 

GRANT ALL ON TempDB.* to bone@localhost;

image

I usually prefer to create my tables in code rather than through the MySQL prompt.  The reason is that if I ever want to make any changes or start over, I can just drop the table and then rerun my code and it will take care of it.  I find that this makes it faster and easier to make changes to my table.

 

Interfacing with the Database

So, now that the database and user are set up, we can shift over to C++ to create the table and take temperature measurements.  We’ll start by creating a program that just inserts in any old data into the table and then we’ll incorporate a temperature sensor.  Here’s the first cut at the program:

 

#include <mysql.h>

#include <stdlib.h>

#include <stdio.h>

#include <string.h>

 

/// Prints out a MySQL error message and exits

///

/// This function should be called after a MySQL error has been encountered.  This function will then

/// notify the user of the error that has occurred, clean up the existing MySQL connection, and then

/// exit the program.

///

/// @param The MySQL connection to clean up before exiting

void error_exit(MYSQL *con)

{

fprintf(stderr, "%s\n", mysql_error(con));

 

if (con != NULL)

{

mysql_close(con);

}

           

exit(1);

}

 

int main(int argc, const char *argv[])

{

// Initialize a connection to MySQL

MYSQL *con = mysql_init(NULL);

if(con == NULL)

{

error_exit(con);

}

           

// Connect to MySQL

// Here we pass in:

//  host name => localhost

//  user name => bone

//  password => bone

//  database name => TempDB

if (mysql_real_connect(con, "localhost", "bone", "bone", "TempDB", 0, NULL, 0) == NULL)

{

error_exit(con);

}

 

// Create the TempMeas database (if it doesn't already exist)

if (mysql_query(con, "CREATE TABLE IF NOT EXISTS TempMeas(MeasTime DATETIME, Temp DOUBLE)"))

{

error_exit(con);

}

 

// Initialize a MySQL statement

MYSQL_STMT *stmt = mysql_stmt_init(con);

if (stmt == NULL)

{

error_exit(con);

}

           

// Set out insert query as the MySQL statement

const char *query = "INSERT INTO TempMeas(MeasTime, Temp) VALUES(NOW(), ?)";

if (mysql_stmt_prepare(stmt, query, strlen(query)))

{

error_exit(con);

}

 

// Create the MySQL bind structure to store the data that we are going to insert

double temp = 0.0;

MYSQL_BIND bind;

memset(&bind, 0, sizeof(bind));

bind.buffer_type = MYSQL_TYPE_DOUBLE;

bind.buffer = (char *)&temp;

bind.buffer_length = sizeof(double);

 

// Bind the data structure to the MySQL statement

if (mysql_stmt_bind_param(stmt, &bind))

{

error_exit(con);

}

 

// Insert multiple records into the database,

// with different data each time

for (int i = 0; i < 10; i++)

{

temp = (float)i;

mysql_stmt_execute(stmt);

}

 

// Close the MySQL connection

mysql_close(con);

 

return 0;

}

 

The code is surprisingly straight-forward.  We start by creating the table if it does not exist.  Then we create a parameterized query.  Note that we don’t need to recreate the query or rebind the parameters. This is because we pass a pointer to the bind structure.  So, all we need to do is execute the statement every time a new measurement is taken.

 

To build the code, use the following command:

 

g++ tempmeas_initial.cpp -o tempmeas_initial -I/usr/include/mysql –lmysqlclient

 

Then you can run it using:

 

./tempmeas_initial

 

After running the program, we can go over to MySQL and make sure that everything worked like we expected:

image

That looks good, so let’s move on to incorporating a temperature sensor.

 

Temperature Sensor

Now that we know that we can put data into the database, let’s set up a circuit to gather that data:

image

Here we have a MCP9701E temperature sensor connected to analog input #1.  I also did a simple voltage divider to cut the voltage in half since the input voltage is 3.3V and the analog input pins can only handle a maximum of 1.8V.  The sensor output will never be that high (unless it gets really hot), so it is probably unnecessary, but better safe than sorry.

 

Now we can test to make sure that the circuit is working properly by reading the value that it outputs at:

 

Older BeagleBone:

cat /sys/devices/platform/tsc/ain1

 

Newer BeagleBone:

cat /sys/devices/platform/omap/tsc/ain1

 

Reading the Temperature Sensor

The value that is returned is between 0 - 4096 and it is a measurement of the voltage that is connected to ain1.  We need to convert that voltage into a temperature and to do that, we use the information from the datasheet.  Here is the conversion in code:

 

Header:

 

#ifndef MCP9701E_H

#define MCP9701E_H

 

class MCP9701E

{

private:

int _input;

char _buffer[1024];

 

static const float Vdd;

 

static const int TempSensorMin;

static const int TempSensorMax;

 

static const float V0;

static const float Tc;

 

public:

MCP9701E(const char *pin);

float GetTemperature();

void Close();

};

 

#endif

 

Definition:

 

#include "MCP9701E.h"

 

#include <stdlib.h>

#include <fcntl.h>

#include <stdio.h>

#include <unistd.h>

 

/// Input voltage

const float MCP9701E::Vdd = 3.3;

 

/// Maximum and minimum values that can be measured

const int MCP9701E::TempSensorMin = 0;

const int MCP9701E::TempSensorMax = 4096;

 

/// Temperature sensor constants

const float MCP9701E::V0 = 0.3f;

const float MCP9701E::Tc = 0.0195f;

 

/// Handles a MCP9701E temperature sensor

///

/// @param Hardware device to read the temperature measurements from

MCP9701E::MCP9701E(const char *pin)

{

_input = open(pin, O_RDONLY);

}

 

/// Grabs a temperature measurement

float MCP9701E::GetTemperature()

{

// Read the sensor

int status = read(_input, _buffer, sizeof(_buffer));

if (status == -1)

{

fprintf(stderr, "ERROR: Could not get temperature measurement.");

return -999.0f;

}

 

// Reset the sensor

lseek(_input, 0, 0);

 

// Convert the string into an integer

_buffer[status] = '\0';

int value = atoi(_buffer);

           

// Convert the measurement into a temperature

float voltage = ((float) value) / (TempSensorMax - TempSensorMin + 1) * Vdd;

float temp = (voltage - V0) / Tc;

 

return temp;

}

 

/// Closes the temperature sensor

void MCP9701E::Close()

{

if(_input != -1)

{

close(_input);

_input = -1;

}

}

 

Then we can make a small modification to our code that imports numbers into the MySQL database, so that it now imports in actual temperature measurements.  To do this, we replace the previous for loop with the code below:

 

// Initialize the temperature sensor

MCP9701E sensor("/sys/devices/platform/omap/tsc/ain2");

           

// Take a temperature measurement and insert it into the database

for (int i = 0; i < 10; i++)

{

temp = sensor.GetTemperature();

mysql_stmt_execute(stmt);

sleep(60);

}

           

// Close the temperature sensor

sensor.Close();

 

The full version of the code is attached below.

 

To build the code, use the following command:

 

g++ tempmeas.cpp MCP9701E.cpp -o tempmeas -I/usr/include/mysql –lmysqlclient

 

Then you can run it using:

 

./tempmeas

 

Next we can go over to MySQL and verify that actual temperature measurements are being populated in the database:

image

 

Creating a Web Page

The final piece of the puzzle is to create a web page to display the information in.  To do this, we will use google charts, and slightly modify their line chart example.  All we need to do is add some logic to query the data from the MySQL database:

 

<html>

<head>

<title>BeagleBone Temperature</title>

<script type="text/javascript" src="https://www.google.com/jsapi"></script>

<script type="text/javascript">

google.load("visualization", "1", {packages:["corechart"]});

google.setOnLoadCallback(drawChart);

function drawChart() {

var data = google.visualization.arrayToDataTable([

['Time', 'Temperature'],

<?php

$con = mysqli_connect("localhost", "bone", "bone", "TempDB");

 

$query = "SELECT * FROM TempMeas";

$result = mysqli_query($con, $query);

 

mysqli_close($con);

 

while ($row = mysqli_fetch_array($result))

{

$time = $row['MeasTime'];

$temp = $row['Temp'];

echo "['$time', $temp],";

}

?>

]);

 

var options = {

title: 'BeagleBone Measured Temperature',

vAxis: { title: "Degrees Celsius" }

};

 

var chart = new google.visualization.LineChart(document.getElementById('chart_div'));

chart.draw(data, options);

}

</script>

</head>

<body>

<div id="chart_div" style="width: 900px; height: 500px;"></div>

</body>

</html>

 

The change that we made to the google chart example is the addition of the PHP code.  This code will query all of the data in the database and insert it into the web page that is returned to the user.  If the sensor has been running for a long time, this could be a lot of data.  An improvement would be to limit the measurements to the past hour or so. Even better would be to make it user configurable through the web page!  Here we are just focused on a simple example.

 

Finally, we can visit our web page and check out our results!

image

Summary

In these articles, we have demonstrated how to turn your BeagleBone into a very powerful web server. MySQL, PHP, and JavaScript are the building blocks of most web sites.  Using these tools, you can create some very exciting sites on your BeagleBone! And if you do, please post them to the comments, I’d love to see what projects you are working on.

Attachments:
tempmeas.zip
  • Sign in to reply
  • Former Member
    Former Member over 10 years ago in reply to Former Member

    You might want to have a look at http://docs.gadgetkeeper.com/pages/viewpage.action?pageId=10551892 .  The DHT11 and the MCP9701E are somewhat different in function and use.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • oneleggedredcow
    oneleggedredcow over 10 years ago in reply to Former Member

    Wish I could, but I've never used that sensor before.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Former Member
    Former Member over 10 years ago

    i like it.... would you tell me how to use DHT11 humidity sensor instead of MCP9701E.... ??

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Former Member
    Former Member over 10 years ago in reply to oneleggedredcow

    Thank you so much. I found the solution. The problem was due to the directory. In the latest kernel, (3.8.13 onward) the channels are exported to folder /sys/bus/iio/devices/iio:devices0/in_voltage1_raw instead of /sys/devices/platform/omap/tsc/ain1.

    Changing the channel solved my problem. Thank you so much again. image

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • oneleggedredcow
    oneleggedredcow over 10 years ago in reply to Former Member

    That error message looks like it is not able to read the spot on the file system that has the temperature measurement.  The easiest way to debug this is using the command line.  Run the following command (based on what type of system you have) and see what it returns:

     

    Older BeagleBone:

    cat /sys/devices/platform/tsc/ain1

     

    Newer BeagleBone:

    cat /sys/devices/platform/omap/tsc/ain1

     

    One of those commands should return a value, if both give you an error message, then something is not configured properly.  (Not sure if there is another directory possibility on even newer BeagleBones?)

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube