The LightBlue Bean is a legacy product and is no longer being sold

The Bean loader apps will continue to function, but no further updates will be provided. Updates to your OS may change Bluetooth functionality and therefore may break the functionality of the Bean apps.

Hardware files are available here.

We're proud to have helped people prototype their products with the Bean, and for all the incredible things they've built. The Bean was an incredibly fun and challenging product to work on, and we will miss it..

Our goal at Punch Through is to help companies develop products. Our consulting services and software products have been growing so quickly that they require our full focus and attention. If you're developing a connected product, we'd love to help in any way possible.

Reference

Bean Arduino Reference

This reference is for users writing Arduino sketches to run on Bean and Bean+. If you’re looking for more in-depth walkthroughs on how to use Bean’s features, check out the Bean Guides.

Accelerometer

Read acceleration values and configure the accelerometer’s sensitivity.

Bean.enableMotionEvent

Enable accelerometer interrupts

Parameters

Bean.disableMotionEvents

Disables all currently enabled accelerometer interrupts

Bean.checkMotionEvent

Checks to see if a particular acclerometer interrupt has occured. If the event occurs it sets a flag that can only be cleared by reading this function.

Parameters

Returns

Examples

This example sets off police lights on the Bean if motion is detected:
1234567891011121314151617181920212223242526272829303132333435// Create boolean to run loop persistently
bool motionDetected = false;
void setup() {
  // Enable low-g motion events to be detected
  Bean.enableMotionEvent(ANY_MOTION_EVENT);
  // Make sure accelerometer is in normal power mode
  if (Bean.getAccelerometerPowerMode() != VALUE_NORMAL_MODE) {
    // Set accelerometer power mode to normal
    Bean.setAccelerometerPowerMode(VALUE_NORMAL_MODE);
  }
  // Initially set LED to blank
  Bean.setLed(0, 0, 0);
}
void loop() {
  // Check for low-g movement
  if (Bean.checkMotionEvent(ANY_MOTION_EVENT) && !motionDetected) {
    motionDetected = true;
  } else if (!Bean.checkMotionEvent(ANY_MOTION_EVENT) && !motionDetected) {
    Bean.sleep(2000);  // Sleep for 2 seconds before rechecking
  }
  if (motionDetected) {
    // If motion is detected, blue/red lights will flash continuously
    Bean.setLed(255, 0, 0);
    Bean.sleep(100);
    Bean.setLed(0, 0, 255);
    Bean.sleep(100);
    Bean.setLed(255, 0, 0);
    Bean.sleep(100);
    Bean.setLed(0, 0, 255);
    Bean.sleep(100);
    Bean.setLed(255, 0, 0);
    Bean.sleep(100);
    Bean.setLed(0, 0, 255);
  }
}

Bean.getAccelerationX

Get the current value of the Bean accelerometer X axis.

Returns

  • int16_t

    a 10-bit value corresponding to the current X axis acceleration

Bean.getAccelerationY

Get the current value of the Bean accelerometer Y axis.

Returns

  • int16_t

    a 10-bit value corresponding to the current Y axis acceleration

Bean.getAccelerationZ

Get the current value of the Bean accelerometer Z axis.

Returns

  • int16_t

    a 10-bit value corresponding to the current Z axis acceleration

Bean.getAcceleration

Get the current value of all axes and the current sensitivity setting from the Bean accelerometer.

Returns

  • AccelerationReading

    an AccelerationReading object containing current acceleration and sensitivity

Bean.accelRegisterWrite

Low level function for writing directly to the accelerometers registers.

Parameters

  • uint8_t reg

    the register to write to

  • uint8_t value

    the value to write to the register

Bean.accelRegisterRead

Low level function for reading the accelerometers register directly

Parameters

  • uint8_t reg

    the register to read

  • uint8_t length

    the number of bytes to read starting at that register

  • uint8_t * value

    a pointer to a user supplied array to fill with values

Returns

  • int

    the number of bytes actually read

Examples

This example uses a Bean as a motion alarm by reading/writing to the accelerometer register directly:
123456789101112131415161718192021222324252627282930313233343536373839// Create boolean to run loop persistently
bool motionDetected = false;
void setup() {
  // Enable low-g motion events to be detected
  Bean.enableMotionEvent(ANY_MOTION_EVENT);
  // (The next two lines are equivalent to "uint8_t value = Bean.getAccelerometerPowerMode()")
  uint8_t value;
  Bean.accelRegisterRead(REG_POWER_MODE_X11, 1, &value);
  if (value != VALUE_NORMAL_MODE) {
    // Set accelerometer power mode to normal power mode if it isn't already
    // (This is the same as "Bean.setAccelerometerPowerMode(VALUE_NORMAL_MODE)")
    Bean.accelRegisterWrite(REG_POWER_MODE_X11, VALUE_NORMAL_MODE);
  }
}
void loop() {
  // Check for low-g movement
  if (Bean.checkMotionEvent(ANY_MOTION_EVENT) && !motionDetected) {
    motionDetected = true;
  } else if (!Bean.checkMotionEvent(ANY_MOTION_EVENT) && !motionDetected) {
    Bean.sleep(2000);  // Sleep for 2 seconds before rechecking
  }
  if (motionDetected) {
    // If motion is detected, blue/red lights will flash continuously
    Bean.setLed(255, 0, 0);
    Bean.sleep(500);
    Bean.setLed(0, 0, 255);
    Bean.sleep(500);
    Bean.setLed(255, 0, 0);
    Bean.sleep(500);
    Bean.setLed(0, 0, 255);
    Bean.sleep(500);
    Bean.setLed(255, 0, 0);
    Bean.sleep(500);
    Bean.setLed(0, 0, 255);
    Bean.sleep(500);
    Serial.print("Motion has been detected; ");
    Serial.println();
  }
}

Bean.getAccelerationRange

Get the current sensitivity setting of the Bean accelerometer.

Returns

  • uint8_t

    2, 4, 8, or 16, corresponding to ±2g, ±4g, ±8g, or ±16g

Bean.setAccelerationRange

Configure the sensitivity of the Bean accelerometer.

Parameters

  • uint8_t range

    2, 4, 8, or 16, corresponding to ±2g, ±4g, ±8g, or ±16g

Examples

This example prints out the acceleration values associated with high and low g-force values:
123456789101112131415161718192021222324252627282930313233343536373839404142void setup() {
  // Enable motion events to see how they're calibrated
  Bean.enableMotionEvent(LOW_G_EVENT);
  Bean.enableMotionEvent(HIGH_G_EVENT);
  // Configure accelerometer to sense ±16g if it's not set already
  if (Bean.getAccelerationRange() != 16) {
    Bean.setAccelerationRange(16);
  }
}
void loop() {
  // Sleep forever while transmitting iBeacon location data
  if (Bean.checkMotionEvent(HIGH_G_EVENT)) {
    Serial.print("High-g event detected: ");
    printAcceleration(Bean.getAcceleration());
    // Blink green LED
    Bean.setLed(0, 255, 0);
    Bean.sleep(1000);
  } else if (Bean.checkMotionEvent(LOW_G_EVENT)) {
    Serial.print("Low-g event detected: ");
    printAcceleration(Bean.getAcceleration());
    // Blink yellow LED
    Bean.setLed(255, 255, 0);
    Bean.sleep(1000);
  } else {
    Serial.print("No movement detected: ");
    printAcceleration(Bean.getAcceleration());
    // Blink red LED
    Bean.setLed(255, 0, 0);
    Bean.sleep(1000);
  }
  Bean.sleep(1000);  // Sleep and recheck every second
}
void printAcceleration(AccelerationReading acceleration) {
  // Print axes of acceleration in a nice-looking way
  Serial.print("(x= ");
  Serial.print(acceleration.xAxis);  // Same as getAccelerationX()
  Serial.print(", y= ");
  Serial.print(acceleration.yAxis);  // Same as getAccelerationY()
  Serial.print(", z= ");
  Serial.print(acceleration.zAxis);  // Same as getAccelerationZ()
  Serial.println(")");
}

Bean.setAccelerometerPowerMode

Set power mode of the accelerometer Power modes: Normal mode: 0x00 (~140uA) Suspend mode: 0x80 (~0.5uA) Low Power 10ms: 0x54 (~16.4uA) Low Power 100ms: 0x5A (~2.3uA) Low Power 1s: 0x5E (~0.7uA)

Parameters

  • uint8_t mode

    the power mode of the accelerometer

Bean.getAccelerometerPowerMode

Get power mode of the accelerometer Power modes: Normal mode: 0x00 (~140uA) Suspend mode: 0x80 (~0.5uA) Low Power 10ms: 0x54 (~16.4uA) Low Power 100ms: 0x5A (~2.3uA) Low Power 1s: 0x5E (~0.7uA)

Returns

  • uint8_t

    the power mode of the accelerometer

LED

