Quantcast
Channel: 英特尔开发人员专区文章
Viewing all articles
Browse latest Browse all 583

畅玩游戏:英特尔® Edison 与 XADOW 可穿戴套件

$
0
0

Xadow

大多数人第一次看到英特尔® Edison 模块安装在 Arduino* 扩展板上时,会认为它太大了,无法移动使用。 因此许多人认 为 Edison 在紧凑型或可穿戴设备上不会发挥太大的作用。

如下图所示,英特尔® Edison 模块的体积非常小。 但它的用法并不简单,因为用来连接外设的针脚极其的小:英特尔 Edison 开发板上的 Hirose 有 70 个针脚,其长度仅为 1 厘米。使用 Seeed 提供的面向英特尔® Edison 的  Xadow 可穿戴套件可以完全解决这一问题。 该套件包含设计紧凑型可穿戴设备时需要的所有适配器和小型传感器。

它包含具有不同特性的各种小型扩展板。 所有扩展板可以用一根柔性扁平电缆 (FFC) 连接起来。 你可以用菊花链连接扩展 板,为设备提供所需的特性。

套件所包含的内容如下所示:

Xadow 套件

本文 “可穿戴套件组件” 部分对这些组件进行了详细介绍。

    • 电池。
    • Xadow – Edison:插入英特尔® Edison 开发板的主要连接器。
    • Xadow – Edison 编程器:通过 USB 连接英特尔® Edison 和 PC 的模块。
    • Xadow – Edison SD:连接 SD 内存卡的模块。
    • Xadow – OLED: 128x64 单色 OLED 显示屏。
    • Xadow – 蜂鸣器。
    • Xadow – 振动电机。
    • Xadow – Q 触摸传感器:触摸按钮。
    • Xadow – NFC: NFC 读卡器。
    • NFC 标签 – 3 个 NFC 标签(图中显示了 1 个)。
    • Xadow – 3 轴加速计。
    • Xadow – 气压计 BMP 180:气压计和温度计。
    • 数字 RGB LED Flexi-Strip:带有 5 个受控 RGB LED 的条带。
    • 整套 FFC 电缆。
    • 电源线(图中未显示)。

简介

开始描述流程之前,我觉得有必要跟大家阐述一下我在处理该项目时所发现的一些特殊性、问题及其解决方法。 首先,强烈 建议更新开发板固件

如欲查看当前版本,请使用以下命令:

configure_edison –version

截至本文撰写时,当前开发板固件的版本是 159。

还建议更新所有安装的库。 更新时需要连接互联网。

opkg update

opkg upgrade

本文的所有代码示例均面向 Arduino* IDE。 Seeed 套件的开发人员没有提供面向其他 IDE 的示例。

我尝试过将该开发板用于面向物联网和 С++ 的英特尔® XDK,但并未成功。 原因可能是开发板电路与标准 Arduino 扩展板 的不同。 I2C 接口也存在一些问题,而且加速计运行有时不太稳定。 不过,在游戏设置中,它在 OLED 显示屏之后连接,运行 比较顺畅。 无法成功运行气压计/温度计开发板。

有时无法连接开发板和 Arduino* IDE,或者无法编译或传输 sketch。 在这种情况下,需要终止 sketch 在开发板上的运行 :

systemctl stop clloader

然后清空 /sketch 文件夹,并关闭所有在 PC 上运行的 Arduino* IDE。 (使用“立即关闭”)关闭英特尔® Edison 开发板,并通过长按 PWR 按钮直至 LED 变亮来重新打开开发板。

电源接通后,如果需要 Edison 开发板运行 sketch,可以创建在启动时运行的文件: 创建文件夹 /etc/init.d。  在 该文件夹中创建名为 automateSketch.sh 的文件,文件包含以下内容:

#!/bin/sh

exec /sketch/sketch.elf /dev/ttyGS0 /dev/ttyGS0

创建并保存 automateSketch.sh 之后,使其成为可执行文件:

chmod +x automateSketch.sh

然后将 automateSketch.sh 添加至启动列表:

update-rc.d automateSketch.sh defaults

入门

需要在 PC 上安装所有英特尔 Edison 驱动程序。 与该套件的模块之间的所有交互均通过 Arduino* sketche 执行,因此需 要安装 Arduino* IDE。 可以从 www.arduino.cc下载。

