Reading LightBlue Bean digital and analog pins
I got several requests on how to read the Bean pins value, so here it comes ...
The Bean SDK API has callable methods to retrieve sensors value but not the digital and analog pins, my example here is to re-use the
DemoSketch from PunchThrough and read the pins value through serial message.
Install and run the DemoSketch on your bean.
First come first is to install the Sketch, please refer to ....
a). Refer to the source and introduction of the demo sketch.
https://punchthrough.com/bean/docs/guides/everything-else/lb-demo-sketch/
b). Load the sketch into your bean.
I am using MacOSX (link below), you can find the loader based on your platform.
https://www.punchthrough.com/bean/docs/guides/getting-started/os-x/
Handshake details from the DemoSketch
With reference to the source ...
#define BUFFER_SIZE 64
void setup() {
// Set a timeout so that Bean won't stall indefinitely if something goes wrong
Serial.setTimeout(25);
// Configure digital pins as inputs
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
}
void loop() {
// Grab up to 64 bytes from Bean's Virtual Serial port
char buffer[BUFFER_SIZE];
uint8_t bytes_rcvd = Serial.readBytes(buffer, BUFFER_SIZE);
if (bytes_rcvd == 1 && buffer[0] == 0x02) {
// We got a request for data from LightBlue!
// Read analog pins A0 and A1
int analog1 = analogRead(A0);
int analog2 = analogRead(A1);
// Read digital pins D0 through D5 and join their bits into a single byte
uint8_t digitalAll = 0;
digitalAll |= digitalRead(0);
digitalAll |= digitalRead(1) << 1;
digitalAll |= digitalRead(1) << 2;
digitalAll |= digitalRead(1) << 3;
digitalAll |= digitalRead(1) << 4;
digitalAll |= digitalRead(1) << 5;
// Package the data into a 6-byte buffer
buffer[0] = 0x82;
buffer[1] = digitalAll;
buffer[2] = analog1 & 0xFF;
buffer[3] = analog1 >> 8;
buffer[4] = analog2 & 0xFF;
buffer[5] = analog2 >> 8;
// Send back 6 bytes of data to LightBlue
Serial.write((uint8_t *)buffer, 6);
}
// Sleep until another serial request wakes us up
Bean.sleep(0xFFFFFFFF);
}
Based on the source, the interface spec is as the following.
- When bean receives a serial message with first byte equals to 0x02, it responses back with a 6 bytes serial message.
- The 6 bytes response message is formatted as ..
byte 1 - Response header code equals 0x82
byte 2 - Binary value of pins D0 through D5
byte 3 and 4 - Analog value of A0
byte 5 and 6 - Analog value of A1
Android Program
Based on the DemoSketch, Bean won't read and send its pins value unless it receives a request message through its Serial transport, our Android program need to send a request message to the bean to get things started.
A). Sending the request message
byte requestCode=0x02;
byte[] requestMsg= {requestCode};
bean.sendSerialMessage(requestMsg);
B). Bean's callback and response parsing
Your BeanListener interface will receive a call back on onSerialMessageReceived
and the 6 bytes serial message is passed through the byte array. The following example
code is validate the proper responser header byte (0x82) and parses the byte array
to retrieve the digital and analog pins value.
public void onSerialMessageReceived(byte[] data) {
Log.d(TAG, "onSerialMessageReceived >> "+BeanInfo);
char[] chars= Hex.encodeHex(data);
Log.d(TAG,"data: "+ String.valueOf(chars));
int size=data.length;
Log.d(TAG,"number of bytes: "+ size);
Log.d(TAG,"byte 1 (should be 82):"+ Integer.toHexString(data[0] & 0xFF));
byte digitalPins=data[1];
String s1 = String.format("%8s", Integer.toBinaryString(digitalPins & 0xFF)).replace(' ', '0');
Log.d(TAG,"byte 2 Pins[xx543210]:"+ s1);
byte a1L = data[2];
byte a1H = data[3];
byte a2L = data[4];
byte a2H = data[5];
int a1=a1H*256+a1L;
int a2=a2H*256+a2L;
Log.d(TAG,"A1 values:"+ a1);
Log.d(TAG,"A2 values:"+ a2);
}
Herewith is the complete read pins function whereas a discovered bean is passed and connect with
the example BeanListener.
public static void readPins(Context context, Bean bean){
final String TAG="BEAN";
final String BeanInfo=bean.describe();
byte requestCode=0x02;
byte[] requestMsg= {requestCode};
bean.sendSerialMessage(requestMsg);
bean.connect(context, new BeanListener() {
@Override public void onConnected() {
Log.d(TAG, "onConnected >> "+BeanInfo);
}
@Override public void onConnectionFailed() {
Log.d(TAG, "onConnectionFailed >> "+BeanInfo);
}
@Override public void onDisconnected() {
Log.d(TAG, "onDisconnected >> "+BeanInfo);
}
@Override public void onSerialMessageReceived(byte[] data) {
Log.d(TAG, "onSerialMessageReceived >> "+BeanInfo);
char[] chars= Hex.encodeHex(data);
Log.d(TAG,"data: "+ String.valueOf(chars));
int size=data.length;
Log.d(TAG,"number of bytes: "+ size);
Log.d(TAG,"byte 1 (should be 82):"+ Integer.toHexString(data[0] & 0xFF));
byte digitalPins=data[1];
String s1 = String.format("%8s", Integer.toBinaryString(digitalPins & 0xFF)).replace(' ', '0');
Log.d(TAG,"byte 2 Pins[xx543210]:"+ s1);
byte a1L = data[2];
byte a1H = data[3];
byte a2L = data[4];
byte a2H = data[5];
int a1=a1H*256+a1L;
int a2=a2H*256+a2L;
Log.d(TAG,"A1 values:"+ a1);
Log.d(TAG,"A2 values:"+ a2);
}
@Override public void onScratchValueChanged(ScratchBank bank, byte[] value) {
Log.d(TAG, "onScratchValueChanged >> "+bank);
}
@Override public void onError(BeanError error) {
Log.d(TAG, "onConnectionFailed >> "+error);
}
@Override public void onReadRemoteRssi(int rssi) {
Log.d(TAG, "onReadRemoteRssi >> "+rssi);
}
});
}