summaryrefslogtreecommitdiff
path: root/minion/src
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2022-05-16 12:44:58 +0200
committerHampusM <hampus@hampusmat.com>2022-05-16 13:50:22 +0200
commit3ede86caf948d6e989fd056ea4f8d8c588939971 (patch)
treea3226c6b9005ddc24a4af7a3c38722eb113963d4 /minion/src
parent6aa69cdcd8720d835e922323cdcf79147c9b3154 (diff)
feat(minion): add reading temperature sensor
Diffstat (limited to 'minion/src')
-rw-r--r--minion/src/gymnasiearbete.cpp47
-rw-r--r--minion/src/http/response_status.hpp1
-rw-r--r--minion/src/temperature.cpp117
-rw-r--r--minion/src/temperature.hpp42
4 files changed, 203 insertions, 4 deletions
diff --git a/minion/src/gymnasiearbete.cpp b/minion/src/gymnasiearbete.cpp
index a1f6d51..fada1e2 100644
--- a/minion/src/gymnasiearbete.cpp
+++ b/minion/src/gymnasiearbete.cpp
@@ -1,6 +1,7 @@
#include "http/request.hpp"
#include "http/response_status.hpp"
#include "secrets.hpp"
+#include "temperature.hpp"
#include "wifi_module.hpp"
#include <Arduino.h>
@@ -14,10 +15,16 @@ constexpr auto BAUDRATE = 9600U;
constexpr auto NETWORK_MODULE_RX_PIN = 13U;
constexpr auto NETWORK_MODULE_TX_PIN = 11U;
+constexpr auto TEMPERATURE_SENSOR_PIN = 9U;
+
constexpr auto SECOND_IN_MILLIS = 1000U;
+constexpr auto RESPONSE_DATA_MAX_LENGTH = 64U;
+
auto wifi_module = WiFiModule({ NETWORK_MODULE_RX_PIN, NETWORK_MODULE_TX_PIN });
+auto temperature_sensor = TemperatureSensor(TEMPERATURE_SENSOR_PIN);
+
void setup()
{
Serial.begin(BAUDRATE);
@@ -102,12 +109,44 @@ void loop()
Serial.print("\nData: ");
Serial.println(request.data());
- wifi_module.send_response(connection, HTTP_RESPONSE_STATUS_OK, "hello there!");
+ const auto temperature_sensor_status = temperature_sensor.read_temperature();
- wifi_module.close_connection(connection);
+ if (temperature_sensor_status != TemperatureSensorStatus::OK)
+ {
+ Serial.print("Error: ");
+ Serial.println(static_cast<int>(temperature_sensor_status));
- Serial.print("Connection closed: ");
- Serial.println(connection.is_closed() ? "true" : "false");
+ wifi_module.send_response(
+ connection,
+ HTTP_RESPONSE_STATUS_INTERNAL_SERVER_ERROR,
+ R"({"error": "Internal server error"})"
+ );
+
+ wifi_module.close_connection(connection);
+
+ delay(SECOND_IN_MILLIS);
+
+ return;
+ }
+
+ char response_data[RESPONSE_DATA_MAX_LENGTH] = "";
+
+ snprintf(
+ response_data,
+ RESPONSE_DATA_MAX_LENGTH,
+ "%u",
+ temperature_sensor.temperature()
+ );
+
+ const auto send_response_ok =
+ wifi_module.send_response(connection, HTTP_RESPONSE_STATUS_OK, response_data);
+
+ if (!send_response_ok)
+ {
+ Serial.println("Failed to send response");
+ }
+
+ wifi_module.close_connection(connection);
delay(SECOND_IN_MILLIS);
}
diff --git a/minion/src/http/response_status.hpp b/minion/src/http/response_status.hpp
index 577eedd..4db7546 100644
--- a/minion/src/http/response_status.hpp
+++ b/minion/src/http/response_status.hpp
@@ -1,3 +1,4 @@
#pragma once
constexpr auto HTTP_RESPONSE_STATUS_OK = 200U;
+constexpr auto HTTP_RESPONSE_STATUS_INTERNAL_SERVER_ERROR = 500U;
diff --git a/minion/src/temperature.cpp b/minion/src/temperature.cpp
new file mode 100644
index 0000000..1231e24
--- /dev/null
+++ b/minion/src/temperature.cpp
@@ -0,0 +1,117 @@
+#include "temperature.hpp"
+
+#include <Arduino.h>
+
+TemperatureSensor::TemperatureSensor(uint8_t pin) noexcept : _pin(pin)
+{
+ pinMode(_pin, OUTPUT);
+}
+
+auto TemperatureSensor::read_temperature() noexcept -> TemperatureSensorStatus
+{
+ // Send start signal and wait
+ digitalWrite(_pin, LOW);
+ delay(TemperatureSensorTiming::START_SIGNAL_TIME_MILLIS);
+
+ // Pull up and wait for response
+ digitalWrite(_pin, HIGH);
+ delayMicroseconds(TemperatureSensorTiming::RESPONSE_SIGNAL_WAIT_TIME_MICROS);
+
+ pinMode(_pin, INPUT);
+
+ // The sensor sends a LOW signal and keeps it for 80us
+ if (!_wait_read(LOW, TemperatureSensorTiming::RESPONSE_SIGNAL_TIME_MICROS))
+ {
+ return TemperatureSensorStatus::TIMEOUT;
+ }
+
+ // The sensor sends a HIGH signal and keeps it for 80us
+ if (!_wait_read(HIGH, TemperatureSensorTiming::RESPONSE_SIGNAL_TIME_MICROS))
+ {
+ return TemperatureSensorStatus::TIMEOUT;
+ }
+
+ uint8_t data_bytes[TEMPERATURE_SENSOR_RESPONSE_DATA_BYTE_CNT] = { 0U,
+ 0U,
+ 0U,
+ 0U,
+ 0U };
+
+ uint8_t bit_index = BITS_IN_BYTE - 1U;
+ uint8_t byte_index = 0U;
+
+ for (uint16_t index = 0U;
+ index < (BITS_IN_BYTE * TEMPERATURE_SENSOR_RESPONSE_DATA_BYTE_CNT);
+ index++)
+ {
+ // Wait for the start to transmit signal
+ if (!_wait_read(
+ LOW,
+ TemperatureSensorTiming::START_TO_TRANSMIT_SIGNAL_TIME_MICROS + 5U
+ ))
+ {
+ return TemperatureSensorStatus::TIMEOUT;
+ }
+
+ const auto start_time = micros();
+
+ if (!_wait_read(HIGH, TemperatureSensorTiming::DATA_TRANSMIT_TIMEOUT_MICROS))
+ {
+ return TemperatureSensorStatus::TIMEOUT;
+ }
+
+ // A voltage length greater than 40 means the bit is a 1
+ if ((micros() - start_time) > 40U)
+ {
+ data_bytes[byte_index] |= static_cast<uint8_t>(1U << bit_index);
+ }
+
+ // Continue to the next byte if it's the last bit
+ if (bit_index == 0U)
+ {
+ // Restart at the MSB
+ bit_index = BITS_IN_BYTE - 1U;
+
+ byte_index++;
+ continue;
+ }
+
+ bit_index--;
+ }
+
+ // Restore pin to initial state
+ pinMode(_pin, OUTPUT);
+ digitalWrite(_pin, HIGH);
+
+ _temperature = data_bytes[2];
+
+ auto sum = data_bytes[0] + data_bytes[2];
+
+ if (data_bytes[4] != sum)
+ {
+ return TemperatureSensorStatus::CHECKSUM_ERROR;
+ }
+
+ return TemperatureSensorStatus::OK;
+}
+
+auto TemperatureSensor::temperature() const noexcept -> uint8_t
+{
+ return _temperature;
+}
+
+// NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
+auto TemperatureSensor::_wait_read(uint8_t level, size_t timeout_micros) noexcept -> bool
+{
+ const auto start_time = micros();
+
+ while (digitalRead(_pin) == level)
+ {
+ if ((start_time + timeout_micros) < micros())
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/minion/src/temperature.hpp b/minion/src/temperature.hpp
new file mode 100644
index 0000000..dcc213c
--- /dev/null
+++ b/minion/src/temperature.hpp
@@ -0,0 +1,42 @@
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+
+namespace TemperatureSensorTiming
+{
+
+constexpr auto START_SIGNAL_TIME_MILLIS = 18U;
+constexpr auto RESPONSE_SIGNAL_WAIT_TIME_MICROS = 40U;
+constexpr auto RESPONSE_SIGNAL_TIME_MICROS = 80U;
+constexpr auto START_TO_TRANSMIT_SIGNAL_TIME_MICROS = 50U;
+constexpr auto DATA_TRANSMIT_TIMEOUT_MICROS = 80U;
+
+} // namespace TemperatureSensorTiming
+
+constexpr auto TEMPERATURE_SENSOR_RESPONSE_DATA_BYTE_CNT = 5U;
+constexpr auto BITS_IN_BYTE = 8U;
+
+enum class TemperatureSensorStatus
+{
+ OK,
+ TIMEOUT,
+ CHECKSUM_ERROR
+};
+
+class TemperatureSensor
+{
+public:
+ explicit TemperatureSensor(uint8_t pin) noexcept;
+
+ auto read_temperature() noexcept -> TemperatureSensorStatus;
+
+ auto temperature() const noexcept -> uint8_t;
+
+private:
+ const uint8_t _pin;
+
+ uint8_t _temperature{};
+
+ auto _wait_read(uint8_t level, size_t timeout_micros) noexcept -> bool;
+};