Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: BLE_API nRF51822 mbed
Fork of KS7 by
main.cpp
- Committer:
- akita11
- Date:
- 2016-04-04
- Branch:
- KS3
- Revision:
- 27:8c3c29b3f704
- Parent:
- 25:da723b86c60b
- Child:
- 28:d8c652994988
File content as of revision 27:8c3c29b3f704:
#include "mbed.h"
#include "io.h"
#include "BLE.h"
#include "DFUService.h"
#include "common.h"
#include <stdlib.h>
#define DISPLAY_DEMO // display random number for demo & LED check
// BLE
#define INTERVAL_500MSEC (500UL)
#define CONNTIMEOUT_3000MSEC (3000UL)
#define ADV_TIMEOUT (0)
#define DEVICE_NAME "Kitchen Scale"
#define BLE_TXPOWER_4DBM (4)
// Device Information Service (DIS) (20 character limit)
// https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.device_information.xml
#define MANUFACTURER_NAME_STRING "Hacarus" // Manufacturer Name String - shall represent the name of the manufacturer of the device.
#define MODEL_NUMBER_STRING "0001" // Model Number String - shall represent the model number that is assigned by the device vendor.
#define SERIAL_NUMBER_STRING "000780c0ffeef00d" // Serial Number String - shall represent the serial number for a particular instance of the device.
#define FIRMWARE_REVISION_STRING "v1.00.009@rev0023" // Firmware Revision String - shall represent the firmware revision for the firmware within the device.
// Weight Scale Service (Original)
#define UUID_WEIGHT_SCALE_SERVICE (0x181D)
#if defined(PCB_VER1) || defined(PCB_VER2)
// Switch
#define SW_THRESHOLD (0.5)
#define SW_SAMPLECOUNT (3)
#endif
// Mode
#define MODE_OFF (0) // LED OFF
#define MODE_START (1) // LED OFF -> ON
#define MODE_ON (2) // LED ON
#define MODE_END (3) // LED ON -> OFF
// Led
#define LED_INTERVAL_MSEC (100)
#define BRIGHTNESS_ADDVALUE (0.1)
#define BRIGHTNESS_MINVALUE (0.0)
#define BRIGHTNESS_MAXVALUE (1.0)
// Properties
//io io;
io io(P0_15, P0_13); // HX711's CLK & DAT
//io(P0_5, P0_4); // HX711's CLK & DAT for BLEnano debug
uint32_t weight_data;
float32_t weight = 0.0;
uint32_t scale = 0;
int update_counter = 0;
#if defined(PCB_VER1) || defined(PCB_VER2)
float sw_data[SW_SAMPLECOUNT];
uint8_t sw_count = 0;
#endif
int led_mode = MODE_OFF;
float led_brightness = BRIGHTNESS_MINVALUE;
#ifdef UART_DEBUG
#if defined(PCB_VER1) || defined(PCB_VER2)
Serial pc(P0_9, P0_8);// TX=P0_9
#else
Serial pc(P0_9, P0_11);// TX=P0_9
#endif
#define UART_BAUD_RATE (9600UL)
#define DEBUG(...) { pc.printf(__VA_ARGS__); }
#else
#define DEBUG(...) {}
#endif
Timer t;
// BLE
BLE ble;
Gap::ConnectionParams_t connectionParams;
/* Complete list of 16-bit Service IDs */
uint16_t uuid16_list[] = {GattService::UUID_DEVICE_INFORMATION_SERVICE};
/* Weight Scale Service */
static const uint8_t UUID_HACARUS_WEIGHT_CHAR[] = {0x00, 0x00, 0x2A, 0x9D, 0x00, 0x01, 0x00, 0x01, 0x00, 'H','a', 'c', 'a', 'r','u', 's'};
GattCharacteristic WeightMeasurement (UUID(UUID_HACARUS_WEIGHT_CHAR), (uint8_t *)&weight_data, sizeof(weight_data), sizeof(weight_data),
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
static const uint8_t UUID_HACARUS_SCALE_CHAR[] = {0x00, 0x00, 0x2A, 0x9E, 0x00, 0x01, 0x00, 0x01, 0x00, 'H','a', 'c', 'a', 'r','u', 's'};
GattCharacteristic WeightScale (UUID(UUID_HACARUS_SCALE_CHAR), (uint8_t *)&scale, sizeof(scale), sizeof(scale),
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_WRITE);
GattCharacteristic *Chars[] = {&WeightMeasurement,&WeightScale};
static const uint8_t UUID_HACARUS_WEIGHT_SERVICE[] = {0x00, 0x00, 0x18, 0x1D, 0x00, 0x01, 0x00, 0x01, 0x00, 'H','a', 'c', 'a', 'r','u', 's'};
GattService HWS = GattService(UUID(UUID_HACARUS_WEIGHT_SERVICE), Chars, sizeof(Chars) / sizeof(GattCharacteristic *));
/* Device Information Service */
GattCharacteristic ManuName(GattCharacteristic::UUID_MANUFACTURER_NAME_STRING_CHAR, (uint8_t *)&MANUFACTURER_NAME_STRING, sizeof(MANUFACTURER_NAME_STRING) - 1, sizeof(MANUFACTURER_NAME_STRING) - 1,
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
GattCharacteristic ModelNum(GattCharacteristic::UUID_MODEL_NUMBER_STRING_CHAR, (uint8_t *)&MODEL_NUMBER_STRING, sizeof(MODEL_NUMBER_STRING) - 1, sizeof(MODEL_NUMBER_STRING) - 1,
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
GattCharacteristic SerialNum(GattCharacteristic::UUID_SERIAL_NUMBER_STRING_CHAR, (uint8_t *)&SERIAL_NUMBER_STRING, sizeof(SERIAL_NUMBER_STRING) - 1, sizeof(SERIAL_NUMBER_STRING) - 1,
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
GattCharacteristic FWVersion(GattCharacteristic::UUID_FIRMWARE_REVISION_STRING_CHAR, (uint8_t *)&FIRMWARE_REVISION_STRING, sizeof(FIRMWARE_REVISION_STRING) - 1, sizeof(FIRMWARE_REVISION_STRING) - 1,
GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
GattCharacteristic *DISChars[] = {&ManuName, &ModelNum, &SerialNum, &FWVersion};
GattService DIS(GattService::UUID_DEVICE_INFORMATION_SERVICE , DISChars, sizeof(DISChars) / sizeof(GattCharacteristic *));
#ifdef PCB_VER1
bool check_joystick()
{
float sum_data = 0;
sw_data[sw_count] = io.get_x();
if(++sw_count >= SW_SAMPLECOUNT) {
sw_count = 0;
}
for(int count = 0; count < SW_SAMPLECOUNT; count++) {
sum_data += sw_data[count];
}
return ((sum_data / SW_SAMPLECOUNT) >= SW_THRESHOLD);
}
#endif
uint32_t quick_ieee11073_from_float(float data)
{
uint8_t exponent = 0xFE; //exponent is -2
uint32_t mantissa = (uint32_t)(data*100);
return ( ((uint32_t)exponent) << 24) | mantissa;
}
#if defined(PCB_VER1) || defined(PCB_VER2)
void SWInit(void)
{
// SW Initialize
for(int count = 0; count < SW_SAMPLECOUNT; count++) {
sw_data[count] = 0;
}
}
#endif
void AppInit(void)
{
#if defined(PCB_VER1) || defined(PCB_VER2)
SWInit();
#endif
io.analog_pow(1);
#ifdef PCB_VER3
// check XTALFREQ for TaiyoYuden module in PCB_VER3
/*
if(NRF_UICR->XTALFREQ == 0xFFFFFF00){
io.display_value = 3232;
}else if(NRF_UICR->XTALFREQ == 0xFFFFFFFF){
io.display_value = 1616;
}
*/
#endif
}
/*
* BLE CallBacks
*/
void BLEConnectionCallback(const Gap::ConnectionCallbackParams_t *params)
{
ble.updateConnectionParams(params->handle, params->connectionParams);
}
void BLEDisconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
{
if(led_mode == MODE_ON) {
ble.startAdvertising();
}
}
void BLERadioNotificationCallback(bool radio_active)
{
if (radio_active == false) {
if(led_mode == MODE_ON) {
}
}
}
void BleInitialize(void)
{
uint8_t advertiseServiceID[16];
// Initialize
ble.init();
// Event Set
ble.onConnection(&BLEConnectionCallback);
ble.onDisconnection(&BLEDisconnectionCallback);
ble.onRadioNotification(&BLERadioNotificationCallback);
ble.getPreferredConnectionParams(&connectionParams);
connectionParams.maxConnectionInterval = INTERVAL_500MSEC;
connectionParams.minConnectionInterval = INTERVAL_500MSEC;
connectionParams.connectionSupervisionTimeout = CONNTIMEOUT_3000MSEC;
connectionParams.slaveLatency = 2;
ble.setPreferredConnectionParams(&connectionParams);
ble.setTxPower(BLE_TXPOWER_4DBM);
for(int i=0; i<16; i++) {
advertiseServiceID[i] = UUID_HACARUS_WEIGHT_SERVICE[16 - 1 - i];
}
ble.accumulateAdvertisingPayload((GapAdvertisingData::Flags)(GapAdvertisingData::LE_GENERAL_DISCOVERABLE | GapAdvertisingData::BREDR_NOT_SUPPORTED));
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME,
(const uint8_t *)DEVICE_NAME,
strlen(DEVICE_NAME));
ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_128BIT_SERVICE_IDS,
(const uint8_t *)advertiseServiceID, sizeof(advertiseServiceID));
ble.setAdvertisingInterval(INTERVAL_500MSEC);
ble.setAdvertisingTimeout(ADV_TIMEOUT); /* 0 is disable the advertising timeout. */
ble.addService(HWS);
ble.addService(DIS);
DFUService dfu(ble);
}
int main()
{
float weight_s;
int Navg = 5;
int sample = 0;
#ifdef UART_DEBUG
pc.baud(UART_BAUD_RATE);
/*
pc.printf("SPI->PSELSCK = %x\r\n", NRF_SPI0->PSELSCK); // will be 15 (P0_15)
pc.printf("SPI->PSELMISO = %x\r\n", NRF_SPI0->PSELMISO); // will be 13 (P0_13)
pc.printf("SPI->PSELMOSI = %x\r\n", NRF_SPI0->PSELMOSI); // will be 14 (P0_14): dummy
pc.printf("SPI->PSELSCK = %x\r\n", NRF_SPI1->PSELSCK); // will be 15 (P0_15)
pc.printf("SPI->PSELMISO = %x\r\n", NRF_SPI1->PSELMISO); // will be 13 (P0_13)
pc.printf("SPI->PSELMOSI = %x\r\n", NRF_SPI1->PSELMOSI); // will be 14 (P0_14): dummy
io.analog_pow(1);
while(1){
pc.printf("%x\r\n", io._get_adc_raw(0));
}
*/
#endif
#ifdef PCB_VER3
// set XTAL=32MHz for TaiyoYuden's module
// is moved to mbed-src/targets/cmsis/TARGET_NORDIC/TARGET_MCU_NRF51822/system_nrf51.c
DEBUG("UICR->XTALFREQ=%x\r\n", NRF_UICR->XTALFREQ); // this should be 0xffffff00, not 0xffffffff
#endif
BleInitialize();
AppInit();
led_mode = MODE_OFF;
#ifdef DISPLAY_DEMO
uint16_t d = 0;
uint8_t demo_count = 0;
led_mode = MODE_START; // for debug mode
#endif
for (;; ) {
// 100msec waitForEvent
t.reset();
while(t.read_ms() < LED_INTERVAL_MSEC) {
t.start();
ble.waitForEvent();
t.stop();
}
switch(led_mode) {
case MODE_OFF:
io.analog_pow(0);
io.display(0);
if(io.get_switch()) {
led_mode = MODE_START;
}
break;
case MODE_START:
io.analog_pow(1);
io.power_save_mode(0);
led_brightness += BRIGHTNESS_ADDVALUE;
io.display(led_brightness);
if(led_brightness >= BRIGHTNESS_MAXVALUE) {
update_counter = 0;
io.calibrate_weight();
#if defined(PCB_VER1) || defined(PCB_VER2)
SWInit();
#endif
ble.startAdvertising();
led_mode = MODE_ON;
weight_s = 0.0;
sample = 0;
}
break;
case MODE_ON:
#ifdef UART_DEBUG
// pc.printf("%d %d %.2f\r\n", io.get_switch(), io.get_weight_raw(), io.get_weight());
#endif
io.analog_pow(1);
#ifdef DISPLAY_DEMO
demo_count++;
if (demo_count == 10){
demo_count = 0;
io.display_value = d++; // increment display value for every 1s in demo mode
}
#else
if(io.get_switch()) {
led_mode = MODE_END;
if(ble.getGapState().connected) {
ble.disconnect(Gap::REMOTE_USER_TERMINATED_CONNECTION);
} else {
ble.stopAdvertising();
}
} else {
scale++;
ble.updateCharacteristicValue(WeightScale.getValueAttribute().getHandle(),
(uint8_t *)&scale,
sizeof(scale));
weight_s += io.get_weight();
sample++;
if (sample == Navg){
weight = weight_s / (float)Navg;
io.display_value = (uint16_t)weight;
weight_s = 0.0;
sample = 0;
}
// pc.printf("weight=%.1f\r\n", weight);
// io.display_value = 8888; // for LED soldering check
#ifdef UART_DEBUG
// pc.printf("%d\r\n", io._get_adc_raw(0));
// pc.printf("weight=%f %d / %d\r\n", weight, io.display_value, io._adc0);
#endif
if(++update_counter >= 5) {
weight_data = quick_ieee11073_from_float(weight);
ble.updateCharacteristicValue(WeightMeasurement.getValueAttribute().getHandle(),
(uint8_t *)&weight_data,
sizeof(weight_data));
update_counter = 0;
}
}
#endif
break;
case MODE_END:
led_brightness -= BRIGHTNESS_ADDVALUE;
io.display(led_brightness);
if(led_brightness <= BRIGHTNESS_MINVALUE) {
#if defined(PCB_VER1) || defined(PCB_VER2)
SWInit();
#endif
led_mode = MODE_OFF;
io.power_save_mode(1);
}
break;
}
}
}
