Hardware components | ||||||
![]() |
| × | 1 | |||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 1 |
Quite a lot of coffee is consumed at work but real statistics are missing. For the coffee machines with a can it can be interesting to have a visualization with coffee left in can, water in machine, time left until machine is finished, estimated time until can is empty. This would probably require a modified coffee can so is not very straightforward (pressure pad on the bottom of the can, fluid meter,…). For the other coffee machines statistics like number of cups made might be of interest (for cleaning, stocking, …).
Perhaps make a game out of it: get bonus points to get that last coffee that makes the next one needing to refill the water reservoir or empty the tray
For my hacking project, I assumed a coffee machine for individual cups..
Goals:
- know whether there is a cup or not: using a light sensor (if a cup is on top of it ~ less light) Why? The rfid reader reads the ID when a cup (with rfid tag) moves over the sensor. Hence when you take away the cup, we are not informed about that.
(Why? The rfid reader reads the ID when a cup (with rfid tag) moves over the sensor. Hence when you take away the cup, we are not informed about that.)
- know which cup is at the machine: read out rfid identification
- keep statistics: should be done in the back-end
- push a button to try to get coffee, and let the server then decide whether you get some coffee, with our without warnings
- access statistics with a mobile app or web app
I could only work for an hour or so, hence I didn't manage to reach all goals with the code supplied below (it needs some debugging too, sorry).
Untitled file
Warning: Embedding code files within the project story has been deprecated. To edit this file or add more files, go to the "Software" tab. To remove this file from the story, click on it to trigger the context menu, then click the trash can button (this won't delete it from the "Software" tab).
#include <Ethernet.h> //for loading components required by the iot device object.
#include <EthernetClient.h>
#include <PubSubClient.h>
#include <ATT_IOT.h> // SmartLiving for Makers Arduino Library
#include <SPI.h> //required to have support for signed/unsigned long type.
#include <SoftwareSerial.h>
char deviceId[] = ""; // Your device id comes here
char clientId[] = ""; // Your client id comes here;
char clientKey[] = ""; // Your client key comes here;
ATTDevice Device(deviceId, clientId, clientKey); //create the object that provides the connection to the cloud to manager the device.
char httpServer[] = "api.smartliving.io"; // HTTP API Server host
char* mqttServer = "broker.smartliving.io";
int rfid = 2; // Digital 8 is the input pin, this corresponds with the number on the Grove shiled where the push button is attached to
int led = 5; // Pin 8 is the LED pin and it's also used to construct the AssetID
int button = 8;
int lightsensor = 0;
int validcup = 100;
int relay = 4;
SoftwareSerial SoftSerial(2, 3);
// unsigned char buffer[64]; // buffer array for data recieve over serial port
char buffer[64]; // buffer array for data recieve over serial port
int count=0; // counter for buffer array
String currentRFIDconnected = "";
String supportedRFIDs[] = {"2300FB4B0A99", "BBBB"};
int coffeeCount[] = {0, 0};
//required for the device
void callback(char* topic, byte* payload, unsigned int length);
EthernetClient ethClient;
PubSubClient pubSub(mqttServer, 1883, callback, ethClient);
void setup()
{
pinMode(led, OUTPUT); // initialize the digital pin as an output.
pinMode(rfid, INPUT); // initialize the digital pin as an output.
pinMode(button, INPUT);
pinMode(lightsensor, INPUT);
pinMode(validcup, INPUT);
pinMode(relay, OUTPUT); // initialize the digital pin as an output.
Serial.begin(9600); // init serial link for debugging
SoftSerial.begin(9600);
Serial.begin(9600);
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x8C, 0xC1 }; // Adapt to your Arduino MAC Address
if (Ethernet.begin(mac) == 0) // Initialize the Ethernet connection:
{
Serial.println(F("DHCP failed,end"));
while(true); //we failed to connect, halt execution here.
}
delay(1000); //give the Ethernet shield a second to initialize:
if(Device.Connect(ðClient, httpServer)) //connect the device with the IOT platform.
{
Device.AddAsset(rfid, "rfid", "RFID Reader",false, "String");
Device.AddAsset(button, "button", "Button",false, "bool");
Device.AddAsset(led, "led", "light emitting diode", true, "bool");
Device.AddAsset(lightsensor, "lightsensor", "sensor of light", false, "int");
Device.AddAsset(validcup, "valid cup", "valid cup", false, "bool");
Device.AddAsset(relay, "toggle machine on", "toggle coffee machine", true, "bool");
Device.Subscribe(pubSub); // make certain that we can receive message from the iot platform (activate mqtt)
} else {
while(true); //can't set up the device on the cloud, can't continue, so put the app in an ethernal loop so it doesn't do anything else anymore.
}
}
unsigned long time; //only send every x amount of time.
unsigned int prevVal =0;
bool canTakeCoffee = false;
void loop()
{
unsigned int r = analogRead(lightsensor);
if(r < 600){
//there is a cup, is there an rfid tag
if (SoftSerial.available()) // if date is comming from softwareserial port ==> data is comming from SoftSerial shield
{
while(SoftSerial.available()) // reading RFID data into char array
{
buffer[count++]=SoftSerial.read(); // writing RFID data into array
if(count == 64)break;
}
Device.Send(buffer, rfid); // Sned RFID dara to SmartLiving
if(strcmp(buffer,"2300FB4B0A99")){
digitalWrite(led, HIGH);
delay(500);
digitalWrite(led, LOW);
delay(500);
digitalWrite(led, HIGH);
delay(500);
digitalWrite(led, LOW);
delay(500);
digitalWrite(led, HIGH);
delay(500);
digitalWrite(led, LOW);
if(digitalRead(button)){
if(coffeeCount[0] < 3){
coffeeCount[0]++;
digitalWrite(relay, HIGH);
}
}
}
clearBufferArray(); // call clearBufferArray function to clear the storaged data from the array
count = 0; // set counter of while loop to zero
digitalWrite(validcup, HIGH);
}
} else {
digitalWrite(validcup, LOW);
digitalWrite(relay, LOW);
digitalWrite(led, LOW);
Device.Send("no cup", rfid);
}
String buttonState = "false";
if(digitalRead(button))
buttonState = "true";
String validCupState = "false";
if(digitalRead(validcup));
validCupState = "true";
Device.Send(buttonState, button);
Device.Send(String(analogRead(lightsensor)), lightsensor);
Device.Send(validCupState, validcup);
if (Serial.available()) // if data is available on hardwareserial port ==> data is comming from PC or notebook
SoftSerial.write(Serial.read()); // write it to the SoftSerial shield
Device.Process();
delay(1000);
}
void clearBufferArray() // function to clear buffer array
{
for (int i=0; i<count;i++)
{ buffer[i]=NULL;} // clear all index of array with command NULL
}
// Callback function: handles messages that were sent from the iot platform to this device.
void callback(char* topic, byte* payload, unsigned int length)
{
String msgString;
{ //put this in a sub block, so any unused memory can be freed as soon as possible, required to save mem while sending data
char message_buff[length + 1]; //need to copy over the payload so that we can add a /0 terminator, this can then be wrapped inside a string for easy manipulation.
strncpy(message_buff, (char*)payload, length); //copy over the data
message_buff[length] = '\0'; //make certain that it ends with a null
msgString = String(message_buff);
msgString.toLowerCase(); //to make certain that our comparison later on works ok (it could be that a 'True' or 'False' was sent)
}
int* idOut = NULL;
{ //put this in a sub block, so any unused memory can be freed as soon as possible, required to save mem while sending data
int pinNr = Device.GetPinNr(topic, strlen(topic));
Serial.print("Payload: "); //show some debugging.
Serial.println(msgString);
Serial.print("topic: ");
Serial.println(topic);
if (pinNr == led)
{
if (msgString == "false") {
digitalWrite(led, LOW); //change the led
idOut = &led;
}
else if (msgString == "true") {
digitalWrite(led, HIGH);
idOut = &led;
}
}
}
if(idOut != NULL) //also let the iot platform know that the operation was succesful: give it some feedback. This also allows the iot to update the GUI's correctly & run scenarios.
Device.Send(msgString, *idOut);
}
How far did I get?
- detect cups with the light sensor
- get the id of the cup
- have a routing to detect if there is a cup and if so: what is the id; if not: remove the id
- send this information to a server (smartliving.io server)
Hackaton_CoffeeMachine.txt
Plain text#include <Ethernet.h> //for loading components required by the iot device object.
#include <EthernetClient.h>
#include <PubSubClient.h>
#include <ATT_IOT.h> // SmartLiving for Makers Arduino Library
#include <SPI.h> //required to have support for signed/unsigned long type.
#include <SoftwareSerial.h>
char deviceId[] = ""; // Your device id comes here
char clientId[] = ""; // Your client id comes here;
char clientKey[] = ""; // Your client key comes here;
ATTDevice Device(deviceId, clientId, clientKey); //create the object that provides the connection to the cloud to manager the device.
char httpServer[] = "api.smartliving.io"; // HTTP API Server host
char* mqttServer = "broker.smartliving.io";
int rfid = 2; // Digital 8 is the input pin, this corresponds with the number on the Grove shiled where the push button is attached to
int led = 5; // Pin 8 is the LED pin and it's also used to construct the AssetID
int button = 8;
int lightsensor = 0;
int validcup = 100;
int relay = 4;
SoftwareSerial SoftSerial(2, 3);
// unsigned char buffer[64]; // buffer array for data recieve over serial port
char buffer[64]; // buffer array for data recieve over serial port
int count=0; // counter for buffer array
String currentRFIDconnected = "";
String supportedRFIDs[] = {"2300FB4B0A99", "BBBB"};
int coffeeCount[] = {0, 0};
//required for the device
void callback(char* topic, byte* payload, unsigned int length);
EthernetClient ethClient;
PubSubClient pubSub(mqttServer, 1883, callback, ethClient);
void setup()
{
pinMode(led, OUTPUT); // initialize the digital pin as an output.
pinMode(rfid, INPUT); // initialize the digital pin as an output.
pinMode(button, INPUT);
pinMode(lightsensor, INPUT);
pinMode(validcup, INPUT);
pinMode(relay, OUTPUT); // initialize the digital pin as an output.
Serial.begin(9600); // init serial link for debugging
SoftSerial.begin(9600);
Serial.begin(9600);
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x8C, 0xC1 }; // Adapt to your Arduino MAC Address
if (Ethernet.begin(mac) == 0) // Initialize the Ethernet connection:
{
Serial.println(F("DHCP failed,end"));
while(true); //we failed to connect, halt execution here.
}
delay(1000); //give the Ethernet shield a second to initialize:
if(Device.Connect(ðClient, httpServer)) //connect the device with the IOT platform.
{
Device.AddAsset(rfid, "rfid", "RFID Reader",false, "String");
Device.AddAsset(button, "button", "Button",false, "bool");
Device.AddAsset(led, "led", "light emitting diode", true, "bool");
Device.AddAsset(lightsensor, "lightsensor", "sensor of light", false, "int");
Device.AddAsset(validcup, "valid cup", "valid cup", false, "bool");
Device.AddAsset(relay, "toggle machine on", "toggle coffee machine", true, "bool");
Device.Subscribe(pubSub); // make certain that we can receive message from the iot platform (activate mqtt)
} else {
while(true); //can't set up the device on the cloud, can't continue, so put the app in an ethernal loop so it doesn't do anything else anymore.
}
}
unsigned long time; //only send every x amount of time.
unsigned int prevVal =0;
bool canTakeCoffee = false;
void loop()
{
unsigned int r = analogRead(lightsensor);
if(r < 600){
//there is a cup, is there an rfid tag
if (SoftSerial.available()) // if date is comming from softwareserial port ==> data is comming from SoftSerial shield
{
while(SoftSerial.available()) // reading RFID data into char array
{
buffer[count++]=SoftSerial.read(); // writing RFID data into array
if(count == 64)break;
}
Device.Send(buffer, rfid); // Sned RFID dara to SmartLiving
if(strcmp(buffer,"2300FB4B0A99")){
digitalWrite(led, HIGH);
delay(500);
digitalWrite(led, LOW);
delay(500);
digitalWrite(led, HIGH);
delay(500);
digitalWrite(led, LOW);
delay(500);
digitalWrite(led, HIGH);
delay(500);
digitalWrite(led, LOW);
if(digitalRead(button)){
if(coffeeCount[0] < 3){
coffeeCount[0]++;
digitalWrite(relay, HIGH);
}
}
}
clearBufferArray(); // call clearBufferArray function to clear the storaged data from the array
count = 0; // set counter of while loop to zero
digitalWrite(validcup, HIGH);
}
} else {
digitalWrite(validcup, LOW);
digitalWrite(relay, LOW);
digitalWrite(led, LOW);
Device.Send("no cup", rfid);
}
String buttonState = "false";
if(digitalRead(button))
buttonState = "true";
String validCupState = "false";
if(digitalRead(validcup));
validCupState = "true";
Device.Send(buttonState, button);
Device.Send(String(analogRead(lightsensor)), lightsensor);
Device.Send(validCupState, validcup);
if (Serial.available()) // if data is available on hardwareserial port ==> data is comming from PC or notebook
SoftSerial.write(Serial.read()); // write it to the SoftSerial shield
Device.Process();
delay(1000);
}
void clearBufferArray() // function to clear buffer array
{
for (int i=0; i<count;i++)
{ buffer[i]=NULL;} // clear all index of array with command NULL
}
// Callback function: handles messages that were sent from the iot platform to this device.
void callback(char* topic, byte* payload, unsigned int length)
{
String msgString;
{ //put this in a sub block, so any unused memory can be freed as soon as possible, required to save mem while sending data
char message_buff[length + 1]; //need to copy over the payload so that we can add a /0 terminator, this can then be wrapped inside a string for easy manipulation.
strncpy(message_buff, (char*)payload, length); //copy over the data
message_buff[length] = '\0'; //make certain that it ends with a null
msgString = String(message_buff);
msgString.toLowerCase(); //to make certain that our comparison later on works ok (it could be that a 'True' or 'False' was sent)
}
int* idOut = NULL;
{ //put this in a sub block, so any unused memory can be freed as soon as possible, required to save mem while sending data
int pinNr = Device.GetPinNr(topic, strlen(topic));
Serial.print("Payload: "); //show some debugging.
Serial.println(msgString);
Serial.print("topic: ");
Serial.println(topic);
if (pinNr == led)
{
if (msgString == "false") {
digitalWrite(led, LOW); //change the led
idOut = &led;
}
else if (msgString == "true") {
digitalWrite(led, HIGH);
idOut = &led;
}
}
}
if(idOut != NULL) //also let the iot platform know that the operation was succesful: give it some feedback. This also allows the iot to update the GUI's correctly & run scenarios.
Device.Send(msgString, *idOut);
}
Comments