close

前一陣子看到一個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();   //時:分整數, 0~2359
    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試算表 =股票機 (二)

arrow
arrow
    創作者介紹
    創作者 terrywu5 的頭像
    terrywu5

    IoT 智慧生活的異想世界

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