From 57d517b0d3cef012a9f1034cd023dffef20e5054 Mon Sep 17 00:00:00 2001 From: createskyblue Date: Tue, 25 Aug 2020 12:35:22 +0800 Subject: [PATCH] v1.7 beta 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复动画显示异常 --- img/cskyb.ttf | Bin 0 -> 41328 bytes software/binaries/1.7t2/T12.ino.standard.hex | 1591 ++++++++++++++++ .../T12.ino.with_bootloader.standard.hex | 1624 +++++++++++++++++ ...SolderingStation2_arduboy_gplib_v1.7t2.ino | 1347 ++++++++++++++ 4 files changed, 4562 insertions(+) create mode 100644 img/cskyb.ttf create mode 100644 software/binaries/1.7t2/T12.ino.standard.hex create mode 100644 software/binaries/1.7t2/T12.ino.with_bootloader.standard.hex create mode 100644 software/sources/SolderingStation2_arduboy_gplib_v1.7t2.ino diff --git a/img/cskyb.ttf b/img/cskyb.ttf new file mode 100644 index 0000000000000000000000000000000000000000..05d6454bbef5e8f769ad632a2ccb8f5bb197ded4 GIT binary patch literal 41328 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 iKFFgF{BXd}{r>@7yUS1_WcC370000为了加入欠压报警只能阉割掉关于页面的二维码 +//const unsigned char QRCode[] PROGMEM = { 0x00, 0x00, 0x3e, 0x0e, 0x7c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x0e, 0x7c, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x0e, 0x7c, 0x0c, 0x00, 0x00, 0x1f, 0xfe, 0x3f, 0xc1, 0x8c, 0x0c, 0x7f, 0xf8, 0x1f, 0xfe, 0x3f, 0xc1, 0x8c, 0x0c, 0x7f, 0xf8, 0x18, 0x06, 0x30, 0x01, 0xf3, 0x8c, 0x60, 0x18, 0x18, 0x06, 0x30, 0x01, 0xf3, 0x8c, 0x60, 0x18, 0x18, 0x06, 0x30, 0x01, 0xf3, 0x8c, 0x60, 0x18, 0x18, 0x06, 0x3e, 0x0f, 0xf0, 0x0c, 0x60, 0x18, 0x18, 0x06, 0x3e, 0x0f, 0xf0, 0x0c, 0x60, 0x18, 0x18, 0x06, 0x3f, 0xc1, 0xf0, 0x0c, 0x60, 0x18, 0x18, 0x06, 0x3f, 0xc1, 0xf0, 0x0c, 0x60, 0x18, 0x18, 0x06, 0x3f, 0xc1, 0xf0, 0x0c, 0x60, 0x18, 0x1f, 0xfe, 0x3e, 0x30, 0x70, 0x0c, 0x7f, 0xf8, 0x1f, 0xfe, 0x3e, 0x30, 0x70, 0x0c, 0x7f, 0xf8, 0x00, 0x00, 0x31, 0xce, 0x73, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x31, 0xce, 0x73, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x31, 0xce, 0x73, 0x8c, 0x00, 0x00, 0xff, 0xff, 0xf0, 0x01, 0x83, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x01, 0x83, 0x8f, 0xff, 0xff, 0x00, 0xc0, 0x01, 0xc1, 0x8c, 0x00, 0x7f, 0x1f, 0x00, 0xc0, 0x01, 0xc1, 0x8c, 0x00, 0x7f, 0x1f, 0x00, 0xc0, 0x01, 0xc1, 0x8c, 0x00, 0x7f, 0x1f, 0x07, 0xc7, 0xcf, 0xce, 0x7f, 0x8c, 0x1f, 0xf8, 0x07, 0xc7, 0xcf, 0xce, 0x7f, 0x8c, 0x1f, 0xf8, 0x07, 0xc7, 0xcf, 0xce, 0x7f, 0x8c, 0x1f, 0xf8, 0xf8, 0x00, 0x3e, 0x3e, 0x03, 0xf0, 0x7f, 0x00, 0xf8, 0x00, 0x3e, 0x3e, 0x03, 0xf0, 0x7f, 0x00, 0xe0, 0xc7, 0xcf, 0xfe, 0x03, 0x80, 0x1f, 0xe7, 0xe0, 0xc7, 0xcf, 0xfe, 0x03, 0x80, 0x1f, 0xe7, 0xe0, 0xc7, 0xcf, 0xfe, 0x03, 0x80, 0x1f, 0xe7, 0x18, 0xc0, 0x31, 0xfe, 0x0c, 0x0c, 0x1c, 0xe0, 0x18, 0xc0, 0x31, 0xfe, 0x0c, 0x0c, 0x1c, 0xe0, 0xe7, 0x39, 0xf1, 0xf0, 0x03, 0xfc, 0x7c, 0xf8, 0xe7, 0x39, 0xf1, 0xf0, 0x03, 0xfc, 0x7c, 0xf8, 0xe7, 0x39, 0xf1, 0xf0, 0x03, 0xfc, 0x7c, 0xf8, 0x1f, 0x00, 0x31, 0xcf, 0xf3, 0x8c, 0x03, 0x00, 0x1f, 0x00, 0x31, 0xcf, 0xf3, 0x8c, 0x03, 0x00, 0xe0, 0x3f, 0xff, 0xc1, 0x83, 0x8f, 0x9c, 0xe7, 0xe0, 0x3f, 0xff, 0xc1, 0x83, 0x8f, 0x9c, 0xe7, 0xe0, 0x3f, 0xff, 0xc1, 0x83, 0x8f, 0x9c, 0xe7, 0x18, 0x00, 0x30, 0x0e, 0x00, 0x00, 0x00, 0xff, 0x18, 0x00, 0x30, 0x0e, 0x00, 0x00, 0x00, 0xff, 0x18, 0x00, 0x30, 0x0e, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xf0, 0x3e, 0x7c, 0x0f, 0xe0, 0x00, 0xff, 0xff, 0xf0, 0x3e, 0x7c, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x31, 0xce, 0x0c, 0x0c, 0x63, 0xe0, 0x00, 0x00, 0x31, 0xce, 0x0c, 0x0c, 0x63, 0xe0, 0x00, 0x00, 0x31, 0xce, 0x0c, 0x0c, 0x63, 0xe0, 0x1f, 0xfe, 0x30, 0x01, 0x83, 0x8f, 0xe0, 0xff, 0x1f, 0xfe, 0x30, 0x01, 0x83, 0x8f, 0xe0, 0xff, 0x18, 0x06, 0x31, 0xf1, 0x8f, 0x80, 0x03, 0xe7, 0x18, 0x06, 0x31, 0xf1, 0x8f, 0x80, 0x03, 0xe7, 0x18, 0x06, 0x31, 0xf1, 0x8f, 0x80, 0x03, 0xe7, 0x18, 0x06, 0x3f, 0xff, 0x83, 0x83, 0xe3, 0x1f, 0x18, 0x06, 0x3f, 0xff, 0x83, 0x83, 0xe3, 0x1f, 0x18, 0x06, 0x31, 0xfe, 0x73, 0x8f, 0x80, 0xf8, 0x18, 0x06, 0x31, 0xfe, 0x73, 0x8f, 0x80, 0xf8, 0x18, 0x06, 0x31, 0xfe, 0x73, 0x8f, 0x80, 0xf8, 0x1f, 0xfe, 0x31, 0xfe, 0x00, 0x0c, 0x60, 0xe7, 0x1f, 0xfe, 0x31, 0xfe, 0x00, 0x0c, 0x60, 0xe7, 0x00, 0x00, 0x31, 0xfe, 0x0c, 0x0f, 0x9f, 0xe0, 0x00, 0x00, 0x31, 0xfe, 0x0c, 0x0f, 0x9f, 0xe0, 0x00, 0x00, 0x31, 0xfe, 0x0c, 0x0f, 0x9f, 0xe0 }; +//const unsigned char QRCode[] PROGMEM = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0x86, 0x70, 0x80, 0x03, 0x80, 0x03, 0x86, 0x70, 0x80, 0x03, 0x9f, 0xf3, 0xe1, 0x30, 0x9f, 0xf3, 0x9f, 0xf3, 0xe1, 0x30, 0x9f, 0xf3, 0x98, 0x33, 0x01, 0xcc, 0x98, 0x33, 0x98, 0x33, 0x01, 0xcc, 0x98, 0x33, 0x98, 0x33, 0x87, 0xc0, 0x98, 0x33, 0x98, 0x33, 0xe1, 0xc0, 0x98, 0x33, 0x98, 0x33, 0xe1, 0xc0, 0x98, 0x33, 0x9f, 0xf3, 0x98, 0xc0, 0x9f, 0xf3, 0x9f, 0xf3, 0x98, 0xc0, 0x9f, 0xf3, 0x80, 0x03, 0x66, 0xcc, 0x80, 0x03, 0x80, 0x03, 0x66, 0xcc, 0x80, 0x03, 0xff, 0xff, 0x01, 0x0c, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x1f, 0xff, 0x81, 0x00, 0x61, 0x30, 0x1f, 0x3f, 0x87, 0x3c, 0xe6, 0xfc, 0x87, 0x33, 0x87, 0x3c, 0xe6, 0xfc, 0x87, 0xf3, 0xf8, 0x03, 0x9e, 0x0f, 0x1f, 0x03, 0xf8, 0x03, 0x9e, 0x0f, 0x1f, 0x03, 0xe1, 0x3c, 0xfe, 0x0c, 0x07, 0xcf, 0xe1, 0x3c, 0xfe, 0x0c, 0x07, 0xcf, 0x99, 0x03, 0x3e, 0x30, 0x86, 0xc3, 0xe6, 0xcf, 0x38, 0x0f, 0x9e, 0xf3, 0xe6, 0xcf, 0x38, 0x0f, 0x9e, 0xf3, 0x9e, 0x03, 0x27, 0xcc, 0x81, 0x03, 0x9e, 0x03, 0x27, 0xcc, 0x81, 0x03, 0xe0, 0xff, 0xe1, 0x0c, 0xe6, 0xcf, 0xe0, 0xff, 0xe1, 0x0c, 0xe6, 0xcf, 0x98, 0x03, 0x06, 0x00, 0x00, 0xff, 0x98, 0x03, 0x06, 0x00, 0x00, 0xff, 0xff, 0xff, 0x1e, 0xf0, 0xf8, 0x03, 0x80, 0x03, 0x66, 0x30, 0x99, 0xc3, 0x80, 0x03, 0x66, 0x30, 0x99, 0xc3, 0x9f, 0xf3, 0x01, 0x0c, 0xf8, 0xff, 0x9f, 0xf3, 0x01, 0x0c, 0xf8, 0xff, 0x98, 0x33, 0x39, 0x3c, 0x01, 0xcf, 0x98, 0x33, 0x39, 0x3c, 0x01, 0xcf, 0x98, 0x33, 0xff, 0x0c, 0x79, 0x3f, 0x98, 0x33, 0x3e, 0xcc, 0xe0, 0xf3, 0x98, 0x33, 0x3e, 0xcc, 0xe0, 0xf3, 0x9f, 0xf3, 0x3e, 0x00, 0x98, 0xcf, 0x9f, 0xf3, 0x3e, 0x00, 0x98, 0xcf, 0x80, 0x03, 0x3e, 0x30, 0xe7, 0xc3, 0x80, 0x03, 0x3e, 0x30, 0xe7, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +//ICO +//width:16,height:16 +const unsigned char Tag[] PROGMEM = { 0x00, 0x00, 0x3b, 0xec, 0x7b, 0xee, 0x63, 0xe6, 0x63, 0xe6, 0x63, 0xe6, 0x63, 0xe6, 0x63, 0xe6, 0x63, 0xe6, 0x63, 0x66, 0x62, 0x26, 0x60, 0x06, 0x60, 0x06, 0x7f, 0xfe, 0x3f, 0xfc, 0x00, 0x00 }; +const unsigned char Chip[] PROGMEM = { 0x14, 0xa0, 0x3f, 0xf0, 0x7f, 0xf8, 0xe0, 0x1c, 0x6e, 0x18, 0xec, 0x1c, 0x68, 0x18, 0x60, 0x18, 0xe0, 0x1c, 0x60, 0x58, 0xe0, 0x1c, 0x7f, 0xf8, 0x3f, 0xf0, 0x14, 0xa0 }; +//const unsigned char HeatPipe[] PROGMEM = { 0x00, 0x00, 0x09, 0x90, 0x11, 0x88, 0x21, 0x84, 0x11, 0x88, 0x09, 0x90, 0x11, 0x88, 0x21, 0x84, 0x11, 0x88, 0x09, 0x90, 0x11, 0x88, 0x21, 0x84, 0x11, 0x88, 0x09, 0x90, 0x01, 0x80, 0x00, 0x00 }; +const unsigned char Lightning[] PROGMEM = { 0x0f, 0xe0, 0x1f, 0xc0, 0x1f, 0xc0, 0x3f, 0x80, 0x3f, 0xf8, 0x7f, 0xf0, 0x7f, 0xe0, 0x07, 0xc0, 0x07, 0x80, 0x0f, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0x18, 0x00, 0x10, 0x00 }; +//const unsigned char Thermometer[] PROGMEM = { 0x01, 0x80, 0x02, 0x40, 0x03, 0x40, 0x02, 0x40, 0x03, 0x40, 0x02, 0x40, 0x03, 0x40, 0x02, 0x40, 0x03, 0x40, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x07, 0xe0, 0x07, 0xe0, 0x07, 0xe0, 0x03, 0xc0 }; +const unsigned char Pointer[] PROGMEM = { 0x20, 0x20, 0x70, 0xf8 }; +//状态提示 +//width:14,height:14 图标库 + +const unsigned char c1[] PROGMEM = { 0x03, 0x00, 0x07, 0x80, 0x0f, 0xc0, 0x0c, 0xc0, 0x1c, 0xe0, 0x1c, 0xe0, 0x3c, 0xf0, 0x3c, 0xf0, 0x7f, 0xf8, 0x7f, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xfc, 0x7f, 0xf8 }; +const unsigned char c2[] PROGMEM = { 0x7f, 0xf8, 0xff, 0xfc, 0xc0, 0x0c, 0xc3, 0x0c, 0xcb, 0x4c, 0xdb, 0x6c, 0xdb, 0x6c, 0xd8, 0x6c, 0xdc, 0xec, 0xcf, 0xcc, 0xc7, 0x8c, 0xc0, 0x0c, 0xff, 0xfc, 0x7f, 0xf8 }; +const unsigned char c3[] PROGMEM = { 0x00, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x18, 0xf8, 0x38, 0xf0, 0x30, 0x30, 0x70, 0x60, 0x70, 0x78, 0x78, 0xf8, 0x78, 0x00, 0x3c, 0x02, 0x3f, 0x0c, 0x1f, 0xf8, 0x0f, 0xf0, 0x03, 0xc0, 0x00, 0x00 }; +const unsigned char c5[] PROGMEM = { 0x7f, 0xf0, 0xff, 0xe0, 0xc0, 0x08, 0xc0, 0x1c, 0xc0, 0x38, 0xc8, 0x70, 0xdc, 0xe4, 0xcf, 0xcc, 0xc7, 0x8c, 0xc3, 0x0c, 0xc0, 0x0c, 0xc0, 0x0c, 0xff, 0xfc, 0x7f, 0xf8 }; +const unsigned char c6[] PROGMEM = { 0x1e, 0x10, 0x33, 0x38, 0x2d, 0x7c, 0x25, 0x38, 0x2d, 0x38, 0x25, 0x38, 0x2d, 0x38, 0x6d, 0x80, 0xde, 0xc0, 0xbf, 0x40, 0xbf, 0x40, 0xde, 0xc0, 0x61, 0x80, 0x3f, 0x00 }; +const unsigned char c7[] PROGMEM = { 0x1f, 0xe0, 0x3f, 0xf0, 0x70, 0x38, 0x60, 0x18, 0x60, 0x18, 0x60, 0x18, 0xff, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, 0x7c, 0xf8, 0x7c, 0xfc, 0xfc, 0x7f, 0xf8 }; +const unsigned char c_NO[] PROGMEM = { 0x80, 0x04, 0x00, 0x00, 0x3f, 0xf0, 0x37, 0xb0, 0x23, 0x10, 0x30, 0x30, 0x38, 0x70, 0x38, 0x70, 0x30, 0x30, 0x23, 0x10, 0x37, 0xb0, 0x3f, 0xf0, 0x00, 0x00, 0x80, 0x04 }; +const unsigned char *C_table[] = {c1, c2, c3, Lightning, c5, c6, c7}; + +//设置(陈星汉认为语言是一种低像素的表达方式,容易造成隔阂; 交互界面设计尽可能形象化) +// width: 48, height: 48 + +const unsigned char Set0[] PROGMEM = { 0x88,0x24,0x08,0x20,0x38,0x30,0x38,0x30,0x38,0x30,0x38,0x30,0x38,0x30,0x38,0x30,0x39,0x30,0x3b,0xb0,0x3f,0xf0,0x3f,0xf0,0x00,0x00,0x80,0x04 }; +const unsigned char Set1[] PROGMEM = { 0xf8,0x7c,0xf3,0x3c,0xf4,0xbc,0xf6,0xbc,0xf4,0xbc,0xf6,0xbc,0xf4,0xbc,0xe4,0x9c,0xc8,0x4c,0xd0,0x2c,0xd0,0x2c,0xc8,0x4c,0xe7,0x9c,0xf0,0x3c }; +const unsigned char Set2[] PROGMEM = { 0x8f, 0xc4, 0x10, 0x20, 0x20, 0x10, 0x4c, 0xc8, 0x9f, 0xe4, 0x3d, 0xf0, 0x3d, 0xf0, 0x1d, 0xe0, 0x3e, 0xf0, 0x3f, 0x70, 0x9f, 0xe4, 0x8c, 0xc4, 0x00, 0x00, 0x30, 0x30 }; +const unsigned char Set3[] PROGMEM = { 0xc3, 0xfc, 0x18, 0x00, 0x18, 0x00, 0xc3, 0xfc, 0xff, 0xfc, 0xff, 0x0c, 0x00, 0x60, 0x00, 0x60, 0xff, 0x0c, 0xff, 0xfc, 0xf0, 0xfc, 0x06, 0x00, 0x06, 0x00, 0xf0, 0xfc }; +const unsigned char Set4[] PROGMEM = { 0x80, 0x04, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x10, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04 }; +const unsigned char Set4F[] PROGMEM = { 0x80, 0x04, 0x00, 0x00, 0x3f, 0xf0, 0x38, 0x30, 0x33, 0x10, 0x3f, 0x90, 0x38, 0x10, 0x33, 0x90, 0x27, 0x90, 0x26, 0x10, 0x30, 0x90, 0x3f, 0xf0, 0x00, 0x00, 0x80, 0x04 }; +const unsigned char Set4FF[] PROGMEM = { 0x80, 0x04, 0x00, 0x00, 0x3f, 0xf0, 0x24, 0x30, 0x21, 0x90, 0x27, 0x90, 0x27, 0x30, 0x20, 0x70, 0x27, 0xf0, 0x23, 0x30, 0x30, 0x70, 0x3f, 0xf0, 0x00, 0x00, 0x80, 0x04 }; +const unsigned char Set5[] PROGMEM = { 0xfc, 0xfc, 0xf8, 0x7c, 0xe0, 0x1c, 0xc0, 0x0c, 0xc0, 0x0c, 0xc0, 0x0c, 0xc0, 0x0c, 0xc0, 0x0c, 0xc0, 0x0c, 0x80, 0x04, 0x80, 0x04, 0xff, 0xfc, 0xf8, 0x7c, 0xfc, 0xfc }; +const unsigned char Set5_1[] PROGMEM = { 0xfc, 0xf4, 0xf8, 0x60, 0xe0, 0x44, 0xc0, 0x8c, 0xc1, 0x1c, 0xc2, 0x2c, 0xc4, 0x4c, 0xc8, 0x8c, 0xd1, 0x0c, 0xa2, 0x04, 0xc4, 0x04, 0x8f, 0xfc, 0x18, 0x7c, 0xbc, 0xfc }; +const unsigned char Set6[] PROGMEM = { 0xf8, 0x7c, 0xe0, 0x1c, 0xc0, 0x0c, 0xcf, 0xcc, 0xcf, 0xcc, 0xcf, 0xcc, 0xcf, 0xcc, 0xcf, 0xcc, 0xcf, 0xcc, 0xcf, 0xcc, 0xc8, 0x4c, 0xcf, 0xcc, 0xc0, 0x0c, 0xe0, 0x1c }; +const unsigned char Set_LANG[] PROGMEM = { 0xf0, 0x3c, 0xce, 0x4c, 0xbc, 0x34, 0xb8, 0x14, 0x18, 0x80, 0x10, 0x80, 0x42, 0x30, 0x60, 0x78, 0x60, 0xf8, 0x44, 0xc0, 0x80, 0x04, 0xb8, 0x84, 0xcf, 0xcc, 0xf0, 0x3c }; +const unsigned char Set7[] PROGMEM = { 0x80, 0x0c, 0x00, 0x1c, 0x3f, 0xf4, 0x3f, 0xe0, 0x3f, 0xc4, 0x37, 0x8c, 0x23, 0x18, 0x30, 0x30, 0x38, 0x70, 0x3c, 0xf0, 0x3f, 0xf0, 0x3f, 0xf0, 0x00, 0x00, 0x80, 0x04 }; +const unsigned char Set11[] PROGMEM = { 0xf3, 0xfc, 0xe7, 0xfc, 0xce, 0x0c, 0x8e, 0x1c, 0x9f, 0x9c, 0x1f, 0x3c, 0x1f, 0x0c, 0x0e, 0x0c, 0x0f, 0xfc, 0x87, 0xf8, 0x81, 0xe4, 0xc0, 0x0c, 0xe0, 0x1c, 0xf8, 0x7c }; +const unsigned char Set8[] PROGMEM = { 0x81, 0xdc, 0x55, 0x9c, 0x29, 0x04, 0x55, 0x00, 0x29, 0x90, 0x55, 0xd0, 0x03, 0xfc, 0xff, 0x00, 0x2e, 0x00, 0x26, 0x70, 0x02, 0x50, 0x82, 0x70, 0xe6, 0x00, 0xee, 0x04 }; +const unsigned char Set9[] PROGMEM = { 0xf0, 0x3c, 0xce, 0x0c, 0xbf, 0x04, 0xb3, 0x04, 0x73, 0x00, 0x7f, 0x00, 0x7e, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x7c, 0x60, 0xbc, 0x64, 0xbe, 0x04, 0xcf, 0x0c, 0xf0, 0x3c }; +const unsigned char Set10[] PROGMEM = { 0xf8, 0x7c, 0xf7, 0xbc, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x00, 0xbf, 0xf4, 0xab, 0x54, 0xab, 0x54, 0xab, 0x54, 0xab, 0x54, 0xab, 0x54, 0xab, 0x54, 0xbf, 0xf4, 0xc0, 0x0c }; +const unsigned char Set13[] PROGMEM = { 0x80, 0x04, 0x00, 0x00, 0x3f, 0xf0, 0x3c, 0xf0, 0x34, 0xb0, 0x24, 0x90, 0x24, 0x90, 0x27, 0x90, 0x23, 0x10, 0x30, 0x30, 0x38, 0x70, 0x3f, 0xf0, 0x00, 0x00, 0x80, 0x04 }; +const unsigned char Set12[] PROGMEM = { 0x80, 0x04, 0x00, 0x00, 0x3f, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x20, 0x10, 0x20, 0x10, 0x3c, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x3f, 0xf0, 0x00, 0x00, 0x80, 0x04 }; +const unsigned char Set14[] PROGMEM = { 0xff, 0x7c, 0xfe, 0x7c, 0xfc, 0xec, 0xe8, 0xdc, 0xc8, 0x4c, 0x98, 0x4c, 0x88, 0x24, 0x08, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x04, 0xe0, 0x1c }; +const unsigned char Set15[] PROGMEM = { 0x15, 0x54, 0x3f, 0xfc, 0x15, 0x54, 0x3f, 0xfc, 0x15, 0x54, 0x3c, 0x04, 0x14, 0x04, 0x3c, 0xfc, 0x14, 0x54, 0x3c, 0xfc, 0x00, 0x54, 0x00, 0xa8, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char Set16[] PROGMEM = { 0x15, 0x54, 0x3f, 0xf8, 0x15, 0x50, 0x3f, 0xf0, 0x15, 0x50, 0x38, 0x70, 0x10, 0x20, 0x31, 0x04, 0x13, 0x8c, 0x22, 0xa8, 0x17, 0xfc, 0x2a, 0xa8, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char Set17[] PROGMEM = { 0x80, 0x00, 0xbf, 0xf8, 0x1f, 0xf8, 0xb0, 0x08, 0x18, 0x08, 0xb9, 0xe8, 0x19, 0xb8, 0xb8, 0x38, 0x18, 0x38, 0xb9, 0xb8, 0xb9, 0xf8, 0xb0, 0xf8, 0xbf, 0xf8, 0x80, 0x00 }; +const unsigned char Set18[] PROGMEM = { 0x80, 0x00, 0xbf, 0xf8, 0x1f, 0xf8, 0xb0, 0x28, 0x1f, 0xf8, 0xb4, 0x08, 0x1f, 0xf8, 0xb1, 0x08, 0x1f, 0xf8, 0xb0, 0x48, 0xbf, 0xf8, 0xb2, 0x88, 0xbf, 0xf8, 0x80, 0x00 }; +const unsigned char Lang_CN[] PROGMEM = { 0x80, 0x04, 0x00, 0x00, 0x3f, 0xf0, 0x3c, 0xf0, 0x3c, 0xf0, 0x20, 0x10, 0x24, 0x90, 0x24, 0x90, 0x20, 0x10, 0x3c, 0xf0, 0x3c, 0xf0, 0x3f, 0xf0, 0x00, 0x00, 0x80, 0x04 }; +const unsigned char Lang_EN[] PROGMEM = { 0x80, 0x04, 0x00, 0x00, 0x3f, 0xf0, 0x38, 0x70, 0x30, 0x30, 0x23, 0x10, 0x27, 0x90, 0x20, 0x10, 0x20, 0x10, 0x27, 0x90, 0x27, 0x90, 0x3f, 0xf0, 0x00, 0x00, 0x80, 0x04 }; +const unsigned char Save[] PROGMEM = { 0x00, 0x04, 0x58, 0x08, 0x58, 0x08, 0x58, 0x08, 0x40, 0x08, 0x7f, 0xf8, 0x60, 0x18, 0x5f, 0xe8, 0x5b, 0x68, 0x5f, 0xe8, 0x5b, 0x68, 0x1c, 0xe8, 0x5f, 0xe8, 0x00, 0x00 }; +const unsigned char *Ico_table[] = { + Set0, Set1, Set2, Set3, Set4, Set5, Set6, Set_LANG, Set7, + Set8, Set9, Set0, Set10, Set12, Save, + Set0, Set11, Set14, Save, + Set11, Set13, Set14, Save, + Set15, Set16, + Set17, Set18, //5 + Set5_1, Set5, + c_NO, Set7, + Lang_CN, Lang_EN, //8 + Set4F, Set4FF, + Set4, Set4F, Save, +}; +const byte Menu_table[] = {9, 6, 4, 4, 2, 2, 2, 2, 2, 2, 3}; //菜单 标签 温控 定时 控制方式 首页 蜂鸣器 标签删除确认界面 语言菜单 翻转 显示 +byte MenuLevel = 0; //菜单层级 + +/*//////////////////////////////////////////////////////////////////////////////////////////////////// + 多语言支持 + Multilingual support + /////////////////////////////////////////////////////////////////////////////////////////////////// +*/ +/* + 英语库 ENGLISH +*/ +const char EN_0[] PROGMEM = "Tip"; +const char EN_1[] PROGMEM = "Temp"; +const char EN_2[] PROGMEM = "Timer"; +const char EN_3[] PROGMEM = "Control"; +const char EN_4[] PROGMEM = "Screen"; +const char EN_5[] PROGMEM = "Buzzer"; +const char EN_6[] PROGMEM = "LOW Vol"; +const char EN_7[] PROGMEM = "Lang"; +const char EN_8[] PROGMEM = "Return"; +const char EN_9[] PROGMEM = "Change"; +const char EN_10[] PROGMEM = "Calibrate"; +const char EN_11[] PROGMEM = "Rename"; +const char EN_12[] PROGMEM = "Delete"; +const char EN_13[] PROGMEM = "Add"; +const char EN_14[] PROGMEM = "Save"; +const char EN_15[] PROGMEM = "Default"; +const char EN_16[] PROGMEM = "Sleep"; +const char EN_17[] PROGMEM = "Boost"; +const char EN_18[] PROGMEM = "Save"; +const char EN_19[] PROGMEM = "Sleep"; +const char EN_20[] PROGMEM = "Off"; +const char EN_21[] PROGMEM = "Boost"; +const char EN_22[] PROGMEM = "Save"; +const char EN_23[] PROGMEM = "Direct"; +const char EN_24[] PROGMEM = "PID"; +const char EN_25[] PROGMEM = "Big"; +const char EN_26[] PROGMEM = "Infos"; +const char EN_27[] PROGMEM = "OFF"; +const char EN_28[] PROGMEM = "ON"; +const char EN_29[] PROGMEM = "NO"; +const char EN_30[] PROGMEM = "YES"; +const char EN_31[] PROGMEM = "CN"; +const char EN_32[] PROGMEM = "EN"; +const char EN_33[] PROGMEM = "NO"; +const char EN_34[] PROGMEM = "OK"; +const char EN_35[] PROGMEM = "Main Screen"; +const char EN_36[] PROGMEM = "Flip"; +const char EN_37[] PROGMEM = "Save"; +const char *const EN_table[] PROGMEM = {EN_0, EN_1, EN_2, EN_3, EN_4, EN_5, EN_6, EN_7, EN_8, EN_9, EN_10, EN_11, EN_12, EN_13, EN_14, EN_15, EN_16, EN_17, EN_18, EN_19, EN_20, EN_21, EN_22, EN_23, EN_24, EN_25, EN_26, EN_27, EN_28, EN_29, EN_30, EN_31, EN_32, EN_33, EN_34, EN_35, EN_36, EN_37,}; +/* + #!/usr/bin/python + # -*- coding: UTF-8 -*- + for num in range(0,38): + print("EN_",end="") + print(num,end='') + print(",",end="") +*/ +/* + 中文语言库 CHINESE + + //////////////////////////////////////////////////////////////////////////////////////////////////////// + 本地化提示:你可以按照位图的大小,把这里的文字位图替换成你的语言,确保位图分辨率一致即可,我们欢迎你把程序翻译为你当地的语言! + Localization tips: you can according to the size of the bitmap, + replace the text bitmap here with your language, + ensure that the bitmap resolution is consistent, + we welcome you to translate the program into your local language! + //////////////////////////////////////////////////////////////////////////////////////////////////////// +*/ +//width:28,height:14 主界面中文提示 +//Main Screen +//错误-ERROR +const unsigned char S1[] PROGMEM = { 0x20, 0x92, 0x1f, 0xc0, 0x3d, 0xf9, 0x90, 0x40, 0x20, 0x90, 0x90, 0x40, 0x40, 0x90, 0x1f, 0xc0, 0x7b, 0xff, 0x00, 0x00, 0xa0, 0x01, 0x3f, 0xe0, 0x21, 0xf9, 0x02, 0x00, 0xfd, 0x09, 0x02, 0x00, 0x21, 0x09, 0x7f, 0xf0, 0x21, 0xf9, 0x05, 0x00, 0x21, 0x09, 0x45, 0x00, 0x29, 0x09, 0x88, 0x80, 0x31, 0xf9, 0x10, 0x70, 0x21, 0x08, 0x20, 0x20 }; +//关机-OFF +const unsigned char S2[] PROGMEM = { 0x10, 0x40, 0x47, 0xc0, 0x17, 0xfc, 0x44, 0x40, 0x20, 0x03, 0xf4, 0x40, 0x23, 0xf8, 0x44, 0x40, 0x62, 0x08, 0xc4, 0x40, 0xa3, 0xf8, 0xe4, 0x40, 0x20, 0x01, 0x54, 0x40, 0x2f, 0xfd, 0x44, 0x40, 0x28, 0x06, 0x44, 0x40, 0x23, 0xf8, 0x44, 0x40, 0x20, 0x40, 0x44, 0x50, 0x20, 0x40, 0x48, 0x50, 0x21, 0x40, 0x50, 0x30, 0x20, 0x80, 0x40, 0x00 }; +//休眠-SLEEP +const unsigned char S3[] PROGMEM = { 0x10, 0x83, 0xdf, 0xc0, 0x10, 0x82, 0x50, 0x40, 0x20, 0x82, 0x50, 0x40, 0x2f, 0xff, 0xdf, 0xc0, 0x60, 0x82, 0x52, 0x00, 0x61, 0xc2, 0x52, 0x00, 0xa1, 0xc2, 0x5f, 0xe0, 0x22, 0xa3, 0xd2, 0x00, 0x22, 0xa2, 0x51, 0x00, 0x24, 0x92, 0x51, 0x00, 0x28, 0x8e, 0x50, 0x90, 0x30, 0x8b, 0xd4, 0x50, 0x20, 0x82, 0x58, 0x30, 0x20, 0x80, 0x10, 0x10 }; +//提温-BOOST +const unsigned char S4[] PROGMEM = { 0x23, 0xf2, 0x1f, 0xc0, 0x22, 0x11, 0x10, 0x40, 0xfb, 0xf0, 0x90, 0x40, 0x22, 0x12, 0x1f, 0xc0, 0x2a, 0x11, 0x10, 0x40, 0x33, 0xf1, 0x10, 0x40, 0x60, 0x00, 0x5f, 0xc0, 0xaf, 0xfc, 0x80, 0x00, 0x20, 0x41, 0x3f, 0xe0, 0x22, 0x43, 0x25, 0x20, 0x22, 0x79, 0x25, 0x20, 0x22, 0x41, 0x25, 0x20, 0xa5, 0x41, 0x25, 0x20, 0x48, 0xfd, 0x7f, 0xf0 }; +//正常工作-WORKY +const unsigned char S5[] PROGMEM = { 0x7f, 0xf8, 0x48, 0x80, 0x02, 0x00, 0x49, 0x00, 0x02, 0x01, 0xff, 0xf0, 0x02, 0x01, 0x00, 0x10, 0x02, 0x02, 0x7f, 0x20, 0x22, 0x00, 0x41, 0x00, 0x23, 0xf0, 0x7f, 0x00, 0x22, 0x00, 0x08, 0x00, 0x22, 0x00, 0xff, 0x80, 0x22, 0x00, 0x88, 0x80, 0x22, 0x00, 0x88, 0x80, 0x22, 0x00, 0x8a, 0x80, 0x22, 0x00, 0x89, 0x00, 0xff, 0xfc, 0x08, 0x00 }; +//加热-HEAT +const unsigned char S6[] PROGMEM = { 0x0f, 0x42, 0x1f, 0xc0, 0x78, 0x41, 0x10, 0x40, 0x08, 0x40, 0x90, 0x40, 0x08, 0x42, 0x1f, 0xc0, 0x08, 0x41, 0x10, 0x40, 0xff, 0xfd, 0x10, 0x40, 0x08, 0x40, 0x5f, 0xc0, 0x08, 0x40, 0x80, 0x00, 0x08, 0x41, 0x3f, 0xe0, 0x08, 0x43, 0x25, 0x20, 0x10, 0x41, 0x25, 0x20, 0x10, 0x41, 0x25, 0x20, 0x20, 0x41, 0x25, 0x20, 0x40, 0x41, 0x7f, 0xf0 }; +//维持-HOLD +const unsigned char S7[] PROGMEM = { 0x11, 0x40, 0x82, 0x00, 0x21, 0x20, 0x8f, 0xe0, 0x23, 0xfc, 0x82, 0x00, 0x4a, 0x23, 0xe2, 0x00, 0xfe, 0x20, 0x9f, 0xf0, 0x13, 0xf8, 0x80, 0x80, 0x22, 0x20, 0xc0, 0x80, 0x42, 0x21, 0xbf, 0xf0, 0xfb, 0xfa, 0x88, 0x80, 0x02, 0x20, 0x84, 0x80, 0x02, 0x20, 0x84, 0x80, 0x1a, 0x20, 0x80, 0x80, 0xe3, 0xfe, 0x82, 0x80, 0x02, 0x01, 0x01, 0x00 }; +const unsigned char *S_table[] = {S1, S2, S3, S4, S5, S6, S7}; + +// 菜单 width:36,height:16 +//MENU Oj +/* + The order here(↓) can refer to EN_table(↑↑↑) +*/ +const unsigned char t0[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x7f, 0x90, 0xf8, 0x00, 0x01, 0x08, 0x08, 0x88, 0x00, 0x0a, 0x10, 0x08, 0x88, 0x00, 0x04, 0x7f, 0x01, 0x07, 0x00, 0x1f, 0xc1, 0x3a, 0x00, 0x00, 0x05, 0x49, 0x09, 0xfc, 0x00, 0x04, 0x49, 0x08, 0x84, 0x00, 0x04, 0x49, 0x08, 0x88, 0x00, 0x04, 0x49, 0x08, 0x48, 0x00, 0x04, 0x49, 0x08, 0x50, 0x00, 0x04, 0x49, 0x0a, 0x20, 0x00, 0x04, 0x16, 0x0c, 0x58, 0x00, 0x14, 0x21, 0x89, 0x87, 0x00, 0x08, 0xc0, 0x86, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t1[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xfe, 0x08, 0x20, 0x00, 0x08, 0x82, 0x0b, 0xff, 0x00, 0x04, 0x82, 0x0a, 0x01, 0x00, 0x10, 0xfe, 0x3c, 0x51, 0x00, 0x08, 0x82, 0x08, 0x88, 0x00, 0x08, 0x82, 0x09, 0x04, 0x00, 0x02, 0xfe, 0x0c, 0x00, 0x00, 0x04, 0x00, 0x19, 0xfc, 0x00, 0x09, 0xff, 0x28, 0x20, 0x00, 0x19, 0x29, 0x08, 0x20, 0x00, 0x09, 0x29, 0x08, 0x20, 0x00, 0x09, 0x29, 0x08, 0x20, 0x00, 0x09, 0x29, 0x2b, 0xff, 0x00, 0x0b, 0xff, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t2[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3e, 0x04, 0x00, 0x1f, 0xff, 0xa2, 0x04, 0x00, 0x10, 0x00, 0xa2, 0xff, 0x00, 0x00, 0x01, 0x22, 0x04, 0x00, 0x0f, 0xfe, 0x22, 0x04, 0x00, 0x00, 0x40, 0x3e, 0x44, 0x00, 0x00, 0x40, 0x22, 0x24, 0x00, 0x04, 0x40, 0x22, 0x24, 0x00, 0x04, 0x7c, 0x22, 0x04, 0x00, 0x04, 0x40, 0x22, 0x04, 0x00, 0x0a, 0x40, 0x3e, 0x04, 0x00, 0x09, 0x40, 0x22, 0x24, 0x00, 0x10, 0xff, 0x80, 0x14, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00 }; +const unsigned char t3[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x12, 0x02, 0x00, 0x05, 0xff, 0x9f, 0xd2, 0x00, 0x05, 0x00, 0x92, 0x12, 0x00, 0x1e, 0x28, 0xa2, 0x12, 0x00, 0x04, 0x44, 0x3f, 0xf2, 0x00, 0x04, 0x82, 0x02, 0x12, 0x00, 0x06, 0x00, 0x02, 0x12, 0x00, 0x0c, 0xfe, 0x1f, 0xd2, 0x00, 0x14, 0x10, 0x12, 0x52, 0x00, 0x04, 0x10, 0x12, 0x42, 0x00, 0x04, 0x10, 0x13, 0x42, 0x00, 0x04, 0x10, 0x12, 0x82, 0x00, 0x15, 0xff, 0x82, 0x0a, 0x00, 0x08, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t4[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x0f, 0xf8, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x04, 0x02, 0x3f, 0xfe, 0x00, 0x04, 0x02, 0x00, 0x80, 0x00, 0x07, 0xfe, 0x00, 0x80, 0x00, 0x00, 0x90, 0x04, 0x90, 0x00, 0x08, 0x91, 0x0c, 0x88, 0x00, 0x06, 0x93, 0x10, 0x86, 0x00, 0x02, 0x94, 0x20, 0x82, 0x00, 0x00, 0x90, 0x00, 0x80, 0x00, 0x00, 0x90, 0x02, 0x80, 0x00, 0x1f, 0xff, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t5[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x80, 0x00, 0x1f, 0xff, 0x9f, 0xfc, 0x00, 0x00, 0x40, 0x04, 0x10, 0x00, 0x0f, 0xff, 0x02, 0x20, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x0f, 0xfe, 0x00, 0x00, 0x00, 0x08, 0x42, 0x0f, 0xf8, 0x00, 0x08, 0x42, 0x08, 0x08, 0x00, 0x0f, 0xfe, 0x08, 0x08, 0x00, 0x08, 0x02, 0x0f, 0xf8, 0x00, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, 0x00, 0x0f, 0xf8, 0x00, 0x10, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t6[] PROGMEM = { 0x09, 0xff, 0x00, 0x40, 0x00, 0x04, 0x20, 0x3f, 0xff, 0x00, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x1c, 0x42, 0x0f, 0xfc, 0x00, 0x04, 0x42, 0x00, 0x00, 0x00, 0x07, 0xff, 0x80, 0x00, 0x00, 0x04, 0x00, 0x0f, 0xfc, 0x00, 0x04, 0xff, 0x00, 0x00, 0x00, 0x04, 0x81, 0x00, 0x00, 0x00, 0x05, 0x81, 0x0f, 0xfc, 0x00, 0x06, 0x81, 0x08, 0x04, 0x00, 0x04, 0xff, 0x08, 0x04, 0x00, 0x00, 0x81, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +const unsigned char t7[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0xfe, 0x00, 0x01, 0x00, 0x08, 0x20, 0x00, 0x03, 0xff, 0x08, 0x20, 0x00, 0x02, 0x01, 0x08, 0x20, 0x00, 0x04, 0x22, 0x08, 0x20, 0x00, 0x08, 0x20, 0x0b, 0xfe, 0x00, 0x10, 0x20, 0x08, 0x20, 0x00, 0x00, 0x50, 0x08, 0x28, 0x00, 0x00, 0x50, 0x08, 0x24, 0x00, 0x00, 0x88, 0x08, 0x22, 0x00, 0x00, 0x88, 0x10, 0x20, 0x00, 0x01, 0x04, 0x10, 0x20, 0x00, 0x02, 0x03, 0xa7, 0xff, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char Back[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x07, 0x00, 0x00, 0x00, 0x08, 0xf8, 0x3f, 0xfe, 0x00, 0x04, 0x80, 0x20, 0x02, 0x00, 0x00, 0x80, 0x20, 0x02, 0x00, 0x00, 0xbe, 0x23, 0xe2, 0x00, 0x1c, 0x82, 0x22, 0x22, 0x00, 0x04, 0xa4, 0x22, 0x22, 0x00, 0x04, 0x94, 0x22, 0x22, 0x00, 0x04, 0x88, 0x22, 0x22, 0x00, 0x04, 0x94, 0x23, 0xe2, 0x00, 0x05, 0x22, 0x20, 0x02, 0x00, 0x05, 0x42, 0x20, 0x02, 0x00, 0x0a, 0x00, 0x3f, 0xfe, 0x00, 0x11, 0xff, 0xa0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +const unsigned char t1_1[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x20, 0x90, 0x00, 0x02, 0x7f, 0x98, 0x90, 0x00, 0x1f, 0x80, 0x09, 0xff, 0x00, 0x02, 0x22, 0x01, 0x10, 0x00, 0x06, 0x21, 0x8b, 0x10, 0x00, 0x07, 0x62, 0x8d, 0xfe, 0x00, 0x0a, 0xa2, 0x09, 0x10, 0x00, 0x0a, 0x14, 0x11, 0x10, 0x00, 0x12, 0x14, 0x31, 0xfe, 0x00, 0x02, 0x08, 0x11, 0x10, 0x00, 0x02, 0x14, 0x11, 0x10, 0x00, 0x02, 0x22, 0x11, 0x10, 0x00, 0x02, 0x43, 0x91, 0xff, 0x00, 0x02, 0x81, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t1_2[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x80, 0x00, 0x00, 0x50, 0x01, 0xfc, 0x00, 0x00, 0x88, 0x01, 0x04, 0x00, 0x01, 0x04, 0x03, 0x08, 0x00, 0x06, 0xfb, 0x04, 0x90, 0x00, 0x08, 0x00, 0xc0, 0x60, 0x00, 0x07, 0xdf, 0x01, 0x80, 0x00, 0x04, 0x51, 0x06, 0x00, 0x00, 0x04, 0x51, 0x1b, 0xfe, 0x00, 0x04, 0x51, 0x02, 0x02, 0x00, 0x07, 0xd9, 0x02, 0x02, 0x00, 0x04, 0x56, 0x02, 0x02, 0x00, 0x00, 0x10, 0x03, 0xfe, 0x00, 0x00, 0x10, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t1_3[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x78, 0xbc, 0x20, 0x00, 0x09, 0x48, 0xa4, 0x50, 0x00, 0x09, 0x4a, 0xa8, 0x50, 0x00, 0x09, 0x4a, 0xa8, 0x88, 0x00, 0x09, 0x4a, 0xb1, 0x04, 0x00, 0x1f, 0xfe, 0xaa, 0xfb, 0x00, 0x09, 0x4a, 0xa4, 0x20, 0x00, 0x09, 0x4a, 0xa4, 0x20, 0x00, 0x09, 0x4a, 0xa7, 0xfe, 0x00, 0x09, 0x4a, 0xb4, 0x20, 0x00, 0x09, 0x48, 0xa9, 0x24, 0x00, 0x0b, 0x48, 0xa2, 0x22, 0x00, 0x08, 0x8a, 0xa4, 0xa2, 0x00, 0x11, 0x19, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t1_4[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x03, 0x00, 0x10, 0x00, 0x1f, 0xdc, 0x3e, 0xfe, 0x00, 0x08, 0x90, 0x02, 0x12, 0x00, 0x05, 0x10, 0x04, 0xff, 0x00, 0x1f, 0xdf, 0x84, 0x12, 0x00, 0x02, 0x12, 0x0c, 0xfe, 0x00, 0x1f, 0xd2, 0x02, 0x10, 0x00, 0x02, 0x12, 0x22, 0xfe, 0x00, 0x0a, 0x92, 0x14, 0x10, 0x00, 0x0a, 0x52, 0x14, 0x10, 0x00, 0x12, 0x22, 0x0d, 0xff, 0x00, 0x02, 0x22, 0x08, 0x10, 0x00, 0x0a, 0x42, 0x14, 0x10, 0x00, 0x04, 0x02, 0x23, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +//默认 +const unsigned char t2_0[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc8, 0x10, 0x20, 0x00, 0x12, 0x4a, 0x0c, 0x20, 0x00, 0x1a, 0xc9, 0x04, 0x20, 0x00, 0x17, 0x48, 0x00, 0x20, 0x00, 0x1f, 0xff, 0xb8, 0x20, 0x00, 0x02, 0x08, 0x08, 0x50, 0x00, 0x1f, 0xc8, 0x08, 0x50, 0x00, 0x02, 0x08, 0x08, 0x50, 0x00, 0x03, 0xc8, 0x08, 0x48, 0x00, 0x1e, 0x14, 0x08, 0x88, 0x00, 0x01, 0x54, 0x0a, 0x88, 0x00, 0x15, 0x22, 0x0c, 0x84, 0x00, 0x14, 0x43, 0x89, 0x07, 0x00, 0x00, 0x81, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +//休眠 +const unsigned char t2_1[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x3d, 0xfc, 0x00, 0x02, 0x10, 0x25, 0x04, 0x00, 0x04, 0x10, 0x25, 0x04, 0x00, 0x05, 0xff, 0xbd, 0xfc, 0x00, 0x0c, 0x10, 0x25, 0x20, 0x00, 0x0c, 0x38, 0x25, 0x20, 0x00, 0x14, 0x38, 0x25, 0xfe, 0x00, 0x04, 0x54, 0x3d, 0x20, 0x00, 0x04, 0x54, 0x25, 0x10, 0x00, 0x04, 0x92, 0x25, 0x10, 0x00, 0x05, 0x11, 0xa5, 0x09, 0x00, 0x06, 0x11, 0x3d, 0x45, 0x00, 0x04, 0x10, 0x25, 0x83, 0x00, 0x04, 0x10, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +//提温 +const unsigned char t2_2[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x7e, 0x21, 0xfc, 0x00, 0x04, 0x42, 0x11, 0x04, 0x00, 0x1f, 0x7e, 0x09, 0x04, 0x00, 0x04, 0x42, 0x21, 0xfc, 0x00, 0x05, 0x42, 0x11, 0x04, 0x00, 0x06, 0x7e, 0x11, 0x04, 0x00, 0x0c, 0x00, 0x05, 0xfc, 0x00, 0x15, 0xff, 0x88, 0x00, 0x00, 0x04, 0x08, 0x13, 0xfe, 0x00, 0x04, 0x48, 0x32, 0x52, 0x00, 0x04, 0x4f, 0x12, 0x52, 0x00, 0x04, 0x48, 0x12, 0x52, 0x00, 0x14, 0xa8, 0x12, 0x52, 0x00, 0x09, 0x1f, 0x97, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +//关机 +const unsigned char t3_1[] PROGMEM = { 0x01, 0x04, 0x04, 0x7c, 0x00, 0x00, 0x88, 0x04, 0x44, 0x00, 0x0f, 0xff, 0x3f, 0x44, 0x00, 0x00, 0x20, 0x04, 0x44, 0x00, 0x00, 0x20, 0x0c, 0x44, 0x00, 0x00, 0x20, 0x0e, 0x44, 0x00, 0x1f, 0xff, 0x95, 0x44, 0x00, 0x00, 0x20, 0x14, 0x44, 0x00, 0x00, 0x50, 0x24, 0x44, 0x00, 0x00, 0x50, 0x04, 0x44, 0x00, 0x00, 0x88, 0x04, 0x45, 0x00, 0x01, 0x04, 0x04, 0x85, 0x00, 0x06, 0x03, 0x85, 0x03, 0x00, 0x18, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +const unsigned char t_4[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x20, 0x00, 0x0f, 0xff, 0x09, 0xfc, 0x00, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, 0x20, 0x3e, 0x88, 0x00, 0x03, 0xfe, 0x08, 0x50, 0x00, 0x02, 0x02, 0x0b, 0xfe, 0x00, 0x03, 0xfe, 0x0c, 0x40, 0x00, 0x02, 0x02, 0x18, 0x40, 0x00, 0x03, 0xfe, 0x2b, 0xfe, 0x00, 0x02, 0x02, 0x08, 0x48, 0x00, 0x03, 0xfe, 0x08, 0x88, 0x00, 0x02, 0x02, 0x08, 0x50, 0x00, 0x02, 0x02, 0x28, 0x30, 0x00, 0x1f, 0xff, 0x91, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t_PID[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc3, 0xf1, 0xe0, 0x00, 0x0f, 0xe3, 0xf1, 0xf8, 0x00, 0x0c, 0x70, 0xc1, 0x9e, 0x00, 0x0c, 0x30, 0xc1, 0x86, 0x00, 0x0c, 0x30, 0xc1, 0x83, 0x00, 0x0c, 0x30, 0xc1, 0x83, 0x00, 0x0c, 0x60, 0xc1, 0x83, 0x00, 0x0c, 0x60, 0xc1, 0x83, 0x00, 0x0f, 0xc0, 0xc1, 0x83, 0x00, 0x0f, 0xc0, 0xc1, 0x86, 0x00, 0x0c, 0x00, 0xc1, 0x86, 0x00, 0x0c, 0x00, 0xc1, 0x98, 0x00, 0x0c, 0x03, 0xf1, 0xf8, 0x00, 0x0c, 0x03, 0xf1, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +const unsigned char t5_0[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xdf, 0x88, 0x40, 0x00, 0x0a, 0x24, 0x10, 0x40, 0x00, 0x11, 0x42, 0x10, 0xfe, 0x00, 0x04, 0x00, 0x22, 0x82, 0x00, 0x02, 0xff, 0x3d, 0x02, 0x00, 0x08, 0x01, 0x0a, 0x42, 0x00, 0x09, 0xf9, 0x10, 0x32, 0x00, 0x09, 0x09, 0x20, 0x12, 0x00, 0x09, 0xf9, 0x3e, 0x02, 0x00, 0x09, 0x09, 0x00, 0x02, 0x00, 0x09, 0x09, 0x0e, 0x02, 0x00, 0x09, 0xf9, 0x30, 0x22, 0x00, 0x08, 0x05, 0x00, 0x14, 0x00, 0x08, 0x02, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t5_1[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x44, 0x10, 0xfe, 0x00, 0x04, 0x28, 0x10, 0x92, 0x00, 0x05, 0xff, 0x22, 0x92, 0x00, 0x00, 0x10, 0x3c, 0x92, 0x00, 0x00, 0x10, 0x08, 0x92, 0x00, 0x1c, 0xfe, 0x10, 0x92, 0x00, 0x04, 0x10, 0x20, 0xfe, 0x00, 0x04, 0x10, 0x3e, 0x92, 0x00, 0x05, 0xff, 0x80, 0x92, 0x00, 0x04, 0x10, 0x00, 0x92, 0x00, 0x05, 0x10, 0x0e, 0x92, 0x00, 0x06, 0x10, 0x30, 0x92, 0x00, 0x04, 0x10, 0x00, 0xfe, 0x00, 0x00, 0x10, 0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t5_3[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x3f, 0xfe, 0x00, 0x1f, 0xff, 0x81, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x07, 0xfe, 0x0f, 0xf8, 0x00, 0x04, 0x02, 0x08, 0x08, 0x00, 0x04, 0x02, 0x08, 0x88, 0x00, 0x07, 0xfe, 0x08, 0x88, 0x00, 0x04, 0x02, 0x08, 0x88, 0x00, 0x04, 0x02, 0x08, 0x88, 0x00, 0x07, 0xfe, 0x08, 0x88, 0x00, 0x04, 0x02, 0x09, 0x48, 0x00, 0x04, 0x02, 0x02, 0x30, 0x00, 0x07, 0xfe, 0x04, 0x0c, 0x00, 0x04, 0x02, 0x18, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +const unsigned char t_off[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x82, 0x04, 0xff, 0x00, 0x00, 0x44, 0x02, 0x01, 0x00, 0x07, 0xff, 0x90, 0x21, 0x00, 0x00, 0x10, 0x10, 0x21, 0x00, 0x00, 0x10, 0x17, 0xfd, 0x00, 0x00, 0x10, 0x10, 0x21, 0x00, 0x0f, 0xff, 0xd0, 0x61, 0x00, 0x00, 0x10, 0x10, 0xa1, 0x00, 0x00, 0x28, 0x11, 0x21, 0x00, 0x00, 0x28, 0x12, 0x21, 0x00, 0x00, 0x44, 0x14, 0x21, 0x00, 0x00, 0x82, 0x10, 0xa1, 0x00, 0x03, 0x01, 0xd0, 0x45, 0x00, 0x0c, 0x00, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t_on[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x80, 0x20, 0x00, 0x00, 0x84, 0x07, 0xff, 0x00, 0x00, 0x84, 0x04, 0x01, 0x00, 0x00, 0x84, 0x04, 0x01, 0x00, 0x00, 0x84, 0x04, 0x01, 0x00, 0x0f, 0xff, 0xc7, 0xff, 0x00, 0x00, 0x84, 0x04, 0x00, 0x00, 0x00, 0x84, 0x04, 0x00, 0x00, 0x00, 0x84, 0x05, 0xff, 0x00, 0x00, 0x84, 0x05, 0x01, 0x00, 0x01, 0x04, 0x09, 0x01, 0x00, 0x01, 0x04, 0x09, 0x01, 0x00, 0x02, 0x04, 0x11, 0xff, 0x00, 0x04, 0x04, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +const unsigned char t_NO[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x04, 0x91, 0x00, 0x04, 0x40, 0x02, 0x52, 0x00, 0x04, 0x7f, 0x90, 0x54, 0x00, 0x04, 0x50, 0x88, 0xff, 0x00, 0x07, 0xd0, 0x84, 0x81, 0x00, 0x04, 0x51, 0x00, 0x81, 0x00, 0x04, 0x49, 0x01, 0xff, 0x00, 0x07, 0xca, 0x02, 0x81, 0x00, 0x04, 0x44, 0x04, 0x81, 0x00, 0x04, 0x4a, 0x1c, 0xff, 0x00, 0x07, 0xea, 0x04, 0x81, 0x00, 0x0c, 0x51, 0x04, 0x81, 0x00, 0x00, 0x61, 0xc4, 0x85, 0x00, 0x00, 0x40, 0x80, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t_OK[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xdf, 0x10, 0x20, 0x00, 0x02, 0x12, 0x0c, 0x20, 0x00, 0x02, 0x24, 0x04, 0x20, 0x00, 0x04, 0x7f, 0x80, 0x20, 0x00, 0x04, 0x24, 0xb8, 0x20, 0x00, 0x0f, 0xa4, 0x88, 0x50, 0x00, 0x14, 0xbf, 0x88, 0x50, 0x00, 0x04, 0xa4, 0x88, 0x50, 0x00, 0x04, 0xa4, 0x88, 0x48, 0x00, 0x04, 0xbf, 0x88, 0x88, 0x00, 0x04, 0xa4, 0x8a, 0x88, 0x00, 0x07, 0xa4, 0x8c, 0x84, 0x00, 0x04, 0x44, 0x89, 0x07, 0x00, 0x00, 0x81, 0x86, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +const unsigned char t_CN_CN[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x40, 0x00, 0x80, 0x00, 0x0f, 0xff, 0x3f, 0xff, 0x00, 0x08, 0x41, 0x04, 0x08, 0x00, 0x08, 0x41, 0x04, 0x08, 0x00, 0x08, 0x41, 0x04, 0x10, 0x00, 0x08, 0x41, 0x02, 0x10, 0x00, 0x0f, 0xff, 0x02, 0x20, 0x00, 0x08, 0x41, 0x01, 0x20, 0x00, 0x00, 0x40, 0x00, 0xc0, 0x00, 0x00, 0x40, 0x01, 0x30, 0x00, 0x00, 0x40, 0x02, 0x08, 0x00, 0x00, 0x40, 0x0c, 0x07, 0x00, 0x00, 0x40, 0x30, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char t_CN_EN[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x80, 0x00, 0x1f, 0xff, 0x80, 0x80, 0x00, 0x01, 0x10, 0x3f, 0xff, 0x00, 0x00, 0x40, 0x04, 0x08, 0x00, 0x07, 0xfc, 0x04, 0x08, 0x00, 0x04, 0x44, 0x04, 0x10, 0x00, 0x04, 0x44, 0x02, 0x10, 0x00, 0x04, 0x44, 0x02, 0x20, 0x00, 0x1f, 0xff, 0x81, 0x20, 0x00, 0x00, 0x40, 0x00, 0xc0, 0x00, 0x00, 0xa0, 0x01, 0x30, 0x00, 0x01, 0x10, 0x02, 0x08, 0x00, 0x06, 0x0c, 0x0c, 0x07, 0x00, 0x18, 0x03, 0xb0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +//翻转 +const unsigned char t4f[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x1d, 0xc2, 0x08, 0x00, 0x05, 0x44, 0x42, 0x08, 0x00, 0x03, 0x84, 0x5f, 0xbf, 0x00, 0x0f, 0xe4, 0x44, 0x10, 0x00, 0x01, 0x15, 0x45, 0x10, 0x00, 0x05, 0x4c, 0xc9, 0x7f, 0x80, 0x09, 0x24, 0x4f, 0x90, 0x00, 0x07, 0xc4, 0xc1, 0x10, 0x00, 0x05, 0x4d, 0x41, 0x3f, 0x00, 0x05, 0x54, 0x43, 0x81, 0x00, 0x07, 0xc4, 0x4d, 0x02, 0x00, 0x05, 0x44, 0x41, 0x14, 0x00, 0x05, 0x55, 0x41, 0x08, 0x00, 0x07, 0xc8, 0x81, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +//保存 +const unsigned char t_save[] PROGMEM = { 0x02, 0xfe, 0x01, 0x00, 0x00, 0x02, 0x82, 0x3f, 0xff, 0x00, 0x04, 0x82, 0x02, 0x00, 0x00, 0x04, 0xfe, 0x02, 0x00, 0x00, 0x0c, 0x10, 0x04, 0xfc, 0x00, 0x14, 0x10, 0x04, 0x08, 0x00, 0x05, 0xff, 0x8c, 0x10, 0x00, 0x04, 0x10, 0x14, 0x10, 0x00, 0x04, 0x38, 0x25, 0xff, 0x00, 0x04, 0x34, 0x04, 0x10, 0x00, 0x04, 0x52, 0x04, 0x10, 0x00, 0x04, 0x91, 0x84, 0x10, 0x00, 0x05, 0x10, 0x04, 0x50, 0x00, 0x04, 0x10, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char *CN_table[] = { + t0, t1, t2, t3, t4, t5, t7, t6, Back, //0 + t0, t1_1, t1_2, t1_3, t1_4, t_save, //1 + t2_0, t2_1, t2_2, t_save, //2 + t2_1, t3_1, t2_2, t_save,//3 + t_4, t_PID,//4 + t5_0, t5_1,//5 + t_off, t_on,//6 + t_NO, t_OK,//7 + t_CN_CN, t_CN_EN,//8 + t_NO, t_OK,//9 + t5_3, t4f, t_save, //10 +}; + +bool lastbutton; +#include //注意 这里使用被阉割的图形库,只有绘图功能,并非通用的版本 +Arduboy2 arduboy; + +#include +#include +#include + +// Firmware version +#define VERSION "v1.7t2" + +// Type of rotary encoder +#define ROTARY_TYPE 1 // 0: 2 increments/step; 1: 4 increments/step + +// Pins +#define SENSOR_PIN A0 // temperature sense +#define VIN_PIN A1 // input voltage sense +#define BUZZER_PIN 5 // buzzer +#define BUTTON_PIN 6 // rotary encoder switch +#define ROTARY_1_PIN 7 // rotary encoder 1 +#define ROTARY_2_PIN 8 // rotary encoder 2 +#define CONTROL_PIN 9 // heater MOSFET PWM control +#define SWITCH_PIN 10 // handle vibration switch + +// Default temperature control values (recommended soldering temperature: 300-380°C) +#define ChipTempCalVal 330 //芯片内部温度读取校准值 -->可以根据实际情况修改,不同机器情况不同,通常误差在10°C内 +#define TEMP_MIN 50 // min selectable temperature +#define TEMP_MAX 400 // max selectable temperature +#define TEMP_DEFAULT 320 // default start setpoint +#define TEMP_SLEEP 150 // temperature in sleep mode +#define TEMP_BOOST 60 // temperature increase in boost mode +#define TEMP_STEP 10 // rotary encoder temp change steps + +// Default tip temperature calibration values +#define TEMP200 216 // temperature at ADC = 200 +#define TEMP280 308 // temperature at ADC = 280 +#define TEMP360 390 // temperature at ADC = 360 +#define TEMPCHP 30 // chip temperature while calibration +#define TIPMAX 8 // max number of tips +#define TIPNAMELENGTH 6 // max length of tip names (including termination) +#define TIPNAME "BC1.5" // default tip name + +// Default timer values (0 = disabled) +#define TIME2SLEEP 5 // time to enter sleep mode in minutes +#define TIME2OFF 15 // time to shut off heater in minutes +#define TIMEOFBOOST 40 // time to stay in boost mode in seconds + +// Control values +#define TIME2SETTLE 950 // time in microseconds to allow OpAmp output to settle +#define SMOOTHIE 0.05 // OpAmp output smooth factor (1=no smoothing; 0.05 default) +#define PID_ENABLE true // enable PID control +#define BEEP_ENABLE true // enable/disable buzzer +#define MAINSCREEN 1 // type of main screen (0: big numbers; 1: more infos) + +// EEPROM identifier +#define EEPROM_IDENT 0x08FF // to identify if EEPROM was written by this program + +//Beep +#define SetBeepCoolTime 200 +unsigned long BeepCoolTime; + +// Define the aggressive and conservative PID tuning parameters +double aggKp = 11, aggKi = 0.5, aggKd = 1; +double consKp = 11, consKi = 3, consKd = 5; + +// Default values that can be changed by the user and stored in the EEPROM +uint16_t DefaultTemp = TEMP_DEFAULT; +uint16_t SleepTemp = TEMP_SLEEP; +uint8_t BoostTemp = TEMP_BOOST; +uint8_t time2sleep = TIME2SLEEP; +uint8_t time2off = TIME2OFF; +uint8_t timeOfBoost = TIMEOFBOOST; +uint8_t MainScrType = MAINSCREEN; +bool PIDenable = PID_ENABLE; +bool beepEnable = BEEP_ENABLE; +// Default values for tips +uint16_t CalTemp[TIPMAX][4] = {TEMP200, TEMP280, TEMP360, TEMPCHP}; +char TipName[TIPMAX][TIPNAMELENGTH] = {TIPNAME}; +uint8_t CurrentTip = 0; +uint8_t NumberOfTips = 1; + +// Menu items +/* + 这个可以选择进行界面美化 + const char *DeleteMessage[] = { "Warning", "You cannot", "delete your", "last tip!" }; + const char *MaxTipMessage[] = { "Warning", "You reached", "maximum number", "of tips!" }; +*/ +// Variables for pin change interrupt +volatile uint8_t a0, b0, c0, d0; +volatile bool ab0; +volatile int count, countMin, countMax, countStep; +volatile bool handleMoved; + +// Variables for temperature control +uint16_t SetTemp, ShowTemp, gap, Step; +double Input, Output, Setpoint, RawTemp, CurrentTemp, ChipTemp; + +// Variables for voltage readings +uint16_t Vcc, Vin; + +// State variables +bool inSleepMode = false; +bool inOffMode = false; +bool inBoostMode = false; +bool inCalibMode = false; +bool isWorky = true; +bool beepIfWorky = true; +bool TipIsPresent = true; +bool FlipState = false; +// Timing variables +uint32_t sleepmillis; +uint32_t boostmillis; +uint32_t buttonmillis; +uint8_t goneMinutes; +uint8_t goneSeconds; +uint8_t SensorCounter = 255; +//串口助手 +int x, y, a, b; +//欠压报警 +byte UnderVoltage = 0; +// Control variables +uint16_t time2settle = 300; + +//模拟数字滚轮 Numerical scrolling effect +String value; +int LastValue[3]; +float SlidingAnimationY[3]; + +// Specify the links and initial PID tuning parameters +PID ctrl(&Input, &Output, &Setpoint, aggKp, aggKi, aggKd, REVERSE); + + + +//LANG 语言支持 +/* 0 - 中文 CHINESE + 1 - 英文 ENGLISH +*/ +byte LANG = 0; +void Flip(bool Fmode) { + arduboy.flipVertical(Fmode); + arduboy.flipHorizontal(Fmode); +} +void setup() { + arduboy.begin(); + arduboy.setFrameRate(30); + + //Serial.begin(115200); + // set the pin modes + pinMode(SENSOR_PIN, INPUT); + pinMode(VIN_PIN, INPUT); + pinMode(BUZZER_PIN, OUTPUT); + pinMode(CONTROL_PIN, OUTPUT); + pinMode(ROTARY_1_PIN, INPUT_PULLUP); + pinMode(ROTARY_2_PIN, INPUT_PULLUP); + pinMode(BUTTON_PIN, INPUT_PULLUP); + pinMode(SWITCH_PIN, INPUT_PULLUP); + + analogWrite(CONTROL_PIN, 255); // this shuts off the heater + digitalWrite(BUZZER_PIN, LOW); // must be LOW when buzzer not in use + + // setup ADC + ADCSRA |= bit (ADPS0) | bit (ADPS1) | bit (ADPS2); // set ADC prescaler to 128 + ADCSRA |= bit (ADIE); // enable ADC interrupt + interrupts (); // enable global interrupts + + // setup pin change interrupt for rotary encoder + PCMSK0 = bit (PCINT0); // Configure pin change interrupt on Pin8 + PCICR = bit (PCIE0); // Enable pin change interrupt + PCIFR = bit (PCIF0); // Clear interrupt flag + + + // get default values from EEPROM + getEEPROM(); + //设置屏幕反转状态 + Flip(FlipState); + // read supply voltages in mV + Vcc = getVCC(); Vin = getVIN(); + + // read and set current iron temperature + SetTemp = DefaultTemp; + RawTemp = denoiseAnalog(SENSOR_PIN); + ChipTemp = getChipTemp(); + calculateTemp(); + + // turn on heater if iron temperature is well below setpoint + if ((CurrentTemp + 20) < DefaultTemp) analogWrite(CONTROL_PIN, 0); + + // tell the PID to range between 0 and the full window size + ctrl.SetOutputLimits(0, 255); + + // start PID + ctrl.SetMode(AUTOMATIC); + + // set initial rotary encoder values + a0 = PINB & 1; b0 = PIND >> 7 & 1; ab0 = (a0 == b0); + setRotary(TEMP_MIN, TEMP_MAX, TEMP_STEP, DefaultTemp); + + // reset sleep timer + sleepmillis = millis(); + + // long beep for setup completion + beep(); beep(); + + +} + + +void loop() { + //HelpMeSerialer(); + ROTARYCheck(); // check rotary encoder (temp/boost setting, enter setup menu) + SLEEPCheck(); // check and activate/deactivate sleep modes + SENSORCheck(); // reads temperature and vibration switch of the iron + Thermostat(); // heater control + MainScreen(); // updates the main page on the OLED + //beep(0); +} + + + + +// check rotary encoder; set temperature, toggle boost mode, enter setup menu accordingly +void ROTARYCheck() { + // set working temperature according to rotary encoder value + SetTemp = getRotary(); + + // check rotary encoder switch + uint8_t c = digitalRead(BUTTON_PIN); + if ( !c && c0 ) { + beep(); + buttonmillis = millis(); + while ( (!digitalRead(BUTTON_PIN)) && ((millis() - buttonmillis) < 500) ); + if ((millis() - buttonmillis) >= 500) SetupScreen(); + else { + inBoostMode = !inBoostMode; + if (inBoostMode) boostmillis = millis(); + handleMoved = true; + } + } + c0 = c; + + // check timer when in boost mode + if (inBoostMode && timeOfBoost) { + goneSeconds = (millis() - boostmillis) / 1000; + if (goneSeconds >= timeOfBoost) { + inBoostMode = false; // stop boost mode + beep(); // beep if boost mode is over + beepIfWorky = true; // beep again when working temperature is reached + } + } +} + + +// check and activate/deactivate sleep modes +void SLEEPCheck() { + if (handleMoved) { // if handle was moved + if (inSleepMode) { // in sleep or off mode? + if ((CurrentTemp + 20) < SetTemp) // if temp is well below setpoint + analogWrite(CONTROL_PIN, 0); // then start the heater right now + beep(); // beep on wake-up + beepIfWorky = true; // beep again when working temperature is reached + } + handleMoved = false; // reset handleMoved flag + inSleepMode = false; // reset sleep flag + inOffMode = false; // reset off flag + sleepmillis = millis(); // reset sleep timer + } + + // check time passed since the handle was moved + goneMinutes = (millis() - sleepmillis) / 60000; + if ( (!inSleepMode) && (time2sleep > 0) && (goneMinutes >= time2sleep) ) { + inSleepMode = true; + beep(); + } + if ( (!inOffMode) && (time2off > 0) && (goneMinutes >= time2off ) ) { + inOffMode = true; + beep(); + } +} + + +// reads temperature, vibration switch and supply voltages +void SENSORCheck() { + analogWrite(CONTROL_PIN, 255); // shut off heater in order to measure temperature + delayMicroseconds(time2settle); // wait for voltage to settle + + uint16_t temp = denoiseAnalog(SENSOR_PIN); // read ADC value for temperature + uint8_t d = digitalRead(SWITCH_PIN); // check handle vibration switch + if (d != d0) { + handleMoved = true; // set flag if handle was moved + d0 = d; + } + if (! SensorCounter--) Vin = getVIN(); // get Vin every now and then + + analogWrite(CONTROL_PIN, Output); // turn on again heater + + RawTemp += (temp - RawTemp) * SMOOTHIE; // stabilize ADC temperature reading + calculateTemp(); + + // stabilize displayed temperature when around setpoint + if ((ShowTemp != Setpoint) || (abs(ShowTemp - CurrentTemp) > 5)) ShowTemp = CurrentTemp; + + // set state variable if temperature is in working range; beep if working temperature was just reached + gap = abs(SetTemp - CurrentTemp); + if (gap < 5) { + if (!isWorky && beepIfWorky) beep(); + isWorky = true; + beepIfWorky = false; + } + else isWorky = false; + // checks if tip is present or currently inserted + if (ShowTemp > 500) TipIsPresent = false; // tip removed ? + if (!TipIsPresent && (ShowTemp < 500)) { // new tip inserted ? + analogWrite(CONTROL_PIN, 255); // shut off heater + beep(); // beep for info + TipIsPresent = true; // tip is present now + ChangeTipScreen(); // show tip selection screen + updateEEPROM(); // update setting in EEPROM + handleMoved = true; // reset all timers + RawTemp = denoiseAnalog(SENSOR_PIN); // restart temp smooth algorithm + c0 = LOW; // switch must be released + setRotary(TEMP_MIN, TEMP_MAX, TEMP_STEP, SetTemp); // reset rotary encoder + } +} + + +// calculates real temperature value according to ADC reading and calibration values +void calculateTemp() { + if (RawTemp < 200) CurrentTemp = map (RawTemp, 0, 200, 21, CalTemp[CurrentTip][0]); + else if (RawTemp < 280) CurrentTemp = map (RawTemp, 200, 280, CalTemp[CurrentTip][0], CalTemp[CurrentTip][1]); + else CurrentTemp = map (RawTemp, 280, 360, CalTemp[CurrentTip][1], CalTemp[CurrentTip][2]); +} + + +//调温 +void Thermostat() { + // define Setpoint acoording to current working mode + if (inOffMode) Setpoint = 0; + else if (inSleepMode) Setpoint = SleepTemp; + else if (inBoostMode) Setpoint = SetTemp + BoostTemp; + else Setpoint = SetTemp; + + // control the heater (PID or direct) + gap = abs(Setpoint - CurrentTemp); + if (PIDenable) { + Input = CurrentTemp; + if (gap < 30) ctrl.SetTunings(consKp, consKi, consKd); + else ctrl.SetTunings(aggKp, aggKi, aggKd); + ctrl.Compute(); + } else { + // turn on heater if current temperature is below setpoint + if ((CurrentTemp + 0.5) < Setpoint) Output = 0; else Output = 255; + } + analogWrite(CONTROL_PIN, Output); // set heater PWM +} + + +// creates a short beep on the buzzer +void beep() { + /* + if (beepEnable) { + if (BeepCoolTime + SetBeepCoolTime < millis()) { + if (state) BeepCoolTime = millis(); + analogWrite(BUZZER_PIN, 0); + } else analogWrite(BUZZER_PIN, 127); + } else analogWrite(BUZZER_PIN, 0); + */ + //体谅一下,没内存了,只能用原始的办法驱动无源蜂鸣器,否则我也不想牺牲宝贵响应资源换内存 + if (beepEnable) { + for (uint8_t i = 0; i < 255; i++) { + digitalWrite(BUZZER_PIN, HIGH); + delayMicroseconds(125); + digitalWrite(BUZZER_PIN, LOW); + delayMicroseconds(125); + } + } +} + +//设置旋转编码器的起始值 +// sets start values for rotary encoder +void setRotary(int rmin, int rmax, int rstep, int rvalue) { + countMin = rmin << ROTARY_TYPE; + countMax = rmax << ROTARY_TYPE; + countStep = rstep; + count = rvalue << ROTARY_TYPE; +} + + +// reads current rotary encoder value +int getRotary() { + return (count >> ROTARY_TYPE); +} + + +// reads user settings from EEPROM; if EEPROM values are invalid, write defaults +void getEEPROM() { + uint16_t identifier = (EEPROM.read(0) << 8) | EEPROM.read(1); + if (identifier == EEPROM_IDENT) { + DefaultTemp = (EEPROM.read(2) << 8) | EEPROM.read(3); + SleepTemp = (EEPROM.read(4) << 8) | EEPROM.read(5); + BoostTemp = EEPROM.read(6); + time2sleep = EEPROM.read(7); + time2off = EEPROM.read(8); + timeOfBoost = EEPROM.read(9); + MainScrType = EEPROM.read(10); + PIDenable = EEPROM.read(11); + beepEnable = EEPROM.read(12); + CurrentTip = EEPROM.read(13); + NumberOfTips = EEPROM.read(14); + LANG = EEPROM.read(15); + FlipState = EEPROM.read(16); + UnderVoltage = EEPROM.read(17); + uint8_t i, j; + uint16_t counter = 18; + for (i = 0; i < NumberOfTips; i++) { + for (j = 0; j < TIPNAMELENGTH; j++) { + TipName[i][j] = EEPROM.read(counter++); + } + for (j = 0; j < 4; j++) { + CalTemp[i][j] = EEPROM.read(counter++) << 8; + CalTemp[i][j] |= EEPROM.read(counter++); + } + } + } + else { + EEPROM.update(0, EEPROM_IDENT >> 8); EEPROM.update(1, EEPROM_IDENT & 0xFF); + updateEEPROM(); + } +} + + +// writes user settings to EEPROM using updade function to minimize write cycles +void updateEEPROM() { + EEPROM.update( 2, DefaultTemp >> 8); + EEPROM.update( 3, DefaultTemp & 0xFF); + EEPROM.update( 4, SleepTemp >> 8); + EEPROM.update( 5, SleepTemp & 0xFF); + EEPROM.update( 6, BoostTemp); + EEPROM.update( 7, time2sleep); + EEPROM.update( 8, time2off); + EEPROM.update( 9, timeOfBoost); + EEPROM.update(10, MainScrType); + EEPROM.update(11, PIDenable); + EEPROM.update(12, beepEnable); + EEPROM.update(13, CurrentTip); + EEPROM.update(14, NumberOfTips); + EEPROM.update(15, LANG); + EEPROM.update(16, FlipState); + EEPROM.update(17, UnderVoltage); + uint8_t i, j; + uint16_t counter = 18; + for (i = 0; i < NumberOfTips; i++) { + for (j = 0; j < TIPNAMELENGTH; j++) EEPROM.update(counter++, TipName[i][j]); + for (j = 0; j < 4; j++) { + EEPROM.update(counter++, CalTemp[i][j] >> 8); + EEPROM.update(counter++, CalTemp[i][j] & 0xFF); + } + } +} +//此片段用于DEBUG +void HelpMeSerialer() { + //串口助手 + if (Serial.available()) { + char TmpChar = Serial.read(); + switch (TmpChar) { + case 'x': x = Serial.parseInt(); + case 'y': y = Serial.parseInt(); + case 'a': a = Serial.parseInt(); + case 'b': b = Serial.parseInt(); + } + } + /* + Serial.println(String("X ->") + x); + Serial.println(String("Y ->") + y); + Serial.println(String("A ->") + a); + Serial.println(String("B ->") + b); + */ +} +// draws the main screen +void MainScreen() { + if (!(arduboy.nextFrame())) //帧率锁 + return; + byte SysState; + if (MainScrType) { + arduboy.clear(); + //详细信息页 + arduboy.fillRect(0, 0, 128, 64, 1); //白底 + arduboy.setTextSize(1); + SetTextColor(0); + //预设名 + arduboy.drawSlowXYBitmap(0, 0, Tag, 16, 16, 0); + arduboy.setCursor(19, 4); arduboy.print(TipName[CurrentTip]); + //状态显示 + if (ShowTemp > 500) SysState = 0; + else if (inOffMode) SysState = 1; + else if (inSleepMode) SysState = 2; + else if (inBoostMode) SysState = 3; + else if (isWorky) SysState = 4; + else if (Output < 180) SysState = 5; + else SysState = 6; + //显示状态 + arduboy.setCursor(53, 1); + arduboy.setTextSize(2); + switch (LANG) { + case 0: arduboy.drawSlowXYBitmap(80, 1, S_table[SysState], 28, 14, 0); break; //中文 Chinese + default: //英文 English + switch (SysState) { + case 1: arduboy.print(F("OFF")); break; + case 2: arduboy.print(F("SLEEP")); break; + case 3: arduboy.print(F("BOOST")); break; + case 4: arduboy.print(F("WORKY")); break; + case 5: arduboy.print(F("HEAT")); break; + case 6: arduboy.print(F("HOLD")); break; + default: arduboy.print(F("ERROR")); break; + } break; + } + arduboy.drawSlowXYBitmap(113, 1, C_table[SysState], 14, 14, 0); + arduboy.setTextSize(1); + //芯片 + //R1 + if (getChipTemp() > 80 && ((millis() * 4) / 1000) % 2) beep(); else arduboy.drawSlowXYBitmap(2, 18, Chip, 14, 14, 0); + + //R2 + if ((float)Vin / 100 < UnderVoltage && ((millis() * 4) / 1000) % 2) beep(); else arduboy.drawSlowXYBitmap(2, 34, Lightning, 14, 14, 0); + //R3 + arduboy.setCursor(19, 16); arduboy.print(getChipTemp(), 1); arduboy.print((char)248); arduboy.print(F("C")); //芯片温度 + arduboy.setCursor(19, 24); arduboy.print((float)getVCC() / 1000, 2); arduboy.print(F("V")); //芯片电压 + arduboy.setCursor(19, 32); arduboy.print((float)Vin / 1000, 1); arduboy.print(F("V")); //输入电压 + arduboy.setCursor(19, 40); arduboy.print(F(VERSION)); //固件 + //显示探头温度 + arduboy.setCursor(57, 18); + arduboy.setTextSize(4); + if (ShowTemp > 500) arduboy.print(F("000")); else arduboy.print(ShowTemp); + arduboy.drawRect(55, 16, 72, 32, 0); + + DrawStatusBar(0); + arduboy.display(); + } else { + arduboy.clear(); + if (getChipTemp() > 80 && ((millis() * 4) / 1000) % 2) beep(); + if ((float)Vin / 100 < UnderVoltage && ((millis() * 4) / 1000) % 2) beep(); + if (ShowTemp > 500) DisplayNum(999); else DisplayNum(ShowTemp); + arduboy.fillRect(0, 48, 128, 3, 0); + DrawStatusBar(1); + arduboy.display(); + } + +} + +void DrawStatusBar(bool color) { + SetTextColor(color); + arduboy.setTextSize(1); + //温度条 + //框 + arduboy.drawRect(1, 49, 102, 14, color); + //条 + if (ShowTemp <= 500) arduboy.fillRect(1, 49, map(ShowTemp, 0, 500, 2, 102), 14, color); + //指示部分 + arduboy.fillRect(map(Setpoint, 0, 500, 2, 102) - 2, 50, 3, 13, color); + //先来个白底 + arduboy.fillRect(map(Setpoint, 0, 500, 2, 102) - 3, 60, 5, 4, color); + arduboy.drawLine(map(Setpoint, 0, 500, 2, 102) - 1, 60, map(Setpoint, 0, 500, 2, 102) - 1, 49, !color); + + //画指示针 + arduboy.drawSlowXYBitmap(map(Setpoint, 0, 500, 2, 102) - 3, 59, Pointer, 5, 4, !color); + + //功率条 + arduboy.drawRect(104, 49, 23, 14, color); + arduboy.fillRect(104, 49, map(Output, 255, 0, 0, 23), 14, color); + + SetTextColor(!color); + //////////////进入反色//////////////////////////////// + arduboy.setCursor(2, 55); arduboy.print(Setpoint, 0); arduboy.print((char)248); arduboy.print(F("C")); //探头预设温度 + arduboy.setCursor(105, 55); arduboy.print(map(Output, 255, 0, 0, 100)); arduboy.print(F("%")); //功率百分比 + SetTextColor(color); +} + +//设置画笔颜色 +void SetTextColor(bool color) { + arduboy.setTextBackground(!color); + arduboy.setTextColor(color); +} +// setup screen +void SetupScreen() { + analogWrite(CONTROL_PIN, 255); // shut off heater + beep(); + uint16_t SaveSetTemp = SetTemp; + uint8_t selection = 0; + bool repeat = true; + + while (repeat) { + MenuLevel = 0; //默认打开主菜单 + selection = MenuScreen(selection); + switch (selection) { + case 0: MenuLevel = 1; TipScreen(); repeat = false; break; + case 1: MenuLevel = 2; TempScreen(); break; + case 2: MenuLevel = 3; TimerScreen(); break; + case 3: MenuLevel = 4; PIDenable = MenuScreen(PIDenable); break; + case 4: MenuLevel = 10; ScreenSet(); break; + case 5: MenuLevel = 6; beepEnable = MenuScreen(beepEnable); break; + case 7: MenuLevel = 8; LANG = MenuScreen(LANG); break; + case 6: UnderVoltageSet(); break; + default: repeat = false; break; + } + } + updateEEPROM(); + handleMoved = true; + SetTemp = SaveSetTemp; + setRotary(TEMP_MIN, TEMP_MAX, TEMP_STEP, SetTemp); +} + + +//显示设置菜单 +// tip settings screen +void ScreenSet() { + uint8_t selection = 0; + bool repeat = true; + while (repeat) { + MenuLevel = 10; + selection = MenuScreen(selection); + switch (selection) { + case 0: MenuLevel = 5; MainScrType = MenuScreen(MainScrType); break; + case 1: MenuLevel = 9; FlipState = MenuScreen(FlipState); break; + default: repeat = false; break; + } + Flip(FlipState); //设置屏幕反转状态 + } + updateEEPROM(); +} + +//预设设置菜单 +// tip settings screen +void TipScreen() { + uint8_t selection = 0; + bool repeat = true; + while (repeat) { + MenuLevel = 1; + selection = MenuScreen(selection); + switch (selection) { + case 0: ChangeTipScreen(); break; + case 1: CalibrationScreen(); break; + case 2: InputNameScreen(); break; + case 3: DeleteTipScreen(); break; + case 4: AddTipScreen(); break; + default: repeat = false; break; + } + } +} + +//温控设置菜单 +// temperature settings screen +void TempScreen() { + uint8_t selection = 0; + bool repeat = true; + while (repeat) { + selection = MenuScreen(selection); + switch (selection) { + case 0: setRotary(TEMP_MIN, TEMP_MAX, TEMP_STEP, DefaultTemp); + DefaultTemp = InputScreen(); break; + case 1: setRotary(20, 200, TEMP_STEP, SleepTemp); + SleepTemp = InputScreen(); break; + case 2: setRotary(10, 100, TEMP_STEP, BoostTemp); + BoostTemp = InputScreen(); break; + default: repeat = false; break; + } + } + updateEEPROM(); +} + +//定时器设置菜单 +// timer settings screen +void TimerScreen() { + uint8_t selection = 0; + bool repeat = true; + while (repeat) { + selection = MenuScreen(selection); + switch (selection) { + case 0: setRotary(0, 30, 1, time2sleep); + time2sleep = InputScreen(); break; + case 1: setRotary(0, 60, 5, time2off); + time2off = InputScreen(); break; + case 2: setRotary(0, 180, 10, timeOfBoost); + timeOfBoost = InputScreen(); break; + default: repeat = false; break; + } + } + updateEEPROM(); +} +//英语支持 +void Print_EN(byte i) { + char buffer[11]; + strcpy_P(buffer, (char *)pgm_read_word(&(EN_table[i]))); + arduboy.print(buffer); +} +//菜单界面 +// menu screen +uint8_t MenuScreen(uint8_t selected) { + int SlidingAnimationX; + uint8_t lastselected = selected; + setRotary(0, Menu_table[MenuLevel] - 1, 1, selected); + lastbutton = (!digitalRead(BUTTON_PIN)); + SetTextColor(1); + do { + selected = getRotary(); + //非线性滑动动画 + SlidingAnimationX += (selected - lastselected) * 56; + if (SlidingAnimationX != 0) SlidingAnimationX += 0.5 * (-SlidingAnimationX); + lastselected = selected; + arduboy.clear(); + //绘制图标 如果有指定的话 + for (byte i = 0; i < 5; i++) if (selected - 2 + i >= 0 && selected - 2 + i < Menu_table[MenuLevel]) { + DrawUIFrame(-72 + i * 56 + SlidingAnimationX, 0, 1); + drawSlowXYBitmapResize(-72 + i * 56 + SlidingAnimationX + 3, 3, Ico_table[selected - 2 + i + QueryMenuObject()], 14, 14, 3, 1); + } + + if (LANG == 0) arduboy.drawSlowXYBitmap(48, 48, CN_table[selected + QueryMenuObject()], 36, 16, 1); else { + arduboy.setCursor(48, 49); + arduboy.setTextSize(1); + Print_EN(selected + QueryMenuObject()); + } + + + arduboy.display(); + CheckLastButton(); + //beep(0); + } while (digitalRead(BUTTON_PIN) || lastbutton); + beep(); + return selected; +} +void DrawUIFrame(int x, int y, bool color) { + arduboy.fillRect(x, y, 48, 48, color); + arduboy.fillRect(x + 3, y + 3, 42, 42, !color); //雕空 + DrawPoint(x, y, 0); + DrawPoint(x + 47, y, 0); + DrawPoint(x, y + 47, 0); + DrawPoint(x + 47, y + 47, 0); +} +void DrawPoint(int x, int y, bool color) { + arduboy.drawPixel(x + 1, y, color); + arduboy.drawPixel(x - 1, y, color); + arduboy.drawPixel(x, y + 1, color); + arduboy.drawPixel(x, y - 1, color); + arduboy.drawPixel(x, y, color); +} +//检查按键 +void CheckLastButton() { + if (lastbutton && digitalRead(BUTTON_PIN)) { + delay(10); + lastbutton = false; + } +} +//返回对应层数的对象数 +byte QueryMenuObject() { + int SUM = 0; + for (int i = 0; i < (MenuLevel); i++) SUM += Menu_table[i]; + return SUM; +} +//信息窗 +/* + void MessageScreen(const char *Items[], uint8_t numberOfItems) { + lastbutton = (!digitalRead(BUTTON_PIN)); + + //u8g.setFont(//u8g_font_9x15); + //u8g.setFontPosTop(); + for (uint8_t i = 0; i < numberOfItems; i++) //u8g.drawStr( 0, i * 16, Items[i]); + + do { + CheckLastButton(); + } while (digitalRead(BUTTON_PIN) || lastbutton); + beep(); + } +*/ +/* + 好看是好看,但是浪费内存 + int wav(byte wavi, int num) { + return (wavi + byte(millis() / 100)) * (float(float(num - countMin) / float(countMax - countMin)) - 0.5) * 5; + } +*/ + +//模拟数字滚轮 Numerical scrolling effect +void DisplayNum(int Num) { + + arduboy.setTextSize(6); + SetTextColor(0); + //数字滚轮 + for (byte i = 0; i < 3; i++) LastValue[i] = byte(value[i]); + value = Num; + for (byte i = 0; i < 3; i++) { + SlidingAnimationY[i] += (byte(value[i]) - LastValue[i]) * 50; + if (SlidingAnimationY[i] != 0) SlidingAnimationY[i] += 0.8 * (-SlidingAnimationY[i]); + arduboy.fillRect(0 + i * 44, 0, 38, 50, 1); //白底 + for (int ii = -1; ii < 2; ii++) { + arduboy.setCursor(4 + i * 44, 4 - SlidingAnimationY[i] + ii * 50); + arduboy.print(LastValue[i] + ii - 48); + } + } + //刻度标 + arduboy.fillRect(0, 0, 128, 2, 0); //上遮罩层 + arduboy.fillRect(0, 51, 128, 13, 0); //下遮罩层 +} + +//数值输入界面 +// input value screen +uint16_t InputScreen() { + lastbutton = (!digitalRead(BUTTON_PIN)); + do { + arduboy.clear(); + DisplayNum(getRotary()); + arduboy.display(); + CheckLastButton(); + } while (digitalRead(BUTTON_PIN) || lastbutton); + beep(); + return value.toInt(); +} + +//欠压报警设置 +// information display screen +void UnderVoltageSet() { + setRotary(0, 250, 1, UnderVoltage); + UnderVoltage = InputScreen(); + beep(); +} + +//更换预设界面 +// change tip screen +void ChangeTipScreen() { + uint8_t selected = CurrentTip; + uint8_t lastselected = selected; + int8_t arrow = 0; + if (selected) arrow = 1; + setRotary(0, NumberOfTips - 1, 1, selected); + lastbutton = (!digitalRead(BUTTON_PIN)); + do { + //beep(0); + arduboy.clear(); + selected = getRotary(); + arrow = constrain(arrow + selected - lastselected, 0, 2); + lastselected = selected; + SetTextColor(0); + arduboy.setTextSize(2); + arduboy.setCursor(0, 0); arduboy.print(F("Select Tip")); + SetTextColor(1); + arduboy.setCursor(0, 16 * (arrow + 1)); arduboy.print(F(">")); + for (uint8_t i = 0; i < 3; i++) { + uint8_t drawnumber = selected + i - arrow; + if (drawnumber < NumberOfTips) { + arduboy.setCursor(12, 16 * (i + 1)); arduboy.print(TipName[selected + i - arrow]); + } + } + CheckLastButton(); + arduboy.display(); + } while (digitalRead(BUTTON_PIN) || lastbutton); + + beep(); + CurrentTip = selected; +} + +//温度校准界面 +// temperature calibration screen +void CalibrationScreen() { + uint16_t CalTempNew[4]; + for (uint8_t CalStep = 0; CalStep < 3; CalStep++) { + SetTemp = CalTemp[CurrentTip][CalStep]; + setRotary(100, 500, 1, SetTemp); + beepIfWorky = true; + lastbutton = (!digitalRead(BUTTON_PIN)); + do { + arduboy.clear(); + arduboy.setTextSize(2); + SENSORCheck(); // reads temperature and vibration switch of the iron + Thermostat(); // heater control + arduboy.setCursor(0, 0); arduboy.print(F("Step: ")); arduboy.print(CalStep + 1); arduboy.print("/3"); + if (isWorky) { + arduboy.setCursor(0, 16); arduboy.print(F("Set measured")); + arduboy.setCursor(0, 32); arduboy.print(F("temp: ")); arduboy.print(getRotary()); + } else { + arduboy.setCursor(0, 16); arduboy.print(F("ADC: ")); arduboy.print(uint16_t(RawTemp)); + arduboy.setCursor(0, 32); arduboy.print(F("Please wait")); + } + CheckLastButton(); + arduboy.display(); + } while (digitalRead(BUTTON_PIN) || lastbutton); + + CalTempNew[CalStep] = getRotary(); + beep(); delay (10); + } + + analogWrite(CONTROL_PIN, 255); // shut off heater + delayMicroseconds(time2settle); // wait for voltage to settle + CalTempNew[3] = getChipTemp(); // read chip temperature + if ((CalTempNew[0] + 30 < CalTempNew[1]) && (CalTempNew[1] + 30 < CalTempNew[2])) { + MenuLevel = 7; + if (MenuScreen(0)) { + for (uint8_t i = 0; i < 4; i++) CalTemp[CurrentTip][i] = CalTempNew[i]; + } + } +} + +//命名界面 文本输入界面 +// input tip name screen +void InputNameScreen() { + uint8_t value; + for (uint8_t digit = 0; digit < (TIPNAMELENGTH - 1); digit++) { + lastbutton = (!digitalRead(BUTTON_PIN)); + setRotary(31, 96, 1, 65); + do { + value = getRotary(); + if (value == 31) { + value = 95; + setRotary(31, 96, 1, 95); + } + if (value == 96) { + value = 32; + setRotary(31, 96, 1, 32); + } + //arduboy.setCursor(0, 0);arduboy.print(); + arduboy.clear(); + arduboy.setTextSize(2); + arduboy.setCursor(16 * digit, 48); arduboy.print(char(94)); + arduboy.setCursor(0, 32); + for (uint8_t i = 0; i < digit; i++) arduboy.print(TipName[CurrentTip][i]); + arduboy.setCursor(16 * digit, 32); arduboy.print(char(value)); + CheckLastButton(); + arduboy.display(); + } while (digitalRead(BUTTON_PIN) || lastbutton); + TipName[CurrentTip][digit] = value; + beep(); delay (10); + } + TipName[CurrentTip][TIPNAMELENGTH - 1] = 0; + return value; +} + + +// delete tip screen +void DeleteTipScreen() { + MenuLevel = 7; + if (NumberOfTips == 1) { + //MessageScreen(DeleteMessage, sizeof(DeleteMessage)); + } + else if (MenuScreen(0)) { + if (CurrentTip == (NumberOfTips - 1)) { + CurrentTip--; + } + else { + for (uint8_t i = CurrentTip; i < (NumberOfTips - 1); i++) { + for (uint8_t j = 0; j < TIPNAMELENGTH; j++) TipName[i][j] = TipName[i + 1][j]; + for (uint8_t j = 0; j < 4; j++) CalTemp[i][j] = CalTemp[i + 1][j]; + } + } + NumberOfTips--; + } +} + + +// add new tip screen +void AddTipScreen() { + if (NumberOfTips < TIPMAX) { + CurrentTip = NumberOfTips++; InputNameScreen(); + CalTemp[CurrentTip][0] = TEMP200; CalTemp[CurrentTip][1] = TEMP280; + CalTemp[CurrentTip][2] = TEMP360; CalTemp[CurrentTip][3] = TEMPCHP; + } //MessageScreen(MaxTipMessage, sizeof(MaxTipMessage)); 信息窗 +} + + +// average several ADC readings in sleep mode to denoise +uint16_t denoiseAnalog (byte port) { + uint16_t result = 0; + ADCSRA |= bit (ADEN) | bit (ADIF); // enable ADC, turn off any pending interrupt + if (port >= A0) port -= A0; // set port and + ADMUX = (0x0F & port) | bit(REFS0); // reference to AVcc + set_sleep_mode (SLEEP_MODE_ADC); // sleep during sample for noise reduction + for (uint8_t i = 0; i < 32; i++) { // get 32 readings + sleep_mode(); // go to sleep while taking ADC sample + while (bitRead(ADCSRA, ADSC)); // make sure sampling is completed + result += ADC; // add them up + } + bitClear (ADCSRA, ADEN); // disable ADC + return (result >> 5); // devide by 32 and return value +} + +//读取芯片温度 +// get internal temperature by reading ADC channel 8 against 1.1V reference +double getChipTemp() { + unsigned int wADC; + double t; + ADMUX = (_BV(REFS1) | _BV(REFS0) | _BV(MUX3)); + ADCSRA |= _BV(ADEN); + delay(5); + ADCSRA |= _BV(ADSC); + while (bit_is_set(ADCSRA, ADSC)); + wADC = ADCW; + t = (wADC - ChipTempCalVal ) / 1.22; + return (t); +} + +/* + // get internal temperature by reading ADC channel 8 against 1.1V reference + double getChipTemp() { + uint16_t result = 0; + ADCSRA |= bit (ADEN) | bit (ADIF); // enable ADC, turn off any pending interrupt + ADMUX = bit (REFS1) | bit (REFS0) | bit (MUX3); // set reference and mux + delay(20); // wait for voltages to settle + set_sleep_mode (SLEEP_MODE_ADC); // sleep during sample for noise reduction + for (uint8_t i = 0; i < 32; i++) { // get 32 readings + sleep_mode(); // go to sleep while taking ADC sample + while (bitRead(ADCSRA, ADSC)); // make sure sampling is completed + result += ADC; // add them up + } + bitClear (ADCSRA, ADEN); // disable ADC + result >>= 2; // devide by 4 + return ((result - 2594) / 9.76); // calculate internal temperature in degrees C + } +*/ +// get input voltage in mV by reading 1.1V reference against AVcc +uint16_t getVCC() { + uint16_t result = 0; + ADCSRA |= bit (ADEN) | bit (ADIF); // enable ADC, turn off any pending interrupt + // set Vcc measurement against 1.1V reference + ADMUX = bit (REFS0) | bit (MUX3) | bit (MUX2) | bit (MUX1); + delay(1); // wait for voltages to settle + set_sleep_mode (SLEEP_MODE_ADC); // sleep during sample for noise reduction + for (uint8_t i = 0; i < 16; i++) { // get 16 readings + sleep_mode(); // go to sleep while taking ADC sample + while (bitRead(ADCSRA, ADSC)); // make sure sampling is completed + result += ADC; // add them up + } + bitClear (ADCSRA, ADEN); // disable ADC + result >>= 4; // devide by 16 + return (1125300L / result); // 1125300 = 1.1 * 1023 * 1000 +} + + +// get supply voltage in mV +uint16_t getVIN() { + long result; + result = denoiseAnalog (VIN_PIN); // read supply voltage via voltage divider + return (result * Vcc / 179.474); // 179.474 = 1023 * R13 / (R12 + R13) +} + +//ADC中断服务 +// ADC interrupt service routine +EMPTY_INTERRUPT (ADC_vect); // nothing to be done here + +//旋转编码器触发中断 +// Pin change interrupt service routine for rotary encoder +ISR (PCINT0_vect) { + uint8_t a = PINB & 1; + uint8_t b = PIND >> 7 & 1; + if (a != a0) { // A changed + a0 = a; + if (b != b0) { // B changed + b0 = b; + count = constrain(count + ((a == b) ? countStep : -countStep), countMin, countMax); + if (ROTARY_TYPE && ((a == b) != ab0)) { + count = constrain(count + ((a == b) ? countStep : -countStep), countMin, countMax);; + } + ab0 = (a == b); + handleMoved = true; + } + } +} + +//显示位图,并允许放大 代码片段改自arduboy2 +void drawSlowXYBitmapResize(int x, int y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t size, uint8_t color) { + // no need to draw at all of we're offscreen + /* + if (x + w < 0 || x > WIDTH - 1 || y + h < 0 || y > HEIGHT - 1) + return; + */ + int16_t xi, yi, byteWidth = (w + 7) / 8; + for (yi = 0; yi < h; yi ++) { + for (xi = 0; xi < w; xi ++) { + if (pgm_read_byte(bitmap + yi * byteWidth + xi / 8) & (128 >> (xi & 7))) { + //arduboy.drawPixel(x + xi, y + yi, color); + arduboy.fillRect(x + xi * size, y + yi * size, size, size, color); + } + } + } +}