Search This Blog

Monday, June 19, 2017

Bot, my personal pet robot

It has been about a two months since I started writing to my blog again after may be 2-3 years. I wish to continue writing from now on. So, today I post about my personal pet robot, Bot.
I first started working on my personal robot about probably a year and a half ago. I wanted to make a robot which I can use for various experiments and of course I have a dream of having my own pet robot. The picture posted here is the latest revision of the robot. It has undergone three revisions due to various issues and my personal preferences.

Latest revision of Bot. Yeah,its untidy. But I still love it.

The first Bot only had an ESP8266 as a its brain. That was only used for an OpenCV experiement. Later on I bought another chassis with two wheels and encoders. But That platform turned out to be unstable and the motors were of bad quality.
Bot rev. 2.0 had a raspberry pi 2 as its brain and an Arduino UNO for more "realtime" things like controlling the motors,taking battery voltage reading and acquiring data from IMU etc. I also added a Raspberry pi NoIR camera and a dot matrix display as its face. 
Here is a video of that robot smiling when it saw a ball,
This was just a basic color based object tracking demo. After facing numerous stability issues and lack of space, I gave up that platform and finally bought the current chassis you can see in the previous photo. It has two motors built in.
This chassis is great as it doesn't overspeed and both motors rotate almost at the same rate. Now my objective was to make it go in a straight line.As this chassis had no encoder, I had to use an MPU6050 IMU.
This Intertial Measurement UNIT has a 3 axis accelerometer and a 3 axis gyroscope and is an excellent bargain for $2-$3(in my country). Now,in order to move in a straight line, the robot must keep its yaw angle constant. Now we all know that accelerometers can't measure yaw angle and gyros have a drift problem, which means they tend to drift and therefore for the same orientation, their reading changes. So I would need a magnetometer. Fortunately, MPU6050 has a built in digital motion processor which runs some sort of weird and wonderful low pass filtering algorithm that keeps the yaw angle stable enough(note this enough) even without help from a magnetometer. 
The arduino runs a simple nested if...else... to keep itself steady when going straight or steering 90 degrees. I could have used PID there, but this if else seems to be working so didnt.
Then comes another problem. This robot runs on a 7.4V 800mAh lipo battery. Battery voltage is not a constant thing.When you charge it, it goes up to a value. When you use it, the voltage drops. As a result, the minor speed tweaking of the two motors of our differential drive system doesnt work anymore and the robot canoot correct its orientation properly or turn efficiently etc.
Now this issue can be solved in many ways like taking voltage reading and adjusting calibration accordingly in the code. But I did something that is not very efficient but easy. 
I connected a boost converter followed by a buck converter between battery and motor driver. The boost converter boosts the voltage to about 9V and then the buck converter converts it to about 8 volts, at which I did my tweaks.That way the voltage remains pretty much constant but since nothing is free in our world, I lose efficiency that means my battery runs out faster but thats okay for now.
Dusty, very very dusty. On the left are the power input cables for motor driver and on the right are the battery cables 

Now let's take a look at the brain, the raspberry pi 2. It is running raspbian jessie. Its a great sbc for community support etc. but not powerful enough to do anything beyond very basic image processing. So when I work with image processing things with this robot. I usually stream video from the pi over wifi and use opencv on PC to process the stream. 
The following link contains an excellent set of instructions on how to do this.
Reducing image size or 320x240 resulted in a near instant streaming with almost zero lag,but we are using wifi dongle, so sometimes it suffers some lag.
I am working on adding autonomy but for now,I use it as a remote controlled car to test its driving performance etc. This is a very slow project as I work on it maybe once a week or month. But work is progressing and I hope it will be done someday.
I wanted to implement a ROS based control environment for this robot. So I installed ROS in raspberry pi following the instructions at ROS website.
After initializing etc. if you want to connect your pi to your PC,then change the ROS_MASTER_URI environment variable in pi to your PC ip address.
run these commands
nano ~/.bashrc
then at the end of that file. Paste the following,
export ROS_MASTER_URI="http://:11311"
then close nano by pressing Ctrl+x->y->Enter
run source ~/.bashrc
Now, you can run roscore in your pc and the pi will talk to it.  
Right now, I am working on ROS integration. will post more when its done.
My ultimate goal is to make a robot that can move between rooms and find the caller. It may also notify me about important emails and things. It has a speaker. I shall add a microphone. I added one but the audio reception was really bad.
If any of you are wondering about the laser beside the camera, I used it to implement a laser rangefinder using image processing. I shall post it soon.   

