.

.

Bean Console

.



Bean Console is an input/output console to be used with the LightBlue Bean Bluetooth LE micro-controller board from Punch Through Design. The app allows you to communicate with the LightBlue Bean on an IOS device the way you would from the Serial Monitor within the Arduino IDE. However, the app also provides functionality not found in the Arduino IDE's Serial Monitor.

For information on (or to purchase) the LightBlue Bean visit https://punchthrough.com/bean/

v1.0.0 - Initial Release

FEATURES:



The Find Your Bean Screen

The Find Your Bean screen will show you a list of active and known Beans. When the app launches it automatically does a quick search for any active beans nearby. If you see the stop icon in the upper-left corner a search is in progress – you may tap the icon to stop searching for Beans. If you see the refresh icon in the upper-left corner the app is not currently searching – you may tap the icon to start searching for Beans.

You can press the information icon in the upper-right corner to get some information and links about the app and about the LightBlue Bean micro controller board.

The Bean list has three sections. The Active Known Beans section will contain Beans you have connected to before that were found available during the last scan for Beans. The New Beans section will show Beans discovered during the last scan that you have not yet connected to. You can select a Bean from either of these sections to attempt to connect to that Bean. The Inactive Known Beans section will list the names of Beans which you have connected to in the past, but that were not found during the last Bean scan. Selecting a Bean in this last section will do nothing. To forget a “known” Bean you can swipe to the left on that Bean in the list; this will present you with a “Forget” option.



The Bean Console Screen

The Bean Console screen is where you can interact with your LightBlue Bean micro controller Board.

Header

The header shows the name of the currently connected Bean and its battery voltage as reported by the LightBlue Bean Apple SDK. The settings icon will switch the lower section of the Bean Console screen to a settings panel. When the settings panel is visible the settings icon will be replaced with a controls icon . The controls icon will switch the settings panel back to the controls panel. To disconnect from the current Bean and return to the Find Your Bean screen press the close icon .

Console

The console section is where you will see Serial output from the LightBlue Bean and where you can send characters to the LightBlue Bean via Serial. The green-on-black output screen displays information received from the Bean. The text input field below the output screen is used to send characters to the Bean. If you hold your finger on the output screen for a moment you will notice the border turn yellow. While the border is yellow you can scroll up and down to review data that has scrolled off the top of the screen. In this mode you can also select text from the output screen to copy to the IOS device’s clipboard. To return to the active output screen clear any active text selection and then do not touch the output screen for three seconds.

To send characters to the Bean enter them in the text input field then press the “Send” button on the keyboard. There are settings (see below) that control whether (an) end-of-line character(s) are appended to the text input and whether the input is echoed to the output screen or not.

Controls Panel

The controls panel is not yet implemented, but it will work in conjunction with a future arduino library for the LightBlue Bean that will allow you to setup and use virtual LED, button, switch, etc. controls with the LightBlue Bean.

Settings Panel

The settings panel allows you to toggle the power to the arduino circuit on the LightBlue Bean. It also allows you to toggle whether input text is echoed to the output screen or not. You can set whether an end-of-line sequence should be appended to the data being sent to the Bean and whether the end-of-line sequence should be CR or CR/LF. Finally there is a section that will allow you to set or clear the Bean’s pairing PIN. Though the Bean can support PINs less than 100000 this app requires a PIN between 100000 and 999999.

Demo Sketch

The following arduino sketch can be used to demonstrate some of the things you can do using the Bean Console app:

unsigned long nLastScratchWrite = 0;
boolean bPrevConnected = false;
int nLoopsSinceInput = 15;
boolean bStreamnAccelData = false;
boolean bCounterOn = false;
uint8_t nCounter = 0;

void showMenu();
void menuReminder();
void cmdPrompt();
void accelReminder();
void clearScratchString( int nBank );
String readScratchString( int nBank );
void writeScratchString( int nBank, String strScratch );


void setup()
{
  Serial.begin();
  Serial.setTimeout(100);
  randomSeed(analogRead(0));
}

