Home | pfodApps/pfodDevices | WebStringTemplates | Java/J2EE | Unix | Torches | Superannuation | | About Us
 

Forward Logo (image)      

pfodApp controlled IR Temperature Meter with Menus
Android/Arduino based InfarRed(IR) Temperature Meter

by Matthew Ford 16th August 2016 (original 9th September 2013)
© Forward Computing and Control Pty. Ltd. NSW Australia
All rights reserved.

An Android Menu driven, Arduino based IR Temperature Meter using pfodApp
Select degsF / degsC display, Select Number of Samples to Average over,
Start Logging Readings to your Andriod
TM mobile
NO Android Programming required.

pfodApp IRTemp Meter with Menus

Updated: 16th August 2016 – Revised to use pfodParser library v2.37+, correct spelling and clarify saving of readings
Note: The screens shown here are pfodApp V1 screens. You should use pfodDesignerV2 to generate your own pfodApp V2 screens.

This project builds on pfodApp IRTemp Meter (Arduino/Android Bluetooth) by menus that allow you to select between Fahrenheit and Celsius display. Displays the averaged reading and lets you select the number of readings to average over. The reading are automatically saved to a file on your Android mobile for later transfer to your PC for further processing/plotting. The complete parts list is here.
No Android programming is required.
You can make this unit stand alone and portable by adding a 9V battery as described here.

This change will be done in two steps:- First the basic menu will be added to allow you to change between oF and oC and to start logging the reading. Then the averaged reading will be added to the display together with a sub-menu to allow you to select the number of samples to averaged. The complete sketch, pfodUnoIRTempMenus.ino, is here and also included in the examples for the Arduino pfodIRTemp library. Unzip pfodIRTemp.zip to your Arduino library directory.

Adding the Basic Menus

Above screen shots show the basic menus that will be added and the screen that the “Show readings” menu will open. Update, pfodApp V2 automatically saves reading to a file so the previous “Save readings ..” button has been renamed to the more accurate “Show readings”. The first part of the sketch with these basic menu items is here (pfodUnoIRBasicMenus.ino)

The previous sketch, pfodUnoIRTempData.ino, needs to a) handle more commands and b) send a main menu with more items and update the main menu when the reading is changed from Fahrenheit to Celsius.

Handling More Commands

