吹蟑螂游戏机基于纳芯微NSPGD1M006DT04设计
该项目使用了NSPGD1M006DT04,实现了游戏机的设计,它的主要功能为:实现了一个双人游戏机,双方通过吹气的方式移动中间的 LED。
标签
Arduino
数字逻辑
I2C
NSPGD1M006DT04
Zoologsit
更新2025-12-02
40
KiCad文件
全屏

所选任务介绍

这次展示的是使用表压传感器NSPGD1M006DT04设计一个双人对战的“吹蟑螂游戏机”。

在神秘的南亚次大陆,存在着一个神奇的国度,那里的人们经过几千年的洗礼,能够做到和各种小动物和平共存。在当地有着一个古老的游戏:吹蟑螂比赛。双方选手将一直蟑螂放置在玻璃管中,然后同时吹气,能够将蟑螂吹到另外一方的选手就获得了胜利。

image.png

很多人第一次听到这种游戏的时候,都会由衷感叹:印吹死挺!

 

项目描述

项目使用 WS2812 LED 作为指示灯,它是一款集控制电路与发光电路于一体的智能外控LED光源,其外型与5050LED灯珠相同,每个元件即为一个像素点。它采用单线归零码通信方式,通过一根信号线即可实现数据的接收与解码,支持级联控制,理论上可无限扩展

游戏方法非常简单:

1.      双方比赛开始后,对着自己面前带有传感器的盒子吹气

2.      中间有24LED,其中2LED会亮起红色,当一方吹气后,LED会向着对方方向移动

3.      红色LED触及一方最后一个 LED后游戏结束

4.      按下按钮会重新开始新的对战


芯片选型/简短的硬件介绍

项目实际上有三块 PCB

1.      NSPGD1M006DT04 的转接板,方便我们实现这个传感器和 Arduino 的连接。NSPGD1M006DT04是表压传感器。表压传感器(Gauge Pressure Sensor)是一种测量相对压力的传感器,即相对于大气压力的压力值。相对的还有绝压传感器(Absolute Pressure Sensor)是一种测量相对于真空或绝对零点的压力的传感器。

2.      带有 Arduino 的控制板,位于游戏机的最左侧和最右侧,理论上需要设计一个左侧和右侧板,但是这里为了成本考量,将二者放在同一块板子上,根据需要焊接左侧或者右侧;

3.      WS2812 灯板,这个位于中间

出于成本考虑,板子长度都是小于10cm的,中间使用 U形状的 2.54mm排针进行连接

 

方案框图 + 设计思路

 

 原理图、PCB设计

1.NSPGD1M006DT04 的转接板电路板和PCB

image.png

image.png

2.控制板电路和PCB设计,控制板上也带有 WS2812 LED,这样可以最大化利用空间

具体使用的时候,需要额外导线将右侧Arduino TX 连接左侧的 RX

3.WS2812 电路板和 PCB,输入VCC ,控制信号(DIN)和 GND 即可,多余的引脚主要是为了保证连接的稳固

软件流程图 + 调试软件说明 + 关键代码说明

代码分为2部分:左侧和右侧 Arduino 代码不同(具体左右区分方法在下图中)。右侧的只负责读取传感器数据,然后通过串口传输给左侧。然后左侧同样获得传感器数据,比较之后对 WS2812 发送控制信号,操作LED

右侧代码:

#include <Wire.h>

#include "NSPGD1M006DT04.h"

 

NSPGD1M006DT04 sensor(0xFF);

 

void setup() {

    Serial.begin(115200);

    Serial1.begin(2400);

    if (!sensor.begin()) {

       Serial.println("Device not found");

       while(1);

    }

}

 

void loop() {

    char s[20];

    float pr=sensor.readPressure();

    //float pr=3.14159269;

    uint8_t *p;

    dtostrf(pr,1,6,s);

    Serial.println(s);

    p=(uint8_t*)&pr;

    Serial1.write(0x55);

    Serial1.write(0xAA);

    Serial1.write(*p);

    Serial1.write(*(p+1));

    Serial1.write(*(p+2));

    Serial1.write(*(p+3));

   

    delay(50);

}

左侧代码:

#include <FastLED.h>

#include "NSPGD1M006DT04.h"

 

// 灯带

#define LED_PIN     5

#define COLOR_ORDER GRB

#define CHIPSET     WS2812B

#define NUM_LEDS    24

 

#define BLOWTIME    300

 

#define RSTARTPIN   10

 

NSPGD1M006DT04 sensor(0xFF);

 

CRGB leds[NUM_LEDS];

 

