0
# Advanced Arduino Features
1
2
Specialized Arduino functionality including interrupts, tone generation, pulse measurement, and EEPROM operations for advanced hardware control. These features enable sophisticated Arduino applications with real-time event handling, audio output, timing measurements, and persistent data storage.
3
4
## Capabilities
5
6
### External Interrupts
7
8
Hardware interrupt support for real-time event handling on Arduino interrupt-capable pins.
9
10
```java { .api }
11
enum InterruptPin {
12
PIN_2_INT0, // Arduino Uno pin 2 (interrupt 0)
13
PIN_3_INT1; // Arduino Uno pin 3 (interrupt 1)
14
15
byte getValue();
16
static InterruptPin fromValue(byte b);
17
}
18
19
enum InterruptTrigger {
20
CHANGE, // Trigger on any logic change
21
RISING, // Trigger on rising edge (LOW to HIGH)
22
FALLING, // Trigger on falling edge (HIGH to LOW)
23
LOW; // Trigger when pin is LOW
24
}
25
26
// Interrupt management commands
27
static FixedSizePacket createAttachInterrupt(InterruptPin interrupt, InterruptTrigger mode);
28
static FixedSizePacket createDetachInterrupt(InterruptPin interrupt);
29
30
// Interrupt notification message
31
class InterruptNotificationMsg extends JArduinoProtocolPacket {
32
InterruptPin getInterrupt();
33
}
34
```
35
36
### Tone Generation
37
38
Audio tone generation capability for buzzers, speakers, and audio feedback.
39
40
```java { .api }
41
// Tone generation commands
42
static FixedSizePacket createTone(DigitalPin pin, short frequency, short duration);
43
static FixedSizePacket createNoTone(DigitalPin pin);
44
45
// Tone command messages
46
class ToneMsg extends JArduinoProtocolPacket {
47
DigitalPin getPin();
48
short getFrequency(); // Hz (20 - 20000)
49
short getDuration(); // milliseconds (0 = continuous)
50
}
51
52
class NoToneMsg extends JArduinoProtocolPacket {
53
DigitalPin getPin();
54
}
55
```
56
57
### Pulse Measurement
58
59
Precise timing measurement for ultrasonic sensors, encoders, and timing-critical applications.
60
61
```java { .api }
62
// Pulse measurement command
63
static FixedSizePacket createPulseIn(DigitalPin pin, DigitalState state);
64
65
// Pulse measurement messages
66
class PulseInMsg extends JArduinoProtocolPacket {
67
DigitalPin getPin();
68
DigitalState getState(); // HIGH or LOW pulse to measure
69
}
70
71
class PulseInResultMsg extends JArduinoProtocolPacket {
72
int getValue(); // Pulse duration in microseconds
73
}
74
```
75
76
### EEPROM Operations
77
78
Non-volatile memory operations for persistent configuration and data storage.
79
80
```java { .api }
81
// EEPROM commands
82
static FixedSizePacket createEeprom_read(short address);
83
static FixedSizePacket createEeprom_write(short address, byte value);
84
static FixedSizePacket createEeprom_sync_write(short address, byte value);
85
86
// EEPROM messages
87
class Eeprom_readMsg extends JArduinoProtocolPacket {
88
short getAddress(); // EEPROM address (0-1023 for Arduino Uno)
89
}
90
91
class Eeprom_writeMsg extends JArduinoProtocolPacket {
92
short getAddress();
93
byte getValue();
94
}
95
96
class Eeprom_sync_writeMsg extends JArduinoProtocolPacket {
97
short getAddress();
98
byte getValue();
99
}
100
101
// EEPROM result messages
102
class Eeprom_valueMsg extends JArduinoProtocolPacket {
103
short getAddress();
104
byte getValue();
105
}
106
107
class Eeprom_write_ackMsg extends JArduinoProtocolPacket {
108
short getAddress();
109
}
110
```
111
112
### Communication Testing
113
114
Built-in connectivity testing for Arduino communication reliability.
115
116
```java { .api }
117
// Ping/pong commands for connection testing
118
static FixedSizePacket createPing();
119
static FixedSizePacket createPong();
120
121
// Ping/pong messages
122
class PingMsg extends JArduinoProtocolPacket;
123
class PongMsg extends JArduinoProtocolPacket;
124
```
125
126
## Usage Examples
127
128
### External Interrupt Handling
129
130
```java
131
import org.sintef.jarduino.*;
132
import org.sintef.jarduino.observer.JArduinoObserver;
133
134
public class InterruptExample implements JArduinoObserver {
135
private Serial4JArduino arduino;
136
137
public void setupInterrupts() {
138
arduino = new Serial4JArduino("COM3");
139
arduino.register(this);
140
141
// Attach interrupt on pin 2 for button press detection
142
FixedSizePacket attachBtn = JArduinoProtocol.createAttachInterrupt(
143
InterruptPin.PIN_2_INT0,
144
InterruptTrigger.RISING
145
);
146
arduino.receiveMsg(attachBtn.getPacket());
147
148
// Attach interrupt on pin 3 for motion sensor
149
FixedSizePacket attachMotion = JArduinoProtocol.createAttachInterrupt(
150
InterruptPin.PIN_3_INT1,
151
InterruptTrigger.CHANGE
152
);
153
arduino.receiveMsg(attachMotion.getPacket());
154
}
155
156
@Override
157
public void receiveMsg(byte[] msg) {
158
FixedSizePacket packet = JArduinoProtocol.createMessageFromPacket(msg);
159
160
if (packet instanceof InterruptNotificationMsg) {
161
InterruptNotificationMsg notification = (InterruptNotificationMsg) packet;
162
InterruptPin interrupt = notification.getInterrupt();
163
164
switch (interrupt) {
165
case PIN_2_INT0:
166
handleButtonPress();
167
break;
168
case PIN_3_INT1:
169
handleMotionDetected();
170
break;
171
}
172
}
173
}
174
175
private void handleButtonPress() {
176
System.out.println("Button pressed!");
177
// Trigger LED or other response
178
FixedSizePacket ledOn = JArduinoProtocol.createDigitalWrite(
179
DigitalPin.PIN_13, DigitalState.HIGH
180
);
181
arduino.receiveMsg(ledOn.getPacket());
182
}
183
184
private void handleMotionDetected() {
185
System.out.println("Motion detected!");
186
// Trigger alarm or recording
187
}
188
189
public void cleanup() {
190
// Detach interrupts
191
FixedSizePacket detach1 = JArduinoProtocol.createDetachInterrupt(InterruptPin.PIN_2_INT0);
192
FixedSizePacket detach2 = JArduinoProtocol.createDetachInterrupt(InterruptPin.PIN_3_INT1);
193
194
arduino.receiveMsg(detach1.getPacket());
195
arduino.receiveMsg(detach2.getPacket());
196
arduino.close();
197
}
198
}
199
```
200
201
### Tone Generation for Audio Feedback
202
203
```java
204
public class AudioFeedbackExample {
205
private Serial4JArduino arduino;
206
207
public AudioFeedbackExample(Serial4JArduino arduino) {
208
this.arduino = arduino;
209
}
210
211
public void playStartupSound() {
212
// Play a sequence of tones
213
playTone(DigitalPin.PIN_8, 440, 200); // A4 for 200ms
214
sleep(50);
215
playTone(DigitalPin.PIN_8, 554, 200); // C#5 for 200ms
216
sleep(50);
217
playTone(DigitalPin.PIN_8, 659, 400); // E5 for 400ms
218
}
219
220
public void playErrorSound() {
221
// Play error tone
222
playTone(DigitalPin.PIN_8, 200, 500); // Low frequency, 500ms
223
}
224
225
public void playSuccessSound() {
226
// Play success chime
227
playTone(DigitalPin.PIN_8, 800, 100); // High frequency, short
228
sleep(50);
229
playTone(DigitalPin.PIN_8, 1000, 100);
230
}
231
232
public void startAlarm() {
233
// Continuous alarm tone
234
FixedSizePacket alarm = JArduinoProtocol.createTone(
235
DigitalPin.PIN_8,
236
(short) 1000,
237
(short) 0 // 0 = continuous
238
);
239
arduino.receiveMsg(alarm.getPacket());
240
}
241
242
public void stopAlarm() {
243
FixedSizePacket stopTone = JArduinoProtocol.createNoTone(DigitalPin.PIN_8);
244
arduino.receiveMsg(stopTone.getPacket());
245
}
246
247
private void playTone(DigitalPin pin, int frequency, int duration) {
248
FixedSizePacket tone = JArduinoProtocol.createTone(
249
pin,
250
(short) frequency,
251
(short) duration
252
);
253
arduino.receiveMsg(tone.getPacket());
254
}
255
256
private void sleep(int ms) {
257
try { Thread.sleep(ms); } catch (InterruptedException e) {}
258
}
259
}
260
```
261
262
### Ultrasonic Distance Sensor
263
264
```java
265
public class UltrasonicSensor implements JArduinoObserver {
266
private Serial4JArduino arduino;
267
private DigitalPin triggerPin = DigitalPin.PIN_7;
268
private DigitalPin echoPin = DigitalPin.PIN_8;
269
270
public UltrasonicSensor(Serial4JArduino arduino) {
271
this.arduino = arduino;
272
arduino.register(this);
273
setupPins();
274
}
275
276
private void setupPins() {
277
// Set trigger pin as output, echo pin as input
278
FixedSizePacket triggerMode = JArduinoProtocol.createPinMode(triggerPin, PinMode.OUTPUT);
279
FixedSizePacket echoMode = JArduinoProtocol.createPinMode(echoPin, PinMode.INPUT);
280
281
arduino.receiveMsg(triggerMode.getPacket());
282
arduino.receiveMsg(echoMode.getPacket());
283
}
284
285
public void measureDistance() {
286
// Send 10μs trigger pulse
287
FixedSizePacket triggerHigh = JArduinoProtocol.createDigitalWrite(triggerPin, DigitalState.HIGH);
288
arduino.receiveMsg(triggerHigh.getPacket());
289
290
try { Thread.sleep(1); } catch (InterruptedException e) {} // 1ms delay
291
292
FixedSizePacket triggerLow = JArduinoProtocol.createDigitalWrite(triggerPin, DigitalState.LOW);
293
arduino.receiveMsg(triggerLow.getPacket());
294
295
// Measure HIGH pulse duration on echo pin
296
FixedSizePacket pulseIn = JArduinoProtocol.createPulseIn(echoPin, DigitalState.HIGH);
297
arduino.receiveMsg(pulseIn.getPacket());
298
}
299
300
@Override
301
public void receiveMsg(byte[] msg) {
302
FixedSizePacket packet = JArduinoProtocol.createMessageFromPacket(msg);
303
304
if (packet instanceof PulseInResultMsg) {
305
PulseInResultMsg result = (PulseInResultMsg) packet;
306
int duration = result.getValue(); // Duration in microseconds
307
308
// Calculate distance in centimeters
309
// Speed of sound = 343 m/s = 0.0343 cm/μs
310
// Distance = (duration * 0.0343) / 2 (divide by 2 for round trip)
311
double distance = (duration * 0.0343) / 2.0;
312
313
System.out.println("Distance: " + distance + " cm");
314
handleDistanceMeasurement(distance);
315
}
316
}
317
318
private void handleDistanceMeasurement(double distance) {
319
if (distance < 10.0) {
320
System.out.println("Object too close!");
321
// Trigger warning
322
} else if (distance > 200.0) {
323
System.out.println("Object out of range");
324
} else {
325
System.out.println("Distance measured: " + distance + " cm");
326
}
327
}
328
}
329
```
330
331
### EEPROM Configuration Management
332
333
```java
334
public class ConfigurationManager implements JArduinoObserver {
335
private Serial4JArduino arduino;
336
private Map<Short, Byte> configCache = new HashMap<>();
337
338
// Configuration addresses
339
private static final short SENSOR_THRESHOLD_ADDR = 0;
340
private static final short LED_BRIGHTNESS_ADDR = 1;
341
private static final short ALARM_ENABLED_ADDR = 2;
342
private static final short CALIBRATION_ADDR = 10; // Multiple bytes starting at 10
343
344
public ConfigurationManager(Serial4JArduino arduino) {
345
this.arduino = arduino;
346
arduino.register(this);
347
}
348
349
public void loadConfiguration() {
350
// Read configuration values from EEPROM
351
readEEPROM(SENSOR_THRESHOLD_ADDR);
352
readEEPROM(LED_BRIGHTNESS_ADDR);
353
readEEPROM(ALARM_ENABLED_ADDR);
354
355
// Read calibration data (multiple bytes)
356
for (short addr = CALIBRATION_ADDR; addr < CALIBRATION_ADDR + 10; addr++) {
357
readEEPROM(addr);
358
}
359
}
360
361
public void saveConfiguration() {
362
// Save current configuration to EEPROM
363
writeEEPROM(SENSOR_THRESHOLD_ADDR, (byte) 128); // Default threshold
364
writeEEPROM(LED_BRIGHTNESS_ADDR, (byte) 255); // Max brightness
365
writeEEPROM(ALARM_ENABLED_ADDR, (byte) 1); // Alarm enabled
366
}
367
368
public void setSensorThreshold(int threshold) {
369
byte value = (byte) Math.min(255, Math.max(0, threshold));
370
writeEEPROM(SENSOR_THRESHOLD_ADDR, value);
371
}
372
373
public void setLEDBrightness(int brightness) {
374
byte value = (byte) Math.min(255, Math.max(0, brightness));
375
writeEEPROM(LED_BRIGHTNESS_ADDR, value);
376
}
377
378
public void setAlarmEnabled(boolean enabled) {
379
writeEEPROM(ALARM_ENABLED_ADDR, (byte) (enabled ? 1 : 0));
380
}
381
382
public void saveCalibrationData(byte[] calibrationData) {
383
for (int i = 0; i < calibrationData.length && i < 10; i++) {
384
writeEEPROM((short) (CALIBRATION_ADDR + i), calibrationData[i]);
385
}
386
}
387
388
private void readEEPROM(short address) {
389
FixedSizePacket read = JArduinoProtocol.createEeprom_read(address);
390
arduino.receiveMsg(read.getPacket());
391
}
392
393
private void writeEEPROM(short address, byte value) {
394
FixedSizePacket write = JArduinoProtocol.createEeprom_sync_write(address, value);
395
arduino.receiveMsg(write.getPacket());
396
}
397
398
@Override
399
public void receiveMsg(byte[] msg) {
400
FixedSizePacket packet = JArduinoProtocol.createMessageFromPacket(msg);
401
402
if (packet instanceof Eeprom_valueMsg) {
403
Eeprom_valueMsg result = (Eeprom_valueMsg) packet;
404
short address = result.getAddress();
405
byte value = result.getValue();
406
407
configCache.put(address, value);
408
System.out.println("EEPROM[" + address + "] = " + (value & 0xFF));
409
410
handleConfigurationValue(address, value);
411
412
} else if (packet instanceof Eeprom_write_ackMsg) {
413
Eeprom_write_ackMsg ack = (Eeprom_write_ackMsg) packet;
414
System.out.println("EEPROM write confirmed at address: " + ack.getAddress());
415
}
416
}
417
418
private void handleConfigurationValue(short address, byte value) {
419
switch (address) {
420
case SENSOR_THRESHOLD_ADDR:
421
System.out.println("Sensor threshold: " + (value & 0xFF));
422
break;
423
case LED_BRIGHTNESS_ADDR:
424
System.out.println("LED brightness: " + (value & 0xFF));
425
break;
426
case ALARM_ENABLED_ADDR:
427
System.out.println("Alarm enabled: " + (value != 0));
428
break;
429
default:
430
if (address >= CALIBRATION_ADDR && address < CALIBRATION_ADDR + 10) {
431
System.out.println("Calibration[" + (address - CALIBRATION_ADDR) + "] = " + (value & 0xFF));
432
}
433
break;
434
}
435
}
436
437
public byte getCachedValue(short address) {
438
return configCache.getOrDefault(address, (byte) 0);
439
}
440
}
441
```
442
443
### Connection Monitoring
444
445
```java
446
public class ConnectionMonitor implements JArduinoObserver {
447
private Serial4JArduino arduino;
448
private boolean isConnected = false;
449
private Timer pingTimer;
450
451
public ConnectionMonitor(Serial4JArduino arduino) {
452
this.arduino = arduino;
453
arduino.register(this);
454
startPeriodicPing();
455
}
456
457
private void startPeriodicPing() {
458
pingTimer = new Timer(5000, e -> sendPing()); // Ping every 5 seconds
459
pingTimer.start();
460
}
461
462
private void sendPing() {
463
FixedSizePacket ping = JArduinoProtocol.createPing();
464
arduino.receiveMsg(ping.getPacket());
465
466
// Set timeout to detect disconnection
467
Timer timeoutTimer = new Timer(2000, e -> handlePingTimeout());
468
timeoutTimer.setRepeats(false);
469
timeoutTimer.start();
470
}
471
472
@Override
473
public void receiveMsg(byte[] msg) {
474
FixedSizePacket packet = JArduinoProtocol.createMessageFromPacket(msg);
475
476
if (packet instanceof PongMsg) {
477
if (!isConnected) {
478
System.out.println("Arduino connection established");
479
isConnected = true;
480
notifyConnectionRestored();
481
}
482
}
483
}
484
485
private void handlePingTimeout() {
486
if (isConnected) {
487
System.out.println("Arduino connection lost");
488
isConnected = false;
489
notifyConnectionLost();
490
}
491
}
492
493
private void notifyConnectionRestored() {
494
// Notify application that Arduino is connected
495
}
496
497
private void notifyConnectionLost() {
498
// Notify application that Arduino is disconnected
499
// Could trigger reconnection attempts
500
}
501
502
public boolean isConnected() {
503
return isConnected;
504
}
505
506
public void cleanup() {
507
if (pingTimer != null) {
508
pingTimer.stop();
509
}
510
}
511
}
512
```
513
514
## Advanced Features Summary
515
516
### Interrupt Capabilities
517
- **Real-time event handling**: Sub-millisecond response to external events
518
- **Multiple trigger modes**: Rising, falling, change, and level detection
519
- **Two interrupt pins**: PIN_2_INT0 and PIN_3_INT1 on Arduino Uno
520
- **Automatic notifications**: Asynchronous interrupt messages to observers
521
522
### Audio Features
523
- **Frequency range**: 20 Hz to 20 kHz tone generation
524
- **Precise timing**: Millisecond-accurate duration control
525
- **Continuous tones**: Zero duration for ongoing audio
526
- **Multiple pins**: Any digital pin can generate tones
527
528
### Timing Measurements
529
- **Microsecond precision**: High-resolution pulse measurement
530
- **Ultrasonic sensors**: Perfect for HC-SR04 distance sensors
531
- **Encoder support**: Measure pulse widths from rotary encoders
532
- **Timeout handling**: Prevents blocking on missing pulses
533
534
### EEPROM Storage
535
- **1024 bytes**: Full Arduino Uno EEPROM capacity (addresses 0-1023)
536
- **Synchronous/asynchronous**: Choice of write modes
537
- **Wear leveling**: Minimize EEPROM wear with strategic addressing
538
- **Configuration management**: Perfect for persistent settings
539
540
### Connection Reliability
541
- **Ping/pong protocol**: Built-in connectivity testing
542
- **Automatic detection**: Observer-based connection monitoring
543
- **Timeout handling**: Configurable connection timeouts
544
- **Reconnection support**: Framework for automatic reconnection