——————/
OpenWrt是一高度模块化、自动化的嵌入式Linux系统,拥有强大的网络组件,常常被用于工控设备、电话、小型机器人、智能家居、路由器等设备中
OpenWrt支持各种处理器架构,如ARM、X86、PowerPC、MIPS等
WiFi小车:uboot——kernel— —文件系统——app
工具链无需单独安装,属于openwrt
WiFi小车出厂时已烧写uboot,想自己开发相应uboot很困难(需用电烙铁将spiFlash从PCB板取下,然后烧写,然后再焊接)
kernel、文件系统均属于openwrt
app若软件市场有则直接下载安装,如Android,否则自己开发
——————/
——/搭建环境
root@lyl:/wifiCar# apt-get install subversion git-core
root@lyl:/wifiCar# apt-get install gcc g++ binutils patch bzip2 flex bison make autoconf
gettext texinfo unzip sharutils zlib1g-dev libncurses5-dev gawk
——/下载源码
lyl@lyl:/wifiCar$ ls -ld /wifiCar
drwxrwxrwx 3 root root 4096 10月 3 21:56 /wifiCar
//使用root账号产生权限问题导致编译失败,一晚上才解决
lyl@lyl:/wifiCar/trunk$ ./scripts/feeds update –a
lyl@lyl:/wifiCar/trunk$ ./scripts/feeds install –a
——/配置编译
lyl@lyl:/wifiCar/trunk$ make menuconfig
Target System (Ralink RT288x/RT3xxx) ---> //选成Ralink RT288x/RT3xxx,雷凌WiFi产品
Subtarget (RT3x5x/RT5350 based boards) ---> // RT5350WiFi模块
WiFi小车Flash为8m,内存为12m,与HAME MPR-A2同,故:
Target Profile (HAME MPR-A2) --->
root@lyl:/wifiCar/openWrt/trunk# make
lyl@lyl:/wifiCar/trunk$ make V=99 //编译同时下载资源,需4h左右
——/
lyl@lyl:/wifiCar$ du -sh trunk
6.2G trunk
lyl@lyl:/wifiCar/trunk/bin/ramips$ ls -lh *
openwrt-ramips-rt305x-mpr-a2-squashfs-sysupgrade.bin 3.1M //烧写目标
使用u-boot菜单经window tftp下载自动烧写自动启动
——————/ 添加web界面
用户交互的界面,快速设置的接口
vi /etc/config/network //修改ip
lyl@lyl:/wifiCar/trunk$ make menuconfig
重新烧写重启,在浏览器输入192.168.10.1,还是登陆不了,因:
WiFi模块rt5350有5个网络端口,均可被配置为wan(广域网)或lan(局域网),WiFi小车使用网络端口4,默认被openwrt配置为wan口,需将其改为lan口,修改方法见视频
——————/工作于AP、STA模式
AP:access point
局域网监控,小车工作于AP模式
P2P监控,小车工作于STA模式
——/使小车工作于AP模式
vi /etc/config/wireless
——————/
openWrt与window通过SSH共享文件,前提:
lyl@lyl:/wifiCar/trunk$ make menuconfig
——/
每次给WiFi小车烧固件后,都需修改配置文件/etc/config/network麻烦
在源码中设置默认IP、将WAN改为LAN、使能AP
lyl@lyl:/wifiCar/trunk$ vi ./package/base-files/files/lib/functions/uci-defaults.sh
set network.lan.ipaddr='192.168.10.1'
ucidef_set_interfaces_lan_wan() {
local lan_ifname=$2
local wan_ifname=$1
lyl@lyl:/wifiCar/trunk$ vi ./package/kernel/mac80211/files/lib/wifi/mac80211.sh
# option disabled 1
——————/驱动之hello world
openwrt所用内核3.10
openwrt显著特点:以软件包形式管理app及驱动模块
hello world驱动与Linux驱动同
软件包管理常用命令:
opkg install xxx.ipk
opkg remove xxx.ipk
opkg list
opkg help
软件包的介绍:http://www.right.com.cn/forum/thread-75653-1-1.html
——/
lyl@lyl:/wifiCar/trunk/package/kernel$ mkdir example
lyl@lyl:/wifiCar/trunk/package/kernel/example$ cp ../gpio-button-hotplug/* . -fr
lyl@lyl:/wifiCar/trunk/package/kernel/example$ ls
Makefile src
lyl@lyl:/wifiCar/trunk/package/kernel/example$ ls src/
gpio-button-hotplug.c Makefile //将*.c替换为example.c
lyl@lyl:/wifiCar/trunk/package/kernel/example$ vi src/Makefile
obj-m += example.o
——/
lyl@lyl:/wifiCar/trunk/package/kernel/example$ vi Makefile
lyl@lyl:/wifiCar/trunk$ make menuconfig
lyl@lyl:/wifiCar/trunk$ ls bin/ramips/packages/base/*example* -lh
kmod-example_3.14.18-1_ramips_24kec.ipk 1.5k
将其共享到WiFiCar
——/
/lib/modules/3.10.36/目录下没有example.ko
opkg install kmod-example_3.14.18-1_ramips_24kec.ipk
/lib/modules/3.10.36/目录下出现example.ko
insmod example.ko
Makefile中AUTOLOAD:=…不注释掉,便无需手动insmod
——————/电机、蜂鸣器硬件原理
蜂鸣器:GPIO#25为1三极管导通,蜂鸣器响,反之…
电机:
M1右轮M2左轮
+-正转-+反转
OUT输出7.4V
EN A低则OUT1 OUT2同时为低,EN A高OUT1 OUT2输出受57控制
L298N左侧与PC817光耦芯片连
GPIO#7——OUT1
GPIO#8——OUT2
GPIO#9——OUT3
GPIO#10——OUT4
GPIO#17——EN A
GPIO#18——EN B
——————/电机、蜂鸣器驱动
——————/libncurses应用
为什么用libncurses?
因需通过键盘上下左右方向键来控制小车方向,通过回车键控制蜂鸣器
make menuconfig时移动菜单即使用该库
安装库文件
sudo apt-get install libncurses5-dev
root@lyl:~# man ncurses
没有 ncurses 的手册页条目
故还需sudo apt-get install ncurses-doc
上下左右及其它功能键,无ascii码,故使用curses.h内部定义宏,其余有则使用ASCII
——————/串口控制WiFi
Makefile src
root@lyl:/wifiCar/trunk/package/utils/motor_test/src# ls
Makefile motor.c //具体见视频,类似上节驱动编译
OpenWrt是一高度模块化、自动化的嵌入式Linux系统,拥有强大的网络组件,常常被用于工控设备、电话、小型机器人、智能家居、路由器等设备中
OpenWrt支持各种处理器架构,如ARM、X86、PowerPC、MIPS等
WiFi小车:uboot——kernel— —文件系统——app
工具链无需单独安装,属于openwrt
WiFi小车出厂时已烧写uboot,想自己开发相应uboot很困难(需用电烙铁将spiFlash从PCB板取下,然后烧写,然后再焊接)
kernel、文件系统均属于openwrt
app若软件市场有则直接下载安装,如Android,否则自己开发
——————/
——/搭建环境
root@lyl:/wifiCar# apt-get install subversion git-core
root@lyl:/wifiCar# apt-get install gcc g++ binutils patch bzip2 flex bison make autoconf
gettext texinfo unzip sharutils zlib1g-dev libncurses5-dev gawk
——/下载源码
lyl@lyl:/wifiCar$ ls -ld /wifiCar
drwxrwxrwx 3 root root 4096 10月 3 21:56 /wifiCar
//使用root账号产生权限问题导致编译失败,一晚上才解决
lyl@lyl:/wifiCar/trunk$ ./scripts/feeds update –a
lyl@lyl:/wifiCar/trunk$ ./scripts/feeds install –a
——/配置编译
lyl@lyl:/wifiCar/trunk$ make menuconfig
Target System (Ralink RT288x/RT3xxx) ---> //选成Ralink RT288x/RT3xxx,雷凌WiFi产品
Subtarget (RT3x5x/RT5350 based boards) ---> // RT5350WiFi模块
WiFi小车Flash为8m,内存为12m,与HAME MPR-A2同,故:
Target Profile (HAME MPR-A2) --->
root@lyl:/wifiCar/openWrt/trunk# make
lyl@lyl:/wifiCar/trunk$ make V=99 //编译同时下载资源,需4h左右
——/
lyl@lyl:/wifiCar$ du -sh trunk
6.2G trunk
lyl@lyl:/wifiCar/trunk/bin/ramips$ ls -lh *
openwrt-ramips-rt305x-mpr-a2-squashfs-sysupgrade.bin 3.1M //烧写目标
使用u-boot菜单经window tftp下载自动烧写自动启动
——————/ 添加web界面
用户交互的界面,快速设置的接口
vi /etc/config/network //修改ip
lyl@lyl:/wifiCar/trunk$ make menuconfig
//openwrt支持两种web界面:LuCI(官方维护)、webif(第三方开发)
LuCI --->
1. Collections --->
<*> luci
5. Translations --->
<*> luci-i18n-chinese......Chinese (by Chinese Translators)
lyl@lyl:/wifiCar/trunk$ make V=99 //7分钟
重新烧写重启,在浏览器输入192.168.10.1,还是登陆不了,因:
WiFi模块rt5350有5个网络端口,均可被配置为wan(广域网)或lan(局域网),WiFi小车使用网络端口4,默认被openwrt配置为wan口,需将其改为lan口,修改方法见视频
——————/工作于AP、STA模式
AP:access point
局域网监控,小车工作于AP模式
P2P监控,小车工作于STA模式
——/使小车工作于AP模式
vi /etc/config/wireless
——————/
openWrt与window通过SSH共享文件,前提:
lyl@lyl:/wifiCar/trunk$ make menuconfig
Network --->
SSH --->
<*> openssh-sftp-server.......OpenSSH SFTP server
使WiFi小车工作于AP模式
——/
每次给WiFi小车烧固件后,都需修改配置文件/etc/config/network麻烦
在源码中设置默认IP、将WAN改为LAN、使能AP
lyl@lyl:/wifiCar/trunk$ vi ./package/base-files/files/lib/functions/uci-defaults.sh
set network.lan.ipaddr='192.168.10.1'
ucidef_set_interfaces_lan_wan() {
local lan_ifname=$2
local wan_ifname=$1
lyl@lyl:/wifiCar/trunk$ vi ./package/kernel/mac80211/files/lib/wifi/mac80211.sh
# option disabled 1
——————/驱动之hello world
openwrt所用内核3.10
openwrt显著特点:以软件包形式管理app及驱动模块
hello world驱动与Linux驱动同
软件包管理常用命令:
opkg install xxx.ipk
opkg remove xxx.ipk
opkg list
opkg help
软件包的介绍:http://www.right.com.cn/forum/thread-75653-1-1.html
——/
lyl@lyl:/wifiCar/trunk/package/kernel$ mkdir example
lyl@lyl:/wifiCar/trunk/package/kernel/example$ cp ../gpio-button-hotplug/* . -fr
lyl@lyl:/wifiCar/trunk/package/kernel/example$ ls
Makefile src
lyl@lyl:/wifiCar/trunk/package/kernel/example$ ls src/
gpio-button-hotplug.c Makefile //将*.c替换为example.c
lyl@lyl:/wifiCar/trunk/package/kernel/example$ vi src/Makefile
obj-m += example.o
——/
lyl@lyl:/wifiCar/trunk/package/kernel/example$ vi Makefile
include $(TOPDIR)/rules.mk //固定格式
include $(INCLUDE_DIR)/kernel.mk
PKG_NAME:=example
PKG_RELEASE:=1
include $(INCLUDE_DIR)/package.mk
define KernelPackage/example //定义make menuconfig菜单中相应配置项
SUBMENU:=Other modules
# DEPENDS:=@!LINUX_3_3 //@表条件成立才显示
TITLE:=Simple example by lyl //短帮助信息
FILES:=$(PKG_BUILD_DIR)/example.ko
# AUTOLOAD:=$(call AutoLoad,30,gpio-button-hotplug,1)
KCONFIG:=
endef
define KernelPackage/example/description //长帮助信息
This is a example for hello world drivers
endef
MAKE_OPTS:= \ //固定格式
ARCH="$(LINUX_KARCH)" \
CROSS_COMPILE="$(TARGET_CROSS)" \
SUBDIRS="$(PKG_BUILD_DIR)"
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
define Build/Compile
$(MAKE) -C "$(LINUX_DIR)" \
$(MAKE_OPTS) \
modules
endef
$(eval $(call KernelPackage,example))
——/
lyl@lyl:/wifiCar/trunk$ make menuconfig
Kernel modules --->
Other modules --->
<*> kmod-example...... Simple example by lyl
lyl@lyl:/wifiCar/trunk$ make package/kernel/example/compile V=99
lyl@lyl:/wifiCar/trunk$ ls bin/ramips/packages/base/*example* -lh
kmod-example_3.14.18-1_ramips_24kec.ipk 1.5k
将其共享到WiFiCar
——/
/lib/modules/3.10.36/目录下没有example.ko
opkg install kmod-example_3.14.18-1_ramips_24kec.ipk
/lib/modules/3.10.36/目录下出现example.ko
insmod example.ko
Makefile中AUTOLOAD:=…不注释掉,便无需手动insmod
——————/电机、蜂鸣器硬件原理
蜂鸣器:GPIO#25为1三极管导通,蜂鸣器响,反之…
电机:
M1右轮M2左轮
+-正转-+反转
OUT输出7.4V
EN A低则OUT1 OUT2同时为低,EN A高OUT1 OUT2输出受57控制
L298N左侧与PC817光耦芯片连
GPIO#7——OUT1
GPIO#8——OUT2
GPIO#9——OUT3
GPIO#10——OUT4
GPIO#17——EN A
GPIO#18——EN B
——————/电机、蜂鸣器驱动
#define WIFI_ROBOT_RUN 0
#define WIFI_ROBOT_BACK 1
#define WIFI_ROBOT_LEFT 2
#define WIFI_ROBOT_RIGHT 3
#define WIFI_ROBOT_STOP 4
#define WIFI_BUZZER_ON 5
#define WIFI_BUZZER_OFF 6
volatile unsigned long *GPIOMODE;
volatile unsigned long *GPIO21_00_DIR; //控制gpio 0-21方向
volatile unsigned long *GPIO21_00_DATA;
volatile unsigned long *GPIO27_22_DIR;
volatile unsigned long *GPIO27_22_DATA;
static int motor_drv_open(struct inode *inode, struct file *file)
{
/* 配置相应引脚用于GPIO */
*GPIOMODE |= (0x7<<2)|(0x1<<6);
/* 将GPIO#7、GPIO#8、GPIO#9、GPIO#10、GPIO#17、GPIO#18设置为输出 */
*GPIO21_00_DIR |= (1<<7)|(1<<8)|(1<<9)|(1<<10)|(1<<17)|(1<<18);
return 0;
}
static ssize_t motor_drv_write(struct file *file, const char __user *buf,
size_t size, loff_t *ppos)
{
char val;
copy_from_user(&val, buf, 1);
if(val & 0x1)
{
*GPIO21_00_DATA |= (1<<17)|(1<<18);
}
else
{
*GPIO21_00_DATA &= ~((1<<17)|(1<<18));
}
return 1;
}
static long motor_drv_unlocked_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
switch(cmd)
{
case WIFI_ROBOT_RUN: // 小车前进,LED不亮
*GPIO21_00_DATA &= ~((1<<7)|(1<<8)|(1<<9)|(1<<10));
*GPIO21_00_DATA |= (0<<7)|(1<<8)|(0<<9)|(1<<10);
break;
case WIFI_ROBOT_BACK: // 小车后退,LED全亮
*GPIO21_00_DATA &= ~((1<<7)|(1<<8)|(1<<9)|(1<<10));
*GPIO21_00_DATA |= (1<<7)|(0<<8)|(1<<9)|(0<<10);
break;
case WIFI_ROBOT_LEFT: // 小车左转弯,左边的LED亮
*GPIO21_00_DATA &= ~((1<<7)|(1<<8)|(1<<9)|(1<<10));
*GPIO21_00_DATA |= (0<<7)|(1<<8)|(1<<9)|(1<<10);
mdelay(20);
*GPIO21_00_DATA &= ~((1<<7)|(1<<8)|(1<<9)|(1<<10));
*GPIO21_00_DATA |= (1<<7)|(1<<8)|(1<<9)|(1<<10);
break;
case WIFI_ROBOT_RIGHT:
*GPIO21_00_DATA &= ~((1<<7)|(1<<8)|(1<<9)|(1<<10));
*GPIO21_00_DATA |= (1<<7)|(1<<8)|(0<<9)|(1<<10);
mdelay(20);
*GPIO21_00_DATA &= ~((1<<7)|(1<<8)|(1<<9)|(1<<10));
*GPIO21_00_DATA |= (1<<7)|(1<<8)|(1<<9)|(1<<10);
break;
case WIFI_ROBOT_STOP:
*GPIO21_00_DATA &= ~((1<<7)|(1<<8)|(1<<9)|(1<<10));
*GPIO21_00_DATA |= (1<<7)|(1<<8)|(1<<9)|(1<<10);
break;
case WIFI_BUZZER_ON:
*GPIO27_22_DATA |= 1<<3;
break;
case WIFI_BUZZER_OFF:
*GPIO27_22_DATA &= ~(1<<3);
break;
default:
break;
}
return 0;
}
static struct file_operations motor_drv_fops = {
.owner = THIS_MODULE,
.open = motor_drv_open,
.write = motor_drv_write,
.unlocked_ioctl = motor_drv_unlocked_ioctl,
};
static int major;
static struct class *motor_drv_class;
static int __init motor_drv_init(void)
{
major = register_chrdev(0, "motor_drv", &motor_drv_fops);
motor_drv_class = class_create(THIS_MODULE, "motor");
device_create(motor_drv_class, NULL, MKDEV(major, 0), NULL, "motor");
GPIOMODE = (volatile unsigned long *)ioremap(0x10000060, 4); //功能选择
GPIO21_00_DIR = (volatile unsigned long *)ioremap(0x10000624, 4); //输出输入
GPIO21_00_DATA = (volatile unsigned long *)ioremap(0x10000620, 4);
GPIO27_22_DIR = (volatile unsigned long *)ioremap(0x10000674, 4);
GPIO27_22_DATA = (volatile unsigned long *)ioremap(0x10000670, 4);
*GPIOMODE |= (0x1<<14);/* 关闭蜂鸣器,否则一上电就响 */
*GPIO27_22_DIR = (1<<3);
*GPIO27_22_DATA &= ~(1<<3);
return 0;
}
static void __exit motor_drv_exit(void)
{
device_destroy(motor_drv_class, MKDEV(major, 0));
class_destroy(motor_drv_class);
unregister_chrdev(major, "motor_drv");
iounmap(GPIOMODE);
iounmap(GPIO21_00_DIR);
iounmap(GPIO21_00_DATA);
iounmap(GPIO27_22_DIR);
iounmap(GPIO27_22_DATA);
}
——————/libncurses应用
为什么用libncurses?
因需通过键盘上下左右方向键来控制小车方向,通过回车键控制蜂鸣器
make menuconfig时移动菜单即使用该库
安装库文件
sudo apt-get install libncurses5-dev
root@lyl:~# man ncurses
没有 ncurses 的手册页条目
故还需sudo apt-get install ncurses-doc
上下左右及其它功能键,无ascii码,故使用curses.h内部定义宏,其余有则使用ASCII
——————/串口控制WiFi
#include <stdio.h>
#include <curses.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define ENTER 13
#define ESC 27
#define WIFI_ROBOT_RUN 0
#define WIFI_ROBOT_BACK 1
#define WIFI_ROBOT_LEFT 2
#define WIFI_ROBOT_RIGHT 3
#define WIFI_ROBOT_STOP 4
#define WIFI_BUZZER_ON 5
#define WIFI_BUZZER_OFF 6
int main(int argc, char **argv)
{
int fd;
int key;
char val;
int is_on = 0;
fd = open("/dev/motor", O_RDWR | O_NONBLOCK);
if (fd < 0)
{
printf("can't open!\n");
return -1;
}
val = 1;
write(fd, &val, 1); /*使能EN A、EN B*/
initscr();//在使用之前,必须初始化
nonl();//不把换行作为回车字符
intrflush(stdscr, FALSE);//是否处理中断信号
keypad(stdscr, TRUE);//使能keypad功能,这样就能接收上下左右等特殊字符
while( (key=getch()) != ESC )
{
switch(key)
{
case KEY_UP:
clear();
printw("KEY UP\n");
ioctl(fd, WIFI_ROBOT_RUN);
break;
case KEY_DOWN:
clear();
printw("KEY DOWN\n");
ioctl(fd, WIFI_ROBOT_BACK);
break;
case KEY_LEFT:
clear();
printw("KEY LEFT\n");
ioctl(fd, WIFI_ROBOT_LEFT);
break;
case KEY_RIGHT:
clear();
printw("KEY RIGHT\n");
ioctl(fd, WIFI_ROBOT_RIGHT);
break;
case ENTER:
{
clear();
printw("KEY ENTER\n");
if(is_on == 0)
{
ioctl(fd, WIFI_BUZZER_ON);
is_on = 1;
}
else
{
ioctl(fd, WIFI_BUZZER_OFF);
is_on = 0;
}
break;
}
default:
clear();
printw("key = %d\n", key);
break;
}
}
endwin();//退出
return 0;
}
root@lyl:/wifiCar/trunk/package/utils/motor_test# ls
Makefile src
root@lyl:/wifiCar/trunk/package/utils/motor_test/src# ls
Makefile motor.c //具体见视频,类似上节驱动编译