Tuesday, April 25, 2017

An attempt to make a minimal busybox rootfs with glibc dropbear and wpa_supplicant on Orange pi zero Part1

This blog post and anything that comes after this and is related to this is probably gonna be less like a tutorial and more like an attempt to keep a record of whatever I am doing/did as I have found the steps forgotten pretty much every time I tried repeating them.

Okay,lets get started. I love single board computers. I have various ones(mostly from China). I was formerly working in an R&D company and I was doing basic linux image building using various build systems there. Now,up untill a few days ago,I was quite happy with the build systems available but then I saw a wonderful video on how someone managed to boot linux with busybox in just 1 frigging second! Here is the video,  

That got me thinking, hmm ,lets try that! First I will try to create a very basic filesystem and boot and will also enable wifi. Fast booting is for later experiments.
I chose Orange pi Zero as my guinea pig as I am playing with that board now.Its a pretty nice board with an Allwinner H2 quad core processor,512MB RAM and 10/100 ethernet and wifi! It costs about $6.99 in aliexpress(mine was twice as much as I bought it from a local source).
Alright,so the first step was to boot obviously.So,I downloaded the latest u-boot source and tried to build it for orange pi zero(u-boot has defconfig for this board so I didnt have to write my own) and volla! it failed. It was a gcc issue.I am running Ubuntu 16.04 and the default gcc version is 5.4.0(same for the arm-linux-gnueabihf-gcc I used) and u-boot and linux build for Allwinner boards doesnt go well with that. 
Then after some other random attempts,I tried another weird idea. I saw this link where they ran OpenWrt on that board using kernel and u-boot from Armbian build system.

So I thought,lets try it this way first.But, my requirement is a very basic filesystem with thing that I need only.For now, that is just wifi and dropbear with scp support.Now I am using u-boot and kernel from Armbian with all the drivers(I will load whatever I want).

For doing most of the steps,a linux system is needed. You can try linux in VirtualBox or VMWare if you are in Windows. For some of the super annoying problems, even I had to switch to a 32bit ubuntu server VM image as my 64 bit Ubuntu was throwing errors during some builds.
Note: use sudo if you see permission denied.
so here are my steps.
  1. Download/build an armbian ubuntu xenial headless image(kernel 3.4.113 for now). Armbian website has very nice download page for each of the single board computers they support.The Legacy one was the choice here.I will try the mainline one too.
  2. Write that to SD card.Now you have a nice Armbian filesystem with u-boot and 3.4.113 legacy kernel.
  3. Now delete everything there except boot and lib folder. Inside lib folder, you can delete everything except modules and firmware folders.
  4. Now time for some build operations. First some prerequisites.Some of them may not even be prerequisites, but I am still including them anyway.Note that these may not contain everything you need.So if an error comes like no such file bla bla bla,feel free to google.Now,open up a terminal and type,
    sudo apt-get install build-essential gawk autoconf libncurses5-dev git libssl-dev crossbuild-essential-armhf
  5. Once we are done with that. its time to build busybox. Its a set of many useful linux tools. Some of the version selections etc might look weird but its basically a compilation of things I scavenged from the internet.
    tar -xjf busybox-1.24.1.tar.bz2
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- defconfig
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- install
          It then copies the files to _install folder in the busybox directory. Now we copy it to SD card. probably we could have copied it in the last command by specifying CONFIG_PREFIX.
    Now run,
    sudo rsync -a _install/ /path/to/sd/card

    This copies the contents of _install to SD card with proper permission.
  6. We are almost done on that.Now time to do some finishing touches.
    cd /path/to/sd/card
    mkdir proc sys dev etc
    sudo mknod dev/console c 5 1
    (note the missing / before dev.we are not working on our PC filesystem dont put a / before anything unless specified here)
    sudo mknod dev/null c 1 3
    Now we create the inittab file where we specify what to load during boot
    gedit etc/inittab (add sudo if says permission denied)
    copy paste the following
    null::sysinit:/bin/mount -t proc proc /proc
    null::sysinit:/bin/hostname -F /etc/hostname
    null::respawn:/sbin/getty -L ttyS0 115200 vt100
    null::shutdown:/sbin/umount -a -r
    Save and close
    mkdir root
    gedit etc/passwd

    copy paste the following
    Save and exit
    gedit etc/shadow
    copy paste
    Save and exit
    mkdir -p usr/share/udhcpc
    cp /path/to/busybox_src/examples/udhcp/simple.script usr/share/udhcpc/default.script
    gedit etc/hostname
  7. Now we make glibc which is used by various programs.
    tar -xJf glibc-2.22.tar.xz
    mkdir glibc-build
    cd glibc-build/
    ../glibc-2.22/configure arm-linux-gnueabihf --target=arm-linux-gnueabihf --build=x86_64-pc-linux-gnu --prefix= --enable-add-ons
    make install install_root=/path/to/sd/card
    If you get error like LD_LIBRARY_PATH should not contain current directory etc. during configuration, run
    then run configure again. 
  8. Now that everything is done,Open up a terminal in ur sd card folder and type sync.
