Things used in this project

Hardware components:
Abx00014 featured xjsqphgdlv
Arduino MKR Fox 1200
Core of Fox Advisor
×1
181 02
Adafruit Standard LCD - 16x2 White on Blue
Screen for communication
×1
Keypad
Keypad for interaction with customers
×1
Adafruit white led
For user-adjustable luminosity
×1
09939 01
Rotary potentiometer (generic)
20k potentiometer for luminosity adjustment
×1
Fairchild semiconductor pn2222abu. image
General Purpose Transistor NPN
For Arduino-based LED strip regulation
×1
Mfr 25frf52 1k sml
Resistor 1k ohm
×4
Mfr 25fbf52 221r sml
Resistor 221 ohm
×1
9V alkaline
×1
09264 1
RGB Diffused Common Cathode
Diet indication LED
×1
09590 01
LED (generic)
Peronnel calling LED (green)
×1
Mydigital protoboard box 600  45096.1449790643.500.659
Digilent myDigital Protoboard for NI myDAQ & myRIO
×1
11026 02
Jumper wires (generic)
×1
Software apps and online services:
Ide web
Arduino IDE
Ide web
Arduino Web Editor
Sigfox logo rgb j7ilnvhq6o
Sigfox
Hackster
ThingSpeak API
H5g3etjnacmazg8oq17z
MATLAB
D94d qxu
Autodesk Fusion 360
Ultimaker Cura Software
Hand tools and fabrication machines:
09507 01
Soldering iron (generic)
3drag
3D Printer (generic)

Custom parts and enclosures

Fox Advisor 3D model
Smart Box to improve customer satisfaction in restaurants which allows clients to rate the service via Sigfox and ThingSpeak IoT platform. This model represents the housing of Fox Advisor device.
Fox Advisor 3D box model
Smart Box to improve customer satisfaction in restaurants which allows clients to rate the service via Sigfox and ThingSpeak IoT platform. This model represents the box located near Fox Advisor device

Schematics

Fox Advisor Schematics
Smart Box to improve customer satisfaction in restaurants which allows clients to rate the service via Sigfox and ThingSpeak IoT platform.
foxadvisor_sketch_4QqtltX6QG.fzz

Code

Fox Advisor codeArduino
This code includes LCD, keypad and MKRFox1200 board to build a Smart Table able to interact with customers in restaurants: Fox Advisor.
/*Developed by Celia Garrido Hidalgo - FoxAdvisor: a rating a day keeps the failure away (with MKRFox1200)

   This code includes LCD, keypad and MKRFox1200 board to build a Smart Table able to interact with customers in restaurants.

 *  ************************** INSTRUCTIONS **************************
   //             Press (A)dvance to next question.                  //
   //             Press (B)ill to request the check.                 //
   //             Press (C)all to ask for assistance.                //
   //             Press (D)iet for special requirements.             //
   //               (1) = Gluten-free                                //
   //               (2) = Lactose-free                               //
   //               (3) = Sugar-free                                 //
   //               (4) = Vegetarian                                 //
   //               (5) = Vegan                                      //
   //               (0) = Other                                      //
   //             Press (*) to rate our restaurant.                  //
 *  ******************************************************************

   Useful libraries and examples:
    Sigfox:
      SendBoolean.ino (from <SigFox.h>)
      WeatherMonitor.ino (from <SigFox.h>)
    LCD:
      HelloWorld.ino (from <LiquidCrystal.h>)
    Keypad:
      EventKeypad.ino (from <Keypad.h>)

   Ratings from customers are sent to Sigfox Backend and an HTTP callback sends    the results to ThingSpeak cloud using:
    Custom payload config:
      restaurantID::uint:8 tableID::uint:8 allergy::uint:8 question1::uint:8          question2::uint:8 question3::uint:8
    URL pattern:
      http://api.thingspeak.com/update?api_key=yourapikeyhere&field1={customData#restaurantID}&field2={customData#tableID}&field3={customData#allergy}&field4={customData#question1}&field5={customData#question2}&field6={customData#question3}
*/

