Things used in this project

Hardware components:
Phpoc blue per 100x1000 euk22wtv9i
PHPoC Blue
We can use PHPoC black instead
×1
Grove - HDC1000 Temperature&Humidity Sensor
Optional
×1
Grove TH02 Temperature & Humidity Sensor
Optional
×1
mikroBUS - HTS221 temp & humi Click
Optional
×1
Grove board cpdgvu5jko
PHPoC Grove Expansion Board
Optional if using Grove sensor
×1
Mikrobus board pfuubo0pro
PHPoC mikroBUS Expansion Board
Optional if using MikroBUS sensor
×1
Software apps and online services:
Hackster
ThingSpeak API

Schematics

Connection
Just stack and connect it (Grove sensor to grove expansion board - I2C Grove Interface. Mikro sensor to Mikro to MikroBUS expansion Boar - any mikroBUS interface)
Things bmwjd2hwjy

Code

Main task (task0.php)PHP
This program is run in infinite loop to read and send temperature and humidity to ThingSpeak
<?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);
    
}
 
?>
ThingSpeak Library for PHPoC (vn_thingspeak.php)PHP
This is ThingSpeak library for PHPoC ()
<?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;
}

?>
TH02 Library (vd_th02.php)PHP
TH02 Sensor Library
<?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;
}

?>
HDC1000 Library (vd_hdc1000.php)PHP
HDC1000 Sensor Library
<?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;
}

?>
HTS221 Library (vd_hts221.php)PHP
HTS221 Sensor Library
<?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;
}

?>

Credits

On uvdqjvxt6b
phpoc_man
3 projects • 81 followers
Contact

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Sign up / LoginProjectsPlatformsTopicsContestsLiveAppsBetaBlog