极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 25447|回复: 11

OLED+DS1307+光敏电阻制作模拟钟表,实现手势感应切换画面

[复制链接]
发表于 2015-8-7 00:06:45 | 显示全部楼层 |阅读模式
本帖最后由 Cambridge 于 2015-8-7 10:51 编辑

之前在论坛里面看见有网友说要做一个钟表,刚好又买来了一个OLED屏,在论坛学习了一下OLED的使用,就自己写了一个这样的程序。但是许多网友表示U8G的库不能使用,而且编译也会很慢,我就用了adafruit的库。
这个库包含了许多使用的函数,例如display.drawCircle(x,y,r,color);display.drawLine(x0,y0,x1,y1,color)等。所以用这些函数就可以很快的画出我们的钟表。然后在利用DS1307得到时间的数据,用一系列的运算就可以做出模拟的钟表了。另外我们可以利用一个光敏电阻和中断,来实现当手挥过的时候,OLED屏的画面会切换,显示温度日期之类的信息。好了先上代码。连线是OLED:SCL--10,SDA--9,RST--13,DC--11;DS1307:SCL--A5,SDA--A4;光敏电阻:D2,还有一个10k欧下拉电阻

  1. #include <SPI.h>
  2. #include <Wire.h>
  3. #include <Adafruit_GFX.h>
  4. #include <Adafruit_SSD1306.h>
  5. #include "RTClib.h"

  6. RTC_DS1307 rtc;
  7. /*initiate the OLED;*/
  8. #define OLED_MOSI 9
  9. #define OLED_CLK 10
  10. #define OLED_DC 11
  11. #define OLED_CS 12
  12. #define OLED_RESET 13
  13. Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

  14. #define NUMFLAKES 10
  15. #define XPOS 0
  16. #define YPOS 1
  17. #define DELTAY 2

  18. #define LOGO16_GLCD_HEIGHT 16
  19. #define LOGO16_GLCD_WIDTH  16

  20. #if (SSD1306_LCDHEIGHT != 64)
  21. #error("Height incorrect, please fix Adafruit_SSD1306.h!");
  22. #endif

  23. int counter=0;
  24. int light;
  25. int year1,month1,day1;
  26. int hour1;
  27. int minute1;
  28. int second1;
  29. float hx,hy,mx,my,sy,sx;
  30. float pi=3.1415926;

  31. void setup(){
  32.   display.begin(SSD1306_SWITCHCAPVCC);
  33.   display.clearDisplay();
  34.   #ifdef AVR
  35.   Wire.begin();
  36. #else
  37.   Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
  38. #endif
  39.   rtc.begin();

  40.   if (! rtc.isrunning()) {
  41.     Serial.println("RTC is NOT running!");
  42.     // following line sets the RTC to the date & time this sketch was compiled
  43.     rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  44.     // This line sets the RTC with an explicit date & time, for example to set
  45.     // January 21, 2014 at 3am you would call:
  46.     // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  47.   }
  48.   attachInterrupt(0,counterChange,FALLING);
  49. }
  50. void loop(){
  51.   DateTime now = rtc.now();
  52.   year1=now.year();
  53.   month1=now.month();
  54.   day1=now.day();
  55.   switch(counter){
  56.     case 0:showtime();delay(200);break;
  57.     case 1:showdate();delay(200);break;
  58.     case 2:showweather();delay(200);break;
  59.   }
  60. }
  61. void showtime(){
  62.   display.clearDisplay();
  63.   while(1){
  64.     DateTime now = rtc.now();
  65.   
  66.   hour1=now.hour();
  67.   if(hour1>=12)hour1=hour1-12;
  68.   minute1=now.minute();
  69.   second1=now.second();
  70.     display.setTextSize(1);
  71.     display.setTextColor(WHITE);
  72.     display.setCursor(display.width()/2-2, display.height()/2+26-2);
  73.     display.print("6");
  74.     display.setCursor(display.width()/2+26-2, display.height()/2-2);
  75.     display.print("3");
  76.     display.setCursor(display.width()/2-5, display.height()/2-26-2);
  77.     display.print("12");
  78.     display.setCursor(display.width()/2-26-2, display.height()/2-2);
  79.     display.print("9");
  80.     display.fillCircle(77,10,1,WHITE);//1
  81.     display.fillCircle(86,19,1,WHITE);//2
  82.     display.fillCircle(86,45,1,WHITE);//4
  83.     display.fillCircle(77,54,1,WHITE);//5
  84.     display.fillCircle(51,54,1,WHITE);//7
  85.     display.fillCircle(42,45,1,WHITE);//8
  86.     display.fillCircle(42,19,1,WHITE);//10
  87.     display.fillCircle(51,10,1,WHITE);//11
  88.     display.fillCircle(64,32,1,WHITE);//center
  89.     display.display();
  90.     hx=18*sin((30.0*hour1+minute1/2.0)/180.0*pi);
  91.    
  92.     hy=18*cos((30.0*hour1+minute1/2.0)/180.0*pi);
  93.    
  94.     mx=22*sin((minute1*6.0)/180.0*pi);
  95.    
  96.     my=22*cos((minute1*6.0)/180.0*pi);
  97.    
  98.     sx=22*sin((second1*6.0)/180.0*pi);
  99.    
  100.     sy=22*cos((second1*6.0)/180.0*pi);
  101.    
  102.     display.drawLine(64,32,64+hx,32-hy,WHITE);//hour
  103.     display.drawLine(64,32,64+mx,32-my,WHITE);//minute
  104.     display.drawLine(64,32,64+sx,32-sy,WHITE);//second
  105.     display.display();
  106.     delay(950);
  107.     display.clearDisplay();
  108.    
  109.     if(counter!=0)break;   
  110.   }
  111. }
  112. void showdate(){
  113.   display.clearDisplay();
  114.   while(1){
  115.   display.setTextSize(1);
  116.   display.setTextColor(WHITE);
  117.   display.setCursor(40,20);
  118.   display.print("Today is:");
  119.   display.setCursor(40,28);
  120.   display.print(year1);
  121.   display.print("/");
  122.   display.print(month1);
  123.   display.print("/");
  124.   display.print(day1);
  125.   display.display();
  126.   
  127.   if(counter!=1)break;   
  128.   }
  129. }
  130. void showweather(){
  131.   display.clearDisplay();
  132.   while(1){
  133.   display.setTextSize(1);
  134.   display.setTextColor(WHITE);
  135.   display.setCursor(20,20);
  136.   display.print("temperature:28.3^C");
  137.   display.display();
  138.   
  139.   if(counter!=2)break;   
  140.   }
  141. }
  142. void counterChange(){
  143.   counter++;
  144.   if(counter>2)counter=0;
  145. }
复制代码

还有很多地方还没完善,例如温度传感器还没加上,大家一起学习交流一下吧

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2015-8-7 00:32:23 | 显示全部楼层
很厉害~~~!!!
回复 支持 反对

使用道具 举报

发表于 2015-8-7 12:32:38 | 显示全部楼层
硬件成本多少啊?还没买过OLED
回复 支持 反对

使用道具 举报

发表于 2015-8-7 19:46:44 | 显示全部楼层
oled分辨率是高可惜尺寸太小乐趣,而且多是单色的,大屏的太贵了,大屏全彩的模块还没看到
回复 支持 反对

使用道具 举报

发表于 2015-8-7 19:54:32 | 显示全部楼层
怎么用按键换页?第一面显示时间,温湿度。第二页显示气压高度,第三面显示电子罗盘。用U8GLIB的库。小白一个,用别人的程序拼越来不行啊,老花屏,而且气压读数也不正常,能帮改一下么,谢谢!
#include "U8glib.h"
#include <dht11.h>
#include "DS18B20_S.h"
#include <DS3231.h>
#include <Wire.h>
#include "I2Cdev.h"
#include "BMP085.h"
dht11 DHT11;
int button=5;
int val;
BMP085 barometer;
float pressure;
float altitude;
int32_t lastMicros;
unsigned long time1=millis();

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE);