void loop()
{
  if (Bean.getConnectionState())
  {
    if (!bPrevConnected)
    {
      Bean.setLed(100,150,0);
      Bean.sleep(750);
      Bean.setLed(0,0,0);
      // Delay for serial gate timeout
      Bean.sleep(7000);
      Bean.setLed(000,180,0);
      Bean.sleep(250);
      Bean.setLed(0,0,0);
      bPrevConnected = true;
      showMenu();
      cmdPrompt();
    }

    if ( (millis() < nLastScratchWrite) || ( (millis() - nLastScratchWrite) > 5000) )
    {
      long nBank = random(5) + 1;   
      String strTemp = "Millis: ";
      strTemp += String(millis());
      writeScratchString( nBank, strTemp );
      nLastScratchWrite = millis();
    }

    if (Serial.available())
    {
      nLoopsSinceInput = 0;
      String strInput = "";
      char bInput[256];
      int nLength = 256;
      int nBytesRead = Serial.readBytesUntil(char(13), bInput, nLength);
      for (int n=0; n<nBytesRead; n++)
      {
        if (bInput[n] != char(13) && bInput[n] != char(10))
        {
          strInput = strInput + bInput[n];
        }
      }
      Serial.println( "" );
      delay(5);
      if (strInput == "")
      {
        // No Command so ignore
        int doh;
      }
      else if (strInput == "m")
      {
        showMenu();
        cmdPrompt();
      }
      else if (strInput == "t")
      {
        int8_t nTemp = Bean.getTemperature();
        // Convert the temperature reading to Fahrenheit
        int nTempF = ( ( nTemp * 9 ) / 5 ) + 32; // Convert to Fahrenheit
        String strOut = "Temperature: " + String(nTempF) + " degrees";
        Serial.println( strOut );
        delay(5);
        cmdPrompt();
      }
      else if (strInput == "v")
      {
        int16_t nVoltage = Bean.getBatteryVoltage();
        float fVoltage = float(nVoltage) / 100.0;
        char caVolts[10];
        dtostrf(fVoltage,1,2,caVolts);
        String strOut = "Voltage: ";
        strOut = strOut + caVolts;
        strOut = strOut + "V";
        Serial.println( strOut );
        delay(5);
        cmdPrompt();

      }
      else if (strInput == "c")
      {
        bCounterOn = !bCounterOn;
      }
      else if (strInput == "a")
      {
        bStreamnAccelData = !bStreamnAccelData;
      }
      else
      {
        Serial.println( "Unknown command." );
        delay(5);
        cmdPrompt();
      }
    }
    else
    {
      nLoopsSinceInput++;
      if (bStreamnAccelData)
      {
        if (nLoopsSinceInput >= 60)
        {
          nLoopsSinceInput = 0;
          accelReminder();
        }
      }
      else
      {
        if (nLoopsSinceInput >= 20)
        {
          nLoopsSinceInput = 0;
          menuReminder();
          cmdPrompt();
        }
      }
    }

    if (bCounterOn)
    {
        // Process our counter and send controls
        if (nCounter < 255)
        {
          nCounter++;
        }
        else
        { 
          nCounter = 0;
        }
        uint8_t output[18];
        output[0] = 255;  // This byte tells Bean Console the following data is for the Control Panel instead of the monitor window.
        output[1] = 8;    // This indicates how many command pairs to expect.
        // The following loop sets 8 control/value byte pairs -- 16 bytes total.
        for (int n = 1; n <= 8; n++)
        {
          uint8_t bit = (nCounter >> (8-n)) & 1;
          output[(n-1)*2+2] = n;
          output[(n-1)*2+3] = bit;
        }
        // Send the data to Bean Console so it can display the counter value in the virtual LEDs.
        Serial.write( output, 18 );
        delay(5);
    }

    if (bStreamnAccelData)
    {
      AccelerationReading acc = Bean.getAcceleration();
      String strOut = "X: ";
      strOut = strOut + acc.xAxis;
      strOut = strOut + " Y: ";
      strOut = strOut + acc.yAxis;
      strOut = strOut + " Z: ";
      strOut = strOut + acc.zAxis;
      Serial.println( strOut );
      delay(5);
      Bean.sleep(500);
    }
    else
    {
      Bean.sleep(1000);
    }
  }
  else
  {
    if (bPrevConnected)
    {
      Bean.setLed(100,0,0);
      Bean.sleep(100);
      Bean.setLed(0,0,0);
      bPrevConnected = false;
      bStreamnAccelData = false;
    }
    Bean.sleep(3000);
  }
}

void showMenu()
{
  String strMenu = "\r\nMENU\r\n";
  strMenu += "------------------\r\n";
  strMenu += "m - Show this menu\r\n";
  strMenu += "t - Display Bean's temperature\r\n";
  Serial.print( strMenu );
  delay(5);
  strMenu = "v - Display Bean's battery voltage\r\n";
  strMenu += "a - Start/Stop streaming accelerometer data\r\n";
//  strMenu += "p - Play a game\r\n\r\n";
  Serial.print( strMenu );
  delay(5);
  strMenu = "c - Byte counter on/off (uses LEDs)\r\n";
//  strMenu += "p - Play a game\r\n\r\n";
  Serial.print( strMenu );
  delay(5);
}

void cmdPrompt()
{
  Serial.print( "\r\nCommand: " );
  delay(5);
}

void menuReminder()
{
  Serial.print( "\r\nEnter \"m\" for menu." );
  delay(5);
}

void accelReminder()
{
  Serial.print( "<Send \"a\" to stop accelerometer data.>" );
  delay(5);
}

String readScratchString( int nBank )
{
  // Read the scratch bank
  ScratchData scratchRead = Bean.readScratchData( (uint8_t) nBank );
  clearScratchString( nBank );

  // Convert to a String object
  String strScratch = "";
  for (int i=0; i<scratchRead.length; i++)
  {
    strScratch += (String) (char) scratchRead.data[i];
  }

  return strScratch;
}

void writeScratchString( int nBank, String strScratch )
{
  // Convert the string to a uint8_t array
  uint8_t bufTemp[20];
  for ( int i=0; i<strScratch.length(); i++ )
  {
    bufTemp[i] = strScratch.charAt(i);
  }

  // Write string to scratch bank
  Bean.setScratchData( (uint8_t) nBank, bufTemp, strScratch.length() );

  return;
}

void clearScratchString( int nBank )
{
  // Write a blank space to the scratch bank
  uint8_t buffer[1] = { 0 };
  Bean.setScratchData( (uint8_t) nBank, buffer, 1 );

  return;
}