如欲操作开发板,需要连接 Xadow-Edison 编程器模块。 请注意,两个 USB 端口都已插入:一个用于提供电源,一个用于 连接 Arduino* IDE。 开发板上的开关应设在 "Device"位置。 请使用 Boards Manager 在 Arduino* IDE 中选择 英特尔 Edison 开发板。

Edison 操作系统启动后(大约 30 秒),在 PC 的 Device Manager 中查找虚拟端口的编号。

Xadow 入门

在 Arduino* IDE 中选择英特尔® Edison 虚拟 Com 端口 (COM25)。 可以使用 USB 串行端口 (COM29) 连接控制台,比如通 过 Putty。

Arduino* 库

与模块交互时,库必不可少。 可以从 github.com/Seeed-Studio/Xadow_Edison_Demos下载库(单个 ZIP 文件)。 可能无法一次 性安装整个程序包,因此需要在 IDE 菜单中添加包含所需库的文件夹。

连接模块

插入模块之前,请关闭英特尔 Edison 的电源,以降低损坏组件的几率。 如果尝试热插拔模块,sketch 应停止加载。

用柔性扁平电缆 (FFC) 连接所有模块。 电缆的长度、宽度各不相同;电缆宽度必须与连接器相匹配。 所有电缆插入时,蓝 色边朝上,针脚朝下。 开发板上的连接器分为两种。 第一种是向上打开的连接器,像一个盖子。 打开连接器,轻轻插入电缆 (约 3 毫米),然后关闭连接器。

连接模块

第二种连接器是一个滑动板夹,使用起来不太方便。 需要撬开板夹的两端,向外拔出 1 毫米。请小心操作,我曾不小心折 断了一个针脚。 稍微用力往里插电缆(约 3 毫米)。 然后将连接器按下去。 电缆必须牢牢固定在连接器上。

带有连接器的模块

所有模块的另一端都有连接器。 模块和主板的一边还有斜角。 开发板连接后,这些斜角应该在同一边。 如下图所示,斜角 都在左边。

连接后的模块

可穿戴套件组件

正如本文开头所述,套件的每个部件都可用来创建不同类型的可穿戴技术(取决于你如何组合与编程)

电池

 

该系统的电池为标准的 3.7 V、500 mAh 锂电池。

电池组

Xadow - Edison

 

Xadow Edison

它是用来连接 Edison 模块的主板,比模块稍大一些。 如果将 Edison 模块插入其插槽,连接的非常牢固,不过为了提高安 全性,可以将它连接至 Arduino* 模块的螺钉。

开发板有一个针对电池的连接器和四个针对扩展板的连接器。 上部的连接器用于连接 Edison 编程器开发板、两边的连接器 用于连接传感器和制动器开发板,底部的连接器用于连接 SD 卡模块。

还有两个按钮:PWR 和 FW_RCVR。 长按 PWR 可以打开和关闭设备 — 长按 9 秒关闭设备,长按 2 秒打开设备。

电池连接器旁的绿色 LED 表示电源状态。 闪烁表示通过 USB 供电。 常亮表示正在充电。 关闭表示充电完成。

开发板和电池是保持 Edison 运行的必要条件。

电池和开发板

这款紧凑型设备的功能给我留下了非常深刻的印象:小型开发板和电池就是一台采用真实 Linux* 操作系统、可通过 WiFi* 访问的迷你 PC。

Xadow - Edison 编程器

 

PC 连接

这个开发板用于连接 PC。 可以用于调试和通过 PC 提供电源。 它包含两个 Micro USB 连接器:

  • UART 连接器通过 COM 端口连接 PC 并提供电源。
  • Device/Host 连接器运行 Arduino* IDE 的开发板。 还有一个用于选择 "Device"或 "Host"模式的开关。 就 Arduino* 而言,选择 "Device” 模式。

Xadow - Edison SD

 

Xadow Edison SD

这个开发板包含一个用于插入 SD 内存卡的连接器。 它借助最宽的电缆连接至主板底部的插槽。

可以在设备目录 /dev/mmcblk1 中查找 SD 卡。

安装时,请遵循标准 Linux 规程。 创建一个空文件夹,比如:

mkdir /home/data

然后将卡放在文件夹中:

mount /dev/mmcblk1   /home/data 

如需在 Linux 启动时自动安装卡,将以下字符串添加至 /etc/fstab 文件:

/dev/mmcblk1   /home/data     auto    auto 0

0

Xadow - OLED 12864

 

套件中包含的显示屏为 128x64 OLED 显示屏。

Xadow OLED

请访问 Seeed 网址,查看规格

该显示屏通过 I2C 接口连接。 设备地址为 0x3C。

以下代码为屏幕显示示例:

#include <Wire.h>
#include <SeeedOLED.h>

void setup()
 {
  Wire.begin();
  SeeedOled.init();  //initialze SEEED OLED display
  SeeedOled.clearDisplay();          //clear the screen and set start position to top left corner
  SeeedOled.setBrightness(255);
  SeeedOled.setNormalDisplay();      //Set display to normal mode (i.e non-inverse mode)
  SeeedOled.setPageMode();           //Set addressing mode to Page Mode
  SeeedOled.setTextXY(0,0);          //Set the cursor to Xth Page, Yth Column
  SeeedOled.putString("Xadow and Edison"); //Print the String

  SeeedOled.setTextXY(7,0);          //Set the cursor to Xth Page, Yth Column
  for(int k = 0; k < 128; k++)
  {
    SeeedOled.sendData(k);
  }
}

void loop() {
}

屏幕包含 8 排,每排 16 个字符,帧速率为每秒数帧。

我们使用了以下函数:

  • init() – 初始化 Seeed OLED 帧,并将显示屏设置为 Normal 模式。
  • clearDisplay() – 清空整个屏幕。 应在重新打开之前或滚动取消激活之后使用。 该函数还可以将光标设 置在左上角。
  • setBrightness(unsigned char Brightness) – 设置 OLED 显示屏的对比度。 亮度范围是 0 - 255。
  • setNormalDisplay() – 将显示屏设置为 mode(non-inverse) 模式。
  • setPageMode() - 将显示屏设置为页面寻址模式。
  • setTextXY(0,0) - 将文本位置(光标)设置为 Xth Page,Yth Column。 X 范围为 0 - 7。 Y 范围为 0 - 127。
  • putString(cont char *string) - 从 setTextXY(X,Y) 设置的当前地址-指示器开始将字符串印在 OLED 屏幕上。
  • sendData(unsigned char Data) – 将一字节发送至屏幕。

如欲了解其他函数和信息,请访问 www.seeedstudio.com/wiki/OLED_Frame 和 SeeedOLED.h 文件。

Xadow - 蜂鸣器

 

Xadow 蜂鸣器

该蜂鸣器连接至针脚 11 和 13。 这两个针脚必须同时关闭和打开。 向它们发送 0 或 1,可以使蜂鸣器发出声音。

根据我的经验,最简单的方法是将其中一个针脚预设值为 1,然后改变另一个针脚的状态,就可以使蜂鸣器发出声音。

以下代码为声音输出示例:

void buzzerInit()
{
    pinMode(11,OUTPUT);
    pinMode(13,OUTPUT);
}

void buzzerOn()
{
    digitalWrite(11,HIGH);
    digitalWrite(13,HIGH);
}

void buzzerOff()
{
    digitalWrite(11,LOW);
    digitalWrite(13,LOW);
}

void buzzerSignal(int t_ms)
{
    unsigned long cur = millis();
    while((millis()-cur) < t_ms )
    {
        buzzerOn();
        delayMicroseconds(150);
        buzzerOff();
        delayMicroseconds(150);
    }
}

void setup()
{
    buzzerInit();
    buzzerSignal(1000);
}

void loop()
{
}

由于是基于软件进行的回放,因此声音不太清晰。 最好使用脉宽调制。 值得一提的是,为面向物联网和 С++ 的英特尔® XDK 制作的 sketch 副本无法工作 — 没有发出声音。

Xadow - 振动电机

 

Xadow 振动电机

控制振动电机的方法可以与蜂鸣器相同:通过将针脚 10 和 11 设置为相同的值来打开和关闭振动电机。 以下示例代码为控 制方法:

// Xadow - Vibro
void vibroInit()
{
    pinMode(11,OUTPUT);
    pinMode(10,OUTPUT);
}

void vibroOn()
{
    digitalWrite(11,HIGH);
    digitalWrite(10,HIGH);
}

