一个用 Arduino 实现的完整项目

来源:http://www.oschina.net/translate/a-complete-project-with-arduino?utm_source=tuicool  
英文原文:
A complete project with Arduino
参与翻译 (3人) : realZ, leoxu, Ley

介绍

我有一个上小学的女儿. 作为一位父亲,当然该负起责任. 我喜欢自己作为父亲的角色,对此我毫无疑问. 但因此所带给我的困扰则是无止境的数学学习事务. 有时候这真的让我很头疼. 2+2, 5+6, 4+3,一遍又一遍. 那才刚开始呢, 现在又多了减法: 5-4, 10-4 .. 而每个人都知道这是没有结束可言的. 我抱怨的够多了,因而决定利用此项技术. 你知道的,技术为人而生, 而现在是为我而存在. 到这里来,我亲爱的 Arduino, 我需要你.

在最开始的时候,我希望这个项目能很容易实现. 我预计所有需要做的事情就是写一些函数来展示一些数字,并且为了根据趣味性,也许要来点蜂鸣声和一些LED灯光. 然后,情况在我开始精心考虑它的时候发生了改变, 出现了一些硬件管理问题, 然后是内容管理问题. 我们这个小小的 Arduino 应用程序变成了一个认真把握的东西,这导致我写下了这篇文章. 让我们先从需求开始吧.

计划需求

  • 系统可以显示一个菜单,提供一些基本的操作:加、减、乘、除 。

  • 用户(我的女儿)可以用键盘从菜单上选择一种算数运算来学习。

  • 会有一些难度级别:在选择运算后,难度级别会显示出来。

  • 根据选择的难度级别,会随机显示出一些问题,用户可以用键盘回答这些问题。

  • 用户可以在确认前修改自己的答案。

  • 在确认答案后,根据正确与否会显示出一条信息。

  • 如果三次答错,将会显示出正确答案。

  • 用户可以浏览菜单(点开菜单并选择菜单项)。

  • 系统应具有音频和视频警告API,错误信息可以通过该API发送。

  • 每种算术运算有一个限时小测环节。

  • 限时小测随机从简到难给出问题。  

  • 测试后会显示出统计数据(回答了多少题目,答对了多少题目)。

  • 在用户接近时系统可以引起她的注意。

  • 可以有一些数学以外的娱乐环节,比如让她唱首歌、亲自己的爸爸等等。如果不这么做,用户将无法继续使用系统。

  • 警告API可以用来在娱乐环节做一些有趣的事情。

硬件 

我们在这个项目中需要什么: 

  1. Arduino Mega:http://arduino.cc/en/Main/arduinoBoardMega2560  

  2. 字符液晶面板(Serial LCD):http://www.dfrobot.com/index.php?route=product/product&filter_name=adkeyboard&product_id=197#.UvNglbQSHxQ  

  3. 矩阵键盘 :https://www.sparkfun.com/products/8653

  4. 模拟键盘 :http://www.dfrobot.com/index.php?route=product/product&filter_name=adkeyboard&product_id=197#.UvNglbQSHxQ

  5. PIR运动传感器:http://www.cooking-hacks.com/pir-motion-sensor

  6. LED 和 400欧姆电阻

  7. 数字蜂鸣模块:http://www.dfrobot.com/index.php?route=product/product&filter_name=buzzer&product_id=84#.UvNc2rQSHxQ

  8. 连接线

看看下面的硬件设计:

注意一些和上面不匹配的部分:

  1. LCD应该是字符LCD。

  2. Arduino UNO应该用Mega替代。

(我用Arduino UNO开启了这个项目,但是因为内存的需要后来改用Arduino Mega继续这个项目。开始的时候,Arduino UNO工作的很好。但是,当代码量增加,我无法将RAM使用量控制在Arduino UNO的容量之内,然后就想你所想的,我最终启用了Arduino Mega,它有8K的SRAM。)

软件设计

 

图1:设计的概览

