There are things that deep inside every man wants to have. Combining beer and tanks is one of these things! This project will be about this thing, a voice controlled tank that delivers beer to you with an autonomous "follow me" function or with an RC control. Let's build the beer tank of our dreams!
We need a good base for the tank. I found this chassis on banggood. It was quite cheap and it looked so cool that I needed to buy one.
Right after receiving the product came the first problem. Due to the improper packaging it suffered some serious injuries during shipping.
It took lots of hours and lots of glue but luckily mostly I could repair it.
CraneThe tank chassis contains both the motors and the gearboxes, so the next step was to figure out how to serve the beer. After numerous ideas I figured out that the best and coolest way to do it is to hide the beer and then elevate it using a crane. This is the basic design that I came up with:
I used my old metal builder kit because I needed a strong but easy-to-modify skeleton. The crane is connected to a stepper motor with a fishing line The 28byj-48 stepper motor was great for this purpose. It is not fast but it could easily lift the crane and the beer. Actually the motor is so strong that if I didn't stop it in time it broke the fishing line.
It worked wonderfully, however the skeleton wasn't strong enough and started to bend very early. To solve this problem I needed to increase structural integrity. I used two, 30 cm long hard wood rulers and some extra parts to make it stronger. After some drilling, sawing and rasping here is the next version:
As you can see the modifications solved the bending problem and it is very stable.
CaseA Walabot (Developer version) will be the 'eye' of the tank. More on Walabot in the Walabot section. The front place has a holder part for the Walabot. I had a metal part that has the perfect size to make use of Walabot's magnetic holder. I also made a Walabot logo shape out of hot glue to prevent the Walabot from rotating on the round part:
The magnetic mounting is great because I can easily use one Walabot in multiple projects without any serious disassembly and it is also strong enough.
I started to make a cover around the frame to hide the parts. I used black cardboard paper and plastic sheets for the cover.
At this point the front and middle part wasn't covered. I also needed a hatch on the top to hide the beer completely. To move the hatch I used two servos, some hot blue and some insulating tape. This top door used only for design, it doesn't really protects the beer. However it is very cool when it opens up and elevates the beer.
The doors are made of two plastic sheets, wood sticks and some glued and rolled up paper, glued together with hot glue. It is not the prettiest thing, but in real life it doesn't look that bad. I painted black everything. In real life it is much more difficult to see the difference between the black parts.
Let's go back to the crane once more. I needed one more thing to use it reliably: feedback.
Originally I wanted to use a simple binary feedback for this. When the crane is in lowered state, it would close a circuit. When elevated it would open: The screws and the spring in the red circle would have been that switch. It would have used a timer to determine the top position.
It wasn't too sophisticated but the idea is worked. Unfortunately it wasn't reliable at all thus it could have easily led to damaging the crane.
I came up with another, a lot better solution, the one in the blue rectangle. I glued a 10K potentiometer to the and of the crane's shaft, so I have reliable feedback about the current angle of the crane. It is very easy to determine the top and the bottom positions in this way. FYI: until this point I used my good old Arduino Uno for testing because its proto shield is so handy.
Actually I really like this feedback part. It wasn't planned but it adds some extra coolness to the tank's look.
CircuitAll right, the body of the tank is finished but we need some electronics to make it move!
I also placed this image into the Schematics section, but here you can enlarge it without downloading. The circuit might seem a little complex at first but actually it is pretty straightforward. The attached notes should help with anything that needs some explanation.
This project is not using the WiFi functionality of the Arduino MKR1000 at the moment, but as I know, you can't just replace it with an Arduino Uno if you want to control the tank using an RC transmitter. My project is using 3 channels for controlling speed, turning and the crane. I need 3 pins with external interrupt capability. Arduino Uno's have only 2 pins for this purpose. We need those pins to read the PWM values of the RC receiver's corresponding channels.
I built the circuit on a proto PCB. It got quite compact. The blue LED on the left would have been a simple 'built-in' LED for debugging, but I never actually used it. The green connector is used to connect the LiPo battery.
Most of the wires that are connecting to this board are on the top part of the tank. It was obvious to glue the board there to avoid 'wire hell'.
As you can see on the image, originally I started with a Raspberry Pi Zero W, but due to the lack of power I moved on to use a Raspberry Pi 3 B.
It was working perfectly at this point but I added an extra cool feature: hidden headlamp. The black plastic part on the right can be easily moved. I attached a servo to move it up and down and I also used one segment of a 12V LED strip. Powering a 12V LED strip from a 7.4V LiPo battery is not a good idea. The lights will be very weak. I replaced the middle LED with a wire to make the remaining LEDs bright. It worked perfectly.
The front LEDs are controlled with the same pin as the blue indicator LED. I had to slightly modify the board by adding some extra headers and a transistor to it. The result is awesome:
I used an Arduino MKR1000 to control the tank. This is the smallest Arduino or Arduino IDE compatible device in my collection that can handle 3 external interrupts and has enough pins for this project. It also has WiFi capabilities but I won't use that now.
The tank needs 5 PWM capable pins. 3 for the servos and 2 for the motors. If you check the capabilities then you see that there's 12 PWM capable pins. That is good enough right? Well yes and no.
Pins 2-5 have the ~ marking. I believe it means that only this four pins are capable of creating hardware PWM signals. I think the other pins can create software PWM signals only. The tech specs doesn't write about this, however when I got my first, prototype MKR1000, the documentation mentioned only 4 PWM capable pins. That four. Originally I controlled the hatch servos through two of these software PWM pins. The combination of software PWM generation and hardware interrupt based PWM signal reading is resulted this problem:
I solved this issue by using hardware PWM pins for the servos. Unfortunately I had to use one of those pins for the LED door's servo, because the other two hardware pins needed to control the motors. Thanks to the TB6612FNG motor driver, I only needed two PWM pins (and 4 other digital pins) to control the motors. The 'LED door' servo is much slower than the others so it just makes some quiet buzzing noise sometimes. Using only one software PWM pin rather than two also helped. In the future I might rebuild that part to use some other means to open the LEDs' door. Solenoid(s) might do the trick.
The Arduino can measure the voltage of the battery and then send it through serial. Furthermore, I integrated a simple voltmeter into the back of the tank. It is used as the feedback for the user regarding the status of the battery. It is a separate circuit and not controlled by the Arduino.
Arduino - Radio ControlThe MKR1000 is processing 3 separate PWM signals with external interrupts. The signals' pulse time is in the range of about 1000 and 2000 us. The first channel is used to calculate a variable called motorSpeedBase. It is the basic speed for the motors and is calculated like this:
motorSpeedBase = (vertical_pulse_time - 1500) / 2;
To control the motors I used 8 bit PWM signals, so I scaled the values to this -255 to 255 range. The MKR1000 can do better than 8 bit but it is more than good enough for these motors.
The motorSpeedChange variable is used for stirring and is calculated from the second channel. It is calculated similarly to motorSpeedBase. The difference is the division by 3 instead of 2: This difference helps to control the tank.
motorSpeedChange = (horizontal_pulse_time - 1500) / 3;
The 3rd channel is used by a single switch. It controls the movement of the crane and the hatch doors. It is calculated like this:
elevated = state_switch_pulse_time < 1500;
Its value is 1000 us when switched off and 2000 us when switched on. The result is a bool.
The final motor speed is calculated like this:
int rightMotorSpeed = motorSpeedBase + motorSpeedChange;
int leftMotorSpeed = motorSpeedBase - motorSpeedChange;
If the result is higher / lower than the maximum / minimum value then the value will be set to the max / min value (255 or -255). The related pins will be updated based on the motorSpeed values. If a speed value doesn't reach the minimum value then that motor will be disabled.
The crane and the hatch are handled by this function:
void handleCrane() {
int craneValue = analogRead(CRANE_FEEDBACK_PIN);
if (elevated) {
if (craneValue < CRANE_ELEVATED_VALUE) {
elevateCrane();
}
else {
disableTheCoils();
}
openTheHatch();
}
else {
if (craneValue < CRANE_LOWERED_VALUE) {
closeTheHatch();
disableTheCoils();
}
else {
dropCrane();
}
}
}
It starts with checking the current state of the crane. If it needs to be elevated but it isn't then it will update the hatch doors' servos and move the crane up. If it should be lowered but it isn't then it lowers the crane and then closes the hatch. The coils of the stepper motor needs to be disabled at the end of the process because they can seriously heat up and drain the battery if we leave one on.
Arduino - Raspberry Pi communicationThe Arduino is connected and powered from the Raspberry Pi with an USB - micro USB cable and they are communicating through serial. The Raspberry will control the Arduino with these commands:
- s --> switch off radio control and accept only serial commands. The Arduino will answer with 'OK' to this and it will disable radio control. This OK is a part of how the Rpi recognizes the Arduino.
- r --> turn back on radio control
- e --> elevate the crane (and thus open the hatch)
- d --> lower the crane
- m X Y -> setting the speed of the motors. X is motorSpeedBase and Y is motorSpeedChange. Both X and Y needs to be integers
- b --> the arduino will answer with an integer: battery voltage * 100
- l --> turn on lighting
- o --> turn off lighting
It needs to be noted that in case of serial control, the Arduino disables the interrupts on RC channel 1 and 2 but not on 3. Channel 3 (the switch) is used as a safety switch to disable the WalaBeer Tank if it starts doing crazy things in autonomous mode.
WalabotHere's the part where Walabot comes in. Walabot is a 3D sensor that uses microwaves for imaging. It can do amazing things like see through walls, detect your breathing from a distance, see in dark and so on. I don't want to write pages about its other capabilities because others did a great job doing that. However I really recommend reading about them.
I'll be using Walabot as the only navigation sensor on the tank. To use the Walabot with the Raspberry Pi we have to install the Walabot SDK first. You can download the SDK from here and the Walabot API site will help you install it. There are lots of useful information and examples there about how to use Walabot. I recommend checking the site.
The power consumption of the Walabot is between 0.4-0.9A. It means that by default the Raspberry Pi can't provide enough energy to power the Walabot. Luckily there's a way to increase the power output of the rpi's USB ports by adding this line: `max_usb_current=1` to the /boot/config.txt. As I know it increases the power output from 600mA to 1200mA.
That would be great but here comes a problem: I also power the Arduino and the servos from the Raspberry. The motors of the tank and the stepper motor is powered by the battery so I thought it shouldn't matter. However it does. If I start the Walabot in this condition it stops with WALABOT_ERR_PROTOCOL message. Possibly a brownout happens when I try to start it.
The battery eliminator circuit can provide up to 3A, so that is more than enough here. The Walabot has two micro USB ports. The middle port will help me in this situation because it can be powered from there while communicating on the other. To do this I had to do a modification and remove the cover of the Walabot to move this jumper
After that the Walabot worked perfectly, no more WALABOT_ERR_PROTOCOL.
The logo on the back (the smooth part is the front side) contains four very strong built-in magnets. Those were used to easily attach the Walabot to the tank's metal front without any extra hardware.
Follow meOne of the 'selling points' of the tank is its follow me mode. If you ask the beer tank to follow you, then it will do its best and follow you. Once you reached your destination you just ask for the beer inside. It is a great party trick!
The Walabot SDK provides all kinds of ways to interact with the Walabot. My project uses the getTargets function with Moving Target Identification (MTI) mode. It is used to detect moving objects in front of the Walabot. With my configuration, the getTargets will return a maximum of 4 targets and it will see objects at a maximum distance of 1,5 meters.
The targets have XYZ coordinates and an amplitude parameter. I use only Y and Z coordinates because height (X) is not important here. The problem is that there's no way to tell which target is what.
In the early version, to find the human in the targets list I created a rule: before you order it to follow you, you have to stand in front of the Walabot at an 80cm distance. After that my code assumes that the closest object with high enough amplitude is the human. If the human is detected, all the tank has to do is to keep the human in the desired position by moving.
Unfortunately it wasn't perfect. Luckily I got a suggestion for a different approach. It starts the same: you have to stand in front of the Walabot at an 80cm distance. The closest target to the tank will be considered as the human. After that, in each iteration the human's position will be the closest target to the previous position. If the distance between the new and old position would be too high then the tank won't update the human's position and it will stop. The tank will try to find the human at around the old position so if it finds the person then it will continue following him. It is a pretty straightforward idea.
Let's examine some cases on the Arena view. The goal of the tank is to keep the human in the target area (red rectangle). The blue is the closest and that is the human in these cases:
- Case 1: The human is in the target area so no movement is required
- Case 2: The human is on the right and he is too close to the tank. At first the tank will turn right then it will move away from the human by going backwards.
- Case 3: The tank doesn't need to turn but the human is too far away. It will move forward. The Walabot saw 3 targets when I made this picture
- Case 4: There is only one target in this picture and its on the left. The tank will move to the left then forward.
- Case 5: The tank will go backwards until the human is in the red rectangle.
These images are print screens of the Arena view from a slightly modified version of the Walabot-SensorTargets demo. My project doesn't need and thus doesn't have a GUI but it uses the same principals. I recommend checking out the other demo projects from their github page.
The movement with the current setup is not too fluid. It can't go forward and turn in autonomous mode at the same time. The main reason for that is the frame rate of the Walabot. It is about 6 FPS with the current settings. It means that the Raspberry gets one update in every 0.16 seconds. This is a problem. A lot can happen in 0.16 seconds. To overcome this issue I slowed down the tank. I used the minimum possible speed to move forward and to turn. I also removed the combination of turning and moving because those movements wasn't reliable with my tracked setup. At higher speeds they overshot a lot and at lower speeds they were less reliable than the current version.
Voice controlIn autonomous mode I needed a cool way to control the tank. I used Amazon's Alexa Skill Kit to do this. In the early version I used it with ngrok to directly control the Raspberry. Usually people would be using a version of the Amazon Echo to do this, but unfortunately I don't have such device. I had to use echosim and the Amazon Alexa app from Google Play to do this. The name of the skill is Beer Tank because WalaBeer is something that Alexa doesn't recognize. Buy beer, love beer, etc, but not WalaBeer. You can use these commands to interact with Alexa:
- start beer tank
- turn {on/off} the lights
- {open/close} the cargo hold
- {start/stop} following me
- [stop/cancel]
Here's a video about the first two capabilities:
Some of the voice commands in the video might differ from the current commands due to some requirements during the publishing process (e.g: 'stop' changed to 'stop following me'). Controlling a Raspberry Pi using Alexa is very easy, however to get the knowledge to do that is not. For the first time I used ngrok and it was super easy to do this but ngrok is only good for testing purposes. The URL provided by ngrok will change after every restart and there are other problems too. Long story short, I needed a better solution.
I moved on to using AWS Lambda and AWS IoT. They are perfect for my purpose but it was quite difficult to find useful information about how to use them. I mean I found lots of partial tutorials and documentation but usually they were missing some crucial information and/or just didn't work. Finally, I found the youtube channel of Kurt Braun. He made an excellent tutorial that helped me a LOT. I really recommend his videos if you want to use AWS Lambda and AWS IoT:
This other video also helped me when I did the experimenting part. I won't go into details about configuring Lambda and AWS IoT, these videos are containing every necessary information about this topic.
He used Node-RED in his videos. That is a very useful tool, however I needed to use Python instead of JavaScript. Amazon provides an SDK for Python, but I used Paho MQTT Client to make the Raspberry Pi subscribe to my 'wbt' topic's messages. It was easier for me to use.
Finally, here's a video about the current status of the prototype:
As you can see the "follow me" mode is working quite well, but the tank is very slow in this mode. Possibly it is capable of slightly higher speeds but I wanted to be sure that it doesn't do crazy things. Slowing the tank down was needed because at higher speeds it can easily lose me, mostly when it is turning. I've got a couple of ideas how I can significantly increase the speed in "follow me" mode but it will take some time and possibly some extra hardware to implement a solution for that.
You can access my skill here and this is its id:
amzn1.ask.skill.a7453502-b1aa-47fa-a552-ed8e2c792b2e
If you want to publish your skill it might be a good idea to you authentication to differentiate the devices. For that follow this great tutorial.
CanceledI'd like to write some words about another part that is on the "Most of the electronics are integrated onto the top part" image. I'm talking about these:
These are tachometers. I didn't use them in the final version, but they are still there.
A tachometer like this is made of two parts: a black and white paper on the main wheel and a reflective IR sensor in front of it. The reflected light depends on the color of the object. The difference is very big so distinguishing the states is very easy and thus you can easily calculate the speed of rotation. The only problem of this setup is the low sample rate in case of slow movement, however they work quite well on higher speeds.
The tachometers worked great, but I realized that I don't need them for the project and I also needed the GPIO pins on the Arduino for other purposes. This is their story.
ConclusionThe end result is great, useful and fun! It is also a good platform for other future projects. With hard work I managed to make the voice control work and Walabot proved to be a great sensor for this purpose, too. I see numerous ways to improve this tank so it is likely that you'll see more about it in the future!
This is my best and most successful project so far. And also the longest. To keep it from getting even longer I'd like to thank for all the help that I got and I also thank you for reading! As a prize here's a picture about a strange dog:
Comments