void vibroOff()
{
    digitalWrite(11,LOW);
    digitalWrite(10,LOW);
}

void setup()
{
    vibroInit();
    vibroOn();
    delay(500);
    vibroOff();
}

void loop()
{
}

与蜂鸣器一样,(将另一针脚预设为 1 之后)仅需控制一个针脚。

Xadow - Q 触摸传感器

 

Xadow Q 触摸传感器

该开发板背面有三个触摸按钮,通过 I2C 接口连接;地址为 0x1B。

按钮非常敏感。 它们甚至还可以通过几层纸或膜感知触摸,因此可以用照片盖住按钮。

以下示例代码返回了所按按钮的编号:

#include <Wire.h>
#include "Seeed_QTouch.h"

void setup()
{
    Serial.begin(9600);
    Wire.begin();
}

void loop()
{
    int tn = QTouch.touchNum();

    if(tn>=0)
    {
        Serial.print("KEY");
        Serial.print(tn);
        Serial.println(" touched");
    }

    delay(10);
}

Xadow - NFC

 

Xadow NFC

NFC 读卡器支持 I2C、SPI 和 UART 连接。 运行频率为 13.56 MHz。 它支持读写操作、ISO14443 Type A 和 Type B 协议 ,以及 P2P。 还有一根带有连接线的天线。 如欲了解更多信息,请访问 http://www.seeedstudio.com/wiki/Xadow_-_NFC

套件包含 3 个空白可写入 NFC 标签。

空白可写入标签

该模块要求安装 NDEF、PN532、PN532_HSU、PN532_I2C 和 PN532_SPI 库。 安装通用 Seeed 示例库提供的这些库。

如欲测试标签和读卡器,可以使用 NDEF 库中的示例程序 readTag。 它可阅读标签的数据,并将其显示在控制台中。

套件的标签有序列号。 由于还没有格式化,查询时会返回以下输出:

Tag is not NDEF formatted.
NFC Tag - Mifare Classic
UID 6E A5 0B 01

经 NDEF 库中的 FormatTag 示例完成格式化后,才能将数据写入标签。

如欲将数据写入标签,可以使用 NDEF 库中的 WriteTag 示例。

如下所示为从标签读取数据的结果:

NFC Tag - Mifare Classic
UID 5E B1 FB 01

NDEF Message 1 record, 28 bytes
  NDEF Record
    TNF 0x1 Well Known
    Type Length 0x1 1
    Payload Length 0x18 24
    Type 55  U
    Payload 00 49 6E 74 65 6C 20 45 64 69 73 6F 6E 20 77 69 74 68 20 58 61 64 6F 77  .Intel® Edison with Xadow
    Record is 28 bytes

Xadow - 3 轴加速计

 

Xadow 轴加速计

它是一个 3 轴加速传感器。 测量范围为 ±16 G,通过 I2C 接口连接,地址为 0x53。 该传感器安装在 ADXL345 芯片上 。 使用时,需要安装套件中的 DigitalAccelerometer_ADXL345 库。

有四种测量范围,其准确率和换算率分别为: ±2 g, ±4 g,±8 g,±16 g。

芯片数据表位于此处: pdf1.alldatasheet.com/datasheet-pdf/view/254714/AD/ADXL345.html

数据以 16 位数的形式返回。 库以 int 变量的形式返回数字,因此需要作出如下调整:

void correct(int &a)
{
 if( a > 32767 )
     a = -(65536 - a);
}

如果适用 ±2g 范围,按照数据表,返回值需要除以 256。 如前所述,我在使用加速计时遇到过一些问题。 有时检测不到 ,有时 Linux 控制台返回 I2C 错误。 不过,将屏幕连接至主模块,然后将加速计连接至屏幕时,运行比较稳定。 也许该传 感器没有终端电阻。

Xadow - 气压计 BMP 180

 

Xadow 气压计 BMP

该开发板包含一个气压计和一个温度计。 压力测量范围为 300–1100 hPa(比如 -500m 至海拔 +9000m)。 它通过 I2C 接口连接,使用 0x77 地址。

遗憾的是,我无法运行该开发板,可能是因为 I2C 接口出现了错误。 出现的问题可能与加速计的相同。 我测试了其他 Xadow 套件,也无法工作。

Xadow - Breakout

 

Xadow Breakout

