Skip to content

Commit ef1411f

Browse files
Refactor codebase with clean library architecture and comprehensive API documentation
- Separate core libraries from examples in both implementations - Create modular library structure (src/lib/) for Arduino/Node.js and Raspberry Pi - Add complete API documentation (arduino-api.md, raspberry-pi-api.md) - Remove all commented-out code from Arduino firmware - Improve Python utilities with proper docstrings and structure - Fix threading.Event() bug in Raspberry Pi display code - Update configuration to use library modules - Move old implementations to to-sort/ for backup
1 parent ed08713 commit ef1411f

29 files changed

+3209
-898
lines changed

docs/api/arduino-api.md

Lines changed: 523 additions & 10 deletions
Large diffs are not rendered by default.

docs/api/raspberry-pi-api.md

Lines changed: 683 additions & 12 deletions
Large diffs are not rendered by default.

implementations/arduino-bluetooth/README.md

Lines changed: 224 additions & 103 deletions
Large diffs are not rendered by default.

implementations/arduino-bluetooth/firmware/AudioHaptics/AudioHaptics.ino

Lines changed: 24 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
#include <SoftwareSerial.h>
2-
//#include <OSCBundle.h>
3-
//#include <SLIPEncodedSerial.h>
4-
//SLIPEncodedSerial SLIPSerial(Serial);
52
#include <stdlib.h>
63
#include <stdio.h>
74

@@ -12,19 +9,14 @@ void print_time(unsigned long time_millis);
129

1310
char c=' ';
1411

15-
// RX, TX LEDs
16-
// UNO: SoftwareSerial Bluetooth( 8, 7 );
17-
// LILY: SoftwareSerial Bluetooth( 1, 0 ); ( 17, 16 );
18-
SoftwareSerial Bluetooth( 17, 16 ); //(7->RXblue , 8->TXblue
19-
//SLIPEncodedSerial SLIPSerial(SoftwareSerial);
12+
// Bluetooth serial communication (RX=17, TX=16)
13+
SoftwareSerial Bluetooth(17, 16);
2014

2115
// the on-board LED
2216
int LED = 13;// Arduino pin numbers
2317

24-
// the haptic-LEDs
25-
// UNO: PWM- int LEDPins[] = { 3, 5, 6, 9, 10, 11 };
26-
// LILY: PWM- int LEDPins[] = { 5, 6, 9, 10, 11 };
27-
int LEDPins[ ] = { 5, 6, 9, 10, 11 };
18+
// Haptic motor PWM pins
19+
int LEDPins[] = { 5, 6, 9, 10, 11 };
2820

2921
int FrontLeft = 5;
3022
int FrontRight = 11;
@@ -35,11 +27,9 @@ int Center = 9;
3527
int CW[ ] = { Center, SideLeft, FrontLeft, FrontRight, SideRight, Center }; //3
3628
int CCW[ ] = { Center, SideRight, FrontRight, FrontLeft, SideLeft, Center }; //4
3729
int PULSE[ ] = { Center, SideLeft, FrontLeft, Center, SideRight, FrontRight }; //7
38-
int PULSX[ ] = { Center, SideRight, FrontRight, Center, SideLeft, FrontLeft }; //7
30+
int PULSX[] = { Center, SideRight, FrontRight, Center, SideLeft, FrontLeft };
3931

40-
// Pedro add -- wants pattern 1: C | 2: C-SL|SR-C | 3: C-SL|SR-FL|FR-SL|SR-C // combo all together into pattern 4
41-
42-
int FRONT[ ] = { 5, 6 };
32+
int FRONT[] = { 5, 6 };
4333
int BACK[ ] = { 10, 11, 9 };
4434

4535
int FL[ ] = { 5, 5 }; // 5, 13
@@ -65,8 +55,7 @@ int numC;
6555
int freqC;
6656
int buzzC;
6757

