aboutsummaryrefslogtreecommitdiff
path: root/Mussel
diff options
context:
space:
mode:
authorJonas Smedegaard <dr@jones.dk>2025-03-11 12:02:07 +0100
committerJonas Smedegaard <dr@jones.dk>2025-03-11 16:48:06 +0100
commit02876f961fc8b68f2cb43a23a1d98d89fce11858 (patch)
treed12658d92f62c4fd957fb68e683d75b8f378428f /Mussel
parent8d0212da635222b404113ad0ff5d469adf00ab6f (diff)
add library Mussel
Diffstat (limited to 'Mussel')
-rw-r--r--Mussel/Mussel.cpp205
-rw-r--r--Mussel/Mussel.h42
-rw-r--r--Mussel/README.md36
-rw-r--r--Mussel/examples/button/button.ino20
-rw-r--r--Mussel/examples/button_states/button_states.ino20
-rw-r--r--Mussel/examples/command/command.ino19
-rw-r--r--Mussel/examples/minute/minute.ino19
-rw-r--r--Mussel/examples/seconds/seconds.ino19
-rw-r--r--Mussel/examples/temperature/temperature.ino21
-rw-r--r--Mussel/keywords.txt17
10 files changed, 418 insertions, 0 deletions
diff --git a/Mussel/Mussel.cpp b/Mussel/Mussel.cpp
new file mode 100644
index 0000000..3e13316
--- /dev/null
+++ b/Mussel/Mussel.cpp
@@ -0,0 +1,205 @@
+/// Mussel - a small library for Arduino to emulate a mussel biosensor
+///
+/// SPDX-FileCopyrightText: 2025 Amal Mazrah <mazrah@ruc.dk>
+/// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk>
+/// SPDX-FileCopyrightText: 2025 Mennatullah Hatim Kassim <stud-mennatulla@ruc.dk>
+/// SPDX-FileCopyrightText: 2025 Noor Ahmad <noora@ruc.dk>
+/// SPDX-FileCopyrightText: 2025 Tanishka Suwalka <tanishkas@ruc.dk>
+/// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "Mussel.h"
+#include "Arduino.h"
+
+/// Main constructor
+///
+/// @param attitude behavioral profile as integer
+Mussel::Mussel(int attitude) {
+ _attitude = attitude;
+}
+
+/// Constructor for attitudes using a pin
+///
+/// @param attitude behavioral profile as integer
+/// @param pin Used pin as uint8_t
+Mussel::Mussel(int attitude, uint8_t pin) {
+ _attitude = attitude;
+ _pin = pin;
+}
+
+/// Constructor for attitudes using a pin and certain type of sensor
+///
+/// @param attitude behavioral profile as integer
+/// @param pin Used pin as uint8_t
+/// @param type type of sensor as uint8_t
+Mussel::Mussel(int attitude, uint8_t pin, uint8_t type)
+#ifdef DHT_H
+ : mussel_dht(pin, type)
+#endif
+{
+ _attitude = attitude;
+ _pin = pin;
+}
+
+/// Setup function
+void Mussel::begin() {
+ switch(_attitude) {
+#ifdef DHT_H
+ case 3:
+ mussel_dht.begin();
+ break;
+#endif
+ case 4:
+ // use INPUT_PULLDOWN to signal when the button is held down
+ // (not PULLUP which signals when it is released)
+ pinMode(_pin, INPUT_PULLDOWN);
+ break;
+ case 5:
+ _boolState = HIGH;
+ _count = 0;
+ _time = 0;
+
+ // Enable internal pull-up resistor for button
+ pinMode(_pin, INPUT_PULLUP);
+ break;
+ case 6:
+ _boolState = HIGH;
+ break;
+ }
+}
+
+/// Description of mussel
+///
+/// @return name and attitude of mussel as String
+String Mussel::desc() {
+ String _str;
+
+ switch(_attitude) {
+ case 1:
+ _str = "closed 10 seconds every 50 seconds";
+ break;
+ case 2:
+ _str = "closed 4 seconds every 8 seconds";
+ break;
+ case 3:
+ _str = "closed when cold";
+ break;
+ case 4:
+ _str = "closed when button is pushed";
+ break;
+ case 5:
+ _str = "changes state when button is pushed";
+ break;
+ case 6:
+ _str = "changes state on ON/OFF command";
+ break;
+ default:
+ _str = "undefined [" + static_cast<String>(_attitude) + "]";
+ break;
+ }
+
+ return _str;
+}
+
+/// Sensor reading
+///
+/// * Values 0-99 is a measured relative mussel gape size
+/// * Values 100-254 are reserved for future use
+/// * Value 255 is an internal error
+///
+/// @return relative gape size as value 0-255 encoded as byte
+byte Mussel::read() {
+ byte _byte;
+
+ switch(_attitude) {
+ case 1:
+ // 42 if current second modulo 60 is below 50, else 2
+ _byte = static_cast<byte>(
+ (static_cast<unsigned long>(millis() / 1000) % 60) < 50
+ ? 42
+ : 2);
+ break;
+ case 2:
+ // 42 if current second modulo 12 is below 9, else 2
+ _byte = static_cast<byte>(
+ (static_cast<unsigned long>(millis() / 1000) % 12) < 9
+ ? 42
+ : 2);
+ break;
+ case 3:
+#ifdef DHT_H
+ // temperature in Celsius
+ _byte = static_cast<byte>(
+ mussel_dht.readTemperature());
+#else
+ _byte = 255;
+#endif
+ break;
+ case 4:
+ // 2 if button is pressed, else 42
+ _byte = static_cast<byte>(
+ digitalRead(_pin) == HIGH
+ ? 2
+ : 42);
+ break;
+ case 5: {
+ bool _reading = digitalRead(_pin); // Read button state
+
+ // Debounce logic:
+ // Ensures a single press isn't detected multiple times
+ if (_reading != _boolState) {
+ _time = millis(); // Reset debounce timer
+ }
+
+ if ((millis() - _time) > MUSSEL_DEBOUNCE_DELAY) {
+ // Check for button press (transition from HIGH to LOW)
+ if (_reading == LOW && _boolState == HIGH) {
+ _count++; // Increment click count
+ if (_count > 3) {
+ _count = 0; // Reset cycle after 3 clicks
+ }
+ switch (_count) {
+ case 1: _byte = 2; break; // State: Angry
+ case 2: _byte = 42; break; // State: Happy
+ case 3: _byte = 15; break; // State: Unsure
+ case 0: _byte = 99; break; // State: Off
+ }
+ }
+ }
+
+ _boolState = _reading; // Update button state
+ break;
+ }
+ case 6:
+ if (Serial.available() > 0) {
+ String command = Serial.readStringUntil('\n');
+ command.trim();
+
+ if (command.equalsIgnoreCase("ON")) {
+ _boolState = HIGH;
+ }
+ else if (command.equalsIgnoreCase("OFF")) {
+ _boolState = LOW;
+ }
+ }
+ _byte = _boolState == HIGH
+ ? 42
+ : 2;
+ break;
+ default:
+ _byte = 255;
+ break;
+ }
+
+ return _byte;
+}
+
+/// Dump internal variables, formatted for use with Serial Plotter
+///
+/// @return internal variables as String
+String Mussel::debug() {
+ return static_cast<String>(
+ "pin:") + _pin
+ + "\tboolState:" + _boolState
+ + "\ttime:" + _time
+ + "\tcount:" + _count;
+}
diff --git a/Mussel/Mussel.h b/Mussel/Mussel.h
new file mode 100644
index 0000000..5d85068
--- /dev/null
+++ b/Mussel/Mussel.h
@@ -0,0 +1,42 @@
+/// Mussel - a small library for Arduino to emulate a mussel biosensor
+///
+/// SPDX-License-Identifier: GPL-3.0-or-later
+/// SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk>
+
+#ifndef Mussel_h
+#define Mussel_h
+#include "Arduino.h"
+
+#define MUSSEL_DEBOUNCE_DELAY 50U
+
+class Mussel {
+ public:
+
+ // Default constructor
+ Mussel(const int attitude);
+
+ // Constructor for attitudes using a pin
+ Mussel(const int attitude, const uint8_t pin);
+
+ // Constructor for attitudes using a pin and certain type of sensor
+ Mussel(
+ const int attitude,
+ const uint8_t pin,
+ const uint8_t type);
+
+ void begin();
+ String desc();
+ byte read();
+ String debug();
+ private:
+ int _attitude;
+ int _pin;
+ bool _boolState;
+ byte _count;
+ unsigned long _time;
+#ifdef DHT_H
+ DHT mussel_dht;
+#endif
+};
+
+#endif
diff --git a/Mussel/README.md b/Mussel/README.md
new file mode 100644
index 0000000..4420e2a
--- /dev/null
+++ b/Mussel/README.md
@@ -0,0 +1,36 @@
+# Mussel
+
+SPDX-FileCopyrightText: 2025 Amal Mazrah <mazrah@ruc.dk>
+SPDX-FileCopyrightText: 2025 Jonas Smedegaard <dr@jones.dk>
+SPDX-FileCopyrightText: 2025 Mennatullah Hatim Kassim <stud-mennatulla@ruc.dk>
+SPDX-FileCopyrightText: 2025 Noor Ahmad <noora@ruc.dk>
+SPDX-FileCopyrightText: 2025 Tanishka Suwalka <tanishkas@ruc.dk>
+SPDX-License-Identifier: GPL-3.0-or-later
+
+Mussel is a tiny library to emulate a mussel biosensor.
+
+## Motivation
+
+For exploration of various biosensor behaviours,
+hooking into various networking setups with various looping constructs,
+maintaining the behaviours as a library seemed convenient.
+
+## Features
+
+* Super simple API
+* Offers multiple behaviours.
+
+## Requirements
+
+* An Arduino — http://arduino.cc/
+
+## Installation
+
+Download the ZIP archive from
+<https://app.radicle.xyz/nodes/seed.radicle.garden/rad:z2tFBF4gN7ziG9oXtUytVQNYe3VhQ>,
+then open the Arduino IDE
+and choose Sketch > Include Library > Add .ZIP Library...
+and select your downloaded file.
+
+You should now see in File > Examples > Mussel
+an entry for the `basic_usage` example.
diff --git a/Mussel/examples/button/button.ino b/Mussel/examples/button/button.ino
new file mode 100644
index 0000000..5efae46
--- /dev/null
+++ b/Mussel/examples/button/button.ino
@@ -0,0 +1,20 @@
+#include <Mussel.h>
+
+// instantiate with attitude #4,
+// and pin 4 connected to a button
+Mussel mussel(4, 4);
+
+void setup() {
+ Serial.begin(115200);
+ mussel.begin();
+
+ Serial.printf("\n\nDevice ready: %s\n",
+ mussel.desc().c_str());
+}
+
+void loop() {
+ Serial.printf("gap:%d\n",
+ mussel.read());
+
+ delay(1000);
+}
diff --git a/Mussel/examples/button_states/button_states.ino b/Mussel/examples/button_states/button_states.ino
new file mode 100644
index 0000000..1d91b41
--- /dev/null
+++ b/Mussel/examples/button_states/button_states.ino
@@ -0,0 +1,20 @@
+#include <Mussel.h>
+
+// instantiate with attitude #5,
+// and pin 9 connected to a button
+Mussel mussel(5, 9);
+
+void setup() {
+ Serial.begin(115200);
+ mussel.begin();
+
+ Serial.printf("\n\nDevice ready: %s\n",
+ mussel.desc().c_str());
+}
+
+void loop() {
+ Serial.printf("gap:%d\n",
+ mussel.read());
+
+ delay(1000);
+}
diff --git a/Mussel/examples/command/command.ino b/Mussel/examples/command/command.ino
new file mode 100644
index 0000000..f359e00
--- /dev/null
+++ b/Mussel/examples/command/command.ino
@@ -0,0 +1,19 @@
+#include <Mussel.h>
+
+// instantiate with attitude #6
+Mussel mussel(6);
+
+void setup() {
+ Serial.begin(115200);
+ mussel.begin();
+
+ Serial.printf("\n\nDevice ready: %s\n",
+ mussel.desc().c_str());
+}
+
+void loop() {
+ Serial.printf("gap:%d\n",
+ mussel.read());
+
+ delay(1000);
+}
diff --git a/Mussel/examples/minute/minute.ino b/Mussel/examples/minute/minute.ino
new file mode 100644
index 0000000..928537c
--- /dev/null
+++ b/Mussel/examples/minute/minute.ino
@@ -0,0 +1,19 @@
+#include <Mussel.h>
+
+// instantiate with attitude #2
+Mussel mussel(2);
+
+void setup() {
+ Serial.begin(115200);
+ mussel.begin();
+
+ Serial.printf("\n\nDevice ready: %s\n",
+ mussel.desc().c_str());
+}
+
+void loop() {
+ Serial.printf("gap:%d\n",
+ mussel.read());
+
+ delay(1000);
+}
diff --git a/Mussel/examples/seconds/seconds.ino b/Mussel/examples/seconds/seconds.ino
new file mode 100644
index 0000000..928537c
--- /dev/null
+++ b/Mussel/examples/seconds/seconds.ino
@@ -0,0 +1,19 @@
+#include <Mussel.h>
+
+// instantiate with attitude #2
+Mussel mussel(2);
+
+void setup() {
+ Serial.begin(115200);
+ mussel.begin();
+
+ Serial.printf("\n\nDevice ready: %s\n",
+ mussel.desc().c_str());
+}
+
+void loop() {
+ Serial.printf("gap:%d\n",
+ mussel.read());
+
+ delay(1000);
+}
diff --git a/Mussel/examples/temperature/temperature.ino b/Mussel/examples/temperature/temperature.ino
new file mode 100644
index 0000000..6b4ca08
--- /dev/null
+++ b/Mussel/examples/temperature/temperature.ino
@@ -0,0 +1,21 @@
+#include <DHT.h>
+#include <Mussel.h>
+
+// instantiate with attitude #3,
+// and PIN 15 connected to an external sensor of type DHT11
+Mussel mussel(3, 15, DHT11);
+
+void setup() {
+ Serial.begin(115200);
+ mussel.begin();
+
+ Serial.printf("\n\nDevice ready: %s\n",
+ mussel.desc().c_str());
+}
+
+void loop() {
+ Serial.printf("gap:%d\n",
+ mussel.read());
+
+ delay(1000);
+}
diff --git a/Mussel/keywords.txt b/Mussel/keywords.txt
new file mode 100644
index 0000000..4f3eaf1
--- /dev/null
+++ b/Mussel/keywords.txt
@@ -0,0 +1,17 @@
+#######################################
+# Syntax Coloring Map for Mussel library
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+Mussel KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+read KEYWORD2
+begin KEYWORD2
+desc KEYWORD2