Elisabeth Levert
Published © GPL3+

Connected Weight Scale Using Sigfox

This was a quick school project at Polytech Sorbonne on a connected weight scale for medical purposes with Sigfox.

BeginnerWork in progress7,256
Connected Weight Scale Using Sigfox

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
SparkFun Load Cell Amp HX711
×1
RGB Backlight LCD - 16x2
Adafruit RGB Backlight LCD - 16x2
×1
Base Shield V2
Seeed Studio Base Shield V2
×1
Breadboard (generic)
Breadboard (generic)
×1
Load cell straight bar 50kg
×4
Raspberry Pi 3 Model B
Raspberry Pi 3 Model B
×1
Sigfox BREAKOUT BOARD BRKWS01
×1

Software apps and online services

BlueMix
IBM BlueMix
Sigfox
Sigfox

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Code

Arduino_scale

Arduino
This is the sketch for the whole scale. It gets the value and sends it to Sigfox.
/*
 * Connected scale
 * Author : Elisabeth Levert
 * Date 05.02.2018
 * 
 * Code made from different sources :
 *  1/ Scale (calibration, readings)
 *    Example using the SparkFun HX711 breakout board with a scale
 *    By: Nathan Seidle
 *    SparkFun Electronics
 *    Date: November 19th, 2014
 *    License: This code is public domain
 * 
 *  2/ LCD
 *    2013 Copyright (c) Seeed Technology Inc.  All right reserved.  
 *    Author:Loovee 
 *    2013-9-18
 *    
 *    Grove - Serial LCD RGB Backlight demo.
 *    
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License as published by the Free Software Foundation; either
 *    version 2.1 of the License, or (at your option) any later version.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *  
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *    
 *    3/ Sleep - Wake Up : Watchdog timer
 *    
 */

#include "HX711.h"
#include <Wire.h>
#include "rgb_lcd.h"
#include <SoftwareSerial.h>

#define DAT 3
#define CLK 2

#define rxPin 6
#define txPin 7

SoftwareSerial Sigfox(rxPin, txPin);
String tmp;
uint8_t msg[12];
#define DEBUG 1


rgb_lcd lcd;

const int colorR = 0;
const int colorG = 0;
const int colorB = 100;

HX711 scale(DAT, CLK);
float calibration_factor = 11520; 
long zero_factor = 54898;
float weight_old;
float weight_current;
int counter = 0;
float toSend = 0;
bool dataSent = false;

void setup() {

  ///////////
  // TEST
  Serial.begin(9600);
  ///////////



  ////////////
  // SIGFOX
 Sigfox.begin(9600);
  Serial.println("Sigfox initializing");
  delay(100);
  getID();
  delay(100);
  getPAC();
  ///////////  
  
  // set up the LCD's number of columns and rows:
  lcd.begin(16, 2);
  lcd.setRGB(colorR, colorG, colorB);
  // Print a message to the LCD.
  lcd.setCursor(4, 0);
  lcd.print("Bonjour");
  
  scale.set_scale(calibration_factor); //Adjust to this calibration factor
  scale.tare(); //Reset the scale to 0

  zero_factor = scale.read_average(); //Get a baseline reading
}

void sleepNow(){
  clearLCD();
  lcd.setCursor(3, 0);
  lcd.print("Au revoir");
  delay(2000);
  lcd.noDisplay();
}

void clearLCD(){
  lcd.home();
  lcd.print("                       ");
  lcd.home();
}



//////////////

//SIGFOX FUNCTIONS 

///////////////

//Get Sigfox ID
String getID(){
  String id = "";
  char output;

  Sigfox.println("AT$I=10\r");

  while(!Sigfox.available()){
  }

  while(Sigfox.available()){
    output = Sigfox.read();
    id += output;
    delay(10);
  }

    Serial.println("Sigfox Device ID: ");
    Serial.println(id);

  return id;
}


//Get PAC number
String getPAC(){
  String pac = "";
  char output;

  Sigfox.print("AT$I=11\r");
  while (!Sigfox.available()){
  }


  while(Sigfox.available()){
    output = Sigfox.read();
    pac += output;
    delay(10);
  }

    Serial.println("PAC number: ");
    Serial.println(pac);

  return pac;
}


