WiFi小车笔记

——————/
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 //具体见视频,类似上节驱动编译
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Wifi遥控小车使用说明: 本例程采用ESP8266 wifi模块与STM32串口连接,并提供AT指令封装库与STM32通讯,实现如下的通讯方式: 1、硬件部分 Wifi模块丝印图即引脚如下: 硬件连接如下: 2、手机APP部分 APP部分我们采用常用的APP wifi调试软件 ITEAD WIFI,安装完成后打开 如下界面,点击Set up进入设置: 进入后会自动获取到手机的IP,注意手机是连接到一个路由器下的,支持局域网内调试,先设置端口,一般是 8080 然后设置指令,我们使用到了如下红框内的指令,指令协议可以参考工程文件interface.h有如下描述: //指令定义 #define COMM_STOP 'I'//停止 #define COMM_UP 'A'//前进 #define COMM_DOWN 'B'//后退 #define COMM_LEFT 'C'//左转 #define COMM_RIGHT 'D'//右转 指令设置好之后就可以启动服务了,如下点击开始就好了 设置完成后如下,这里记下服务端IP和端口号,我这里是 192.168.31.195,端口 8080 ,然后返回: 3、stm32软件部分 设置完APP软件后,再来修改我们的工程文件,打开工程“wifi遥控小车”,打开main.c文件,修改红框内信息: HOST_NAME和HOST_PORT为手机上面的IP和端口号,SSID为您的路由器名,PSD为路由器密码,修改好后重新编译后下载。 下载完成复位一下,就可以运行了,程序会自动连接手机开启的服务,实现TCP/IP通信,连接成功后,看手机端的设置会有如下提示: 本程序还是用了串口1来输出调试信息,将串口1连接电脑后也会在串口调试助手看到如下信息: 连接成功后即可在如下界面按键,操作小车运行:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值