Hackster is hosting Hackster Holidays, Finale: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Tuesday!Stream Hackster Holidays, Finale on Tuesday!
gusgonnet
Published © CC BY-NC-SA

Blynk Meets Bluz

No Blynk libraries for Bluz? No problem!

AdvancedFull instructions provided24 hours2,783
Blynk Meets Bluz

Things used in this project

Hardware components

Bluz DK
Bluz DK
×1
Photon
Particle Photon
this one goes in the gateway shield (BLE to WiFi gateway)
×1
gateway shield
×1

Software apps and online services

Blynk
Blynk

Story

Read more

Schematics

The Bluz wireless temperature sensor

Code

Bluz DK code

Arduino
//**************************************************************************************
// Author: Gustavo Gonnet
// Contact: gusgonnet@gmail.com
// Projects: https://www.hackster.io/gusgonnet/
//
// Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
// This is a human-readable summary of (and not a substitute for) the license.
// Disclaimer
//
// You are free to:
// Share — copy and redistribute the material in any medium or format
// Adapt — remix, transform, and build upon the material
// The licensor cannot revoke these freedoms as long as you follow the license terms.
//
// Under the following terms:
// Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
// NonCommercial — You may not use the material for commercial purposes.
// ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
// No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
//
// Notices:
// You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation.
// No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material.
//
// Free for personal use.
//
// https://creativecommons.org/licenses/by-nc-sa/4.0/

//**************************************************************************************
// Notes:
// when I started this app with a cheap cr 2032 battery it lasted one week
//**************************************************************************************
#include <math.h>
#include "application.h"

#define APP_NAME "BLUZ_thermistor"
String VERSION = "Version 0.01";
int version = 1;

#define EVENT_NAME_TEMP "BLUZ_TEMP"
#define EVENT_NAME_BUTTON "BLUZ_BUTTON"

/*******************************************************************************
 * changes in version 0.01:
       * initial commit
*******************************************************************************/

// by default, the temperature will be displayed in degrees celsius,
//  but if you prefer farenheit please set this to true
bool useFahrenheit = false;

// this is the thermistor used
// https://www.adafruit.com/products/372
// resistance at 25 degrees C
#define THERMISTORNOMINAL 10000
// temp. for nominal resistance (almost always 25 C)
#define TEMPERATURENOMINAL 25
// how many samples to take and average, more takes longer
// but is more 'smooth'
#define NUMSAMPLES 5
// The beta coefficient of the thermistor (usually 3000-4000)
#define BCOEFFICIENT 3950
// the value of the 'other' resistor
#define SERIESRESISTOR 10000

// A7 is not available in bluz!
// source: http://docs.bluz.io/hardware/dk/
// A6 and A7 cannot read analog data even though they are still labeled A6 and A7 (which was done for compatible code). There simple weren't enough ADC pins on the nrf51.
int THERMISTOR = A5;
// this gives power to the thermistor
int VCC_FOR_THERMISTOR = A0;

int LED = D7;

// this variable helps you match the measurement to another source (eg: your thermostat)
// hum, this value is pretty high, I guess is a consecuence of me not using a 1% 10k resistor
// but a less precise 10k resistor
float temperatureCorrection = -5.9;

// store the previous measured temp to check if current measurement needs to be transmited
float previousTemperature;

float currentTemperature;

unsigned long lastTime = 0;

// polling period: 20 mins == 1200000
// adjust to your liking
unsigned long checkPeriod = 10000;

// this variable defines the range where the temp is not updated (not published)
// adjust to your liking
float deltaTemperature = 0.5;

/*******************************************************************************
 * Function Name  : setup
 * Description    : this function runs once at system boot
 *******************************************************************************/
void setup()
{
  pinMode(LED, OUTPUT);
  pinMode(VCC_FOR_THERMISTOR, OUTPUT);
  digitalWrite(VCC_FOR_THERMISTOR, LOW);
  pinMode(THERMISTOR, INPUT);

  Particle.publish(APP_NAME, VERSION, PRIVATE);

  // turn off led to save power
  // comment these two lines below while regular development
  //   RGB.control(true);
  //   RGB.color(0, 0, 0);

  Particle.subscribe(EVENT_NAME_BUTTON, hitButton, MY_DEVICES);

  Particle.function("getTemp", getTemperature);
  Particle.function("getVersion", getVersion);
  Particle.function("pulseLed", pulseLed);
}

/*******************************************************************************
 * Function Name  : loop
 * Description    : this function runs all the time
 *******************************************************************************/
void loop()
{

  System.sleep(SLEEP_MODE_CPU);

  // source: https://community.particle.io/t/millis-and-rollover-tutorial/20429
  unsigned long now = millis();

  if ((now - lastTime) >= checkPeriod)
  {
    lastTime = now;

    // power on the thermistor
    digitalWrite(VCC_FOR_THERMISTOR, HIGH);

    calculateTemperature();

    // power off the thermistor
    digitalWrite(VCC_FOR_THERMISTOR, LOW);
  }
}

/*******************************************************************************
 * Function Name  : calculateTemperature
 * Description    : read the value of the thermistor and convert it to degrees
 * Return         : none
 *******************************************************************************/
