Recent things:
Hi! I'm AmitBuilding Autonomous Road At HomeHow to build RC Lego car

How to build RC Lego car

Amit Taller, 01/23/2023

When I was at mid-elementary school age I boarded for the first time in my life (and last) on a $20 million yacht. Needless to say, as a child from a small and simple town, I was perplexed. I never imagined myself that things like that even exist. It was like a mansion on water: 3-4 floors of unbelievably luxury, all-wooden floors, some of which was carved with white decorations, cinema room, bar room, engine room (I'm spitting anything I remember - don't judge), on sea level floor there was another boat inside the yacht itself! Anyway - It left a big impression on me. So the next day, I've done what I had always done to digest things - I've built it in Lego! And boy - what a (lego built) yacht that was…

Thus, the current lego model on my shelf reflected current events in my life: Apollo 13 Service and (!) Lunar modules - after the 1995 Apollo 13 movie. CH-53 Sea Stallion helicopter following an horrific accident involving one craft hitting another's tail (I've made that one so that the tail could easily fall) and so on and so forth.

Therefore, naturally, when I decided to build a Lego RC car I used the one on my shelf - Ford F-150 Raptor (a set, unfortunately - but you've got to pick your battles, right?).

But transforming a model car (however beautifully built it may be) to computer controlled RC is not a straightforward task. Actually, it could have been, had I not imposed a small requirement: all the software in the project should be written in Rust. Considering all the buzz surrounding this programming language and some of its genuinely awesome advantages - I've decided to learn it and get some ‘hands on experience' with it. And what a better way to do that than to write a project?

The technical stack

No matter how good or how bad you think it is, these are fascinating times, no doubt. And Lego is no exception to this. There must only be admiration for the technical staff there who chose to follow the LEGO Powered Up technology, a Bluetooth based communication - making development much easier. The previous one was based on infrared, so you can understand why I am so relieved to live in our time.

For the control part, I used two motors, one for steering, the other for speeding. Each motor is powered and controlled by a hub. The bluetooth connection is made to the hub and on top of it one can send commands and get information following the LEGO Wireless Protocol.

I won't be surprised if the LEGO Wireless Protocol 3.0.00 documentation was randomly butchered by some authoritative in the Lego management for IP conservation purposes. From time to time, it seems as if the documentation makes no sense at all and is missing important endpoints while still giving them as examples in other parts. But it is what it is, right?

But let's get back for a sec. There must be several good implementations of this protocol for various languages. As for Rust, I found on crates.io only one: lego-powered-up - but it had a big drawback: the main crate for bluetooth communication in Rust is btleplug. btleplug is, currently, an asynchronous crate. But previously it wasn't. And when lego-powered-up was first written it was not developed as an asynchronous crate which made the upgrade process from sync to async - not trivial. I contacted David Young, the guy who wrote it and asked him about that. While he said that he's going to work on it - I already knew that I'm going to do it myself: for the sake of speed and my education. Later in this article I'm going to talk a little bit about that crate of mine and how to use it, but it is worth mentioning that Young did upgrade the crate, and functionality-wise - his is much more rigorous (link below).

Motorizing the Ford F-150 Raptor Lego Technic set

I must admit that for a substantial part of my life I didn't count the Technic sets as ‘real' Lego sets. The Raptor was the first for more than two decades. So I was blown away by a few cool characteristics of the set. As if it were a real engine, the model's 'engine' has six cylinders with pistons inside that are connected to the rear wheels, so they actually move with the wheels. Moreover, the suspensions are impressive and give the truck an off-road feel. Finally, the rear wheels have a differential! But I wanted to add motors right in the middle of this beauty - so let's break some things…

Lego F-150 Raptor chassis

Above is the chassis of the car. Left is front, right is rear. Arrow A points to the axle connected to the differential at the rear. You can see that it is connected to another axle that goes to the front. This is the axle that moves the pistons at the front. Because I wanted to minimize power lost - I decided, against my heart, to remove that connection. The motor is sitting right in the middle of the white square facing right and attached directly to the differential's axle.

Arrow B points to the wheeling axle. That one was easier than the speed motor. While I kept the structure as is, I found the steering mechanism to be too soft. Even when I kept the motor power low, the steering gear kept rolling even when it got to the end. This made some clunking noise and raised a problem of inconsistency between the motor's cycles and wheels position. There are few ways to address this problem, but it's not a real problem for a manual RC car, so I'll deal with it later.

The Hub, by the way, is placed on the back of the truck.

The Lego motors

While the previous version of Lego motors has a servo motor, this version doesn't have such a thing. But there is no need to be nostalgic, since today's motors have characteristics that could serve as a servo motor. It is possible to define an absolute 0 (by setting a specific position with a specific number of degrees) and then turn the motor to any other absolute positions.

Serving as a servo motor it is possible to control it with absolute position (as being said) or by turning it by degrees. When speeding, the control is by setting the power the motor is to activate (and then you have to control the speed), or by setting the speed itself (and defining the max power to use).

Rust interface - rust-powered-lego

Since I'm pretending to be an adult facing real world problems, I separated the interface and motor control problems from the management and automation ones. That's why this crate is only dealing with the task of ‘speaking' the Lego Hub's language.

Generally there are three main parts: The manager object and the Hub and Port objects. If you want a Hub, ask the manager to get it for you. If you want a Port, ask the Hub about it

#[tokio::main]
async fn main() -> Result<()> {
    // Hub "MAC" address can be found in several ways.
    // Connect it to a computer and continue from there...
    let hub_mac_address = "90:84:2b:4e:5b:96";
    let port_id = TechnicHubPorts::B;

    // Converting the MAC string to btleplug::api::BDAddr type
    let address = BDAddr::from_str(hub_mac_address)?;

    // The ConnectionManager connects stuff - so ask it for the hub...
    let cm = ConnectionManager::new();

    // It is possible to use the name of the hub or its MAC address. That's why it's Option<>
    // Here, only address is implemented
    let hub = cm.get_hub(None, Some(address), 5).await?;

    // Ask to get the motor object (pay attention to the port_id)
    let motor = hub.get_motor(port_id as u8).await?;

    // Initiate the motor with power
    _ = motor.start_power(100, StartupAndCompletionInfo::ExecuteImmediatelyAndNoAction).await?;

    // Let it hang there for 3 seconds
    time::sleep(Duration::from_secs(3)).await;

    // And stop
    _ = motor.stop_motor(EndState::FLOAT, Profile::AccDec, StartupAndCompletionInfo::ExecuteImmediatelyAndNoAction).await?;

    Ok(())
}

More examples, like calibrating the steering motor, you can find at: rust-powered-lego/examples

Controlling the car - velocirustor

The last part of this current trail is to be able to control the car manually through the keyboard. We have the translator - now we need to transfer commands. For that purpose I created a new crate.

This crate's aim is to deal with everything in the context of managing cars on the road. Now it's going to be manually, later - automatically. The specific manual control is in the examples directory: manual.rs

The main (and only for now) thing worth mentioning here is the fact that many of the UI crates that support metadata from the keyboard (like releasing a key, not just pressing it) are not async crates. Therefore, one needs to think well on the method of sending commands to async code where these commands origin is sync code. I solved this situation by spawning a new thread with the async code running eventloop, where I inject the commands I want.

Ok - now what?

While I'm really anxious to start the autonomous thing, there's the problem of localizing the car in the vicinity. So until then…

Oh, I forgot..:

© All rights reserved to 4m17.io
Popular Tags:
'Homemade, 'DIY, 'RC car, Autonomous Vehicles, Lego, Autonomous Road, Rust