2024/1/7
下午看到 Volos 大神的新影片,時間月曆很漂亮
本來忙別的事,還是忍不住就動動手試著轉至 Pico_Game 上了
原作者的影片,https://www.youtube.com/watch?v=lCZJ36ELdRY&t=606s
原專案為使用 M5 + RTC 來設定時間
我改為使用 Pico_W + Pico_Game,,用網路 NTP 時間自動更新
目前轉至 Pico W 的 arduino 完整程式請見以下 link
https://drive.google.com/drive/folders/1xqDVREq4Be39KYCcGz0h2KhBiO-tqWcH
file: 10_pico_game_deskGauge.zip
Arduino Pico_Game 環境,可用我目前打包的可攜版本
link : https://drive.google.com/drive/folders/1zBnLwsjQWi7zIyoj8PP9tPbz93RwkmZm
file : arduino-1.8.19_picogame.zip ,建議在根目錄下解開,大小約 1G
arduino 主程式如下:
請記得先改成你的 wifi 後,再上傳至 Pico_Game 上
// Pico_Game 月曆時間 by Mason 2024/1/7
// Ref : https://github.com/VolosR/desktopGauges/blob/main/DeskGauges/deskGauge/deskGauge.ino
// 原先為使用 M5,改為使用 Pico_W + Pico_Game
// 原先為使用 RTC 獲取時間,改為使用網路 NTP 時間
#include <Wire.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <NTPClient.h>
#include <ArduinoJson.h>
#include <WiFiUdp.h>
#include "Arduino.h"
#include <TFT_eSPI.h>
#include <SPI.h>
#include "font.h"
#include "sett.h"
#include "boldFont.h"
// 設定要連的 WIFI 帳號和密碼
const char *ssid = "xxxx";
const char *password = "1234567890";
unsigned long currentSec;
WiFiClient wifiClient;
String weatherStr, nowTemp, maxTemp, minTemp;
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org"); // NTP 得到時間
String currentTime, hour, minute,second;
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite spr = TFT_eSprite(&tft);
int tm_Year,tm_Month,monthDay;
int tm_Hour,tm_Minute,tm_Second;
int daysInMonth;
int weekDay,month,day,year,firstDay;
float vol, curr;
String lblT[]={"HOUR","MIN","SEC","DAY","MONTH","YEAR"};
int posTX[6]={50,160,280,50,160,280};
int posTY[6]={90,90,90,90,90,90};
bool timeOrDate=0;
String lblTod[2]={"DATE","TIME"};
String lblBoW[2]={"BRIGHTNES","WEEKDAY"};
int BoW[2]={2,3};
bool mode=0;
String days2[7]={"SUNDAY","MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY"};
String days[7]={"Mo","Tu","We","Th","Fr","Sa","Su"};
String monthNames[12]={"JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE","JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"};
unsigned short grays[13];
unsigned short blue=0x1BB7;
unsigned short blue2=0x469F;
unsigned short darkOrange=0xC460 ;
float tmp = 0.0;
float hum = 0.0;
float pressure = 0.0;
bool light=0;
int y=0;
int x=0;
int brightness[7]={2580,2650,2725,2820,2900,3000,3200};
int flag = 1;
// int tm_Hour,tm_Minute,monthDay,tm_Month;
int weather_state;
int week_day;
// 儲存日期及時間的變數
String formattedDate;
String dayStamp;
String timeStamp;
String splitString(String data, char separator, int index)
{
int stringData = 0; //variable to count data part nr
String dataPart = ""; //variable to hole the return text
for(int i = 0; i<data.length(); i++) {
if(data[i]==separator) {
//Count the number of times separator character appears in the text
stringData++;
}else if(stringData==index) {
//get the text when separator is the rignt one
dataPart.concat(data[i]);
}else if(stringData>index) {
//return text and stop if the next separator appears - to save CPU-time
return dataPart;
break;
}
}
return dataPart;
}
void setup() {
tft.init(); // 初始化
tft.invertDisplay(true);
tft.fillScreen(TFT_BLACK); // 填上黑色
tft.setTextColor(TFT_WHITE); // 字體為白色
tft.setCursor(15+40, 30, 1); // 設定顯示的座標
tft.setTextSize(2);
tft.setRotation(1); // 旋轉方向,0/1/2/3 會各轉90度,視使用情況來設定
tft.println("Connect to Wifi ~");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected"); // 連線成功
Serial.print("IP address: ");
Serial.println(WiFi.localIP()); // 印出 IP address
tft.fillScreen(TFT_BLACK);
tft.setCursor(20+40, 30, 2);
tft.setTextSize(2);
tft.println("WiFi Connected!");
delay(200);
if (WiFi.status() == WL_CONNECTED )
{
// 使用 NTP 抓取網路時間
timeClient.begin();
timeClient.setTimeOffset(8 * 3600); //UTC+8 8 * 3600
while (!timeClient.update()) {
timeClient.forceUpdate();
}
}
tft.fillScreen(TFT_BLACK);
spr.createSprite(320,240);
int co=220;
for(int i=0;i<13;i++)
{
grays[i]=tft.color565(co, co, co);
co=co-20;
}
}
void draw() {
if(mode==0){
spr.fillSprite(TFT_BLACK);
spr.setTextDatum(0);
spr.fillRect(5,0,252,4,blue);
spr.setFreeFont(&DSEG14_Modern_Bold_56);
spr.setTextColor(TFT_WHITE,TFT_BLACK);
spr.drawString(hour+":"+minute,10,15); ///
spr.setFreeFont(&DSEG14_Modern_Bold_26);
spr.setTextColor(0xD69A,TFT_BLACK);
spr.drawString(second,212,44); ///
spr.fillRect(274,0,40,18,darkOrange);
spr.fillRect(314,4,4,10,darkOrange);
spr.setTextColor(TFT_BLACK,darkOrange);
spr.drawString(String(vol),278,1,2);
spr.setTextColor(grays[3],TFT_BLACK);
spr.drawString(String(curr),80,220,2);
spr.fillRoundRect(273,25,47,78,3,blue);
spr.fillRoundRect(282,28,27,37,8,grays[0]);
spr.fillRoundRect(288,55,15,37,4,grays[0]);
spr.fillRoundRect(292,65,7,10,2,blue);
spr.fillRect(282,28,27,15,blue);
spr.fillRect(282,48,27,3,blue);
if(light)
{
for(int i=0;i<4;i++)
spr.fillRoundRect(282+(i*8),29,3,9,2,grays[0]);
}
//YEAR
spr.setTextColor(darkOrange,TFT_BLACK);
spr.fillRect(210,82,46,2,darkOrange);
spr.drawString(String(tm_Year),224,85,2);
spr.drawString("BRIGHT",80,178,2);
spr.drawString("POWER",80,205,2);
// bright
for(int i=0;i<7;i++)
spr.fillRect(80+i*7,195,3,8,grays[8]);
for(int i=0;i<BoW[0];i++)
spr.fillRect(80+i*7,195,3,8,grays[2]);
spr.setTextDatum(4);
spr.fillRoundRect(0, 110, 64, 60, 4, grays[9]);
spr.fillRoundRect(70, 110, 64, 60, 4, grays[9]);
spr.setTextColor(grays[2],grays[9]);
spr.drawString(String((int)tmp)+"C",32,155,4);
spr.drawString(String((int)hum)+"%",102,155,4);
spr.setFreeFont(&DejaVu_LGC_Sans_Mono_15);
spr.setTextColor(blue2,grays[9]);
spr.drawString("TMP",32,124);
spr.drawString("HUM",102,124);
spr.setTextColor(grays[4],TFT_BLACK);
// spr.drawString(monthNames[month-1]+" "+String(day)+", "+days2[weekDay],12,92);
spr.drawString(monthNames[tm_Month-1]+" "+String(monthDay)+", "+days2[week_day],100,92);
spr.fillRoundRect(140, 110, 180, 130, 6, grays[9]);
spr.fillRect(150,134,160,1,grays[4]);
spr.fillRect(12,134,40,1,darkOrange);
spr.setTextColor(grays[0],grays[9]);
for(int i=0;i<7;i++)
spr.drawString(days[i],160+(i*23),124,2);
int n=1;
bool found=false;
for(int i=0;i<5;i++)
for(int j=0;j<7;j++)
{
if(j==firstDay ) found=true;
if(found && n<=daysInMonth) // daysInMonth
{
if(n==monthDay)
spr.setTextColor(blue2,grays[9]);
else
spr.setTextColor(grays[4],grays[9]);
spr.drawString(String(n),160+(j*23),144+(i*18),2);
n++;
}
}
spr.pushImage(2,175,64,64,sett);
}
spr.pushSprite(0,0);
}
void loop() {
timeClient.update();
unsigned long epochTime = timeClient.getEpochTime();
// Serial.println(epochTime);
if(flag == 1)
{
currentSec = epochTime;
flag = 0;
}
String formattedTime = timeClient.getFormattedTime();
// Serial.println(formattedTime);
// 取得日期
// formattedDate函式取得的日期格式為: 2022-06-24T16:00:13Z
formattedDate = timeClient.getFormattedDate();
int splitT = formattedDate.indexOf("T");
dayStamp = formattedDate.substring(0, splitT);
tm_Year = splitString(dayStamp, '-', 0).toInt();
tm_Month = splitString(dayStamp, '-', 1).toInt();
monthDay = splitString(dayStamp, '-', 2).toInt();
Serial.print("DATE: ");
Serial.println(tm_Month);
tm_Hour = timeClient.getHours();
tm_Minute = timeClient.getMinutes();
tm_Second = timeClient.getSeconds();
week_day = timeClient.getDay();
String currentDate = String(tm_Month) + "/" + String(monthDay);
if (tm_Hour < 10)
hour = "0" + String(tm_Hour);
else
hour = String(tm_Hour);
if (tm_Minute < 10)
minute = "0" + String(tm_Minute);
else
minute = String(tm_Minute);
if (tm_Second < 10)
second = "0" + String(tm_Second);
else
second = String(tm_Second);
currentTime = hour + ":" + minute;
Serial.println(currentTime);
daysInMonth=rtcMonthDays(tm_Month, tm_Year);
firstDay=getDayOfWeek(week_day,monthDay); //weekDay
draw();
}
int rtcMonthDays(int month, int year) {
if (month == 2) {
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
return 29; // Prijestupna godina
} else {
return 28; // Nije prijestupna godina
}
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
} else {
return 31;
}
}
int getDayOfWeek(int wd, int day) {
int n=wd;
for(int i=day;i>0;i--)
{n--; if(n<0) n=6;}
return n;
}