Skip to content

Commit c8b2725

Browse files
committed
code ready to test streaming to robot pipeline
1 parent f9bc4b3 commit c8b2725

File tree

3 files changed

+382
-73
lines changed

3 files changed

+382
-73
lines changed

soccer-robots-esp32/src/goalpost_mechanism.c

Lines changed: 123 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
#define IR_SENSOR_PIN GPIO_NUM_5 // IR receiver wire - GPIO5
1616

17-
//DRV8833 input pins for one motor
1817
#define MOTOR_IN1_PIN GPIO_NUM_18 // DRV8833 IN1 (forward)
1918
#define MOTOR_IN2_PIN GPIO_NUM_16 // DRV8833 IN2 (reverse)
2019

@@ -24,11 +23,7 @@
2423
#define DETECT_DELAY_MS 500 // wait time after ball detection
2524
#define SPIN_TIME_MS 2000 // how long to spin the motor
2625

27-
//server config
28-
// change to your Raspberry Pi / game server IP
29-
#define GOAL_SERVER_IP "???"
30-
31-
#define GOAL_SERVER_PORT 30000
26+
#define GOAL_LISTEN_PORT 30000
3227

3328
static const char *TAG = "IR_MOTOR";
3429

@@ -60,20 +55,20 @@ static void goalpost_led_pulse(int times)
6055
//motor helper functions
6156
static void motor_init(void)
6257
{
63-
// Configure motor pins as plain GPIO outputs
58+
//configure motor pins as plain GPIO outputs
6459
gpio_reset_pin(MOTOR_IN1_PIN);
6560
gpio_reset_pin(MOTOR_IN2_PIN);
6661
gpio_set_direction(MOTOR_IN1_PIN, GPIO_MODE_OUTPUT);
6762
gpio_set_direction(MOTOR_IN2_PIN, GPIO_MODE_OUTPUT);
6863

69-
// Start with motor stopped (both low => coast)
64+
//start with motor stopped (both low => coast)
7065
gpio_set_level(MOTOR_IN1_PIN, 0);
7166
gpio_set_level(MOTOR_IN2_PIN, 0);
7267
}
7368

7469
static void motor_spin_forward(void)
7570
{
76-
// Spin the motor forward: IN1 = 1, IN2 = 0
71+
//spin the motor forward: IN1 = 1, IN2 = 0
7772
gpio_set_level(MOTOR_IN1_PIN, 1);
7873
gpio_set_level(MOTOR_IN2_PIN, 0);
7974
}
@@ -84,11 +79,17 @@ static void motor_stop(void)
8479
gpio_set_level(MOTOR_IN2_PIN, 0);
8580
}
8681

