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;
}
还有很多地方还没完善,例如温度传感器还没加上,大家一起学习交流一下吧 很厉害~~~!!! 硬件成本多少啊?:D还没买过OLED oled分辨率是高可惜尺寸太小乐趣,而且多是单色的,大屏的太贵了,大屏全彩的模块还没看到 怎么用按键换页?第一面显示时间,温湿度。第二页显示气压高度,第三面显示电子罗盘。用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;
} 貌似用光敏电阻切换不实用,容易误触发,还是用按键好,如果OLED能够调亮度,用光敏电阻改变屏幕亮度还是不错的。另外感觉adafruit库太大了嘛,刚刚编译了一下你那么程序,用了78%内存 雨轩 发表于 2015-8-7 19:56 static/image/common/back.gif
貌似用光敏电阻切换不实用,容易误触发,还是用按键好,如果OLED能够调亮度,用光敏电阻改变屏幕亮度还是不 ...
不会吧,adafruit的比U8Glib的小很多呢 雨轩 发表于 2015-8-7 19:56 static/image/common/back.gif
貌似用光敏电阻切换不实用,容易误触发,还是用按键好,如果OLED能够调亮度,用光敏电阻改变屏幕亮度还是不 ...
光敏电阻切换酷炫哈 雨轩 发表于 2015-8-7 19:54 static/image/common/back.gif
怎么用按键换页?第一面显示时间,温湿度。第二页显示气压高度,第三面显示电子罗盘。用U8GLIB的库。小白一 ...
u8g的库不是很会用,我还没用他点亮OLED0.0 GeekHQM 发表于 2015-8-7 12:32 static/image/common/back.gif
硬件成本多少啊?还没买过OLED
OLED比较贵,0.96寸的就要20-30了,但是确实比其他LCD要漂亮好多 初学者学习 Cambridge 发表于 2015-8-8 11:45 static/image/common/back.gif
u8g的库不是很会用,我还没用他点亮OLED0.0
那如果就用adafruit呢?怎么写?我硬件搞好了,不会写软件,嘿嘿
页:
[1]