NezaRobot Power supply:
1) Input: +12VDC
2) Output:
a: +3.3V (ez430 board, CAN bus)
b: +5.0V (BBB board)
c: +6.0V (Servos)
d: +12.0V (Motors)
Sunday, September 20, 2015
Monday, September 14, 2015
NezaRobot H/W: ez430 - CAN bus board
Figure 1: CAN Bus of ez430 schematic
As showed above figure, MCP2515 is a stand-alone CAN controller with SPI interface. ez430 connects to MCP2515 through SPI interface to put in CAN bus devices to send and receive command to/from BBB board. MCP2515 supports CAN V2.0B at 1Mb/s.
MCP2515 output is TTL (+3.3V) level, a transceiver is required to convert TTL level to CAN bus standard. I use SN65HVD230, it is 3.3V CAN transceivers.
Figure 2: ez430 and CAN Bus board
ez430 board is used to control 2 motors, speed and direction through CAN bus connected to BBB board.
Sunday, September 13, 2015
NezaRobot HW: BBB board connection
In NezaRobot, I only use BBB to control 6 servos and 1 CAN bus and USB WIFI.
6 PWM:
ehrpwm0A-0B, 1A-1B, 2A-2B, 3 groups PWM timer.
1 CAN Bus:
CAN bus needs a converter to convert +3.3V level to CAN bus standard.
1 serial port:
It is for debugging
Other pins are not used.
I use KiCAD for draw electronic schematics. It is open source and free.
From above figure, BBB has +5.0VDC connector, 1 USB WIFI, Serial port, CAN Bus, 6 PWM servo controllers.
Thursday, September 10, 2015
BBB: Kernel - CAN Bus support
BBB board has two CAN bus, can0 is enabled by default. For NezaRobot, one CAN bus is enough. It is used to communicate to ez430 board to send out motor control command.
Oscillator of BBB CAN bus clock used is 20MHz, but I can't find the same frequency oscillator, before I have one board from other project which oscillator is 12.288MHz, no matter what register to configure, it is very difficult to match with 20MHz, communication sometimes is lost, finally I found one 24MHz oscillator from my old video card. Then configure CAN bus register, both are exactly matched.
#enable CAN device
echo BB-DCAN1 > /sys/devices/bone_capemgr.9/slots
#configure bitrate to be 300Kbps
./canconfig can0 bitrate 300000
#network up
ifconfig can0 up
Oscillator of BBB CAN bus clock used is 20MHz, but I can't find the same frequency oscillator, before I have one board from other project which oscillator is 12.288MHz, no matter what register to configure, it is very difficult to match with 20MHz, communication sometimes is lost, finally I found one 24MHz oscillator from my old video card. Then configure CAN bus register, both are exactly matched.
#enable CAN device
echo BB-DCAN1 > /sys/devices/bone_capemgr.9/slots
#configure bitrate to be 300Kbps
./canconfig can0 bitrate 300000
#network up
ifconfig can0 up
Wednesday, September 9, 2015
NezaRobot H/W: H-Bridge motor control
H-bridge is a standard method to control DC motor. P4 controls direction, and P10 is PWM from microchip to control motor speed.
Thursday, September 3, 2015
BBB: Kernel - USB WIFI support
At NezaRobot, BBB will communicate with smart phone to receive object detection information, such as ball and goal location.
BBB has one USB port, I insert it with a USB Wifi, it happens to be rt2800 which Kernel support this.
After compile Kernel and driver, you can copy following drivers and install them after reboot. You can put following commands into one script.
#install all necessary drivers
insmod rfkill.ko
insmod cfg80211.ko
insmod mac80211.ko
insmod lib80211.ko
insmod rt2x00lib.ko
insmod rt2800lib.ko
insmod rt2x00usb.ko
insmod rt2800usb.ko
#like eth0 is ethernet, wlan0 is for Wifi
ip link set wlan0 up
#turn off power save, otherwise it is not stable
iw dev wlan0 set power_save off
#read configure file and set user name, password to your home Wifi server
wpa_supplicant -B -D wext -i wlan0 -c /etc/wpa_supplicant.conf
#you can scan your Wifi server now
#iw dev wlan0 scan | grep SSID
#ip addr show wlan0
#ip link show wlan0
iw dev wlan0 link
#my home router is 192.168.2.1
ifconfig wlan0 192.168.2.77 up
configure file:
vi /etc/wpa_supplicant.conf
ctrl_interface=/var/run/wpa_supplicant
network={
ssid="BELL647"
proto=WPA2
pairwise=CCMP
group=CCMP
key_mgmt=WPA-PSK
#psk="password"
psk=generated 64 hex
}
psk is generated by wpa_passphrase tool. For example, my router ssid is BELL647, password is 12345678
wpa_passphrase BELL647 12345678
Save file, reboot, run above script, Wifi should work.
ifconfig:
root@beaglebone:~# ifconfig
can0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
UP RUNNING NOARP MTU:16 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:10
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interrupt:71
eth0 Link encap:Ethernet HWaddr C8:A0:30:AC:87:22
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interrupt:56
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:20 errors:0 dropped:0 overruns:0 frame:0
TX packets:20 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1760 (1.7 KiB) TX bytes:1760 (1.7 KiB)
wlan0 Link encap:Ethernet HWaddr 00:87:34:1D:96:BA
inet addr:192.168.2.77 Bcast:192.168.2.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:35 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:282 (282.0 B) TX bytes:3534 (3.4 KiB)
Congratulation! Now you can ping to and from 192.168.2.77
For wpa_supplicant please refer to:
WPA supplicant
wpa_passphrase BELL647 12345678
network={
ssid="BELL647"
#psk="12345678"
psk=ab2c7c0b8e0d9abe8c28418fd47365b7efb834fafd9d4c21986c648b39a0e0a2
}
so /etc/wpa_supplicant.conf should be:
ctrl_interface=/var/run/wpa_supplicant
network={
ssid="BELL647"
proto=WPA2
pairwise=CCMP
group=CCMP
key_mgmt=WPA-PSK
#psk="12345678"
psk=ab2c7c0b8e0d9abe8c28418fd47365b7efb834fafd9d4c21986c648b39a0e0a2
}
Save file, reboot, run above script, Wifi should work.
ifconfig:
root@beaglebone:~# ifconfig
can0 Link encap:UNSPEC HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
UP RUNNING NOARP MTU:16 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:10
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interrupt:71
eth0 Link encap:Ethernet HWaddr C8:A0:30:AC:87:22
UP BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
Interrupt:56
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:20 errors:0 dropped:0 overruns:0 frame:0
TX packets:20 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1760 (1.7 KiB) TX bytes:1760 (1.7 KiB)
wlan0 Link encap:Ethernet HWaddr 00:87:34:1D:96:BA
inet addr:192.168.2.77 Bcast:192.168.2.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:2 errors:0 dropped:0 overruns:0 frame:0
TX packets:35 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:282 (282.0 B) TX bytes:3534 (3.4 KiB)
Congratulation! Now you can ping to and from 192.168.2.77
For wpa_supplicant please refer to:
WPA supplicant
Wednesday, September 2, 2015
BBB: Kernel - Servo PWM support
Above figure is about servo control signal, period is about 20ms, adjust duration to set servo position. It can be controlled by BBB timers. BBB has 6 timers to output PWM signal. That means it can control 6 servos at same time. But default Kernel doesn't support 20ms period.
By default, Linux Kernel timer period can't be changed, it is hardcoded to be 500000. That is 500K ps = 0.5ms. To control servo, period must set to about 20ms, so this value should be 20000000 = 20 ms. All servos shares this same period value.
By default, Linux Kernel timer period can't be changed, it is hardcoded to be 500000. That is 500K ps = 0.5ms. To control servo, period must set to about 20ms, so this value should be 20000000 = 20 ms. All servos shares this same period value.
You need to modify Kernel source code to set it. Another thing is, PWM timer is enabled by default, servo will start to work as soon as power is on. It is not expected behaviour. If you have 6 servos, all servos will consume current at same time, they move to initial positions together, it may break power supply. You need to modify pwm dts file to disable PWM output, then let application to enable it when necessary.
pwm dts file looks like bone_pwm_P8(or 9)_xx-00A0.dts, they are located at kernel\kernel\firmware\capes\
For example,
kernel\kernel\firmware\capes\bone_pwm_P9_31-00A0.dts
/*
* Copyright (C) 2013 CircuitCo
* Copyright (C) 2013 Texas Instruments
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
/plugin/;
/ {
compatible = "ti,beaglebone", "ti,beaglebone-black";
/* identification */
part-number = "bone_pwm_P9_31";
version = "00A0";
/* state the resources this cape uses */
exclusive-use =
/* the pin header uses */
"P9.31", /* pwm: ehrpwm0A */
/* the hardware IP uses */
"ehrpwm0A";
fragment@0 {
target = <&am33xx_pinmux>;
__overlay__ {
pwm_P9_31: pinmux_pwm_P9_31_pins {
pinctrl-single,pins = <0x190 0x1>; /* P9_31 (ZCZ ball A13) | MODE 1 */
};
};
};
fragment@1 {
target = <&ocp>;
__overlay__ {
pwm_test_P9_31 {
compatible = "pwm_test";
pwms = <&ehrpwm0 0 500000 1>;
pwm-names = "PWM_P9_31";
pinctrl-names = "default";
pinctrl-0 = <&pwm_P9_31>;
enabled = <1>;
duty = <0>;
status = "okay";
};
};
};
};
Modify:
pwms = <&ehrpwm0 0 500000 1>;
to
pwms = <&ehrpwm0 0 20000000 1>;
Modify:
enabled = <1>;
to
enabled = <0>;
Then compile kernel and update image file. DTS files are embedded into Kernel image.
You need to install pwm_test driver which enabled pwm for servo after boot.
insmod pwm_test.ko
Some PWM pins are shared with HDMI tx, to use these pins, disable HDMI tx by edit uEnv.txt file.
more /media/BEAGLEBONE/uEnv.txt
optargs=quiet drm.debug=7 capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN
capemgr.enable_partno=am33xx_pwm,bone_pwm_P9_31
Add following code in start-up script to enable all 6 PWM timers.
echo am33xx_pwm > /sys/devices/bone_capemgr.9/slots
echo bone_pwm_P9_31 > /sys/devices/bone_capemgr.9/slots
echo bone_pwm_P9_29 > /sys/devices/bone_capemgr.9/slots
echo bone_pwm_P8_36 > /sys/devices/bone_capemgr.9/slots
echo bone_pwm_P8_34 > /sys/devices/bone_capemgr.9/slots
echo bone_pwm_P8_45 > /sys/devices/bone_capemgr.9/slots
echo bone_pwm_P8_46 > /sys/devices/bone_capemgr.9/slots
For example to control PWM P9_31:
start PWM P9_31
echo 1 > /sys/devices/ocp.3/pwm_test_P9_31.12/run
set polarity of duty to be 0, must be 0
echo 0 > /sys/devices/ocp.3/pwm_test_P9_31.12/polarity
set duty to control servo position
echo 50000 > /sys/devices/ocp.3/pwm_test_P9_31.12/duty
BBB: Kernel - Source code and Cross Compiling
BBB Linux Kernel:
1) Download tool chain
Arm GCC build tool: Linaro
https://wiki.linaro.org/WorkingGroups/ToolChain
2) Download kernel for beagleboard
git clone git://github.com/beagleboard/kernel.git
3) Cross compiling
cd kernel
git checkout 3.8
./patch.sh
cp configs/beaglebone kernel/arch/arm/configs/beaglebone_defconfig
wget http://arago-project.org/git/projects/?p=am33x-cm3.git\;a=blob_plain\;f=bin/am335x-pm-firmware.bin\;hb=HEAD -O kernel/firmware/am335x-pm-firmware.bin
cd kernel
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- beaglebone_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- uImage dtbs
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- uImage-dtb.am335x-boneblack
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules
1) Download tool chain
Arm GCC build tool: Linaro
https://wiki.linaro.org/WorkingGroups/ToolChain
2) Download kernel for beagleboard
git clone git://github.com/beagleboard/kernel.git
3) Cross compiling
cd kernel
git checkout 3.8
./patch.sh
cp configs/beaglebone kernel/arch/arm/configs/beaglebone_defconfig
wget http://arago-project.org/git/projects/?p=am33x-cm3.git\;a=blob_plain\;f=bin/am335x-pm-firmware.bin\;hb=HEAD -O kernel/firmware/am335x-pm-firmware.bin
cd kernel
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- beaglebone_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- uImage dtbs
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- uImage-dtb.am335x-boneblack
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules
Android: Visual Soccer and Goal Detection
Soccer is pingpang ball, since it is semi-transparent and has black letter on it, it is very hard to filter colour under OpenCV, so I painted it with water colour.
Same with goal, to easy distinguish, painted it with blue water colour.
OpenCV is very powerful, it has plenty of functions for object detection. The main idea is, with smart phone camera, convert image to grey under HSV space, then filter colour, blur it then detect circle for soccer and rectangle for goal.
Following is source code for visual soccer and goal detection under Android with JNI c code.
Using OpenCV library under Android, ball is coloured to red and net is coloured to blue.
int detectDoor(Mat & img_rgba, int & door_x, int & door_y)
{
Mat img_temp;
Mat img_work;
Mat img_gray;
int sel_id;
int max_area;
Mat img_3;
Mat kernel_ero = getStructuringElement(MORPH_RECT, Size(2,2));
int h;
int s;
int v;
door_x = 0;
door_y = 0;
h = 237/2;
s = 100*2 + 55;
v = 25*2 + 55;
cv::cvtColor(img_rgba, img_temp, CV_RGB2HSV); // convert to HSV
inRange(img_temp, Scalar(266/2-20, 0, 0), Scalar(266/2+20, 255, 255), img_work); // filter color
cv::blur(img_work, img_gray, Size(30, 30));
threshold(img_gray, img_gray, 100, 255, CV_THRESH_BINARY);
erode(img_gray, img_gray, kernel_ero);
Size sz;
vector<vector<Point> > contours;
vector<vector<Point> > contours0;
vector<Vec4i> hierarchy;
findContours( img_gray, contours0, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
int idx = 0;
sel_id = 0;
max_area = 0;
for( idx = 0; idx < contours0.size(); idx++ )
{
Rect r = boundingRect(contours0[idx]);
Scalar color( 255, 0, 0 );
if(hierarchy[idx][2] < 0) //Check if there is a child contour
rectangle(img_rgba,Point(r.x-10,r.y-10), Point(r.x+r.width+10,r.y+r.height+10), Scalar(0,0,255),2,8,0); //Opened contour
else
rectangle(img_rgba,Point(r.x-10,r.y-10), Point(r.x+r.width+10,r.y+r.height+10), Scalar(0,255,0),2,8,0); //closed contour
if( max_area < r.width * r.height)
{
max_area = r.width * r.height;
sel_id = idx;
}
}
// choose area > 400
if( max_area > 400 )
{
Rect r = boundingRect(contours0[sel_id]);
door_x = r.x + r.width/2;
door_y = r.y + r.height/2;
circle(img_rgba,Point(door_x,door_y),20, Scalar(255,0,0), 3, 8, 0); //closed contour
}
return 0;
}
JNIEXPORT jintArray JNICALL Java_com_example_balltrace_BallTrace_BallDetect(JNIEnv* env, jobject thiz,
jint width, jint height, jlong yuv, jlong rgba, jlong outPtr)
{
jint outArray[5];
Mat mGray = *((Mat*)yuv);
Mat mRgba = *((Mat*)rgba); // original camera image
int door_x = 0;
int door_y = 0;
Mat hsv_frame;
outArray[0] = 0;
outArray[1] = 0;
outArray[2] = 0;
outArray[3] = -1; // door rect center X
outArray[4] = -1; // door rect center y
detectDoor(mRgba, door_x, door_y);
outArray[3] = door_x;
outArray[4] = door_y;
//Mat thresholded;
cv::Mat* thresholded = new cv::Mat(cv::Size(width, height), CV_8UC1);
cv::Rect roi( cv::Point( 0, 0 ), Size(width, height) );
CvSize size = cvSize(width, height);
cvtColor(mRgba, hsv_frame, CV_RGB2HSV);
inRange(hsv_frame, Scalar(1, 80, 80), Scalar(7, 250, 250), *thresholded);
GaussianBlur(*thresholded, *thresholded, Size(9,9), 0, 0);
vector<Vec3f> circles;
HoughCircles(*thresholded, circles, CV_HOUGH_GRADIENT,1.5, height/4, 100, 40, 15, 80 );
for( size_t i = 0; i < circles.size(); i++ )
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
if( radius < 5 )
continue;
// draw the circle center
circle( mRgba, center, 3, Scalar(0,255,0), -1, 8, 0 );
// draw the circle outline
circle( mRgba, center, radius, Scalar(0,0,255), 3, 8, 0 );
outArray[0] = cvRound(circles[i][0]);
outArray[1] = cvRound(circles[i][1]);
outArray[2] = radius;
break;
}
delete thresholded;
jintArray retArray = env->NewIntArray(5);
env->SetIntArrayRegion(retArray, 0 , 5, outArray);
return retArray;
}
Robot Hardware
1. Smart phone Nexus 5
CPU: Qualcomm SnapdragonTM 800, 2.26GHz
RAM: 2 GB
Sensors: GPS, Gyroscope, Accelerometer, Compass, Proximity/Ambient, Light, Pressure, Hall Effect
Android 4.4
This smart phone is very powerful. It has everything for image recognition, fast CPU, huge DRAM, open-source OS Android. It can detect ball and net very quickly at real time. So the Robot can respond as fast as possible. In addition, embedded sensors can give the Robot enough information for accurate position control.
Since it is Android system, plenty of free samples and free source code can be found in open source world. Unlike iPhone, Nexus 5 is free to program on it. User can get free development environment tools from internet.
OpenCV is open source and standard image recognition software, it has reach functions for object detection and widely used by commercial field. It is powerful but simple for programmer.
2. BeagleBone Black Development Board
CPU: 1GHz AM3359 Sitara ARM Cortex-A8
RAM: 512MB DDR3
CAN Bus
Wifi
6 Timers
It is ARM9 CPU, running Linux OS. With its WI-FI, it can communicate with smart phone through TCP/IP protocol. <br>
Six Timers IO control 6 servos, 4 of them for arm and 2 for smart phone panning and tilting control.
CAN BUS is for eZ430 board communication to control 2 rear wheels DC motors.
With process programming, it can search ball by head servos panning and tilting, moving arm to kick and grab ball and driving the Robot.
3. TI micro controller
eZ430-RF2500 Development Board
CAN Bus
Timer 2 - for Motor control
It has two GPIO and two timers to control 2 DC motors.
CAN bus is used to communicate with BBB board.
4. Power Supply
+12VDC -> +6.0VDC for Servo
+12VDC -> +5.0VDC for CAN Bus and BBB board
+12VDC -> +3.3VDC for eZ430
5. Motor control
H-Bridge
PWM
Direction
Rear wheel drive
6. Servo control
PWM
Position
7. CAN BUS
Robot System
1. Goal
This Robot system shall detect ball and net, kick ball to net, talk, listen and dance.
2. Components
Arm: one arm which has 4 servos, that it is 4 free degree, can kick and grab ball.
Eye: one smart phone camera, with OpenCV, it can detect object and image recognition.
Leg: Two rear wheel drive.
Head: Smart phone - Nexus 5 + Arm9 + microcontroller
3. Communication
Wifi + CAN BUS
Three components need to communicate with each other. Smart phone will send ball and net position to BBB through WIFI at home router, BBB sends motors control command to eZ430 by industry CAN BUS.
4. Design
The most difficult part is object detection at software point of view. At initial design, using a desk PC as image processing, but it will require an extra camera, in now days, smart phone is very powerful, cheaper and easy for programming, it is a very good idea to use smart phone as eye and I just have a Nexus 5.
To search ball and net, smart phone panning and tilting is a must, so two servos are needed, plus one arm has 4 servos, totally 6 servos are required.
Nexus 5 has many sensors which is very useful for speed, direction and position control and feedback.
And it contains voice recognition and speech on text. With it, the robot can listen command and talk, singing, etc.
BeagleBone Black board has one ARM9 CPU which running Linux OS, it has 6 timers, WIFI, CAN BUS, everything. And very important, it is cheap--only $45 when I bought it, now price is up to $55.
eZ430 is TI small board which has one microcontroller, it is used to control H-Bridge two motors for rear wheel drive. With two motors, the robot can move forward, backward, tune left and right.
Arm has 4 servos, so it can kick and grab ball. To reduce cost, only one arm is installed.<br>
Single +12VDC power input, output +3.3VDC, +5.0VDC, +6.0VDC and +12VDC. +6.0VDC is for servos, +12VDC is for two motors. +3.3VDC and +5.0VD is for controllers.
Subscribe to:
Posts (Atom)