FruitBot Help Page
From startup to shutdown. This page covers the ins and outs of FruitBot.
FIRST CONNECTION
We will start simply with on and off.
To turn FruitBot ON, start by flipping the rocker switch to the right of the EGO battery. Next, connect the blue spade and prong at the front of the robot, tucked in to the left of the Raspberry Pi. The system should be ready in less than one minute.
To turn FruitBot OFF, press the Red button to the left of the Raspberry Pi. This will send a signal to start the shutdown process. Wait for the blue LED to turn off, then wait another 10 seconds before disconnecting the blue spade and prong connection. Once the Raspberry Pi is off, you can switch off the power in back to the right of the EGO battery.
To get 'under the hood' of FruitBot we will use several techniques to monitor and control the software and hardware. SFTP can be used as file sharing to review and edit the Python and Arduino code to manage all aspects of the robot. The Mac Terminal can be used to SSH into the Raspberry Pi device for live control. From there, you can update the Arduino .ino files and send them to either of the Arduino boards using arduino-cli.
SSH keys are used to log into Raspberry Pi so passwords are not needed. Below is the Terminal code that will copy your public SSH key over to FruitBot.
cat ~/.ssh/id_rsa.pub | ssh pi@fruitbot.local 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'If copying the SSH key fails, you may have to setup an SSH key pair for yourself.
- On the client computer, make the hidden directory '.ssh' in the user folder, -p = if needed & without error message
mkdir -p ~/.ssh- move into the directory and generate a key pair
cd ~/.ssh && ssh-keygen -b 1024 -t rsa -f id_rsa -P ''- Make sure you are disconnected from the host, then copy your local public key to the server.
cat ~/.ssh/id_rsa.pub | ssh administrator@server2.example.com 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'- Type 'yes' if asked about a fingerprint.
- Enter the server password.
- The mkdir command is included in the key copy command to make the .ssh folder on the host computer if necessary.
To take control of the software that runs FruitBot, start by connecting to the Raspberry Pi using SSH.
ssh://pi@fruitbot.local
When you first login, you should be met with a VERY simple menu that allows you to quickly perform some basic tasks. This is the run by the 'menu.sh' file, and launches using the .bashrc config file. Modify the .bashrc to turn off the menu, and modify the menu.sh file to change the menu commands.
GENERAL
Robot Web Control interface.
http://fruitbot.local:5020/
UV4L Streaming Video.
https://fruitbot.local:8080/
There are some personal conventions I tend use in the code (inconsistently). Global variables start with 'v', local variables start with 'w' and functions start with 'fn'. This helps me distinguish language developed in code vs. functions that are part of the language. I have not memorized the list of functions for all the programming languages I use. Arduino code is indented with spaces, since that's what the Arduino IDE prefers, and everything else is indented with tabs. For files with lots of code, there should be a table of contents at the top. I use that to quickly copy a function name and search for it to jump to a section. Most comments and references have been moved to the bottom of the file. I am an experienced developer, so I do not rely on any cloud services, all support code has been loaded locally.
When booting up, it takes about 60 seconds for the FruitBot web page to be available. It used to be much faster (~20 seconds), but I installed some GUI tools to allow a locally connected display to be used for map navigation. That increased the startup time quite a bit.
To turn off FruitBot, use the power switch to turn off main power from the EGO battery. RPi monitors 5V power on GPIO 22, and when main power is turned off, RPi waits for 1 minute, than runs the shutdown process. If main power is turned back on before the minute is up, shutdown is cancelled.
This is a differential drive stem, with tow motors connected to two wheels. Turning is achieved by applying different speeds to different wheels. In the code, a spin is defined as one wheel forward and one wheel back. An even amount of space is needed all around the robot for the spin to work. A turn is defined as one wheel moving twice as fast as the other. No room is needed on the left when turning right, so a turn is useful when the robot is sitting against a wall and needs to move without scratching the wall. Not scratching the walls was an important factor in the build of this robot.
After 5 minutes of inactivity, ItsyBitsy will switch to low power mode. All the lights switch to a dim red and the system slows down to save power. Send any command to wake it up again. To prevent FruitBot from going to sleep, turn the headlights on or off. FruitBot can only go to sleep when the headlights are set to automatic.
Anyone can take manual control of the robot by using the joystick found near the back. Press the joystick down once to activate it. Press again to deactivate. To shift up one gear, double-click the joystick. Once in top gear, click once more to shift back to the bottom. Having the joystick on does interfere with regular navigation, so turn it off when done. The joystick is NOT tied in to any of the sensors, so it can run into walls and fall down the stairs when using the joystick.
Shutdown button is GPIO 17 connecting to ground. This is controlled by the 'shutdown_button.py' script that runs on boot. This script also monitors the main power source on GPIO 22. If the main power is turned off, a timer starts for 1 minute then shuts down the RPi. If power is restored before then, the shutdown is cancelled. To modify the shutdown script's boot process, edit the rc.local file.
sudo nano /etc/rc.localTo modify code, you can use SFTP as a form of file sharing.
sftp://pi@fruitbot.local
CyberDuck is a popular open-source SFTP client for Mac and Windows. It has been around since 2002. You can download it with the link below.
https://cyberduck.io/
Check the log file to find any problems with the Python program. The log file also records data received from the Arduino boards every 5 minutes (300 sec) controlled by a variable at the top of app.py.
cat ~/static/webserverlog.txtAlso, check the system log file to find any errors.
grep error /var/log/syslogor
tail /var/log/syslogCheck the kernel log for any hardware problems.
dmesg | tailRobot Web Control interface is run by a systemd service. Use these commands to control fruitbot service.
(sudo) systemctl status fruitbot - Restart the service to apply any code changes, 'sudo' is optional for status.sudo systemctl restart fruitbot - Stop stops until next reboot.sudo systemctl stop fruitbotsudo systemctl start fruitbot - Disable prevents fruitbot from launching on boot.sudo systemctl disable fruitbotsudo systemctl enable fruitbotModify fruitbot systemd service.
sudo nano /etc/systemd/system/fruitbot.serviceComponents of the service.
[Unit]
|
|
See if a Python script is running in the background.
ps -aux | grep pythonIf a script is running in the background, you can kill the process by calling the script name.
pkill -f app.pyTo test the fruitbot script, stop the process using systemctl (above) then start the script manually.
python3 app.pyCheck to see if sensors are connected on the I2C port.
i2cdetect -y 1Should return something like this:
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- 1f
20: 20 21 -- -- -- -- -- -- -- 29 -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 69
70: 70 -- -- -- -- -- -- -- See next section for I2C Address Assignments
The CUPS printer driver service has been installed, but is not running because it tends to use 100% of a CPU while idle. This can be turned on again as needed.
sudo systemctl start cups
sudo systemctl stop cups
sudo systemctl enable cups
sudo systemctl disable cups
USB
List all USB devices.
lsusbResult:
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 004: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP2102/CP2109 UART Bridge Controller [CP210x family]
Bus 001 Device 003: ID 239a:802b
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Metro Mini = Cygnal Integrated Products
Arduino boards are connected to RPi through USB so they can be updated directly from the command line. When a board is updated, the USB connection may change. For example if IB was on '/dev/ttyACM0' it could now be /dev/ttyACM1' after update. Restarting app.py should fix that issue because it checks multiple ports when starting. You'll have to change the corresponding part of the CLI command on the next update too.
./bin/arduino-cli compile -b arduino:avr:uno /home/pi/Arduino/FruitBot_NewPing && ./bin/arduino-cli upload -p /dev/ttyUSB0 -b arduino:avr:uno /home/pi/Arduino/FruitBot_NewPing./bin/arduino-cli compile -b adafruit:samd:adafruit_itsybitsy_m4 /home/pi/Arduino/FruitBot_Sabertooth && ./bin/arduino-cli upload -p /dev/ttyACM0 -b adafruit:samd:adafruit_itsybitsy_m4 /home/pi/Arduino/FruitBot_SabertoothOther Arduino commands:
./bin/arduino-cli board list - shows a list of connected boardsResult:
/dev/ttyACM0 Serial Port (USB) Adafruit ItsyBitsy M4 (SAMD51)
adafruit:samd:adafruit_itsybitsy_m4 adafruit:samd
/dev/ttyAMA0 Serial Port Unknown
/dev/ttyUSB0 Serial Port (USB) Unknown
Metro Mini = /dev/ttyUSB0
./bin/arduino-cli board listall - shows a list of all compatible boardsWhen uploading new code to an Arduino unit, you may experience communication problems afterward. This is probably because the board has changed ports (from ttyUSB0 to ttyUSB1 or from ttyACM0 to ttyACM1). All you have to do is restart the FruitBot service, and it will pickup the new port.
sudo systemctl restart fruitbot
VIDEO CAMERA
Verify the camera is attached and working. You should get something like: '/dev/video0'.
ls /dev/video*Show information about the camera.
ls -l /dev/video0Take a picture.
raspistill -o cam.jpgRecord a 7 second video
raspivid -o video.h264 -t 7000Control UV4L streaming webcam (service and systemctl are interchangable commands, just swap the positions of the action and module).
sudo service uv4l_raspicam status-OR-
sudo systemctl status uv4l_raspicamsudo service uv4l_raspicam restartsudo service uv4l_raspicam stopUV4L control panel.
https://fruitbot.local:8080/panelModify UV4L configuration. This controls the webcam.
sudo nano /etc/uv4l/uv4l-raspicam.confUV4L configuration can also be modified from this password protected web page.
https://fruitbot.local:8080/configuser: configpass: mypwModify UV4L service.
sudo nano /etc/systemd/system/uv4l_raspicam.serviceRESOURCES
Make an Autonomous "Follow Me" Cooler by Aaron Tainter (atainter) 2017 or on GitHub - The 'Follow Me Cooler' was the inspiration that started the FruitBot project. Unfortunately, GPS navigation is only accurate to a city block, so indoor navigation needed different resources.
Drawing Route For Car On The Office's Map - This project provided the indoor navigation possibilities I needed. They used a totally Arduino solution. I opted for a combination of Raspberry Pi and Arduino to leverage the WiFi hardware and server software capabilities already found in the RPi4.
How to Make an Object Tracking Robot Using Raspberry Pi by Automatic Addison 2019 - This was one of my early prototypes. It was easy to build, and worked quite well. FruitBot might be able to follow a person based on the color of their clothes that day. Addison's articles are very clear and easy for me to understand. He also has some good obstacle avoiding robot articles. Fari warning, some articles get very heady very quickly, so brace yourself.
DIY Web Controlled Raspberry Pi Surveillance Robotic Car 2017 - Sets up the live webcam using Motion. This was very easy to set up. But I eventually moved to UV4L software for its low latency and peer-to-peer WebRTC services.
Build a Robot Car with Speed Sensors by DroneBot Workshop 2017 - Deals with the TT motor encoders and optical interrupt sensors. After testing with the TT motors, I switched to stepper motors for better control. Then I got the Power Wheels gearboxes with RS 550 motors for the final FruitBot v1 drive motors. If the project goes well, I may switch to hub motors (like from an electric skateboard) because they are powerful and quiet.
Pathfinding Visualizer by Abdallah Hemdan 2020 or on GitHub
A* (AStar) Search Algorithm in JavaScript by Brian Grinstead (bgrins) 2015 or on GitHub
A* (AStar) Search Algorithm in JavaScript by Brian Grinstead (bgrins) 2015 or on GitHub
Control of Mobile Robots
by Dr. Magnus Egerstedt and Jean Pierre de la Croix
from Corsera 2013
This is how the primary navigation functions were developed. It employs activity states like go-to-goal, avoid-obstacle, and follow wall to make it to its destination. A 'state machine' is used to switch among the techniques until the goal is reached.
http://pysimiam.sourceforge.net
55 video lessons - https://www.youtube.com/playlist?list=PLp8ijpvp8iCvFDYdcXqqYU5Ibl_aOqwjr
To run the simulator, you need Python 2.7 and PyQt4. Old software can be hard to find and even harder to install properly. The best way for PySimiam is to download the full Anaconda 3 virtual machine and install some of the included libraries https://repo.anaconda.com/archive/Anaconda3-2.4.1-MacOSX-x86_64.pkg
- Removed 'conda' lines from ~/.bash_profile
- Left the two Anaconda3 2.4.1 lines.
- deleted the folders ~/opt, ~/.conda, ~/.continuum but left the ~/.condarc file alone.
- reloaded bash profile
source ~/.bash_profile
- now conda is v3.18.8
- looks like pyqt4 is available
- creating new environment
conda create -n pysimiam python=2.7
source activate pysimiam
conda install numpy sip pyqt=4 --use-local
- install seemed to work
python qtsimiam_week1.py
- WORKED!! (I think)
Sobot Rimulator by Nick McCrea - Nick upgraded the code to Python 3, replaced the QtPy4 GUI with Gtk3, and uses a Khepera III robot instead of a QuickBot.
https://www.toptal.com/robotics/programming-a-robot-an-introductory-tutorial
pysimiam_simulator by Delijati (2014)
https://github.com/delijati/pysimiam-simulator
Path Tracking With PID Controller Simulation for Differential Drive Robots in Python by BurakDmb (2019). This is a very simple simulator, but it deals with PID, one of the foundation pieces for the 'Control of Mobile Robots' course. Requires scipy.
https://github.com/BurakDmb/DifferentialDrivePathTracking
Rahul-Ratheesh released his version of PySimiam (2019)
https://github.com/Rahul-Ratheesh/pysimiam
- It has been updated for Python3 and PyQt5.
- Downloaded and tried to run with Python3 on TouchMBP.
- Error - cannot import name 'clock' from 'time'.
- seems clock was depreciated in python 3.3
- Open the 'scripts/simulator.py' file and delete clock import from
Hopefully, some useful docs.
FruitBot ItsyBitsy M4 circuit.pdf
FruitBot Metro Mini circuit.pdf
FruitBot Power diagram 2021-10.pdf
FruitBot RPi GPIO circuit.pdf
| GPIO pins | Description |
|---|---|
| 2 & 3 (I2C) | NXP Compass, Servo HAT, VL53 Laser cliff sensor, GPIO Expander |
| 4 | Reset ItsyBitsy |
| 5, 6, 12, 17, 18, 19, 20, 21 | Voice Bonnet |
| 13 | 3 watt LEDs |
| 14 & 15 (UART) | MakerFocus UPSpack V3P battery board |
| 16 & 25 | GPIO Expander interrupt signals |
| 17 | Shutdown Button (shared with Voice Bonnet) |
| 22 | Reset VL53 Laser cliff sensor |
| 23 | Monitor main power from servo HAT for auto-shutdown |
| 24 | Reset NXP compass |
| 7, 8, 9, 10, 11, 13, 26, 27 | AVAILABLE |
| I2C Addresses | Description |
|---|---|
| 0x1A or UU | Voice Bonnet |
| 0x1F | NXP 9DoF Accelerometer, Magnetometer |
| 0x20 | GPIO Expander Bonnet |
| 0x21 | NXP 9DoF Gyroscope |
| 0x29 | VL53L0X laser distance cliff sensor |
| 0x40 & 0x70 | Servo HAT |
| Ultrasonic Connections | |||||||||
|---|---|---|---|---|---|---|---|---|---|
| — | FR | BR | BM | BL | FL | FM | ML | MR | — |
The ultrasonic connection configuration assumes the top of the robot is upside-down and you are looking at the pins from the back of the robot. A copy of this table should be affixed near these connections as well.
Ultrasonic range is set in the Arduino code to 3cm minimum and 400cm maximum.
These instructions assume you are connected to FruitBot throught the SSH terminal.
- Check the last 10 lines of the kernel log for anything odd.
dmesg | tail
- Show medium problems, the -T option adds timestamp.
dmesg --level=err,warn -T
- Check the log file to find any problems with the Python program. The log file also records data received from the Arduino boards every 5 minutes (300 sec) controlled by a variable at the top of app.py.
cat ~/logs/webserver.log
- Check the system log for errors.
grep error /var/log/syslog
If the live video feed is not working, try these steps.
- Check to see if the original UV4L feed is working.
https://fruitbot.local:8080/stream
- Verify the camera is attached and working.
ls /dev/video*
- You should get something like: /dev/video0.
- Take a picture.
raspistill -o cam.jpg
- Check UV4L status.
sudo service uv4l_raspicam status
sudo service uv4l-webrtc status
- Use the 'top' command to see which apps are using the most CPU and memory.
top
- Stop the video streaming service if necessary.
sudo service uv4l_raspicam stop
- Make sure the I2C devices are visible.
i2cdetect -y 1
- I2C communicates with:
0x1A or UU - Voice Bonnet
0x1f & 0x21 - NXP board (accelerometer, gyroscope, magnetometer/compass)
0x29 - VL53L0X (laser distance cliff sensor)
0x40 & 0x70 - Servo HAT
- Make sure the SSL certificate is up-to-date. Look for the 'Not After' date.
openssl x509 -text -in /etc/ssl/certs/FruitBotCert.pem -noout
- Raspberry Pi stats
https://www.raspberrypi.org/documentation/computers/configuration.html#firmware-warning-icons
CPU Load - RPi4 has four cores, so 1 (100%) is not the maximum for the system. RPi Zero has only one core, so 1 (100%) is the max for that.
CPU Temperature - 55C is typical indoor core temperature. 80-85C shows a warning. Over 85C means the system will throttle back to protect itself. Without a fan, the small 14mm heatsink can drop 5 degrees Larger 25mm heatsink can drop 20 degrees.
Core Clock - RPi4 core clock is 500000992.
Core Volts - RPi4 core volts is 0.89V.
Throttling - Any messages here mean problems for performance and/or RPi longevity.
- Compass Offset Values
If one or more of the compasses are pointing in the wrong direction, the first thing to do is to calibrate them. On the Controls screen, switch to the Compass tab and click 'Calibrate Compass' The robot will turn in circles until calibration is complete.
If the Compasses are still not correct, you can force the direction of the pin by adding or subtracting degrees using the Compass Offset Value fields on the Console page.
MAP RULES:
Yellow cells are obstacle cells positioned on top of walls and
furniture. This is the maze the robot must navigate around.
HTML span must be formatted like this: <span class='node empty' id='cell_1_20'></span>
Class first, then ID. ID should have X coordinates,
then Y coordinates both starting at zero.
Start must be class='node start' not class='node empty start'.
Goal must be class='node goal'.
In my version of this maze solver, once the goal is reached,
it becomes the new start point. My version also has hard-coded
obstacles representing walls and furniture in the home map.
AStar.findPath is the call that produces the solution.
The outputGridAs2DArray function turns the HTML grid into a
numeric array of arrays for AStar like this.
[[1,0,3,0],
[0,0,0,2],
[3,3,0,0]]
- It says, starting at 0,0 (first value in the upper-left corner)
find a path to 3,1 (4th column, 2nd row). Remember numbering starts
at zero, not one. If you imagine the zeros as flat space and the
threes as block columns, you can kind of see a representation of
the map in the numbers.
0 = empty
1 = start
2 = goal
3 = obstacle
AStar returns an array with cell coordinate objects for a path that looks like this.
[{"x": 0, "y": 1},
{"x": 1, "y": 1},
{"x": 2, "y": 1},
{"x": 3, "y": 1}]
- It says, starting at 0,0 (not given in the results) go down
one cell (Y + 1) and right 3 cells (X + 1 + 1 + 1).
The apartment map table is 25 x 43 cells. Each cell represents 8".
Each wood square of our apartment floor is 9" square.
There are 20.5 squares across the living room (east-west).
20.5 * 9 = 184.5" or 15.4'
Grid is 25 squares wide - 2 for each wall = 23 squares
184.5" / 23 squares = 8" per square
There are 25 squares + 7" through the living room (north-south)
starting at the edge of the stairs.
25 * 9 + 7 = 232" or 19.3'
232 / 29 squares = 8" per square