Project tutorial
Menu Card To Speech, Reads And Writes Data On Thingspeak

Menu Card To Speech, Reads And Writes Data On Thingspeak © GPL3+

Talk to the waitress. Order your menu. See how Arduino parses the price list from Thingspeak and see your order charts updating.

  • 725 views
  • 0 comments
  • 2 respects

Components and supplies

About this project

Intro

In the first place I wanted to discover how to parse multiple fields of a Thingspeak channel on an Arduino Uno with the internet shield of Onesheeld (first picture, www.onesheeld.com). Finally I came up with the idea to create a sketch that asks me what I want to order.

The parsing part is that it reads the price list from a Thingspeak channel in the first part of my code. Then the Arduino asks me: "What do you want to order?". I respond with voice commands my choice of three items on a menu list (second picture).

The Arduino calculates the total amount I have to pay, tells me the outcome and writes my order to an other Thingspeak channel (third picture).

Step 1 Start to create your channels and fields on Thingspeak

In this project we choose 3 products (otherwise we get memory errors on the Arduino Uno):

  • Hamburger;
  • Milkshake;
  • Pizza.

So you have a menu list of 3 items. Make a channel called "price list" on Thingspeak with these three items as field labels.

Next: add a value to each field being the price of one piece. Be careful when you update. Make sure that you update all three, because the code reads the last value's.

Make a second channel called "total orders" on Thingspeak to write the orders to:

  • Hamburger;
  • Milkshake;
  • Pizza.

More info if you are not familiar with Thingspeak, see: http://nl.mathworks.com/help/thingspeak/getting-started-with-thingspeak.html

To add a price to a menu item, I use:

https://addons.mozilla.org/nl/firefox/addon/poster/

Step 2 Making the code for the right response to parse later on

In this step I explain the part of the code that makes the right response that we have to parse later on (step 3). The request must have a name. Let's call it 'Request'.

The url to get the respond from Thingspeak channel is: https://api.thingspeak.com/channels/121797/feeds.json?&results=1

So the code, that has to be placed above the void setup(), must be:

HttpRequest request("https://api.thingspeak.com/channels/121797/feeds.json?&results=1");

Here the channel number is: 121797. Please put here your own channel number. To start the Request, the next code has to be in the Void Setup (). Not in the void loop because you only want to get the response once:

/* part getting price values from Thingspeak */
// wait serial port initialization
/* Start communication. */
OneSheeld.begin();
/* Subscribe to success callback for the request. */
request.setOnSuccess(&onSuccess);
/* Subscribe to json value replies. */
request.getResponse().setOnJsonResponse(&onJsonReply);
/* Subscribe to response errors. */
/* Add paramter to the URL with the name of the country from the voice recognition. */
request.addParameter("key","put-here-your-key");
/* Perform a GET request using the Internet shield. */
Internet.performGet(request);
/* Wait for 5 seconds. */
OneSheeld.delay(5000);

In this code you see a referal to a void called "onSuccess":

request.setOnSuccess(&onSuccess);

Down further in the sketch this void looks like this:

void onSuccess(HttpResponse & response)
{
response["feeds"][0].query();  query to continue with the field data
}

Using this query the Json response of the Thingspeak server is something like this:

