ECE 4180 Medication Adherence Smart Pill-Dispenser Prototype
Smart Pill-Dispenser
Group Member: Xiannan Di, Yuhao Lin, Zhipeng Shao
Description
This design is created for ECE 4180 final project as well as for an initial prototype of ECE 4011/4012 Senior Design project. For more information on our Senior Design project on Medication Adherence, please check out our proposal.
This prototype utilizes nRF52 board's built-in BLE function to receive commands from smartphone app. The LCD screen will display the commanded number of pills each time. The dispenser, based on a small geared DC motor driven by MOSFET, revolves and drops the specified amount of pills at a constant rate.
Parts List
- Nordic nRF52-DK
- uLCD-144-G2 128 by 128 Smart Color LCD
- Power MOSFET breakout board
- DC Motor
- SN74HC04 inverter
Software
The nRF Connect is a mobile app developed by Nordic Semiconductor. It is available on both iOS and Android, and supports BLE communication with the nRF52-DK board.
Schematic
Source Code
main.cpp
#include "mbed.h" #include "ble/BLE.h" #include "uLCD_4DGL.h" uLCD_4DGL uLCD(p6,p8,p11); BLEDevice ble; DigitalOut led(LED1); PwmOut Ctrl(p19); DigitalOut drop_led(LED2); uint16_t PILL_SERVICE_UUID = 0xA000; // service UUID uint16_t readCharUUID = 0xA001; // read characteristic UUID uint16_t writeCharUUID = 0xA002; // write characteristic UUID int pill_num = 0; const static char DEVICE_NAME[] = "PILL_DROP"; static const uint16_t uuid16_list[] = {PILL_SERVICE_UUID}; static uint8_t readValue[1] = {0}; ReadOnlyArrayGattCharacteristic<uint8_t, sizeof(readValue)> readChar(readCharUUID, readValue); static uint8_t writeValue[1] = {0}; WriteOnlyArrayGattCharacteristic<uint8_t, sizeof(writeValue)> writeChar(writeCharUUID, writeValue); // Set up pill service GattCharacteristic *characteristics[] = {&readChar, &writeChar}; GattService pillService(PILL_SERVICE_UUID, characteristics, sizeof(characteristics) / sizeof(GattCharacteristic *)); void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) { //(void) params; BLE::Instance().gap().startAdvertising(); } /* * handle writes to writeCharacteristic */ void writeCharCallback(const GattWriteCallbackParams *params) { // check to see what characteristic was written, by handle if(params->handle == writeChar.getValueHandle() && params->len == 1) { pill_num = params->data[0]; led = params->data[0]; uLCD.printf("%x pill(s)\n\r",pill_num);// //(params->data[0] == 0x00) ? printf("\n\rled on ") : printf("\n\rled off "); // print led toggle for(int i = 1; i <= pill_num; i++){ Ctrl = 0.95f; drop_led = 1; wait(7); Ctrl = 1.0f; drop_led = 0; wait(5); } //Pill drop code ble.updateCharacteristicValue(readChar.getValueHandle(), params->data,params->len); } // update the readChar with the value of writeChar } /* * main loop */ int main(void) { Ctrl = 1.0f; /* Initialization */ ble.init(); ble.gap().onDisconnection(disconnectionCallback); ble.gattServer().onDataWritten(writeCharCallback); /* setup advertising */ // BLE only, no classic BT ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list)); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); /* 1000ms. */ ble.gap().setAdvertisingInterval(1000); /* 1000ms. */ ble.addService(pillService); ble.gap().startAdvertising(); uLCD.printf("Hello, BLE connection successful\n\r"); // infinite loop waiting for BLE interrupt events while (true) { ble.waitForEvent(); //Save power } }
Photos
Demo Video
Please log in to post comments.