La Pebble Time possède une interface série permettant de la relier à des dispositifs électroniques extérieurs. Ce principe est nommé par pebble le SmartStrap.
A) l’Interface :
Attention aux spécifications :
Characteristic | Value |
---|---|
Pin layout (watch face down, left to right) | Ground, data, power in/out, ground. |
Type of data connection | Single wire, open drain serial connection with external pull-up required. |
Data voltage level | 1.8V input logic level with tolerance for up to 5V. |
Baud rate | Configurable between 9600 and 460800 bps. |
Output voltage (power pin) | 3.3V (+/- 10%) |
Maximum output current draw (power pin) | 20mA |
Minimum charging voltage (power pin) | 5V (+/- 5%) |
Maximum charging current draw | 500mA |
B) Connexion à un Arduino :
- Download and install teensyduino for the Arduino
- Download this Library as a .zip by clicking on the « Download ZIP » button on GitHub.
- In Arduino, create a new project and go to « Sketch » -> « Include Library » -> « Add .ZIP Library… » Select the .zip you just downloaded.
- Create a new Arduino sketch and put the following code to it, select your board type and download the code to the board
#include <ArduinoPebbleSerial.h>
static const char* Button_Values[]= {"NONE","BACK", "UP", "SELECT", "DOWN"};
static const uint16_t SUPPORTED_SERVICES[] = {0x0000, 0x1001};
static const uint8_t NUM_SERVICES = 2;
static uint8_t pebble_buffer[GET_PAYLOAD_BUFFER_SIZE(200)];
static String pc_string;
void setup() {
// General init
Serial.begin(115200);
#if defined(__AVR_ATmega32U4__)
ArduinoPebbleSerial::begin_hardware(pebble_buffer, sizeof(pebble_buffer), Baud57600,
SUPPORTED_SERVICES, NUM_SERVICES);
#else
#error "This example will only work for those 32u4 based boards, e.g. Arduino Micro"
#endif
}
void loop() {
// Let the ArduinoPebbleSerial code do its processing
size_t length;
uint16_t service_id;
uint16_t attribute_id;
RequestType type;
if (ArduinoPebbleSerial::feed(&service_id, &attribute_id, &length, &type)) {
if ((service_id == 0x1001) && (attribute_id == 0x1001)) {
// we have a raw data frame to process
if (type == RequestTypeRead) {//Pebble want to read from Arduino
// send a response to the Pebble - reuse the same buffer for the response
uint32_t current_time = millis();
if(pc_string.length()==0){
pc_string = "EMPTY!!";
}
char buf[50];
pc_string.toCharArray(buf, 50);
Serial.print("pc_string.length()");
Serial.println(pc_string.length());
Serial.print("buf");
Serial.println(buf);
memcpy(pebble_buffer, buf, pc_string.length());
pebble_buffer[pc_string.length()]='\0';
Serial.print("pebble_buffer");
Serial.println(pebble_buffer[0]);
ArduinoPebbleSerial::write(true, pebble_buffer, pc_string.length());
Serial.print("Sent message to Pebble");
Serial.println(pc_string);
pc_string = "";
} else if (type == RequestTypeWrite) {//Pebble wrote something to Arduino
Serial.print("Got New Button event: ");
uint8_t button_value = pebble_buffer[0];
uint8_t click_type = pebble_buffer[1];
if(button_value<=4){
Serial.println(Button_Values[button_value]);
}
}
} else {
// unsupported attribute - fail the request
ArduinoPebbleSerial::write(false, NULL, 0);
}
}
static bool is_connected = false;
if (ArduinoPebbleSerial::is_connected()) {
if (!is_connected) {
Serial.println("Connected to the smartstrap!");
is_connected = true;
}
//scan the usb serial port for new input data
if(Serial.available()){
char inChar = (char)Serial.read();
pc_string +=inChar;
if(inChar=='#'){//stop sign
Serial.println("Notifying Pebble: ");
ArduinoPebbleSerial::notify(0x1001, 0x1001);
}
}
} else {
if (is_connected) {
Serial.println("Disconnected from the smartstrap!");
is_connected = false;
}
}
}
Sur le Pebble Cloud, créez un fichier main.c
#include <pebble.h>
#define TIMEOUT_MS 1000
#define MAX_READ_SIZE 100
static Window *s_main_window;
static TextLayer *s_status_layer;
static TextLayer *s_attr_text_layer;
static char s_text_buffer1[20];
static SmartstrapAttribute *s_raw_attribute;
static SmartstrapAttribute *s_attr_attribute;
static void prv_update_text(void) {
if (smartstrap_service_is_available(0x1001)) {
text_layer_set_text(s_status_layer, "Connected!");
} else {
text_layer_set_text(s_status_layer, "Connecting...");
}
}
static void prv_did_read(SmartstrapAttribute *attr, SmartstrapResult result,
const uint8_t *data, size_t length) {
char str[50] = " ";
if (attr == s_attr_attribute) {
APP_LOG(APP_LOG_LEVEL_DEBUG, "did_read(s_attr_attribute, %d, %d)", result, length);
if (result == SmartstrapResultOk ) {
memcpy(str, data, length);
str[length] = '\0';
snprintf(s_text_buffer1, 50, "%s", str);
text_layer_set_text(s_attr_text_layer, s_text_buffer1);
APP_LOG(APP_LOG_LEVEL_DEBUG, "message: %s)", str);
}
}else {
APP_LOG(APP_LOG_LEVEL_ERROR, "did_read(<%p>, %d)", attr, result);
}
}
static void prv_did_write(SmartstrapAttribute *attr, SmartstrapResult result) {
if (attr == s_attr_attribute) {
APP_LOG(APP_LOG_LEVEL_DEBUG, "did_write(s_attr_attribute, %d)", result);
} else {
APP_LOG(APP_LOG_LEVEL_ERROR, "did_write(<%p>, %d)", attr, result);
}
}
static void prv_write_button_action(uint8_t button_value, uint8_t click_type) {
SmartstrapResult result;
if (!smartstrap_service_is_available(smartstrap_attribute_get_service_id(s_attr_attribute))) {
APP_LOG(APP_LOG_LEVEL_DEBUG, "s_attr_attribute is not available");
return;
}
// get the write buffer
uint8_t *buffer = NULL;
size_t length = 0;
result = smartstrap_attribute_begin_write(s_attr_attribute, &buffer, &length);
if (result != SmartstrapResultOk) {
APP_LOG(APP_LOG_LEVEL_ERROR, "Write of s_attr_attribute failed with result %d", result);
return;
}
// write the data into the buffer
buffer[0] = button_value;
buffer[1] = click_type;
// send it off
result = smartstrap_attribute_end_write(s_attr_attribute, 2, false);
if (result != SmartstrapResultOk) {
APP_LOG(APP_LOG_LEVEL_ERROR, "Write of s_attr_attribute failed with result %d", result);
}
}
static void prv_availablility_status_changed(SmartstrapServiceId service_id, bool is_available) {
APP_LOG(APP_LOG_LEVEL_DEBUG, "Availability for 0x%x is %d", service_id, is_available);
prv_update_text();
}
static void prv_notified(SmartstrapAttribute *attr) {
SmartstrapResult result;
if (attr == s_attr_attribute) {
APP_LOG(APP_LOG_LEVEL_DEBUG, "notified(s_attr_attribute)");
result = smartstrap_attribute_read(s_attr_attribute);
if(result != SmartstrapResultOk) {
APP_LOG(APP_LOG_LEVEL_ERROR, "Error reading attribute (<%p>, %d)", attr, result);
}
} else {
APP_LOG(APP_LOG_LEVEL_ERROR, "notified(<%p>)", attr);
}
}
static void up_click_handler(ClickRecognizerRef recognizer, void *context) {
prv_write_button_action(0x02, 0x01);
}
static void select_click_handler(ClickRecognizerRef recognizer, void *context) {
prv_write_button_action(0x03, 0x01);
}
static void down_click_handler(ClickRecognizerRef recognizer, void *context) {
prv_write_button_action(0x04, 0x01);
}
static void click_config_provider(void *context) {
window_single_click_subscribe(BUTTON_ID_UP, up_click_handler);
window_single_click_subscribe(BUTTON_ID_SELECT, select_click_handler);
window_single_click_subscribe(BUTTON_ID_DOWN, down_click_handler);
}
static void prv_main_window_load(Window *window) {
s_status_layer = text_layer_create(GRect(0, 15, 144, 40));
text_layer_set_font(s_status_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28));
prv_update_text();
text_layer_set_text_color(s_status_layer, GColorBlack);
text_layer_set_background_color(s_status_layer, GColorClear);
text_layer_set_text_alignment(s_status_layer, GTextAlignmentCenter);
text_layer_set_overflow_mode(s_status_layer, GTextOverflowModeWordWrap);
layer_add_child(window_get_root_layer(window), text_layer_get_layer(s_status_layer));
s_attr_text_layer = text_layer_create(GRect(0, 60, 144, 40));
text_layer_set_font(s_attr_text_layer, fonts_get_system_font(FONT_KEY_GOTHIC_28));
text_layer_set_text(s_attr_text_layer, "-");
text_layer_set_text_color(s_attr_text_layer, GColorBlack);
text_layer_set_background_color(s_attr_text_layer, GColorClear);
text_layer_set_text_alignment(s_attr_text_layer, GTextAlignmentCenter);
text_layer_set_overflow_mode(s_attr_text_layer, GTextOverflowModeWordWrap);
layer_add_child(window_get_root_layer(window), text_layer_get_layer(s_attr_text_layer));
}
static void prv_main_window_unload(Window *window) {
text_layer_destroy(s_status_layer);
}
static void prv_init(void) {
s_main_window = window_create();
window_set_click_config_provider(s_main_window, click_config_provider);
window_set_window_handlers(s_main_window, (WindowHandlers) {
.load = prv_main_window_load,
.unload = prv_main_window_unload
});
window_stack_push(s_main_window, true);
SmartstrapHandlers handlers = (SmartstrapHandlers) {
.availability_did_change = prv_availablility_status_changed,
.did_write = prv_did_write,
.did_read = prv_did_read,
.notified = prv_notified
};
smartstrap_subscribe(handlers);
smartstrap_set_timeout(50);
s_raw_attribute = smartstrap_attribute_create(0, 0, 2000);
s_attr_attribute = smartstrap_attribute_create(0x1001, 0x1001, 20);
}
static void prv_deinit(void) {
window_destroy(s_main_window);
smartstrap_unsubscribe();
smartstrap_attribute_destroy(s_raw_attribute);
smartstrap_attribute_destroy(s_attr_attribute);
}
int main(void) {
prv_init();
APP_LOG(APP_LOG_LEVEL_DEBUG, "STARTING APP");
if (s_attr_attribute && s_raw_attribute) {
app_event_loop();
}
APP_LOG(APP_LOG_LEVEL_DEBUG, "ENDING APP");
prv_deinit();
}
What this demo does?
- Keep Arduino connected to computer, use a serial monitor to open Arduino’s serial port
- Attach the hacked charging cable to Pebble watch
- Run the Pebble app, the watch will show « connected! »
- Send a string ends with ‘#’ (e.g. « 123abc# » ) to your Arduino’s serial port and watch it displaying on pebble watch.
- Click any of the up/down/select button on pebble and watch it showing on the computer screen.
How it works?
Arduino is receiving string end with‘#’ sign from its usb serial port(Serial) and notify the Watch when ‘#’ sign is detected. The Pebble Watch will then read the string from Arduino.
On the other way the Pebble is sending its 3 button click data to the Arduino, Arduino will print this on the usb serial port.
Références :
http://makezine.com/2015/09/25/hacking-on-the-pebble-smartstrap/
http://www.instructables.com/id/Pebble-time-watch-Smartstrap-Tutorial/
Votre commentaire