Set the RGB LED color and check what it’s currently showing.

Bean.setLed

Set intensity values for the color channels of the Bean RGB LED. 0 is off and 255 is on.

Parameters

  • uint8_t red

    the intensity of the red LED. 0 is off and 255 is on.

  • uint8_t green

    the intensity of the green LED. 0 is off and 255 is on.

  • uint8_t blue

    the intensity of the blue LED. 0 is off and 255 is on.

Examples

This example sets the LED to white (all channels on, full intensity):
12345678
void setup() {
  Bean.setLed(255, 255, 255);
}

void loop() {
  Bean.sleep(1000);
}

Bean.getLed

Get current intensity values for the color channels of the Bean RGB LED.

Returns

  • LedReading

    LedReading struct that contains an integer representation of each color.

Examples

This example shows the usage of the getLed() function and how to interperet the return value.
1234567891011121314void setup() {
  // Serial port is initialized automatically; we don't have to do anything
}

void loop() {
  LedReading rgbSetting = Bean.getLed();
  Serial.print("  Red: ");
  Serial.println(rgbSetting.red);
  Serial.print("Green: ");
  Serial.println(rgbSetting.green);
  Serial.print(" Blue: ");
  Serial.println(rgbSetting.blue);
  Bean.sleep(2000);
}

Bean.getLedRed

Get intensity of the red channel of the Bean RGB LED. 0 is off and 255 is on.

Returns

  • uint8_t

    0 for off and 255 for on.

Bean.getLedGreen

Get intensity of the green channel of the Bean RGB LED. 0 is off and 255 is on.

Returns

  • uint8_t

    0 for off and 255 for on.

Bean.getLedBlue

Get intensity of the blue channel of the Bean RGB LED. 0 is off and 255 is on.

Returns

  • uint8_t

    0 for off and 255 for on.

Bean.setLedRed

Set intensity of the red channel of the Bean RGB LED. 0 is off and 255 is on.

Parameters

  • uint8_t intensity

    the intensity of the red LED. 0 is off and 255 is on.

Bean.setLedGreen

Set intensity of the green channel of the Bean RGB LED. 0 is off and 255 is on.

Parameters

  • uint8_t intensity

    the intensity of the green LED. 0 is off and 255 is on.

Bean.setLedBlue

Set intensity of the blue channel of the Bean RGB LED. 0 is off and 255 is on.

Parameters

  • uint8_t intensity

    the intensity of the blue LED. 0 is off and 255 is on.

Observer

Functions related to Observer mode. Observer role allows the Bean to listen for advertisements. As a peripheral, the Bean cannot send scan response requests, but it can listen for undirected advertisements. Paired with the custom advertising role, you can have two Beans interact with each other. This role works even when the Bean is connected.

Bean.getObserverMessage

Listens for advertisements and fills an ObserverAdvertisementInfo message with the first advertisement it sees This function blocks until it receives a message or times out.

Parameters

Returns

  • int

    -1 if there was a failure, 1 if there was a success

Examples

This sketch (observer.ino) demonstrates Bean’s observer role functionality. When a Bean running this sketch is near a Bean running advertiser.ino, it will change its LED to reflect the state of the LED on the advertising Bean.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556void setup() {
  // Serial port is initialized automatically; we don't have to do anything
}

uint8_t expectedPacket[] = {
    // general discoverable mode advertises indefinitely
    0x02,  // length of this data
    GAP_ADTYPE_FLAGS,
    GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,

    // two-byte broadcast
    0x03,  // length of this data including the data type byte
    GAP_ADTYPE_MANUFACTURER_SPECIFIC,
    0xAC  // arbitrary data so we can make sure this is
          // the Bean we're looking for
};

void loop() {
  uint32_t start = millis();

  ObserverAdvertisementInfo info;
  int res = Bean.getObserverMessage(&info, 2000);
  if (res == 1) {
    Serial.print(info.eventType);
    Serial.print(',');
    Serial.print(info.addrType);
    Serial.print(',');
    Serial.print("addr: ");
    for (int i = 0; i < 6; i++) {
      Serial.print(info.addr[i]);
      Serial.print(',');
    }
    Serial.print("  advData: ");
    for (int i = 0; i < info.dataLen; i++) {
      Serial.print(info.advData[i], HEX);
      Serial.print(',');
    }
    Serial.println();

    // check to see if this packet is form the custom advertiser
    bool isEqual = true;
    for (int i = 0; i < sizeof(expectedPacket) - 1; i++) {
      if (expectedPacket[i] != info.advData[i]) {
        isEqual = false;
      }
    }
    if (isEqual) {
      Serial.println("Custom adv found");
      if (info.advData[6] == 0) {
        Bean.setLedGreen(60);
      } else {
        Bean.setLedGreen(0);
      }
    }
  }
}

Scratch

Read and write arbitrary data using pre-defined BLE characteristics. Scratch characteristics are Bluetooth Low Energy characteristics that Bean provides for arbitrary use by developers. Each characteristic can hold up to 20 bytes due to BLE restrictions. Scratch characteristics will trigger Notify events on BLE Central clients when they are changed by Bean’s Arduino sketch. Bean sketches must poll to find out when a client changes scratch characteristic data. Bean and Bean+ have five scratch characteristics. All scratch chars are contained in a single BLE service.
  • Scratch Service UUID: a495ff20-c5b1-4b44-b512-1370f02d74de
  • Scratch Characteristic UUIDs:
    1. a495ff21-c5b1-4b44-b512-1370f02d74de
    2. a495ff22-c5b1-4b44-b512-1370f02d74de
    3. a495ff23-c5b1-4b44-b512-1370f02d74de
    4. a495ff24-c5b1-4b44-b512-1370f02d74de
    5. a495ff25-c5b1-4b44-b512-1370f02d74de
In the below methods, behavior is undefined when the bank parameter is not 1, 2, 3, 4, or 5.

Bean.setScratchData

Set the data in a scratch characteristic. Triggers a BLE Notify event for connected clients.

Parameters

  • uint8_t bank

    The index of the destination scratch char: 1, 2, 3, 4, or 5

  • const uint8_t * data

    An array of bytes or uint8_ts to be copied into the scratch char

  • uint8_t dataLength

    The number of bytes to copy from data

Returns

  • bool

    Success: false if dataLength is greater than 20, true otherwise

Examples

This example reads two of Bean’s analog pins and writes the values to two scratch characteristics:
1234567891011121314151617181920212223242526272829303132void setup() {
  // We don't need to set anything up here
}

void loop() {
  // Create a 2-byte buffer to hold our analog value when we split it into bytes
  uint8_t buffer[2];

  // Read 10-bit values from A0 and A1
  uint16_t an0 = analogRead(A0);
  uint16_t an1 = analogRead(A1);

  // Split A0's 10-bit value into two bytes and store in the buffer:
  // [<least significant 8 bits>, <most significant two bits>]
  buffer[0] = an0 & 0xFF;
  buffer[1] = an0 >> 8;

  // Store those two bytes in scratch characteristic 1
  Bean.setScratchData(1, buffer, 2);

  // Do the same as above: split A1...
  buffer[0] = an1 & 0xFF;
  buffer[1] = an1 >> 8;

  // ...and store in scratch characteristic 2
  Bean.setScratchData(2, buffer, 2);

  // Sleep for 3 seconds
  // If you're connected to this Bean in LightBlue,
  // you should see Notify events firing every 3 seconds
  Bean.sleep(10000);
}

Bean.setScratchNumber

Write a 32-bit (four-byte) value into a scratch characteristic. Triggers a BLE Notify event for connected clients.

Parameters

  • uint8_t bank

    The index of the destination scratch char: 1, 2, 3, 4, or 5

  • uint32_t data

    The 32-bit value to be written into the scratch char

Returns

  • bool

    Success: always returns true, since all 32-bit numbers are under 20 bytes in length

Examples

This example writes a value to and reads a value from a scratch characteristic:
12345678910111213141516171819void setup() {
  // Serial port is initialized automatically; we don't have to do anything
}

void loop() {
  // Write a 32-bit number to scratch characteristic 1
  // Connect to Bean with LightBlue to view the hex bytes
  Bean.setScratchNumber(1, millis());
  // Then wait a bit
  Bean.sleep(250);

  // Read the number back and print it via serial
  uint32_t number = Bean.readScratchNumber(1);
  Serial.print("Number: ");
  Serial.println(number);

  // Then wait a bit and try again
  Bean.sleep(750);
}

Bean.readScratchData

Read the data from a scratch characteristic.

Parameters

  • uint8_t bank

    The index of the source scratch char: 1, 2, 3, 4, or 5

Returns

  • ScratchData

    The contents of the scratch characteristic

Examples

This example polls a scratch characteristic and blinks Bean’s LED if the value changes:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647// Holds the last data we read from scratch characteristic 1
ScratchData lastScratch;