Now remove the SD card and put it in your Orange pi Zero SD slot. Attach a USB-serial to it and fire up your favorite terminal emulator(picocom in my case). Power the Orange pi and you should see something like this.  
U-Boot SPL 2017.03-armbian (Mar 16 2017 - 14:23:25)
DRAM: 512 MiB
Trying to boot from MMC1

U-Boot 2017.03-armbian (Mar 16 2017 - 14:23:25 +0600) Allwinner Technology

CPU:   Allwinner H3 (SUN8I 1680)
Model: Xunlong Orange Pi Zero
DRAM:  512 MiB
*** Warning - bad CRC, using default environment

Setting up a 720x576i composite-pal console (overscan 32x20)
Error: no valid bmp image at 66000000
In:    serial
Out:   vga
Err:   vga
Net:   phy interface0
eth0: ethernet@1c30000
Hit any key to stop autoboot:  0
6944 bytes read in 159 ms (42 KiB/s)
switch to partitions #0, OK
mmc0 is current device
Scanning mmc 0:1...
Found U-Boot script /boot/boot.scr
1884 bytes read in 147 ms (11.7 KiB/s)
## Executing script at 43100000
115 bytes read in 123 ms (0 Bytes/s)
5156878 bytes read in 633 ms (7.8 MiB/s)
4754656 bytes read in 620 ms (7.3 MiB/s)
Found legacy kernel configuration
35384 bytes read in 487 ms (70.3 KiB/s)
## Loading init Ramdisk from Legacy Image at 43300000 ...
   Image Name:   uInitrd
   Image Type:   ARM Linux RAMDisk Image (gzip compressed)
   Data Size:    5156814 Bytes = 4.9 MiB
   Load Address: 00000000
   Entry Point:  00000000
   Verifying Checksum ... OK
   Loading Ramdisk to 49b15000, end 49ffffce ... OK

Starting kernel ...

[sun8i_fixup]: From boot, get meminfo:
    Start:    0x40000000
    Size:    512MB
ion_carveout reserve: 160m@0 256m@0 130m@1 200m@1
ion_reserve_select: ion chipid  [0x2c00042!
ion_reserve_common: ion reserve: [0x57e00000, 0x60000000]!
Loading, please wait...
starting version 229
Begin: Loading essential drivers ... done.
Begin: Running /scripts/init-premount ... done.
Begin: Mounting root file system ... Begin: Running /scripts/local-top ... done.
Begin: Running /scripts/local-premount ... Scanning for Btrfs filesystems
Begin: Will now check root file system ... fsck from util-linux 2.27.1
[/sbin/fsck.ext4 (1) -- /dev/mmcblk0p1] fsck.ext4 -a -C0 /dev/mmcblk0p1
/dev/mmcblk0p1: recovering journal
/dev/mmcblk0p1: clean, 4787/89584 files, 89637/358144 blocks
Begin: Running /scripts/local-bottom ... done.
Begin: Running /scripts/init-bottom ... done.
mount: mounting /run on /root/run failed: No such file or directory

testboard login: root
login[151]: root login on 'ttyS0'
~ #
Right now some errors are there and we will fix them.Right now the boot time is about 9 seconds from boot to console login.
References used: