Category: Project

  • ESP-Now Remote Control Test

    ESP-Now Remote Control Test

    To control a robot, I wanted to see if ESP-NOW, a communication method developed explicitly for the ESP family, would work. This project aims to determine whether ESP-NOW provides a reliable connection over a reasonable distance and whether ESP-NOW can send sufficient data back and forth.
    ESP-NOW makes it possible to set up different types of communication:

    • One-way communication
    • One master and multiple slaves
    • One slave and multiple masters
    • Two-way communication
    • Multiple-way communication (a network of ESP boards)

    In my example, I use the two-way communication protocol to build a remote control that can operate a robot. The robot must also send data back. If you want to read more about the possibilities and background of ESP-NOW, check out this excellent source of information:
    https://randomnerdtutorials.com/esp-now-esp32-arduino-ide/

    Setup

    My first test setup consists of the following components:

    Board 1

    • Joystick (Sends signal)
    • Prints the distance from the distance sensor via Serial

    Board 2

    • Servo (Uses X position from the joystick)
    • HC-SR04 distance sensor mounted on the servo
    • Prints the distance from the distance sensor via Serial

    The joystick on the master board controls the servo on the slave board. The distance sensor rotates along with the servo, and the measured distance is sent back to the master board. The setup is simple, and it gives a first impression of the speed and reliability of the ESP-NOW connection.

    BOM (Bill of Materials)

    In this project, I used:

    • DOIT ESP32 DEVKIT V1
    • ESP32S 38P/V4/Goouuu Expansion board
    • ESP32/V4/Goouuu Terminal Adapter Expansion board
    • Dual-axis XY Joystick Module
    • Tower Pro Micro Servo SG90
    • HC-SR04 Distance sensor
    • Level Converter board
    • Jumpwires
    • 3D printed parts (Optional)

    Of course, you can use different components if you want — no problem at all.

    Preparation

    To use ESP-NOW, you need to know the MAC addresses of the ESP boards. It is essential to send data to the correct board. You can find this easily by uploading the following code and reading the MAC address via the Serial Monitor in the Arduino IDE:

    #include "WiFi.h"
    
    void setup(){
      Serial.begin(115200);
      WiFi.mode(WIFI_MODE_STA);
      Serial.println(WiFi.macAddress());
    }
    
    void loop(){
    }

    Once uploaded, open the Serial Monitor and press the reset button on the DOIT board, and the MAC address will appear.

    Build

    Once we know the MAC addresses, we can start building the setup. I’m using parts from Evenblox to keep everything neatly together and make it easier to transport. You can find these parts and more information on https://www.evenblox.com. Also, check out this great 3D model for mounting your sensor: HCSR04 mount for SG90 servo by rjlew – Thingiverse

    Below you’ll find the schematic of board one (Master) and a photo of the breadboard setup:

    Next is the schematic of board 2 (Slave) and a photo of its setup:

    I’m using the HC-SR04 sensor to measure distance. I’ve written an article about this before — check it out here: HC-SR04 Project – SwanRobotics.

    The servo and the HC-SR04 both run on 5V. The ESP32 operates at 3.3V, so a level converter is needed. There are HC-SR04 versions that support both 3.3V and 5V, but the one used in this project does not. For more information about level converters, check out Level Converter – SwanRobotics.

    Alternatively, you could use the HC-SR04P sensor, which supports both 3.3V and 5V directly.

    Code

    The code is available on GitHub. Remote_control_test_ESP-NOW

    You’ll need to update the MAC addresses in the code to make it work for your setup. The code handles several tasks:

    The remote sends a heartbeat every 200 ms. A heartbeat is essential when the system controls an actual robot. The robot checks for incoming data. If no data comes in, the servo returns to its middle position.
    The joystick value is sent to the robot, which reads it and converts it to a servo position.
    The sensor measures the distance and sends it back to the remote.
    The data from both ESP boards can be monitored via the Serial Monitor in the Arduino IDE, making it easy to test the connection in different locations.

    Once the code is uploaded, it should be possible to view the correct data.

    What’s Next

    This setup works well, and the ESP boards pass data smoothly. I want to test how far the boards can communicate in different environments (home, street, forest), so I’ll add a display to the remote control to show the connection status. That way, I can see when the signal is lost. The joystick is sensitive near the center position, so I plan to smooth that out in software.

  • Levelconverter

    Levelconverter

    In my last article, I wrote about using an MD04 motor driver for my motors. In the example, I used an Arduino Uno to test the motor drivers and made the code work. I want to use the Teensy 4.1 in my robot because of the board’s multiple serial connections and its higher speed. The Teensy runs on 3.3 Volt instead of the 5V Arduino uses. I could not find the voltage level for the I2C wiring in the documentation. According to the manual, the serial communication and the analog input use 5V, so I assume the SCL and SDA are the same.

    To overcome the voltage differences, I used a level converter. A level converter is a small board with a low and a high-level side. A MOSFET and other components on this board compensate for the voltage difference between the two sides. Connect the low-level side (LV) to the Teensy and the high-level side (HV) to the MD03. The image below shows how I wired the Teensy, the motor driver, and the level converter.

    I used a USB breakout board to provide the 5 volts to the high side of the level converter. The low side of the level converter gets its power from the Teensy. I used two pull-up resistors on both sides of the level converter (10K). Technical, the connections remained the same. We used the standard I2C pins, so the software stayed the same. You can use the code example from the previous article.

    Supplies

    Level Converter
    Buy at AliExpress
    Buy at Amazon
    Make sure you get the Bi-Directional version to use it with I2C.

  • MD04 motor drivers

    MD04 motor drivers

    The first thing to do for my A1 robot is to control the motors. I wanted to use MD03 motor drivers from Devantech. I had used them before on the same robot. You cannot buy them anymore because Devantech has a newer motor driver available. I had it all working fine, but then I made a mistake. A 24V power lead connected the 5V circuit because I forgot to disconnect the battery connector when changing the configuration. I had to buy two new MD04 drivers. Ouch. I got mine from www.robotshop.com.

    MD04

    These drivers look the same, but the power of the control circuit comes from the motor circuit. Powering the board this way is a disadvantage because, with the MD03 configuration, I routed the power wires through the emergency stop. Cutting the power stops the motors immediately. I can’t do the same thing with the power of the drive side because the switch can not handle the current flowing through.

    In my design, I want to control the MD04 motor drivers through I2C. It’s easier to use PWM, but by using I2C, I can read data from the MD04. The data I want to use is the current flowing through the motor and the temperature of the driver. If the current is too high, we can determine if the motor is struggling or stalling. You can also get the version of the software of the MD04 motor driver. To set up an I2C connection, you need to configure the MD04 with the software from Deventac en set the communication to I2C. A useful source about the I2C bus is: I2C Bus (i2c-bus.org) 

    Connect to an Arduino

    My robot has two MD04 drivers, and with I2C, we can control them both with two pins. To make this work, I connected the boards with USB to my computer and configured the boards with the software from Devantech. MD04 (robot-electronics.co.uk) It’s a simple program, and you can select the address for the motor drivers. 

    The MD04 only uses three wires. P1 is the SCL, P2 is the SDA, and a GND wire is needed. On the Arduino Uno, the SCL is GPIO19 and SDA is GPIO18. I2C also needs two pull-up resistors (I used 4.7k) on the lines to prevent data loss. The rest of the schematic is reasonably straightforward. Internally on the MD04 board, the ground is connected. Connecting the ground poles from the 24V and 5V sources is not desirable to prevent ground loops.

    Arduino Code

    For the program, I started with the example: Arduino Examples (robot-electronics.co.uk) This example also used a display; I only needed the part to control the motors, so I changed the code example from James Henderson to a simpler version. The purpose is to make a loop of spinning a motor to half the speed and slowing down to a halt. At the same time, the code needs to read the information from the MD04 and send them to the serial connection. The code below is also available at GitHub: https://github.com/SwanRobotics/arduino-md04

    /*
     * From www.swanrobotics.com
     * 
     * Code example for an MD04 motor driver from Robot Electronics for Arduino
     * https://www.robot-electronics.co.uk/md04.html
     * 
     * In a loop, the code spins up the motor to maximum speed and slows it down to a hold.
     * Then change the direction and goes to maximum speed, and hold again.
     * It uses the I2C protocol from the Wire library.
     * 
     * To connect the MD04 motor driver, for example, an Arduino Uno with the following connections:
     *  MD04      Arduino Uno
     *  P1    <=> D19 (SCL)
     *  P2    <=> D18 (SDA) 
     *  G     <=> GND
     * 
     * The original code by:
     * James Henderson 2012
     * https://www.robot-electronics.co.uk/htm/arduino_examples.htm#MD03%2050V%2020A%20Motor%20Driver
     */
    
    #include <Wire.h>
    
    #define ADDRESS             0x58                    // Address of MD03
    #define SOFTREG             0x07                    // Byte to read software
    #define CMDBYTE             0x00                    // Command byte
    #define SPEEDBYTE           0x02                    // Byte to write to speed register
    #define TEMPREG             0x04                    // Byte to read temperature
    #define CURRENTREG          0x05                    // Byte to read motor current
    
    byte direct = 1;                                    // Stores what direction the motor should run in
    
    void setup(){
      Serial.begin(19200);                              // Start Serial connection
      delay(100);
      
      Wire.begin();                                     // Start I2C connection
      delay(100);
      
      Serial.print("Software version MD04: ");          // Print Software version from MD04
      Serial.println(getData(SOFTREG));
    }
    
    void loop(){
      for(int i = 0; i < 250; i=i+10){
        sendData(SPEEDBYTE, i);             // Sets speed to i
        sendData(CMDBYTE, direct);          // Sets motor to direct, a value of 1 runs the motor forward and 2 runs backward
        showData(direct,i);                 // Call function to print data to Serial
        delay(100);                         // Wait 0,1 second to send the next speed value
      }
      delay(100);
      for(int i = 250; i > 10; i=i-10){
        sendData(SPEEDBYTE, i);             // Sets speed to i
        sendData(CMDBYTE, direct);          // Sets motor to direct, a value of 1 runs the motor forward and 2 runs backward
        showData(direct,i);                 // Call function to print data to Serial
        delay(100);                         // Wait 0,1 second to send the next speed value
      }
      if(direct == 1)                       // If loop that swaps value of direct between 1 and 2 each time through loop
        direct = 2;                        
      else
        direct = 1;                     
    }
    
    void showData(byte valdirection, byte valSpeed) {
        Serial.print("Direction: ");
        Serial.print(valdirection);         // Prints current direction (1 or 2)
        Serial.print(" - Speed: ");
        Serial.print(valSpeed);             // Prints current Speed (0-250) tot Serial
       
        byte current = getData(CURRENTREG); // Get current value (186 = 20 Amp) to Serial
        delay(10);
        Serial.print(" - Current: ");       
        Serial.print(current);              
        
        byte temp = getData(TEMPREG);       // Get surface temperature of the PCB in degrees centigrade.
        delay(10);
        Serial.print(" - Temperature: ");
        Serial.print(temp);                
        
        Serial.println(".");                // Point at the end of the line and an Enter
    }
    
    byte getData(byte reg){                 // function for getting data from MD03
      Wire.beginTransmission(ADDRESS);
      Wire.write(reg);
      Wire.endTransmission();
      
      Wire.requestFrom(ADDRESS, 1);         // Requests byte from MD03
      while(Wire.available() < 1);          // Waits for byte to become available
      byte data = Wire.read();
    
      return(data);
    }
    
    void sendData(byte reg, byte val){      // Function for sending data to MD03
      Wire.beginTransmission(ADDRESS);      // Send data to MD03
        Wire.write(reg);                    // Command like Direction, Speed
        Wire.write(val);                    // Value for the command
      Wire.endTransmission();
    }

    Adresses?

    The addresses for controlling the MD04 differ from what you expect because I2C uses the upper 7 bits for addressing. The extra bit is for telling the MD04 board to read return data. So if we configure the board with Address B0, we have to send 0x58 (hexadecimal) to the MD04.

    Hexadecimal = B0

    Binary = 1011 0000 (8 bits)

    When discarding the last bit:

    Binary = 1011 000 (7 bits)

    Hex = 58

    Receiving data

    When reading data from the MD04, you must be aware that the current value is proportional to motor current, with 186 representing the 20A limit. The temperature value is the temperature from the PCB in degrees centigrade.

    The output to Serial from the Arduino will show the Direction (1 or 2), and speed sent to the MD04. The Current and Temperature returned are received from the MD04.

    Conclusion

    Controlling a motor driver with an Arduino is straightforward, and the code is simple enough. You only have to be aware of the addresses used by I2C. You can use this information for your projects. See the code in action Motor driver MD04 with Arduino Uno – YouTube.

  • Starting over

    Starting over

    My A1 robot is a robot based on a wheelchair. The robot’s purpose was to do telepresence. I built this thing 12 years ago and is collecting dust since then. I could not make it work at that time because of the lack of affordable technology, software possibilities, and my skillset.

    A lot has changed now. The widely available electronics and the amount of cheap computer power give much more functionality out of the box. I want the robot to be a platform capable of driving around autonomy and doing image-recognizing tasks like detecting garbage and faces.

    The old electronics on this robot, like an Intel Mini ITX D945GSEJT and a servo driver, had to go. I ripped the electronics to make room for new components. I have already replaced the pulverized old tyers. The plan is to reuse the wheelchair base, motors, and motor drivers (MD03 from Devantech). The 24 Volt power supply is also staying for testing now. A Teensy 4.1 will do the low-level control, like handling the motor drivers and reading sensor data. This controller has many inputs and outputs and serial, SPI, CAN, and I2C ports.

    I haven’t decided what single-board computer I will use to do higher-level control. A prominent candidate is the NVIDIA Jetson Nano or better. It’s hard to get one because of a chip shortage. Another option is to use one or more Raspberry Pi boards and connect them with ethernet. The Teensy will use a serial connection to transfer data between a Raspberry Pi or the Jetson. This configuration makes it possible to build a modular system and allows swapping components when better components are available.

    The first task is to make the robot drive remote-controlled. I build a remote control for this with a Bluetooth module. There will also be a Bluetooth module connected to the Teensy on the robot. The motor drivers will be connected through I2C, making it possible to read data from the driver like current use and temperature.

  • InMoov Back Covers

    InMoov Back Covers

    Now we are going to put the back covers in place. This is a fairly easy build. Just print all parts and clean them up. It’s important to put all the mounts in place first. The panels should be glued together on the robot itself because to prevent to much stress on the parts.

    On the following picture, the parts are layed out as they should be mounted.

    The top part of the back covers should look like this. I used super glue to glue the PLA parts together. Those cheap clamps are usefull to keep everything aligned.

    At the end you should see something like this.

    If you have questions or comments, please let me know. inMoov is designed by Gaël Langevin so make sure you visit is website at https://inmoov.fr.

  • InMoov hand build

    InMoov hand build

    Finally I made some progress on inMoov robot in a long time. The left arm is completely done already, but the right side still needs the lower arm and the right hand. In this article we going to look at the right hand.

    I made a video with every step of the build in detail, so you can follow along. inMoov is designed by Gaël Langevin so make sure you visit is website at https://inmoov.fr.

    I always print the parts with a brim so it needs a lot of cleanup, but it makes sure the parts are nice and straight. This is important if you need to glue parts together. After cleaning up it’s a good thing to lay all the part on the table to see if everything is there.

    I found it a little bit confusing how the fingers should be glued together, but it’s fairly simple If you know where to look at.

    The lower part of the finger has a marking in the shape of a rectangle when the parts are glued together. The top cap should be glued together with the part with two small holes on the top for the wires. I use hot glue for this part so I can remove the cap if I have to replace the wires someday. For the other parts I used Super Glue. The middle parts of the finger have a shape on the face where the two parts come together.

    For the rotating part I used a piece of filament and cut it with a small wire cutter to make a straight cut.

    .

    The other parts are not too complicated to fit together, with help of the picture below.

    You need a tweezer to put the wires through the fingers and the hand. It’s not easy but with some patients it’s not impossible.

    At last I mounted the top of the hand with some 3 mm screws. The 4 parts on the fingers are glued on the fingers. I made the mistake once to glue them on the hand and that looks strange when the hand is in closed position.

    If you have questions or comments, please let me know. inMoov is designed by Gaël Langevin so make sure you visit is website at https://inmoov.fr

  • inMoov Robot Bicep

    inMoov Robot Bicep

    The bicep from the inmoov is not a complex part and are the same for both left and right arm. The covers are sometimes a struggle to mount because in my case the print is a bit taller then it should be.

    My Servo (Hitec HS-805BB+) has a square potentiometer so this doesn’t fit in the orginal LowArmSideV1 version from Gaël . I found a LowArmSideV1 with a square hole on Thingiverse by alansrobotlab (https://www.thingiverse.com/thing:533469). This part receives the square potentiometer snugly.

    Let’s start. I started with gluing the HighArmSide and the LowArmSide parts together twice. Only a few adjustments where needed with sanding paper and a file.

    After this the Reinforcer was added to both sides. I used glue to make a strong connection between the parts.

    Then I glued one of the sides to the RotMid. I didn’t glue the other side, because I want to be able to remove one side, if something is wrong.

    The gears from Pistonanticlock and the Pistonbaseanti prints had some rough edges. I sanded these parts a little bit and then I rotated the piston over and over again in the Piston base. I went back and forth with the sandpaper and after a while it rotated nicely. The Pistonbaseanti needed some adjustments on the axle on the sides. In my case the axle was not completely round, but more like an oval shape. I used a file and sandpaper to make it as round as possible. I also made the holes from the arm sides a little bit bigger.

    The Pistonbaseanti fits together with the Spacer between the two sides.

    The Servobase and the Servoholder are mounted together with screws so you can replace the servo if it breaks down. I used screws with a diameter of 3,5 mm and a length of 16 mm. The wires from the modified servo need to go through the holes on the side of the Servoholder. The potentiometer is to large and has to be detached from the servo. The wires have to be guided through the channel on the side, so the wires don’t get squashed by other parts of the bicep. I used thicker wire then intended, so I had to make the channel for the wire a bit bigger. A drop of hot glue keeps them in place. To guide the wires over the servo I used black tape.

    To mount the Pistonanticlock on the servo I made the four holes bigger with a 3 mm drill. Then I used a screw with a diameter of 3 mm and a length of 16mm. My screws where to long so I had to file them to the right length.

    Then I fitted the Pistonanticlock and the Pistonbaseanti together by turning the servo manually.

    The Elbowshaftgear and the Robcap are glued together and then mounted on the bicep with a 8mm bolt.

    My potentiometer fits nicely in the square hole. It doesn’t need any screws now, but maybe I will add them later. On the potentiometer the Gearpotentio is mounted. The Gearholder then is slided over the gear to prevent is from sliding off.

    The last step in this assembly is to glue all covers together and mount them on the bicep. It’s looks a lot cooler with the covers on. I needed to file some parts because it didn’t fit.

    In the next episode I am going to build the lower arm and will connect the arm to the shoulders part of the inMoov. If you have questions or comments, please let me know. inMoov is designed by Gaël Langevin so make sure you visit is website at https://inmoov.fr

  • InMoov Support Block

    InMoov Support Block

    After the crash of my inMoov robot it took a lot of work to put it back together. To prevent a crash again I decided buy a stable speaker stand for big speakers. To make it fit it was necessary to design a special block to connect the upper body of the inMoov robot to the 35 mm pipe of the speaker stand.

    My speaker stand is from the brand Innox, but there are several brands offering the same product. For example: Speaker stand on Amazon.

    You can find the STL file of this support on Thingiverse.com.

    Make sure you take a look at the website from the designer of the inMoov robot at www.inmoov.fr.

  • Eye Mechanism inMoov robot

    Eye Mechanism inMoov robot

    Wow. Time flies when you having fun. This website is about my the things I build in my free time. Last 2 years where very intense at work and in my private life. Now I decided to work less, to put more time in building robots and at first finish my inMoov robot.

    After the crash on the floor and all the broken pieces the robot in the same state where I left off before my last post. The first thing to do was finishing the Eye Mechanism of my inMoov robot.

    In the designs of the inMoov robot (www.inMoov.fr) you can add small camera’s. In this stage I don’t want to use these yet, so I will use an round piece of 3D printed plastic to cover the hole in the eye. I also want to keep the inMoov robot as robot like as it can be at the moment. So I don’t bother to make the eye as realistic as it can be.

    I made a video of the build on my YouTube channel.

    The Eye mechanism has some small parts.On the picture below you can see the standard parts.

    The parts fitted nicely. The only thing that not fit directly was the EyeHingeCurve. Probably because I used an other servo than Gael Langevin did in his design. I had to adjust the hinge with a knife 😉

    The final eye Mechanism.

    In the Youtube video I used a small test code in arduino to move the eyes. You can use this code to test your own servo. In this example the servo’s are connected to a Arduino Mega on pin 22 and 24. Please change the value’s to your needs.

    /* Based on the Sweep example
     by BARRAGAN <http://barraganstudio.com>
     This example code is in the public domain.
    
    modified 8 Nov 2013
     by Scott Fitzgerald
     http://arduino.cc/en/Tutorial/Sweep
    
    Modified to control Eye mechanism inMoov robot (With Arduino Mega)
     https://swanrobotics.com
     */
    
    #include <Servo.h>
    
    Servo horServo; // Horizontal servo (left tot right)
     Servo verServo; // Vertical servo (Up and down)
    
    // Change these settings to your own setup and preferences.
     int horServoPin = 22;
     int horMaxLeft = 60; // Maximum servo position Left
     int horMid = 90; // Middle servo position horizontal
     int horMaxRight = 120; // Maximum servo position Right
     int horStep = 1; // Step size for position horizontal
    
    int verServoPin = 24;
     int verMaxUp = 45; // Maximum servo position Up
     int verMid = 65; // Middle servo position vertical
     int verMaxDown = 95; // Maximum servo position Down
     int verStep = 1; // Step size for position vertical
    
    int delaySpeed = 500; // time between the movement
     int pos = 0; // variable to store the servo position
     int positionwait = 5; // variable to wait for the servo to reach the position
    
    void setup()
     {
     horServo.attach(22); // attaches the servo on horzontal pin
     verServo.attach(24); // attaches the servo on vertical pin
    
    horServo.write(horMid); // Put horizontal servo in neutral position
     verServo.write(verMid); // Put vertical servo in neutral position
     }
    
    void loop()
     {
    
    // Look right
     for(pos = horMid; pos <= horMaxRight; pos += horStep)
     {
     horServo.write(pos);
     delay(positionwait);
     }
     delay(delaySpeed);
    
    // Look left
     for(pos = horMaxRight; pos>=horMaxLeft; pos-=horStep)
     {
     horServo.write(pos);
     delay(positionwait);
     }
     delay(delaySpeed);
    
    // Look neutral
     for(pos = horMaxLeft; pos<=horMid; pos+=horStep)
     {
     horServo.write(pos);
     delay(positionwait);
     }
     delay(delaySpeed);
    
    // Look Up
     for(pos = verMid; pos <= verMaxDown; pos += verStep)
     {
     verServo.write(pos);
     delay(positionwait);
     }
     delay(delaySpeed);
    
    // Look down
     for(pos = verMaxDown; pos>=verMaxUp; pos-=verStep)
     {
     verServo.write(pos);
     delay(positionwait);
     }
     delay(delaySpeed);
    
    //Look neutral
     for(pos = verMaxUp; pos <= verMid; pos += verStep)
     {
     verServo.write(pos);
     delay(positionwait);
     }
     delay(delaySpeed);
     }

     

     

  • Warning. Not nice to watch!

    Warning. Not nice to watch!

    A few weeks ago I was printing some new parts for my inMoov robot. It was time to make some progress again. But… i was doing some vacuum cleaning and the power cord was wrapped around my inMoov robot. I am still wondering how this happened, but it few down hard. The pieces were al over the place.

    img_7691

    img_7696 img_7695 img_7694 img_7690

    As you can see on the pictures a lot of parts a really broken. PLA is a nice material to print and very hard when it’s printed. I still have to figure out what part have to be reprinted, but I already started with the parts on the lower torso, because al these parts are broken.

    I think inMoov was a little top heavy and the stand was not stable enough. The side to side stability was OK, but front to back bot. At first it was no problem I guess, but when adding the arms a lot off weight was added. I have to find another solution for this before I build it again.

    mount3