// Compare two ScratchData objects.
// Return true if they contain the same bytes in the same order.
bool compareScratch(ScratchData *scratch1, ScratchData *scratch2) {
  // If they contain different numbers of bytes, they can't be equal,
  // so return false
  if (scratch1->length != scratch2->length) {
    return false;
  }

  // Compare each byte in order and return false if two bytes don't match
  for (int i = 0; i < scratch1->length; i++) {
    if (scratch1->data[i] != scratch2->data[i]) {
      return false;
    }
  }

  // If we've gotten this far, every byte in both ScratchData objects matches
  return true;
}

void setup() {
  // We don't need to set anything up here
}

void loop() {
  // Read data from scratch characteristic 1
  ScratchData thisScratch = Bean.readScratchData(1);

  // Compare the data we just read with the data we saw last time
  bool matched = compareScratch(&thisScratch, &lastScratch);

  // Save the data we just read for our next comparison
  lastScratch = thisScratch;

  if (!matched) {
    // Set the LED to green for 1 second if the data has changed
    Bean.setLed(0, 255, 0);
    Bean.sleep(1000);
    Bean.setLed(0, 0, 0);
  } else {
    // Otherwise, just sleep for one second and check again
    Bean.sleep(1000);
  }
}

Bean.readScratchNumber

Read a 32-bit (four-byte) value from a scratch characteristic.

Parameters

  • uint8_t bank

    The index of the source scratch char: 1, 2, 3, 4, or 5

Returns

  • long

    The number of the scratch characteristic

Examples

This example writes a value to and reads a value from a scratch characteristic:
12345678910111213141516171819void setup() {
  // Serial port is initialized automatically; we don't have to do anything
}

void loop() {
  // Write a 32-bit number to scratch characteristic 1
  // Connect to Bean with LightBlue to view the hex bytes
  Bean.setScratchNumber(1, millis());
  // Then wait a bit
  Bean.sleep(250);

  // Read the number back and print it via serial
  uint32_t number = Bean.readScratchNumber(1);
  Serial.print("Number: ");
  Serial.println(number);

  // Then wait a bit and try again
  Bean.sleep(750);
}

Sleep

Bean power management functions to help save battery life.

Bean.sleep

Sleep for a period of time. This method puts the ATmega chip to sleep until it is woken by the LBM313 at the requested time. Bean can be woken from sleep by the following:
  • The requested sleep time elapses
  • A serial message is received from a connected client
  • A client connects to Bean while wake on connect is enabled
  • A pin change interrupt occurs
Bean.sleep() is more power-efficient than Arduino sleep() because it puts the ATmega into a low-power mode known as “power-down”. This disables the ATmega’s internal timers, so functions like millis() will not track time elapsed during Bean.sleep(). The ATmega can take up to 7 ms to wake from Bean.sleep(). If you are looking for more precise timings, please consider using delay() or delayMicroseconds(). For more information on low-power mode on the ATmega328, check out this Sparkfun tutorial.

Parameters

  • uint32_t duration_ms

    The duration to sleep for, in milliseconds

Examples

This example turns on Bean’s LED, sleeps for one second, turns off Bean’s LED and sleeps for four more seconds, then repeats:
12345678910111213141516void setup() {
  // We don't need to set anything up here
}

void loop() {
  // Check if LED is on
  if (Bean.getLedGreen() == 0) {
    // LED is off. Turn LED on and sleep for 1 second
    Bean.setLed(0, 255, 0);
    Bean.sleep(1000);
  } else {
    // LED is on. Turn LED off and sleep for 4 seconds
    Bean.setLed(0, 255, 0);
    Bean.sleep(4000);
  }
}

Bean.keepAwake

Enable or disable keep-awake mode. By default, the Bean radio sleeps frequently to conserve power. Enabling keep-awake forces the LBM into wake mode and decreases latency between the LBM313 and the ATmega. This may be useful if you are having trouble with latency between an event and a Bluetooth transmission: for example, to decrease the time between Bean reading a pin change event and sending a Bluetooth message. Enabling keep-awake may signficantly decrease battery life. Use with caution.

Parameters

Examples

This example keeps the Bean awake to reduce latency between reading a pinstate and transmitting Bluetooth information:
1234567891011121314void setup() {
  // Keep Bean awake to reduce latency between certain events
  Bean.keepAwake(true);
  pinMode(0, INPUT_PULLUP);
}
void loop() {
  // Read digital pin 0
  if (!digitalRead(0)) {
    // D0 is LOW; check to see if BLE connected to any devices
    bool connectionState = Bean.getConnectionState();
    Serial.println(connectionState);  // True if connected to a device, false if not
  }
  Bean.sleep(1000);  // Sleep for 1 second
}

Bean.enableWakeOnConnect

Enable or disable wake on connect. By default, Bean does not wake up when a BLE client connects.

Parameters

  • bool enable

    true to enable wake on connect, false to disable

Examples

This example wakes Bean when a client connects, waits for the client to disconnect, and sleeps on disconnect:
123456789101112131415161718192021222324252627282930void setup() {
  // Configure Bean to wake up when a client connects
  Bean.enableWakeOnConnect(true);
}

// Loop runs once at program start.
// When a client connects, Bean wakes up and runs loop again.
// Loop continues to run as long as a client is connected.

void loop() {
  // Check if client has disconnected
  bool connected = Bean.getConnectionState();

  if (connected) {
    // Client connected: set LED to green
    Bean.setLed(0, 255, 0);

  } else {
    // Client disconnected: turn off LED
    Bean.setLed(0, 0, 0);

    // This sketch runs only when a client is connected.
    // This might be useful for interactive installations, where you don't want
    // Bean to spend any power unless someone is actively connected.

    // Sleep for a long time to conserve power.
    // 0xFFFFFFFF = 4,294,967,295 milliseconds = 49 days
    Bean.sleep(0xFFFFFFFF);
  }
}

Advertising

Set and verify the Bean BLE advertising configuration. Bean makes itself visible to BLE Central devices by broadcasting BLE advertising packets. If advertising is disabled, Central devices will not be able to find or connect to Bean. Advertising is automatically enabled when Bean is powered on or resets. However, uploading a sketch that disables advertising indefinitely may make it impossible to connect to Bean. If this happens to you, see this guide (TODO: ADD GUIDE + LINK) to clear the sketch stored on Bean.

Bean.setBeanName

Set the advertising name of the Bean. BLE advertising names are truncated at 20 bytes.

Parameters

Examples

This example changes Bean’s name based on its temperature:
123456789101112131415161718192021void setup() {
  // Disable writing to NVRAM to preserve its lifespan,
  // since we are setting a new Bean name every 15 seconds
  Bean.enableConfigSave(false);
}

void loop() {
  // Get the temperature
  int temperature = Bean.getTemperature();

  // Build a new name for Bean using the temperature
  String name = "Temp is ";
  name += temperature;
  name += " C";

  // Set Bean's new name
  Bean.setBeanName(name);

  // Sleep for 15 seconds, then read the temperature again
  Bean.sleep(15000);
}

Bean.getBeanName

Read the currently-advertised name of the Bean.

Returns

  • const char *

    The Bean name as a char array, null-terminated

Examples

This example prints Bean’s name to Virtual Serial every two seconds:
12345678910111213141516void setup() {
  // Set up serial communication
  Serial.begin(57600);
}

void loop() {
  // Retrieve the name of this Bean
  const char *name = Bean.getBeanName();

  // And print it
  Serial.print("My name is ");
  Serial.println(name);

  // Then sleep for 2 seconds
  Bean.sleep(2000);
}

Bean.setAdvertisingInterval

Sets the Beans advertisement interval. This is useful if you are trying to optimize battery life at the exense of advertisement rates and can also be useful for increasing beacon advertisement rates.

Parameters

  • uint16_t interval_ms

    length of advertisement interval in milliseconds. Minimum of BEAN_MIN_ADVERTISING_INT_MS and max of BEAN_MAX_ADVERTISING_INT_MS

Bean.enableAdvertising

Enable or disable BLE advertising for a specific duration. Advertising is automatically enabled when Bean is powered on or resets. Configuration changes made by calling this method are not stored in non-volatile memory.

Parameters

  • bool enable

    true to enable advertising, false to disable

  • uint32_t timer

    the duration to enable/disable advertising, in milliseconds

Examples

This example disables advertising for 10 seconds when digital pin 0 is pulled low:
1234567891011121314void setup() {
  // Configure digital pin 0 as an input in pullup mode
  pinMode(0, INPUT_PULLUP);
}

void loop() {
  // Read digital pin 0
  if (!digitalRead(0)) {
    // D0 is LOW; disable advertising for 10 seconds
    Bean.enableAdvertising(false, 10000);
  }

  Bean.sleep(1000);  // Sleep for 1 second
}

Bean.enableAdvertising