系统被分为2个主要部分。就像你在图1中看到的,第一个模块负责硬件的管理。

  • 输入系统:我们有两个不同的键盘,他们被统一在一起,对外提供统一的接口。统一的键盘信息将在(矩阵键盘或模拟键盘上的)任何按键被按下时告知注册的客户端。

  • 输出系统:具有附加功能的字符液晶面板。

  • 发信系统:统一发信子系统。它由一个LED和一个数字蜂鸣器组成,它将不同的信号转化为目标客户端的编码。它将不同的信号转换为客户端代码,客户端代码可以根据需求运行各种代码。

  • 运动检测:用PIR传感器实现运动检测。当有人被检测到,它触发一个信号来引起注意。

    前面说了,晶振相当于一个人的心脏,如果一个人心跳没了,那么人再好也没有用了。同样,单片机没了晶振部分,程序再好,电源再好也没有用,也没法正常工作。所以说晶振部分是重中之重。

表现层负责与用户的交互。它包含图形界面的处理(菜单和页面)并包含管理子系统。

  • UI管理:在这个子系统中,我们定义了图像对象。一个菜单列表被显示出来供用户选择。一个菜单项可以显示出子菜单或者一个页面。用户可以通过输入显示在其上的索引来选择菜单项。通过按'Escape'键来返回上级菜单。如果一个菜单项是一个页面,选择后将会将这个页面显示出来。页面可以显示出其上面的信息,并等待用户输入来改变它的内容,此时按下'Escape'键就会显示出用户菜单。如果用户输入错误,可以通过按'Backspace'键删除答案。根据答案的正确与否,相应的信号将会被触发。

  • 内容管理:这个子系统提供显示在屏幕上的内容,包括各种算术运算的各种难度级别的生成算法。客户端代码(页面)会向这个子系统请求内容。

简单的类框图如下。这些图像展示了基本的框架,帮助你更容易的理解实际的类实现。

硬件管理  

MFK_InputDevice将Keypad2和AdKeyboard统一为同一个接口。它处理它们的事件,并向其客户端提供一组新的编码,如下所示。

图2:输入子系统

按键映射:

Keypad Button Key Value (hex) 
Matrix '0' 0x30
Matrix  '1'  0x31
Matrix  '2'   0x32
Matrix  '3'  0x33
Matrix  '4'  0x34
Matrix  '5'  0x35
Matrix  '6'  0x36
Matrix  '7'  0x37
Matrix  8 '8'  0x38
Matrix  9 '9'  0x39
Matrix  * Escape 0x1B
Matrix  # Enter 0x0D
AD  S1 Backspace 0x08
AD S2 F1 0x80
AD S3 F2 0x81
AD S4 F3 0x82
AD S5 F4 0x83

MFK_OutputDevice继承自SerialLCD类。它结合SerialLCD类的功能,并对其进行了增强。

图3:输出子系统

一个信号模式从信号源产生。一个模式连同它的索引被储存在信号控制器中。想要启动一个信号模式非常简单,只要用它的索引从信号控制器调用它。


图4:发信系统

在硬件管理层顶层的是MFK_Hardware类。它只会所有其他硬件设备,对客户端隐藏多余的复杂性。举例来说,PIRMotionandSignalController没有被暴露给客户端。但是输入和输出设备必须要向外界开放,因为UI系统需要对这些功能的直接访问。信号模式也是在这个类里构建的,可以通过索引来访问他们。

图5:硬件管理

表现层

这一层负责与用户进行交互,它提供了视觉元素和内容。

ContentFactory根据toContentTypeEnum和ContentLevelEnum创建ContentProviders。客户端得到ContentFactory的实例,之后他可以请求一个content provider。

 

图6:内容管理

VisualItem是所有的视觉元素(菜单和页面)的基类。它还将硬件管理和呈现结合起来。'show' 和'msgbox'方法通过调用和回调VisualItem提供的方法使用输出设备(MFK_OutputDevice)和输入设备(MFK_InputDevice) 。'msgbox'方法也有能力启动一个信号模式,只要调用硬件(MFK_Hardware)的'signal'方法就可以了。

菜单就像他的名字一样,提供了一系列的菜单项可以选择。用户可以通过一个菜单项前面的索引选择它,然后菜单 'show' VisualItem。

Pageis是显示内容的视觉工具。除了娱乐内容,它会等待用户的输入。用户'Enter'她的答案,显示信息告知她对错。显示信息之后,就需要从内容管理获取新的内容。