//Send Sigfox Message
void sendMessage(uint8_t msg[], int size){

  String status = "";
  char output;

  Sigfox.print("AT$SF=");
 
  for(int i=0;i<size;i++){
    Sigfox.print(msg[i]);
    if(DEBUG){
      Serial.print("Byte:");
      Serial.println(msg[i]);
    }
  }
  
  Sigfox.print("\r");

  while (!Sigfox.available()){
  }
  while(Sigfox.available()){
    output = Sigfox.read();
    status += output;
    delay(10);
  }
  if(DEBUG){
    Serial.println();
    Serial.print("Status \t");
    Serial.println(status);
  }
}




void loop(){
//weighing

  //set screen
  clearLCD();
  lcd.setCursor(4, 0);
  lcd.print("Allez-y");
  lcd.setCursor(10, 1);
  lcd.print("kg");
    
  //start measures 
    weight_old = weight_current;
    weight_current = scale.get_units();
    lcd.setCursor(4, 1);
    lcd.print(weight_current);

    
    ///////////
    // TEST
    Serial.print(weight_current);
    Serial.println(" kg");
    ///////////

  
    if(abs((int)weight_current) == abs((int)weight_old))
      counter++;
    else
      counter = 0;

    ///////////
    // TEST
    Serial.print(counter);
    Serial.println(" counts");
    ///////////

    if(counter > 4){
      //no one on it (around 0 for a certain time)
      if(weight_current < 1){
          if(counter>20){
          sleepNow();
          Serial.println("No one on it");
        }
      }
      //stabilized weight => toSend
      else{
        if(!dataSent){
          toSend = weight_current;
          dataSent = true;
          Serial.println("Sending data");
          clearLCD();
          lcd.print("Donnee recoltee");
          lcd.setCursor(4, 1);
          lcd.print(toSend);
          lcd.setCursor(10, 1);
          lcd.print("kg"); 
          delay(5000);
          tmp = String(toSend);
          tmp.getBytes(msg, tmp.length());
          sendMessage(msg, tmp.length()-1);
          //sendMessage(tmp, tmp.length());
          Serial.println("msg sent");
        } else{
          Serial.println("Someone still on it");
        } 
      }
    }
    
    delay(300);
}

style.css

CSS
body {
	font-family: "Times New Roman", Times, serif;
	margin: 0;
}

#background {
	background: url(../images/bg_login.jpg) top;
}

#header {
	display: flex;
	flex-direction: row;
	justify-content: center;
	width: 1000px;
	height: 1000px;
	padding-top: 10%;
	margin: auto;
}

#login
{
	display: flex;
	flex-direction: column;
}

#header_content
{
	display: flex;
	flex-direction: column;
	width: 1000px;
	padding-top: 1%;
	padding-left: 1%;
}

#bandeau
{
	display: flex;
	flex-direction: row;
}

.log
{
	font-size: 24px;
}

DBconnect.php

PHP
<?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");


$user = "root";
$passwd = "medisures";
$host = "localhost";
$bdd = "mesures";

$conn = new mysqli($host, $user, $passwd,$bdd);

$result = $conn->query("SELECT poids  FROM mesures ORDER BY date ASC");

$outp ="";
$outp .= '{"cols":[{"id":"1","label":"Time","type":"string"}';

$outp .= ',{"id":"2","label":"Poids","type":"number"},],"rows": [';

while($rs = $result->fetch_array(MYSQLI_ASSOC)) {
			if ($rs["poids"] == "")
					break;
			
			if ($data != "") {$data .= ",";}
			$data .= '{"c":[{"v":"'. $rs["date"] . '"}';
			$data .= ',{"v":'. $rs["poids"]. ',"f": '. $rs["poids"] .'}]}';
		}
		
		
$outp .= $data . ']}';

$conn->close();

echo($outp);
?>

patient.php

PHP
 <?php
 session_start();
?>

