diff --git a/PillTracker/PillTracker/ViewController.swift b/PillTracker/PillTracker/ViewController.swift index 2514154..5e3017c 100644 --- a/PillTracker/PillTracker/ViewController.swift +++ b/PillTracker/PillTracker/ViewController.swift @@ -9,7 +9,7 @@ import UIKit class ViewController: UIViewController { var simpleBluetoothIO: SimpleBluetoothIO! - + @IBOutlet var virtualButton:UISwitch! @IBOutlet weak var ledToggleButton: UIButton! @IBOutlet weak var statusLabel: UILabel! @@ -19,30 +19,30 @@ class ViewController: UIViewController { @IBOutlet weak var pillsTotal: UILabel! @IBOutlet weak var pillsAttached: UILabel! @IBOutlet weak var refreshToggle: UISwitch! - + let totalPills: Int = 6 var usedPills: Int = 0 var remainingPills: Int = 0 let updateFreq: Float = 2.0 weak var timer: Timer? - + override func viewDidLoad() { super.viewDidLoad() overrideUserInterfaceStyle = .light simpleBluetoothIO = SimpleBluetoothIO(serviceUUID: "4fafc201-1fb5-459e-8fcc-c5c9c331914b", delegate: self) // startTimer() - + } - + deinit { stopTimer() } - + func sendUpdateCommand(){ print("Sending update command...") simpleBluetoothIO.writeValue(value: 51) } - + func startTimer() { timer?.invalidate() // just in case you had existing `Timer`, `invalidate` it before we lose our reference to it timer = Timer.scheduledTimer(withTimeInterval: TimeInterval(updateFreq), repeats: true) { [weak self] _ in @@ -53,15 +53,15 @@ class ViewController: UIViewController { func stopTimer() { timer?.invalidate() } - + @IBAction func ledToggleButtonDown(_ sender: UIButton) { simpleBluetoothIO.writeValue(value:49) } - + @IBAction func ledToggleButtonUp(_ sender: UIButton) { simpleBluetoothIO.writeValue(value: 50) } - + @IBAction func forcePillRefresh(_ sender: UIButton) { self.sendUpdateCommand() } @@ -72,7 +72,7 @@ class ViewController: UIViewController { stopTimer() } } - + } extension ViewController: SimpleBluetoothIODelegate { @@ -85,12 +85,14 @@ extension ViewController: SimpleBluetoothIODelegate { } else if value == 99 { //view.backgroundColor = UIColor.black virtualButton.setOn(false, animated: true) - } else if value == 55 { + } else if value == 97 { self.pillsConsumed.text = "X" self.pillsRemaining.text = "X" self.pillsTotal.text = "X" self.pillsAttached.text = "Detached" self.pillsAttached.textColor = UIColor.red + } else if value == 96 { + self.pillsAttached.text = "TODO: Battery low..." } else { self.remainingPills = Int(value) self.usedPills = self.totalPills - self.remainingPills @@ -101,7 +103,7 @@ extension ViewController: SimpleBluetoothIODelegate { self.pillsAttached.textColor = UIColor.green } } - + func simpleBluetoothIO(simpleBluetoothIO: SimpleBluetoothIO, didConnect value: Bool) { print("VC: connect: \(value)") self.cStatus.text = "Connected!" @@ -111,7 +113,7 @@ extension ViewController: SimpleBluetoothIODelegate { self.sendUpdateCommand() } } - + func simpleBluetoothIO(simpleBluetoothIO: SimpleBluetoothIO, didDisconnect value: Bool) { print("VC: disconnect: \(value)") self.cStatus.text = "Disconnected..." @@ -119,17 +121,17 @@ extension ViewController: SimpleBluetoothIODelegate { self.pillsAttached.text = "Detached" self.pillsAttached.textColor = UIColor.red } - - + + } extension String { - + func index(at position: Int, from start: Index? = nil) -> Index? { let startingIndex = start ?? startIndex return index(startingIndex, offsetBy: position, limitedBy: endIndex) } - + func character(at position: Int) -> Character? { guard position >= 0, let indexPosition = index(at: position) else { return nil diff --git a/embedded/main/main.ino b/embedded/main/main.ino index c0b24e8..622d3f3 100644 --- a/embedded/main/main.ino +++ b/embedded/main/main.ino @@ -1,3 +1,13 @@ +// +// main.ino +// PillTracker +// +// Created by Max Hunt on 16/01/2021. +// © Max Hunt 2021 + + +// TODODODODODODO: SWITCH AROUND FOR PULLDOWN INPUT SYSTEM AND DEFAULT LOW RAIL OUTPUTS + #include #include #include @@ -7,134 +17,250 @@ #define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b" #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8" -#define LED_PIN 2 -#define BTN_PIN 5 -#define PILL_1_PIN 25 -#define PILL_2_PIN 13 -#define PILL_3_PIN 12 -#define PILL_4_PIN 26 -#define PILL_5_PIN 27 -#define PILL_6_PIN 14 -#define DETECT_PIN 18 +#define LED_PIN 13 +#define TEST_BTN_PIN 5 -int deviceConnected = false; -int waitingForUpdate = 0; +#define MUX_BIT_0 13 +#define MUX_BIT_1 12 +#define MUX_BIT_2 27 +#define MUX_BIT_3 33 +#define MUX_COM 32 + +#define RAIL_EVEN 15 +#define RAIL_ODD 14 + +#define PILL_SENSE 21 + +#define BATTERY_PIN 35 + +// int deviceConnected = false; +bool waiting_for_update = false; +bool pills_plugged_in = false; class MyCallbacks:public BLECharacteristicCallbacks { - void onConnect(BLEServer * pServer) { - deviceConnected = true; - Serial.println("device connected"); - }; - void onDisconnect(BLEServer * pServer) { - deviceConnected = false; - Serial.println("device disconnected"); - } - void onWrite(BLECharacteristic * pCharacteristic) { - std::string value = pCharacteristic -> getValue(); - if (value.length() > 0) { - Serial.print("*********"); - Serial.print(value.c_str()); - Serial.print("-"); - Serial.print(atoi(value.c_str())); - Serial.print("-"); - if (atoi(value.c_str()) == 1) { - digitalWrite(LED_PIN, HIGH); - Serial.print("LEDON"); - } else if (atoi(value.c_str()) == 2) { - digitalWrite(LED_PIN, LOW); - Serial.print("LEDOFF"); - } else if (atoi(value.c_str()) == 3) { - Serial.print("UPDATE_PILL_TRACK"); - waitingForUpdate = 1; - } else { - Serial.println(); - Serial.println(atoi(value.c_str())); - Serial.println(); - } - Serial.println("*********"); - } - } + void onConnect(BLEServer * pServer) { + // deviceConnected = true; + Serial.println("device connected"); + }; + void onDisconnect(BLEServer * pServer) { + // deviceConnected = false; + Serial.println("device disconnected"); + } + void onWrite(BLECharacteristic * pCharacteristic) { + std::string value = pCharacteristic -> getValue(); + if (value.length() > 0) { + if (atoi(value.c_str()) == 1) { + digitalWrite(LED_PIN, HIGH); + Serial.print("LEDON"); + + } else if (atoi(value.c_str()) == 2) { + digitalWrite(LED_PIN, LOW); + Serial.print("LEDOFF"); + + } else if (atoi(value.c_str()) == 3) { + Serial.print("UPDATE_PILL_TRACK"); + waiting_for_update = true; + + } else { + Serial.println("****************** UNEXPECTED MESSAGE!!! ******************"); + Serial.println(atoi(value.c_str())); + Serial.println("****************** END UNEXPECTED MESSAGE!!! ******************"); + } + + } + } }; BLECharacteristic * pCharacteristic; void setup() { - Serial.begin(115200); - pinMode(LED_PIN, OUTPUT); - pinMode(PILL_1_PIN, INPUT_PULLUP); - pinMode(PILL_2_PIN, INPUT_PULLUP); - pinMode(PILL_3_PIN, INPUT_PULLUP); - pinMode(PILL_4_PIN, INPUT_PULLUP); - pinMode(PILL_5_PIN, INPUT_PULLUP); - pinMode(PILL_6_PIN, INPUT_PULLUP); - pinMode(BTN_PIN, INPUT_PULLUP); - pinMode(DETECT_PIN, INPUT_PULLUP); - digitalWrite(LED_PIN, LOW); - Serial.println("1- Download and install an BLE scanner app in your phone"); - Serial.println("2- Scan for BLE devices in the app"); - Serial.println("3- Connect to MyESP32"); - Serial.println("4- Go to CUSTOM CHARACTERISTIC in CUSTOM SERVICE and write something"); - Serial.println("5- See the magic =)"); - BLEDevice::init("PILL_TRACKER"); - BLEServer * pServer = BLEDevice::createServer(); - BLEService * pService = pServer -> createService(SERVICE_UUID); - pCharacteristic = pService -> createCharacteristic( - CHARACTERISTIC_UUID, - BLECharacteristic::PROPERTY_READ | - BLECharacteristic::PROPERTY_WRITE | - BLECharacteristic::PROPERTY_NOTIFY - ); - pCharacteristic -> setCallbacks(new MyCallbacks()); - pCharacteristic -> setValue("Hello World"); - pService -> start(); - BLEAdvertising * pAdvertising = pServer -> getAdvertising(); - pAdvertising -> start(); + Serial.begin(115200); + + pinMode(LED_PIN, OUTPUT); + pinMode(TEST_BTN_PIN, INPUT_PULLUP); + + pinMode(MUX_BIT_0, OUTPUT); + pinMode(MUX_BIT_1, OUTPUT); + pinMode(MUX_BIT_2, OUTPUT); + pinMode(MUX_BIT_3, OUTPUT); + pinMode(MUX_COM, INPUT); + + pinMode(RAIL_EVEN, OUTPUT); + pinMode(RAIL_ODD, OUTPUT); + + pinMode(PILL_SENSE, INPUT_PULLUP); + pinMode(BATTERY_PIN, INPUT); + + digitalWrite(LED_PIN, LOW); + + digitalWrite(RAIL_EVEN, HIGH); + digitalWrite(RAIL_ODD, HIGH); + + digitalWrite(MUX_BIT_0, LOW); + digitalWrite(MUX_BIT_1, LOW); + digitalWrite(MUX_BIT_2, LOW); + digitalWrite(MUX_BIT_3, LOW); + + int debug_btn_previous_value = 0; + + BLEDevice::init("PILL_TRACKER"); + BLEServer * pServer = BLEDevice::createServer(); + BLEService * pService = pServer -> createService(SERVICE_UUID); + pCharacteristic = pService -> createCharacteristic( + CHARACTERISTIC_UUID, + BLECharacteristic::PROPERTY_READ | + BLECharacteristic::PROPERTY_WRITE | + BLECharacteristic::PROPERTY_NOTIFY + ); + pCharacteristic -> setCallbacks(new MyCallbacks()); + pCharacteristic -> setValue("Hello World"); + pService -> start(); + BLEAdvertising * pAdvertising = pServer -> getAdvertising(); + pAdvertising -> start(); } -int prevVal = LOW; -int prevVal2 = LOW; +bool seekValueFromMatrix(int column_id, int row_id) { + + if (column_id > 1 || row_id > 15) { + Serial.println("@@@@@@@@@@@@@@@@@@@@ BINARY ERROR!!! @@@@@@@@@@@@@@@@@@@@"); + } + + int rail_to_GND = 0; + int rail_to_INPUT = 0; + int mux_bit_0 = 0; + int mux_bit_1 = 0; + int mux_bit_2 = 0; + int mux_bit_3 = 0; + bool is_pill_present = false; + + if (column_id == 0) { + rail_to_GND = RAIL_EVEN; + rail_to_INPUT = RAIL_ODD; + } else if (column_id == 1) { + rail_to_GND = RAIL_ODD; + rail_to_INPUT = RAIL_EVEN; + } else { return -1;} + + mux_bit_0 = row_id & 0b1000; + mux_bit_1 = row_id & 0b0100; + mux_bit_2 = row_id & 0b0010; + mux_bit_3 = row_id & 0b0001; + + pinMode(rail_to_INPUT, INPUT); + digitalWrite(rail_to_GND, LOW); + + + digitalWrite(MUX_BIT_0, mux_bit_0); + digitalWrite(MUX_BIT_1, mux_bit_1); + digitalWrite(MUX_BIT_2, mux_bit_2); + digitalWrite(MUX_BIT_3, mux_bit_3); + delay(10); + if (digitalRead(PILL_SENSE) == LOW){ + is_pill_present = true + } + + Serial.println("########## COMPUTED BINARY ##########"); + Serial.print("ROW ID: "); + Serial.print(row_id); + Serial.print(" | BIT 0: "); + Serial.print(mux_bit_0); + Serial.print(" | BIT 1: "); + Serial.print(mux_bit_1); + Serial.print(" | BIT 2: "); + Serial.print(mux_bit_2); + Serial.print(" | BIT 3: "); + Serial.print(mux_bit_3); + Serial.print(" | OBTAINED RESULT: "); + Serial.println(is_pill_present); + Serial.println("########## END COMPUTED BINARY ##########"); + + pinMode(rail_to_INPUT, OUTPUT); + digitalWrite(RAIL_EVEN, HIGH); + digitalWrite(RAIL_ODD, HIGH); + + digitalWrite(MUX_BIT_0, LOW); + digitalWrite(MUX_BIT_1, LOW); + digitalWrite(MUX_BIT_2, LOW); + digitalWrite(MUX_BIT_3, LOW); + + return is_pill_present; +} + + int getPillCount() { - int totalCount = 0; - if (digitalRead(DETECT_PIN) == LOW) { - Serial.println("PROBE_ATTACHED"); - if (digitalRead(PILL_1_PIN) == LOW){totalCount++;Serial.println("25:FULL");} - if (digitalRead(PILL_2_PIN) == LOW){totalCount++;Serial.println("13:FULL");} - if (digitalRead(PILL_3_PIN) == LOW){totalCount++;Serial.println("12:FULL");} - if (digitalRead(PILL_4_PIN) == LOW){totalCount++;Serial.println("26:FULL");} - if (digitalRead(PILL_5_PIN) == LOW){totalCount++;Serial.println("27:FULL");} - if (digitalRead(PILL_6_PIN) == LOW){totalCount++;Serial.println("14:FULL");} - } else { - Serial.println("PROBE_DETACHED"); - totalCount = 55; - } - return totalCount; + int total_pill_count = 0; + if (digitalRead(PILL_SENSE) == LOW) { + Serial.println("PROBE_ATTACHED"); + + for (int col = 0; col < 2; col++){ + for (int row = 0; row < 8; row++){ + bool is_pill_present = false + is_pill_present = seekValueFromMatrix(col, row) + if (is_pill_present == true){ + total_pill_count++; + } + } + } + } else { + Serial.println("PROBE_DETACHED"); + totalCount = 97; + } + return total_pill_count; } +float getVoltage(){ + int sensorValue = analogRead(35); + float theVoltage = (sensorValue/4095.0)*6.6*1.1; + return theVoltage; +} +void printVoltage(){ + Serial.println((String)"\nBattery Voltage: "+getVoltage()+"\n"); +} + +void checkBatteryVoltage() { + float voltage = getVoltage(); + printVoltage(); + if (voltage < 3.5) { + // Automatically notify the phone that battery is low + pCharacteristic -> setValue((uint8_t *) & 96, 4); // NOTE: WTF does the 4 mean?!? + pCharacteristic -> notify(); + } +} + +int loopcounter = 0; void loop() { - // put your main code here, to run repeatedly: - int currentVal = digitalRead(BTN_PIN); - if (currentVal != prevVal) { - prevVal = currentVal; - if (currentVal == HIGH) { - int value = 99; - pCharacteristic -> setValue((uint8_t *) & value, 4); - pCharacteristic -> notify(); - } - else { - int value = 98; - pCharacteristic -> setValue((uint8_t *) & value, 4); - pCharacteristic -> notify(); - } - } - if (waitingForUpdate == 1) { - Serial.println("************************************************************"); - Serial.println("**************UPDATE AND SEND PILL COUNT********************"); - Serial.println("************************************************************"); - waitingForUpdate = 0; - int value = getPillCount(); - pCharacteristic -> setValue((uint8_t *) & value, 4); - pCharacteristic -> notify(); - } + loopcounter++; + if(loopcounter > 50000000){ + loopcounter = 0; + checkBatteryVoltage(); + // TODO: Make a proper voltage to ios bt interface? + } + + int debug_btn_current_value = digitalRead(BTN_PIN); + if (debug_btn_current_value != debug_btn_previous_value) { + debug_btn_previous_value = debug_btn_current_value; + if (debug_btn_current_value == HIGH) { + int debug_value = 99; + pCharacteristic -> setValue((uint8_t *) & debug_value, 4); + pCharacteristic -> notify(); + } + else { + int debug_value = 98; + pCharacteristic -> setValue((uint8_t *) & debug_value, 4); + pCharacteristic -> notify(); + } + } + if (waiting_for_update == true) { + Serial.println("************************************************************"); + Serial.println("**************UPDATE AND SEND PILL COUNT********************"); + Serial.println("************************************************************"); + waiting_for_update = false; + int pill_quantity = getPillCount(); + // pCharacteristic -> setValue("Hello World"); <-- Interesting!?! + pCharacteristic -> setValue((uint8_t *) & pill_quantity, 4); // NOTE: WTF does the 4 mean?!? + pCharacteristic -> notify(); + printVoltage(); + } }