前一陣子看到一個ESP8266的開發版,蠻特別的非ESP模組 + 0.91" SSD1306 OLED顯示器,WiFi Kit 8,大概就2cm x 5cm 的大小,內建CP2104模組,插USB即可直接燒錄程式碼。

kit81.png

kit82.png

 

當下有一個想法,有什麼資料可以從網路下載直接顯示出來........股票好像是一個不錯的選擇

好吧!就動手做看看吧

首先,要顯示當下的日期時間,可以參考這篇,有很詳盡的說明

利用 NTP 伺服器來同步 Arduino 系統時鐘 (二)


文章裡面是使用LCD,修改一下用OLED,使用 Adafruit_SSD1306.h 的函式庫,然後自製WiFi 訊號強度圖示,原本扇形的有點醜,把他改成手機訊號的型式。

程式碼如下:

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h> 

//oled
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 16 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

unsigned int localPort=2390; //local port to listen for UDP packets
IPAddress timeServerIP; //time.nist.gov NTP server address
const char* ntpServerName="time.nist.gov"; //NTP Server host name
const int NTP_PACKET_SIZE=48; //NTP timestamp resides in the first 48 bytes of packets
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
WiFiUDP udp; //UDP instance to let us send and receive packets over UDP
int count=0;
 static const unsigned char PROGMEM signal5[] =
{
 0xfe, 0x00, 0x00, 0x92, 0x00, 0x03, 0x54, 0x00, 0x33, 0x38, 0x03, 0x33, 0x10, 0x33, 0x33, 0x10, 
 0x33, 0x33, 0x13, 0x33, 0x33, 0x00, 0x00, 0x00 
};
 static const unsigned char PROGMEM signal4[] =
{
 0xfe, 0x00, 0x00, 0x92, 0x00, 0x00, 0x54, 0x00, 0x30, 0x38, 0x03, 0x30, 0x10, 0x33, 0x30, 0x10, 
 0x33, 0x30, 0x13, 0x33, 0x30, 0x00, 0x00, 0x00
};
 static const unsigned char PROGMEM signal3[] =
{
 0xfe, 0x00, 0x00, 0x92, 0x00, 0x00, 0x54, 0x00, 0x00, 0x38, 0x03, 0x00, 0x10, 0x33, 0x00, 0x10, 
 0x33, 0x00, 0x13, 0x33, 0x00, 0x00, 0x00, 0x00
};
 static const unsigned char PROGMEM signal2[] =
{
 0xfe, 0x00, 0x00, 0x92, 0x00, 0x00, 0x54, 0x00, 0x00, 0x38, 0x00, 0x00, 0x10, 0x30, 0x00, 0x10, 
 0x30, 0x00, 0x13, 0x30, 0x00, 0x00, 0x00, 0x00
};
 static const unsigned char PROGMEM signal1[] =
{
 0xfe, 0x00, 0x00, 0x92, 0x00, 0x00, 0x54, 0x00, 0x00, 0x38, 0x00, 0x00, 0x10, 0x00, 0x00, 0x10, 
 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00 
};
 static const unsigned char PROGMEM signal0[] =
{
 0xfe, 0x00, 0x00, 0x92, 0x00, 0x20, 0x54, 0x00, 0x20, 0x39, 0x26, 0x20, 0x11, 0xa9, 0x20, 0x11, 
 0x69, 0x00, 0x11, 0x26, 0x20, 0x00, 0x00, 0x00 
};

void setup() {
 Serial.begin(115200);
 if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32
 Serial.println(F("SSD1306 allocation failed"));
 for(;;); // Don't proceed, loop forever
 }

 // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
 display.display();
 
 WiFiManager wifiManager;
 wifiManager.autoConnect("AutoConnectAP");
 //Start UDP
 Serial.println("Starting UDP");
 udp.begin(localPort);
 Serial.print("Local port: ");
 Serial.println(udp.localPort());
 sync_clock(); //以 NTP 時間初始設定內部時鐘

 // Clear the buffer
 display.clearDisplay();
}
void loop() {
 //int rssi = WiFi.RSSI();
 String d=getDate();
 String t=getTime();
 String w=getWeek();
 int Hm=hour()*100 + minute(); //時:分整數, 02359
 Serial.print(d + " " + t + " " + w + " ");
 Serial.println(Hm);
 display.clearDisplay();
 display.setTextSize(1); // Normal 1:1 pixel scale
 display.setTextColor(SSD1306_WHITE); // Draw white text
 display.setCursor(0,0); // Start at top-left corner
 display.print(d);display.print(" ");display.println(w);//display.print(" ");display.println(rssi);
 display.println(" ");
 display.setTextSize(2);
 display.println(t);
 //display.drawBitmap(96, 0, signal1_icon24x8, 24, 8, SSD1306_WHITE);
 winfi_signal();
 display.display();
 ++count;
 if (count >= 300) { //每 40 次迴圈與 NTP 同步一次
 sync_clock();
 count=0;
 }
 delay(1000);
 }
 
void sync_clock() {
 unsigned long GMT=getUnixTime();
 if (GMT != 0) { //有得到 NTP 回應才更新 ESP8266 內建 RTC
 setTime(GMT + 28800L); //以台灣時間更新內部時鐘
 }
 }
