A low cost DIY sound pressure level sensor for enabling environmental noise awareness. https://lukasschwarz.org/noise-sensor
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. // vim: noai:sw=2:tw=88
  2. #include <TimeLib.h>
  3. #include "NoiseSensor.h"
  4. //#include "NoiseSensorNode.h"
  5. bool NoiseSensorClass::begin() {
  6. _PACKET_SIZE = ( _tick_count + LORA_HEADER_LENGTH + BATTERY_FIELD_SIZE );
  7. _REQUEST_SIZE = ( PACKET_COUNT * _PACKET_SIZE * 2 ); // * 2, it's 16 bit.
  8. for (int i = 0; i < PACKET_COUNT; i++) {
  9. _nodes[i] = new NoiseSensorNode(i, _PACKET_SIZE * 2);
  10. }
  11. if (this->_tick_duration < 2) {
  12. Serial.println("--> Using a tick duration of less than two seconds. This "
  13. "will fail unless you've increased the MCUs SYSCLK!");
  14. }
  15. if (this->_tick_count >= 100) {
  16. Serial.println(
  17. "--> Using a tick count of more than 100 gets dangerously close to the "
  18. "LoRa transmission limitations and is not supported as of now.");
  19. } else if (this->_tick_count < 10) {
  20. Serial.println(
  21. "--> Using a tick count smaller than 10 might screw things up in a "
  22. "unpredictable manner and is not recommended.");
  23. }
  24. if (this->_tick_count >= 120) {
  25. Serial.println(
  26. "--> Increased the tick count over 120. This results in I²C packages of "
  27. "(tick_count + 3 ) * 2. "
  28. "Note that I²C packets longer than 256 bytes will need to be split into "
  29. "smaller chunks to allow them to transfer."
  30. }
  31. if (!setupNTPClient()) {
  32. Serial.println("!!!-------------------------!!!");
  33. Serial.println("NTPClient couldn't be started.");
  34. Serial.println("!!!-------------------------!!!");
  35. return false;
  36. }
  37. I2C.begin(400000);
  38. this->sendSyncBeacon();
  39. while (I2C.writeBusy) {
  40. delay(250);
  41. Serial.println("Writing!");
  42. }
  43. this->_first_sync = 1;
  44. }
  45. bool NoiseSensorClass::begin(uint8_t tick_count) {
  46. this->_tick_count = tick_count;
  47. this->begin();
  48. }
  49. bool NoiseSensorClass::begin(uint8_t tick_count, uint8_t tick_duration) {
  50. this->_tick_count = tick_count;
  51. this->_tick_duration = tick_duration;
  52. this->begin();
  53. }
  54. bool NoiseSensorClass::begin(uint8_t tick_count, uint8_t tick_duration,
  55. uint8_t tx_offset) {
  56. this->_tick_count = tick_count;
  57. this->_tick_duration = tick_duration;
  58. this->_tx_offset = tx_offset;
  59. this->begin();
  60. }
  61. void NoiseSensorClass::setIds(const char* sensebox_ids[], const char* sensor_ids[]) {
  62. for (int i = 0; i < PACKET_COUNT; i++) {
  63. char tmp[24] = {0};
  64. _nodes[i]->sensebox_id = sensebox_ids[i];
  65. _nodes[i]->sensor_id = sensor_ids[i];
  66. }
  67. }
  68. bool NoiseSensorClass::beaconReady() {
  69. // if (this->_time_client->getEpochTime() - this->_last_sync_time ==
  70. if (now() - _last_sync_time ==
  71. (this->_tick_count * this->_tick_duration)) {
  72. Serial.println("---->Beacon ready");
  73. return true;
  74. }
  75. return false;
  76. }
  77. bool NoiseSensorClass::requestReady() {
  78. // 1 second as tolerance
  79. if (!this->_first_sync &&
  80. //this->_time_client->getEpochTime() - this->_last_sync_time ==
  81. now() - _last_sync_time ==
  82. (5 * this->_tx_offset * this->_tick_duration + 1)) {
  83. Serial.println("---->Request ready");
  84. return true;
  85. }
  86. return false;
  87. }
  88. bool NoiseSensorClass::read() {
  89. Serial.println("Starting read");
  90. for (int pkt = 0; pkt < PACKET_COUNT; pkt++) {
  91. // Calculate the time of the sync message that triggered this packet.
  92. uint32_t time_offset = (_tick_count * _tick_duration) + 1; // TODO Move
  93. this->_nodes[pkt]->_sync_message_ts = this->_last_sync_time - time_offset;
  94. Serial.print("Last sync time: ");
  95. Serial.println(_last_sync_time);
  96. Serial.print("Offset: ");
  97. Serial.println(time_offset);
  98. Serial.print("TS: ");
  99. Serial.println(_nodes[pkt]->_sync_message_ts);
  100. Serial.print(minute(_nodes[pkt]->_sync_message_ts));
  101. Serial.print(":");
  102. Serial.println(second(_nodes[pkt]->_sync_message_ts));
  103. /*
  104. if (_nodes[pkt]->missing_answers > 0) {
  105. _nodes[pkt]->_sync_message_ts -= time_offset * _nodes[pkt]->missing_answers;
  106. }
  107. */
  108. I2C.readBytes(this->_i2c_address, (uint8_t *) this->_nodes[pkt]->_measurements, this->_PACKET_SIZE * 2);
  109. }
  110. uint32_t read_start_time = millis();
  111. while (I2C.readBusy) {
  112. Serial.println("Reading!");
  113. delay(1);
  114. // Restart I²C if no response for more than a second.
  115. if (millis() - read_start_time >= 1000) {
  116. Serial.println("Restarting I²C");
  117. I2C.end();
  118. I2C.begin(400000);
  119. return false;
  120. }
  121. }
  122. // Skip 0, it has no battery.
  123. for (int pkt = 1; pkt < PACKET_COUNT; pkt++) {
  124. // TODO Move this to a sane place (own function).
  125. if (_nodes[pkt]->_measurements[_PACKET_SIZE - 1]) {
  126. Serial.print("Battery low on device");
  127. Serial.println(pkt);
  128. }
  129. }
  130. Serial.println("Reading done.");
  131. return true;
  132. }
  133. void NoiseSensorClass::printMeasurements(uint8_t node_id) {
  134. uint32_t ts = this->_nodes[node_id]->_sync_message_ts;
  135. char printbuf[32];
  136. sprintf(printbuf, "- ID %u - ", node_id);
  137. Serial.println(printbuf);
  138. for (int i = 2; i < (this->_PACKET_SIZE - BATTERY_FIELD_SIZE); i++) {
  139. sprintf(printbuf, "%02i:%02i:%02i -> ", hour(ts), minute(ts), second(ts));
  140. Serial.print(printbuf);
  141. Serial.println(this->_nodes[node_id]->_measurements[i]);
  142. ts += this->_tick_duration;
  143. }
  144. }
  145. bool NoiseSensorClass::sendSyncBeacon() {
  146. //_last_sync_time = _time_client->getEpochTime();
  147. uint8_t setup_values[3];
  148. setup_values[0] = this->_tick_count;
  149. setup_values[1] = this->_tick_duration;
  150. setup_values[2] = this->_tx_offset;
  151. Serial.println("Sent beacon");
  152. I2C.writeBytes(this->_i2c_address, 0x01, (uint8_t *)setup_values,
  153. sizeof(setup_values));
  154. this->_first_sync = 0;
  155. _last_sync_time = now();
  156. Serial.println(_last_sync_time);
  157. Serial.print(minute(_last_sync_time));
  158. Serial.print(":");
  159. Serial.println(second(_last_sync_time));
  160. while (I2C.writeBusy) {
  161. delay(250);
  162. Serial.println("Writing!");
  163. }
  164. }
  165. String NoiseSensorClass::buildSenseBoxJSON(uint8_t device_id) {
  166. // _time_client->update();
  167. NoiseSensorNode* node = _nodes[device_id];
  168. uint32_t ts = node->_sync_message_ts;
  169. // Each measurement line is max. 94 chars long + 2 curly brackets.
  170. uint16_t bufsize = _tick_count * 94 + 2;
  171. char json_buf[bufsize] = {0};
  172. char sensor_id[25] = {0};
  173. node->sensor_id.toCharArray(sensor_id, 25);
  174. // Build a json string in a very comprehensible way...
  175. strcat(json_buf, "[\n");
  176. for (int i = 2; i < (_PACKET_SIZE - BATTERY_FIELD_SIZE); i++) {
  177. char tmpbuf[1024] = {0};
  178. char timestamp[24] = {0};
  179. float m = node->_measurements[i] / 10.0; // From fixed point to float.
  180. if (m >= 29 && m <= 120) {
  181. sprintf(timestamp, "%i-%02i-%02iT%02i:%02i:%02iZ", year(ts), month(ts),
  182. day(ts), hour(ts), minute(ts), second(ts));
  183. sprintf(tmpbuf, "{\"sensor\":\"%s\", \"value\":\"%.1f\", \"createdAt\":\"%s\"}", sensor_id, m, timestamp);
  184. // No trailing comma on the last entry.
  185. if (i != _PACKET_SIZE - BATTERY_FIELD_SIZE - 1) {
  186. strcat(tmpbuf, ",");
  187. }
  188. strcat(json_buf, tmpbuf);
  189. strcat(json_buf, "\n");
  190. }
  191. ts += this->_tick_duration;
  192. }
  193. /*
  194. if (strlen(json_buf) > 2) {
  195. node->missing_answers = 0;
  196. Serial.println("Missing answers reset.");
  197. } else {
  198. node->missing_answers++;
  199. Serial.print("Missing answers: ");
  200. Serial.println(node->missing_answers);
  201. }
  202. */
  203. strcat(json_buf, "]");
  204. return json_buf;
  205. }
  206. String NoiseSensorClass::buildHTTPHeader(uint8_t device_id, const char* server, uint16_t content_length) {
  207. char sb_id[25] = {0};
  208. _nodes[device_id]->sensebox_id.toCharArray(sb_id, 25);
  209. char uploadbuf[2048] = {0};
  210. sprintf(uploadbuf, "POST /boxes/%s/data HTTP/1.1\n"
  211. "Host: %s\n"
  212. "content-type: application/json\n"
  213. "Connection: close\n"
  214. "Content-Length: %u", sb_id, server, content_length);
  215. return String(uploadbuf);
  216. }
  217. // Private functions
  218. bool NoiseSensorClass::setupNTPClient() {
  219. uint32_t start_time = millis();
  220. while (timeStatus() != timeSet) {
  221. if (millis() - start_time >= 200) {
  222. return false;
  223. }
  224. }
  225. return true;
  226. //setSyncProvider(
  227. //WiFiUDP ntpUDP;
  228. //this->_time_client = new NTPClient(ntpUDP);
  229. //this->_time_client->begin();
  230. //if (this->_time_client->update()) { return true; }
  231. }
  232. NoiseSensorClass NoiseSensor;