<!DOCTYPE html>
<!-- Website template by freewebsitetemplates.com -->
<html>
<head>
	<meta charset="UTF-8">
	<title>Home</title>
	<link rel="stylesheet" href="css/style.css" type="text/css">
	<script src="plotly-latest.min.js"></script>
	
	<script type="text/javascript">
      google.charts.load('current', {packages: ['corechart', 'line']});
	//google.charts.setOnLoadCallback(drawRegionsMap);
	  
      function drawRegionsMap(){
	  
		
		//param = "Average Temperature";
		//var div = document.getElementById("divData");
		//var chara = document.getElementById("select"+id).value;
		//var time = document.getElementById("time"+id).value;
		//var point = document.getElementById("Point"+id).value;
		//var type = document.getElementById("Type"+id).value;
		
		var jsonData = $.ajax({
          url: "DBconnect.php",
          dataType: "json",
		  //data : "chara=" + chara +"&time="+ time,
          async: false
          }).responseText;
		//document.write(jsonData);
		
		var data = new google.visualization.DataTable(jsonData);
		

       var options = {
        hAxis: {
          title: ' '
        },
        vAxis: {
          title: ' '
        }
		};

		/*switch(type){
			case 'Line':
				var chart = new google.visualization.LineChart(document.getElementById("regions_div"+id));
				break;
			case 'Column':
				var chart = new google.visualization.ColumnChart(document.getElementById("regions_div"+id));
				break;
			case 'Histogram':
				var chart = new google.visualization.Histogram(document.getElementById("regions_div"+id));
				break;
			case 'Scatter':
				var chart = new google.visualization.ScatterChart(document.getElementById("regions_div"+id));
				break;
			
		}*/
		
		var chart = new google.visualization.LineChart(document.getElementById("regions_div"));
        //var chart = new google.visualization.LineChart(document.getElementById("regions_div"+id));

      chart.draw(data, options);
	  //setTimeout("drawRegionsMap()",1000);
      }
	  
	  function refresh()
	  {
		  /*for(var i =1; i<nbDiv+1; i++)
		  {
			div = document.getElementById("div"+i);
			if(div.innerHTML !== "")
			  drawRegionsMap(i);
		  } */
			drawRegionMap();
	  }
	  setInterval(refresh, 1000);
    </script>
	
	
	
</head>
<body>
	<div id="background">
		<div id="page">
			<div id="header_content">
				<div id="bandeau">
					<div id="logo_content">
						<a  href="index.php" ><img src="images/Medisure.jpg" alt="LOGO" height="160" width="200"></a>
					</div>

					<div class="log">
						<?php if( empty($_SESSION['Type']) or empty($_SESSION['Log/Pass'])){	// no connected
							header('Location: login_disconnect.php');
						}else{
							?>
							<form action="login_disconnect.php" method="post">
								<div id="EnterButton">
									<input type="submit" value="Disconnect" />
								</div>
								<div id="LoginAndPass">
									Bonjour <?php echo $_SESSION['First_Name'] ?> <?php echo $_SESSION['Last_Name'] ?>
								</div>
							</form>
							<?php 
						}	
						?>
					</div>
				</div>
				
			</div>
			<!--
			<div id="graphe"></div>
				<script>
					function trace(x_new, y_new, type) {
						this.x = new Array(x_new);
						this.y = new Array(y_new);
						this.type = type;
					}
				</script>
			
			  <script>
				
				var trace1 = new trace("2", "3", 'scatter');
				trace1.x.push("3");
				trace1.y.push("2");
				var data = [trace1];
				Plotly.newPlot('graphe', data);
			  </script>
			  -->
			  <div id="regions_div'+nbDiv+'" ></div>
			
		</div>
	</div>
</body>
</html>

Forgotpass.php

PHP
 <?php
 session_start();
?>

<!DOCTYPE html>
<!-- Website template by freewebsitetemplates.com -->
<html>
<head>
	<meta charset="UTF-8">
	<title>Home</title>
	<link rel="stylesheet" href="css/style.css" type="text/css">
