Skip to content

Commit e6d6166

Browse files
committed
add arduino firmware
1 parent e35ad2d commit e6d6166

File tree

3 files changed

+488
-0
lines changed

3 files changed

+488
-0
lines changed
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# Arduino Firmware for Ethopy
2+
3+
This directory contains two Arduino firmware options for interfacing with behavioral experiment hardware. Both support lick detection, proximity sensing, and liquid reward delivery.
4+
5+
## Choose Your Firmware
6+
7+
### Option 1: arduino_digital_comm.ino
8+
**For basic setups with digital pin outputs**
9+
10+
**What it does:**
11+
- Reads analog sensors and outputs digital HIGH/LOW signals on pins 8, 9, 10
12+
- Perfect for connecting to Raspberry Pi GPIO or other digital input devices
13+
- No serial communication (doesn't send data to computers via USB)
14+
- Hardware calibration with button press
15+
- Minimal memory usage and simple operation
16+
17+
### Option 2: arduino_serial_comm.ino
18+
**For computer-controlled experiments with serial communication**
19+
20+
**What it does:**
21+
- Everything from Option 1 PLUS full computer communication
22+
- Sends real-time JSON messages to computer about sensor events
23+
- Receives commands from computer to control liquid dispensers
24+
- Digital pin outputs (same as Option 1) for immediate hardware responses
25+
- Advanced event detection and logging
26+
27+
**Use this if:**
28+
- You want to record all animal behavior data on your computer
29+
- You need to control liquid dispensers remotely from software
30+
- You want real-time monitoring and data logging
31+
32+
**Technical details:**
33+
- Bidirectional JSON communication at 115200 baud
34+
- Real-time event notifications (lick detection, proximity changes)
35+
- Remote liquid dispensing control via serial commands
36+
- State change detection to avoid message spam
37+
38+
## Hardware Requirements
39+
40+
- Arduino or compatible microcontroller
41+
- Analog sensors (capacitive/optical lick detectors, proximity sensor)
42+
- Liquid dispensers (solenoid valves or peristaltic pumps)
43+
- Pushbutton for calibration
44+
- Appropriate power supply for dispensers
45+
46+
## Pin Connections
47+
48+
```
49+
Analog Inputs:
50+
- A0: Center/proximity sensor
51+
- A1: Lick detector 2
52+
- A2: Lick detector 1
53+
54+
Digital Outputs:
55+
- Pin 8: Lick detector 1 (on/off)
56+
- Pin 9: Lick detector 2 state (on/off)
57+
- Pin 10: Center sensor state (on/off)
58+
- Pin 4: Liquid valve 1 control (only in in serial_comm)
59+
- Pin 5: Liquid valve 2 control (only in in serial_comm)
60+
61+
Digital Inputs:
62+
- Pin 3: Calibration button
63+
```
64+
65+
## Installation
66+
67+
### For arduino_digital_comm.ino (Simple Setup)
68+
69+
1. **Install Arduino IDE** (version 1.8.0 or newer)
70+
2. **Open firmware file**:
71+
- Open `arduino_digital_comm.ino` in Arduino IDE
72+
3. **Upload to Arduino**:
73+
- Select your Arduino board type
74+
- Select the correct COM port
75+
- Click Upload
76+
77+
### For arduino_serial_comm.ino (Advanced Setup)
78+
79+
1. **Install Arduino IDE** (version 1.8.0 or newer)
80+
2. **Install ArduinoJson library**:
81+
- Open Arduino IDE
82+
- Go to Sketch → Include Library → Manage Libraries
83+
- Search for "ArduinoJson"
84+
- Install version 6.x
85+
3. **Open firmware file**:
86+
- Open `arduino_serial_comm.ino` in Arduino IDE
87+
4. **Upload to Arduino**:
88+
- Select your Arduino board type
89+
- Select the correct COM port
90+
- Click Upload
91+
92+
## Which Firmware Should You Choose?
93+
94+
**Choose arduino_digital_comm.ino if:**
95+
- You want simple analog-to-digital conversion
96+
- You don't need computer serial communication
97+
98+
**Choose arduino_serial_comm.ino if:**
99+
- You need real-time communication with a computer
100+
101+
## Calibration
102+
103+
1. **Hardware calibration**:
104+
- Press and hold the calibration button (Pin 3)
105+
- Current sensor readings become new thresholds
106+
- Thresholds are stored in EEPROM
107+
- Release button to complete calibration
108+
109+
2. **When to calibrate**:
110+
- First time setup
111+
- After hardware changes
112+
- If sensor sensitivity changes
113+
- Environmental condition changes
114+
115+
116+
## Integration with Ethopy
117+
118+
### For arduino_serial_comm.ino (Serial Communication)
119+
Works with Ethopy's `Arduino.py` interface:
120+
- Automatic serial port detection and connection
121+
- JSON message parsing and validation
122+
- Event logging with precise timestamps
123+
- Integration with experiment control workflows
124+
- Baudrate: 115200 (configurable in code)
125+
126+
### For arduino_digital_comm.ino (Digital Pins)
127+
Works with Ethopy's `RPPorts.py` interface for Raspberry Pi:
128+
- Direct GPIO pin reading (pins 8, 9, 10)
129+
- No serial communication overhead
130+
- Perfect for real-time applications
131+
- Raspberry Pi hardware SPI/I2C compatibility
132+
133+
## Sensor Types & Wiring
134+
135+
### Supported Sensor Types
136+
- **Capacitive lick detectors**: Connect to analog inputs A1, A2
137+
- **Optical break-beam sensors**: Use with voltage divider circuits
138+
- **Proximity sensors**: IR or capacitive types on A0
139+
- **Custom analog sensors**: 0-5V output range
140+
141+
## Testing & Troubleshooting
142+
143+
### Testing Without Full Setup
144+
1. **Upload firmware** to Arduino
145+
2. **Open Serial Monitor** (115200 baud for serial_comm version)
146+
3. **Touch analog pins** A0, A1, A2 with finger to simulate sensors
147+
4. **Press Pin 3 to GND** to test calibration
148+
5. **Watch digital pins 8, 9, 10** with LEDs or multimeter
149+
150+
### Common Issues & Solutions
151+
| Problem | Solution |
152+
|---------|----------|
153+
| Upload fails | Check board type and COM port selection |
154+
| Sensors not responding | Verify power and ground connections |
155+
| Thresholds incorrect | Recalibrate using button (Pin 3) |
156+
| JSON errors | Install ArduinoJson library v6.x |
157+
| No serial communication | Check baud rate (115200) and cable |
158+
| False triggers | Adjust sensor distance or add noise filtering |
159+
160+
### Customization Options
161+
- **Change pin assignments**: Modify `const int` declarations at top of file
162+
- **Adjust baud rate**: Change `Serial.begin(115200)` to desired rate
163+
- **Modify thresholds**: Use calibration button or edit EEPROM values
164+
- **Add sensors**: Extend code following existing analog input pattern
165+
166+
## Safety Notes
167+
168+
- Always disconnect power when wiring
169+
- Use appropriate current limiting for LEDs (220Ω resistors recommended)
170+
- Ensure proper isolation for liquid dispensers (use relays/optocouplers)
171+
- Test all connections before animal experiments
172+
- Keep water and liquids away from electronics
173+
- Use shielded cables for analog sensors to reduce noise
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*
2+
* Ethopy Arduino Firmware - Digital Communication Version
3+
*
4+
* Simple analog-to-digital conversion for behavioral experiments:
5+
* - Reads analog sensors (lick detectors, proximity sensors)
6+
* - Outputs digital signals for detected states
7+
* - Hardware calibration with EEPROM storage
8+
*
9+
* Use this version for basic setups that don't need computer communication.
10+
*/
11+
12+
#include <EEPROM.h>
13+
14+
// Pin assignments
15+
const int LICK_PIN_1 = 8; // output Port 1
16+
const int LICK_PIN_2 = 9; // output Port 2
17+
const int CENTER_PIN = 10; // output Center Port
18+
const int INTERRUPT_PIN = 3; // interrupt pin
19+
20+
// Analog input pins
21+
const int ANALOG_CENTER = A0; // Analog input for center sensor
22+
const int ANALOG_LICK_1 = A2; // Analog input for lick detector 1
23+
const int ANALOG_LICK_2 = A1; // Analog input for lick detector 2
24+
25+
// EEPROM addresses for saving the the calibration thresholds
26+
const int EEPROM_LICK_1 = 0;
27+
const int EEPROM_LICK_2 = 2;
28+
const int EEPROM_CENTER = 4;
29+
30+
// Global variables - Sensor thresholds (stored in EEPROM)
31+
int threshold_center; // Threshold value for center/proximity sensor detection
32+
int threshold_lick_1; // Threshold value for lick detector 1 activation
33+
int threshold_lick_2; // Threshold value for lick detector 2 activation
34+
35+
// Current sensor states (true when sensor is activated)
36+
bool low_center = false; // Current state of center/proximity sensor
37+
bool low_lick_1 = false; // Current state of lick detector 1
38+
bool low_lick_2 = false; // Current state of lick detector 2
39+
40+
// Raw analog sensor readings
41+
int CenterInput; // Raw analog reading from center/proximity sensor
42+
int LickInput1; // Raw analog reading from lick detector 1
43+
int LickInput2; // Raw analog reading from lick detector 2
44+
45+
// Temporary variable for calibration process
46+
int calibration_value; // Holds sensor readings during calibration
47+
48+
void setup() {
49+
// Get stored thresholds
50+
threshold_lick_1 = readIntFromEEPROM(EEPROM_LICK_1);
51+
threshold_lick_2 = readIntFromEEPROM(EEPROM_LICK_2);
52+
threshold_center = readIntFromEEPROM(EEPROM_CENTER);
53+
54+
// Setup input/output pins
55+
pinMode(INTERRUPT_PIN, INPUT_PULLUP); // sets interrupt pin
56+
pinMode(LICK_PIN_1, OUTPUT); // sets the pin as output Port 1
57+
pinMode(LICK_PIN_2, OUTPUT); // sets the pin as output Port 2
58+
pinMode(CENTER_PIN, OUTPUT); // sets the pin as output Port Center
59+
}
60+
61+
void loop() {
62+
// if interrupt, calibrate
63+
if (digitalRead(INTERRUPT_PIN) == LOW) {
64+
calibrate();
65+
}
66+
67+
// Read analog values
68+
CenterInput = analogRead(ANALOG_CENTER);
69+
LickInput1 = analogRead(ANALOG_LICK_1);
70+
LickInput2 = analogRead(ANALOG_LICK_2);
71+
72+
// Compare to stored thresholds
73+
low_lick_1 = LickInput1 > threshold_lick_1;
74+
low_lick_2 = LickInput2 > threshold_lick_2;
75+
low_center = CenterInput > threshold_center;
76+
77+
// Write digital outputs
78+
digitalWrite(LICK_PIN_1, low_lick_1);
79+
digitalWrite(LICK_PIN_2, low_lick_2);
80+
digitalWrite(CENTER_PIN, low_center);
81+
}
82+
83+
void calibrate() {
84+
// read max values to calibrate
85+
calibration_value = analogRead(ANALOG_LICK_1);
86+
writeIntIntoEEPROM(EEPROM_LICK_1, calibration_value);
87+
calibration_value = analogRead(ANALOG_LICK_2);
88+
writeIntIntoEEPROM(EEPROM_LICK_2, calibration_value);
89+
calibration_value = analogRead(ANALOG_CENTER);
90+
writeIntIntoEEPROM(EEPROM_CENTER, calibration_value);
91+
92+
// Get stored thresholds
93+
threshold_lick_1 = readIntFromEEPROM(EEPROM_LICK_1);
94+
threshold_lick_2 = readIntFromEEPROM(EEPROM_LICK_2);
95+
threshold_center = readIntFromEEPROM(EEPROM_CENTER);
96+
}
97+
98+
void writeIntIntoEEPROM(int address, int number) {
99+
EEPROM.put(address, number >> 8);
100+
EEPROM.put(address + 1, number & 0xFF);
101+
}
102+
103+
int readIntFromEEPROM(int address) {
104+
return (EEPROM.read(address) << 8) + EEPROM.read(address + 1);
105+
}

0 commit comments

Comments
 (0)