Enable or disable BLE advertising. Advertising is automatically enabled when Bean is powered on or resets. Configuration changes made by calling this method are not stored in non-volatile memory.

Parameters

  • bool enable

    true to enable advertising, false to disable

Examples

This example disables advertising when digital pin 0 is pulled low and enables it otherwise:
1234567891011121314151617void setup() {
  // Configure digital pin 0 as an input in pullup mode
  pinMode(0, INPUT_PULLUP);
}

void loop() {
  // Read digital pin 0
  if (digitalRead(0)) {
    // D0 is HIGH; enable advertising
    Bean.enableAdvertising(true);
  } else {
    // D0 is LOW; disable advertising
    Bean.enableAdvertising(false);
  }

  Bean.sleep(1000);  // Sleep for 1 second
}

Bean.getAdvertisingState

Check whether the Bean is currently advertising.

Returns

  • bool

    true if Bean is advertising, false if Bean is not advertising

Examples

This example toggles Bean’s advertising every 15 seconds and indicates the current advertising status with the LED:
12345678910111213141516171819void setup() {
  // We don't need to set anything up here
}

void loop() {
  bool advertising = Bean.getAdvertisingState();

  if (advertising) {
    // Bean is currently advertising.
    // Disable advertising and set the LED to red.
    Bean.setLed(255, 0, 0);
  } else {
    // Bean is not advertising.
    // Enable advertising and set the LED to green.
    Bean.setLed(0, 255, 0);
  }

  Bean.sleep(15000);  // Sleep for 15 seconds
}

Bean.enableCustom

Enables custom advertisement. The Bean will enter a rotating advertisement mode where it will advertise as a bean for a few moments then advertise whatever is in the custom advertisement packet and back again

Bean.disableCustom

Disables custom advertisement.

Bean.setCustomAdvertisement

Sets the custom advertisement packet. The max length is 31 bytes. The first 3 bytes specify the advertisement mode. They take the form 0x2, GAP_ADTYPE_FLAGS, any sum of advertisement types (as defined by AdvertisementType) All following data are up to the user to define and follow the pattern of [length, AdvertisementDataTypes, data1, data2, …] where length includes the number of data plus 1 (for the AdvertisementDataTypes) The data can be chained together into the single buffer up to the maxiumum length. For example: [0x02, GAP_ADTYPE_FLAGS, GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED + GAP_ADTYPE_FLAGS_GENERAL, 0x02, GAP_ADTYPE_MANUFACTURER_SPECIFIC, 42, 0x02, GAP_ADTYPE_POWER_LEVEL, 10, …]

Parameters

  • uint8_t * buf

    a buffer full of data to advertise

  • int len

    the length of the buffer

Examples

This sketch (advertiser.ino) will enable a custom advertisement for the Bean. It will broadcast the following packet: {0x02, GAP_ADTYPE_FLAGS (0x01), GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED (0x06), 0x03, GAP_ADTYPE_MANUFACTURER_SPECIFIC (0xFF), 0xAC, 0x0n} When pin 0 is pulled to ground, Bean will toggle the green LED. It will also set the last byte in the advertisement packet to reflect the LED’s on state. When used in conjunction with observer.ino, the observer Bean will see this packet and will turn its light on.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950// debounce code
int buttonState;            // the current input
int lastButtonState = LOW;  // the previous read input
long lastDebounceTime = 0;  // the last time we flipped the output pin
long debounceDelay = 50;    // how long to debounce for

static uint8_t customAdvertData[] = {
    // general discoverable mode advertises indefinitely
    0x02,  // length of this data
    GAP_ADTYPE_FLAGS,
    GAP_ADTYPE_FLAGS_GENERAL | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,

    // two-byte broadcast
    0x03,  // length of this data including the data type byte
    GAP_ADTYPE_MANUFACTURER_SPECIFIC,
    0xAC,  // arbitrary data so we can make sure this is
           // the Bean we're looking for
    0x00};

bool enabled = true;
void setup() {
  Bean.setCustomAdvertisement(customAdvertData, sizeof(customAdvertData));
  Bean.enableCustom();
  Bean.enableConfigSave(false);
  Bean.setAdvertisingInterval(100);
  pinMode(0, INPUT_PULLUP);
}

void loop() {
  // Read the state of pin 0 and debounce in software
  int reading = digitalRead(0);
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != buttonState) {
      buttonState = reading;

      if (buttonState == LOW) {
        // Pin 0 was pulled to ground (button was pressed)
        enabled = !enabled;
        Bean.setLedGreen(enabled ? 0 : 255);
        customAdvertData[6] = enabled ? 1 : 0;
        Bean.setCustomAdvertisement(customAdvertData, sizeof(customAdvertData));
      }
    }
  }
  lastButtonState = reading;
}

iBeacon

Let your Bean act as an iBeacon, a way to convey real-world location to iOS devices. Bean supports a limited subset of UUIDs available to iBeacon devices. A Bean iBeacon UUID is made up of 16 user-configurable bits and 112 preconfigured bits, where xx represents a user-configurable byte: A495xxxx-C5B1-4B44-B512-1370F02D74DE Major and minor IDs are used to identify the iBeacon with greater accuracy than with the UUID alone, and are both unsigned integers between 0 and 66535 Using iBeacon features will, by default, write to Bean’s NVRAM. The NVRAM has a limited number of writes. Use enableConfigSave to store settings temporarily and conserve NVRAM writes.

Bean.enableiBeacon

Works very similarly to setBeaconEnable. The primary difference being that enableiBeacon adds the beacon advertisement to a rotating adverisement instead of overrwriting the current standard Bean advertisement. Parameters are still set with the setBeaconParameters function.

Bean.setBeaconParameters

Configure Bean’s iBeacon UUID, major ID, and minor ID. Each of these parameters, including UUID, takes 16-bit unsigned values. For more information on UUID, major, and minor values, see this iBeacon FAQ.

Parameters

  • uint16_t uuid

    The 16-bit value used to set part of the iBeacon UUID. For example: Passing 0xABCD to uuid will set the Bean’s UUID to A495ABCD-C5B1-4B44-B512-1370F02D74DE.

  • uint16_t major_id

    The minor ID of the iBeacon

  • uint16_t minor_id

Examples

This example configures iBeacon and uses the Bean only to advertise and transmit iBeacon data:
123456789101112131415161718void setup() {
  /* Configure beacon with:
  *  ----------------------
  *  UUID: A495-BEEF-C5B1-4B44-B512-1370F02D74DE
  *  Major ID: 0 (Any unsigned int 0-66535)
  *  Minor ID: 65535 (Any unsigned int 0-66535)
  */
  Bean.setBeaconParameters(0xBEEF, 0, 999);
  // Enable iBeacon
  Bean.setBeaconEnable(true);
}
void loop() {
  // Blink LED to verify the sketch is working
  Bean.setLed(0, 0, 100);
  Bean.sleep(100);
  Bean.setLed(0, 0, 0);
  Bean.sleep(5000);
}

Bean.setBeaconEnable

Enable or disable iBeacon functionality.

Parameters

  • bool beaconEnable

    true to enable iBeacon, false to disable

Battery

Read the Bean’s battery level.

Bean.getBatteryLevel

Get the current battery level, in percent.

Returns

  • uint8_t

    a value in the range 0 to 100: 0 = 1.95 V, 100 = 3.53 V

Bean.getBatteryVoltage

Get the current battery voltage, in volts. Accuracy is ±0.01 V.

Returns

  • uint16_t

    a value in the range 195 to 353: 195 = 1.95 V, 353 = 3.53 V

Examples

This example will display a Bean’s respective current battery level and voltage every 5 seconds:
1234567891011121314151617181920212223242526272829void setup() {
  // Serial port is initialized automatically; we don't have to do anything
}
void loop() {
  int batteryPercentage = Bean.getBatteryLevel();  // Between 0 and 100
  int batteryVoltage = Bean.getBatteryVoltage();   // Between 191 and 353 (1.91V-3.53V)
  Serial.print("The remaining battery life is: %");
  Serial.println(batteryPercentage);
  blinkLedBasedOnBatteryLevel(batteryPercentage);
  Serial.print("The current battery voltage is: ");
  Serial.print(batteryVoltage / 100);
  Serial.println("V");
  Bean.sleep(5000);  // Sleep for 5 seconds before repeating
}
void blinkLedBasedOnBatteryLevel(int batteryPercentage) {
  if (batteryPercentage > 80) {
    Bean.setLed(0, 255, 0);
  } else if (batteryPercentage > 60) {
    Bean.setLed(255, 255, 0);
  } else if (batteryPercentage > 40) {
    Bean.setLed(255, 150, 0);
  } else if (batteryPercentage > 20) {
    Bean.setLed(255, 75, 0);
  } else {
    Bean.setLed(255, 0, 15);
  }
  Bean.sleep(100);
  Bean.setLed(0, 0, 0);
}

