ICAM Toulouse · Year 2 · Team 4 · Electronics manager

O2 BoatA 70 cm radio-controlled jet boat that has to throw water 60 cm onto a target. I owned the electronics and the code that drives them.

My role
Electronics manager: architecture, propulsion, FPGA logic, ESP32 web interface, tests
Team
5 · hull, assembly, electronics, remote control, mobility
Client brief
70 cm monohull · 12 V brushed motor · 60 cm water jet
Hull
V-shape, thermoformed ABS, self-righting flood chamber
Outcome
Floats, moves, throws water, remote-controlled. Delivered end of year 2
Thermoformed hull with electronics fitted
Scale hull · electronics fitted for the propulsion test
CAD of the jet drive assembly
Jet drive · motor, shaft, impeller, steering nozzle
01 · The hand-overValidate before building

A previous team designed it on paper. Ours had to prove it would actually work.

Semester one was a series of sprints: validate or replace every choice made the year before, function by function. Buoyancy, movement, water throw, control. Semester two, build it.

Changed

Hull wall 1 cm → 0.3 cm and a smaller footprint to hit 70 cm. Lighter roof with a ledge to keep water out.

Kept

The V-hull with a flood chamber: air-filled upright, it floods when capsized and rolls the boat back.

02 · Will it floatArchimedes, then SolidWorks
Masseshull + roof 3 kg · components 1 kg · max immersed volume 0.01047 m³
Displacement limit ρ · V10.47kg
Buoyancy available m · g102.9N
Fitted weight 4 kg · g39.2N
Immersed volume when fitted0.0042m³
Waterline on a 12.6 cm hull5.58cm

7.5 kg of margin before the hull sinks. The catch was lateral: the flood chamber puts 2.31 kg on one side against 1.31 kg on the other, so components and a 1 kg ballast go to port to keep the boat level under way.

39 N ≪ 103 Nit floats, with room for 7.5 kg of kit
03 · Electronic architectureWhat I designed
1

Power and propulsion

  • 12 V · 12 Ah battery feeding an L298 H-bridge for speed and reverse.
  • A jet needs revs, not torque: a small, fast JYCRS390H 12 V brushed motor driving a 3D-printed impeller.
  • Servo on the nozzle for steering; current sensor and compass on the bus.
General electronic diagram
General electronic diagram
2

Three brains

  • ESP32 hosts the Wi-Fi web interface: speed, battery, link status, start/stop.
  • Arduino MKR + Vidor: the Vidor’s FPGA decodes the radio receiver in hardware.
  • Mode selection: phone, remote or autopilot, the remote taking over past ~100 m when the phone signal drops.
Electronics bay with battery and motor
Electronics bay · battery, motor, wiring
04 · Counting pulses in hardwareFPGA logic · Logisim

The receiver outputs a pulse between 1 and 2 ms. I wanted 8-bit resolution over that window, so 256 counts in 2 ms.

Count rate 256 / 2 ms128kHz
Clock divider 70 MHz / 128 kHz÷ 547
Comparator threshold for throttle64
128 – 170
Left

Steering band read from the counter value.

170 – 212
Neutral

Same bands select the pilot: phone, remote, autopilot.

212 – 256
Right

Above 64 on the throttle channel: speed up. Below: slow down.

05 · SoftwareWeb UI on the boat · logic in the FPGA

Two kinds of code. A web page served by the ESP32 over its own Wi-Fi, so any phone becomes the console; and hardware logic drawn in Logisim for the FPGA, so decoding the radio pulses costs the microcontroller nothing.

  • Interface first. HTML / CSS / JS page written and tested on a reference board: start, stop, speed, battery, Wi-Fi and radio link status. Then moved to the Arduino IDE and wired to the boat’s own sensors.
  • Who is in charge. The ESP32 pings the phone every second. No answer past ~100 m and control hands over to the radio remote; the FPGA switches the mode.
  • Pulse to number. A ÷547 divider, a 256-step counter built from four 4-bit counters, and a comparator. One byte per channel, no interrupts, no jitter.
// ESP32 · who drives the boat
void loop() {
  if (millis() - lastPing > 1000) {
    phoneAlive = server.ping(phone);   // 1 Hz heartbeat
    lastPing   = millis();
  }
  mode = phoneAlive ? PHONE : REMOTE;   // remote past ~100 m
  fpga.select(mode);                    // 128–170 · 170–212 · 212–256

  int throttle = fpga.count(CH_THROTTLE);
  hbridge.drive(throttle > 64 ? FASTER : SLOWER);
  nozzle.write(bandToAngle(fpga.count(CH_STEER)));

  ui.send(speed, battery, mode);        // live telemetry to the web page
}
Sketch of the control logic · ESP32 + Vidor FPGA · L298 H-bridge
06 · Building itPlaster, heat, glue
H-bridge · L298FPGA · Arduino VidorESP32 · Wi-Fi UILogisimSolidWorksThermoforming3D printingGantt · OBS / PBS / WBS