68-
void LED_wave( int PINS[ ], int PINlength, int count, int freq) {
69-
//Bluetooth.println( "Testing LED array..." );
58+
void LED_wave( int PINS[], int PINlength, int count, int freq) {
7059
Serial.println("\nlights on");
7160
int delayTime = freq*100;
7261
Serial.print(delayTime);
@@ -84,28 +73,23 @@ void LED_wave( int PINS[ ], int PINlength, int count, int freq) {
8473
}
8574

8675
void setup() {
87-
Bluetooth.begin( 57600 ); //57600 115200
88-
//SLIPSerial.begin( 115200 );
89-
Serial.begin( 57600 );
76+
Bluetooth.begin(57600);
77+
Serial.begin(57600);
9078
pinMode( LED, OUTPUT );
9179
for ( index = 0; index <= 5; index++ ) {
9280
pinMode( LEDPins[ index ], OUTPUT );
9381
}
9482
}
9583

96-
void loop() {
97-
//OSCBundle bundleIN;
84+
void loop() {
9885
int size;
99-
int data = 4;;
86+
int data = 4;
10087
delay(500);
101-
if( (size=Bluetooth.available()) > 0 ) {
88+
if ((size = Bluetooth.available()) > 0) {
10289
lights = false;
10390
Serial.println(data);
104-
//Serial.println('\n');
105-
while(size--) {
106-
//Serial.println(data);
107-
//int in = 0;
108-
if (full==false) {
91+
while (size--) {
92+
if (full == false) {
10993
bundleIN[i] = Bluetooth.read();
11094
i++;
11195
if(i==data) {
@@ -187,66 +171,35 @@ void loop() {
187171
newIN = false;
188172
} else if (bundleIN[1]=='2') {
189173
for ( jindex = 0; jindex < numC; jindex++ ) {
190-
digitalWrite(9, HIGH);
174+
digitalWrite(9, HIGH);
191175
delay(freqC*25);
192-
digitalWrite(9, LOW);
193-
//delay(freqC*25);
194-
//digitalWrite(9, HIGH);
195-
//delay(freqC*100);
196-
//digitalWrite(9, LOW);
197-
digitalWrite(6, HIGH);
176+
digitalWrite(9, LOW);
177+
digitalWrite(6, HIGH);
198178
digitalWrite(10, HIGH);
199-
delay(freqC*25);
179+
delay(freqC*25);
200180
digitalWrite(10, LOW);
201-
digitalWrite(6, LOW);
202-
//digitalWrite(9, HIGH);
181+
digitalWrite(6, LOW);
203182
delay(freqC*25);
204-
//digitalWrite(9, LOW);
205-
//delay(freqC*50);
206183
}
207184
lights = true;
208185
newIN = false;
209186
} else if (bundleIN[1]=='3') {
210187
for ( jindex = 0; jindex < numC; jindex++ ) {
211-
digitalWrite(9, HIGH);
188+
digitalWrite(9, HIGH);
212189
delay(freqC*25);
213-
digitalWrite(9, LOW);
190+
digitalWrite(9, LOW);
214191
delay(freqC*25);
215-
//digitalWrite(9, HIGH);
216-
//delay(freqC*50);
217-
//digitalWrite(9, LOW);
218-
digitalWrite(6, HIGH);
192+
digitalWrite(6, HIGH);
219193
digitalWrite(10, HIGH);
220-
delay(freqC*25);
194+
delay(freqC*25);
221195
digitalWrite(10, LOW);
222-
digitalWrite(6, LOW);
196+
digitalWrite(6, LOW);
223197
digitalWrite(11, HIGH);
224198
digitalWrite(5, HIGH);
225199
delay(freqC*25);
226-
//digitalWrite(9, LOW);
227-
//delay(freqC*50);
228-
//digitalWrite(9, HIGH);
229-
//delay(freqC*50);
230-
//digitalWrite(9, LOW);
231-
//digitalWrite(6, HIGH);
232-
//digitalWrite(10, HIGH);
233-
//delay(freqC*50);
234-
//digitalWrite(6, LOW);
235-
//digitalWrite(10, LOW);
236200
digitalWrite(5, LOW);
237201
digitalWrite(11, LOW);
238202
delay(freqC*25);
239-
//digitalWrite(5, LOW);
240-
//digitalWrite(11, LOW);
241-
//digitalWrite(6, HIGH);
242-
//digitalWrite(10, HIGH);
243-
//delay(freqC*25);
244-
//digitalWrite(10, LOW);
245-
//digitalWrite(6, LOW);
246-
//digitalWrite(9, HIGH);
247-
//delay(freqC*25);
248-
//digitalWrite(9, LOW);
249-
//delay(freqC*100);
250203
}
251204
lights = true;
252205
newIN = false;
@@ -268,6 +221,5 @@ void loop() {
268221
newIN = false;
269222
}
270223
}
271-
//Serial.println('\n');
272224
}
273225
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# Arduino Bluetooth Server Examples
2+
3+
This directory contains example implementations showing different ways to use the On-Body Haptics system.
4+
5+
## Examples Overview
6+
7+
### 1. send-pattern.js - Basic OSC Pattern Sender
8+
9+
**What it does:** Sends a simple haptic pattern every second via OSC protocol
10+
11+
**Use case:** Testing the system, learning the OSC message format
12+
13+
**Usage:**
14+
```bash
15+
node examples/send-pattern.js
16+
```
17+
18+
**Configuration:**
19+
- Update `remoteAddress` to point to your haptic server's IP
20+
- Update `remotePort` to match your haptic server's OSC port (default: 9998)
21+
22+
### 2. websocket-server.js - WebSocket to OSC Bridge
23+
24+
**What it does:** Creates a WebSocket server that receives messages from web clients and forwards them as OSC commands to the haptic server
25+
26+
**Use case:** Web-based applications, browser-based controls, VR web apps
27+
28+
**Usage:**
29+
```bash
30+
node examples/websocket-server.js
31+
```
32+
33+
**Configuration:**
34+
- `WS_PORT`: WebSocket server port (default: 8080)
35+
- `OSC_REMOTE_ADDRESS`: IP of your haptic server
36+
- `OSC_REMOTE_PORT`: OSC port of your haptic server (default: 9998)
37+
38+
**Client Usage:**
39+
Connect to the WebSocket server and send the string `"sendHaptics"` to trigger a pattern
40+
41+
Example client code:
42+
```javascript
43+
const ws = new WebSocket('ws://localhost:8080');
44+
ws.onopen = () => {
45+
ws.send('sendHaptics');
46+
};
47+
```
48+
49+
### 3. threejs-vr-client.js - VR Head Tracking Integration
50+
51+
**What it does:** Demonstrates how to integrate haptic feedback with Three.js VR applications using head/gaze tracking
52+
53+
**Use case:** WebXR applications, VR experiences, interactive 3D environments
54+
55+
**Usage:**
56+
Include this module in your Three.js VR application and call `intersectHead()` in your render loop
57+
58+
**Integration:**
59+
```javascript
60+
import { intersectHead } from './threejs-vr-client.js';
61+
62+
let raycaster = new THREE.Raycaster();
63+
let websocket = new WebSocket('ws://localhost:8080');
64+
65+
function render() {
66+
intersectHead(raycaster, camera, userObject, websocket);
67+
renderer.render(scene, camera);
68+
}
69+
```
70+
71+
## Example Integration Workflow
72+
73+
1. **Start the haptic server:**
74+
```bash
75+
node src/index.js 0.0.0.0 9998
76+
```
77+
78+
2. **Start the WebSocket bridge (if needed):**
79+
```bash
80+
node examples/websocket-server.js
81+
```
82+
83+
3. **Test with pattern sender:**
84+
```bash
85+
node examples/send-pattern.js
86+
```
87+
88+
## Dependencies
89+
90+
All examples require the `osc` package:
91+
```bash
92+
npm install osc
93+
```
94+
95+
The WebSocket example also requires:
96+
```bash
97+
npm install ws
98+
```
99+
100+
The Three.js example requires Three.js in your web application:
101+
```bash
102+
npm install three
103+
```
104+
105+
## Custom Examples
106+
107+
These examples serve as starting points. You can:
108+
109+
- Modify the OSC message format to target different belts/buzzers
110+
- Change pattern parameters (repetitions, frequency)
111+
- Create custom WebSocket message protocols
112+
- Integrate with other 3D libraries or frameworks
113+
- Build custom UIs for haptic control
114+
115+
## OSC Message Format
116+
117+
All examples use the standard OSC format:
118+
119+
**Buzzer control:**
120+
```
121+
/belt_{1-6}/buzzer_{1-5}/frequency
122+
Arguments: [repetitions, frequency]
123+
```
124+
125+
**Pattern control:**
126+
```
127+
/belt_{1-6}/pattern_{1-4}/frequency
128+
Arguments: [repetitions, frequency]
129+
```
130+
131+
**Belt 6 = All belts** (broadcasts to all configured devices)
132+
133+
## Troubleshooting
134+
135+
**"Cannot connect to server"**
136+
- Verify the haptic server is running
137+
- Check IP addresses and ports in your config
138+
- Ensure firewall allows UDP (OSC) and TCP (WebSocket) connections
139+
140+
**"WebSocket connection refused"**
141+
- Ensure websocket-server.js is running
142+
- Check the WebSocket port (default: 8080)
143+
- Verify client is connecting to correct address
144+
145+
**"No haptic feedback"**
146+
- Check Bluetooth connections to Arduino devices
147+
- Verify MAC addresses in `config/default.json`
148+
- Check server console for error messages
149+
- Ensure Arduino firmware is uploaded and running
150+
151+
## Additional Resources
152+
153+
- [OSC Protocol Specification](../../../docs/api/osc-protocol.md)
154+
- [Arduino API Documentation](../../../docs/api/arduino-api.md)
155+
- [Integration Guides](../../../docs/integration/)

0 commit comments

Comments
 (0)