Temperature

Read the ambient temperature of the Bean.

Bean.getTemperature

Get the current temperature of the Bean, in degrees Celsius. The Bean uses the BMA250 (datasheet) for temperature readings.

Returns

  • int8_t

    temperature, between -40 and 88 degrees Celsius

Examples

This example changes the color of the LED based on the temperature reading of the Bean:
1234567891011121314151617181920void setup() {
  // Serial port is initialized automatically; we don't have to do anything
}
void loop() {
  // Get temperature reading
  int temperature = Bean.getTemperature();
  // Set LED color based on temperature of the Bean
  if (temperature > 80) {
    Bean.setLed(255, 0, 0);  // Set LED red
  } else if (temperature > 60) {
    Bean.setLed(255, 150, 0);  // Set LED orange
  } else if (temperature > 40) {
    Bean.setLed(255, 255, 0);  // Set LED yellow
  } else if (temperature > 20) {
    Bean.setLed(0, 255, 0);  // Set LED green
  } else {
    Bean.setLed(0, 0, 255);  // Set LED blue
  }
  Bean.sleep(5000);  // Sleep for 5 seconds before rechecking temperature
}

Connection

Work with active BLE Central devices that connect to Bean.

Bean.disconnect

Terminate the connection between Bean and the connected BLE Central device. If no Central device is connected, this method does nothing.

Bean.getConnectionState

Check if any BLE Central devices are currently connected to Bean.

Returns

  • bool

    true if a device is connected, false otherwise

Examples

This example blinks the LED on the Bean green if connected, red if disconnected:
123456789101112131415161718void setup() {
  // Nothing to initialize up here
}
void loop() {
  // If Bean is connected to a device, blink green LED
  if (Bean.getConnectionState() == true) {
    Bean.setLed(0, 255, 0);
    Bean.sleep(250);
    Bean.setLed(0, 0, 0);
    // If Bean is not connected, blink red LED
  } else if (Bean.getConnectionState() == false) {
    Bean.setLed(255, 0, 0);
    Bean.sleep(250);
    Bean.setLed(0, 0, 0);
  }
  // Sleep for 2 seconds
  Bean.sleep(2000);
}

Bluetooth Services

Functions dealing with Bluetooth service configurations and pairing.

Bean.getServices

Returns a struct of all of the currently services and whether or not they are enabled.

Returns

Bean.setServices

Sets services for the Bean to use (NOTE: disabling the standard service will no longer allow the Bean to connect to the Bean Loader)

Parameters

Bean.resetServices

Resets services leaving only the primary standard Bean service advertising.

Bean.setPairingPin

Sets the pairing PIN for a secure PIN-based connection. The default PIN is 000000. Calling this function enables the pairing PIN mode. Disable it with enablePairingPin(false). If you wish to use this with HID or ANCS, set the PIN after enabling either of the profiles. After pairing, your device and Bean will be bonded. In order to un-bond, you will have to manually disconnect from Bean in your device’s settings. The PIN will be saved to nonvolatile memory unless enableConfigSave(false) is called.

Parameters

  • uint32_t pin

    the pairing PIN to set, from 000000 to 999999

Examples

This example sets a pairing PIN of 123456 for future connections:
1234567891011void setup() {
  // Enable 6-digit pairing PIN code (default is 000000)
  Bean.enablePairingPin(true);
  // Set pairing PIN to 123456
  Bean.setPairingPin(123456);
  // Pairing PIN will be required when future connections are established
}
void loop() {
  // Sleep forever
  Bean.sleep(0xffffffff);
}

Bean.enablePairingPin

Enables or disables pairing PIN functionality. The default PIN is 000000. This can be changed using setPairingPin.

Parameters

Other

Functions that don’t belong in any of the other categories.

Bean.enableConfigSave

Allows temporary storage of BLE configuration settings, as opposed to permanent storage in non-volatile memory (NVRAM). Bean can only write to NVRAM a maximum of 20,000 times. If your sketch changes its advertising configuration frequently, it will quickly use up all of your Bean NVRAM’s writes. To prevent this, disable saving to NVRAM first. Configurations written while NVRAM saving is disabled will persist until the Bean is power cycled. When the Bean is power cycled, saving to NVRAM is re-enabled.

Parameters

  • bool enableSave

    true to disable saving to NVRAM, false to enable

Examples

This example enables settings that will only be used temporarily because enableConfigSave is used:
123456789101112void setup() {
  // Set enableConfigSave to true to save settings temporarily
  Bean.enableConfigSave(false);
  // Enable some settings which will be temporary now
  Bean.enableAdvertising(true);
  Bean.enableCustom();
  Bean.enableiBeacon();
  // These settings will be reset to default upon rebooting the Bean
}
void loop() {
  // Do anything here with new temporary settings
}

Bean.restartBluetooth

Performs a hard reset on the bluetooth module. WARNING: Advanced function. The misuse of this method can cause the Bean to repeatedly reboot, causing it to be unconnectable.

HID

The user must enter a pairing code (default of 000000) to connect. HID allows the bean to act as a mouse, keyboard, or media control device. Important: When disconnecting from a device, you must manually forget Bean in the system’s Bluetooth settings as well as Bean Loader.

BeanHid.enable

This function turns on the Bean’s HID functionality. It will require pairing using a pin code with your device and if you wish to disconnect it you must disconnect through your devices bluetooth system settings menu. HID may not work well with other profiles such as ANCS or MIDI. Use multiple profiles simultaneously at your own risk. You may need to power cycle Bean after enabling HID.

Examples

This sketch demonstrates how to use Bean as a HID peripheral. Bean will move a mouse pointer around the screen when it’s tilted side to side, forward, and back. Sending ASCII ‘1’ via Virtual Serial will cause Bean to type “Hello, world!”, and sending ‘2’ will cause Bean to send the Play media key.
1234567891011121314151617181920212223242526272829303132333435363738void setup() {
  BeanHid.enable();
  // Serial port is initialized automatically; we don't have to do anything
}

void loop() {
  AccelerationReading accel = Bean.getAcceleration();

  int16_t x = accel.xAxis;
  int16_t y = accel.yAxis;
  int16_t z = accel.zAxis;

  // Add a deadzone. If Bean is reasonabally flat, don't move the mouse pointer
  if (abs(x) < 20) {
    x = 0;
  }
  if (abs(y) < 20) {
    y = 0;
  }

  // we want to map the movements to reasonable values.
  // This constrains the accelerometer to -20 to 20.
  int16_t mousex = map(x, -60, 60, -20, 20);
  int16_t mousey = map(y, -60, 60, 20, -20);

  BeanHid.moveMouse(mousex, mousey);

  if (Serial.available()) {
    byte read = Serial.read();
    if (read == '1') {
      // send the ASCII number 1 to type a message
      BeanHid.sendKeys("Hello, world!");
    } else if (read == '2') {
      // send the ASCII number 2 to use a media command
      BeanHid.sendMediaControl(PLAY);
    }
  }
}

BeanHid.isEnabled

Returns

  • bool

    True if HID is enabled

BeanHid.disable

Disables the HID functionality. If Bean has been paired with another device, you must un-pair Bean from that device manually. You may need to power cycle Bean after disabling HID.

BeanHid.holdKey

Holds a key down. Takes any ascii character. Can hold a max of 6 character keys.

Parameters

  • char key

    single character key

Returns

  • int

    1 if success 0 if failure

BeanHid.holdKey

Holds a key down. takes any modifier key specified by modifierKey. Does not affect a users keyboard (sending hold shift won’t type capital letters when you press them on your keyboard)

Parameters

  • modifierKey key

    takes a modifier key to hold down. Can hold down all 8 of the first 8 modifier keys. The keys that come after the first 8 are counted as standard keys and therefore part of the 6 character keys.

Returns

BeanHid.releaseKey

Releases a key.

Parameters

  • char key

    the key to release in character form

Returns

BeanHid.releaseKey

Releases a key.

Parameters

  • modifierKey key

    the key to release of type modifierKey

Returns

  • int

    1 if success 0 if failure

BeanHid.releaseAllKeys

Releases all currently held keys

BeanHid.sendKey

Sends a full keypress event. Like calling holdKey then releaseKey

Parameters

  • char key

    the key to send in character form

Returns

  • int

    1 if success 0 if failure

BeanHid.sendKey

Sends a full keypress event. Like calling holdKey then releaseKey

Parameters

Returns

  • int

    1 if success 0 if failure

BeanHid.sendKeys

Sends a string of characters as keyboard events

Parameters

  • String charsToType

    a String of characters for the keyboard to emulate

Returns

  • int

    1 if success 0 if failure

BeanHid.moveMouse

Sends a mouse move command

