Skip to content

Instantly share code, notes, and snippets.

@takeru
Created September 13, 2020 20:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takeru/6c0eaf513f41c3bfdcf9b98e566516c2 to your computer and use it in GitHub Desktop.
Save takeru/6c0eaf513f41c3bfdcf9b98e566516c2 to your computer and use it in GitHub Desktop.
3Dプリントの残り時間カウントダウンタイマー
/**
* 3Dプリンタタイマー
* 1. OctoPrintAPIから残り時間を取得して表示
* 2. deepsleepで電池節約
* 3. プリントが終わったら音と光でお知らせ
*/
#include "time.h"
#include <M5StickC.h>
#include <WiFi.h>
#include <WiFiMulti.h>
#include <ESPmDNS.h>
#include <HTTPClient.h>
#include <ArduinoJson.h> // 6.16.1 https://arduinojson.org/v6/doc/installation/
#include <TimeLib.h> // "Time by Michael Margolis" https://github.com/PaulStoffregen/Time
#define LED_BUILTIN 10
#define LED_IR 9
#define PIN_SPK 26
#define OCTOPRINT_API_KEY "xxxxxx"
#define OCTOPRINT_MDNS_NAME "octopi" // http://octopi.local/... without ".local"
WiFiMulti wifiMulti;
#include "secret.h";
//#define WIFI_MULTI_ADD_APS() \
// wifiMulti.addAP("aaa", "xxx"); \
// wifiMulti.addAP("bbb", "yyy");
IPAddress ipaddr = INADDR_NONE;
unsigned long origin_ms = 0;
String state = "";
float completion = 0.0;
int printTime0 = 0;
int printTimeLeft0 = 0;
TFT_eSprite tftSprite = TFT_eSprite(&M5.Lcd);
void set_led_red(bool on)
{
digitalWrite(LED_BUILTIN, on ? LOW : HIGH);
}
void init_timelib(void)
{
RTC_TimeTypeDef time;
RTC_DateTypeDef date;
M5.Rtc.GetTime(&time);
M5.Rtc.GetData(&date);
setTime(time.Hours, time.Minutes, time.Seconds, date.Date, date.Month, date.Year);
}
String datetime_string(){
time_t t = now();
char s[20];
sprintf(s, "%04d-%02d-%02d_%02d:%02d:%02d", year(t), month(t), day(t), hour(t), minute(t), second(t));
return String(s);
}
bool sync_rtc()
{
configTime(9 * 3600, 0, "ntp.nict.jp"); // JST
// Get local time
struct tm timeInfo;
if (getLocalTime(&timeInfo))
{
// Set RTC time
RTC_TimeTypeDef TimeStruct;
TimeStruct.Hours = timeInfo.tm_hour;
TimeStruct.Minutes = timeInfo.tm_min;
TimeStruct.Seconds = timeInfo.tm_sec;
M5.Rtc.SetTime(&TimeStruct);
RTC_DateTypeDef DateStruct;
DateStruct.WeekDay = timeInfo.tm_wday;
DateStruct.Month = timeInfo.tm_mon + 1;
DateStruct.Date = timeInfo.tm_mday;
DateStruct.Year = timeInfo.tm_year + 1900;
M5.Rtc.SetData(&DateStruct);
return true;
}
else
{
return false;
}
}
String mac_string(const uint8_t *mac)
{
char macStr[18] = {0};
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return String(macStr);
}
String get_printer_job_json() {
HTTPClient http;
String url = "http://";
url += ipaddr.toString();
// url += ":8080"
url += "/api/job?apikey=";
url += OCTOPRINT_API_KEY;
printf("url=%s\n", url.c_str());
http.begin(url);
int code = http.GET();
String jsonString = "";
if (code == HTTP_CODE_OK) {
jsonString = http.getString();
}
http.end();
return jsonString;
}
void deepsleep(long ms) {
WiFi.disconnect();
printf("deepsleep ms=%ld\n", ms);
Serial.flush();
M5.Axp.DeepSleep(ms * 1000);
}
unsigned long millis_from_origin(){
return millis() - origin_ms;
}
bool get_printer_status(bool ntp_sync){
if (wifiMulti.run() == WL_CONNECTED) {
printf("localIP=%s\n", WiFi.localIP().toString().c_str());
if(ntp_sync){
printf("sync_rtc=%d\n", sync_rtc());
}
}
init_timelib();
printf("now=%s\n", datetime_string().c_str());
MDNS.begin("mdns-client");
ipaddr = MDNS.queryHost(OCTOPRINT_MDNS_NAME);
printf("ipaddr=%s\n", ipaddr.toString().c_str());
String jsonString = get_printer_job_json();
WiFi.disconnect();
printf("WiFi.disconnect\n");
if (jsonString == "") {
printf("ERROR: http failed.\n");
return false;
}
printf("jsonString========\n");
jsonString.trim();
printf("%s\n", jsonString.c_str());
printf("========\n");
const size_t capacity = 1000;
DynamicJsonDocument doc(capacity);
DeserializationError error = deserializeJson(doc, jsonString);
if (error) {
printf("ERROR: deserialize failed.\n");
return false;
}
String _state = doc["state"];
state = _state;
completion = doc["progress"]["completion"];
printTime0 = doc["progress"]["printTime"];
printTimeLeft0 = doc["progress"]["printTimeLeft"];
printf("state=%s\n", state.c_str());
printf("completion=%5.2f\n", completion);
printf("printTime=%d\n", printTime0);
printf("printTimeLeft=%d\n", printTimeLeft0);
origin_ms = millis();
//printTimeLeft0 = 100*60+20;
//completion = 98.34;
return true;
}
void setup() {
pinMode(PIN_SPK, OUTPUT);
digitalWrite(PIN_SPK, LOW);
M5.Axp.begin();
M5.Axp.ScreenBreath(0);
M5.Lcd.begin();
M5.Rtc.begin();
M5.Lcd.fillScreen(BLACK);
printf("rotation=%d width=%d height=%d\n", M5.Lcd.getRotation(), M5.Lcd.width(), M5.Lcd.height());
M5.Lcd.setRotation(1);
printf("rotation=%d width=%d height=%d\n", M5.Lcd.getRotation(), M5.Lcd.width(), M5.Lcd.height());
tftSprite.createSprite(M5.Lcd.width(), M5.Lcd.height());
pinMode(LED_BUILTIN, OUTPUT);
pinMode(LED_IR, OUTPUT);
set_led_red(false);
WIFI_MULTI_ADD_APS();
uint8_t mac[6];
WiFi.macAddress(mac);
printf("macAddress=%s\n", mac_string(mac).c_str());
if(!get_printer_status(true)){
for (int i = 0; i < 10; i++) {
set_led_red(true);
delay(100);
set_led_red(false);
delay(400);
}
delay(1000);
deepsleep(60 * 1000);
}
M5.Axp.ScreenBreath(9);
}
void loop() {
bool demo_mode = false;
update_display();
if(printTimeLeft0==0){
set_led_red(true);
delay(100);
set_led_red(false);
delay(100);
if(millis_from_origin()/1000 % 60 == 59){
get_printer_status(false);
}
for(int j=0; j<2; j++){
for(int i=0; i<50; i++){
digitalWrite(PIN_SPK, HIGH);
delayMicroseconds(400);
digitalWrite(PIN_SPK, LOW);
delayMicroseconds(400);
}
delay(100);
}
delay(1000);
}else if(printTimeLeft0 < 3*60 || demo_mode){
if(millis_from_origin()/1000 % 15 == 14){
if(!get_printer_status(false)){
deepsleep(5 * 1000);
}
}
}else if(printTimeLeft0 < 15*60){
if(60*1000 < millis_from_origin()){
deepsleep(1 * 60 * 1000);
}
}else{
if(30*1000 < millis_from_origin()){
deepsleep(5 * 60 * 1000);
}
}
delay(100);
}
void update_display()
{
int printTime = printTime0 + millis_from_origin() / 1000;
int printTimeLeftMs = printTimeLeft0*1000 - millis_from_origin();
if(printTimeLeftMs < 0){
printTimeLeftMs = 0;
}
tftSprite.fillSprite(M5.Lcd.color565(200, 60, 0));
tftSprite.setTextColor(BLACK);
tftSprite.setCursor(5, 10);
tftSprite.setTextFont(7);
tftSprite.setTextSize(1);
int mode = 0;
if(printTimeLeftMs==0){
mode = millis()/1000 / 1 % 2 + 1;
}else if(printTimeLeftMs < 100*60*1000){
mode = millis()/1000 / 5 % 3;
}else{
mode = millis()/1000 / 5 % 2;
}
if(mode==0){
time_t t = now() + printTimeLeftMs / 1000;
tftSprite.printf("%02d:%02d", hour(t), minute(t));
}
if(mode==1){
tftSprite.printf("%2d.%1d", int(completion), int(completion*10)%10);
}
if(mode==2){
if(printTimeLeftMs < 10*60*1000){ // 9:59.9
tftSprite.printf("%1d:%02d.%1d", printTimeLeftMs/1000/60, printTimeLeftMs/1000%60, printTimeLeftMs%1000/100);
}else if(printTimeLeftMs < 100*60*1000){ // 99:59
tftSprite.printf("%02d:%02d%s", printTimeLeftMs/1000/60, printTimeLeftMs/1000%60, (printTimeLeftMs%1000/100)%2==0 ? ".":"");
}
}
tftSprite.pushSprite(0, 0);
}
#define WIFI_MULTI_ADD_APS() \
wifiMulti.addAP("aaa", "xxx"); \
wifiMulti.addAP("bbb", "yyy");
#define OCTOPRINT_API_KEY "zzzzzzzzzz"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment