summaryrefslogtreecommitdiff
path: root/api_layers
diff options
context:
space:
mode:
authorChristian Kolset <christian.kolset@gmail.com>2026-04-27 16:53:14 -0600
committerChristian Kolset <christian.kolset@gmail.com>2026-04-27 16:53:14 -0600
commit2b9943ba0d28449a590acfa8a41555b174b6ba84 (patch)
treee8bef8c9bc61dd7e2f9c8a9b177058a4b09546db /api_layers
parent67cfa0a514c7de4605ed7360e15a81aa781e510e (diff)
Improved arduino interface. Now allowing the user to configure pins on the fly.
Diffstat (limited to 'api_layers')
-rw-r--r--api_layers/__pycache__/__init__.cpython-312.pycbin320 -> 311 bytes
-rw-r--r--api_layers/__pycache__/__init__.cpython-314.pycbin322 -> 313 bytes
-rw-r--r--api_layers/__pycache__/arduino_layer.cpython-312.pycbin31077 -> 36567 bytes
-rw-r--r--api_layers/__pycache__/arduino_layer.cpython-314.pycbin35752 -> 41780 bytes
-rw-r--r--api_layers/__pycache__/nidaqmx_layer.cpython-312.pycbin8503 -> 8501 bytes
-rw-r--r--api_layers/__pycache__/nidaqmx_layer.cpython-314.pycbin10249 -> 10240 bytes
-rw-r--r--api_layers/__pycache__/port_registry.cpython-312.pycbin5983 -> 5907 bytes
-rw-r--r--api_layers/__pycache__/port_registry.cpython-314.pycbin0 -> 6791 bytes
-rw-r--r--api_layers/arduino_layer.py121
9 files changed, 114 insertions, 7 deletions
diff --git a/api_layers/__pycache__/__init__.cpython-312.pyc b/api_layers/__pycache__/__init__.cpython-312.pyc
index 689f52e..a9a035b 100644
--- a/api_layers/__pycache__/__init__.cpython-312.pyc
+++ b/api_layers/__pycache__/__init__.cpython-312.pyc
Binary files differ
diff --git a/api_layers/__pycache__/__init__.cpython-314.pyc b/api_layers/__pycache__/__init__.cpython-314.pyc
index d30ccf5..01ab34b 100644
--- a/api_layers/__pycache__/__init__.cpython-314.pyc
+++ b/api_layers/__pycache__/__init__.cpython-314.pyc
Binary files differ
diff --git a/api_layers/__pycache__/arduino_layer.cpython-312.pyc b/api_layers/__pycache__/arduino_layer.cpython-312.pyc
index a0191ad..cb2dd3b 100644
--- a/api_layers/__pycache__/arduino_layer.cpython-312.pyc
+++ b/api_layers/__pycache__/arduino_layer.cpython-312.pyc
Binary files differ
diff --git a/api_layers/__pycache__/arduino_layer.cpython-314.pyc b/api_layers/__pycache__/arduino_layer.cpython-314.pyc
index 1cfec4e..769e4f0 100644
--- a/api_layers/__pycache__/arduino_layer.cpython-314.pyc
+++ b/api_layers/__pycache__/arduino_layer.cpython-314.pyc
Binary files differ
diff --git a/api_layers/__pycache__/nidaqmx_layer.cpython-312.pyc b/api_layers/__pycache__/nidaqmx_layer.cpython-312.pyc
index d310f54..8dda62e 100644
--- a/api_layers/__pycache__/nidaqmx_layer.cpython-312.pyc
+++ b/api_layers/__pycache__/nidaqmx_layer.cpython-312.pyc
Binary files differ
diff --git a/api_layers/__pycache__/nidaqmx_layer.cpython-314.pyc b/api_layers/__pycache__/nidaqmx_layer.cpython-314.pyc
index 6902c49..c11967d 100644
--- a/api_layers/__pycache__/nidaqmx_layer.cpython-314.pyc
+++ b/api_layers/__pycache__/nidaqmx_layer.cpython-314.pyc
Binary files differ
diff --git a/api_layers/__pycache__/port_registry.cpython-312.pyc b/api_layers/__pycache__/port_registry.cpython-312.pyc
index 48e7384..088d6d3 100644
--- a/api_layers/__pycache__/port_registry.cpython-312.pyc
+++ b/api_layers/__pycache__/port_registry.cpython-312.pyc
Binary files differ
diff --git a/api_layers/__pycache__/port_registry.cpython-314.pyc b/api_layers/__pycache__/port_registry.cpython-314.pyc
new file mode 100644
index 0000000..3ff0ab0
--- /dev/null
+++ b/api_layers/__pycache__/port_registry.cpython-314.pyc
Binary files differ
diff --git a/api_layers/arduino_layer.py b/api_layers/arduino_layer.py
index fed54f9..4f8cee4 100644
--- a/api_layers/arduino_layer.py
+++ b/api_layers/arduino_layer.py
@@ -27,6 +27,16 @@ PC → Arduino (commands, newline-terminated):
C:KP:1.2
C:MODE:1
+ DPIN:IN:<pins> Configure digital input pins (CSV pin numbers, no 'D' prefix)
+ DPIN:IN:2,3,8 → set DI pins to 2,3,8; sets N_DIG_IN=3
+
+ DPIN:OUT:<pins> Configure digital output pins (CSV pin numbers, no 'D' prefix)
+ DPIN:OUT:5,6,13 → set DO pins to 5,6,13; sets N_DIG_OUT=3
+
+ APIN:<indices> Configure analog input pins (CSV indices 0–5 into A0–A5)
+ APIN:0,1,3 → read A0,A1,A3; sets N_ANALOG=3
+ Output labels use actual indices: A0:val,A1:val,A3:val
+
Q:<name> Request current reading by name (Arduino replies immediately)
Q:TEMP → Arduino sends TEMP:23.45\n
@@ -75,6 +85,9 @@ class ArduinoLayer:
DEFAULT_ANALOG_PINS = ["A0", "A1", "A2", "A3", "A4", "A5"]
DEFAULT_DIGITAL_PINS = ["D2", "D3", "D4", "D5", "D6", "D7"]
+ # Firmware DIGITAL_IN[] and DIGITAL_OUT[] arrays — match arduino_layer.py firmware sketch
+ DEFAULT_DI_PINS = ["D2", "D3", "D4"]
+ DEFAULT_DO_PINS = ["D5", "D6", "D7", "D9", "D10", "D11"]
def __init__(
self,
@@ -262,6 +275,48 @@ class ArduinoLayer:
"""Reset all outputs to default state. Sends: X:RESET\n"""
return self._send("X:RESET")
+ def configure_pins(
+ self,
+ di_pins: List[str] = None,
+ do_pins: List[str] = None,
+ analog_pins: List[str] = None,
+ ) -> bool:
+ """
+ Send pin-configuration commands so the firmware activates the requested channels.
+ No-op in simulation mode. Commands are deferred 1 s to allow Arduino boot time.
+
+ di_pins: ["D2","D3","D8"] — sends DPIN:IN:2,3,8
+ do_pins: ["D5","D6","D9"] — sends DPIN:OUT:5,6,9
+ analog_pins: ["A0","A1","A3"] — sends APIN:0,1,3
+ """
+ if self.simulate:
+ return True
+
+ def _dnum(p: str) -> str:
+ return p[1:] if p.upper().startswith("D") else p
+
+ def _anum(p: str) -> str:
+ return p[1:] if p.upper().startswith("A") else p
+
+ cmds = []
+ if di_pins:
+ cmds.append(f"DPIN:IN:{','.join(_dnum(p) for p in di_pins)}")
+ if do_pins:
+ cmds.append(f"DPIN:OUT:{','.join(_dnum(p) for p in do_pins)}")
+ if analog_pins:
+ cmds.append(f"APIN:{','.join(_anum(p) for p in analog_pins)}")
+
+ if not cmds:
+ return True
+
+ def _deferred():
+ time.sleep(1.0)
+ for cmd in cmds:
+ self._send(cmd)
+
+ threading.Thread(target=_deferred, daemon=True, name="PinInit").start()
+ return True
+
# ── Legacy compat ─────────────────────────────────────────────────────
def write(self, pin: str, value: int) -> bool:
@@ -546,12 +601,13 @@ ARDUINO_FIRMWARE = r"""
*/
// ── Configuration ─────────────────────────────────────────────────────────
-const int ANALOG_PINS[] = {A0, A1, A2, A3, A4, A5};
-const int DIGITAL_IN[] = {2, 3, 4};
-const int DIGITAL_OUT[] = {5, 6, 7, 9, 10, 11}; // 9,10,11 are PWM-capable
-const int N_ANALOG = 1; // ← set to how many analog pins you use
-const int N_DIG_IN = 0; // ← set to how many digital inputs you use
-const int N_DIG_OUT = 6; // ← set to how many digital outputs you use
+int ANALOG_PINS[6] = {A0, A1, A2, A3, A4, A5}; // actual pin numbers (reconfigured by APIN:)
+int ANALOG_IDX[6] = {0, 1, 2, 3, 4, 5}; // label indices used in output (A0, A1, …)
+int DIGITAL_IN[16] = {2, 3, 4}; // reconfigured at runtime via DPIN:IN:
+int DIGITAL_OUT[16] = {5, 6, 7, 9, 10, 11}; // reconfigured via DPIN:OUT:
+int N_ANALOG = 0; // set by APIN: command (0 = inactive until configured by PC)
+int N_DIG_IN = 0; // set by DPIN:IN: command (0 = inactive until configured)
+int N_DIG_OUT = 0; // set by DPIN:OUT: command (0 = inactive until configured)
const int SEND_INTERVAL = 50; // ms between data frames (50 = 20 Hz)
const long BAUD_RATE = 115200;
@@ -652,6 +708,57 @@ void handleCommands() {
Serial.print("ACK:"); Serial.println(cmd);
}
+ // APIN:0,1,3 — reconfigure analog inputs at runtime (indices 0–5 into A0–A5)
+ else if (type == 'A') {
+ if (!cmd.startsWith("APIN:")) { Serial.println("ERR:Bad A command"); return; }
+ String pinList = cmd.substring(5); // "0,1,3"
+ const int _APINS[] = {A0,A1,A2,A3,A4,A5};
+ N_ANALOG = 0;
+ int start = 0;
+ for (int i = 0; i <= (int)pinList.length(); i++) {
+ if (i == (int)pinList.length() || pinList[i] == ',') {
+ String tok = pinList.substring(start, i); tok.trim();
+ if (tok.length() > 0 && N_ANALOG < 6) {
+ int idx = tok.toInt();
+ if (idx >= 0 && idx < 6) {
+ ANALOG_PINS[N_ANALOG] = _APINS[idx];
+ ANALOG_IDX[N_ANALOG] = idx;
+ N_ANALOG++;
+ }
+ }
+ start = i + 1;
+ }
+ }
+ Serial.print("ACK:"); Serial.println(cmd);
+ }
+
+ // DPIN:IN:2,3,8 or DPIN:OUT:5,6,7 — reconfigure digital I/O pins at runtime
+ else if (type == 'D') {
+ int c1 = cmd.indexOf(':', 2);
+ int c2 = (c1 >= 0) ? cmd.indexOf(':', c1 + 1) : -1;
+ if (c1 < 0 || c2 < 0) { Serial.println("ERR:Bad DPIN format"); return; }
+ String dir = cmd.substring(2, c1); // "IN" or "OUT"
+ String pinList = cmd.substring(c2 + 1); // "2,3,8"
+ bool isIn = (dir == "IN");
+ int* arr = isIn ? DIGITAL_IN : DIGITAL_OUT;
+ int* cnt = isIn ? &N_DIG_IN : &N_DIG_OUT;
+ int mode = isIn ? INPUT_PULLUP : OUTPUT;
+ *cnt = 0;
+ int start = 0;
+ for (int i = 0; i <= (int)pinList.length(); i++) {
+ if (i == (int)pinList.length() || pinList[i] == ',') {
+ String tok = pinList.substring(start, i); tok.trim();
+ if (tok.length() > 0 && *cnt < 16) {
+ arr[*cnt] = tok.toInt();
+ pinMode(arr[*cnt], mode);
+ (*cnt)++;
+ }
+ start = i + 1;
+ }
+ }
+ Serial.print("ACK:"); Serial.println(cmd);
+ }
+
else {
Serial.print("ERR:Unknown command: "); Serial.println(cmd);
}
@@ -671,7 +778,7 @@ void sendFrame() {
for (int i = 0; i < N_ANALOG; i++) {
float v = analogRead(ANALOG_PINS[i]) * (5.0 / 1023.0);
if (!first) out += ",";
- out += "A" + String(i) + ":" + String(v, 3);
+ out += "A" + String(ANALOG_IDX[i]) + ":" + String(v, 3);
first = false;
}
// Digital inputs (INPUT_PULLUP — invert so pressed=1)