DS18B20_S  ds(7);//pin9
#define DHT11PIN 4

DS3231 Clock;
bool Century=false;
bool h12;
bool PM;
byte ADay, AHour, AMinute, ASecond, ABits;
bool ADy, A12h, Apm;
int second,minute,hour,date,DoW,month,year;

int page = 0;
int max_pages = 2;

void draw(void) {
  
  u8g.setFont(u8g_font_gdr10);
   
  switch(page){
    case 1:
    {
  u8g.drawLine(0,17 , 128, 17);
  u8g.drawLine(0,49 , 128, 49);
  
  u8g.setPrintPos(0, 64);
   u8g.print(ds.get(),1);
   u8g.setPrintPos(34, 64);
   u8g.print(char(176));
   u8g.print("C");
   
   u8g.setPrintPos(88, 64);
   u8g.print((float)DHT11.humidity, 1);
   u8g.setPrintPos(116, 64);
   u8g.print("%");  
  
  u8g.setPrintPos(0, 13);
  u8g.print("20");
  u8g.print(year);
  u8g.print(".");
  u8g.print(month);
  u8g.print(".");
  u8g.print(date);


  u8g.setPrintPos(0, 47);  //定义显示位置 横向起始位置0 纵向45
  if(PM==0)                     //判断变量PM返回值 0就显示AM  1就显示PM
  {
  u8g.print("AM");
  }
  else
{
u8g.print("PM");
}
  u8g.setFont(u8g_font_freedoomr25n);  //设定字体(具体请参看 U8GLIB google code页面,大量字体可选)
  u8g.print(hour);                    //输出小时的值
  u8g.print(":");                        //显示一个冒号
  u8g.print(minute);                //显示分钟的值
  u8g.setFont(u8g_font_freedoomr10r);  //调整显示字体
  u8g.print(":");                         //再显示冒号
  u8g.print(second);                       //显示秒
    }
    break;
    case 2:
    {
    u8g.setPrintPos(2, 10);
    u8g.print("Alt:");
    u8g.print(altitude,1);
    u8g.print("M");
    u8g.setPrintPos(2, 25);
   u8g.print("Atm:");
    u8g.print(pressure/1000,3);
    u8g.print("Kpa");
    }
    break;
  }
}