该开发板用来连接标准传感器。 它包含以下针脚: 3.3 V,SCL,SDA,TX0,GND,SCK,MOS1,MOS0,A5。 还有两个供标准 "Seeed"模块插入连接器的垫片。 一个标记为 "Serial",另一个标记为 "I2C"。 可以连接  LED 条。

数字 RGB LED Flexi-Strip

 

RGB LED Flexi-Strip

条带上包含 5 个 RGB WS2812B LED。 只需一根线就可以控制这些 LED。

需要进行焊接,以牢固地连接它们,如下图所示。 使用 Xadow-Breakout 开发板。

LED 条带示意图

Flexi Strip

数据由软件发送,因此有时会出现数据传输错误,导致 LED 可能随机闪烁。

以下为 "Running light"程序:

#include <Wire.h>
#include "Seeed_ws2812.h"

#define SIG_PIN 12
#define LEN_NUM 5

WS2812 strip = WS2812(LEN_NUM, SIG_PIN);

void setup() {
  strip.begin();
  //Serial.begin(115200);
}

int pos = 0;

void loop() {
  strip.WS2812SetRGB(pos,255,0,0);
  strip.WS2812Send();
  delay(100);

  strip.WS2812SetRGB(pos,0,0,0);
  strip.WS2812Send();
  delay(100);

  pos = (pos+1)%LEN_NUM;
}

创建游戏

在想着如何使用这个套件时,我想到了创建游戏的主意。

在游戏中,LED 条连接至游戏盒子的外侧。 随着 LED 的亮起和关闭,玩家可以根据 LED 的颜色将盒子朝某个方向倾斜 45 度。如果中间的 LED 变绿,应将盒子向前倾斜(远离你的方向)。 如果中间的 LED 变红,应将盒子朝你本人的方向倾斜。 如果最右边的 LED 变绿,将盒子朝右倾斜,但如果变红,则朝左倾斜。

设计该游戏的目的不仅是测试反应,而且可以让玩家先思考,再行动。

创建游戏

如欲创建游戏,需要以下组件:

  • 陀螺仪
  • OLED 显示屏
  • LED 条
  • 连接条带的扩展模块
  • 按钮板
  • 电池

首先在电池连接器的一侧连接 Breakout 开发板和传感器按钮。 在另一侧连接屏幕和陀螺仪。 我把几张较厚的彩色纸板粘 贴起来,制成盒子。 然后面向屏幕剪出一个开口。 在屏幕下方连接按钮板;大家应该还记得,按钮的敏感度非常高。 在正面 的按钮上方画上符号。

将纸上方的所有开发板用透明胶带连接起来,以避免损坏。

用透明胶带保护开发板

sketch 开始在 Linux 中自动运行。

如欲启动游戏,长按主模块上的 PWR 按钮约 9 秒钟。 如欲关闭游戏,同样按住该按钮越 3 秒钟。

游戏启动时,会出现一个菜单,你可以在菜单中开始游戏(按下按钮 A)或显示 “帮助”(按下按钮 B)。 如 欲关闭 “帮助” 屏幕,按下箭头按钮。

五个回合

该游戏包括五个回合。 每一个回合亮起一个随机 LED,你需要将盒子朝某个方向倾斜。 如果倾斜方向正确,屏幕将显示 “你赢了!” 如果错误或超时,屏幕将显示 “你输了!”

如欲观看示例视频,请访问 https://www.youtube.com/watch?v=1Tjff7wDPIQ

所有游戏代码都在一个文件中。 我已尽量简化,因此分析起来非常简单。

游戏 sketch 代码

#include <Wire.h>
#include <Seeed_ws2812.h>
#include <SeeedOLED.h>
#include <Seeed_QTouch.h>
#include <ADXL345.h>

// game state
const int stateMenu = 1;
const int stateCount = 3;
const int stateHelp = 4;

// buttons
const int keyBack = 0;
const int keyA = 1;
const int keyB = 2;

// LED strip
const int ledSigPin =  12;
const int numLed = 5;

// answers
const int answerLeft = 1;
const int answerRight = 2;
const int answerUp = 3;
const int answerDown = 4;

const int colorGreen = 1;
const int colorRed = 2;

const int numLevels = 6;
const int answerID = 5;

const int angleScale = 100;
const int angleReact = 100;//tangent of actuating angle * angleScale