void winfi_signal(){
 int rssi = WiFi.RSSI();
 if(rssi<-30 && rssi>=-40)
 display.drawBitmap(104, 0, signal5, 24, 8, 1);
 else if(rssi<-40 && rssi>=-50)
 display.drawBitmap(104, 0, signal4, 24, 8, 1);
 else if(rssi<-50 && rssi>=-60)
 display.drawBitmap(104, 0, signal3, 24, 8, 1); 
 else if(rssi<-60 && rssi>=-70)
 display.drawBitmap(104, 0, signal2, 24, 8, 1);
 else if(rssi<-70 && rssi>=-80)
 display.drawBitmap(104, 0, signal1, 24, 8, 1);
 else
 display.drawBitmap(104, 0, signal0, 24, 8, 1);
}
String getDate() {
 String d=(String)year() + "-";
 byte M=month();
 if (M < 10) {d.concat('0');}
 d.concat(M);
 d.concat('-');
 byte D=day();
 if (D < 10) {d.concat('0');}
 d.concat(D);
 return d;
 }

String getTime() {
 String t="";
 byte h=hour();
 if (h < 10) {t.concat('0');}
 t.concat(h);
 t.concat(':');
 byte m=minute();
 if (m < 10) {t.concat('0');}
 t.concat(m);
 t.concat(':');
 byte s=second();
 if (s < 10) {t.concat('0');}
 t.concat(s);
 return t;
 }

String getWeek() {
 String w[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
 return w[weekday()-1];
 }

String getDateTime() { //傳回日期時間
 String dt=(String)year() + "-";
 byte M=month();
 if (M < 10) {dt.concat('0');}
 dt.concat(M);
 dt.concat('-');
 byte d=day();
 if (d < 10) {dt.concat('0');}
 dt.concat(d);
 dt.concat(' ');
 byte h=hour();
 if (h < 10) {dt.concat('0');}
 dt.concat(h);
 dt.concat(':');
 byte m=minute();
 if (m < 10) {dt.concat('0');}
 dt.concat(m);
 dt.concat(':');
 byte s=second();
 if (s < 10) {dt.concat('0');}
 dt.concat(s);
 return dt; //傳回格式如 2016-07-16 16:09:23 的日期時間字串
 }

unsigned long getUnixTime() {
 WiFi.hostByName(ntpServerName, timeServerIP); //get a random server from the pool
 sendNTPpacket(timeServerIP); //send an NTP packet to a time server
 delay(1000); // wait to see if a reply is available

 int cb=udp.parsePacket(); //return bytes received
 unsigned long unix_time=0; //預設傳回 0, 表示未收到 NTP 回應
 if (!cb) {Serial.println("no packet yet");}
 else { //received a packet, read the data from the buffer
 Serial.print("packet received, length=");
 Serial.println(cb); //=48
 udp.read(packetBuffer, NTP_PACKET_SIZE); //read the packet into the buffer

 //the timestamp starts at byte 40 of the received packet and is four bytes,
 //or two words, long. First, esxtract the two words:
 unsigned long highWord=word(packetBuffer[40], packetBuffer[41]);
 unsigned long lowWord=word(packetBuffer[42], packetBuffer[43]);
 //combine the four bytes (two words) into a long integer
 //this is NTP time (seconds since Jan 1 1900):
 unsigned long secsSince1900=highWord << 16 lowWord;
 Serial.print("Seconds since Jan 1 1900=" );
 Serial.println(secsSince1900);
 Serial.print("Unix time=");
 //Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
 unix_time=secsSince1900 - 2208988800UL; //更新 unix_time
 Serial.print(F("Unix time stamp (seconds since 1970-01-01)="));
 Serial.println(unix_time); //print Unix time
 } 
 return unix_time; //return seconds since 1970-01-01
 }

unsigned long sendNTPpacket(IPAddress& address) {
 Serial.println("sending NTP packet...");
 // set all bytes in the buffer to 0
 memset(packetBuffer, 0, NTP_PACKET_SIZE);
 //Initialize values needed to form NTP request
 //(see URL above for details on the packets)
 packetBuffer[0]=0b11100011; // LI, Version, Mode
 packetBuffer[1]=0; // Stratum, or type of clock
 packetBuffer[2]=6; // Polling Interval
 packetBuffer[3]=0xEC; // Peer Clock Precision
 //8 bytes of zero for Root Delay & Root Dispersion
 packetBuffer[12]=49;
 packetBuffer[13]=0x4E;
 packetBuffer[14]=49;
 packetBuffer[15]=52;
 // all NTP fields have been given values, now
 // you can send a packet requesting a timestamp:
 udp.beginPacket(address, 123); //NTP requests are to port 123
 udp.write(packetBuffer, NTP_PACKET_SIZE);
 udp.endPacket();
 }


ntp1.png
ntp2.png
大功告成,放在辦公室當時鐘也挺不錯的

這是第一步,接下來就要燒腦了,如何去把股票的即時資料抓下來,來杯咖啡好好爬文一下!

 

ESP8266 一次就上手 / Google Script + Google試算表 =股票機 (二)

文章標籤
全站熱搜
創作者介紹
創作者 terrywu5 的頭像
terrywu5

IoT 智慧生活的異想世界

terrywu5 發表在 痞客邦 留言(0) 人氣(678)