Parameters

  • signed char delta_x

    a signed 8 bit value for how many pixels to move the mouse in the x direction

  • signed char delta_y

    a signed 8 bit value for how many pixels to move the mouse in the y direction

  • signed char delta_wheel

    an optional signed 8 bit balue for how many clicks to move the mouse wheel

BeanHid.holdMouseClick

Holds a mouse button down

Parameters

  • mouseButtons button

    the button to hold of type mouseButtons. Defaults to MOUSE_LEFT.

BeanHid.releaseMouseClick

Releases a mouse button.

Parameters

  • mouseButtons button

    the button to release of type mouseButtons. Defaults to MOUSE_LEFT.

BeanHid.sendMouseClick

Sends a mouse hold then a mouse release command.

Parameters

  • mouseButtons button

    the button to click of type mouseButtons. Defaults to MOUSE_LEFT.

BeanHid.sendMediaControl

Sends a media control command command of type mediaControl.

Parameters

  • mediaControl command

    takes a media control command of type mediaControl

BeanHid.holdMediaControl

Holds a media control command command of type mediaControl.

Parameters

  • mediaControl command

    takes a media control command of type mediaControl

BeanHid.releaseMediaControl

Releases a media control command command of type mediaControl.

Parameters

  • mediaControl command

    takes a media control command of type mediaControl

BeanHid.releaseAllMediaControls

Releases all currently held media control commands

ANCS

Use the Apple Notification Center Service to read notifications from your iOS device. This allows a connected Bluetooth device to receive information about iOS nofications. Bean can view details about these notifications, e.g. push notifications, SMS previews, or an incoming phone call’s number. To use ANCS, upload an ANCS sketch to Bean, power cycle Bean, and pair with Bean from your iOS device using pairing code 000000. When you disconnect from an Bean in ANCS mode, you’ll need to manually forget it from the iOS Bluetooth Settings menu.

BeanAncs.enable

Enables ANCS functionality. After uploading an ANCS sketch, make sure to power cycle Bean.

BeanAncs.isEnabled

Returns

  • bool

    true if ANCS is currently enabled

BeanAncs.disable

Disables ANCS functionality

BeanAncs.notificationsAvailable

Returns

  • int

    number of notifications available that can be read using getNotificationHeaders

BeanAncs.getNotificationHeaders

Gets all available notification headers. The ANCS buffer can only hold 8 messages at a time before it begins to overwrite old messages.

Parameters

  • ANCS_SOURCE_MSG_T * buffer

    takes a user defined buffer of type ANCS_SOURCE_MSG_T. When this function returns the buffer will be populated with messages

  • size_t max_length

    takes the length of the maximum buffer size. If the user only has a buffer of one then max_length should also be 1.

Returns

  • int

    number of messages actually read into the buffer.

BeanAncs.getNotificationHeader

Gets a single notification Header. If there are no messages available all values will be set to 0. It is up to the user to check using notificationsAvailable() if there are messages to read.

Returns

BeanAncs.getNotificationAttributes

Parameters

  • NOTI_ATTR_ID_T type

    is the type of data the user wishes to receive of type NOTI_ATTR_ID_T

  • uint32_t ID

    is the UUID of the notification as contained in ANCS_SOURCE_MSG_T.

  • uint16_t len

    is the max number of bytes to receive into data. The maximum possible is 65535 bytes.

  • uint8_t * data

    is the user defined buffer to fill incoming data with.

  • uint32_t timeout

    is the length of time in milliseconds before the function will return if it does not receive data or only receives partial data

Returns

Examples

This example sketch reads ANCS messages and prints them to Virtual Serial. Pair with your iOS device, then use Bean Console for iOS to view data live from your iOS device.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869int latestID = 0;
AncsNotification notifications[8];

void setup() {
  // Serial port is initialized automatically; we don't have to do anything
  BeanAncs.enable();
}

void loop() {
  int msgAvail = BeanAncs.notificationsAvailable();
  if (msgAvail) {
    // blink red every time we have a new message
    Bean.setLedGreen(0);
    Bean.setLedRed(130);

    // fills the notifications array with message header info
    BeanAncs.getNotificationHeaders(notifications, 8);

    for (int i = 0; i < msgAvail; i++) {
      Serial.print("cat:");
      Serial.println(notifications[i].catID);
      Serial.print("flg:");
      Serial.println(notifications[i].flags);
      Serial.print("evt:");
      Serial.println(notifications[i].eventID);
      Serial.print("cnt:");
      Serial.println(notifications[i].catCount);
      Serial.print("id: ");
      Serial.println(notifications[i].notiUID);

      // get some information about each message
      char data[64] = {0};
      int len = BeanAncs.getNotificationAttributes(
        NOTI_ATTR_ID_MESSAGE,
        notifications[i].notiUID,
        39,
        (uint8_t *)data,
        5000);

      Serial.print("l: ");
      Serial.print(len);
      Serial.print(" ");
      for (int j = 0; j < len; j++) {
        Serial.print(data[j]);
      }
      Serial.println();
      delay(5000);
    }
    Bean.setLedRed(0);
  }

  // send a number through serial (with newline at end) to perform a negative
  // action on a message with the given ID
  if (Serial.available() > 0) {
    char idin[8] = {0};
    int index = 0;
    byte read = Serial.read();
    while (read != '\n' && index < 7) {
      idin[index] = read;
      index++;
      read = Serial.read();
    }

    int id = atoi(idin);
    Serial.print("Performing negative action on ID: ");
    Serial.println(id);
    BeanAncs.notificationAction(id, 0x01);
  }
}

BeanAncs.notificationAction

Certain notifications allow different actions. For instance many push notifications can be cleared and calls can be answered.

Parameters

  • uint32_t ID

    the UUID of the notification to perform the action on.

  • uint8_t actionID

    the ID of the action to perform. There are only two: ActionIDPositive(0x00) and ActionIDNegative(0x01). The result of the action is dependent on the notification.

MIDI

Read and write MIDI packets via Bluetooth Low Energy. This profile uses Apple’s Core Midi Framework to act as a musical instrument. The Bean can send midi messages to an app like garage band to emulate diferent instruments. A list of different types of MIDI messages can be found here

BeanMidi.enable

Enables core Midi functionality on the Bean.

Examples

When connected to iOS’s or OSX’s garage band this bean will play through the C Major scale, play a C Major chord, and then bend a note up. The Bean will also listen for incoming Core Midi messages. If you have an app that can send core midi messages to BLE peripherals, the Bean’s green LED will blink.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647void setup() {
  // We don't have to do anything here
}

// C Major Scale
char scale[8] = {NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4,
                 NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5};

void loop() {
  // play the C Major scale
  for (int i = 0; i < 8; i++) {
    BeanMidi.noteOn(CHANNEL1, scale[i], 60);
    delay(1000);
    BeanMidi.noteOff(CHANNEL1, scale[i], 60);
    checkMidi();
  }

  // C Major chord
  BeanMidi.noteOn(CHANNEL1, NOTE_C4, 60);
  BeanMidi.noteOn(CHANNEL1, NOTE_E4, 60);
  BeanMidi.noteOn(CHANNEL1, NOTE_G4, 60);
  delay(2000);
  BeanMidi.noteOff(CHANNEL1, NOTE_C4, 60);
  BeanMidi.noteOff(CHANNEL1, NOTE_E4, 60);
  BeanMidi.noteOff(CHANNEL1, NOTE_G4, 60);

  // pitch bend
  BeanMidi.noteOn(CHANNEL1, 60, 70);
  delay(1000);
  BeanMidi.pitchBend(CHANNEL1, 0x2500);
  delay(1000);
  BeanMidi.pitchBend(CHANNEL1, 0x2000);
  delay(1000);
  BeanMidi.noteOff(CHANNEL1, 60, 0);

  checkMidi();
}

// Poll MIDI to check if new messages have arrived
void checkMidi() {
  uint8_t stat, byte1, byte2;
  if (BeanMidi.readMessage(&stat, &byte1, &byte2)) {
    Bean.setLedGreen(130);
    delay(50);
    Bean.setLedGreen(0);
  }
}

BeanMidi.isEnabled

Returns

  • bool

    true if Midi is currently enabled

BeanMidi.disable

Disables core Midi functionality on the Bean.

BeanMidi.sendMessage

Loads and sends a buffer of Midi messages.

Parameters

  • uint8_t * buff

    a buffer of Midi messages. Will only send Midi messages in groups of 3. Must conform to the Midi spec.

  • uint8_t numBytes

    length of buffer

Returns

  • int

    number of Midi bytes sent, 0 if there are none to be sent

BeanMidi.sendMessage

Loads and sends a single Midi message.

Parameters

  • uint8_t status

    the status byte signifying the type of message

  • uint8_t byte1

    the first data byte of the midi message

  • uint8_t byte2

    the second data byte of the midi message

Returns

  • int

    number of Midi bytes sent, 0 if there are none to be sent

BeanMidi.readMessage

Reads a single incoming Midi message.

Parameters