</head>
<body>
	<div id="background">
		<div id="page">
			<div id="header">
				<div id="logo">
					<a  href="login.php" ><img src="images/Medisure.jpg" alt="Medisure" height="160" width="200"></a>
				</div>
				
				<div class="body">
					<ul id="div_line">
						<h1>Forgot password</h1>
						<p>Send new password by email :</p>
						<form action="SendEmail.php" method="post" style="text-align:center;">
							Email : <input type="text" rows="5" size="35" maxlength="100" name="mail"/>
							<input type="submit" value="Send" />
						</form>
					</ul>
				</div>
		</div>
	</div>
</body>
</html>

login.php

PHP
 <?php
 session_start();
?>

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>LogIn</title>
	<link rel="stylesheet" href="css/style.css" type="text/css">
</head>
<body>
	<div id="background">
		<div id="page">
			<div id="header">
				<div id="logo">
					<a  href="index.php" ><img src="images/Medisure.jpg" alt="LOGO" height="160" width="200"></a>
				</div>

				<?php if(empty($_SESSION['Type'])){	// no connect // First time on WebSite
						if(empty($_SESSION['Log/Pass'])){
						?>
								<table>
									<tr>
										<form action="login_connect.php" method="post">
											<td style="color: #FFFFFF;">Login : <input type="text" rows="5" size="12" maxlength="100" name="Login"></td>
											<td style="color: #FFFFFF;">Password : <input type="password" rows="5" size="12" maxlength="100" name="Password"></td>
											<td><input type="submit" value="Sign in" /></td>
										</form>
									</tr>
									<tr>
										<form action="Forgotpass.php">
											<td><input type="submit" value="Forgot password ?" /></a></td>
										</form>
									</tr>
								</table>

						<?php }else{
							?>
								<table style="float:right;margin-right: 50px;">
									<tr>
										<form action="login_connect.php" method="post">
											<td style="color: #FFFFFF;">Login : <input type="text" rows="5" size="12" maxlength="100" name="Login"></td>
											<td style="color: #FFFFFF;">Password : <input type="password" rows="5" size="12" maxlength="100" name="Password"></td>
											<td><input type="submit" value="Sign in" /></td>
										</form>
									</tr>
									<tr>
										<form action="Forgotpass.php">
											<td><td style="color: #FFFFFF;">Wrong combination Login/Password !</td></td>
											<td><input type="submit" value="Forgot password ?" /></a></td>
										</form>
									</tr>
								</table>
							
							<?php
						}
					?>
					
					<?php
				}else{
					?>
					<form action="login_disconnect.php" method="post">
						<div id="EnterButton">
							<input type="submit" value="Disconnect" />
						</div>
						<div id="LoginAndPass">
							Hello <?php echo $_SESSION['First_Name'] ?> <?php echo $_SESSION['Last_Name'] ?> <?php echo $_SESSION['Type'] ?>
						</div>
					</form> <?php
					switch($_SESSION['Type']) {
						case 1: header('Location: patient.php'); break;
						case 2: header('Location: medecin.php'); break;
						default: header('Location: unknown_user_type.php'); break;
					}
				}	
				?>				

			
		</div>
	</div>
</body>
</html>

login_connect.php

PHP
<?php

		try
        {
           $bdd = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'root', '');
        }
        catch(Exception $e)
        {
            die('Erreur : '.$e->getMessage());
        }

            $reponse = $bdd->query('SELECT * FROM users WHERE login=\'' . $_POST['Login'] . '\' AND password =\'' . $_POST['Password'] .'\'');

          if($donnees = $reponse->fetch()){
              ?>
                <div> Hello <?php echo $donnees['prenom']; ?> <?php echo $donnees['nom']; ?> <?php echo $donnees['login']; ?> </div>

               <?php
                session_start();
                $_SESSION['Login'] = $donnees['login'];
                $_SESSION['Password'] = $donnees['pwd'];
                $_SESSION['First_Name'] = $donnees['prenom'];
                $_SESSION['Last_Name'] = $donnees['nom'];
                $_SESSION['Type'] = $donnees['type'];
                $_SESSION['Log/Pass'] = "true"; 
              
				        header('Location: login.php');
      			    exit();


            }else{
                session_start();
                $_SESSION['Log/Pass'] = "false";    
                header('Location: login.php');         
              
            }

            $reponse->closeCursor(); // finish request
          
 ?>
 
 

