Aruna - ROV

Modular ROV for underwater exploration, discovery and monitoring

Similar projects worth following
Aruna is my attempt to create a low-cost modular ROV (remote operated vehicle) ecosystem. Complete with software, electrical hardware and mechanical hardware.

Because Aruna is very modular it can be used for many applications and easy be adjusted to the users need. For example by adding new sensors, adjusting the motor layout or even running it on a complete new system. This is all possible because of the modular nature of the project. The codebase is already cross-platform and the hardware is very flexible with many possible configurations.

This is the entry video for the Hackaday Prize 2020. It briefly shows the history of the project, the current state and the concept behind it. I hope you enjoy!


Monitoring and observing life is an important aspect of getting an insight on the current state of animal life and if they are in danger of extinction. This can however be a difficult process to do if the life you are trying to monitor is in difficult to reach places, or even hazarded environments to humans like deep water bodies. The ocean is a very fast place with many species that may suffer the hardest from climate change. Therefore, it is important to monitor, inspect and preserve them as much as possible. From the tiniest sea creatures living on the bottom of the ocean to the school of flying fish. Currently, doing so is an expensive operation and require a lot of human labour and expensive equipment like ROVs (remove operate vehicle). A marine expert has to be present to analyse the data and draw conclusions. To do this in a continues matter would be a very cumbersome and expensive task. As new equipment for monitoring is being developed it may be difficult to adapt the already existing hardware to these new equipment.


I propose a low cost, highly modular ROV: Aruna, with specialized equipment that can be used for underwater monitoring and marine research. The ROV can have a wide range of sensor and equipment such as:

  • Camera: This is not just useful for taking pictures and as a visual guide for controlling the ROV, but it can also be used in conjunction with an artificial network to automaticly detect fishes and counts them without user interference.
  • Soil sampler: To inspect life at the sea floor a sample of the soil can be taken with the ROV. For later (or on-board) analysis.
  • Water sample: To monitor the microscopic particles in the water like plankton or micro plastic particles. Samples can be taken from varying depths for further analyses.
  • Tag system: tagging an animal to monitor its behaviour or dropping a node on an interesting side for continues analysis to be later retrieved.
  • Microphone: for monitoring whale activity.

Any other equipment can be easily introduced later because of the modular nature of the ROV. The ROV was designed with modularity in mind, so it can be easily adjusted to the desired situation. The current design has 5DOF (degrees of freedom) using 6 propellers. Adding two extra propellers can be used to get full 6DOF. The model can also be substantially changed by converting it to a glider model, so it can be more effective on longer missions with greater distances where high mobility is not required. The high modular design of the ROV allows for all these adjustments and is at the heart of the implementation of the device.

Aside from the monitoring sensors described above a number of other sensors are to be used for navigation like gyroscope, pressure sensor, accelerometer, GNSS, compass and sonar. The goal is to allow the ROV to complete a mission with as little human interference as possible. Thus, the user can choice to deploy multiple ROVs at a site which all perform a set mission and communicate their findings back to the user. This could also happen periodicity so that a continuously monitoring function can be achieved. The user may also choice to manually control the ROV for precise missions, this is the current focus of the project.



At the base of the project lies the Aruna C++ library. This library is build of multiple modules. The goal of these modules is to be written portable so that they may run on any platform. Beneath the modules are drivers-interfaces. These are abstract classes that divine the behaviour of the platform specific drivers. These are platform specific and need to be rewritten for every platform. Aruna currently has full support for ESP32 (using ESP-IDF 3.2.2), there is partially support for Linux. And lastly, planned support for...

Read more »

  • 1 × ESP-32D S should also work but why bother
  • 1 × RS485→ UART breakdown board for communication from ESP to computer
  • 1 × RS485→USB for communication from computer to ESP
  • 1 × 10 meter long cable with 2 wires for RS485 Ethernet cable works fine
  • 1 × 3D printer w/ filament of your favourite colour

