ThingSpeak is the open platform for Internet of Thing. You can store your data on Thingspeak storage, analyze, visualize… data. For more detail, visit https://thingspeak.com/
Demo
My channel with two fields: temperature and humidity.
Things Used In This Project
- PHPoC Blue
- Temperature and Humidity sensor (one of three: Grove - Temperature&Humidity Sensor TH02, Grove - Temperature&Humidity Sensor (HDC1000) , HTS221).
- USB wireless LAN dongle.
- Grove expansion board for PHPoC (Optional).
- Expansion board for Click boards (optional).
Steps
- Create a ThingSpeak account (visit https://thingspeak.com/users/sign_up ).
- Create a channel with two fields: Temperature and Humidity. (visit https://thingspeak.com/channels )
- Write down your channel id, Write API Key, Read API Key.
Now let’s look at PHPoC source code. Source code includes:
- vn_thingspeak.php: update/get data to/from your channel.
- vd_th02.php: library for TH02 temp&humi sensor.
- vd_hdc1000.php: library for HDC1000 temp&humi sensor.
- vd_hts221.php: library for HTS221 temp&humi sensor.
- task0.php: main program.
You can see one by one below:
<task0.php>
PHP Code:
<?php
if(_SERVER("REQUEST_METHOD"))
exit; // avoid php execution via http request
include_once "/lib/sd_340.php";
include_once "/lib/sn_dns.php";
include_once "/lib/sn_http.php";
include_once "/lib/vn_thingspeak.php";
include_once "/lib/vd_th02.php";
include_once "/lib/vd_hdc1000.php";
include_once "/lib/vd_hts221.php";
define("TH02", 0); // grove Temperature&Humidity Sensor (High-Accuracy & Mini) V1.0
define("HDC1000", 1); // grove Temperature&Humidity Sensor (HDC1000)
define("HTS221", 2); // mikro click
$my_write_api_key = "your write api key";
$my_read_api_key = "your read api key";
$my_channel_id = "your channed id";
$sensor_type = TH02; // choose sensor type here
switch($sensor_type)
{
case TH02:
i2c_TH02_setup(0);
break;
case HDC1000:
i2c_HDC1000_setup(0);
break;
case HTS221:
i2c_HTS221_setup(0);
while(!HTS221_init())
;
break;
default:
exit "library is not yet available for this sensor\r\n";
}
while(1)
{
switch($sensor_type)
{
case TH02:
$temp = TH02_read_temperature();
$humi = TH02_read_humidity();
break;
case HDC1000:
$temp = HDC1000_read_temperature();
$humi = HDC1000_read_humidity();
break;
case HTS221:
$temp = HTS221_read_temperature();
if(is_bool($temp))
{
echo "a new temperature sample is not yet available\r\n";
usleep(500000);
continue;
}
usleep(1000);
$humi = HTS221_read_humidity();
if(is_bool($humi))
{
echo "a new humidity sample is not yet available\r\n";
usleep(500000);
continue;
}
}
thingspeak_set_field(1, $temp);
thingspeak_set_field(2, $humi);
$reval = thingspeak_write_fields($my_channel_id, $my_write_api_key);
if( $reval === OK_SUCCESS)
echo "write successfully\r\n";
else
echo "write unsuccessfully\r\n";
// maximum update rate of thingspeak is 15 second
sleep(15);
}
?>
<vn_thingspeak.php >
PHP Code:
<?php
define("THINGSPEAK_URL", "api.thingspeak.com");
define("FIELDNUM_MIN", 1);
define("FIELDNUM_MAX", 8);
define("FIELDLENGTH_MAX", 255); // Max length for a field in ThingSpeak is 255 bytes (UTF-8)
define("OK_SUCCESS", 200); // OK / Success
define("ERR_BADAPIKEY", 400); // Incorrect API key (or invalid ThingSpeak server address)
define("ERR_BADURL", 404); // Incorrect API key (or invalid ThingSpeak server address)
define("ERR_OUT_OF_RANGE", -101); // Value is out of range or string is too long (> 255 bytes)
define("ERR_INVALID_FIELD_NUM", -201); // Invalid field number specified
define("ERR_SET_FIELD_NOT_CALLED", -210); // thingspeak_set_field() was not called before thingspeak_write_fields()
define("ERR_CONNECT_FAILED", -301); // Failed to connect to ThingSpeak
define("ERR_UNEXPECTED_FAIL", -302); // Unexpected failure during write to ThingSpeak
define("ERR_BAD_RESPONSE", -303); // Unable to parse response
define("ERR_TIMEOUT", -304); // Timeout waiting for server to respond
define("ERR_NOT_INSERTED", -401); // Point was not inserted (most probable cause is the rate limit of once every 15 seconds)
$next_write_fields = array("", "", "", "", "", "", "", "");
$next_write_latitude = "";
$next_write_longitude = "";
$next_write_elevation = "";
$next_write_status = "";
$next_write_twitter = "";
$next_write_tweet = "";
$next_write_created_at = "";
function json_get_value($json_str, $key, &$value, $offset = 0)
{
$value = "";
if(strlen($json_str) == 0)
return false;
$search = """ . $key . "":";
$from_pos = strpos($json_str, $search, $offset);
if($from_pos === false)
return false;
$from_pos += strlen($search);
while($json_str[$from_pos] == " ")
$from_pos++;
$to_pos = $from_pos;
$start_char = $json_str[$from_pos];
if($start_char == "[" || $start_char == "{")
{
if($start_char == "[")
$end_char = "]";
else
$end_char = "}";
$start_count = 0;
$end_count = 0;
for($i = $from_pos; $i < strlen($json_str); $i++)
{
if($json_str[$i] == $start_char)
$start_count++;
if($json_str[$i] == $end_char)
$end_count++;
if($end_count == $start_count)
{
$to_pos = $i;
break;
}
}
}
else
{
$pos1 = strpos($json_str, ",", $from_pos);
$pos2 = strpos($json_str, "}", $from_pos);
if($pos1 === false)
$to_pos = $pos2;
else if($pos2 === false)
$to_pos = $pos1;
else
$to_pos = ($pos1 > $pos2) ? $pos2: $pos1;
$to_pos--;
}
if($to_pos === false)
return false;
$length = $to_pos - $from_pos + 1;
$value = substr($json_str, $from_pos, $length);
$value = rtrim(ltrim($value, """), """);
return $to_pos;
}
function thingspeak_setup($udp_id, $tcp_id, $dns_server = "", $ip6 = false)
{
http_setup($udp_id, $tcp_id, $dns_server, $ip6);
}
/**
*@brief: Write a raw POST to a ThingSpeak channel
*@param: $channel_id: Channel number
*@param: $post_msg: Raw URL to write to ThingSpeak as a String. See the documentation at https://thingspeak.com/docs/channels#update_feed.
*@param: $write_api_key: Write API key associated with the channel. If you share code with others, do not share this key
*@return: status code.
*@remark: This is low level functionality that will not be required by most users.
*@example code:
$post_msg = "field1=23&created_at=2017-03-23T23:59:59";
thingspeak_write_raw($my_channel_id, $post_msg, $my_write_api_key);
*/
function thingspeak_write_raw($channel_id, $post_msg, $write_api_key)
{
$post_msg .= "&headers=false\n";
$cnt_len = strlen($post_msg);
http_add_header("Content-Type: application/x-www-form-urlencoded\r\n");
http_add_header("Content-Length: $cnt_len\r\n");
http_add_header("X-THINGSPEAKAPIKEY: $write_api_key\r\n");
$rsp_head = http_request("post", THINGSPEAK_URL . "/update", $post_msg);
//echo $rsp_head;
if($rsp_head === "")
return ERR_CONNECT_FAILED;
$status = http_status($rsp_head);
$rsp_body = "";
$rbuf = "";
while(http_recv($rbuf))
$rsp_body .= $rbuf;
http_close();
if($status == OK_SUCCESS)
{
$entry_id = (int)$rsp_body;
if($entry_id == 0)
{
// ThingSpeak did not accept the write
$status = ERR_NOT_INSERTED;
}
}
return $status;
}
/**
*@brief: Read a raw response from a ThingSpeak channel
*@param: $rsp_body: buffer to store the http body
*@param: $channel_id: Channel number
*@param: $url_suffix: Raw URL to write to ThingSpeak as a String. See the documentation at https://thingspeak.com/docs/channels#get_feed
*@param: $read_api_key: Read API key associated with the channel. Igrore this param if reading a public channel. If you share code with others, do not share this key
*@return: status code.
*@remark: This is low level functionality that will not be required by most users.
*@example code:
$response = "";
thingspeak_read_raw($response, $my_channel_id, "/feeds/last.txt", $my_read_api_key);
echo $response;
*/
function thingspeak_read_raw(&$rsp_body, $channel_id, $url_suffix, $read_api_key = "")
{
$rsp_body = "";
$uri = THINGSPEAK_URL . "/channels/$channel_id" . $url_suffix;
http_add_header("X-THINGSPEAKAPIKEY: $read_api_key\r\n");
$rsp_head = http_request("get", $uri);
//echo $rsp_head;
if($rsp_head === "")
return ERR_CONNECT_FAILED;
$status = http_status($rsp_head);
$rbuf = "";
while(http_recv($rbuf))
$rsp_body .= $rbuf;
http_close();
if($status != OK_SUCCESS)
{
$rsp_body = "";
}
return $status;
}
/**
*@brief: Write data (any type) to a single field in a ThingSpeak channel
*@param: $channel_id: Channel number
*@param: $field: Field number (1-8) within the channel to write to.
*@param: $value: Value to write (any type). ThingSpeak limits this field to 255 bytes.
*@param: $write_api_key: Write API key associated with the channel. If you share code with others, do not share this key
*@return: status code.
*@remark: Visit https://thingspeak.com/docs/channels for more information about channels, API keys, and fields. ThingSpeak limits the number of writes to a channel to once every 15 seconds.
*@example code:
thingspeak_write_field($my_channel_id, 1, 25, $my_write_api_key);
thingspeak_write_field($my_channel_id, 3, "Too Hot!", $my_write_api_key);
*/
function thingspeak_write_field($channel_id, $field, $value, $write_api_key)
{
$post_msg = "field$field=$value";
return thingspeak_write_raw($channel_id, $post_msg, $write_api_key);
}
/**
*@brief: Set the value of a single field that will be part of a multi-field update. To write multiple fields at once, call thingspeak_set_field() for each of the fields you want to write, and then call thingspeak_write_fields()
*@param: $field: Field number (1-8) within the channel to set
*@param: $value: value to write (any type). ThingSpeak limits this to 255 bytes.
*@return: status code.
*@example code:
thingspeak_set_field(1, 1.2);
thingspeak_set_field(2, 15);
thingspeak_set_field(3, "state ON");
thingspeak_write_fields($my_channel_id, $my_write_api_key);
*/
function thingspeak_set_field($field, $value)
{
global $next_write_fields;
$str_value = "$value";
if($field < FIELDNUM_MIN || $field > FIELDNUM_MAX)
return ERR_INVALID_FIELD_NUM;
// Max # bytes for ThingSpeak field is 255 (UTF-8)
if(strlen($str_value) > FIELDLENGTH_MAX)
return ERR_OUT_OF_RANGE;
$next_write_fields[$field - 1] = $str_value;
return OK_SUCCESS;
}
/**
*@brief: Set the latitude of a multi-field update. To record latitude, longitude and elevation of a write, call thingspeak_set_field() for each of the fields you want to write, thingspeak_set_latitude() / thingspeak_set_longitude() / thingspeak_set_elevation(), and then call thingspeak_write_fields()
*@param: $latitude: Latitude of the measurement (degrees N, use negative values for degrees S)
*@return: status code.
*@see thingspeak_set_field(), thingspeak_set_longitude(), thingspeak_set_elevation(), thingspeak_write_fields()
*@example code:
thingspeak_set_field(1, 1.2);
thingspeak_set_field(2, 15);
thingspeak_set_field(3, "state ON");
thingspeak_set_latitude(42.2833);
thingspeak_set_longitude(-71.3500);
thingspeak_set_elevation(100);
thingspeak_write_fields($my_channel_id, $my_write_api_key);
*/
function thingspeak_set_latitude($latitude)
{
global $next_write_latitude;
$next_write_latitude = "$latitude";
return OK_SUCCESS;
}
/**
*@brief: Set the longitude of a multi-field update. To record latitude, longitude and elevation of a write, call thingspeak_set_field() for each of the fields you want to write, thingspeak_set_latitude() / thingspeak_set_longitude() / thingspeak_set_elevation(), and then call thingspeak_write_fields()
*@param: $longitude: Longitude of the measurement (degrees E, use negative values for degrees W)
*@return: status code.
*@see thingspeak_set_field(), thingspeak_set_latitude(), thingspeak_set_elevation(), thingspeak_write_fields()
*@example code:
thingspeak_set_field(1, 1.2);
thingspeak_set_field(2, 15);
thingspeak_set_field(3, "state ON");
thingspeak_set_latitude(42.2833);
thingspeak_set_longitude(-71.3500);
thingspeak_set_elevation(100);
thingspeak_write_fields($my_channel_id, $my_write_api_key);
*/
function thingspeak_set_longitude($longitude)
{
global $next_write_longitude;
$next_write_longitude = "$longitude";
return OK_SUCCESS;
}
/**
*@brief: Set the elevation of a multi-field update. To record latitude, longitude and elevation of a write, call thingspeak_set_field() for each of the fields you want to write, thingspeak_set_latitude() / thingspeak_set_longitude() / thingspeak_set_elevation(), and then call thingspeak_write_fields()
*@param: $elevation: Elevation of the measurement (meters above sea level)
*@return: status code.
*@see thingspeak_set_field(), thingspeak_set_latitude(), thingspeak_set_longitude(), thingspeak_write_fields()
*@example code:
thingspeak_set_field(1, 1.2);
thingspeak_set_field(2, 15);
thingspeak_set_field(3, "state ON");
thingspeak_set_latitude(42.2833);
thingspeak_set_longitude(-71.3500);
thingspeak_set_elevation(100);
thingspeak_write_fields($my_channel_id, $my_write_api_key);
*/
function thingspeak_set_elevation($elevation)
{
global $next_write_elevation;
$next_write_elevation = "$elevation";
return OK_SUCCESS;
}
/**
*@brief: Set the status of a multi-field update. To record a status message on a write, call thingspeak_set_status() then call thingspeak_write_fields(). Use status to provide additonal details when writing a channel update.
*@param: $status: String to write (UTF8). ThingSpeak limits this to 255 bytes.
*@return: status code.
*@see thingspeak_write_fields()
*@example code:
thingspeak_set_field(1, 1.2);
thingspeak_set_field(2, 15);
thingspeak_set_field(3, "state ON");
thingspeak_set_status("Too Cold!");
thingspeak_write_fields($my_channel_id, $my_write_api_key);
*/
function thingspeak_set_status($status)
{
global $next_write_status;
// Max # bytes for ThingSpeak field is 255 (UTF-8)
if(strlen($status) > FIELDLENGTH_MAX)
return ERR_OUT_OF_RANGE;
$next_write_status = $status;
return OK_SUCCESS;
}
/**
*@brief: Set the Twitter account and message to use for an update to be tweeted. To send a message to twitter call thingspeak_set_twitter_tweet() then call thingspeak_write_fields()
*@param: $twitter: Twitter account name as a String.
*@param: $tweet: Twitter message as a String (UTF-8) limited to 140 character.
*@return: status code.
*@remark: Prior to using this feature, a twitter account must be linked to your ThingSpeak account. Do this by logging into ThingSpeak and going to Apps, then ThingTweet and clicking Link Twitter Account.
*@see thingspeak_write_fields()
*@example code:
thingspeak_set_field(1, 1.2);
thingspeak_set_field(2, 15);
thingspeak_set_field(3, "state ON");
thingspeak_set_status("Too Cold!");
thingspeak_set_twitter_tweet("YourTwitterAccountName", "Too Hot!");
thingspeak_write_fields($my_channel_id, $my_write_api_key);
*/
function thingspeak_set_twitter_tweet($twitter, $tweet)
{
global $next_write_twitter;
global $next_write_tweet;
if((strlen($twitter) > FIELDLENGTH_MAX) || (strlen($tweet) > FIELDLENGTH_MAX))
return ERR_OUT_OF_RANGE;
$next_write_twitter = $twitter;
$next_write_tweet = $tweet;
return OK_SUCCESS;
}
/**
*@brief: Set the created-at date of a multi-field update. To record created-at of a write, call thingspeak_set_field() for each of the fields you want to write, thingspeak_set_created_at(), and then call thingspeak_write_fields()
*@param: $created_at Desired timestamp to be included with the channel update as a String. The timestamp string must be in the ISO 8601 format. Example "2017-03-23T13:59:59"
*@return: status code.
*@remark: Timezones can be set using the timezone hour offset parameter. For example, a timestamp for Eastern Standard Time is: "2017-01-12 13:22:54-05". If no timezone hour offset parameter is used, UTC time is assumed.
*@see thingspeak_set_field(), thingspeak_write_fields()
*@example code:
thingspeak_set_field(1, 1.2);
thingspeak_set_field(2, 15);
thingspeak_set_field(3, "state ON");
thingspeak_set_status("Too Cold!");
thingspeak_set_created_at("2017-03-23T13:59:59");
thingspeak_write_fields($my_channel_id, $my_write_api_key);
*/
function thingspeak_set_created_at($created_at)
{
global $next_write_created_at;
$next_write_created_at = $created_at;
return OK_SUCCESS;
}
/**
*@brief: Write a multi-field update. Call thingspeak_set_field() for each of the fields you want to write, thingspeak_set_latitude() / thingspeak_set_longitude() / thingspeak_set_elevation(), and then call thingspeak_write_fields()
*@param: $channel_id: Channel number
*@param: $write_api_key: Write API key associated with the channel. If you share code with others, do not share this key
*@return: status code.
*@see thingspeak_set_field(), thingspeak_set_latitude(), thingspeak_set_longitude(), thingspeak_set_elevation()
*@example code:
thingspeak_set_field(1, 1.2);
thingspeak_set_field(2, 15);
thingspeak_set_field(3, "state ON");
thingspeak_set_latitude(42.2833);
thingspeak_set_longitude(-71.3500);
thingspeak_set_elevation(100);
thingspeak_write_fields($my_channel_id, $my_write_api_key);
*/
function thingspeak_write_fields($channel_id, $write_api_key)
{
global $next_write_fields;
global $next_write_latitude;
global $next_write_longitude;
global $next_write_elevation;
global $next_write_status;
global $next_write_twitter;
global $next_write_tweet;
global $next_write_created_at;
$post_msg = "";
$is_first_item = true;
for($i = 0; $i < 8; $i++)
{
if($next_write_fields[$i] != "")
{
if(!$is_first_item)
{
$post_msg .= "&";
}
$field = $i + 1;
$post_msg .= "field$field=" . $next_write_fields[$i];
$is_first_item = false;
$next_write_fields[$i] = "";
}
}
if($next_write_latitude != "")
{
if(!$is_first_item)
{
$post_msg .= "&";
}
$post_msg .= "lat=" . $next_write_latitude;
$is_first_item = false;
$next_write_latitude = "";
}
if($next_write_longitude != "")
{
if(!$is_first_item)
{
$post_msg .= "&";
}
$post_msg .= "long=" . $next_write_longitude;
$is_first_item = false;
$next_write_longitude = "";
}
if($next_write_elevation != "")
{
if(!$is_first_item)
{
$post_msg .= "&";
}
$post_msg .= "elevation=" . $next_write_elevation;
$is_first_item = false;
$next_write_elevation = "";
}
if($next_write_status != "")
{
if(!$is_first_item)
{
$post_msg .= "&";
}
$post_msg .= "status=" . $next_write_status;
$is_first_item = false;
$next_write_status = "";
}
if($next_write_twitter != "")
{
if(!$is_first_item)
{
$post_msg .= "&";
}
$post_msg .= "twitter=" . $next_write_twitter;
$is_first_item = false;
$next_write_twitter = "";
}
if($next_write_tweet != "")
{
if(!$is_first_item)
{
$post_msg .= "&";
}
$post_msg .= "tweet=" . $next_write_tweet;
$is_first_item = false;
$next_write_tweet = "";
}
if($next_write_created_at != "")
{
if(!$is_first_item)
{
$post_msg .= "&";
}
$post_msg .= "created_at=" . $next_write_created_at;
$is_first_item = false;
$next_write_created_at = "";
}
if($is_first_item)
{
// thingspeak_set_field() was not called before write_fields
return ERR_SET_FIELD_NOT_CALLED;
}
return thingspeak_write_raw($channel_id, $post_msg, $write_api_key);
}
/**
*@brief: Read the latest field value from a ThingSpeak channel
*@param: $buf: buffer to store the field value
*@param: $channel_id: Channel number
*@param: $field: Field number (1-8) within the channel to read from.
*@param: $read_api_key: Read API key associated with the channel. Igrore this param if reading a public channel. If you share code with others, do not share this key
*@return: status code.
*@example code:
$value = "";
$status = thingspeak_read_field($value, $my_channel_id, 1, $my_read_api_key);
echo "status: $status\r\n";
echo "value: $value\r\n";
*/
function thingspeak_read_field(&$buf, $channel_id, $field, $read_api_key = "")
{
if($field < FIELDNUM_MIN || $field > FIELDNUM_MAX)
return ERR_INVALID_FIELD_NUM;
return thingspeak_read_raw($buf, $channel_id, "/fields/$field/last", $read_api_key);
}
/**
*@brief: Read the latest status from a ThingSpeak channel
*@param: $channel_id: Channel number
*@param: $read_api_key: Read API key associated with the channel. Igrore this param if reading a public channel. If you share code with others, do not share this key
*@return: Value read (UTF8 string). An empty string is returned if there was no status written to the channel or in case of an error. Use getLastthingspeak_read_status() to get more specific information.
*@example code:
$status = thingspeak_read_status($my_channel_id, $my_read_api_key);
echo "Latest status is: $status";
*/
function thingspeak_read_status($channel_id, $read_api_key = "")
{
$buf = "";
$ret = thingspeak_read_raw($buf, $channel_id, "/feeds/last.txt?status=true", $read_api_key);
$status = "";
if($ret == OK_SUCCESS)
json_get_value($buf, "status", $status);
return $status;
}
/**
*@brief: Read the created-at timestamp associated with the latest update to a ThingSpeak channel
*@param: $channel_id: Channel number
*@param: $read_api_key: Read API key associated with the channel. Igrore this param if reading a public channel. If you share code with others, do not share this key
*@return: Value read (UTF8 string). An empty string is returned if there was no created-at timestamp written to the channel or in case of an error. Use getLastthingspeak_read_status() to get more specific information.
*@example code:
$created_at = thingspeak_read_created_at($my_channel_id, $my_read_api_key);
echo "Latest update timestamp is: $created_at";
*/
function thingspeak_read_created_at($channel_id, $read_api_key = "")
{
$buf = "";
$ret = thingspeak_read_raw($buf, $channel_id, "/feeds/last.txt", $read_api_key);
$created_at = "";
if($ret == OK_SUCCESS)
json_get_value($buf, "created_at", $created_at);
return $created_at;
}
?>
<vd_th02.php>
PHP Code:
<?php
include_once "/lib/sd_340.php";
define("TH02_ADDR", 0x40);
define("REG_STATUS", 0x00);
define("REG_DATA_H", 0x01);
define("REG_DATA_L", 0x02);
define("REG_CONFIG", 0x03);
define("REG_ID", 0x11);
define("STATUS_RDY_MASK", 0x01); //poll RDY,0 indicate the conversion is done
define("CMD_MEASURE_HUMI", 0x01); //perform a humility measurement
define("CMD_MEASURE_TEMP", 0x11); //perform a temperature measurement
define("TH02_WR_REG_MODE", 0xC0);
define("TH02_RD_REG_MODE", 0x80);
$pid = 0;
function i2c_TH02_setup($i2c_id)
{
global $pid ;
$sensor_addr = sprintf("%02x", TH02_ADDR << 1);
$pid = pid_open("/mmap/i2c$i2c_id");
pid_ioctl($pid, "req reset");
pid_ioctl($pid, "set saddr $sensor_addr");
pid_ioctl($pid, "set mode sm");
pid_ioctl($pid, "set role master");
}
// Generic I2C write $data to register (single byte)
function TH02_write8($addr_reg, $data)
{
global $pid ;
pid_ioctl($pid, "req reset");
pid_ioctl($pid, "req write wait");
//register to read
pid_write($pid, $addr_reg, 1);
pid_write($pid, $data, 1);
pid_ioctl($pid, "req stop"); // stop writing data
}
// Generic I2C read registers (two bytes, LSB first)
function TH02_read16($addr_reg)
{
global $pid ;
$data_lsb = 0x00;
$data_msb = 0x00;
pid_ioctl($pid, "req reset");
pid_ioctl($pid, "req write wait");
// register to read
pid_write($pid, $addr_reg, 1);
pid_ioctl($pid, "req stop"); // stop writing data
pid_ioctl($pid, "req read 2"); // request to read 2 bytes
while(pid_ioctl($pid, "get rxlen") < 2); // check received data
pid_read($pid, $data_lsb, 1); // read buffer
pid_read($pid, $data_msb, 1); // read buffer
return ($data_lsb | ($data_msb << 8));
}
function TH02_read_temperature()
{
TH02_write8(REG_CONFIG, CMD_MEASURE_TEMP);
usleep(50000);
$value = TH02_read16(REG_DATA_H);
$value = (float)($value >> 2);
/*
Formula:
Temperature(C) = (Value/32) - 50
*/
$temper = ($value/32.0)-50.0;
return $temper;
}
function TH02_read_humidity()
{
TH02_write8(REG_CONFIG, CMD_MEASURE_HUMI);
usleep(50000);
$value = TH02_read16(REG_DATA_H);
$value = (float)($value >> 4);
/*
Formula:
Humidity(%) = (Value/16) - 24
*/
$humility = ($value/16.0)-24.0;
return $humility;
}
?>
<vd_hdc1000.php>
PHP Code:
<?php
include_once "/lib/sd_340.php";
define("HDC1000_ADDR", 0x40);
define("HDC1000_TEMP", 0x00);
define("HDC1000_HUMI", 0x01);
define("HDC1000_CONFIG", 0x02);
define("HDC1000_SERID_1", 0xFB);
define("HDC1000_SERID_2", 0xFC);
define("HDC1000_SERID_3", 0xFD);
define("HDC1000_MFID", 0xFE);
define("HDC1000_DEVID", 0xFF);
define("HDC1000_RST", 0x80);
define("HDC1000_HEAT_ON", 0x20);
define("HDC1000_HEAT_OFF", 0x00);
define("HDC1000_BOTH_TEMP_HUMI", 0x10);
define("HDC1000_SINGLE_MEASUR", 0x00);
define("HDC1000_TEMP_HUMI_14BIT", 0x00);
define("HDC1000_TEMP_11BIT", 0x40);
define("HDC1000_HUMI_11BIT", 0x01);
define("HDC1000_HUMI_8BIT", 0x02);
$pid = 0;
function i2c_HDC1000_setup($i2c_id)
{
global $pid ;
$sensor_addr = sprintf("%02x", HDC1000_ADDR << 1);
$pid = pid_open("/mmap/i2c$i2c_id");
pid_ioctl($pid, "req reset");
pid_ioctl($pid, "set saddr $sensor_addr");
pid_ioctl($pid, "set mode sm");
pid_ioctl($pid, "set role master");
}
// Generic I2C read registers (two bytes, LSB first)
function HDC1000_read16($addr_reg)
{
global $pid ;
$data_lsb = 0x00;
$data_msb = 0x00;
pid_ioctl($pid, "req reset");
pid_ioctl($pid, "req write wait");
// register to read
pid_write($pid, $addr_reg, 1);
pid_ioctl($pid, "req stop"); // stop writing data
usleep(20000);
pid_ioctl($pid, "req read 2"); // request to read 2 bytes
while(pid_ioctl($pid, "get rxlen") < 2); // check received data
pid_read($pid, $data_msb, 1); // read buffer
pid_read($pid, $data_lsb, 1); // read buffer
return ($data_lsb | ($data_msb << 8));
}
// Generic I2C write $data to registers (two bytes, LSB first)
function HDC1000_write16($addr_reg, $data)
{
global $pid ;
$data_lsb = $data & 0xff;
$data_msb = $data >> 8;
pid_ioctl($pid, "req reset");
pid_ioctl($pid, "req write wait");
//register to read
pid_write($pid, $addr_reg, 1);
pid_write($pid, $data_lsb, 1);
pid_write($pid, $data_msb, 1);
while(pid_ioctl($pid, "get txlen")); // check received data
pid_ioctl($pid, "req stop"); // stop writing data
}
function HDC1000_read_temperature()
{
$temp = HDC1000_read16(HDC1000_TEMP);
return $temp/65536.0*165.0-40.0;
}
function HDC1000_read_humidity()
{
$humi = HDC1000_read16(HDC1000_HUMI);
return $humi/65536.0*100.0;
}
?>
< vd_hts221.php >
PHP Code:
<?php
include_once "/lib/sd_340.php";
define("HTS221_ADDR", 0x5F);
//Define a few of the registers that we will be accessing on the HTS221
define("WHO_AM_I", 0x0F);
define("WHO_AM_I_RETURN", 0xBC); //This read-only register contains the device identifier, set to BCh
define("AVERAGE_REG", 0x10); // To configure humidity/temperature average.
define("AVERAGE_DEFAULT", 0x1B);
define("CTRL_REG1", 0x20);
define("POWER_UP", 0x80);
define("BDU_SET", 0x4);
define("ODR0_SET", 0x1); // setting sensor reading period 1Hz
define("CTRL_REG2", 0x21);
define("CTRL_REG3", 0x22);
define("REG_DEFAULT", 0x00);
define("STATUS_REG", 0x27);
define("TEMPERATURE_READY", 0x1);
define("HUMIDITY_READY", 0x2);
define("HUMIDITY_L_REG", 0x28);
define("HUMIDITY_H_REG", 0x29);
define("TEMP_L_REG", 0x2A);
define("TEMP_H_REG", 0x2B);
define("CALIB_START", 0x30);
define("CALIB_END", 0x3F);
/*
define("CALIB_T0_DEGC_X8", 0x32);
define("CALIB_T1_DEGC_X8", 0x33);
define("CALIB_T1_T0_MSB", 0x35);
define("CALIB$T0_OUT_L", 0x3C);
define("CALIB$T0_OUT_H", 0x3D);
define("CALIB$T1_OUT_L", 0x3E);
define("CALIB$T1_OUT_H", 0x3F);
*/
$h0_rH = 0;
$h1_rH = 0;
$T0_degC = 0;
$T1_degC = 0;
$H0_T0 = 0;
$H1_T0 = 0;
$T0_OUT = 0;
$T1_OUT = 0;
$pid = 0;
function twobyte2singedint($twobyte)
{
if($twobyte & 0x8000)
{
$twobyte = ($twobyte & 0x7fff) - 0x8000;
}
return $twobyte;
}
function i2c_HTS221_setup($i2c_id)
{
global $pid ;
$sensor_addr = sprintf("%02x", HTS221_ADDR << 1);
$pid = pid_open("/mmap/i2c$i2c_id");
pid_ioctl($pid, "req reset");
pid_ioctl($pid, "set saddr $sensor_addr");
pid_ioctl($pid, "set mode sm");
pid_ioctl($pid, "set role master");
//pid_close($pid);
}
// Generic I2C read register (single byte)
function HTS221_read8($addr_reg)
{
global $pid ;
//$pid = pid_open("/mmap/i2c0"); // open I2C 0
pid_ioctl($pid, "req reset");
//pid_write($pid, "\x30\x00");
pid_ioctl($pid, "req write wait");
// register to read
pid_write($pid, $addr_reg, 1);
//while(pid_ioctl($pid, "get txlen")); // check transmitted data
pid_ioctl($pid, "req stop"); // stop writing data
$data = 0;
pid_ioctl($pid, "req read 1"); // request to read 1 bytes
while(pid_ioctl($pid, "get rxlen") < 1) // check received data
;
pid_read($pid, $data, 1); // read buffer
//pid_close($pid);
return $data;
}
// Generic I2C write $data to register (single byte)
function HTS221_write8($addr_reg, $data)
{
global $pid ;
//$pid = pid_open("/mmap/i2c0"); // open I2C 0
pid_ioctl($pid, "req reset");
//pid_write($pid, "\x40\x00");
pid_ioctl($pid, "req write wait");
//register to read
pid_write($pid, $addr_reg, 1);
pid_write($pid, $data, 1);
while(pid_ioctl($pid, "get txlen")); // check transmitted data
pid_ioctl($pid, "req stop"); // stop writing data
//pid_close($pid);
}
function HTS221_activate()
{
$data = HTS221_read8(CTRL_REG1);
$data |= POWER_UP;
$data |= ODR0_SET;
HTS221_write8(CTRL_REG1, $data);
return true;
}
function HTS221_store_calibration()
{
global $h0_rH;
global $h1_rH;
global $T0_degC;
global $T1_degC;
global $H0_T0;
global $H1_T0;
global $T0_OUT;
global $T1_OUT;
for ($reg=CALIB_START; $reg<=CALIB_END; $reg++)
{
if (($reg!=CALIB_START+8) && ($reg!=CALIB_START+9) && ($reg!=CALIB_START+4))
{
$data = HTS221_read8($reg);
switch ($reg)
{
case CALIB_START:
$h0_rH = $data;
break;
case CALIB_START+1:
$h1_rH = $data;
break;
case CALIB_START+2:
$T0_degC = $data;
break;
case CALIB_START+3:
$T1_degC = $data;
break;
case CALIB_START+5:
$tmp = $T0_degC;
$T0_degC = ($data&0x3)<<8;
$T0_degC |= $tmp;
$tmp = $T1_degC;
$T1_degC = (($data&0xC)>>2)<<8;
$T1_degC |= $tmp;
break;
case CALIB_START+6:
$H0_T0 = $data;
break;
case CALIB_START+7:
$H0_T0 |= $data<<8;
break;
case CALIB_START+0xA:
$H1_T0 = $data;
break;
case CALIB_START+0xB:
$H1_T0 |= $data <<8;
break;
case CALIB_START+0xC:
$T0_OUT = $data;
break;
case CALIB_START+0xD:
$T0_OUT |= $data << 8;
break;
case CALIB_START+0xE:
$T1_OUT = $data;
break;
case CALIB_START+0xF:
$T1_OUT |= $data << 8;
break;
case CALIB_START+8:
case CALIB_START+9:
case CALIB_START+4:
//DO NOTHING
break;
// to cover any possible error
default:
return false;
} /* switch */
} /* if */
} /* for */
$T0_OUT = twobyte2singedint($T0_OUT);
$T1_OUT = twobyte2singedint($T1_OUT);
$H0_T0 = twobyte2singedint($H0_T0);
$H1_T0 = twobyte2singedint($H1_T0);
return true;
}
function HTS221_init()
{
$data = HTS221_read8(WHO_AM_I);
if ($data == WHO_AM_I_RETURN)
{
if (HTS221_activate())
{
HTS221_store_calibration();
return true;
}
}
return false;
}
function HTS221_read_temperature()
{
global $h0_rH;
global $h1_rH;
global $T0_degC;
global $T1_degC;
global $H0_T0;
global $H1_T0;
global $T0_OUT;
global $T1_OUT;
$data = 0;
$t_out = 0;
$t_temp = 0.0;
$deg = 0.0;
$data = HTS221_read8( STATUS_REG);
if ($data & TEMPERATURE_READY)
{
$data= HTS221_read8( TEMP_H_REG);
$t_out = $data << 8; // MSB
$data = HTS221_read8( TEMP_L_REG);
$t_out |= $data; // LSB
$t_out = twobyte2singedint($t_out);
// Decode Temperature
$deg = (float)($T1_degC - $T0_degC);
// Calculate Temperature in decimal of grade centigrades i.e. 15.0 = 150.
$t_temp = ($t_out - $T0_OUT) * $deg / ($T1_OUT - $T0_OUT);
$temperature = $t_temp + $T0_degC; // provide signed celsius measurement unit
// remove x8 multiple
$temperature /= 8;
}
else
$temperature = false;
return $temperature;
}
function HTS221_read_humidity()
{
global $h0_rH;
global $h1_rH;
global $T0_degC;
global $T1_degC;
global $H0_T0;
global $H1_T0;
global $T0_OUT;
global $T1_OUT;
$data = 0;
$h_out = 0;
$h_temp = 0.0;
$hum = 0.0;
$data = HTS221_read8( STATUS_REG);
if ($data & HUMIDITY_READY)
{
$data = HTS221_read8( HUMIDITY_H_REG);
$h_out = $data << 8; // MSB
$data = HTS221_read8( HUMIDITY_L_REG);
$h_out |= $data; // LSB
$h_out = twobyte2singedint($h_out);
// Decode Humidity
$hum = (($h1_rH) - ($h0_rH))/2.0; // remove x2 multiple
// Calculate humidity in decimal of grade centigrades i.e. 15.0 = 150.
$h_temp = (($h_out - $H0_T0) * $hum) / ($H1_T0 - $H0_T0);
$hum = ($h0_rH) / 2.0; // remove x2 multiple
$humidity = (($hum + $h_temp)); // provide signed % measurement unit
}
else
$humidity = false;
return $humidity;
}
?>
Open web browser, access to your channel (https://thingspeak.com/channels/YOURID and see result.
For my case, I put the sensor to fridge for some minutes.
Result
you can see result in demo part.
If it does not work, please try with include_once "/lib/sn_http_b1.php";