87-
//ir sensor functions
82+
//IR sensor functions
8883
static void ir_sensor_init(void)
8984
{
90-
// Configure IR sensor as input with internal pull-up
91-
// Adafruit break-beam receiver is open-collector and needs a pull-up.
85+
//configure IR sensor as input with internal pull-up
86+
//Adafruit break-beam receiver is open-collector and needs a pull-up.
87+
/*
88+
turns on the ESP32’s internal pull-up resistor because
89+
the Adafruit break-beam sensor has an open-collector output
90+
it basically pulls the line low when the beam is broken
91+
otherwise it floats and needs a pull-up
92+
*/
9293
gpio_config_t io_conf = {
9394
.pin_bit_mask = (1ULL << IR_SENSOR_PIN),
9495
.mode = GPIO_MODE_INPUT,
@@ -107,31 +108,58 @@ static int ir_beam_broken(void)
107108
}
108109

109110
//network functions
110-
static int connect_to_goal_server(void)
111+
static int wait_for_pi_connection(void)
111112
{
112-
struct sockaddr_in dest_addr;
113-
int sock = -1;
113+
int listen_sock = -1;
114+
int client_sock = -1;
115+
struct sockaddr_in listen_addr;
116+
struct sockaddr_in source_addr;
117+
socklen_t addr_len = sizeof(source_addr);
118+
119+
//create TCP socket
120+
listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
121+
if (listen_sock < 0) {
122+
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
123+
return -1;
124+
}
114125

115-
dest_addr.sin_addr.s_addr = inet_addr(GOAL_SERVER_IP);
116-
dest_addr.sin_family = AF_INET;
117-
dest_addr.sin_port = htons(GOAL_SERVER_PORT);
126+
//allow quick reuse of the port if we reset
127+
int opt = 1;
128+
setsockopt(listen_sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
118129

119-
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
120-
if (sock < 0) {
121-
ESP_LOGE(TAG, "Unable to create socket: errno %d", errno);
130+
//bind to all local interfaces on GOAL_LISTEN_PORT
131+
listen_addr.sin_family = AF_INET;
132+
listen_addr.sin_port = htons(GOAL_LISTEN_PORT);
133+
listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
134+
135+
int err = bind(listen_sock, (struct sockaddr *)&listen_addr, sizeof(listen_addr));
136+
if (err < 0) {
137+
ESP_LOGE(TAG, "Socket unable to bind: errno %d", errno);
138+
close(listen_sock);
122139
return -1;
123140
}
124141

125-
ESP_LOGI(TAG, "Connecting to %s:%d", GOAL_SERVER_IP, GOAL_SERVER_PORT);
126-
int err = connect(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
127-
if (err != 0) {
128-
ESP_LOGE(TAG, "Socket unable to connect: errno %d", errno);
129-
close(sock);
142+
err = listen(listen_sock, 1);
143+
if (err < 0) {
144+
ESP_LOGE(TAG, "Error during listen: errno %d", errno);
145+
close(listen_sock);
130146
return -1;
131147
}
132148

133-
ESP_LOGI(TAG, "Successfully connected to goal server");
134-
return sock;
149+
ESP_LOGI(TAG, "Waiting for Raspberry Pi to connect on port %d...", GOAL_LISTEN_PORT);
150+
151+
//block here until the client/Pi connects
152+
client_sock = accept(listen_sock, (struct sockaddr *)&source_addr, &addr_len);
153+
if (client_sock < 0) {
154+
ESP_LOGE(TAG, "Unable to accept connection: errno %d", errno);
155+
close(listen_sock);
156+
return -1;
157+
}
158+
159+
ESP_LOGI(TAG, "Raspberry Pi connected!");
160+
161+
close(listen_sock);
162+
return client_sock;
135163
}
136164

137165
static void send_goal_to_server(int sock)
@@ -140,7 +168,7 @@ static void send_goal_to_server(int sock)
140168
return;
141169
}
142170

143-
// Follow the convention of messages ending with '|'
171+
//Follow the convention of messages ending with '|'
144172
const char *msg = "GOAL|\n";
145173
int len = strlen(msg);
146174

@@ -152,51 +180,54 @@ static void send_goal_to_server(int sock)
152180
}
153181
}
154182

183+
/*
155184
//goalpost task
156185
void goalpost_mechanism_task(void *pvParameters)
157186
{
158-
// Hardware init
187+
//hardware init
159188
ir_sensor_init();
160189
motor_init();
161190
goalpost_led_init();
162191
163192
ESP_LOGI(TAG, "Goalpost mechanism starting...");
164193
165-
// At this point Wi-Fi should already be up (wifi_setup_init was called in app_main)
166-
// Now connect to the game server:
194+
195+
//wait for the Raspberry Pi to connect to us
167196
int sock = -1;
168197
while (sock < 0) {
169-
sock = connect_to_goal_server();
198+
sock = wait_for_pi_connection();
170199
if (sock < 0) {
171-
ESP_LOGW(TAG, "Retrying server connection in 2 seconds...");
200+
ESP_LOGW(TAG, "Failed to get Pi connection, retrying in 2 seconds...");
172201
vTaskDelay(pdMS_TO_TICKS(2000));
173202
}
174203
}
204+
205+
int sock = -1;
175206
176207
ESP_LOGI(TAG, "Waiting for ball...");
177208
178209
while (true) {
179210
if (ir_beam_broken()) {
180-
// Beam broken → "ball detected"
211+
//beam broken → "ball detected"
181212
ESP_LOGI(TAG, "Ball detected! Beam broken.");
182213
goalpost_led_pulse(3); // 3 quick blinks
183214
184215
vTaskDelay(pdMS_TO_TICKS(DETECT_DELAY_MS));
185216
186-
// Spin the motor
217+
//spin the motor
187218
goalpost_led_set(1); // LED ON while spinning
188219
motor_spin_forward();
189220
190-
// Notify server about the goal
191-
send_goal_to_server(sock);
221+
//notify server about the goal
222+
//send_goal_to_server(sock);
192223
193224
vTaskDelay(pdMS_TO_TICKS(SPIN_TIME_MS));
194225
195-
// Stop motor and LED
226+
//stop motor and LED
196227
motor_stop();
197228
goalpost_led_set(0);
198229
199-
// Wait until beam is restored before re-arming
230+
//wait until beam is restored before re-arming
200231
while (ir_beam_broken()) {
201232
vTaskDelay(pdMS_TO_TICKS(50));
202233
}
@@ -207,10 +238,61 @@ void goalpost_mechanism_task(void *pvParameters)
207238
vTaskDelay(pdMS_TO_TICKS(50)); // small poll delay
208239
}
209240
210-
// Not really reached, but for completeness:
241+
//cleanup on exit (never reached in this example)
211242
if (sock >= 0) {
212243
shutdown(sock, 0);
213244
close(sock);
214245
}
215246
vTaskDelete(NULL);
216247
}
248+
*/
249+
250+
//task for testing goalpost mechanism without wifi
251+
void goalpost_mechanism_task(void *pvParameters)
252+
{
253+
//hardware init
254+
ir_sensor_init();
255+
motor_init();
256+
goalpost_led_init();
257+
258+
ESP_LOGI(TAG, "Goalpost HARDWARE TEST: no Wi-Fi sockets, just IR + motor");
259+
260+
bool last_broken = false;
261+
262+
while (true) {
263+
264+
bool broken = ir_beam_broken();
265+
266+
//log when the beam state changes
267+
if (broken != last_broken) {
268+
ESP_LOGI(TAG, "IR beam is now: %s", broken ? "BROKEN" : "OK");
269+
last_broken = broken;
270+
}
271+
272+
//trigger ONCE per break (edge trigger)
273+
if (broken) {
274+
ESP_LOGI(TAG, "Ball detected! Spinning motor once.");
275+
276+
goalpost_led_pulse(3); // blink a bit
277+
goalpost_led_set(1); // LED ON while spinning
278+
279+
motor_spin_forward(); // turn motor ON
280+
vTaskDelay(pdMS_TO_TICKS(SPIN_TIME_MS));
281+
282+
motor_stop(); // turn motor OFF
283+
goalpost_led_set(0); // LED OFF
284+
285+
ESP_LOGI(TAG, "Motor stopped, waiting for beam to restore...");
286+
287+
// Wait until beam is no longer broken
288+
while (ir_beam_broken()) {
289+
vTaskDelay(pdMS_TO_TICKS(50));
290+
}
291+
292+
ESP_LOGI(TAG, "Beam restored, re-armed.");
293+
}
294+
295+
vTaskDelay(pdMS_TO_TICKS(50));
296+
}
297+
}
298+

0 commit comments

Comments
 (0)