Chapter是ContentProvider和Page之间的中间类。当一个页面被第一次显示时,与其相关的chapter和ContentProvider就会被创建。用户的答案直接由chapter处理,并由chapter判断其对错。Chapter也对页面内的学习会话进行统计。FunChapter是一种不向用户要求答案的chapter,QuizChapter是限时的chapter。在一个quiz chapter中,问题只有在时间截止之前才能回答。

图7:UI管理

实现

我希望你已经清楚了系统的通用结构。现在,是时候深入到代码中去,那里是真正的乐趣开始的地方。

我想以MathForKid.ino开始。它是上传到Arduino主板上的主要代码。

// File: MathForKid.ino// hardware managementMFK_Hardware* hw;
 // presentationMenu* mainMenu;
 void setup() {
    // for debugging purposes    Serial.begin(9600);
  
    // get the instance and initialize it    hw = MFK_Hardware::getInstance();
    hw->begin();
 
    // create user interface    CreateUI();
    // show the main menu    mainMenu->show();
}
 void loop() {
    // update hardware    hw->update();
    
    // update active visual item    VisualItem *v = VisualItem::getActiveItem();
    if(v!=NULL)
        v->update();
}

就这么多。在Arduino上运行你的应用吧。好吧,也许解释一下会更好。

正如我在“软件设计”那部分开头所说的,我们有两个部分:一个用来硬件管理,另一个用来展示。它们在代码顶部定义为全局变量,我们在 'setup'函数中将它们初始化。'loop'函数调用代码来更新它们。

事实上,CreateUI方法也是在这个文件中实现的。当用户开始交互时,它创建用户接口。mainMenu、所有的子菜单和一切页面都是这个方法产生的,chapter的属性也是其赋予的。

void CreateUI() {
    mainMenu = new Menu("main");
 
    // addition    Menu* m = new Menu("+");
    mainMenu->addMenuItem(m);
 
    // level-1 page    Page* p = new Page("L1");
    p->setChapterProperties(Chapter::NormalChapter, \
            ContentFactory::Addition, ContentFactory::Level1Content);
    m->addMenuItem(p);
 
    // level-2 page    p = new Page("L2");
    p->setChapterProperties(Chapter::NormalChapter, \
            ContentFactory::Addition, ContentFactory::Level2Content);
    m->addMenuItem(p);
...

我们接着来看这个应用的设计模式。

就像你所想的,MFK_Hardware是Facade模式的一个例子。它将底层的硬件管理问题隐藏起来,并对客户端提供了干净的接口。它同时也是 Singleton模式的代表,因为整个系统运行时其只产生一个实例。为了实现这个功能,MFK_Hardware的构造器、复制和赋值操作都被声明为私有方法。

// File: MFK_Hardware.h// private constructor to achieve singleton pattern    MFK_Hardware();
    MFK_Hardware(MFK_Hardware const&); // copy disabled    void operator=(MFK_Hardware const&); // assigment disabled

你只能通过getInstance静态方法访问它们,这个方法是公共的:

// File: MFK_Hardware.h// static method to get the instance     static MFK_Hardware* getInstance() {
        static MFK_Hardware hw;
        return &hw;
    };

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >

基于单片机的光控路灯设计含程序和仿真图本设计是以光敏电阻对于外界光线强弱的感应能力为基础进行的路灯自动化控制系统设计。当光线强度...

生成海报
点赞 0

thePro

我还没有学会写个人说明!

相关推荐

基于Arduino的显示测量环境数据设计

题目: 基于Arduino的显示测量环境数据设计 目录 基于Arduino的显示测量环境数据设计... 3 第一章 课题任务... 4 1.1课题任务... 4 1.2任务分工... 4 1.3设计条件... 4 第

2021全国电设(F题)灰度传感器——循迹红线

基于灰度传感器的循迹(红色循迹) 通过参加全国电子设计大赛F题总结出识别红色线路的循迹方法——灰度传感器 灰度传感器的工作原理 灰度传感器利用不同颜色的检测面对光的反射程度不同,光敏电阻对不同检测面返