View all 16 components

  • ​New Thruster layout, BLDC driver rabbit hole and Embedded Linux​

    Noeël Moeskops04/13/2021 at 19:02 0 comments

    New thruster layout design

    The current thruster design of the ROV is quite agile with the 6 motors the submersible is able to move in 5 dimensions. With the front (1 and 2) en back (3 and 4) motors being able to use to go in 3 dimensions (X axis, Y axis and yaw). While the middle motors (5 and 6) can only make to ROV move in two dimensions (Z axis and roll). Still one dimension is lacking. With the current layout the ROV is unable to move in the pitch axis. This is not necessarily a huge problem as it is not required to move around but still would be nice to move in that axis.

    Old 6 motor design on the left. On the right new screw design with 8 motors

    By adding two additional thrusters, and chancing to total layout the ROV can now move in all 6 dimensions. And it can do so with all 8 motors! Because all thrusters are located at a double 45-degree angle they are effective in all dimensions. They either need to move backwards of forwards. Four motors (A-D) are located at one end of the tube in a screw motion while at the other end the motors (E-H) are rotated in the opposite direction. This prevents the ROV from spinning around its own axis when all motors are active. The only downside to this design however is the cost in part and the power requirements. But regardless I think it is a worth it to build and try it out.

    New thruster layout attached to the new cap top and bottom view

    As can be seen from the pictures I constructed half of the new design. The motors are now intergraded into the end cap with SP13 connectors. But more on that in the next section.

    New thruster layout attached to the new cap with the rest of the internals connected also


    Another thing that really annoyed me was the cap of the ROV. The wires going inward where kitted to a strain relief and the solution was not very nice. The cap contacts the PVC pipe on side via two O-rings. This was not really a nice seal because there was no active force pushing the two together. It could in theory come loose mid-dive (what I was always really afraid of).

    Old cap design, note the two O-rings and the wires kitted to make a water tight seal

    The new cap is designed to be forcefully pushed to the PVC pipe by four m4 threads that are connected to the cap at the other side. Between the cap and the PVC pipe is a rubber O-ring to make a tight seal. The cap also houses support for IP68 SP13 connectors which replaces the hacked kitted strain relief. And are much nicer all together because they can be reattached easily. The new cap is also integrated into the internals of the ROV. Where before they were two separate parts. Now the cap can be screwed into the other internal component by four m4 threads also.

    New cap design with holes for SP13 connectors and intergraded connection for the thruster

    BLDC motor controller

    Apsu is currently driven by four SimonK motor controllers and four BLHeli controllers. The SimonK drive the motors in the front and back while the BLHeli provide control to the motors for upward and downwards motion. The SimonK controllers were chosen because at the time I did not know the existence of BLHeli. Now when I have had some experience with BLHeli I'm not liking that either. There is very little documentation available and the firmware (properly with good reasons) is written in assembly, so really hard to read. When I implemented Dshot in my project I remembered it being a big puzzle of figuring out how to protocol actually worked. And I had to put together multiple blog posts from various websites before I got a clear image of how to protocol worked and how to interface with it.

    Now that I need more motors and thus more motor controllers I don’t really want to go back to BLHeli, not just because of the lag of documentation but also because the pins on my microcontroller are all in use and I don’t have room for a separate pin for each motor if I’m running eight simultaneously. I would also really like to get data like RPM of the...

    Read more »

  • Software Progress and workflow

    Noeël Moeskops01/20/2021 at 17:28 2 comments

    It has been a while since my last log, this was not entirely intentional as I was hard at work refactoring the Aruna library with the architecture described in my previous post. And I thought posting updates on the software would be boring. Therefore, I was planning to post an update after the refactoring was done. But this took way longer than expected. Well that time has finally come, the refactoring of all the lower layers is as good as done. Just a few tweaks left (like a missing IO abstraction and one module still in FreeRTOS), but those can be kinked out later.


    The abstraction layers of Aruna are now looking really nice. When adding a new driver, sensor of actuator you only need to focus on the part that makes it different from other drivers or sensors and can easily inherit existing logic. Lets for example look at the `Rain40x16` sensor driver, this is a sensor that is normally used to measure rainfall in a 40 mm by 16 mm grid, but I use it measure leaks in the ROV.

    Rain sensor (Rain40x16)

    The driver for this sensor is used as a `SIS::Performer`, SIS stands for Safety instrumented system and is used to keep a system (the ROV) safe. A SIS::Performer in Aruna performs safety checks, so that other SIS modules like the SIS::Watcher (bad name) and SIS::Reporter can report the problem to the user, so they can take action. I am also planning to add an automated response (SIS::Response ?) so that the ROV will try to get itself back to a safe state if compromised.

    Collaboration diagram for aruna::sensor::Rain40x16

    It is of course out of the scope of the rain sensor driver to know anything about SIS, moreover do actions based on the water level. The water level report should be the same for all water sensors, be it a rain sensor as described above or a humidity sensor. The driver should only focus on the part that makes them unique, which in this case is the way of measuring water. The Rain40x16 driver therefore inherits `sensor::Water` to create a standardized interface for water sensors. `sensor::Water` in their turn inherits `SIS::Performer` (can also be used for other task than SIS) and handles all the reporting logic for ROV safety. What also can be seen in this diagram is the use of `driver::ADC`. This is also (like `sensor::Water`) a standardized interface for analogue digital converts.

    The great thing about this architecture is that the Rain40x16 driver is hardware dependent (it needs a specific sensor) but is also cross-platform because it does not handle any device specific things itself. But instead relies on the `driver::ADC` that can be implemented for any platform.

    // Created by noeel on 22-12-20.
    #include <math.h>
    #include "aruna/sensor/Rain40x16.h"
    aruna::sensor::Rain40x16::Rain40x16(aruna::driver::ADC *adc): adc(adc) {
    aruna::err_t aruna::sensor::Rain40x16::get_water_level(uint16_t &water_level_in_mm) {
        int16_t mV;
        err_t e;
        e = adc->read_voltage(mV);
        water_level_in_mm = voltage_to_mm(mV);
        return e;
    int16_t aruna::sensor::Rain40x16::voltage_to_mm(uint16_t mV) {
    //    TODO vcc etc as parameters
        const int16_t sensor_length_mm = 40;
        const int16_t max_voltage_when_dry = 20;
        const int16_t voltage_at_min = 1000;
        const int16_t voltage_at_max = 3300;
        const int16_t voltage_diff = voltage_at_max - voltage_at_min;
        if (mV < max_voltage_when_dry)
            return 0;
        if (mV < voltage_at_min) {
    //        voltage is in grey space.
            return 1;
    //    TODO this conversion is linear while in real-life it is not
        return ceilf(((float) mV - (float) voltage_at_min) * ((float) sensor_length_mm / (float) voltage_diff));

    Above is all the code in `Rain40x16.cpp`. The only function it needs to override is `get_water_level(uint16_t &water_level_in_mm)` from `sensor::Water`

    The refactoring and redesign of Aruna has so far caused: 78 files changed, 3154 insertions and 2218 deletions. (17 Oct 2020 - 4 Jan 2021). With refactoring of the top layer and documentation of all the modules is still...

    Read more »

  • Refactoring Aruna lib

    Noeël Moeskops10/26/2020 at 13:50 0 comments

    Before adding new features and drivers to the Aruna library I thought it would be wise to do some household and refactor the library a bit. The current architecture consist of 2 layers. One for logic and the other for hardware interfacing.

    Old architecture. In the image the control module can be seen that is used for moving the ROV. It used the virtual Actuator class.

    In the image above contains the architecture for the control module. All the PCA9685 specific code rests inside the PCA9685 class that is inherited from Actuator.

    A rather simple approach that worked fine in the beginning. But as more and more features get added it becomes repetitive. There are two main problems with this architecture:

    • PCA9685 is forced to always be an Actuator, if this same chip is be used for PWM of a LED for example it would result in poor code.
    • PCA9685 class needs to be rewritten for every platform I²C driver, despite the PCA9685 driver logic staying the same.

    To mitigate these problems extra abstraction layers are added between the Actuator and the I²C code resulting in 4 layers:

    1. Control logic
    2. PWM Actuator
    3. PCA9685 driver
    4. I²C driver
    New four layered architecture. Separating the PCA9685 driver from hardware or software specific code.

    With the addition of the high level driver layer the PCA9685 driver is now free from hardware specific I²C code because that now rests in the I2C_master implementation. Instead of being hardcoded to an Actuator object the PCA driver is now a PWM object and free to be implemented in any module being an Actuator as shown above or an LED or what not.

    A new implementation of PWM (for example the ESP32 native PWM) can easily replace the PCA driver and the layers above would function as if nothing happened. Also porting to a new platform is easier as only the I2C_master class has to be written, all the other code is portable (given an POSIX OS).

    I have not yet written the PWM_Actuator code but while making this graph I thought to maybe let PWM inherit Actuator. That makes things easier when using the code, and we are not limited to one parent because C++ supports multiple inherits. So any module abstraction can be added later when needed. But it might make PWM bloated, not sure yet what to do. Atlas I'm first going to focus on more refactoring because although the architecture is now much more flexible this is not yet the case for the other modules (comm and blinky). And some internal structures like `direction_t` for given direction feel redundant because I much rather make use of a singed integer.

    I have also been looking into ROS 2,  I might make an Aruna ROS package. But that's all in the far future. Nevertheless, I really like their pub/sub model and I might implement something similar for the comm module. I also think that using a simulator could really benefit the development of the project. But I'm indecisive about Gazebo or Webots. Unit tests and better code quality will be worked on first though.

  • Future roadmap

    Noeël Moeskops10/04/2020 at 19:50 0 comments

    With the Hackaday 2020 prize drawing to an end (and with my submission video uploaded) I thought it might be a good idea to talk about what I'm planning to do next for the Aruna project. Please note that these are ideas of mine and might not be implemented in the order written down or even ever.

    Short term (working on this right now)

    • Write drivers for all components on the PCB.
    • Write unit tests for all functions of the Aruna library
    • Refactor Aruna library to be more consistent
    • Refactor all FreeRTOS from Aruna library to 100% Posix.
    • ROV visualization with Inar (the control module at the surface)
    • Xbox controller support for controlling the ROV

    Long term (going to work on this probably next)

    • Water quality sensor (for plastic levels etc.)
    • Integrate the "dop" into the core
    • Make a detachable cable plug
    • Write a Dshot driver for the PCA9685, buy 4 more BLHeli controllers and get rid of the SimonK.
    • Add two more motors to the design to create a 6DOF model
    • Create a ballast tank
    • Design a more space efficient Apsu board V2
    • Make an automatic fail-safe, so that when the ROV crashes it can return to the surface anyway.
    • Redesign the "universeel houder" because it required an odd position for screwing.

    Hope and dreams (Far future)

    • Sonar
    • Camera
    • Robot arm (for scooping soil)
    • More efficient (maybe bigger) rotor blades
    • Subsistent for BLDC, because these rust.
    • Low frequency radio communication with the ROV (~27MHz)
    • Implement an Aruna ROV for the STM32 and embedded Linux
    • AUV (Autonomous underwater vehicle)
    • Cross the IJsselmeer (the biggest Dutch lake)
    • Create an underwater glider

  • Diving into the canals

    Noeël Moeskops10/01/2020 at 11:06 0 comments

    Now with the core of the ROV assembled it was time to test in uncontrolled waters: the Dutch canals. After fully assembly the ROV; turning it on and testing it. It turned out that a 18650 battery cell was broken. The total battery pack measured 7.4V, yikes. Lucky I had a spare cell, so after a day of charging (I had to do a lot of swapping since all the cells had different voltages) the battery pack was full at 12.4V :).

    Charging 18650 cells using a charger

    Doing the dive into uncontrolled waters was exiting as it was the first time outside the bathtub. The previous bathtub test was in May and a lot has changed since then. I really didn't want my PCB to get soaked. While diving, I noticed that the balance was a bit off and that it was back heavy. In the next iteration I want to make a more adjustable weight system, instead of having two pieces of lead taped to the PVC pipe. I might also add a fin for stabilization.

    ROV in the canal, will upload a video shortly

    After diving with the ROV for a while the fuse broke on the power board broke. I found this rather odd because the fuse is rated at 5A. And when I did a stress test (four motors full throttle) on the motors they came at 3A max. After inserting a 6.5A fuse it broke almost immediately. I couldn't detect any shortages and the system worked (on land) with a small fuse (1A, two motors) at half throttle. The water could add an extra resistance for the motors so that they require more power, more testing is required.

    Broken fuse

    I'm busy with the video for the Hackaday prize featuring the dive described in this log, so keep an eye out for that.

  • Shortage and assembly

    Noeël Moeskops09/26/2020 at 12:28 0 comments

    After finishing writing the driver and confirming that it was working with my logic analyser I connected my SimonK ESC. Unfortunately The ESC weren’t armed by the PCA PWM signal. I tried changing the frequency of the PWM from 200Hz to 50Hz. But no dice, after that my FT2232H JTAG debugger could no longer connect to my ESP. It kept saying “could not halt device: not initialized” (or something similar, I’m typing this from memory). It turned out however that there was a short between my ground and power (~20 Ohms). But I did not know where. I first assumed it was the PCA9685 since it was directly connected to an external chip and had experienced mayor re-routing.

    Left to right: ESP-32 dev board, new ESP32, shorted ESP32. All with different markings

    After desoldering the PCA9685 the short was still present. I removed the ESP and that mitigated the issue. Luckily I had a spare ESP-32 chip however, I messed up the SPI-SS0 pin. So SPI communication will be a little difficult. But that will be an issue for later.

    After measuring the PCA it turned out to be fine. So I tried to reinstall the PCA chip with all its tiny rerouting. This however did not succeed and I ended up destroying three more coper pads.

    PCA9685 resolder attempt. Left shows top-down of the IC, middle side view and right picture with the IC removed

    Since the PCA was beyond repair this time I opted for my second option discussed in previous log; to buy an PCA9685 breakout board. While connecting this to the Apsu board I was afraid that the shortage that happened earlier would strike again. I’m still uncertain why the ESP chip failed earlier. So I measured the PWM signals coming out of the SimonK ESC’s. And they all measured ~5V. This is possibly because they are pulled-up and should not pose a problem since the PCA9685 supports 5V logic levels (while it's still driven by 3.3V). After connecting everything together I was finally greeted with a spinning motor :).

    To enable the PCA9685 breakout board to fit into the tube of the ROV I created a holder for it. It looks very similar to the water holder breakout board I created earlier.

    With everything working now the next step is to put everything together so it will fit into the tube again. Curiously the total size of the assembled core (I am going to call the electronics inside the tube core from now on in lag of a better word) is 3 cm larger than previously! I hypothesized that it would be smaller. But because of the extra space the XT60 cable takes around 4 cm is lost (notice the space between the power and the PCA9685 board). This is something I will have to reconsider in the next PCB design, because the PCB’s itself are very space aware the connections however, are not. I’m planning to put smaller side facing connections on the next iteration.

    Left to right: Battery, BMU, Apsu board, power board, PCA9685 board, BLHeli, 4x SimonK, water sensor

  • PCA9685 driver​

    Noeël Moeskops09/21/2020 at 09:17 0 comments


    After looking at the data sheet for the registers it turned out that the device is pretty simple. At startup the IC is in low power mode, after setting it to normal operation mode the PWM of each pin can be set.

    Some registers from the PCA9685 data sheet

    The register MODE1 contains settings to restart the IC, use external clock, power mode and set broadcast mode. MODE2 is less significant and contain some specific settings for I²C communication and PWM configuration, like putting the output pins to open-drain or totem pole(?). On address 0x6 the PWM output starts. (called LED because this IC is designed for driver LEDs, motors will also work fine).
    So when writing to register 0x6 the PWM can be set by first specifying the time when the PWM needs to be turned on (0-2048, because register *_L and *_H are together 12bits) and then the time when the PWM needs to be turned off. The time is specified between one clock cycle. The clock of the outputs needs to be set separately and is the same for all the outputs.


    Since PWM is such a common peripheral I created an abstract driver in the `aruna::driver::PCA9865` namespace.

    // include/aruna/control/PCA9685.h
     * Set the PWM of an output of the PCA9685
     * @param led, 0-15 output to adjust
     * @param on, 12bit time to turn on
     * @param off, 12bit time to turn off
     * @param address, I²C address of device, default 0b1000000
     * @return
    err_t set_pwm(uint8_t led, uint16_t on, uint16_t off, uint8_t address = default_address);

    This is currently the only function that I wrote yet, very minimal. I want to create a working model as quickly as possible. Its actually only a header. Its Upton each platform to write an implementation for it. The ESP-32 implementation is found at `./src/driver/PCA9685/portable/ESP32/PCA9685_ESP32.cpp`.

    To enable this driver to work seamlessly in place of my previous PWM driver (that uses the GPIO pins on the ESP) I had to create a wrapper of sorts for the `Control::Actuator` class. `Control::Actuator` Is a virtual class so that the control module have a common interface to control actuators on the ROV. Multiple actuators of different natures can be used at the same time.

    // include/aruna/control/Actuator.h
     * Set the speed of the motors directly
     * @param axisMask, multiple axis to apply speed to.
     * @param speed, speed of the motors
     * @param direction, direction to go to.
     * @return err_t::OK if the command was succesfull, others when it fails.
    virtual err_t set(axis_mask_t axisMask, uint16_t speed, direction_t direction) = 0;

    The `set(...)` function is the only required function of an `control::Actuator` class driver implementation. `axis_mask_t` specifies the axis that needed to be driven (X, Y, Z, Roll, Pitch and Yaw). If a given driver can't perform a given axis transformation it wil just return.

    This layered driver structure allows me to quickly switch between hardware.

    // include/aruna/control/PCA9685.h
     * PCA9685 I²C PWM driver
     * @param axis: supported axis masks
     * @param direction: supported directions
     * @param led: PCA9685 LED output number (0-15)
     * @param i2c_address: address of the PCA (default 0b1000000)
     * @param min_duty_cycle_percentage: minimal duty on percentage (default 0)
     * @param max_duty_cycle_percentage: maxumal duty on percentage (default 100)
    PCA9685(axis_mask_t axis, direction_t direction, uint8_t led, uint8_t i2c_address, float min_duty_cycle_percentage = 0, float max_duty_cycle_percentage = 100); 

     Above shows the constructor for the PCA9685 `Control::Actuator` driver. As required by the parent class it needs to be supplied with an axis mask and direction. Other parameters are specific for the PCA9685. Although I took a peek at the ESP32 native PWM driver that I have written earlier and copied `min/max_duty_cycle_percentage`. This is needed for the SimonK driver as it operated within 5-10% of the PWM signal.

    Each actuator needs to be registered by the...

    Read more »

  • Getting the PCA9685 to work

    Noeël Moeskops09/12/2020 at 23:16 0 comments

    In the PCB tests log I talked about having the wrong layout for the PCA9685 IC (I used the TTSOP28 pinout with the HVQFN28 package). In order to solve this I considered four options:

    • Cross wire and cutting traces to connect the correct pin.
    • Buy external PCA chip
    • Design breakdown board for the PCA.
    • Designing Apsu PCB V2

    I kinda wanted to have PWM control as fast a possible because its such a vital part of the ROV. So I opted for the first option of cross wiring the IC, because it could be done within one day (or, so I thought).

    Of the total 28 pins of the PCA chip only 9 vital (+4 non vital) pins needed to be rerouted:

    pin nr.
    22led15ext clock
    23 ~OE
    I²C SCL
    24A5I²C SDA
    25ext clock
    26I²C SCLA0
    27I²C SDAA1
    Left: VCC (pin 25) copper pad destroyed. Right: finished resoldering

    Soldering wires on the tiny connections was a frustrating task. The pad of pin 25 (middle pin in the left picture) was even broke due to extensive heat. And I also broke a solder tip (don't ask how). Luckily I managed to solder directly to the IC and connected pin 25, 26 and 27 to VCC. As can be seen on the right picture.

    Finished rewirering. Now I finally understand why sci-fi films have wires sticking out of their PCB's!

    While cutting the traces I however, also cut the I²C-SCL trace. I didn't notice it at first and thought that I blew up the IO pin on my ESP somehow. So I needed an extra wire going from I²C-SCL directly to the ESP (top wire on the picture). After the complete rewiring the PCA now has the address `0b1100111`. And the Adafruit PWM library finally was working properly.

    Four PWM signals after successful I²C communication
    The back of the PCB is really getting seasoned, but I'm very glad the chip is working now. Now I'm off to write a driver.

  • testing INA219 & MAX6682

    Noeël Moeskops09/10/2020 at 12:14 0 comments


    The INA219 is positioned on the power board to monitor the voltage and current of the 12V battery pack, communication goes over I²C. I used an Arduino sketch to test this sensor and it all worked the first try.

    Multimeter left showing voltage (10.65 V) and multimeter on the right showing current (3.02 mA)
    To monitor the correctness of the measured data I placed two multimeters in the circuit to measure the voltage and current. The left multimeter measured the voltage at 10.65 V. This is only a difference of 0.03 V between the control and the INA219 chip. The right multimeter measured a current flow of 3.02 mA. The INA measured a current of 5.40 mA, this is quite a big difference. But it is consistence with the difference of the voltage measurement: 0.03 V and ~0.02 A. The current is now ridiculously low because the components are also being powered by the debugger. When the debugger is disconnected the current rises on the multimeter. Because the UART of the FT2232H board I use also supplies power to the board is it difficult to get an accurate measurement. Later, when I write a driver for it, I can communicate the current over RS485 this problem would me mitigated and some proper testing with motors in place could be done. But so far it looks functional.
    Bus Voltage:   10.62 V
    Shunt Voltage: 0.54 mV
    Load Voltage:  10.62 V
    Current:       5.40 mA
    Power:         59.00 mW

    Serial output of the example code above.


    The MAX chip converts thermistor temperature to digital data over SPI. This comes in handy for my external thermistor (YC100665). The chip takes care of self heating and power-supply noise and supplies a read-only 10bit SPI signal, very straight forward.

    After reading the SPI documentation of the ESP-IDF it turned out that my assumption of "ESP-32 supports every hardware operation on every IO port" was incorrect. It turns out that there are two SPI IO sets for the ESP: HSPI and VSPI. HSPI is already in use by JTAG so only VSPI is left for mortals. Not using the VPSI pins is possible but at lower speeds and more delay. So not a total loss I though, until I found out that I was using an input only pin for the MOSI :( (also for one BLHeli Dshot output pin, but that was redundant anyway).  I changed the MOSI pin to IO2, since that was the only pin left, so I could at least still test the chip.

    The Slave Select pin of the MAX6682 is connected to an output of an MC74HC138A demultiplexer. This allows for up to eight devices on the SPI bus by using SS0-2 pins for chip selection. My luck turned here and I could successfully read the MAX6682 via SPI (no thermistor attached).

    Looking at the logic analyser the data does not seem to make a lot of sense. At least the MAX6682 is outputting data on the MISO line. More testing with the sensor attached needs to be done. But I'll leave that for later since I want to focus on more essential things first.

  • Documentation and license

    Noeël Moeskops08/28/2020 at 12:42 0 comments

    Documentation of the Aruna library is now hosted on The documentation gets automatically updated after every push! They unfortunately don't support call graphs, so you will have to generate the documentation locally if you want to easily see how everything gets called. I might reupload the documentation somewhere else at some point that does support `dot`.

    Locally build documentation with call graph

    I also added the GNU GPLv3 license for all the repositories in the project.

View all 14 project logs

  • 1

    The goal of Aruna is to create a platform for ROV development, kinda like what ROS (Robot operating System) is for robots or Ardupilot¹ is for drones. Aruna is however not a framework, it is only meant as C++ library to aid in the software development. You are free to implement it however you want. And how much you wish to integrate it into your project.

    The Aruna project is however not limited to just software. It has also an arsenal of CAD object to be used (or modified) for the mechanical part of the ROV. As it has some electronic PCB design for the implementation of Aruna. All of this can be altered by the user so you can create your own unique ROV (or AUV (Autonomous underwater vehicle) with additional software). It is therefore difficult to create an instruction set as I encourage you to design and create your own. The steps in this instruction will thus assume you want to create an MVP (minimal viable product) Aruna ROV similar to the Apsu implementation (Cylinder ROV powered by ESP32 as seen in picture) that I build. But without the PCB design (as it's expensive and not yet ready). Please deviate and use your own creativity wherever you see fit.

    ¹ I have no experience with Ardupilot.

  • 2
    Necessary parts
    1. ESP-32D (S should also work but why bother)
    2. RS485→ UART breakdown board (for communication from ESP to computer)
    3. RS485→USB (for communication from computer to ESP)
    4. 10 meter long cable with 2 wires for RS485 (Ethernet cable works fine)
    5. 3D printer w/ filament of your favourite colour
    6. 6xA2212 930kV BLDC motor
    7. 3x6x 400-100 mm wires (for connecting the BLDC motor to ESC)
    8. 6x BLHeli ESC
    9. 80mmx400 mm PVC pipe
    10. 2+4x rubber ring (for closing up the cap of the PCV pipe)
    11. 4x6x M4 screws and bolds
    12. 12V power source for ESC, motors (9x18650 battery cell recommended)
    13. Battery management unit (optional)
    14. 3.3V power source for internal logic; ESP (buck converter from 12V power source recommended)
    15. 5x 10 mm strain relief (for every outbound cable)
    16. FT2232H like the ESP-PROG for programming (Optionally but highly recommended)
  • 3
    Create development environment
    1. Install ESP-IDF v3.2.x (v4.x might work as well, not tested though)
    2. install cmake
    3. install openocd-esp32
    4. clone Apsu in your git directory
      1. `cd my_git_dir`
      2. git clone --recursive
        1. don’t forget recursively as it needs to clone the Aruna library as well
        2. run `git submodule init` if you forgot –recursive (in the Apsu directory)
    5. build the project
      1. `cd Apsu`
      2. `cmake . -B build`
      3. `cd build`
      4. `make -j6` (change 6 to the number of physical cpu’s on your PC)
      5. You should now have three binaries.
        1. build/Apsu.bin containg the main application
        2. build/bootloader/bootloader.bin containing the bootloader
        3. build/parition_table/partition-table.bin contains the partition table of the image
      6. An IDE with cmake (like Clion) does this process automatically at a press of a button, but since all IDEs are different it is not covered in this instruction.
    6. Flash project on target
      1. with the FT2232H connected to the JTAG of the ESP and to the USB of your computer run: (adjust path accordingly)
        1. install bootloader `~/./esp/openocd-esp32/bin/openocd -s ~/esp/openocd-esp32/share/openocd/scripts -f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp-wroom-32.cfg -c "halt reset ;program_esp build/bootloader/bootloader.bin 0x1000 verify reset exit`
        2. install partition table `~/./esp/openocd-esp32/bin/openocd -s ~/esp/openocd-esp32/share/openocd/scripts -f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp-wroom-32.cfg -c "halt reset ;program_esp build/parition_table/partition-table.bin 0x8000 verify reset exit`
        3. install main application `~/./esp/openocd-esp32/bin/openocd -s ~/esp/openocd-esp32/share/openocd/scripts -f interface/ftdi/esp32_devkitj_v1.cfg -f board/esp-wroom-32.cfg -c "halt reset ;program_esp build/Apsu.bin 0x10000 verify reset exit`

View all 6 instructions

Enjoy this project?



Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates