Once again, another post where I'm going to have to mix subjects that look completely random but do have a thread connecting them: remote control cars and magic boxes that take pictures of birds!

Back in 2024 I started an electronics project that I named: Wind Wheels, because I thought it sounded super "cool" as a name for an RC car. But let me give you some context first...

Since the beginning of my career I've always had a lot of contact with hardware besides software, and I kept small hardware projects going so I wouldn't get rusty, mostly around radio frequency communication, which is a technology I find fascinating. Sending information through the air, wow, isn't that fascinating? I think it is! But those were projects I ran here on my desk to read and identify tags, devices and objects, or poking around development boards like the Arduino Uno/Mega and the ESP8266, and testing modules. What I wanted was something I could take to the field...

First field project, off my desk

So I decided to build a magic box that takes pictures of birds, yeah, really. That way I'd have to deal with external power, which as far as I can tell is still one of the big challenges in projects like this. I had a very old Motorola phone lying around, and I remembered that back then we used wired headphones, and in the middle of the cable there was a button to answer calls and also to take pictures. With that photo button in mind, I figured I could reproduce the electrical behavior it produced, and then take the picture programmatically whenever I wanted, or at the right moment (when a bird got close to a sensor).

0:00
/0:13

How the button behaved with the camera app open

Internally, the button was something like this:

Headphone internal button

I remember reading on some technical blog that, when pressed, this button caused a difference in resistance in the circuit. And I could reproduce that with an LDR (Light Dependent Resistor), which is basically a photoresistor: as the light changes, so does its resistance.

More light = resistance drops
Less light = resistance rises

Which is this little part right here...

LDR

So I already knew how to reproduce the button. I put a LED in front of the LDR, and whenever I wanted to change the resistance all I had to do was turn on that high brightness LED in front of it. To detect whether the bird was within camera range I was using a well known ultrasonic module. (HC-SR04)

And then I built the circuit... and voilà! I captured a shark on camera (Sammy, from DigitalOcean).

0:00
/0:04

Video of the complete circuit

I had a prototype, but now I needed an enclosure to hide all that mess inside. And for prototypes like this, before soldering onto a real PCB or building a case, the best material there is is cardboard! So I put everything inside a cardboard box (the phone's own box, by the way) and cut 3 holes in it that lined up exactly with the ultrasonic sensor and the phone's camera. And it came out something like this:

Prototype ready

Now I needed to put it in the field and test it, right? Well then, I bought a bag of birdseed, put some on a little plate, and behind the plate I placed the magic box that takes pictures of birds...
HA! I almost forgot, I powered it with a 9 V battery. Not the best option, but... it's a prototype, let's make it work and improve it later!
Result: not a single bird wanted to get close to that colorful box with suspiciously easy birdseed. I sat in the garden for hours and nothing... frustration!

But I decided to improve the project anyway, and my brother-in-law helped me cut a more definitive box on his CNC machine. I used this site here https://festi.info/boxes.py/ where you can put a box design together really fast, and then just take the file to be cut. It was a recommendation from a YouTube channel I love, Manual do Mundo, in a special video about cutting machines: https://www.youtube.com/watch?v=BwU0hSmWYdA

0:00
/0:06

Here's a photo I found of me gluing the walls of the box with superglue.

Final case

I couldn't find a photo of the whole thing assembled and running in the garden, but here's the result, which was zero bird pictures, lol. No bird wanted to get anywhere near that metal contraption, no matter how much birdseed was sitting on a plate in front of it. But it was the beginning of a functional field project!

Next field project

Now with field experience, running on external power instead of being plugged into a cable in a controlled environment like my office desk, I could take on something more complex. And this is the point where, with everything I had learned, I started Wind Wheels.

The project was about building a car I could control from my phone at first, but I find controlling things with a virtual joystick really boring. If I was going to build a remote control car, what I actually needed was something physical. So now I'd have to have a project with two controllers that talked to each other, exchanging information wirelessly.

The first thing I thought of were TT motors, which are very affordable and come with wheels in some kits that fit perfectly on their shaft. So I bought the motors, some PCBs, buttons, and one more Arduino UNO to use in the project (which I'd end up replacing later).

I also wanted a camera mounted on the car, so I could watch in real time from the car's point of view, like a rover driving across the surface of Mars. And then I made a terrible choice: the OV7670. A camera that is not friendly at all on the technical side.

OV7670

It doesn't output JPEG, it hands you raw data, and all the work of assembling the image is on you. It needs control of XCLK, PCLK, HREF and VSYNC, meaning the software has to coordinate telling the Arduino when each pixel starts, ends and should be read, on top of a really bad resolution. After generating the first images I realized it wasn't the right choice: it would steal a lot of processing from the UNO, which is already quite limited, and I'd have to write a lot more code for very little gain.

At this point I decided to forget the camera for a while, before researching other alternatives, and focus first on the car's chassis and on controlling the motors individually. For the chassis material I needed something light and sturdy at the same time, and that's when I found an MDF box that was perfect for the project.
I'll take the chance to thank Pedro here, because that box was part of the invitation
to be a groomsman at his wedding.

Holes in the wood to run the zip ties that hold the TT motors.

Little by little the wood was turning into the chassis of a Wind Wheels supercar! To control the motors we need a dual H bridge (L298N), which takes its own power supply. The Arduino's 5 V is far too little here, and once again I used my 9 V battery, since everything is still a prototype. The power question gets solved in part 2 of this series.

PS. I already suspected power was the biggest problem in the world for automation, but this project is where I got proof: I understood how much it matters, and that the battery is the most expensive part of the build.

H bridge

Each motor wired to one output of the bridge, and we have a chassis with the drive wheels connected.

At this point in the project I already knew the Uno would be tight for what I had in mind: at least 2 servomotors, some LEDs, the wireless communication part, a camera, other possible modules like a memory card reader and so on... so I decided to switch to an Arduino Mega. Both do 8 bit processing at 16 MHz, but with the Mega I gained more RAM and Flash, plus more pins, which was the most important part for the project.

Arduino Uno vs Mega

FLASH MEMORY
Arduino Uno ██ 32 KB
Arduino Mega ██████████ 256 KB

RAM MEMORY
Arduino Uno ██ 2 KB
Arduino Mega ██████████ 8 KB

DIGITAL PINS
Arduino Uno ███ 14
Arduino Mega ██████████ 54

Warm Up the Engines!

For the joysticks that would control the motors I bought the KY-023, two of them.

The remote control design in my head was: the left joystick would steer the car, and the right one would handle the speed. And with this module I could read only the X or only the Y axis, whichever I wanted, so I wouldn't waste pins unnecessarily, because on the steering joystick I'd only use VRx to measure left and right, and on the speed joystick only VRy, measuring up and down.

0:00
/0:08

Modular software design

Every electronics project you see out there, especially the Arduino ones, is always a single file, everything loose inside it, and it turns into a mess that looks like a DEMO. But I wanted to build something nicer, modular, reusable and organized.

So instead of doing everything in one .ino and running it all in the Arduino IDE, I decided to create header style files with the extension .h. That way I could split it into modules like:

  • Motor.h
  • MicroServo.h
  • Joystick.h

....

And this is how the code for Motor.h

#ifndef MOTOR_H
#define MOTOR_H

#include <Arduino.h>

class Motor {
  private:
    int pinDirectionA;
    int pinDirectionB;
    int pinSpeed;

  public:
    Motor(int pinDirectionA, int pinDirectionB, int pinSpeed) {
      this->pinDirectionA = pinDirectionA;
      this->pinDirectionB = pinDirectionB;
      this->pinSpeed = pinSpeed;

      pinMode(this->pinDirectionA, OUTPUT);
      pinMode(this->pinDirectionB, OUTPUT);
      pinMode(this->pinSpeed, OUTPUT);
    }

    void setSpeed(int speed) {
      analogWrite(this->pinSpeed, speed);
    }

    void setDirection(char direction) {
      if (direction == 'F') { // Forward
        digitalWrite(this->pinDirectionA, HIGH);
        digitalWrite(this->pinDirectionB, LOW);
      } else if (direction == 'B') { // Backward
        digitalWrite(this->pinDirectionA, LOW);
        digitalWrite(this->pinDirectionB, HIGH);
      } else {
        digitalWrite(this->pinDirectionA, LOW);
        digitalWrite(this->pinDirectionB, LOW);
      }
    }
};

#endif

This entity works like this: when I instantiate a motor, I pass 3 parameters as function arguments, and they define the direction the motor spins and its speed.

  • A HIGH, B LOW = spins in one direction
  • A LOW, B HIGH = spins in the opposite direction
  • A LOW, B LOW = the motor stops

So we can use it like this:

Motor motor(7, 8, 9);

  • 7 and 8: control direction through the H bridge
  • 9: controls speed using PWM

In part 2 I'll show that I also created a configuration file for the pinout, to avoid passing pins straight into the entry point. It ended up working like a "dot.env".

And to keep the motors in sync, I have another header that instantiates two motors. Motors.h

#ifndef MOTORS_H
  #define MOTORS_H

  #include <Arduino.h>
  #include "Motor.h"
  #include "config/CarPins.h"

  class Motors {
    private:
      Motor motor1;
      Motor motor2;
      const int NEUTRAL_JOYSTICK_MIN = 510;
      const int NEUTRAL_JOYSTICK_MAX = 525;

    public:
      Motors()
        : motor1(PIN_DIRECTION_A_MOTOR_1, PIN_DIRECTION_B_MOTOR_1,
        PIN_SPEED_MOTOR_1),
          motor2(PIN_DIRECTION_A_MOTOR_2, PIN_DIRECTION_B_MOTOR_2,
          PIN_SPEED_MOTOR_2) {}

      void drive(char direction, int speed) {
        Serial.println(direction);
        Serial.println(speed);

        motor1.setSpeed(speed);
        motor2.setSpeed(speed);

        motor1.setDirection(direction);
        motor2.setDirection(direction);
      }

      char parseDirection(int joyStickValue) {
        const int neutralMin = NEUTRAL_JOYSTICK_MIN;
        const int neutralMax = NEUTRAL_JOYSTICK_MAX;

        if (joyStickValue < NEUTRAL_JOYSTICK_MIN) {
          return 'F'; // Forward
        } else if (joyStickValue > NEUTRAL_JOYSTICK_MAX) {
          return 'B'; // Backward
        } else {
          return 'N'; // Neutral
        }
      }

      int parseSpeed(int joyStickValue) {
        const int neutralMin = NEUTRAL_JOYSTICK_MIN;
        const int neutralMax = NEUTRAL_JOYSTICK_MAX;
        const int minInput = 0;
        const int maxInput = 1023;
        const int minOutput = 85;
        const int maxOutput = 255;

        int output;

        if (joyStickValue >= neutralMin && joyStickValue <= neutralMax) {
          output = 0;
        } else {
          if (joyStickValue < neutralMin) {
            output = map(joyStickValue, minInput, neutralMin, maxOutput,
            minOutput);
          } else {
            output = map(joyStickValue, neutralMax, maxInput, minOutput,
            maxOutput);
          }
        }

        return output;
      }
  };

  #endif

This part here was really important:

const int NEUTRAL_JOYSTICK_MIN = 510;
const int NEUTRAL_JOYSTICK_MAX = 525;

This kind of joystick module is analog, and it often has noise or small variations, so the motors kept twitching, as if they were switching on and off. So, just like in an air conditioner, you need a kind of hysteresis, a dead zone, so that inside that range the motors don't move. That's how I got rid of the noise and of the annoying behavior of the motor "twitching" even with the joystick standing still.

The parseSpeed(int joyStickValue) is what I use to convert the signal coming from the analog joystick into the PWM for the motors' H bridge. The analog values read from the joystick run from 0 to 1023, and the PWM output for the H bridge runs from 0 to 255. Hence the conversion. And this line:

const int minOutput = 85;

You might be thinking, why doesn't it start at zero? I noticed the TT motor would only start turning, at its minimum rotation, from 85 on the PWM. I don't know whether that's a defect in mine or just the limitation of a cheap little motor.

The part of the project that made me abandon it and put it off for 2 years

It was the front wheels where things got ugly. I didn't want an ordinary car like the ones in internet projects that put 1 motor on each wheel, where to make a turn you lock some wheels and speed up others and the car starts spinning in a very artificial way. That is not how real cars take a corner. So I decided I wanted my car with that mechanical part as close as possible to a real one with rear wheel drive: the back wheels with motors and the front ones on a steering axle. And this is where it stops being electronics and becomes mechanics, something I need to get better at.

I looked up how people do this kind of thing, and there is a well known mechanism, but it's harder than I thought.

Design to 3D print RC car - Steering • Physics Forums
Steering mechanism

To turn one way and the other, you use a servo motor right there.
And I picked the SG92R, and built a driver for it too, which came out functional and reusable.

SG92R servo

And on the tip I'd use a bracket that comes with it, to attach to the steering mechanism, like this:

0:00
/0:13

Servo with a joystick simulating steering

I tried a few prototypes to get the concept right, but none of them was good enough to be the car's steering system:

0:00
/0:14
0:00
/0:23

Shelving the project and picking it up again 2 years later

I remember putting a lot of energy into it, hunting for screws and hinges in hardware stores. I even bought a roll of stiff wire that I never used. And for other reasons, work and life, I ended up abandoning this project for 2 years. Now I'm picking it back up...

I have a lot of news for part 2: a sensational camera module, a remote control prototype, I picked the wireless communication, protocols, electronic warfare, power done properly with a type of lithium battery, a new H bridge, a memory card reader, using VSCODE, and improvements to the project's software and architecture. That's a lot of news, see you in the next chapter.