暑期小实验(一)

(一)项目简介

一.项目名称:微定气体浓度检测仪

  采用arduino单片机接收传感器信号,并驱动隔膜泵,实现定量吸取气体。
  使用Android与arduino通信,Android显示接收数据,并对arduino进行控制。

二.项目开展

   该项目从大一暑假开始,独立开展,历时一个月完成。

(二)检测仪之电路设计

一.硬件清单

  1.单片机 arduino mega 2560
  2.传感器   气体浓度传感器  DFRobot的MiCS-2714  H2测量范围为1-1000ppm
             温湿度传感器   AHT10 湿度精度:0.01 温度精度:0.01
             压强传感器     bmp180 测量范围:30-110kpa 
  3.隔膜泵  可调速直流无刷 nidec 微型真空泵
  4.风扇 AVC调速小风扇
  5.android 旧手机

二.APP软件

 ## 1.库
      使用了github 开源 usb-serial-for-android 库
      > 链接:https://github.com/mik3y/usb-serial-for-android
 ## 2.界面设计
 ## 3.代码实现
        我将app代码放在了github上,可直接下载使用
        注释详细
 ## 4.实现功能
        使用该usb库,可直接连接单片机,连接串口,实现通信。
        发送数据,直接使用函数write 即可 ,我因为个人需求 每次发送8个字节数据,一个字节存放两个16进制数据
   TextView one = (TextView) findViewById(R.id.hex_num);
                //将编辑框中的数据直接发出
                String s = one.getText().toString();
                if (!s.isEmpty()) {
                    byte[] a = HEX.hexStringToByteArray(s);
                    try {
                        port.write(a, 1000);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
         接收数据,使用广播接听即可,我将接听到的数据一位一位放进了自定义的Application的字节队列中。
         由于是新手,一开始调试的时候,read函数不能很好的一次性读取8位数据,所以我将8位数据分开发送。
         经调试,只要在每发送的一位一位数据中间延迟1ms左右,就可以保证数据接收不会丢失。
         (这个请根据自己的情况调整,因为我只需要传送几个传感器的数据,所以牺牲了速度,保证的数据)
    //设置广播接听数据
        private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
        private final SerialInputOutputManager.Listener mListener =
                      new SerialInputOutputManager.Listener() {
                     @Override
                   public void onRunError(Exception e) {
                             //Log.d(TAG, "Runner stopped.");
                        }
                        @Override
                        public void onNewData(final byte[] data) {
                            runOnUiThread(()->{
                                  //因为我一次只发送了一位 所以 每次取一位即可
                                app.value.addLast(data[0]);
                                app.data_count++;
                            });
                          }

                };
    数据处理:我使用定时器Handle+timer的方式,循环处理放在队列中的数据
    Timer
           
          //创建一个定时器 循环 发送一个msg 值 启动handle
        Timer timer=new Timer();
          TimerTask task = new TimerTask() {
              @Override
              public void run() {
                  Message msg=new Message();
                  //发送一下,触法handle
                  myhandle.sendMessage(msg);
              }
          };
            //启动 设置循环时间
          timer.schedule(task,0,5000);

Handle

    //创建handle  用来处理数据
    private final Handler myhandle =new Handler(new Handler.Callback() {
          @Override
          public boolean handleMessage(@NonNull Message msg) {
              while((app.data_count/8)>0)
              {
                    //新建8位数组 for循环
                    //当到第6 7 8 时 若不是ff 则 退出for循环  (防错机制)

                  byte[] bytes=new byte[8];
                  int i=0;
                  for(;i<8;i++)
                  {
                      bytes[i]=app.value.getFirst();
                      if(i>=5){
                          if(bytes[i]!=(byte)0xff)
                          {
                              break;
                          }
                      }
                      app.value.poll();
                      app.data_count--;

                  }
                  if(i == 8){
                  data_handle.S_to_handle(HEX.toHexString(bytes),da_1,da_2,da_3,da_4,da_5,da_6);
                  }
              }
              return false;
          }
      });
  界面设计

在这里插入图片描述

三.单片机

  单片机代码看分为两个部分,一个是接收数据部分,一个是发送数据部分。
  传感器的使用皆使用arduine的库,简单易操作。

定义


//气压
#include<Wire.h>
#include<Adafruit_BMP085.h>
Adafruit_BMP085 bmp;
uint32_t data_pa =0;                     //气压值 100 000   整数 

//mems 气体浓度
#include<DFRobot_MICS.h>
#define CALIBRATION_TIME 3
#define ADC_PIN A0
#define POWER_PIN 26
DFRobot_MICS_ADC mics(ADC_PIN,POWER_PIN);
float data_gas=0;                  //浓度值    1-1000ppm  小数点一位                                           

//泵
#define MOtor_beng 9
int PWM_beng=0;                    //占空比    0-255

 //风扇
 #define Motor_feng 8 //风扇
 int PWM_feng=0;                    //占空比    0-255

//测速
#define FG_Pin 24   //测速引脚
#define asd 2        //每圈脉冲数
int16_t max_n=0;      //上升最大值
int16_t max_m=0;      //下降最大值
int16_t speed=0;      //转速

//AHT 湿度 温度传感器
#include <Adafruit_AHT10.h> 
Adafruit_AHT10 aht;
float data_temp=0;           //温度值,小数点两位
float data_humi=0;           //湿度值,小数点两位

#define a 10000               //sent 延迟

bool bmp_s=0;
bool aht_s=0;
bool mems_s=0;
bool mems_s_tobegin=0;
bool beng_s=0;
bool feng_s=0;
//存储int数
byte data_shu[4];

android发送启动信号,arduino判断并启动或停止

if(Serial.available()>=8)
    {
      byte byts[8];
      Serial.readBytes(byts,8);
        //第一位为 标识位
      int c=byts[0];
      switch (c)
      {
      case 10:
      case 11:
         //如果全为00  则不再读取 温度 湿度
        if(byts[1]==0&&byts[2]==0&&byts[3]==0&&byts[4]==0)
        {
           aht_s=0;
           
        }
        else
        {
            aht.begin();
            aht_s=1;
        }
        break;
      case 12:
         //如果全为0 则不再读取 压强
        if(byts[1]==0&&byts[2]==0&&byts[3]==0&&byts[4]==0)
        {
           bmp_s=0;
           
        }
        else
        {
            bmp.begin();
            bmp_s=1;
        }
        break;
     case 13:
        //打开mems
        if(!mems_s)
        {
          mics.begin();
          mems_s=1;
        }
          //如果为1 启动mems
        if(byts[1]==1||byts[2]==1||byts[3]==1||byts[4]==1)
        {
            uint8_t mode = mics.getPowerState();
           if(mode == SLEEP_MODE){
              mics.wakeUpMode();
              mems_s_tobegin=1;
           }
        }
        else
        {
            mics.sleepMode();
            mems_s_tobegin=0;
        }
        break;
     case 14:
       if(byts[4]!=00)
        {
           if(!feng_s)
          {
          feng_s=1;
          }
            //设置PWM
          PWM_feng=byte_to_int(byts[1],byts[2],byts[3],byts[4]);
          analogWrite(Motor_feng,PWM_feng);    
          
        }
        else
        {  
          feng_s=0;
        }
        break;
     case 15:
       //如果全为00 停止
        if(byts[4]!=00)
        {
                //启动
          if(!beng_s)
          {
          beng_s=1;
          }
            ///设置PWM
          PWM_beng=byte_to_int(byts[1],byts[2],byts[3],byts[4]);
          analogWrite(MOtor_beng,255-PWM_beng);    
        }
        else
        {
          beng_s=0;
        }
        break;
      default:
        break;
      }
    }

数据发送都是重复的,就不一一列出了

//压强发送
    if(bmp_s)
    {
        read_pa();
        int_to_bytes(data_shu,data_pa);
        Serial.write(0x0c);
        delayMicroseconds(a);
        Seriasadite(data_shu[0]);
        delayMicroseconds(a);
        Serial.write(data_shu[1]);
        delayMicroseconds(a);
        Serial.write(data_shu[2]);
        delayMicroseconds(a);
        Serial.write(data_shu[3]);
        delayMicroseconds(a);
        Serial.write(0xff);
        delayMicroseconds(a);
        Serial.write(0xff);
        delayMicroseconds(a);
        Serial.write(0xff);
        delayMicroseconds(a);
        delay(1000);
    }

以下是我定义的一些函数,都很简单。

  //读取压强
void read_pa()
{
    data_pa=bmp.readPressure();
}
  //读取气体浓度
void read_H2()
{
    data_gas =mics.getGasData(H2);
}
  //读取湿度 温度
void read_Shi_temp()
{
  sensors_event_t humidity, temp;
  aht.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
  data_temp=temp.temperature;
  data_humi=humidity.relative_humidity;
}
  //将16字节数组转为 int
 uint32_t  byte_to_int(byte one,byte two,byte three,byte four)
    {
        return (one&0xff)<<24
                |(two&0xff)<<16
                |(three&0xff)<<8
                |(four&0xff);
    }
  //将int 转为字节数组
void int_to_bytes(byte array[4],uint32_t i)
{
    array[0] = (byte) (i>>24);
    array[1] = (byte) ((i & 0xFF0000)>>16);
    array[2] = (byte) ((i &0xFF00)>>8);
    array[3] = (byte) ((i&0xFF));
}

四.电路连接

  1.各传感器与单片机直接连接即可,需要用到相同的引脚(如两个传感器都要连接SDA,SDL),直接并联即可
  不同传感器的地址不同,不同的库函数也不同,可独立使用,互不影响。
  2.泵与风扇要与12V电源相连,同时需与单片机共地。

(三)检测仪之气路设计

一. 原理

由泵运动,形成负压,使气体被吸入气室,得以检测。

二.气路设计

 1.流量计:采用了玻璃转子流量计 2.5m-25ml/min
 2.节流阀:控制压强,流速。
 3.净化装置:除去空气中的灰尘,水分,防止泵的堵塞。
 4.缓冲罐:由于泵本身的特性,气体呈波动性变化,加一个缓冲罐,可以平稳气流。
 5.泵
 6.单向阀:防止气体回流
 7.气室:采样亚克力板制作
 8.电磁阀:控制气室气压,放出气体。

在这里插入图片描述

(四)检测仪之最终效果

   实验所得:
   在泵的PWM调速时,90的占空比,能使气体的流速稳定在17ml左右

在这里插入图片描述
这个是整体效果:在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值