void calculateTemperature()
{

  // read and convert the value to resistance
  float average = analogRead(THERMISTOR);
  average = (1023 / average) - 1;
  average = SERIESRESISTOR / average;

  float steinhart;
  steinhart = average / THERMISTORNOMINAL;          // (R/Ro)
  steinhart = log(steinhart);                       // ln(R/Ro)
  steinhart /= BCOEFFICIENT;                        // 1/B * ln(R/Ro)
  steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To)
  steinhart = 1.0 / steinhart;                      // Invert
  steinhart -= 273.15;                              // convert to C

  // Convert Celsius to Fahrenheit
  // source: http://playground.arduino.cc/ComponentLib/Thermistor2#TheSimpleCode
  if (useFahrenheit)
  {
    steinhart = (steinhart * 9.0) / 5.0 + 32.0;
  }

  currentTemperature = steinhart + temperatureCorrection;

  //   if (abs(currentTemperature - previousTemperature) > deltaTemperature)
  //   {
  //     Particle.publish(EVENT_NAME_TEMP, float2string(currentTemperature), 60, PRIVATE);
  //   }

  Particle.publish(EVENT_NAME_TEMP, float2string(currentTemperature), 60, PRIVATE);

  // keep track of this value
  previousTemperature = currentTemperature;
}

String float2string(float floatNumber)
{
  String stringNumber = String(floatNumber);

  //return only 2 decimals
  // Example: show 19.00 instead of 19.000000
  stringNumber = stringNumber.substring(0, stringNumber.length() - 4);

  return stringNumber;
}

int getTemperature(String dummy)
{
  return (int)(currentTemperature * 100);
}

int getVersion(String dummy)
{
  return version;
}

/*******************************************************************************
 * Function Name  : pulseLed
 * Description    : light up the led
 * Return         : 0
 *******************************************************************************/
int pulseLed(String args)
{
  digitalWrite(LED, HIGH); // sets the LED on
  delay(500);              // waits a bit
  digitalWrite(LED, LOW);  // sets the LED off
  return 0;
}

void hitButton(const char *event, const char *data)
{
  pulseLed("");
}

Bluz-Blynk Gateway code

Arduino
//**************************************************************************************
// Author: Gustavo Gonnet
// Contact: gusgonnet@gmail.com
// Projects: https://www.hackster.io/gusgonnet/
//
// Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0)
// This is a human-readable summary of (and not a substitute for) the license.
// Disclaimer
//
// You are free to:
// Share — copy and redistribute the material in any medium or format
// Adapt — remix, transform, and build upon the material
// The licensor cannot revoke these freedoms as long as you follow the license terms.
//
// Under the following terms:
// Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
// NonCommercial — You may not use the material for commercial purposes.
// ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
// No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
//
// Notices:
// You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation.
// No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material.
//
// Free for personal use.
//
// https://creativecommons.org/licenses/by-nc-sa/4.0/

#include "bluz_gateway.h"

#include "elapsedMillis.h"
#include "BlynkSimpleParticle.h"
#include "blynkAuthToken.h"

#define EVENT_NAME_TEMP "BLUZ_TEMP"
#define EVENT_NAME_BUTTON "BLUZ_BUTTON"

#define APP_NAME "BLUZ_GW_BLYNK"
String VERSION = "Version 0.01";

/*******************************************************************************
 * changes in version 0.01:
    * initial version
*******************************************************************************/

/*******************************************************************************
 Your blynk token goes in another file to avoid sharing it by mistake
 The file containing your blynk auth token has to be named blynkAuthToken.h and it should 
 contain something like this:
  #define BLYNK_AUTH_TOKEN "1234567890123456789012345678901234567890"
 replace with your project auth token (the blynk app will give you one)
*******************************************************************************/
char auth[] = BLYNK_AUTH_TOKEN;
#define BLYNK_DISPLAY_TEMP V0
#define BLYNK_BUTTON V1

//this defines how often the readings are sent to the blynk cloud (millisecs)
#define BLYNK_STORE_INTERVAL 5000
elapsedMillis blynkStoreInterval;

// SYSTEM_MODE(SEMI_AUTOMATIC);
bluz_gateway gateway;

String remoteTemp = "";

void setup()
{

    gateway.init();
    //only set this if you want the nrf51 central to not connect, recomended for Electron gateway
    // gateway.set_ble_local(true);

    Particle.subscribe(EVENT_NAME_TEMP, getRemoteTemp, MY_DEVICES);

    Particle.variable("remoteTemp", remoteTemp);

    Blynk.begin(auth);

    // Serial.begin(9600);
}

void loop()
{
    gateway.loop();

    //all the Blynk magic happens here
    Blynk.run();

    //publish readings to the blynk server every minute so the History Graph gets updated
    // even when the blynk app is not on (running) in the users phone
    updateBlynkCloud();
}

/*******************************************************************************
 * Function Name  : updateBlynkCloud
 * Description    : publish readings to the blynk server every minute so the
                    History Graph gets updated even when
                    the blynk app is not on (running) in the users phone
 * Return         : none
 *******************************************************************************/
void updateBlynkCloud()
{

    //is it time to store in the blynk cloud? if so, do it
    if (blynkStoreInterval > BLYNK_STORE_INTERVAL)
    {

        //reset timer
        blynkStoreInterval = 0;

        Blynk.virtualWrite(BLYNK_DISPLAY_TEMP, remoteTemp);
    }
}

void getRemoteTemp(const char *event, const char *data)
{
    if (data)
    {
        remoteTemp = data;
    }
}

BLYNK_WRITE(BLYNK_BUTTON)
{
    // do this only when blynk sends a 1
    if (param.asInt() == 1)
    {
        Particle.publish(EVENT_NAME_BUTTON, PRIVATE);
    }
}

Credits

gusgonnet
37 projects • 306 followers
With a decade of Software Engineering experience in IoT, I focus on creating Particle IoT solutions coupled with mobile and web applications

Comments