Returns

  • int

    Midi status/timestamp byte

BeanMidi.sendMessages

Sends Midi messages after they have been loaded to the midi buffer using loadMessage() commands. The buffer has a maximum size of 20 messages before it must be dumped or sent using this function.

Returns

  • int

    number of Midi bytes sent, 0 if there are none to be sent

BeanMidi.loadMessage

Loads a message into the Midi buffer for sending using the sendMessages() function

Parameters

  • uint8_t * buff

    a buffer of Midi messages. Will only send Midi messages in groups of 3. Must conform to the Midi spec.

  • uint8_t numBytes

    length of buffer

Returns

  • int

    number of bytes successfully loaded

BeanMidi.loadMessage

Loads a message into the Midi buffer for sending using the sendMessages() function

Parameters

  • uint8_t status

    the status byte signifying the type of message

  • uint8_t byte1

    the first data byte of the midi message

  • uint8_t byte2

    the second data byte of the midi message

Returns

  • int

    1 if bytes successfully loaded 0 if unsuccessful

BeanMidi.noteOn

Turns a specific note on for a specified midi channel. The note will ring out until silenced via noteOff.

Parameters

  • midiChannels channel

    takes a channel 0-15 or specified by midiChannels

  • uint8_t note

    takes a note from 0-127, can also take types midiNotes and midiDrums

  • uint8_t volume

    takes a volume values of 0-127

BeanMidi.noteOff

Turns a specific note off for a specified midi channel.

Parameters

  • midiChannels channel

    takes a channel 0-15 or specified by midiChannels

  • uint8_t note

    takes a note from 0-127, can also take types midiNotes and midiDrums

  • uint8_t volume

    takes a volume values of 0-127

BeanMidi.pitchBend

Bends the pitch of a note up or down

Parameters

  • midiChannels channel

    takes a channel 0-15 or specified by midiChannels takes a pitch bend value from 0-16383 where 0x2000 is the middle or the true value of the note.

  • uint16_t value

BeanMidi.sustain

Enables or disables sustain for the midi channel

Parameters

  • midiChannels channel

    takes a channel 0-15 or specified by midiChannels

  • bool isOn

    set to true to enable sustain and false to disable

Enumerations

The following enumerations (enums) are available for use.

AccelEventTypes

Accelerometer interrupt types
Member Value Description
FLAT_EVENT 0x80 triggers when the accelerometer is lying flat on a surface
ORIENT_EVENT 0x40 triggers when the accelerometer is NOT lying flat on a surface, but is tilted * in any direction
SINGLE_TAP_EVENT 0x20 triggers when the accelerometer is tapped once
DOUBLE_TAP_EVENT 0x10 triggers when the accelerometer is tapped twice
ANY_MOTION_EVENT 0x04 triggers when the accelerometer experiences any change in motion
HIGH_G_EVENT 0x02 triggers when the accelerometer experiences a velocity event higher than it’s * sensitivity
LOW_G_EVENT 0x01 triggers when the accelerometer is in free fall or experiences no gravitational * pull

AdvertisementDataTypes

Advertisement data types
Member Value Description
GAP_ADTYPE_FLAGS 0x01 Discovery Mode: GAP_ADTYPE_FLAGS_MODES
GAP_ADTYPE_16BIT_MORE 0x02 Service: More 16-bit UUIDs available
GAP_ADTYPE_16BIT_COMPLETE 0x03 Service: Complete list of 16-bit UUIDs
GAP_ADTYPE_32BIT_MORE 0x04 Service: More 32-bit UUIDs available
GAP_ADTYPE_32BIT_COMPLETE 0x05 Service: Complete list of 32-bit UUIDs
GAP_ADTYPE_128BIT_MORE 0x06 Service: More 128-bit UUIDs available
GAP_ADTYPE_128BIT_COMPLETE 0x07 Service: Complete list of 128-bit UUIDs
GAP_ADTYPE_LOCAL_NAME_SHORT 0x08 Shortened local name
GAP_ADTYPE_LOCAL_NAME_COMPLETE 0x09 Complete local name
GAP_ADTYPE_POWER_LEVEL 0x0A TX Power Level: 0xXX: -127 to +127 dBm
GAP_ADTYPE_OOB_CLASS_OF_DEVICE 0x0D Simple Pairing OOB Tag: Class of device (3 octets)
GAP_ADTYPE_OOB_SIMPLE_PAIRING_HASHC 0x0E Simple Pairing OOB Tag: Simple Pairing Hash C (16 octets)
GAP_ADTYPE_OOB_SIMPLE_PAIRING_RANDR 0x0F Simple Pairing OOB Tag: Simple Pairing Randomizer R (16 octets)
GAP_ADTYPE_SM_TK 0x10 Security Manager TK Value
GAP_ADTYPE_SM_OOB_FLAG 0x11 Secutiry Manager OOB Flags
GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE 0x12 Min and Max values of the connection interval (2 octets Min, 2 octets Max) (0xFFFF indicates no conn interval min or max)
GAP_ADTYPE_SIGNED_DATA 0x13 Signed Data field
GAP_ADTYPE_SERVICES_LIST_16BIT 0x14 Service Solicitation: list of 16-bit Service UUIDs
GAP_ADTYPE_SERVICES_LIST_128BIT 0x15 Service Solicitation: list of 128-bit Service UUIDs
GAP_ADTYPE_SERVICE_DATA 0x16 Service Data
GAP_ADTYPE_APPEARANCE 0x19 Appearance
GAP_ADTYPE_MANUFACTURER_SPECIFIC 0xFF Manufacturer Specific Data: first 2 octets contain the Company Identifier Code followed by the additional manufacturer specific data

AdvertisementType

Advertisement Type
Member Value Description
GAP_ADTYPE_FLAGS_LIMITED 0x01 Discovery Mode: LE Limited Discoverable Mode
GAP_ADTYPE_FLAGS_GENERAL 0x02 Discovery Mode: LE General Discoverable Mode
GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED 0x04 Discovery Mode: BR/EDR Not Supported

mouseButtons

Enumeration of mouse buttons
Member Value Description
MOUSE_LEFT 1
MOUSE_RIGHT 2
MOUSE_MIDDLE 4
MOUSE_ALL (MOUSE_LEFT|MOUSE_RIGHT|MOUSE_MIDDLE)

modifierKey

Enumeration of modifier keys
Member Value Description
KEY_LEFT_CTRL 0x80
KEY_LEFT_SHIFT 0x81
KEY_LEFT_ALT 0x82
KEY_LEFT_GUI 0x83
KEY_RIGHT_CTRL 0x84
KEY_RIGHT_SHIFT 0x85
KEY_RIGHT_ALT 0x86
KEY_RIGHT_GUI 0x87
KEY_UP_ARROW 0xDA
KEY_DOWN_ARROW 0xD9
KEY_LEFT_ARROW 0xD8
KEY_RIGHT_ARROW 0xD7
KEY_BACKSPACE 0xB2
KEY_TAB 0xB3
KEY_RETURN 0xB0
KEY_ESC 0xB1
KEY_INSERT 0xD1
KEY_DELETE 0xD4
KEY_PAGE_UP 0xD3
KEY_PAGE_DOWN 0xD6
KEY_HOME 0xD2
KEY_END 0xD5
KEY_CAPS_LOCK 0xC1
KEY_F1 0xC2
KEY_F2 0xC3
KEY_F3 0xC4
KEY_F4 0xC5
KEY_F5 0xC6
KEY_F6 0xC7
KEY_F7 0xC8
KEY_F8 0xC9
KEY_F9 0xCA
KEY_F10 0xCB
KEY_F11 0xCC
KEY_F12 0xCD

mediaControl

HID Consumer Usage IDs (subset of the codes available in the USB HID Usage Tables spec)
Member Value Description
POWER 0x30
ASSIGN_SEL 0x81
CHANNEL_UP 0x9C
CHANNEL_DOWN 0x9D
RECALL_LAST 0x83
PLAY 0xB0
PAUSE 0xB1
RECORD 0xB2
FAST_FORWARD 0xB3
REWIND 0xB4
SCAN_NEXT_TRK 0xB5
SCAN_PREV_TRK 0xB6
STOP 0xB7
VOLUME_UP 0xE9
VOLUME_DOWN 0xEA
MUTE 0xE2

AncsNotificationAttribute

Member Value Description
NOTI_ATTR_ID_APPID 0
NOTI_ATTR_ID_TITLE 1
NOTI_ATTR_ID_SUBTITLE 2
NOTI_ATTR_ID_MESSAGE 3
NOTI_ATTR_ID_MSG_SIZE 4
NOTI_ATTR_ID_DATE 5

midiChannels

