Cambridge 发表于 2015-8-7 00:06:45

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

本帖最后由 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欧下拉电阻

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "RTClib.h"

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

#define NUMFLAKES 10
#define XPOS 0
#define YPOS 1
#define DELTAY 2

#define LOGO16_GLCD_HEIGHT 16
#define LOGO16_GLCD_WIDTH16

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

int counter=0;
int light;
int year1,month1,day1;
int hour1;
int minute1;
int second1;
float hx,hy,mx,my,sy,sx;
float pi=3.1415926;

void setup(){
display.begin(SSD1306_SWITCHCAPVCC);
display.clearDisplay();
#ifdef AVR
Wire.begin();
#else
Wire1.begin(); // Shield I2C pins connect to alt I2C bus on Arduino Due
#endif
rtc.begin();

if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
}
attachInterrupt(0,counterChange,FALLING);
}
void loop(){
DateTime now = rtc.now();
year1=now.year();
month1=now.month();
day1=now.day();
switch(counter){
    case 0:showtime();delay(200);break;
    case 1:showdate();delay(200);break;
    case 2:showweather();delay(200);break;
}
}
void showtime(){
display.clearDisplay();
while(1){
    DateTime now = rtc.now();

hour1=now.hour();
if(hour1>=12)hour1=hour1-12;
minute1=now.minute();
second1=now.second();
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(display.width()/2-2, display.height()/2+26-2);
    display.print("6");
    display.setCursor(display.width()/2+26-2, display.height()/2-2);
    display.print("3");
    display.setCursor(display.width()/2-5, display.height()/2-26-2);
    display.print("12");
    display.setCursor(display.width()/2-26-2, display.height()/2-2);
    display.print("9");
    display.fillCircle(77,10,1,WHITE);//1
    display.fillCircle(86,19,1,WHITE);//2
    display.fillCircle(86,45,1,WHITE);//4
    display.fillCircle(77,54,1,WHITE);//5
    display.fillCircle(51,54,1,WHITE);//7
    display.fillCircle(42,45,1,WHITE);//8
    display.fillCircle(42,19,1,WHITE);//10
    display.fillCircle(51,10,1,WHITE);//11
    display.fillCircle(64,32,1,WHITE);//center
    display.display();
    hx=18*sin((30.0*hour1+minute1/2.0)/180.0*pi);
   
    hy=18*cos((30.0*hour1+minute1/2.0)/180.0*pi);
   
    mx=22*sin((minute1*6.0)/180.0*pi);
   
    my=22*cos((minute1*6.0)/180.0*pi);
   
    sx=22*sin((second1*6.0)/180.0*pi);
   
    sy=22*cos((second1*6.0)/180.0*pi);
   
    display.drawLine(64,32,64+hx,32-hy,WHITE);//hour
    display.drawLine(64,32,64+mx,32-my,WHITE);//minute
    display.drawLine(64,32,64+sx,32-sy,WHITE);//second
    display.display();
    delay(950);
    display.clearDisplay();
   
    if(counter!=0)break;   
}
}
void showdate(){
display.clearDisplay();
while(1){
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(40,20);
display.print("Today is:");
display.setCursor(40,28);
display.print(year1);
display.print("/");
display.print(month1);
display.print("/");
display.print(day1);
display.display();

if(counter!=1)break;   
}
}
void showweather(){
display.clearDisplay();
while(1){
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(20,20);
display.print("temperature:28.3^C");
display.display();

if(counter!=2)break;   
}
}
void counterChange(){
counter++;
if(counter>2)counter=0;
}
还有很多地方还没完善,例如温度传感器还没加上,大家一起学习交流一下吧

Atoney 发表于 2015-8-7 00:32:23

很厉害~~~!!!

GeekHQM 发表于 2015-8-7 12:32:38

硬件成本多少啊?:D还没买过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_Sds(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就显示AM1就显示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%内存

Cambridge 发表于 2015-8-8 11:35:44

雨轩 发表于 2015-8-7 19:56 static/image/common/back.gif
貌似用光敏电阻切换不实用,容易误触发,还是用按键好,如果OLED能够调亮度,用光敏电阻改变屏幕亮度还是不 ...

不会吧,adafruit的比U8Glib的小很多呢

Cambridge 发表于 2015-8-8 11:40:23

雨轩 发表于 2015-8-7 19:56 static/image/common/back.gif
貌似用光敏电阻切换不实用,容易误触发,还是用按键好,如果OLED能够调亮度,用光敏电阻改变屏幕亮度还是不 ...

光敏电阻切换酷炫哈

Cambridge 发表于 2015-8-8 11:45:09

雨轩 发表于 2015-8-7 19:54 static/image/common/back.gif
怎么用按键换页?第一面显示时间,温湿度。第二页显示气压高度,第三面显示电子罗盘。用U8GLIB的库。小白一 ...

u8g的库不是很会用,我还没用他点亮OLED0.0

Cambridge 发表于 2015-8-8 11:47:51

GeekHQM 发表于 2015-8-7 12:32 static/image/common/back.gif
硬件成本多少啊?还没买过OLED

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

mondaywoo 发表于 2015-8-8 20:25:17

初学者学习

雨轩 发表于 2015-10-15 20:02:23

Cambridge 发表于 2015-8-8 11:45 static/image/common/back.gif
u8g的库不是很会用,我还没用他点亮OLED0.0

那如果就用adafruit呢?怎么写?我硬件搞好了,不会写软件,嘿嘿
页: [1]
查看完整版本: OLED+DS1307+光敏电阻制作模拟钟表,实现手势感应切换画面