The Smart Water Dispenser
- Nipun Kanade
Just Another ThoughtWorker
This
Is an internet connected water dispenser, which can identify you from your id card, measure the amount of water you draw from it and posts it to a server
Yo !! I'm all ears...
So how do we build it ?
void setup() {
// initialize digital pin 13 as an output.
pinMode(13, OUTPUT);
}
// the loop function runs over and over again forever
void loop() {
digitalWrite(13, HIGH); // turn the LED on (HIGH is the voltage level)
delay(1000); // wait for a second
digitalWrite(13, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
}
/*
* HID RFID Reader Wiegand Interface for Arduino Uno
* Written by Daniel Smith, 2012.01.30
* www.pagemac.com
*
* This program will decode the wiegand data from a HID RFID Reader (or, theoretically,
* any other device that outputs weigand data).
* The Wiegand interface has two data lines, DATA0 and DATA1. These lines are normall held
* high at 5V. When a 0 is sent, DATA0 drops to 0V for a few us. When a 1 is sent, DATA1 drops
* to 0V for a few us. There is usually a few ms between the pulses.
*
* Your reader should have at least 4 connections (some readers have more). Connect the Red wire
* to 5V. Connect the black to ground. Connect the green wire (DATA0) to Digital Pin 2 (INT0).
* Connect the white wire (DATA1) to Digital Pin 3 (INT1). That's it!
*
* Operation is simple - each of the data lines are connected to hardware interrupt lines. When
* one drops low, an interrupt routine is called and some bits are flipped. After some time of
* of not receiving any bits, the Arduino will decode the data. I've only added the 26 bit and
* 35 bit formats, but you can easily add more.
*/
#define MAX_BITS 100 // max number of bits
#define WEIGAND_WAIT_TIME 3000 // time to wait for another weigand pulse.
unsigned char databits[MAX_BITS]; // stores all of the data bits
unsigned char bitCount; // number of bits currently captured
unsigned char flagDone; // goes low when data is currently being captured
unsigned int weigand_counter; // countdown until we assume there are no more bits
unsigned long facilityCode=0; // decoded facility code
unsigned long cardCode=0; // decoded card code
// interrupt that happens when INTO goes low (0 bit)
void ISR_INT0()
{
//Serial.print("0"); // uncomment this line to display raw binary
bitCount++;
flagDone = 0;
weigand_counter = WEIGAND_WAIT_TIME;
}
// interrupt that happens when INT1 goes low (1 bit)
void ISR_INT1()
{
//Serial.print("1"); // uncomment this line to display raw binary
databits[bitCount] = 1;
bitCount++;
flagDone = 0;
weigand_counter = WEIGAND_WAIT_TIME;
}
void setup()
{
pinMode(13, OUTPUT); // LED
pinMode(2, INPUT); // DATA0 (INT0)
pinMode(3, INPUT); // DATA1 (INT1)
Serial.begin(9600);
Serial.println("RFID Readers");
// binds the ISR functions to the falling edge of INTO and INT1
attachInterrupt(0, ISR_INT0, FALLING);
attachInterrupt(1, ISR_INT1, FALLING);
weigand_counter = WEIGAND_WAIT_TIME;
}
void loop()
{
// This waits to make sure that there have been no more data pulses before processing data
if (!flagDone) {
if (--weigand_counter == 0)
flagDone = 1;
}
// if we have bits and we the weigand counter went out
if (bitCount > 0 && flagDone) {
unsigned char i;
Serial.print("Read ");
Serial.print(bitCount);
Serial.print(" bits. ");
// we will decode the bits differently depending on how many bits we have
// see www.pagemac.com/azure/data_formats.php for mor info
if (bitCount == 35)
{
// 35 bit HID Corporate 1000 format
// facility code = bits 2 to 14
for (i=2; i<14; i++)
{
facilityCode <<=1;
facilityCode |= databits[i];
}
// card code = bits 15 to 34
for (i=14; i<34; i++)
{
cardCode <<=1;
cardCode |= databits[i];
}
printBits();
}
else if (bitCount == 26)
{
// standard 26 bit format
// facility code = bits 2 to 9
for (i=1; i<9; i++)
{
facilityCode <<=1;
facilityCode |= databits[i];
}
// card code = bits 10 to 23
for (i=9; i<25; i++)
{
cardCode <<=1;
cardCode |= databits[i];
}
printBits();
}
else {
// you can add other formats if you want!
Serial.println("Unable to decode.");
}
// cleanup and get ready for the next card
bitCount = 0;
facilityCode = 0;
cardCode = 0;
for (i=0; i<MAX_BITS; i++)
{
databits[i] = 0;
}
}
}
void printBits()
{
// I really hope you can figure out what this function does
Serial.print("FC = ");
Serial.print(facilityCode);
Serial.print(", CC = ");
Serial.println(cardCode);
}
Let's See how can we monitor amount of water dispensed
//example request : http://10.132.127.212:3000/order?type=juice&deviceID=123&userID=18427
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <SoftwareSerial.h>
SoftwareSerial arduino(D5, D7, false, 256);
#define buzzer D6
#define red D4
#define green D3
#define blue D2
ESP8266WiFiMulti WiFiMulti;
HTTPClient http;
String url;
String payload;
void setup() {
pinMode(red, OUTPUT);
pinMode(blue, OUTPUT);
pinMode(green, OUTPUT);
pinMode(buzzer, OUTPUT);
digitalWrite(red, LOW);
digitalWrite(green, HIGH);
digitalWrite(blue, HIGH);
digitalWrite(buzzer, LOW);
Serial.begin(9600);
arduino.begin(9600);
Serial.println();
Serial.println();
Serial.println();
for(uint8_t t = 4; t > 0; t--) {
Serial.printf("[SETUP] WAIT %d...\n", t);
Serial.flush();
delay(1000);
}
WiFiMulti.addAP("SSID", "PASSWORD");
}
void buzz(int delayTime){
digitalWrite(buzzer, HIGH);
delay(delayTime);
digitalWrite(buzzer, LOW);
}
void buzzInt(int delayTime, int repeat, int stopDelay){
while(repeat>0){
buzz(delayTime);
delay(stopDelay);
repeat--;
}
}
void loop() {
digitalWrite(red, LOW);
digitalWrite(blue, HIGH);
digitalWrite(green,HIGH);
if((WiFiMulti.run() == WL_CONNECTED)) {
digitalWrite(red, HIGH);
digitalWrite(red, HIGH);
digitalWrite(blue, LOW);
delay(500);
if(Serial.available() > 0) {
url = Serial.readStringUntil('\n');
String toBeSentURl = url.substring(0, url.length()-1);
Serial.print("Got : ");
Serial.println(toBeSentURl);
Serial.print("[HTTP] begin...\n");
http.begin(toBeSentURl); //HTTP
Serial.print("[HTTP] GET...\n");
int httpCode = http.GET();
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
if(httpCode > 0) {
if(httpCode == HTTP_CODE_OK) {
String payload = http.getString();
Serial.println(payload);
digitalWrite(blue, LOW);
digitalWrite(green, LOW);
digitalWrite(red, LOW);
delay(300);
buzzInt(100,3,100);
}
else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
digitalWrite(blue, LOW);
digitalWrite(green, HIGH);
digitalWrite(red, LOW);
buzz(1500);
}
}
http.end();
}
digitalWrite(red, HIGH);
digitalWrite(blue, LOW);
digitalWrite(green,HIGH);
Serial.flush();
}
}
Backend / Frontend
Text
Text
Connections
#include <CapacitiveSensor.h>
String url="http://10.134.124.214:8083/api/waterdispenser/consumption/new/internalNumber/";
int buttonState = 0;
long startMillis = 0;
long stopMillis = 0;
long timeCount = 0;
long volume = 0;
unsigned int cardLed = 10;
unsigned int dispenserLed = 9;
unsigned int sensor = 8;
unsigned int capacitorPin = 2;
unsigned int resistorPin = 4;
#define MAX_BITS 100 // max number of bits
#define WEIGAND_WAIT_TIME 3000 // time to wait for another weigand pulse.
unsigned char databits[MAX_BITS]; // stores all of the data bits
unsigned char bitCount; // number of bits currently captured
unsigned char flagDone; // goes low when data is currently being captured
unsigned int weigand_counter; // countdown until we assume there are no more bits
unsigned long facilityCode=0; // decoded facility code
unsigned long cardCode=0; // decoded card code
CapacitiveSensor cs_4_5 = CapacitiveSensor(4,5);
void ISR_INT0()
{
bitCount++;
flagDone = 0;
weigand_counter = WEIGAND_WAIT_TIME;
}
void ISR_INT1()
{
databits[bitCount] = 1;
bitCount++;
flagDone = 0;
weigand_counter = WEIGAND_WAIT_TIME;
}
void setup()
{
pinMode(2, INPUT); // DATA0 (INT0)
pinMode(3, INPUT); // DATA1 (INT1)
pinMode(sensor, INPUT);
pinMode(cardLed, OUTPUT);
pinMode(dispenserLed, OUTPUT);
cs_4_5.set_CS_AutocaL_Millis(0xFFFFFFFF);
Serial.begin(9600);
digitalWrite(cardLed, LOW);
digitalWrite(dispenserLed, LOW);
digitalWrite(4, HIGH);
attachInterrupt(0, ISR_INT0, FALLING);
attachInterrupt(1, ISR_INT1, FALLING);
weigand_counter = WEIGAND_WAIT_TIME;
}
void loop()
{
// This waits to make sure that there have been no more data pulses before processing data
if (!flagDone) {
if (--weigand_counter == 0)
flagDone = 1;
}
// if we have bits and we the weigand counter went out
if (bitCount > 0 && flagDone) {
unsigned char i;
if (bitCount == 35)
{
for (i=2; i<14; i++)
{
facilityCode <<=1;
facilityCode |= databits[i];
}
for (i=14; i<34; i++)
{
cardCode <<=1;
cardCode |= databits[i];
}
printBits();
}
else if (bitCount == 26)
{
for (i=1; i<9; i++)
{
facilityCode <<=1;
facilityCode |= databits[i];
}
for (i=9; i<25; i++)
{
cardCode <<=1;
cardCode |= databits[i];
}
printBits();
}
// cleanup and get ready for the next card
bitCount = 0;
facilityCode = 0;
cardCode = 0;
for (i=0; i<MAX_BITS; i++)
{
databits[i] = 0;
}
}
}
void printBits()
{
digitalWrite(cardLed, HIGH);
int getVolume = getvol();
if(getVolume > 20){
url.concat(cardCode);
url.concat("/consumption/");
String vol = String(getVolume);
url.concat(String(vol));
Serial.println(url);
url="http://10.134.124.214:8083/api/waterdispenser/consumption/new/internalNumber/";
}
digitalWrite(cardLed, LOW);
}
int getvol(){
startMillis = 0;
stopMillis = 0;
timeCount = 0;
buttonState = digitalRead(sensor);
digitalWrite(dispenserLed, LOW);
long capSense = cs_4_5.capacitiveSensor(30);
Serial.println("capsense" + capSense);
while(capSense < 100 ){
capSense = cs_4_5.capacitiveSensor(30);
if(capSense > 100){
delay(500);
capSense = cs_4_5.capacitiveSensor(30);
}
}
startMillis = millis();
digitalWrite(dispenserLed, HIGH);
while(capSense > 100){
capSense = cs_4_5.capacitiveSensor(30);
}
stopMillis = millis();
digitalWrite(dispenserLed, LOW);
timeCount = (stopMillis - startMillis) / 1000;
volume = map(timeCount, 0, 99, 0, 3000);
digitalWrite(sensor, HIGH);
return volume;
}
twitter : @kanadenipun