Member Value Description
CHANNEL0 0x00
CHANNEL1 0x01
CHANNEL2 0x02
CHANNEL3 0x03
CHANNEL4 0x04
CHANNEL5 0x05
CHANNEL6 0x06
CHANNEL7 0x07
CHANNEL8 0x08
CHANNEL9 0x09
CHANNEL10 0x0A
CHANNEL11 0x0B
CHANNEL12 0x0C
CHANNEL13 0x0D
CHANNEL14 0x0E
CHANNEL15 0x0F

midiNotes

Member Value Description
NOTE_Cn1 0
NOTE_Csn1 1
NOTE_Dn1 2
NOTE_Dsn1 3
NOTE_En1 4
NOTE_Fn1 5
NOTE_Fsn1 6
NOTE_Gn1 7
NOTE_Gsn1 8
NOTE_An1 9
NOTE_Asn1 10
NOTE_Bn1 11
NOTE_C0 12
NOTE_Cs0 13
NOTE_D0 14
NOTE_Ds0 15
NOTE_E0 16
NOTE_F0 17
NOTE_Fs0 18
NOTE_G0 19
NOTE_Gs0 20
NOTE_A0 21
NOTE_As0 22
NOTE_B0 23
NOTE_C1 24
NOTE_Cs1 25
NOTE_D1 26
NOTE_Ds1 27
NOTE_E1 28
NOTE_F1 29
NOTE_Fs1 30
NOTE_G1 31
NOTE_Gs1 32
NOTE_A1 33
NOTE_As1 34
NOTE_B1 35
NOTE_C2 36
NOTE_Cs2 37
NOTE_D2 38
NOTE_Ds2 39
NOTE_E2 40
NOTE_F2 41
NOTE_Fs2 42
NOTE_G2 43
NOTE_Gs2 44
NOTE_A2 45
NOTE_As2 46
NOTE_B2 47
NOTE_C3 48
NOTE_Cs3 49
NOTE_D3 50
NOTE_Ds3 51
NOTE_E3 52
NOTE_F3 53
NOTE_Fs3 54
NOTE_G3 55
NOTE_Gs3 56
NOTE_A3 57
NOTE_As3 58
NOTE_B3 59
NOTE_C4 60
NOTE_Cs4 61
NOTE_D4 62
NOTE_Ds4 63
NOTE_E4 64
NOTE_F4 65
NOTE_Fs4 66
NOTE_G4 67
NOTE_Gs4 68
NOTE_A4 69
NOTE_As4 70
NOTE_B4 71
NOTE_C5 72
NOTE_Cs5 73
NOTE_D5 74
NOTE_Ds5 75
NOTE_E5 76
NOTE_F5 77
NOTE_Fs5 78
NOTE_G5 79
NOTE_Gs5 80
NOTE_A5 81
NOTE_As5 82
NOTE_B5 83
NOTE_C6 84
NOTE_Cs6 85
NOTE_D6 86
NOTE_Ds6 87
NOTE_E6 88
NOTE_F6 89
NOTE_Fs6 90
NOTE_G6 91
NOTE_Gs6 92
NOTE_A6 93
NOTE_As6 94
NOTE_B6 95
NOTE_C7 96
NOTE_Cs7 97
NOTE_D7 98
NOTE_Ds7 99
NOTE_E7 100
NOTE_F7 101
NOTE_Fs7 102
NOTE_G7 103
NOTE_Gs7 104
NOTE_A7 105
NOTE_As7 106
NOTE_B7 107
NOTE_C8 108
NOTE_Cs8 109
NOTE_D8 110
NOTE_Ds8 111
NOTE_E8 112
NOTE_F8 113
NOTE_Fs8 114
NOTE_G8 115
NOTE_Gs8 116
NOTE_A8 117
NOTE_As8 118
NOTE_B8 119
NOTE_C9 120
NOTE_Cs9 121
NOTE_D9 122
NOTE_Ds9 123
NOTE_E9 124
NOTE_F9 125
NOTE_Fs9 126
NOTE_G9 127
NOTE_Gs9 128
NOTE_A9 129
NOTE_As9 130
NOTE_B9 131

midiControlChange

Member Value Description
BANKSELECT 0
MODULATIONWHEEL 1
BREATHCONTROLLER 2
FOOTCONTROLLER 4
PORTAMENTOTIME 5
DATAENTRY 6
CHANNELVOLUME 7
BALANCE 8
PAN 10
EXPRESSIONCONTROLLER 11
EFFECTCONTROL1 12
EFFECTCONTROL2 13
GENERALPURPOSECONTROLLER1 16
GENERALPURPOSECONTROLLER2 17
GENERALPURPOSECONTROLLER3 18
GENERALPURPOSECONTROLLER4 19
SUSTAIN 64
PORTAMENTO 65
SOSTENUTO 66
SOFTPEDAL 67
LEGATO 68
HOLD 69
SOUNDCONTROLLER1 70
SOUNDCONTROLLER2 71
SOUNDCONTROLLER3 72
SOUNDCONTROLLER4 73
SOUNDCONTROLLER5 74
SOUNDCONTROLLER6 75
SOUNDCONTROLLER7 76
SOUNDCONTROLLER8 77
SOUNDCONTROLLER9 78
SOUNDCONTROLLER10 79
GENERALPURPOSECONTROLLER5 80
GENERALPURPOSECONTROLLER6 81
GENERALPURPOSECONTROLLER7 82
GENERALPURPOSECONTROLLER8 83
PORTAMENTOCONTROL 84
EFFECTS1 91
EFFECTS2 92
EFFECTS3 93
EFFECTS4 94
EFFECTS5 95
ALLSOUNDOFF 120
RESETALLCONTROLLERS 121
LOCALCONTROL 122
ALLNOTESOFF 123
OMNIMODEOFF 124
OMNIMODEON 125
MONOMODEON 126
POLYMODEON 127

midiMessageTypes

Member Value Description
NOTEOFF 0x80
NOTEON 0x90
POLYPHONICPRESSURE 0xA0
CONTROLCHANGE 0xB0
PROGRAMCHANGE 0xC0
CHANNELPRESSURE 0xD0
PITCHBENDCHANGE 0xE0
SYSTEMCOMMON 0xF0
SYSTEMREALTIME 0xF8

midiDrums

Member Value Description
BASS_DRUM_2 35
BASS_DRUM_1 36
SIDE_STICK 37
SNARE_DRUM_1 38
HAND_CLAP 39
SNARE_DRUM_2 40
LOW_TOM_2 41
CLOSED_HIHAT 42
LOW_TOM_1 43
PEDAL_HIHAT 44
MID_TOM_2 45
OPEN_HIHAT 46
MID_TOM_1 47
HIGH_TOM_2 48
CRASH_CYMBAL_1 49
HIGH_TOM_1 50
RIDE_CYMBAL_1 51
CHINESE_CYMBAL 52
RIDE_BELL 53
TAMBOURINE 54
SPLASH_CYMBAL 55
COWBELL 56
CRASH_CYMBAL_2 57
VIBRA_SLAP 58
RIDE_CYMBAL_2 59
HIGH_BONGO 60
LOW_BONGO 61
MUTE_HIGH_CONGA 62
OPEN_HIGH_CONGA 63
LOW_CONGA 64
HIGH_TIMBALE 65
LOW_TIMBALE 66
HIGH_AGOGO 67
LOW_AGOGO 68
CABASA 69
MARACAS 70
SHORT_WHISTLE 71
LONG_WHISTLE 72
SHORT_GUIRO 73
LONG_GUIRO 74
CLAVES 75
HIGH_WOOD_BLOCK 76
LOW_WOOD_BLOCK 77
MUTE_CUICA 78
OPEN_CUICA 79
MUTE_TRIANGLE 80
OPEN_TRIANGLE 81

Structures

The following structures (structs) are available for use.

AccelerationReading

An acceleration reading from the Bean accelerometer, the BMA250 (datasheet). Also includes the current sensitivity setting.
Member Type Description
xAxis PTD_INT16
yAxis PTD_INT16
zAxis PTD_INT16
sensitivity PTD_UINT8

LedReading

Intensity values for the color channels of the Bean RGB LED. 0 is off and 255 is on.
Member Type Description
red PTD_UINT8
green PTD_UINT8
blue PTD_UINT8

BluetoothServices

Currently enabled advertisements in the rotating advertisement controller.
Member Type Description
standard PTD_UINT8
hid PTD_UINT8
midi PTD_UINT8
ancs PTD_UINT8
observer PTD_UINT8
ibeacon PTD_UINT8
custom PTD_UINT8

ObserverAdvertisementInfo

Data returned by the observer role.
Member Type Description
eventType PTD_UINT8
addrType PTD_UINT8
addr PTD_UINT8
rssi PTD_INT8
dataLen PTD_UINT8
advData PTD_UINT8

AncsNotification

Needs docs
Member Type Description
eventID PTD_UINT8
flags PTD_UINT8
catID PTD_UINT8
catCount PTD_UINT8
notiUID PTD_UINT32