void setup(void)
{
  Wire.begin();
  barometer.initialize();
  Clock.setClockMode(true);
  pinMode(5,INPUT);
}
void loop(void)
{
  ds.start();
  float a=ds.get();
  second=Clock.getSecond();              //秒
  minute=Clock.getMinute();              //分
  hour=Clock.getHour(h12,PM);           //小时 (分上午和下午模式)   
  date=Clock.getDate();                   //日
  month=Clock.getMonth(Century);          //月
  year=Clock.getYear();
  vobmp085();
  int chk = DHT11.read(DHT11PIN);
  val=digitalRead(5);
  if(val==LOW)
  {
    u8g.firstPage();  
  }
  else if(val==HIGH)
  {
  do
  {
    draw();
  }
  while( u8g.nextPage() );

  page==max_pages?page=0:page++;

  }
   
   }


void vobmp085()
{
  barometer.setControl(BMP085_MODE_TEMPERATURE);

  lastMicros = micros();
  while (micros() - lastMicros < barometer.getMeasureDelayMicroseconds());

  barometer.setControl(BMP085_MODE_PRESSURE_3);
  while (micros() - lastMicros < barometer.getMeasureDelayMicroseconds());

  pressure = barometer.getPressure();

  altitude = barometer.getAltitude(pressure)-120;
}
回复 支持 反对

使用道具 举报

发表于 2015-8-7 19:56:40 | 显示全部楼层
貌似用光敏电阻切换不实用,容易误触发,还是用按键好,如果OLED能够调亮度,用光敏电阻改变屏幕亮度还是不错的。另外感觉adafruit库太大了嘛,刚刚编译了一下你那么程序,用了78%内存
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-8-8 11:35:44 | 显示全部楼层
雨轩 发表于 2015-8-7 19:56
貌似用光敏电阻切换不实用,容易误触发,还是用按键好,如果OLED能够调亮度,用光敏电阻改变屏幕亮度还是不 ...

不会吧,adafruit的比U8Glib的小很多呢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-8-8 11:40:23 | 显示全部楼层
雨轩 发表于 2015-8-7 19:56
貌似用光敏电阻切换不实用,容易误触发,还是用按键好,如果OLED能够调亮度,用光敏电阻改变屏幕亮度还是不 ...

光敏电阻切换酷炫哈
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-8-8 11:45:09 | 显示全部楼层
雨轩 发表于 2015-8-7 19:54
怎么用按键换页?第一面显示时间,温湿度。第二页显示气压高度,第三面显示电子罗盘。用U8GLIB的库。小白一 ...

u8g的库不是很会用,我还没用他点亮OLED  0.0
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-8-8 11:47:51 | 显示全部楼层
GeekHQM 发表于 2015-8-7 12:32
硬件成本多少啊?还没买过OLED

OLED比较贵,0.96寸的就要20-30了,但是确实比其他LCD要漂亮好多
回复 支持 反对

使用道具 举报

发表于 2015-8-8 20:25:17 | 显示全部楼层
初学者学习
回复 支持 反对

使用道具 举报

发表于 2015-10-15 20:02:23 | 显示全部楼层
Cambridge 发表于 2015-8-8 11:45
u8g的库不是很会用,我还没用他点亮OLED  0.0

那如果就用adafruit呢?怎么写?我硬件搞好了,不会写软件,嘿嘿
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-4-25 13:20 , Processed in 0.042512 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表