int numWins;// number of wins
int numLosts;// number of losses
int gameState;// game state

const int numSets = 5;// number of rounds in a game

// level coding
int levels[numLevels][numLed+1] = {  {colorGreen,0,0,0,0,answerLeft},
                             {colorRed,0,0,0,0,answerRight},
                             {0,0,0,0,colorGreen,answerRight},
                             {0,0,0,0,colorRed,answerLeft},
                             {0,0,colorGreen,0,0,answerUp},
                             {0,0,colorRed,0,0,answerRight}};
// correct answer
int rightAnswer;

WS2812 strip = WS2812(numLed, ledSigPin);
ADXL345 adxl;

// current game level
int gameLevel;

// initialization of accelerometer
void initAccel()
{
  adxl.powerOn();

  //set activity/ inactivity thresholds (0-255)s
  adxl.setActivityThreshold(75); //62.5mg per increment
  adxl.setInactivityThreshold(75); //62.5mg per increment
  adxl.setTimeInactivity(10); // how many seconds of no activity is inactive?

  //look of activity movement on this axes - 1 == on; 0 == off
  adxl.setActivityX(1);
  adxl.setActivityY(1);
  adxl.setActivityZ(1);

  //look of inactivity movement on this axes - 1 == on; 0 == off
  adxl.setInactivityX(1);
  adxl.setInactivityY(1);
  adxl.setInactivityZ(1);

  //look of tap movement on this axes - 1 == on; 0 == off
  adxl.setTapDetectionOnX(0);
  adxl.setTapDetectionOnY(0);
  adxl.setTapDetectionOnZ(1);

  //set values for what is a tap, and what is a double tap (0-255)
  adxl.setTapThreshold(50); //62.5mg per increment
  adxl.setTapDuration(15); //625us per increment
  adxl.setDoubleTapLatency(80); //1.25ms per increment
  adxl.setDoubleTapWindow(200); //1.25ms per increment

  //set values for what is considered freefall (0-255)
  adxl.setFreeFallThreshold(7); //(5 - 9) recommended - 62.5mg per increment
  adxl.setFreeFallDuration(45); //(20 - 70) recommended - 5ms per increment

  //setting all interrupts to take place on int pin 1
  //I had issues with int pin 2, was unable to reset it
  adxl.setInterruptMapping( ADXL345_INT_SINGLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_DOUBLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_FREE_FALL_BIT,    ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_ACTIVITY_BIT,     ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_INACTIVITY_BIT,   ADXL345_INT1_PIN );

  //register interrupt actions - 1 == on; 0 == off
  adxl.setInterrupt( ADXL345_INT_SINGLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_DOUBLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_FREE_FALL_BIT,  1);
  adxl.setInterrupt( ADXL345_INT_ACTIVITY_BIT,   1);
  adxl.setInterrupt( ADXL345_INT_INACTIVITY_BIT, 1);
}

void initGame()
{
  SeeedOled.clearDisplay();
  SeeedOled.setNormalDisplay();
  SeeedOled.setPageMode();

  switchToMenu();
}

void setup()
{
    strip.begin();
    SeeedOled.init();
    initAccel();
    initGame();
}

void cleanLED()
{
  for( int led = 0; led < numLed; led++ )
      strip.WS2812SetRGB(led,0,0,0);
}

void updateLED()
{
  strip.WS2812Send();
}

void drawMenu()
{
  SeeedOled.clearDisplay();
  SeeedOled.setTextXY(0,2);
  SeeedOled.putString("Edison Game");

  SeeedOled.setTextXY(2,1);
  SeeedOled.putString("A - Start");

  SeeedOled.setTextXY(4,1);
  SeeedOled.putString("B - Help");
}

void drawHelp()
{
  SeeedOled.clearDisplay();

  char *messages[] = {    "Center green -","tilt forward." ,"Center red -" ,"tilt backward.","Green edge -" ,"tilt same side." ,"Red edge - tilt","other side."
 };

   for( int k = 0; k < 8; k++ )
   {
      SeeedOled.setTextXY(k,0);
      SeeedOled.putString(messages[k]);
   }
}

void makeNewLevel()
{
    gameLevel = rand() % numLevels;
    rightAnswer = levels[gameLevel][answerID];
}