First handling more commands, the top of the loop() method in the sketch becomes

  void loop() {
  byte  cmd = parser.parse();
  if (cmd != 0) { // got something
    if (cmd == '.') { // main menu request
      sendMainMenu();
    } else if (cmd == 'c') {
      switchScale();
      sendMainMenuUpdate();
    } else if (cmd == 's') {
      // open Streaming Raw Data screen
      Serial.print(F("{=IR Temp Readings\n use BACK button to return\n to main menu}"));
    } else { // we don't handle message
      Serial.print(F("{}")); // BUT always respond or pfodApp will timeout
    }
  }

This code add support for two new commands 'c' and 's' in addition to the existing request for main menu command '.'

When the Android pfodApp sends the message {c} the Arduino pfodDevice pfodParser will parse it and return 'c' in the cmd variable which will call switchScale and send back an update to the main menu with the current temperature reading in the new scale. The swichScale method is just

  void switchScale() {
    fahrenheit = !fahrenheit; // toggle from fahrenheit to Celsius 
  }

When the Android pfodApp sends the message {s}, the Arduino pfodDevice will send back the Streaming RawData screen message, {=IR Temp Readings\n use BACK button to return\n to main menu} to ask the Android pfodApp on the Android mobile to open the RawData screen which both displays the readings. pfodAppV2 automatically save all raw data to a file once it receives a response to the main menu request, {.}. Once started, the data is continued to be saved until the connection is closed. Note that the text to be displayed on this screen is broken into a number of lines using the newline char escape sequence, \n

Sending and Updating the Main Menu.

The code for the methods sendMainMenu() and sendMainMenuUpdate() is

void sendMainMenu() {
  Serial.print(F("{" // start message
                 "."));  // tell pfodApp this is a menu screen
  sendMainMenuWithLatestTemp();
}
// send the update to main menu
void sendMainMenuUpdate() {
  Serial.print(F("{" // start message
                 ":"));  // tell pfodApp this is an update to the existing menu screen
  sendMainMenuWithLatestTemp();
}

void sendMainMenuWithLatestTemp() {
  Serial.print(F("IR Temperature Sensor" // display name of menu
                 "`1000" // tell pfodApp to re-request again this menu after 1sec
                 "|t~IR Temperature\n")); // first menu time temp + reading
  if (fahrenheit) {
    Serial.print(irTemp.convertToFahrenheit(lastTemperatureReading));
    Serial.print(F("F"));
  } else {
    Serial.print(irTemp.convertToCelsius(lastTemperatureReading));
    Serial.print(F("C"));
  }
  Serial.print(F("|c~Switch to\n")); // next menu item
  if (fahrenheit) {
    Serial.print(F("Celsius (C)"));
  } else {
    Serial.print(F("Fahrenheit (F)"));
  }
  Serial.print(F("|s~Show readings" // last menu item
                 "}")); // close message
}

As you can see the only difference between the two methods is that {. starts the main menu while {: starts the update. The menu update message, {: , was designed for just this use, where after processing a command you want to just update the existing menu. Updating a menu can change the text displayed to the user and hide / unhide individual menu items by blanking / unblanking their display text. See the pfodSpecification for the details.

An interesting part of this menu (and its update) is the `1000 which tells the Android pfodApp to resend, every 1sec (1000mS), the command that returned this menu. This means every 1sec the Android pfodApp will resend the request for main menu message, {.} , and the Arduino pfodDevice will reply with its main menu containing the latest temperature reading. So the Andriod mobile display is constantly being updated with the current IR temperature.

The revised sketch with these basic menu changes is available here (pfodUnoIRBasicMenus.ino)

Adding the Averaged Reading and a Sub-Menu

The last change for this stage of the project is to average the readings and allow the user to select the number of samples to be used in the average.

Because the IR temperature sensor is so responsive, its reading jumps around. Taking an average of a number of readings provides a more stable display. This step will add an averaging method and a sub-menu to allow the user to select the number of samples to be averages. Because the averaging introduces a delay in the display, this code will also include a command to re-set the average value to the current reading and then continue to average from there.

The complete sketch, pfodUnoIRTempMenus.ino, is here. This sketch also replaces the F and C with the unicode characters for Fahrenheit and Celsius as shown in the screen shot at the top of this page.

When the “Set number of readings to be averaged” menu is selected, the Arduino pfodDevice sends back a single selection list screen message, {? , for the Android pfodApp to display. The message is created by the sendNumberReadingToAverageMenu() method

  void sendNumberReadingToAverageMenu() {
     Serial.print(F("{?m`")); // single selection list returns index of selection 0 to n
     Serial.print(idxNoSamples); // current selection
     Serial.print(F("~Set number of samples to be averaged" // prompt
                    "|Average 2 Readings|Average 4 Readings|Average 8 Readings|Average 16 Readings|Average 32 Readings" // choices
                    "}"));
  }



If the current index selection is 2, this message would be
{?m`2~Set number of samples to be averaged|Average 2 Readings|Average 4 Readings|Average 8 Readings|Average 16 Readings|Average 32 Readings}
See the pfodSpecification for the details of this message's format.

Which the Android pfodApp would display as

When the user selects another option, say 32 averages, and clicks save, the Android pfodApp sends back the message {m|4} where m is the command associated with this screen and 4 is the index (starting at 0) of the option selected.

In order to parse this message, the Arduino pfodDevice needs to use the pfodParser which handles the full range of pfod messages. So the includes at the top of the sketch are #include "pfodEEPROM.h" and #include "pfodParser.h" and a pfodParser is constructed, pfodParser parser;

The command handling code now needs to handle some more commands, 'a' , 'n', 'm'. The {a} command is returned when the user clicks on the IR Average menu item and it re-sets the average to the current reading. The {n} command is returned when the user selects the Set number of readings to be averaged” menu time and as shown above the Arduino pfodDevice returns a screen to allow the user to select the number of readings to average. The {m| ... } command is returned when the user has made a selection from the single selection list of samples to average. The number after the | indicates the index, starting at 0 of the users choice. e.g. {m|4} indicates the user selected the 32 readings choice.

For the 'm' command the code need to parse the number following the | and update the number of reading to be averaged. The pfodParser provides simple methods to do this argument parsing as shown below. Remember the call to parser.parse() will return 0 until the closing } of the pfod message is received. Then parser.parse(); will return the first byte of the command. All the commands here are only one byte so that is the complete command. The command handling code now looks like:-

  byte  cmd = parser.parse();
  if (cmd != 0) { // got something
    if (cmd == '.') { // main menu request
      sendMainMenu();
    } else if (cmd == 'c') {
      switchScale();
      sendMainMenuUpdate();
    } else if (cmd == (byte)'a') {
      // clear the average to current temp
      clearAverage(lastTemperatureReading);
      sendMainMenuUpdate(); // send updated menu with new average
    } else if (cmd == 's') {
      // open Streaming Raw Data screen
      Serial.print(F("{=IR Temp Readings\n use BACK button to return\n to main menu}"));
    } else if (cmd == (byte)'n') {
      sendNumberReadingToAverageMenu();
    } else if (cmd == (byte)'m') {
      byte* idxPtr = parser.getFirstArg(); // parse 1 arg as a number
      long longResult;
      parser.parseLong(idxPtr, &longResult); // only one arg
      idxNoSamples = (byte)longResult; // update current selection
      setNoReadingsToAverage((int)idxNoSamples); // set new average
      Serial.print(F("{}")); // always respond or pfodApp will timeout
    } else { // we don't handle message
      Serial.print(F("{}")); // BUT always respond or pfodApp will timeout
    }
  }

Conclusion

That completes the Uno version of the pfodIRTemp Meter. All these versions only required Arduino code changes. No Android programming was required. The same pfodApp was used throughout and is also used for other diverse functions see www.pfod.com.au for other projects.

Notice that the Arduino pfodDevice code does not keep track of the menu hierarchy. It is the Android pfodApp's job to do that. So that when the user has finished selecting the number of reading to average, the pfodDevice just processes the command and returns {} to the Android pfodApp. The pfodApp has kept track of from which menu the user chose the item that opened the number of averages selection screen. Then when that the pfodDevice returns {} the pfodApp knows to resends the command that will ask the pfodDevice for that menu again, in this case the main menu. This makes the Arduino code very simple even when there are nested menus. The Arduino code just processes each command it receives, ignoring how many menu hierarchies the user traversed to get to it.

The next stage in this project will be to make a battery powered portable version using an FioV3 board.



AndroidTM is a trademark of Google Inc. For use of the Arduino name see http://arduino.cc/en/Main/FAQ


The General Purpose Android/Arduino Control App.
pfodDevice™ and pfodApp™ are trade marks of Forward Computing and Control Pty. Ltd.


Forward home page link (image)

Contact Forward Computing and Control by
©Copyright 1996-2020 Forward Computing and Control Pty. Ltd. ACN 003 669 994