void(* resetFunc) (void) = 0;

 

void setup() {

  //Serial.begin(115200);

  Serial1.begin(2400);

  if (!sensor.begin()) {

    Serial.println("Device not found");

    while (1);

  }

 

  pinMode(RSTARTPIN, INPUT_PULLUP);

 

  FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );

  FastLED.setBrightness( 1 );

 

  for (uint8_t i = 0; i < NUM_LEDS / 2; i++) {

    memset(leds, 0, sizeof(leds));

    leds[NUM_LEDS / 2 - i] = CRGB::Red;

    leds[NUM_LEDS / 2 + i] = CRGB::Red;

    FastLED.show(); // display this frame

    FastLED.delay(300);

  }

 

  memset(leds, 0, sizeof(leds));

  leds[NUM_LEDS / 2 ] = CRGB::Red;

  leds[NUM_LEDS / 2 + 1] = CRGB::Red;

  FastLED.show(); // display this frame

  FastLED.delay(300);

}

 

long int Elsp = 0;

uint8_t  CockroachPosition = NUM_LEDS / 2;

float LeftSum = 0, RightSum = 0;

uint8_t Index = 0;

void loop() {

  float prRight;

  uint8_t *p;

 

 

 

  while (Serial1.available()) {

    uint8_t c = Serial1.read();

 

    if ((Index == 0) && (c == 0x55)) {

      Index++;

      p = (uint8_t*)&prRight;

    } else if ((Index == 1) && (c == 0xAA)) {

      Index++;

    } else if (Index != 0) {

      *p = c;

      p++;

      Index++;

      if (Index == 6) {

        RightSum = RightSum + prRight;

        float Left = sensor.readPressure();

        Index = 0;

        if ((prRight < 0) || (Left < 0)) {

          break;

        }

        LeftSum = LeftSum + Left;

        // Serial.print("Rcv"); Serial.print(" "); Serial.print(Left); Serial.print(" "); Serial.println(prRight);

      }

    }

  }

 

  if ((millis() - Elsp > BLOWTIME) && (Index == 0)) {

    if (LeftSum > RightSum + 0.1) {

      CockroachPosition++;

    }

    if (LeftSum + 0.1 < RightSum) {

      CockroachPosition--;

    }

    memset(leds, 0, sizeof(leds));

    leds[CockroachPosition] = CRGB::Red;

    leds[CockroachPosition + 1] = CRGB::Red;

 

    FastLED.show(); // display this frame

 

 

    // Serial.print("Set LED"); Serial.print(CockroachPosition); Serial.print(" ");

    // Serial.print(LeftSum); Serial.print("   "); Serial.print(RightSum); Serial.print("   "); Serial.println(Index);

 

    LeftSum = 0; RightSum = 0;

    if ((CockroachPosition == 0) || (CockroachPosition == NUM_LEDS - 2)) {

      Serial.println("Win");

      while (1) {

        if (digitalRead(RSTARTPIN) == LOW) {

          resetFunc();

        }

      }

    }

    Elsp = millis();

  }

}


实物演示以及说明

前面提到了,这次设计了三块PCB,实物如下

1.NSPGD1M006DT04 的转接板实物

image.png

2.控制板电路板实物

image.png

3.WS2812 电路板和

image.png


上述PCB 焊接之后通过U型排针连接在一起,按照下图放置

游戏的时候双方对着传感器吹气即可:

遇到的难点及解决方法

1.      NSPGD1M006DT04传感器无法设定设备地址,因此 I2C 上只能放置一个。如果有需要,那么可以通过 GPIO 来进行模拟,或者通过添加元件来解决。最终选择的方案是使用2Arduino 这样可以化简电路,方便代码编写;

2.      两个 Arduino 使用串口通讯,Arduino Leonardo float 占用4字节。为了简单起见,采用直接将float 拆开然后加上识别头的方法来进行传输


对本次活动的心得体会(包括意见或建议)

刚开始玩 Arduino 的时候,碰到过需要判断用户吹气的需求,比如,做一个可以“吹灭”的LED,但是因为无法购买到合适的传感器,最终只能使用声音传感器来替代。这次看到这个活动,让我产生了尝试的想法,最终实现了这个作品。从可靠性上来说,并不完美,但是作为一个游戏机我是非常满意的。玩法简单,半分钟的讲解即可上手,双方在笑声中完成一次又一次的比赛。当然,副作用是用户反应大笑和狂吹气会导致肚子疼…….

附件下载
ws2812.zip
WS2812 灯板电路
left.zip
左侧控制板代码
right.zip
团队介绍
www.lab-z.com
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号