void showGameStart()
{
  SeeedOled.clearDisplay();
  SeeedOled.setTextXY(0,0);
  SeeedOled.putString("Press Start");
}

int getKeys()
{
    int tn = QTouch.touchNum();
    return tn;
}

int haveTime = 20;

void showGameLevel()
{
  for( int k = 0; k < numLed; k++ )
  {
     int color = levels[gameLevel][k];
     switch(color)
     {
         case colorRed  : strip.WS2812SetRGB(k,255,0,0); break;
         case colorGreen: strip.WS2812SetRGB(k,0,255,0); break;
         default        : strip.WS2812SetRGB(k,0,0,0);
     }
  }

  updateLED();
}

void switchToSets()
{
  numWins = 0;
  numLosts = 0;
  switchToPlay();
}

//------------------------------------

void switchToPlay()
{
  cleanLED();
  updateLED();

  SeeedOled.clearDisplay();
  SeeedOled.setTextXY(3,3);
  SeeedOled.putString("Get ready!");

  int waitTime = 2000 + (rand()%4)*500;

  delay(waitTime);

  makeNewLevel();

  SeeedOled.setTextXY(3,3);
  SeeedOled.putString("");

  haveTime = 100;
  gameState = stateCount;
}

void doPlay()
{
  if( haveTime >= 0 )
  {
    SeeedOled.setTextXY(3,1);
    char str[100];
    sprintf(str,"-- TILT NOW --");
    SeeedOled.putString(str);

    SeeedOled.setTextXY(5,6);
    sprintf(str,"%d  ",haveTime);
    SeeedOled.putString(str);

    showGameLevel();

    int answerID = getAnswerID();

    haveTime--;

    if( answerID !=0 || haveTime < 0)
    {
      char *message;
      if( answerID != rightAnswer || haveTime < 0)
      {
        numLosts++;
        message = "You lose!";
      }
      else
      {
        numWins++;
        message = "You win!";
      }

      cleanLED();
      updateLED();

      SeeedOled.clearDisplay();
      SeeedOled.setTextXY(3,4);
      SeeedOled.putString(message);

      delay(1000);

      if( numWins + numLosts == numSets )
      {
        switchToMenu();
      }
      else
      {
        switchToPlay();
      }
    }
  }
}

//-----------------------

void switchToHelp()
{
    drawHelp();
    gameState = stateHelp;

    cleanLED();
    updateLED();
}

void doHelp()
{
  cleanLED();
  updateLED();

  int key = getKeys();

  if( key == keyBack )
      switchToMenu();
}

//-----------------------
void switchToMenu()
{
  drawMenu();
  gameState = stateMenu;

  cleanLED();
  updateLED();
}

void doMenu()
{
  int key = getKeys();

  if( key == keyA )
      switchToSets();

    if( key == keyB )
      switchToHelp();
}
//-----------------------

void correct(int &a)
{
 if( a > 32767 )
     a = -(65536 - a);
}

int  getAnswerID()
{
  int x,y,z;
  adxl.readXYZ(&x, &y, &z);

  correct(x);
  correct(y);
  correct(z);

  int v1 = angleReact;
  if( z != 0 )
      v1 = y*angleScale/z;

  if( v1 > angleReact )
    return answerRight;

  if( v1 < -angleReact )
    return answerLeft;

  int v2 = angleReact;

  if( z != 0 )
      v2 = x*angleScale/z;

  if( v2 > angleReact )
    return answerUp;

  if( v2 < -angleReact )
    return answerDown;

    return 0;
}

void gameStep()
{
  switch(gameState)
  {
    case stateCount: doPlay();break;
    case stateMenu:  doMenu();break;
    case stateHelp:  doHelp();break;
  }
}

void loop()
{
    gameStep();
    delay(10);
}

关于作者

Valery Mosyagin 是一名正式的英特尔软件创新者。 他居住在俄罗斯下诺夫哥罗德市。 他拥有数学与计算机科学专业的硕 士学位。 他曾经在英特尔 OpenCV 团队任职六年,之后前往日本,在 Brain Research Institute 负责开发用于生物实验的软 件 — 即网络流量分析软件和无线覆盖与传播软件。 他在很长的一段时间里教小孩如何编程。 他感兴趣的领域非常广泛 ,有虚拟现实、游戏开发、微控制器,和物联网。


Viewing all articles
Browse latest Browse all 583

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>