/************ LIBRARIES ************/

#include <LiquidCrystal.h>
#include <Keypad.h>
#include <SigFox.h>


/************ VARIABLES ************/

int RED = A1;
int GREEN = A2;
int BLUE = A3; // RGB LED
int questionNumber = 0; // Counter to check the current question asked
String question1 = "Service quality";
String question2 = "Food quality";
String question3 = "Did you enjoy?";
String range = "from 0 to 5: ";
boolean myFlags[] = {false, false}; // {Diet, Rating}

const byte ROWS = 4; // KeyPad: Four rows
const byte COLS = 4; // KeyPad: Four columns

char keys[ROWS][COLS] = { // Keys definition
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

typedef struct __attribute__ ((packed)) sigfox_message { // Structure to store information to be sent to sigfox-backend
  uint8_t restaurantID = 103; // Default
  uint8_t tableID = 7; // Default
  uint8_t allergy;
  uint8_t q1;
  uint8_t q2;
  uint8_t q3;
} SigfoxMessage;

SigfoxMessage msg; // Stub for message which will be sent


/********* INITIALIZATIONS *********/

LiquidCrystal lcd(0, 1, 2, 3, 4, 5);

byte rowPins[ROWS] = {13, 12, 11, 10}; // Pin connections for the keypad (ROWS)
byte colPins[COLS] = {9, 8, 7, 6}; // Pin connections for the keypad (ROWS)

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


/************* SET UP *************/

void setup() {
  if (!SigFox.begin()) {
    // Something is wrong
  }

  SigFox.end(); // Send module to standby until we need to send a message
  SigFox.debug(); // Important (for more information check the Forum http://forum.arduino.cc/index.php?topic=478950.0;nowap)

  lcd.begin(16, 2); // Setting up the LCD's number of columns and rows

  pinMode(14, OUTPUT); // Red LED to call for assitance
  pinMode(RED, OUTPUT); // RGB (red color)
  pinMode(GREEN, OUTPUT); // RGB (green color)
  pinMode(BLUE, OUTPUT); // RGB (blue color)

  pinMode(A5, OUTPUT); // To control the LED strip

  for (int i = 0; i < 3; i++) { // Display "Welcome" message
    lcd.print("    Welcome!");
    delay(500);
    lcd.clear();
    delay(500);
    lcd.setCursor(0, 0);
  }

  lcd.print(" * FoxAdvisor *"); // Default message
  lcd.setCursor(0, 1);
  lcd.print("Can we help you?");
  keypad.addEventListener(keypadEvent); // Add an event listener for this keypad
}


/************* LOOP *************/

void loop() {
  char key = keypad.getKey();
  int rVal = analogRead(A6) / 4; // Read potentiometer voltage
  Serial.println(rVal); // Apply NPN voltage to control the LED strip
  analogWrite(A5, rVal);
}


/************ EVENTS ************/

void keypadEvent(KeypadEvent key) {
  int myCol = 0; // Column to write in the LCD
  int i;

  if (keypad.getState() == PRESSED) { // Once pressed any key...

    switch (key) {
      case 'A': /*************************   A   *************************/
        if (questionNumber == 1) { // If we were in question 1, go to question 2
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print(question2);
          lcd.setCursor(0, 1);
          lcd.print(range);
        }

        else if (questionNumber == 2) { // If we were in question 2, go to question 3
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print(question3);
          lcd.setCursor(0, 1);
          lcd.print(range);
        }

        else if (questionNumber == 3) { // If we were in question 3, send packet via Sigfox
          for (i = 0; i < 3; i++) {
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("Sending result");
            lcd.setCursor(0, 1);
            lcd.print("via Sigfox");

            for (myCol = 10; myCol < 16; myCol++) {
              delay(150);
              lcd.setCursor(myCol, 1);
              lcd.print('.');
            }
          }

          SigFox.begin(); // Wait at least 30ms after first configuration (100ms before)
          delay(100);
          SigFox.status();
          delay(1);
          SigFox.beginPacket(); // Sending packet via Sigfox
          SigFox.write((uint8_t*)&msg, 6);
          SigFox.endPacket(); // We finish the packet
          SigFox.end();

          lcd.clear(); // Say goodbye to customers
          delay(50);
          lcd.setCursor(0, 0);
          lcd.print("    Done! ;)  ");
          lcd.setCursor(0, 1);
          lcd.print("Have a nice day!");

          delay(8000); // Wait 8 seconds...
          lcd.clear();
          lcd.print(" * FoxAdvisor *"); // Receive new customers
          lcd.setCursor(0, 1);
          lcd.print("Can we help you?");
          questionNumber == 0;
        }

        break;

      case 'B':  /*************************   B   *************************/
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("- Bill request -");
        lcd.setCursor(0, 1);
        lcd.print("Press *, please");

        for (i = 0; i < 3; i++) { // Turn on notification LED to call the personnel and request the bill. In the meantime, fulfill the questionnaire
          digitalWrite(14, LOW);
          delay(500);
          digitalWrite(14, HIGH);
          delay(500);
        }

        delay(2000);
        lcd.clear();
        lcd.print(" * FoxAdvisor *");
        lcd.setCursor(0, 1);
        lcd.print("Can we help you?");
        break;

      case 'C':  /*************************   C   *************************/
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("We'll be here");
        lcd.setCursor(0, 1);
        lcd.print("in a moment!");

        for (i = 0; i < 3; i++) { // Turn on notification LED to call the personnel
          digitalWrite(14, LOW);
          delay(500);
          digitalWrite(14, HIGH);
          delay(500);
        }

        delay(2000);
        lcd.clear();
        lcd.print(" * FoxAdvisor *");
        lcd.setCursor(0, 1);
        lcd.print("Can we help you?");

        break;

      case 'D':  /*************************   D   *************************/
        lcd.clear();
        lcd.setCursor(myCol, 0);
        lcd.print("Special diet");
        lcd.setCursor(myCol, 1);
        lcd.print("requirements");

        for (myCol = 12; myCol < 16; myCol++) {
          delay(200);
          lcd.setCursor(myCol, 1);
          lcd.print('.');
        }

        delay(1000);
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Select option:");
        myFlags[0] = true; // Activate the diet flag.

        break;

      case '*': // Let's rate the restaurant!
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("Great! Let's");
        lcd.setCursor(0, 1);
        lcd.print("start");

        for (myCol = 5; myCol < 16; myCol++) {
          delay(150);
          lcd.setCursor(myCol, 1);
          lcd.print('.');
        }

        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print(question1); // Asking question 1...
        lcd.setCursor(0, 1);
        lcd.print(range);

        break;

      case '#': // Nothing happens

        break;

      default: // For the numeric values of the keypad

        if (key > '5') { // The value specified is out of range
          for (i = 0; i < 3; i++) {
            lcd.clear();
            delay(500);
            lcd.setCursor(0, 0);
            lcd.print("Out of range 0-5");
            delay(500);
          }

          if (myFlags[0]) { // If we were asking for diet requirements...
            lcd.clear();
            lcd.setCursor(0, 0);
            lcd.print("Select option:");
          }

          else if (myFlags[1]) { // If we were asking for any question of the questionnaire...

            switch (questionNumber) { // Where are we?
              case 0:
                lcd.clear();
                lcd.setCursor(0, 0);
                lcd.print(question1); // Question 1
                lcd.setCursor(0, 1);
                lcd.print(range);
                break;

              case 1:
                lcd.clear();
                lcd.setCursor(0, 0);
                lcd.print(question2); // Question 2
                lcd.setCursor(0, 1);
                lcd.print(range);
                break;

              case 2:
                lcd.clear();
                lcd.setCursor(0, 0);
                lcd.print(question3); // Question 3
                lcd.setCursor(0, 1);
                lcd.print(range);
                break;
            }
          }
          break;
        }

        if (myFlags[0]) { // Special diet requirements
          lcd.setCursor(15, 0);
          lcd.print((char)key);
          myFlags[0] = false; // Clear the diet flag.
          delay(500);

          for (myCol = 0; myCol < 16; myCol++) {
            lcd.setCursor(myCol, 1);
            lcd.print('.');
            delay(80);
          }

          lcd.setCursor(0, 1);
          lcd.print("   Got it! ;)   ");
          analogWrite(RED, 0); // Switch off the RGB LED just in case
          analogWrite(GREEN, 0);
          analogWrite(BLUE, 0);

          switch (key) {
            case '1': // Gluten-free
              analogWrite(RED, 255);
              analogWrite(GREEN, 71);
              analogWrite(BLUE, 92);
              msg.allergy = 1;
              break;

            case '2': // Lactose-free
              analogWrite(BLUE, 200);
              msg.allergy = 2;
              break;

            case '3': // Sugar-free
              analogWrite(RED, 185);
              analogWrite(GREEN, 100);
              msg.allergy = 3;
              break;

            case '4': // Vegetarian
              analogWrite(RED, 255);
              analogWrite(GREEN, 225);
              analogWrite(BLUE, 53);
              msg.allergy = 4;
              break;

            case '5': // Vegan
              analogWrite(GREEN, 255);
              msg.allergy = 5;
              break;

            default: // Turn on notification LED to call the personnel and set the allergy type
              msg.allergy = 0;
              for (i = 0; i < 3; i++) {
                digitalWrite(14, LOW);
                delay(500);
                digitalWrite(14, HIGH);
                delay(500);
              }
              break;
          }

          delay(2000);
          lcd.clear();
          lcd.print(" * FoxAdvisor *"); // Go back to the default message
          lcd.setCursor(0, 1);
          lcd.print("Can we help you?");
        }

        else if (myFlags[1] && questionNumber == 0) { // Rating process, question 1 (getting the answer of the customer)
          questionNumber++;
          lcd.setCursor(13, 1);
          lcd.print((char)key);
          msg.q1 = key - 48; // Write in the structure the int value
        }

        else if (myFlags[1] && questionNumber == 1) { //Rating process, question 2 (getting the answer of the customer)
          lcd.setCursor(13, 1);
          lcd.print((char)key);
          questionNumber++;
          msg.q2 = key - 48; // Write in the structure the int value
        }

        else if (myFlags[1] && questionNumber == 2) { //Rating process, question 3 (getting the answer of the customer)
          lcd.setCursor(13, 1);
          lcd.print((char)key);
          questionNumber++;
          myFlags[1] = false;
          msg.q3 = key - 48; // Write in the structure the int value
        }
    }
  }
}
ThingSpeak application codeMATLAB
Code for visualization in ThingSpeak
% Celia Garrido-Hidalgo
% Channel ID to read data from 
readChannelID = 357609; 
question1 = 4; 
question2 = 5; 
question3 = 6; 

% Channel Read API Key  
% If your channel is private, then enter the read API 
% Key between the '' below:  
readAPIKey = 'WRITEHEREYOURKEY'; 

question1Data = thingSpeakRead(readChannelID, 'Fields', question1, 'NumPoints', 5, 'ReadKey', readAPIKey); 
question2Data = thingSpeakRead(readChannelID, 'Fields', question2, 'NumPoints', 5, 'ReadKey', readAPIKey); 
question3Data = thingSpeakRead(readChannelID, 'Fields', question3, 'NumPoints', 5, 'ReadKey', readAPIKey); 

bar(1:5, 33.33/5*[question1Data question2Data question3Data], 0.5, 'stack') 

axis([0 6 0 100]) 
title('Customer satisfaction') 
xlabel('Customer ID') 
ylabel('Satisfaction (%)') 
legend('Service quality', 'Food quality', 'Did you enjoy?')  

Credits

Sin titulo222 4vgjw9wz9u
Celia Garrido Hidalgo
7 projects • 1 follower
IoT developer at the Albacete Research Institute of Informatics, Spain
Contact

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Add projectSign up / Login