GPS to Pulga
source/main.cpp
- Committer:
- pancotinho
- Date:
- 2019-07-18
- Revision:
- 22:2c6161c96a76
- Parent:
- 21:6cf50085f9f3
- Child:
- 23:7f1c9c1a4c57
File content as of revision 22:2c6161c96a76:
/* mbed Microcontroller Library * Copyright (c) 2017 ARM Limited * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <events/mbed_events.h> #include <stdio.h> #include "mbed.h" #include "platform/Callback.h" #include "events/EventQueue.h" #include "platform/NonCopyable.h" #include "ble/BLE.h" #include "ble/Gap.h" #include "ble/GattClient.h" #include "ble/GapAdvertisingParams.h" #include "ble/GapAdvertisingData.h" #include "ble/GattServer.h" #include "BLEProcess.h" #include "Si1133.h" #include "BME280.h" /* defines the axis for acc */ #define ACC_NOOF_AXIS 3 #define GYR_NOOF_AXIS 2 /* bmi160 slave address */ #define BMI160_ADDR ((0x69)<<1) #define RAD_DEG 57.29577951 using mbed::callback; Si1133 sensor_light(P0_13, P0_15); BME280 sensor_amb(P0_13, P0_15, 0x77 << 1) ; I2C i2c(p13, p15); int msg; int sens; uint32_t lux = 0; uint32_t amb = 0; uint32_t imux = 0; uint32_t imuy = 0; uint32_t imuz = 0; float sensor_get = 0; int16_t acc_sample_buffer[ACC_NOOF_AXIS] = {0x5555, 0x5555, 0x5555}; int16_t gyr_sample_buffer[GYR_NOOF_AXIS] = {0x5555, 0x5555}; double acc_result_buffer[ACC_NOOF_AXIS] = {0x5555, 0x5555, 0x5555}; double gyr_result_buffer[GYR_NOOF_AXIS] = {0x5555, 0x5555}; double accel_ang_x, accel_ang_y; double tiltx, tilty; double tiltx_prev, tilty_prev; char i2c_reg_buffer[2] = {0}; /** * A My service that demonstrate the GattServer features. * * The My service host three characteristics that model the current amb, * led and lux of the My. The value of the lux characteristic is * incremented automatically by the system. * * A client can subscribe to updates of the My characteristics and get * notified when one of the value is changed. Clients can also change value of * the lux, led and amb characteristric. */ class MyService { typedef MyService Self; public: MyService() : _amb_char("00000000-000a-000a-a000-a0a000aa00aa", 0), _lux_char("11111111-111b-111b-b111-b1b111bb11bb", 0), _imux_char("22222222-222c-222c-c222-c2c222cc22cc", 0), _imuy_char("33333333-333d-333d-d333-d3d333dd33dd", 0), // _imuz_char("44444444-444e-444e-e444-e4e444ee44ee", 0), _led_char("55555555-555f-555f-f555-f5f555ff55ff", 0), _My_service( /* uuid */ "51311102-030e-485f-b122-f8f381aa84ed", /* characteristics */ _My_characteristics, /* numCharacteristics */ sizeof(_My_characteristics) / sizeof(_My_characteristics[0]) ), _server(NULL), _event_queue(NULL), _alive_led(P1_13, 1), _actuated_led(P1_14,0) { // update internal pointers (value, descriptors and characteristics array) _My_characteristics[4] = &_led_char; // _My_characteristics[4] = &_imuz_char; _My_characteristics[3] = &_imuy_char; _My_characteristics[2] = &_imux_char; _My_characteristics[1] = &_amb_char; _My_characteristics[0] = &_lux_char; // setup authorization handlers _amb_char.setWriteAuthorizationCallback(this, &Self::authorize_client_write); _imux_char.setWriteAuthorizationCallback(this, &Self::authorize_client_write); _imuy_char.setWriteAuthorizationCallback(this, &Self::authorize_client_write); // _imuz_char.setWriteAuthorizationCallback(this, &Self::authorize_client_write); _lux_char.setWriteAuthorizationCallback(this, &Self::authorize_client_write); _led_char.setWriteAuthorizationCallback(this, &Self::authorize_client_write); } void start(BLE &ble_interface, events::EventQueue &event_queue) { if (_event_queue) { return; } _server = &ble_interface.gattServer(); _event_queue = &event_queue; // register the service printf("Adding demo service\r\n"); ble_error_t err = _server->addService(_My_service); if (err) { printf("Error %u during demo service registration.\r\n", err); return; } // read write handler _server->onDataSent(as_cb(&Self::when_data_sent)); _server->onDataWritten(as_cb(&Self::when_data_written)); _server->onDataRead(as_cb(&Self::when_data_read)); // updates subscribtion handlers _server->onUpdatesEnabled(as_cb(&Self::when_update_enabled)); _server->onUpdatesDisabled(as_cb(&Self::when_update_disabled)); _server->onConfirmationReceived(as_cb(&Self::when_confirmation_received)); // print the handles printf("My service registered\r\n"); printf("service handle: %u\r\n", _My_service.getHandle()); printf("\tamb characteristic value handle %u\r\n", _amb_char.getValueHandle()); printf("\timu characteristic value handle %u\r\n", _imux_char.getValueHandle()); printf("\timu characteristic value handle %u\r\n", _imuy_char.getValueHandle()); // printf("\timu characteristic value handle %u\r\n", _imuz_char.getValueHandle()); printf("\tlux characteristic value handle %u\r\n", _lux_char.getValueHandle()); printf("\tled characteristic value handle %u\r\n", _led_char.getValueHandle()); _event_queue->call_every(1741 /* ms */, callback(this, &Self::update_char)); _event_queue->call_every(1621 /* ms */, callback(this, &Self::read_sensors)); _event_queue->call_every(503 /* ms */, callback(this, &Self::blink)); } private: /** * Handler called when a notification or an indication has been sent. */ void when_data_sent(unsigned count) { printf("sent %u updates\r\n", count); } /** * Handler called after an attribute has been written. */ void when_data_written(const GattWriteCallbackParams *e) { printf("data written:\r\n"); printf("\tconnection handle: %u\r\n", e->connHandle); printf("\tattribute handle: %u", e->handle); if (e->handle == _amb_char.getValueHandle()) { printf(" (amb characteristic)\r\n"); } else if (e->handle == _led_char.getValueHandle()) { printf(" (led characteristic)\r\n"); _actuated_led = *(e->data); } else if (e->handle == _lux_char.getValueHandle()) { printf(" (lux characteristic)\r\n"); } else if (e->handle == _imux_char.getValueHandle()) { printf(" (imu_x characteristic)\r\n"); } else if (e->handle == _imuy_char.getValueHandle()) { printf(" (imu_y characteristic)\r\n"); // } else if (e->handle == _imuz_char.getValueHandle()) { // printf(" (imu_z characteristic)\r\n"); } else { printf("\r\n"); } printf("\twrite operation: %u\r\n", e->writeOp); printf("\toffset: %u\r\n", e->offset); printf("\tlength: %u\r\n", e->len); printf("\t data: "); for (size_t i = 0; i < e->len; ++i) { printf("%02X", e->data[i]); } printf("\r\n"); } /** * Handler called after an attribute has been read. */ void when_data_read(const GattReadCallbackParams *e) { printf("data read:\r\n"); printf("\tconnection handle: %u\r\n", e->connHandle); printf("\tattribute handle: %u", e->handle); if (e->handle == _amb_char.getValueHandle()) { printf(" (amb characteristic)\r\n"); } else if (e->handle == _led_char.getValueHandle()) { printf(" (led characteristic)\r\n"); } else if (e->handle == _lux_char.getValueHandle()) { printf(" (lux characteristic)\r\n"); } else if (e->handle == _imux_char.getValueHandle()) { printf(" (imu_x characteristic)\r\n"); } else if (e->handle == _imuy_char.getValueHandle()) { printf(" (imu_y characteristic)\r\n"); // } else if (e->handle == _imuz_char.getValueHandle()) { // printf(" (imu_z characteristic)\r\n"); } else { printf("\r\n"); } } /** * Handler called after a client has subscribed to notification or indication. * * @param handle Handle of the characteristic value affected by the change. */ void when_update_enabled(GattAttribute::Handle_t handle) { printf("update enabled on handle %d\r\n", handle); } /** * Handler called after a client has cancelled his subscription from * notification or indication. * * @param handle Handle of the characteristic value affected by the change. */ void when_update_disabled(GattAttribute::Handle_t handle) { printf("update disabled on handle %d\r\n", handle); } /** * Handler called when an indication confirmation has been received. * * @param handle Handle of the characteristic value that has emitted the * indication. */ void when_confirmation_received(GattAttribute::Handle_t handle) { printf("confirmation received on handle %d\r\n", handle); } /** * Handler called when a write request is received. * * This handler verify that the value submitted by the client is valid before * authorizing the operation. */ void authorize_client_write(GattWriteAuthCallbackParams *e) { printf("characteristic %u write authorization\r\n", e->handle); if (e->offset != 0) { printf("Error invalid offset\r\n"); e->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_OFFSET; return; } if (e->len != 1) { printf("Error invalid len\r\n"); e->authorizationReply = AUTH_CALLBACK_REPLY_ATTERR_INVALID_ATT_VAL_LENGTH; return; } e->authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS; } /** * Increment the lux luxer. */ void read_sensors (void) { int32_t float_to_32; if (sensor_light.open() && sens==0) { float_to_32=0; sensor_get = sensor_light.get_light_level(); float_to_32 = sensor_get/10; //float_to_32 = __rev( float_to_32 ); float_to_32 = (float_to_32 < 0 ? 0 : float_to_32); lux = (float_to_32 > 255 ? 255 : float_to_32); sens=1; printf("Lux = %f\n", sensor_get); } if (sens==1) { float_to_32=0; sensor_amb.initialize(); sensor_get = sensor_amb.getTemperature(); float_to_32 = sensor_get*10 -103 ; float_to_32 = (float_to_32 < 0 ? 0 : float_to_32); amb = (float_to_32 > 255 ? 255 : float_to_32); sens=2; printf("Amb = %f\n", sensor_get); } if (sens==2) { i2c.frequency(20000); /*Le os Registradores do Acelerometro*/ i2c_reg_buffer[0] = 0x12; i2c.write(BMI160_ADDR, i2c_reg_buffer, 1, true); i2c.read(BMI160_ADDR, (char *)&acc_sample_buffer, sizeof(acc_sample_buffer), false); /*Le os Registradores do Giroscopio*/ i2c_reg_buffer[0] = 0x0C; i2c.write(BMI160_ADDR, i2c_reg_buffer, 1, true); i2c.read(BMI160_ADDR, (char *)&gyr_sample_buffer, sizeof(gyr_sample_buffer), false); /*Ajusta dados brutos Acelerometro em unidades de g */ acc_result_buffer[0] = (acc_sample_buffer[0]/16384.0); acc_result_buffer[1] = (acc_sample_buffer[1]/16384.0); acc_result_buffer[2] = (acc_sample_buffer[2]/16384.0); /*Ajusta dados Brutos do Giroscopio em unidades de deg/s */ gyr_result_buffer[0] = (gyr_sample_buffer[0]/131.2); gyr_result_buffer[1] = (gyr_sample_buffer[1]/131.2); /*Calcula os Angulos de Inclinacao com valor do Acelerometro*/ accel_ang_x=atan(acc_result_buffer[0]/sqrt(pow(acc_result_buffer[1],2) + pow(acc_result_buffer[2],2)))*RAD_DEG; accel_ang_y=atan(acc_result_buffer[1]/sqrt(pow(acc_result_buffer[0],2) + pow(acc_result_buffer[2],2)))*RAD_DEG; /*Calcula os Angulos de Rotacao com valor do Giroscopio e aplica filtro complementar realizando a fusao*/ tiltx = (0.98*(tiltx_prev+(gyr_result_buffer[0]*0.001)))+(0.02*(accel_ang_x)); tilty = (0.98*(tilty_prev+(gyr_result_buffer[1]*0.001)))+(0.02*(accel_ang_y)); float_to_32 = tiltx * 100 + 127; float_to_32 = (float_to_32 < 0 ? 0 : float_to_32); imux = (float_to_32 > 255 ? 255 : float_to_32); float_to_32 = 0; float_to_32 = tilty * 100 + 127; float_to_32 = (float_to_32 < 0 ? 0 : float_to_32); imuy = (float_to_32 > 255 ? 255 : float_to_32); //imuz = acc_result_buffer[2]; /*Imprime os dados ACC pre-formatados*/ printf("%.3f,%.3f\n\r",tiltx, tilty); sens=0; // update_char(); } //update_char(); } void update_char(void) { if (msg==0) {ble_error_t err = _lux_char.set(*_server, lux); printf ("lux sensor value: %d\n", lux); if (err) { printf("write of the lux value returned error %u\r\n", err); return; } wait(0.1); msg=1; } if (msg==1) {ble_error_t err = _amb_char.set(*_server, amb); printf ("amb sensor value: %d\n", amb); if (err) { printf("write of the amb value returned error %u\r\n", err); return; } wait(0.1); msg=2;} if (msg==2) {ble_error_t err = _imux_char.set(*_server, imux); printf ("imu_x sensor value: %d\n", imux); if (err) { printf("write of the imu_x value returned error %u\r\n", err); return; } wait(0.1); msg=3;} if (msg==3) {ble_error_t err = _imuy_char.set(*_server, imuy); printf ("imu_y sensor value: %d\n", imuy); if (err) { printf("write of the imu_y value returned error %u\r\n", err); return; } wait(0.1); msg=0;} // err = _imuz_char.set(*_server, imuz); // printf ("imu_z sensor value: %d\n", imuz); // if (err) { // printf("write of the imu_z value returned error %u\r\n", err); // return; // } } void blink() { _alive_led = !_alive_led; } /** * Change led status. */ void change_led(void) { uint8_t led = 0; ble_error_t err = _led_char.get(*_server, led); if (err) { printf("read of the led value returned error %u\r\n", err); return; } } private: /** * Helper that construct an event handler from a member function of this * instance. */ template<typename Arg> FunctionPointerWithContext<Arg> as_cb(void (Self::*member)(Arg)) { return makeFunctionPointer(this, member); } /** * Read, Write, Notify, Indicate Characteristic declaration helper. * * @tparam T type of data held by the characteristic. */ template<typename T> class ReadWriteNotifyIndicateCharacteristic : public GattCharacteristic { public: /** * Construct a characteristic that can be read or written and emit * notification or indication. * * @param[in] uuid The UUID of the characteristic. * @param[in] initial_value Initial value contained by the characteristic. */ ReadWriteNotifyIndicateCharacteristic(const UUID & uuid, const T& initial_value) : GattCharacteristic( /* UUID */ uuid, /* Initial value */ (uint8_t *) &_value, /* Value size */ sizeof(_value), /* Value capacity */ sizeof(_value), /* Properties */ GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE, /* Descriptors */ NULL, /* Num descriptors */ 0, /* variable len */ false ), _value(initial_value) { } /** * Get the value of this characteristic. * * @param[in] server GattServer instance that contain the characteristic * value. * @param[in] dst Variable that will receive the characteristic value. * * @return BLE_ERROR_NONE in case of success or an appropriate error code. */ ble_error_t get(GattServer &server, T& dst) const { uint16_t value_length = sizeof(dst); return server.read(getValueHandle(), (uint8_t *) &dst, &value_length); } /** * Assign a new value to this characteristic. * * @param[in] server GattServer instance that will receive the new value. * @param[in] value The new value to set. * @param[in] local_only Flag that determine if the change should be kept * locally or forwarded to subscribed clients. */ ble_error_t set( GattServer &server, const uint8_t &value, bool local_only = false ) const { return server.write(getValueHandle(), (uint8_t *) &value, sizeof(value), local_only); } private: uint32_t _value; }; template<typename T> class ReadWriteCharacteristic : public GattCharacteristic { public: /** * Construct a characteristic that can be read or written and emit * notification or indication. * * @param[in] uuid The UUID of the characteristic. * @param[in] initial_value Initial value contained by the characteristic. */ ReadWriteCharacteristic(const UUID & uuid, const T& initial_value) : GattCharacteristic( /* UUID */ uuid, /* Initial value */ (uint8_t *) &_value, /* Value size */ sizeof(_value), /* Value capacity */ sizeof(_value), /* Properties */ GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE , /* Descriptors */ NULL, /* Num descriptors */ 0, /* variable len */ false ), _value(initial_value) { } /** * Get the value of this characteristic. * * @param[in] server GattServer instance that contain the characteristic * value. * @param[in] dst Variable that will receive the characteristic value. * * @return BLE_ERROR_NONE in case of success or an appropriate error code. */ ble_error_t get(GattServer &server, T& dst) const { uint16_t value_length = sizeof(dst); return server.read(getValueHandle(), (uint8_t *) &dst, &value_length); } /** * Assign a new value to this characteristic. * * @param[in] server GattServer instance that will receive the new value. * @param[in] value The new value to set. * @param[in] local_only Flag that determine if the change should be kept * locally or forwarded to subscribed clients. */ ble_error_t set( GattServer &server, const uint8_t &value, bool local_only = false ) const { return server.write(getValueHandle(), (uint8_t *) &value, sizeof(value), local_only); } private: uint8_t _value; }; ReadWriteNotifyIndicateCharacteristic<uint32_t> _amb_char; ReadWriteCharacteristic<uint8_t> _led_char; ReadWriteNotifyIndicateCharacteristic<uint32_t> _lux_char; ReadWriteNotifyIndicateCharacteristic<uint32_t> _imux_char; ReadWriteNotifyIndicateCharacteristic<uint32_t> _imuy_char; // ReadWriteNotifyIndicateCharacteristic<uint32_t> _imuz_char; // list of the characteristics of the My service GattCharacteristic* _My_characteristics[5]; // demo service GattService _My_service; GattServer* _server; events::EventQueue *_event_queue; DigitalOut _alive_led; DigitalOut _actuated_led; }; int main() { printf("ambient sensor initialized"); wait(1) ; BLE &ble_interface = BLE::Instance(); events::EventQueue event_queue; MyService demo_service; BLEProcess ble_process(event_queue, ble_interface); i2c.frequency(20000); /*Reset BMI160*/ i2c_reg_buffer[0] = 0x7E; i2c_reg_buffer[1] = 0xB6; i2c.write(BMI160_ADDR, i2c_reg_buffer, sizeof(i2c_reg_buffer), false); wait_ms(200); printf("BMI160 Resetado\n\r"); /*Habilita o Acelerometro*/ i2c_reg_buffer[0] = 0x7E; i2c_reg_buffer[1] = 0x11; //PMU Normal i2c.write(BMI160_ADDR, i2c_reg_buffer, sizeof(i2c_reg_buffer), false); printf("Acc Habilitado\n\r"); /*Habilita o Giroscopio*/ i2c_reg_buffer[0] = 0x7E; i2c_reg_buffer[1] = 0x15; //PMU Normal i2c.write(BMI160_ADDR, i2c_reg_buffer, sizeof(i2c_reg_buffer), false); printf("Gyr Habilitado\n\r"); /*Config o Data Rate ACC em 1600Hz*/ i2c_reg_buffer[0] = 0x40; i2c_reg_buffer[1] = 0x2C; i2c.write(BMI160_ADDR, i2c_reg_buffer, sizeof(i2c_reg_buffer), false); printf("Data Rate ACC Selecionado a 1600Hz\n\r"); /*Config o Data Rate GYR em 1600Hz*/ i2c_reg_buffer[0] = 0x42; i2c_reg_buffer[1] = 0x2C; i2c.write(BMI160_ADDR, i2c_reg_buffer, sizeof(i2c_reg_buffer), false); printf("Data Rate GYR Selecionado a 1600Hz\n\r"); /*Config o Range GYR em 250º/s*/ i2c_reg_buffer[0] = 0x43; i2c_reg_buffer[1] = 0x03; i2c.write(BMI160_ADDR, i2c_reg_buffer, sizeof(i2c_reg_buffer), false); printf("Range GYR Selecionado a 250deg/s\n\r"); wait(0.1); printf("BMI160 Configurado\n\r"); ble_process.on_init(callback(&demo_service, &MyService::start)); // bind the event queue to the ble interface, initialize the interface // and start advertising ble_process.start(); // Process the event queue. event_queue.dispatch_forever(); return 0; }