末世生存Kit_V1.0

末世生存Kit_V1.0

想象一下有一天…

地球上爆发了核战争,毁灭性的攻击使得地表生灵涂炭,辐射超标,大量浮尘与有毒有害气体漂浮在大气中,强烈的紫外线照射……
这样的世界在许多科幻电影和游戏中都曾出现过,比如Fallout 4:


1e3H2V.jpg

1e3780.png

总之,这将是一个不太适合生存的世界,如果我们想要在这种环境生存下去,此时你需要的不仅仅是一部动力装甲,你更需要这个宝贝…(把头伸过来,我给你看个宝贝.jpg)


1e84sO.jpg

这就是我们本文要港的末世生存Kit_V1.0。

这是啥???

这是一个“基于Arduino电子平台的环境检测装置”

啊呸…这个学术腔我已经要听吐了(基于…的…)
我们干脆叫他末世生存Kit呗~
为什么叫Kit呢?因为很多电子套件都叫Kit,而这个项目其实可以做成套件的形式,因为它非常简单且有趣又实用还不失逼格( 虽然好像平时也没什么卵用… (小声bb)

整个项目用到了一些传感器模块,还有Arduino Nano,以及一些额外的USB接插件,锂电池座+电池充放电一体管理模块+开关,还有洞洞板(黄黄的像黄油一样的黄油板),M3铜柱,螺母,连接线!
主要元件如下:

VEML6070 – I2C通讯协议 – 数字紫外线强度传感器
SHT31 – I2C通讯协议 – 数字温湿度一体传感器
TEMT6000 – 模拟电压输出 – 模拟光强传感器
PMS7003 – UART通讯协议 – 攀藤的一体化颗粒物浓度检测传感器模块,提供串口通讯接口
MQ-135 – 模拟电压输出 – 有毒有害气体传感器,输出模拟电压信号
1.3 inch 132*64 OLED(蓝色) – SPI通讯协议

关于代码,就是调库!调库!再调库!(白嫖的快乐hhhhh)
我写的一份ino格式代码已经在 我的github 上了

关于元件的库,我也帮你找好了,在Github上都有,下载zip包导入到Arduino IDE的库就好了~

PMS Library(PMS7003传感器)
SHT3x(数字温湿度)
VEML6070(数字紫外线)
U8g2(OLED图形库)

如果你打算着手制作了,建议你先把各个传感器模块单独放在面包板上和Arduino联调进行一次测试哦~

这是检验元件是否好坏的第一步!

如果你不太会做这种测试,我建议你去 Adafruit的官网教程 学习一下√
所谓的测试就像这样:


VEML6070.jpg

等所有的模块都通过了测试(QC Pass!),你就可以着手设计电路连线怎样合理了,其实也没什么需要注意的,IIC协议是固定的2根信号线,UART端口我直接用了默认的下载口(我偷了个懒,因为这样连的话,下载程序时必须断开PMS7003传感器的连接,不然串口会冲突导致下载失败)
至于OLED,我买的SPI的版本,主控是SH1106,对应U8g2的初始化是这样的:

/*
  代码不够闲话来凑
  代码不够闲话来凑
  代码不够闲话来凑
  代码不够闲话来凑
  代码不够闲话来凑
*/
U8G2_SH1106_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 7, /* dc=*/ 6, /* reset=*/ 5);

看代码可以看出,CS(片选) 连D7,DC(指令/数据选择) 连D6,RST(复位) 连D5。

我的测试代码我也在这里贴一遍吧~ 看完你就知道调库(白嫖)是多么的快乐了!

#include 
#include 
#include 

#include 
#include "Adafruit_SHT31.h"
#include "Adafruit_VEML6070.h"
#include "PMS.h"

PMS pms(Serial);
PMS::DATA data;

Adafruit_SHT31 sht31 = Adafruit_SHT31();
Adafruit_VEML6070 uv = Adafruit_VEML6070();

U8G2_SH1106_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 7, /* dc=*/ 6, /* reset=*/ 5);

char i = 0;

const char s1[] PROGMEM = "End World Kit";
const char s2[] PROGMEM = ">-Temp: ";
const char s3[] PROGMEM = "*C";
const char s4[] PROGMEM = ">-Humidity: ";
const char s5[] PROGMEM = "%";
const char s6[] PROGMEM = ">-UV level: ";
const char s7[] PROGMEM = ">-Light LX: ";
const char s8[] PROGMEM = ">-PM2.5(ug/m^3):  ";
const char s9[] PROGMEM = ">-PM10(ug/m^3):   ";
const char s10[] PROGMEM = ">-PM1.0(ug/m^3): ";
const char s11[] PROGMEM = "No data response.";
const char *index[] = { s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11};

void _firstPage(void);
void _secondPage(void);
void _homePage(void);

void setup()
{
  Serial.begin(9600);     //init baudrate at 9600 to communicate with laser-gas sensor
  uv.begin(VEML6070_HALF_T );   //Integration time sets to 62.5ms.
  sht31.begin(0x45);  // 0X45 OR 0X44
  pms.passiveMode();    //set laser-gas sensor to passivemode
  pms.wakeUp();   //wake up the laser-gas sensor
  //u8g2.begin();

  u8g2.begin();
  u8g2.setPowerSave(0);
  _homePage();
  /*
  u8g2.begin();
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_helvB08_tf);   //title Font.
  u8g2.drawStr(30,8,"End World Kit");
  u8g2.setFont(u8g2_font_t0_11_mf);  // choose Internal font.
  u8g2.sendBuffer();
  */

}

void loop()
{
  _firstPage();
  delay(2500);
  _secondPage();
  delay(2500);
}