login_disconnect.php

PHP
 <?php

 		  	session_start();
 		  	$_SESSION = array();
  			// Destruction de la session
 			 session_destroy();
  			// Destruction du tableau de session
  			unset($_SESSION);
			header('Location: login.php');
      		exit();

?>

new_line2.php

PHP
<?php // content="text/plain; charset=utf-8"
	require_once ('jpgraph/jpgraph.php');
	require_once ('jpgraph/jpgraph_line.php');

	$datay1 = array(20,7,16,46);
	$datay2 = array(6,20,10,22);

	// Setup the graph
	$graph = new Graph(350,230);
	$graph->SetScale("textlin");

	$theme_class= new UniversalTheme;
	$graph->SetTheme($theme_class);

	$graph->title->Set('Background Image');
	$graph->SetBox(false);

	$graph->yaxis->HideZeroLabel();
	$graph->yaxis->HideLine(false);
	$graph->yaxis->HideTicks(false,false);

	$graph->xaxis->SetTickLabels(array('A','B','C','D'));
	$graph->ygrid->SetFill(false);
	$graph->SetBackgroundImage("tiger_bkg.png",BGIMG_FILLFRAME);

	$p1 = new LinePlot($datay1);
	$graph->Add($p1);

	$p2 = new LinePlot($datay2);
	$graph->Add($p2);

	$p1->SetColor("#55bbdd");
	$p1->SetLegend('Line 1');
	$p1->mark->SetType(MARK_FILLEDCIRCLE,'',1.0);
	$p1->mark->SetColor('#55bbdd');
	$p1->mark->SetFillColor('#55bbdd');
	$p1->SetCenter();

	$p2->SetColor("#aaaaaa");
	$p2->SetLegend('Line 2');
	$p2->mark->SetType(MARK_UTRIANGLE,'',1.0);
	$p2->mark->SetColor('#aaaaaa');
	$p2->mark->SetFillColor('#aaaaaa');
	$p2->value->SetMargin(14);
	$p2->SetCenter();

	$graph->legend->SetFrameWeight(1);
	$graph->legend->SetColor('#4E4E4E','#00A78A');
	$graph->legend->SetMarkAbsSize(8);


	// Output line
	$graph->Stroke();

?>

SendEmail.php

PHP
<?php
function randomPassword() {
    $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
    $pass = array(); 
    $alphaLength = strlen($alphabet) - 1; 
    for ($i = 0; $i < 8; $i++) {
        $n = rand(0, $alphaLength);
        $pass[] = $alphabet[$n];
    }
    return implode($pass); 
}

if($_POST['mail'] !== ""){
	
	$bdd = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'root', '');
	
			$reponse = $bdd->prepare('SELECT * FROM users WHERE mail= ? ');
            $reponse->execute(array($_POST['mail']));
	
	if($donnees = $reponse->fetch()){
		
		$reponse->closeCursor(); // finish request
		$pass = randomPassword();
		 
		$user = "root";
		$passwd = "";
		$host = "localhost";
		$bdd = "testdb";

		$conn = new mysqli($host, $user, $passwd, $bdd);
		
		$search = $conn->query("UPDATE users SET password = '".$pass."' WHERE mail = '".$_POST['mail']."'");
	 
	 $to      = $_POST['mail'];
     $subject = 'Password';
     $message = 'New password : '. $pass;
     $headers = 'From: Medisures.mail@gmail.com';

	$mailok = mail($to,$subject , $message ,$headers );

	if ($mailok == TRUE)
		 header('Location: login.php');
	else 
		 echo "error";
	}else{
	 $reponse->closeCursor(); // finish request
	 header('Location: login.php');
	}
}
header('Location: Forgotpass.php');
?>

Credits

Polytech Sorbonne - EISE5 - Levert, Maury, Rosanne

Comments