查看: 3244|回复: 5

ATTINY85制作的智能环境监测系统

[复制链接]
  • TA的每日心情
    郁闷
    2019-11-25 19:20
  • 签到天数: 146 天

    [LV.7]常住居民III

    发表于 2018-11-22 21:17 | 显示全部楼层 |阅读模式
    本帖最后由 希岩 于 2018-11-22 21:20 编辑

       由于好奇,买了一个attiny85的单片机,本来说要做Digispark的,但倒腾了好久,终于在arduino IDE下装了这个的开发板插件,结果不能用ISP下载就很烦了,就是无法“导出已编译的二进制文件”,就不能用那个arduino IDE尽心开发,很是郁闷。
       后来找到了ATTINY的开发板,按照ATTINY添加了插件,就抛弃了Digispark。具体方法可以自己去查百度。就是添加attiny85的开发板,便可以编译attiny85程序了。开心。
       看了下ATTINY85,发现有SDA和SCL的引脚,以为有I2C呢,最后发现没有。其实就是USI的一种模式,USI没用过,这个东西能配置成TWI或者SPI。配置成TWI真是麻烦,去网上找库,扎到了TinyWire的库,这还是官方的,加载到Arduino IDE下居然不能用,我的OLED 128 32就是点不亮,换了这个库的好多版本都不行,花了我大半天,还是不行。我看了库里面配置I2C的程序,发现卡在start里了,不知道为什么,就是不好用。无奈,就用软件I2C吧,从网上找了一个51单片机驱动I2C oled的,就是用普通IO模拟的。
       移植完,调试一下,哎,可以了,很是开心。然后就用Arduino的DS18B20的库和DHT11的库带了两个传感器,一个是DS18B20,一个是DHT11温湿度传感器。还有一个引脚,手头有一个TEMT6000光照传感器,三个传感器加上,可以放宿舍了。
      首先准备材料:
    1.0.91寸OLEd,点阵数128*32
    2.DS8B20温度传感器;
    3.DHT11温湿度传感器;
    4.TEMT6000光强传感器。
    5.最重要的ATTNY85控制器。  其中OLED的SDA接2脚,即PB2。SCL接0脚,即PB0。
    DHT11接3脚,即PB3。
    DS18B20接1脚,即PB1。
    TEMT6000接A2脚,即PB4.

    注意I2C加个上拉电阻。按照上述连接便接好了。程序用到了DHT11的库,DS18B20库, I2C用软件模拟的,OLED没有用Adafruit的库,那个太大了,放不下。
    插上电,或者用锂电池供电也行,因为用的是内部8MHz RC振荡器。3.3V就能工作。
    把一部分程序贴出,还有效果图。最后是完整代码。

    kittenblock中小学创客名师推荐的图形化编程软件

    #include <OneWire.h>
    #include "DHT.h"
    // OneWire DS18S20, DS18B20, DS1822 Temperature Example
    //
    // http://www.pjrc.com/teensy/td_libs_OneWire.html
    //
    // The DallasTemperature library can do all this work for you!
    // http://milesburton.com/Dallas_Temperature_Control_Library
    
    #include "codetab.h"     //OLED显示字符数组
    
    //数据类型宏定义
    typedef unsigned char uint08;
    typedef signed   char sint08;
    typedef unsigned int  uint16;
    typedef signed   int  sint16;
    #define PIN4        4              // ATtiny PB4
    #define PIN3        3             // ATtiny PB3
    #define PIN1        1             // ATtiny PB1
    
    #define DHTPIN PIN3    // DHT1连接引脚
    
    OneWire  ds(PIN1);  // on pin 10 (a 4.7K resistor is necessary)
    DHT dht(DHTPIN, DHT11);
    
    #define TWI_ADDR   0x78              // 8 bit I2C address for IIC slave
    
    
    
    #define  Bright     0x80   //最大255
    #define  X_WIDTH    128
    
    
    #define SCL 2    //PB2
    #define SDA 0    //PB0
    
     #define SDA_LOW       PORTB&=~0x01    //sda low
     #define SDA_HIGH      PORTB|=0x01    //sda low
     #define SCL_LOW       PORTB&=~0x04   //sda low
     #define SCL_HIGH      PORTB|=0x04    //sda low
     #define  SDA_SCL_HIGH PORTB|=0x05
     #define  SDA_SCL_LOW  PORTB&=~0x05
     #define  SDA_SCL_OUT  DDRB|=0x05
     #define  SDA_INTPUT   DDRB&=~0x01
     #define  SDA_READ     PINB&0x01
     
    //--------------------------------------------------
    void I2C_Init()
    {
      pinMode(SDA, OUTPUT);
      pinMode(SCL, OUTPUT);
      digitalWrite(SCL, HIGH);
      digitalWrite(SDA, HIGH);
    }
    //--------------------------------------------------
    void I2C_Start()
    {
      SDA_SCL_OUT;
      SDA_SCL_HIGH;
      delayMicroseconds(5); //通信协议规定延时大于4.7us
      SDA_LOW;              //sda low
      delayMicroseconds(5);//通信协议规定延时大于4.7us
    }
    //--------------------------------------------------
    void I2C_Stop()
    {
     SDA_SCL_OUT;
     SDA_LOW;    //sda low
     asm ("nop"); 
     SCL_HIGH;    //scl high
     delayMicroseconds(5);//通信协议规定延时大于4.7us
     SDA_HIGH;
     delayMicroseconds(5);//通信协议规定延时大于4.7us
    }
    //--------------------------------------------------
    char test_ack()
    {
     SCL_HIGH;
     delayMicroseconds(4);//通信协议规定延时大于4us
     SDA_INTPUT;
     if(SDA_READ)
    {
      SCL_LOW;
      I2C_Stop();
      return 0;  
     }else
     {
      SCL_LOW;
      return 1;
    }
    }
    //--------------------------------------------------
    void Write_I2C_Byte(char I2C_Byte)
    {
      unsigned char i;
      //int Ack_Bit;                    //ACK
      SDA_SCL_OUT;
      for(i=0;i<8;i++)
      { SCL_LOW;
        asm ("nop");
        if(I2C_Byte & 0x80) //1 or 0
           SDA_HIGH;
        else
           SDA_LOW;
        SCL_HIGH;
         asm ("nop");
        I2C_Byte<<=1; //loop
      }
      
      SCL_LOW;             //I2C SCL
      asm ("nop");
      SDA_HIGH;  //I2C SDA
      asm ("nop");  //SCL_LOW;
      asm ("nop");
    
    }
    //--------------------------------------------------
    unsigned char  Read_I2C_Byte(char ack)
    {
      unsigned char i;
      unsigned char I2C_Byte=0;
      SDA_SCL_OUT;
      SDA_INTPUT;
      for(i=0;i<8;i++)
      {
        SCL_HIGH;
        if(SDA_READ)    
                I2C_Byte=(I2C_Byte<<1)+1;    
            else   
                I2C_Byte=I2C_Byte<<1;  
          SCL_LOW; 
      }
      if(ack) SDA_HIGH;
      else SDA_LOW;
      SCL_HIGH;             //I2C SCL
      SCL_LOW; 
      return I2C_Byte;
    }  
    
     //-----------------------------------------------------------------
    //TWI写入数据
    /*写指令函数,第一个参数为指令,第二、三个参数选择是否需要通信开始和结束函数,=1有,=0没有*/
    void USI_TWI_Write(uint08 data,uint08 dc)
    {     
      I2C_Start();
      Write_I2C_Byte(TWI_ADDR);
      if(test_ack())
      {
        if(dc)Write_I2C_Byte(0x40);
        else Write_I2C_Byte(0x00);
      }
        if(test_ack())
        Write_I2C_Byte(data);
         test_ack();
         I2C_Stop();
    }
    
    
    
    //--------------------------------------------------------------------------------
    /*********************OLED 设置坐标************************************/
    void Set_Pos(uint08 x, uint08 y) 
    { 
      USI_TWI_Write(0xb0+y,0);
      USI_TWI_Write(((x&0xf0)>>4)|0x10,0);
      USI_TWI_Write(x&0x0f,0);
    }
    /*********************OLED全屏************************************/
    void OLED_Fill(uint08 dat) 
    {
      uint08 y,x;
      for(y=0;y<4;y++)
      {
        USI_TWI_Write(0xb0+y,0);
        USI_TWI_Write(0x01,0);
        USI_TWI_Write(0x10,0);
        for(x=0;x<X_WIDTH;x++)
        USI_TWI_Write(dat,1);
      }
    }
    /*********************OLED初始化************************************/
    void OLED_Init(void)
    {
      delay(500);//初始化之前的延时很重要!
     
      USI_TWI_Write(0xae,0);//--turn off oled panel
      USI_TWI_Write(0x40,0);//---set low column address
      USI_TWI_Write(0xB0,0);//---set high column address
      USI_TWI_Write(0xC8,0);//--set offset
      USI_TWI_Write(0x81,0);//--set contrast control register
      USI_TWI_Write(Bright,0); // Set SEG Output Current Brightness
      USI_TWI_Write(0xa1,0);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
      USI_TWI_Write(0xa6,0);//--set normal display
      USI_TWI_Write(0xa8,0);//--set multiplex ratio(1 to 64)
      USI_TWI_Write(0x1f,0);//--1/64 duty
      USI_TWI_Write(0xd3,0);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
      USI_TWI_Write(0x00,0);//-not offset
      USI_TWI_Write(0xd5,0);//--set display clock divide ratio/oscillator frequency
      USI_TWI_Write(0xf0,0);//--set divide ratio, Set Clock as 100 Frames/Sec
      USI_TWI_Write(0xd9,0);//--set pre-charge period
      USI_TWI_Write(0x22,0);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
      USI_TWI_Write(0xda,0);//--set com pins hardware configuration
      USI_TWI_Write(0x02,0);
      USI_TWI_Write(0xdb,0);//--set vcomh
      USI_TWI_Write(0x49,0);//Set VCOM Deselect Level
      USI_TWI_Write(0x8d,0);//--set Charge Pump enable/disable
      USI_TWI_Write(0x14,0);//--set(0x10) disable
      USI_TWI_Write(0xaf,0);//--turn on oled panel
      OLED_Fill(0x00);      //初始清屏
    
    } 
    /*********功能描述:显示8*16一组标准ASCII字符串*********************************/
    //   显示的坐标(x,y),y为页范围0~3
    //char sign[] = {"a AM PREDATOR BBdDDS"};
    void OLED_P8x16Str(uint08 x,uint08 y,uint08 ch[])
    {
      uint08 c=0,i=0,j=0,temp;
      while (ch[j])                          //扫描
      {
        c =ch[j]-32;
        if(x>120){x=0;y+=2;}
        Set_Pos(x,y);
        for(i=0;i<8;i++)
        {
          temp = pgm_read_word_near(F8X16+c*16+i);
          USI_TWI_Write(temp,1);
        }
        Set_Pos(x,y+1);
        for(i=0;i<8;i++)
        {temp = pgm_read_word_near(F8X16+c*16+i+8);
        USI_TWI_Write(temp,1);
        }
        x+=8;
        j++;
      }
    }
    
    //----------------------------------------------------------------------------
    //根据DS18B20中读的温度字节,计算实际温度值
    sint16 Start_Temperature(void)
    {  
    
      ds.reset();
      ds.write(0xCC);           //忽略地址匹配
      ds.write(0x44, 1);        // start conversion, with parasite power on at the end
    
    }
    //----------------------------------------------------------------------------
    //注意开始转换到获取数据要超过750ms时间
    sint16 Get_Temperature(void)
    {
      byte data[2];
    //  delay(750);     // maybe 750ms is enough, maybe not
      // we might do a ds.depower() here, but the reset will take care of it.
      ds.reset();
      ds.write(0xCC);        //忽略地址匹配   
      ds.write(0xBE);         // Read Scratchpad
      data[0] = ds.read();
      data[1] = ds.read();
      int16_t raw = (data[1] << 8) | data[0];
      return ((long)raw*100/16);   //取整
    }
    //------------------------------------------------------------------------
    void setup()
    {
      OSCCAL = 0x8A;                 //时钟矫正至8Mhz
      //PRR =  0x00;                       //复位功耗抑制寄存器,TWI唤醒
      //pinMode(LED1_PIN,OUTPUT);
      // config TinyWire library for I2C master functionality
      //TinyWire.begin();
      I2C_Init();                                   //软件I2C初始化
      OLED_Init();                                  //OLED初始化
      OLED_Fill(0xFF);
      dht.begin();                                //dht11开始启动
      Start_Temperature();
      delay (1000);
      OLED_Fill(0x00);//清屏
    }
    //------------------------------------------------------------------------
      uint08 Show_Buff[17];
      int temperature;   
      byte hum;     //湿度20%-90%
      int Luxval;
      int hic;
      
    void loop()
    {
       temperature =Get_Temperature();
       Start_Temperature();    //
       hum= dht.readHumidity();
     
       if(temperature<0)
       {
        Show_Buff[0]='-';      //负数标记
        temperature=0-temperature;
       }
       else  Show_Buff[0]='+';      //'+'号
          
         //定点小数显示格式  
         Show_Buff[1]=(temperature/1000)%10+'0';
         Show_Buff[2]=(temperature/100)%10+'0'; 
         Show_Buff[3]='.';      // 小数点
         Show_Buff[4]=(temperature /10)%10+'0';
         Show_Buff[5]=temperature%10+'0';
         Show_Buff[6]=127;       //这个是摄氏度符号 16*8
         Show_Buff[7]=0;          //字符串结束标志
         OLED_P8x16Str(4,0,Show_Buff);//温度数据
         
         Show_Buff[0]=(hum/10)%10+'0';
         Show_Buff[1]=hum%10+'0';
         Show_Buff[2]=128;     //% 字符
         Show_Buff[3]=' ';   
         Show_Buff[4]='R';   
         Show_Buff[5]='H';  
         Show_Buff[6]=0;   //字符串结束标志
         OLED_P8x16Str(76,0,Show_Buff);//湿度数据
    
          Luxval=analogRead(A2);      //connect sensor to Analog 2
          (Luxval>999)?1000uxval; 
    
         Show_Buff[0]=(Luxval/100)%10+'0';
         Show_Buff[1]=(Luxval/10)%10+'0';
         Show_Buff[2]=(Luxval)%10+'0';
         Show_Buff[3]='L';
         Show_Buff[4]='u';
         Show_Buff[5]='x';
         Show_Buff[6]=' ';
          
         hic= dht.computeHeatIndex(temperature/100, hum, false)*10;  // Compute heat index in Celsius (isFahreheit = false)
        if(hic<0)
        {
         Show_Buff[7]='-';      //负数标记
         hic=0-hic;
        }
       else  Show_Buff[7]=' ';      //空格
          
         //定点小数显示格式  
         Show_Buff[8]=(hic/100)%10+'0';
         Show_Buff[9]=(hic/10)%10+'0'; 
         Show_Buff[10]='.';      // 小数点
         Show_Buff[11]=(temperature )%10+'0';
         Show_Buff[12]=127;//这个是摄氏度符号 16*8
         Show_Buff[13]=' ';
         Show_Buff[14]='I';       
         Show_Buff[15]='X';  
        Show_Buff[16]=0; 
         
         OLED_P8x16Str(0,2,Show_Buff);//光照强度数据+指示温度数据
        
        //OLED_P8x16Str(0,2,"Hello World!");//第一行 -- 8x16的显示单元显示ASCII码
    
    
        delay(200);      //可以通过延时控制刷新率
    
    }
    
    
    
    





    2018-11-22_205612.png

    效果

    效果

    效果2

    效果2

    DTH_DS18B20_OLED.zip

    14.41 KB, 下载次数: 36

    完整代码

    该用户从未签到

    发表于 2018-11-23 10:47 | 显示全部楼层
    楼主玩TINY还是玩的挺溜的,我之前用digispark折腾了好久
  • TA的每日心情
    郁闷
    2019-11-25 19:20
  • 签到天数: 146 天

    [LV.7]常住居民III

     楼主| 发表于 2018-11-23 11:55 | 显示全部楼层
    kirbyklein 发表于 2018-11-23 10:47
    楼主玩TINY还是玩的挺溜的,我之前用digispark折腾了好久

    不是啊,我这玩ATTINY85才玩了两天。之前只接触过Attiny13a。digispark在arduino ide下不好使。

    该用户从未签到

    发表于 2019-1-26 13:00 | 显示全部楼层
    请问你这个是怎么烧写上去的?
  • TA的每日心情
    慵懒
    2019-2-15 15:01
  • 签到天数: 5 天

    [LV.2]偶尔看看I

    发表于 2019-2-15 09:21 | 显示全部楼层
    之前我也买过这个模块驱动OLED来着,用IDE上传的确是个麻烦事,上传时显示红色提示的时候把模块与电脑断开连接,然后再插入才行。
  • TA的每日心情
    郁闷
    2019-11-25 19:20
  • 签到天数: 146 天

    [LV.7]常住居民III

     楼主| 发表于 2019-2-19 12:26 | 显示全部楼层
    arduino月色无声 发表于 2019-2-15 09:21
    之前我也买过这个模块驱动OLED来着,用IDE上传的确是个麻烦事,上传时显示红色提示的时候把模块与电脑断开 ...

    我不是用IDE上传的,而是用ISP下载
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    Blynk与m5stack basic以及uiflow的交互玩法
    Blynk与m5stack basic以及
    Blynk与m5stack basic以及uiflow的交互玩法 [准备工作我们假设玩家已经熟悉下面的准备
    【原创】全球最小口袋3D打印机mini one直播教程贴
    【原创】全球最小口袋3D打
    最近闲得蛋疼,没事搞个掌上3D打印机,先放效果图吧。 搞了半天,终于能正常打印,
    交通灯在一定条件的亮起
    交通灯在一定条件的亮起
    交通灯问题 用到了 有限状态机 求助求助
    【原创】 drawbot平面关节scara机械臂写字机 画画机器人直播...
    【原创】 drawbot平面关节
    这个项目上个月就在做了,结构和代码反反复复改了多次,加上自己又太忙,一直没来得及
    教你用Arduino编写FC马戏团
    教你用Arduino编写FC马戏
    演示视频 https://www.bilibili.com/video/av30637311/ 状态 正常 游戏在文
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   
    快速回复 返回顶部 返回列表