void _firstPage(void)
{ 
  u8g2.clearDisplay();
  u8g2.setFont(u8g2_font_helvB08_tf);
  float temp = sht31.readTemperature();
  float humidity = sht31.readHumidity();
  do {
    u8g2.setCursor(30, 8);
    u8g2.print((class __FlashStringHelper *) index[0]);

  if (! isnan(temp)) 
  {  // check if 'is not a number'
    u8g2.setCursor(0, 24);
    u8g2.print((class __FlashStringHelper *) index[1]);
    u8g2.print(temp);
    u8g2.print((class __FlashStringHelper *) index[2]);
  }
  if (! isnan(humidity)) 
  {  // check if 'is not a number'
    u8g2.setCursor(0, 40);
    u8g2.print((class __FlashStringHelper *) index[3]);
    u8g2.print(humidity);
    u8g2.print((class __FlashStringHelper *) index[4]);
  } 
  u8g2.setCursor(0, 56);
  u8g2.print((class __FlashStringHelper *) index[5]);
  u8g2.print(uv.readUV());
  } while (u8g2.nextPage());
}

void _secondPage(void)
{
  u8g2.setFont(u8g2_font_helvB08_tf  );
  unsigned int lx = 0, anr = 0;
  for (i = 0; i < 16; i++)
  {
    anr = analogRead(A6);
    lx = lx + anr; 
    anr = 0;
    delay(5);
  }
  lx = lx / 16;

  do {
    u8g2.clearDisplay();
    u8g2.setCursor(0, 10);
    u8g2.print((class __FlashStringHelper *) index[6]);
    u8g2.print(lx);
    lx = 0;
    pms.requestRead();
    if (pms.readUntil(data))
    {
      u8g2.setCursor(0, 24);
      u8g2.print((class __FlashStringHelper *) index[7]);
      u8g2.print(data.PM_AE_UG_2_5);
      u8g2.setCursor(0, 38);
      u8g2.print((class __FlashStringHelper *) index[8]);
      u8g2.print(data.PM_AE_UG_10_0);
      u8g2.setCursor(0, 52);
      u8g2.print((class __FlashStringHelper *) index[9]);
      u8g2.print(data.PM_AE_UG_1_0);
    }
    else 
    {
      u8g2.setCursor(0, 40);
      u8g2.print((class __FlashStringHelper *) index[10]);
    }
  } while ( u8g2.nextPage() );

}

void _homePage(void)
{
  u8g2.clearDisplay();
  u8g2.setFont(u8g2_font_helvB08_tf);
  do
  {
    //u8g2.setFont(u8g2_font_helvB08_tf);  // choose Internal font.
      u8g2.setCursor(30, 8);
    u8g2.print(F("End world Kit"));
      u8g2.setCursor(0, 20);
    u8g2.print(F("Test & developed by "));
      u8g2.setCursor(0, 32);
    u8g2.print(F("Floydfish.In case of "));
      u8g2.setCursor(0, 44);
    u8g2.print(F("extreme conditions."));
      u8g2.setCursor(0, 56);
    u8g2.print(F("detect everything around."));
  } while ( u8g2.nextPage() );

  delay(3000);

}

我唯一的代码量就是写GUI,因为数据项太多,小小的13264屏幕放不下,所以我分了2页显示,对应的刷新函数为_firstPage()和_secondPage(),以及上电初始化页面_homePage()。

其实U8g2库对于Arduino Nano来说过于臃肿了...我这个程序占用了80%多的代码存储空间,几乎塞满,在我优化前它一度占到了90%多...于是我刚开始还写了一遍U8X8的版本,但是我发现u8x8没有我中意的字体,所以又换了回来233

Assemble

首先把几个小传感器和OLED和接口都焊好,走好线,像这样:


1e8hQK.jpg

接着,把PMS7003和MQ-135固定在另一块板子上,焊好线引好接口:


1e82J1.jpg

我把这第二块板子叫做"颗粒物DLC"23333
因为它就像拓展组件一样,可以堆很多额外的传感器来增强功能。
(这就是它叫V1.0的原因之一~)

然后,全部连接好,烧录程序,开始调试。


1e8RRx.jpg

这是最初的调试代码,只用了一个页面来显示数据。

侧面


1e8Wz6.jpg

屁股翻过来看看


1e8giR.jpg

Final!


1e84sO.jpg

Enjoy!(装逼)

什么?我费尽千辛万苦做出来个炫酷玩意儿还不许我装装逼了?

这个项目本来就是 好 van ♂ 的
想怎样使用都看你自己啦。
在这里放一些我自己玩的图片

在电梯里,我开启了开关,电池充放电管理模块上的电压指示红色LED在电梯上形成一道猩红色的光带 (异闻带)

某CNPP同学说这是"鲨红了眼"


1e85LD.jpg

在某个 Lab Stay Night,我饿了...
于是我出门买烤冷面,路上我用它测量了一下晚上10点长安区的气温(好冷鸭.jpg)
可以看到,-3度,湿度58.22%....


1e8oee.jpg

END!

后记

其实我最后放弃了使用MQ-135。。。
因为我发现这东西耗电太大了,因为它的工作原理依赖电热丝,不仅耗电,发热还会干扰到上面的温湿度传感器正常采集数据(怪我的机械设计布局没考虑周全),所以你在代码中是看不到这个传感器的采集的~

然后。。V2.0版本,我预计会加入简单的盖革计数管,测量环境本底辐射,有条件再加入联网功能,可以查询气象站API并跟自己的数据比对。

我还想加入一些奇怪的传感器,比如氧气浓度和二氧化碳,气压,海拔,电子罗盘,陀螺仪等。(好像有点太多了)(主要还是传感器太贵了,咱买不起啊orz)

还想换一个大一些的显示器,做一个更好看的GUI~!(我希望实现曲线记录显示)

这个坑先挖在这,什么时候填呢...有空再说!

发表回复