{'entry_id,"created_at":"2016-06-03T04:20:59Z","field3":"3.5","field2":"2.7","field1":"2.3"}

That is the rigth response to parse in step 3.

Remark: There should be more checks and balances to do a proper request. But unfortunately I had to minimize the code to prevent the Arduino exceeding the maximum use of the memory.

Step 3 Parsing the prices of the menu items

This step was the most challenging part for me. The code in step 2 has the next referal to the void where the prsing is being excecuted:

request.getResponse().setOnJsonResponse(&onJsonReply);

Down further in the sketch the void is:

void onJsonReply(JsonKeyChain & hell,char * output)
{
StaticJsonBuffer 200 jsonBuffer; 
Terminal.println(output);
delay(5000); //giving the process a little time to do its thing
// const char * json = (json); // not needed here
JsonObject& root = jsonBuffer.parseObject(output);
// Test if parsing succeeds.
if (!root.success()) {
Serial.println("parseObject() failed");
return;
}
const char* value1 = root["field1"];
const char* value2 = root["field2"];
const char* value3 = root["field3"];
val1 = atof(value1);
val2 = atof(value2);
val3 = atof(value3);
PrintValues();
}
void PrintValues()
{
Terminal.println("test");
delay(1000);
Terminal.print("field1= ");
Terminal.println(val1, 2); // it is money so two decimals
delay(1000);
Terminal.print("field2= ");
Terminal.println(val2, 2);
delay(1000);
Terminal.print("field3= ");
Terminal.println(val3, 2);
}

This needs an explanation.

To execute the parsing I used the library: ArduinoJson.h. To download it and read more about this library, see: https://github.com/bblanchon/ArduinoJson/wiki/Using-the-library-with-Arduino

Some details:

StaticJsonBuffer jsonBuffer;

The Buffer needs to be 200. If you run into troubles executing the sketch, try to change this buffer in little steps.

Terminal.println(output);

The Json response is printed out in the OneSheeld Terminal shield. Handy to check if the request and query works. Also the outcome of this parsing is printed out on that Terminal. Coded in:

void PrintValues()

I have converted the values with the command: "atof" meaning: convert char to float. I have used float because the output is money with two decimals.

Step 4 Text to speech and voice detection

In this chapter I explain how to code the text-to-speech function and voice detection. Both are available shields in the OneSheeld app. Above the setup void we start with the next code:

/* A command which will be compared. */
const char firstCommand[]="hello food store";
/* A command which will be compared. */
const char secondCommand[]="hamburger";
/* A command which will be compared. */
const char thirdCommand[]="milkshake";
/* A command which will be compared. */
const char fourthCommand[]="pizza";
/* A command which will be compared. */
const char fifthCommand[]="no";

Here the menu items are hard coded: hamburger, milkshake, pizza. Also I have put in a command to start the whole process: "Hello food store" is the first command to wake up the waitress. Also the last command is: "no". That is the final command when the waitress asks me if I want to order more.

The rest of the code is put in the void loop:

void loop()
{  
/* voice commands and text to speech starts heere
/* Always check if a new voice command received. */ 
if(VoiceRecognition.isNewCommandReceived())
{
/* Check if the voice command is the desired one. */
if(!strcmp(firstCommand,VoiceRecognition.getLastCommand()))
{
/* 1Sheeld responds using text-to-speech. */
TextToSpeech.say("Hello, What do you want to order?");
}
/* Check if the voice command is the desired one. */
else if(!strcmp(secondCommand,VoiceRecognition.getLastCommand()))
{
/* 1Sheeld responds using text-to-speech. */
TextToSpeech.say("Okay, Anything else?");
countHamburger++; //counts ordered hamburgers
}
else if(!strcmp(thirdCommand,VoiceRecognition.getLastCommand()))
{
/* 1Sheeld responds using text-to-speech. */
TextToSpeech.say("Okay, Anything else?");
countMilkshake++; //counts ordered milkshakes
}
else if(!strcmp(fourthCommand,VoiceRecognition.getLastCommand()))
{
/* 1Sheeld responds using text-to-speech. */
TextToSpeech.say("Okay, Anything else?");
countPizza++; //counts ordered pizza's
}
/* Check if the voice command is the desired one. */
else if(!strcmp(fifthCommand,VoiceRecognition.getLastCommand()))
{
/* 1Sheeld responds using text-to-speech. */
TextToSpeech.say("Okay, thank you.");
delay(2000);
calc();
}
else 
{
/* 1Sheeld responds using text-to-speech. */
TextToSpeech.say("Sorry, we don't have that. What do you want?");
delay(2000);
}
}
}

All the communication with the waitress is put in here. You see that here the counting of the orders is done aswell. A little more text-to-speech is done in the next step.

Step 5: The counting of the orders

void calc() // Here the amount is being calculated and spoken
{
float price = (countHamburger * val1) + (countMilkshake* val2) + (countPizza * val3);
String amount = String(price, 2);
Terminal.print(price);
TextToSpeech.say("A moment please. ");
delay(4000);
TextToSpeech.say("the total amount is");
delay(2000);
TextToSpeech.say(amount);
delay(2000);
TextToSpeech.say("euro");
toThingspeak();
}

In this void you see that "val1", "val2" and "val3" are used (the result of the parsing in step 3). Also you see the final part of the text-to-speech part. The waitress tells you what you have to pay. At the end you see the command to start the writing on thingspeak explained in the next step.

Step 6: The final code that writes the total of ordered menu items on Thingspeak

In this step I explain how to write the amount of ordered menu items to your second Thingspeak channel. Let's call this request: "AddCount". So the next request code put it in the void setup():

requestAddCount.addParameter("key","put-here-your-api-key"); // add your API key
OneSheeld.delay(5000);

Above the setup void, put the url of your request:

/* declaring an object from the HttpRequest with the URL of thing speak api */
HttpRequest requestAddCount ("https://api.thingspeak.com/update"); // request to add count to channelfields

In step 5 you saw at the end of that part of the code a command to start the writing: toThingspeak(). Down further you see that void:

void toThingspeak() 
{
dtostrf(countHamburger, 3, 0, charCountHamburger);            // convert from int to char array
dtostrf(countMilkshake, 3, 0, charCountMilkshake);            // convert from int to char array
dtostrf(countPizza, 3, 0, charCountPizza);            // convert from int to char array
requestAddCount.addParameter("field1",charCountHamburger);
requestAddCount.addParameter("field2",charCountMilkshake);
requestAddCount.addParameter("field3",charCountPizza);
Internet.performGet(requestAddCount);                // Perform get to the request
OneSheeld.delay(10000);                      // 10 sec delay between each reading and the other.
}

Here the variables have to be converted into the right value's. In the char array part the countings are added to the request url. Finaly I give the process space to do it's work puting in a delay of 10 seconds.

Step 7: Talk to the waitress and view your results on the graph at Thingspeak

Okay, so in step 1 to 6 I have explained how to setup your Thingspeak channels and fields and the Arduino code. In this chapter I explain how the process is run.

  • Put the UART switch of the onesheeld into the upload position;
  • Upload you Arduino code to the Arduino;
  • Put the UART switch of the onesheeld into the execute position;
  • Start the onesheeld app on your smart phone;
  • Connect the phone with the onesheeld;
  • select the 4 shields in the onesheeld app: Terminal, Internet, Text to Speech, Voice recognizer;
  • Press the reset button of the Arduino board;
  • Activate the Terminal in the app and watch the prices of the menu items coming up;
  • Activate the voice recognizer;
  • Tap on "Tap to Speak";
  • Say: "Hello food store";
  • The waitress says: "Hello, what do you want to order?";
  • Press on "Tap to Speak";
  • Say your menu item, for example: "hamburger";
  • The waitress says: "Okay, anything else?";
  • Press on "Tap to Speak";
  • Say your second menu item, for example: "pizza";
  • The waitress says: "Okay, anything else?";
  • Press on "Tap to Speak";
  • Say your third menu item, for example: "milkshake";
  • The waitress says: "Okay, anything else?";
  • Press on "Tap to Speak";
  • You can keep ordering but in this case you say: "no";
  • Meanwhile you open up the charts of your thingspeak channel "total orders";
  • The waitress says: "Okay, thank you. A moment please. The total amount is xx,xx euro.". Of course she says the right amount where I have putted xx,xx.
  • Watch your charts being updated.

Code

Menu card to Speech, reads and writes data on Thingspeak Arduino
#include <ArduinoJson.h>

#define CUSTOM_SETTINGS
#define INCLUDE_TEXT_TO_SPEECH_SHIELD
#define INCLUDE_VOICE_RECOGNIZER_SHIELD
#define INCLUDE_TERMINAL_SHIELD
#define INCLUDE_INTERNET_SHIELD

/* Include 1Sheeld library. */
#include <OneSheeld.h>

/* declaring an object from the HttpRequest with the URL of thing speak api */
HttpRequest requestAddCount ("https://api.thingspeak.com/update"); // request to add count to channelfields
//HttpRequest request("https://api.thingspeak.com/channels/114952/feeds.json?&results=1"); // request to read prices
 
char charCountHamburger[20];
char charCountMilkshake[20];
char charCountPizza[20];

/* A command which will be compared. */
const char firstCommand[]="hello food store";

/* A command which will be compared. */
const char secondCommand[]="hamburger";

/* A command which will be compared. */
const char thirdCommand[]="milkshake";

/* A command which will be compared. */
const char fourthCommand[]="pizza";

/* A command which will be compared. */
const char fifthCommand[]="no";

int countHamburger = 0;
int countMilkshake = 0;
int countPizza = 0;
int price = 0;


HttpRequest request("https://api.thingspeak.com/channels/121797/feeds.json?&results=1"); // change channel  into your channel price list

/* Create value's for field data Thingspeak. */

float val1 = 0;
float val2 = 0;
float val3 = 0;

void setup() 
{
  
  /* part getting price values from Thingspeak */
    // wait serial port initialization
  /* Start communication. */
  OneSheeld.begin();
  /* Subscribe to success callback for the request. */
  request.setOnSuccess(&onSuccess);
  /* Subscribe to json value replies. */
  request.getResponse().setOnJsonResponse(&onJsonReply);
  

  /* Add paramter to the URL  */
    request.addParameter("key","put-here-your-key"); //put in here your key of the channel price list
    /* Perform a GET request using the Internet shield. */
    Internet.performGet(request);
    /* Wait for 5 seconds. */
    OneSheeld.delay(5000);

  requestAddCount.addParameter("key","put-here-your-key"); // add your API key of the total orders channel
  OneSheeld.delay(5000);
}

void loop()
{  
    
   /* voice commands and text to speech starts heere
   /* Always check if a new voice command received. */ 
   if(VoiceRecognition.isNewCommandReceived())
   {
     /* Check if the voice command is the desired one. */
     if(!strcmp(firstCommand,VoiceRecognition.getLastCommand()))
     {
       /* 1Sheeld responds using text-to-speech. */
       TextToSpeech.say("Hello, What do you want to order?");
     }
     /* Check if the voice command is the desired one. */
     else if(!strcmp(secondCommand,VoiceRecognition.getLastCommand()))
     {
       /* 1Sheeld responds using text-to-speech. */
       TextToSpeech.say("Okay, Anything else?");
       countHamburger++; //counts ordered hamburgers
     }
     else if(!strcmp(thirdCommand,VoiceRecognition.getLastCommand()))
     {
       /* 1Sheeld responds using text-to-speech. */
       TextToSpeech.say("Okay, Anything else?");
       countMilkshake++; //counts ordered milkshakes
     }
     else if(!strcmp(fourthCommand,VoiceRecognition.getLastCommand()))
     {
       /* 1Sheeld responds using text-to-speech. */
       TextToSpeech.say("Okay, Anything else?");
       countPizza++; //counts ordered pizza's
     }
     
     /* Check if the voice command is the desired one. */
     else if(!strcmp(fifthCommand,VoiceRecognition.getLastCommand()))
     {
       /* 1Sheeld responds using text-to-speech. */
       TextToSpeech.say("Okay, thank you.");
       delay(2000);
       calc();
       
     }
     else 
     {
      /* 1Sheeld responds using text-to-speech. */
       TextToSpeech.say("Sorry, we don't have that. What do you want?");
       delay(2000);
     }
   }
    
}

void onSuccess(HttpResponse & response)

{
  
  response["feeds"][0].query(); // query to continue with the field data
}


void onJsonReply(JsonKeyChain & hell,char * output)
{
  
 StaticJsonBuffer<200> jsonBuffer; 
 
  Terminal.println(output);
  delay(5000); //giving the process a little time to do its thing
  
  // const char * json = (json); // not needed here
  JsonObject& root = jsonBuffer.parseObject(output);

  // Test if parsing succeeds.
  if (!root.success()) {
    Serial.println("parseObject() failed");
    return;
  }

  
  const char* value1 = root["field1"];
  const char* value2 = root["field2"];
  const char* value3 = root["field3"];
 
  val1 = atof(value1);
  val2 = atof(value2);
  val3 = atof(value3);

  PrintValues();
}

void PrintValues()
{
  Terminal.println("test");
  delay(1000);
  Terminal.print("field1= ");
  Terminal.println(val1, 2); // it is money so two decimals
  delay(1000);
  Terminal.print("field2= ");
  Terminal.println(val2, 2);
  delay(1000);
  Terminal.print("field3= ");
  Terminal.println(val3, 2);
  
  //Serial.println(latitude, 6);
  //Serial.println(longitude, 6);
  
}



void calc() // Here the amount is being calculated and spoken
{
       
       float price = (countHamburger * val1) + (countMilkshake* val2) + (countPizza * val3);
       String amount = String(price, 2);
       Terminal.print(price);
       TextToSpeech.say("A moment please. ");
       delay(4000);
       TextToSpeech.say("the total amount is");
       delay(2000);
       TextToSpeech.say(amount);
       delay(2000);
       TextToSpeech.say("euro");
       toThingspeak();
}

/* from here code to save orders in dtabase thingspeak */

void toThingspeak() 
{
  dtostrf(countHamburger, 3, 0, charCountHamburger);            // convert from int to char array
  dtostrf(countMilkshake, 3, 0, charCountMilkshake);            // convert from int to char array
  dtostrf(countPizza, 3, 0, charCountPizza);            // convert from int to char array
  
  requestAddCount.addParameter("field1",charCountHamburger);
  requestAddCount.addParameter("field2",charCountMilkshake);
  requestAddCount.addParameter("field3",charCountPizza);
  
  Internet.performGet(requestAddCount);                // Perform get to the request
  OneSheeld.delay(10000);                      // 10 sec delay between each reading and the other.
  
}

Schematics

OneSheeld on an Arduino Uno
Tingspeak 1sheeld bb

Comments

Similar projects you might like

Girlfriend Call and Message

Project tutorial by Khloud Mohamed

  • 1,066 views
  • 1 comment
  • 4 respects

Home surveillance system using skype calls

Project tutorial by Manuel Miguel

  • 1,621 views
  • 0 comments
  • 3 respects

4x4x4 LED cube with Arduino Uno and 1sheeld

Project tutorial by Hassan Ibrahim

  • 30,225 views
  • 6 comments
  • 60 respects

Unlock your door with a knock

Project tutorial by Ashraf Nabil

  • 23,400 views
  • 13 comments
  • 61 respects

Smartwatch car remote

Project tutorial by Mika Wee

  • 17,123 views
  • 20 comments
  • 85 respects

Export Data from Arduino to Excel Sheet

Project showcase by ahmed ismail

  • 14,781 views
  • 1 comment
  • 7 respects
Add projectSign up / Login