aboutsummaryrefslogtreecommitdiff
path: root/sensor/sensor.ino
blob: a05d6cc120ca16521db5ae74310edb736b9555a4 (plain)
  1. // SPDX-FileCopyrightText: 2025 Amal Mazrah <mazrah@ruc.dk>
  2. // SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk>
  3. // SPDX-FileCopyrightText: 2025 Mennatullah Hatim Kassim <stud-mennatulla@ruc.dk>
  4. // SPDX-FileCopyrightText: 2025 Noor Ahmad <noora@ruc.dk>
  5. // SPDX-FileCopyrightText: 2025 Tanishka Suwalka <tanishkas@ruc.dk>
  6. // SPDX-License-Identifier: GPL-3.0-or-later
  7. /// Sensor mussel - an Arduino sketch to emulate a mussel biosensor
  8. ///
  9. /// * v0.0.3
  10. /// * rewrite sensor as sketch,
  11. /// using ESP32 LEDC, Touch sensor and Logging library
  12. ///
  13. /// * v0.0.2
  14. /// * rewrite attitude #2 to also handle button press
  15. /// * add voting functions and example
  16. ///
  17. /// * v0.0.1
  18. /// * initial release to radicle
  19. ///
  20. /// @version 0.0.3
  21. /// @see <https://app.radicle.xyz/nodes/seed.radicle.garden/rad:z2tFBF4gN7ziG9oXtUytVQNYe3VhQ/tree/Mussel/README.md>
  22. /// @see <https://moodle.ruc.dk/course/view.php?id=23504>
  23. #include "mylog.h"
  24. #include "BLEDevice.h"
  25. #include "BLEBeacon.h"
  26. #include "BLEAdvertising.h"
  27. #include "BLEEddystoneTLM.h"
  28. // Adjust these for production use
  29. //
  30. // * BEACON_UUID should be unique for each deployment
  31. // * INSTANCE_ID should be unique for each sensor
  32. //
  33. // @see https://www.uuidgenerator.net/
  34. #define BEACON_NAME "Dummy mussel sensor"
  35. #define BEACON_UUID "00000000-0000-0000-0000-000000000000"
  36. #define INSTANCE_ID "0xbeac0101"
  37. #define STRESS_MAX 50
  38. // touch sensor using ESP32 Touch sensor
  39. // https://docs.espressif.com/projects/arduino-esp32/en/latest/api/touch.html
  40. #define TOUCH_PIN T0 // T0 is GPIO4
  41. #define TOUCH_THRESHOLD 40
  42. // pacemaker using ESP32 LED PWM Controller (LEDC)
  43. // https://docs.espressif.com/projects/arduino-esp32/en/latest/api/ledc.html
  44. #define LED_PIN LED_BUILTIN
  45. #define LEDC_BITS 7
  46. #define LEDC_FREQ 500
  47. #define LEDC_START_DUTY 0
  48. #define LEDC_TARGET_DUTY 90
  49. #define LEDC_CALM_PACE 3000
  50. #define LEDC_STRESSED_PACE 400
  51. // Bluetooth beacon
  52. #define BEACON_POWER ESP_PWR_LVL_N12
  53. int stress = 0;
  54. bool touch_detected = false;
  55. int pace = LEDC_STRESSED_PACE;
  56. bool fade_ended = false;
  57. bool fade_in = true;
  58. BLEAdvertising *pAdvertising;
  59. // Touch sensor callback
  60. void gotTouch() {
  61. // keepPace();
  62. touch_detected = true;
  63. pace = LEDC_STRESSED_PACE;
  64. }
  65. // pacemaker Interrupt Service Routine (ISR)
  66. void ARDUINO_ISR_ATTR LED_FADE_ISR() {
  67. fade_ended = true;
  68. keepPace();
  69. }
  70. void beginTouchDetection() {
  71. touchAttachInterrupt(TOUCH_PIN, gotTouch, TOUCH_THRESHOLD);
  72. log_d("touch detected");
  73. }
  74. // pacemaker initialization
  75. void beginPace() {
  76. // Setup pacemaker timer
  77. ledcAttach(LED_PIN, LEDC_FREQ, LEDC_BITS);
  78. // fade in once supervised and then begin fade out with ISR
  79. ledcFade(LED_PIN, LEDC_START_DUTY, LEDC_TARGET_DUTY, pace);
  80. delay(pace);
  81. ledcFadeWithInterrupt(LED_PIN, LEDC_TARGET_DUTY, LEDC_START_DUTY,
  82. pace, LED_FADE_ISR);
  83. }
  84. // pacemaker maintenance
  85. void keepPace() {
  86. // if (fade_ended || touch_detected) {
  87. if (fade_ended) {
  88. fade_ended = false;
  89. // stress management
  90. if (touch_detected) {
  91. touch_detected = false;
  92. log_i("Stressed by touch!");
  93. if (stress < STRESS_MAX) {
  94. stress = stress + 10;
  95. }
  96. } else if (stress > 0) {
  97. stress--;
  98. if (stress <= 0) {
  99. pace = LEDC_CALM_PACE;
  100. log_i("Calmed down...");
  101. } else {
  102. log_i("Still stressed...");
  103. }
  104. } else {
  105. pace = LEDC_CALM_PACE;
  106. }
  107. // begin fade in opposite direction at decided pace
  108. ledcFadeWithInterrupt(LED_PIN,
  109. fade_in ? LEDC_START_DUTY : LEDC_TARGET_DUTY,
  110. fade_in ? LEDC_TARGET_DUTY : LEDC_START_DUTY,
  111. pace, LED_FADE_ISR);
  112. fade_in = !fade_in;
  113. }
  114. }
  115. // Sensor reading
  116. int getGapeAngle() {
  117. return ledcRead(LED_PIN);
  118. }
  119. // Construct Bluetooth beacon
  120. void setBeacon() {
  121. BLEEddystoneTLM EddystoneTLM;
  122. EddystoneTLM.setTemp(getGapeAngle());
  123. log_i("Gape angle: %.2f°", EddystoneTLM.getTemp());
  124. BLEAdvertisementData oAdvertisementData = BLEAdvertisementData();
  125. BLEAdvertisementData oScanResponseData = BLEAdvertisementData();
  126. oScanResponseData.setServiceData(BLEUUID(
  127. (uint16_t)0xFEAA),
  128. String(EddystoneTLM.getData().c_str(),
  129. EddystoneTLM.getData().length()));
  130. oAdvertisementData.setName(BEACON_NAME);
  131. pAdvertising->setAdvertisementData(oAdvertisementData);
  132. pAdvertising->setScanResponseData(oScanResponseData);
  133. }
  134. void setup() {
  135. // enable logging (when also raised in IDE: Tools -> Core Debug Level)
  136. Serial.begin(115200);
  137. esp_log_level_set("*", ESP_LOG_DEBUG);
  138. Serial.begin(115200);
  139. beginPace();
  140. beginTouchDetection();
  141. // setup Bluetooth
  142. if (BEACON_UUID == "00000000-0000-0000-0000-000000000000")
  143. log_w("Please set a unique BEACON_UUID");
  144. BLEDevice::init("TLMBeacon");
  145. BLEDevice::setPower(BEACON_POWER);
  146. pAdvertising = BLEDevice::getAdvertising();
  147. setBeacon();
  148. pAdvertising->start();
  149. }
  150. void loop() {
  151. // keepPace();
  152. // Serial.println(getGapeAngle());
  153. setBeacon();
  154. delay(500);
  155. }