├── EinkESP8266.cpp ├── EinkESP8266.h ├── README.md └── einkLowPowerDS1820B.ino /EinkESP8266.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 2012 Copyright (c) Seeed Technology Inc. 3 | 4 | Author: Zhangkun 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc.,51 Franklin St,Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | 21 | Converted from STM32 to ESP8266 by Catalin Batrinu 22 | 2016 Copyright (c) bcatalin@gmail.com 23 | 24 | */ 25 | 26 | #include "EinkESP8266.h" 27 | #include 28 | #include 29 | 30 | const unsigned char F8X16[]= 31 | { 32 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0 33 | 0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00,//!1 34 | 0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//"2 35 | 0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00,//#3 36 | 0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00,//$4 37 | 0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00,//%5 38 | 0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10,//&6 39 | 0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//'7 40 | 0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00,//(8 41 | 0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00,//)9 42 | 0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00,//*10 43 | 0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00,//+11 44 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00,//,12 45 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,//-13 46 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00,//.14 47 | 0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00,///15 48 | 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00,//016 49 | 0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//117 50 | 0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00,//218 51 | 0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00,//319 52 | 0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00,//420 53 | 0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00,//521 54 | 0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00,//622 55 | 0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,//723 56 | 0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00,//824 57 | 0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00,//925 58 | 0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,//:26 59 | 0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00,//;27 60 | 0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00,//<28 61 | 0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00,//=29 62 | 0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00,//>30 63 | 0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00,//?31 64 | 0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00,//@32 65 | 0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20,//A33 66 | 0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00,//B34 67 | 0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00,//C35 68 | 0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00,//D36 69 | 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00,//E37 70 | 0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00,//F38 71 | 0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00,//G39 72 | 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20,//H40 73 | 0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//I41 74 | 0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00,//J42 75 | 0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00,//K43 76 | 0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00,//L44 77 | 0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00,//M45 78 | 0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00,//N46 79 | 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00,//O47 80 | 0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00,//P48 81 | 0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00,//Q49 82 | 0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20,//R50 83 | 0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00,//S51 84 | 0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//T52 85 | 0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//U53 86 | 0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00,//V54 87 | 0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00,//W55 88 | 0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20,//X56 89 | 0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00,//Y57 90 | 0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00,//Z58 91 | 0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00,//[59 92 | 0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00,//\60 93 | 0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00,//]61 94 | 0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//^62 95 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,//_63 96 | 0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//`64 97 | 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20,//a65 98 | 0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00,//b66 99 | 0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00,//c67 100 | 0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20,//d68 101 | 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00,//e69 102 | 0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//f70 103 | 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00,//g71 104 | 0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//h72 105 | 0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//i73 106 | 0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,//j74 107 | 0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00,//k75 108 | 0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00,//l76 109 | 0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F,//m77 110 | 0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20,//n78 111 | 0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00,//o79 112 | 0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00,//p80 113 | 0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80,//q81 114 | 0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00,//r82 115 | 0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00,//s83 116 | 0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00,//t84 117 | 0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20,//unsigned char5 118 | 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00,//v86 119 | 0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00,//w87 120 | 0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00,//x88 121 | 0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00,//y89 122 | 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00,//z90 123 | 0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40,//{91 124 | 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,//|92 125 | 0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00,//}93 126 | 0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~94 127 | }; 128 | 129 | 130 | 131 | 132 | 133 | 134 | /* ------------------------------------------------------------- 135 | private class function, called by public fuction: clearScreen(), to init the screen; 136 | --------------------------------------------------------------*/ 137 | void E_ink_ESP8266::initEink(void) //initial code 138 | { 139 | writeComm(0x10);//exit deep sleep mode 140 | writeData(0x00); 141 | writeComm(0x11);//data enter mode 142 | writeData(0x03); 143 | writeComm(0x44);//set RAM x address start/end, in page 36 144 | writeData(0x00);//RAM x address start at 00h; 145 | writeData(0x11);//RAM x address end at 11h(17)->72: [because 1F(31)->128 and 12(18)->76] 146 | writeComm(0x45);//set RAM y address start/end, in page 37 147 | writeData(0x00);//RAM y address start at 00h; 148 | writeData(0xAB);//RAM y address start at ABh(171)->172: [because B3(179)->180] 149 | writeComm(0x4E);//set RAM x address count to 0; 150 | writeData(0x00); 151 | writeComm(0x4F);//set RAM y address count to 0; 152 | writeData(0x00); 153 | writeComm(0xF0);//booster feedback used, in page 37 154 | writeData(0x1F); 155 | writeComm(0x22);//display updata sequence option ,in page 33 156 | writeData(0xC0);//enable sequence: clk -> CP 157 | 158 | configureLUTRegister(); 159 | 160 | writeComm(0x2C);//vcom 161 | writeData(0xA0); 162 | writeComm(0x3C);//board 163 | writeData(0x63); 164 | writeComm(0x22);//display updata sequence option ,in page 33 165 | writeData(0xC4);//enable sequence: clk -> CP -> LUT -> initial display -> pattern display 166 | } 167 | 168 | /*------------- 169 | refresh the screen, need to be called by application every time the screen changed 170 | --------------*/ 171 | void E_ink_ESP8266::refreshScreen(void) 172 | { 173 | writeComm(0x20); 174 | closeBump(); 175 | delay(5000); 176 | 177 | 178 | } 179 | 180 | 181 | /*------------- 182 | clear the original screen, need to be called before writing any data or command to screen ; 183 | ------------*/ 184 | void E_ink_ESP8266::clearScreen(void) 185 | { 186 | INT16U i; 187 | initEink(); 188 | writeComm(0x24); 189 | for(i=0;i<3096;i++) 190 | { 191 | writeData(0xff); 192 | } 193 | delay(1000); 194 | } 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | /* 203 | display character in the Eink screen: 204 | x:the X start address,X value can be 0 to 14; 205 | y:the Y start address, Y vlue can be 171 to 7; 206 | the charater diplay erea is from x to x+3 in X position and from y to y-7 in Y position 207 | unicode_char:the character machine code 208 | */ 209 | void E_ink_ESP8266::displayChar(INT8U x,INT8U y,INT16U unicode_Char) 210 | { 211 | INT16U i; 212 | getCharMatrixData(unicode_Char); 213 | converCharMatrixData(); 214 | //setPositionXY(x,x+3,y,y-7); 215 | setPositionXY(x,x+3,y,y-7); 216 | writeComm(0x11); /*data enter mode command */ 217 | writeData(0x05); /*set Y-mode:X address is increment and y address decrement */ 218 | writeComm(0x24); 219 | for(i=16;i<32;i++) 220 | { 221 | writeData(matrixdata_conver[i]); 222 | } 223 | for(i=0;i<16;i++) 224 | { 225 | 226 | writeData(matrixdata_conver[i]); 227 | } 228 | } 229 | 230 | void E_ink_ESP8266::E_Ink_P8x16Str(INT8U y,INT8U x,char ch[]) 231 | { 232 | unsigned char c=0,j=0; 233 | while (ch[j]!='\0') 234 | //while (j<20) 235 | { 236 | c=ch[j]; 237 | if(x>172) 238 | { 239 | x=0; 240 | y-=2; 241 | } 242 | displayChar(y,x,c); 243 | x+=8; 244 | j++; 245 | } 246 | 247 | } 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | void E_ink_ESP8266::getCharMatrixData(INT16U UNICODE_Char) 256 | { 257 | INT8U c=0,i=0; 258 | c=UNICODE_Char-32; 259 | for(i=0;i<8;i++) 260 | { 261 | matrixdata[i+8]=~F8X16[(c<<4)+15-i]; 262 | 263 | } 264 | for(i=0;i<8;i++) 265 | { 266 | matrixdata[i]=~F8X16[(c<<4)+7-i]; 267 | } 268 | } 269 | 270 | 271 | 272 | 273 | 274 | 275 | /* 276 | display Two-Dimensional Code in the Eink screen: 277 | x:the X start address,X value can be 0 to 14; 278 | y:the Y start address, Y vlue can be 171 to 15; 279 | the charater erea is from x to x+6 in X position and from y to y-24 in Y position 280 | */ 281 | void E_ink_ESP8266::displayTwoDimensionalCode(INT8U x,INT8U y) 282 | { 283 | INT16U i; 284 | writeComm(0x11); /*data enter mode command */ 285 | writeData(0x05); /*set Y-mode:X increment and y decrement */ 286 | setPositionXY(x,x+7,y,y-24); 287 | converDimensionalCode(); 288 | writeComm(0x24); 289 | for(i=0;i<200;i++) 290 | { 291 | writeData(matrixdata_conver[i]); 292 | } 293 | } 294 | 295 | /* 296 | setPositionXY: 297 | Xs --> X start address 0~17 298 | Xe --> X end address 0~17 299 | Ys --> Y start address 0~171 300 | Ye --> Y end address 0~171 301 | */ 302 | void E_ink_ESP8266::setPositionXY(INT8U Xs, INT8U Xe,INT8U Ys,INT8U Ye) 303 | { 304 | writeComm(0x44);//set RAM x address start/end command 305 | writeData(Xs); 306 | writeData(Xe); 307 | writeComm(0x45);//set RAM y address start/end command 308 | writeData(Ys); 309 | writeData(Ye); 310 | writeComm(0x4E);//set RAM x address count to Xs; 311 | writeData(Xs); 312 | writeComm(0x4F);//set RAM y address count to Ys; 313 | writeData(Ys); 314 | } 315 | 316 | 317 | void E_ink_ESP8266::closeBump(void) 318 | { 319 | writeComm(0x22); 320 | writeData(0x03); 321 | writeComm(0x20); 322 | } 323 | 324 | 325 | void E_ink_ESP8266::writeComm(INT8U Command) 326 | { 327 | Eink_CS1_HIGH; 328 | Eink_DC_LOW; 329 | Eink_CS1_LOW; 330 | SPI.transfer(Command); 331 | Eink_CS1_HIGH; 332 | } 333 | 334 | void E_ink_ESP8266::writeData(INT8U data) 335 | { 336 | Eink_CS1_HIGH; 337 | Eink_DC_HIGH; 338 | Eink_CS1_LOW; 339 | SPI.transfer(data); 340 | Eink_CS1_HIGH; 341 | } 342 | 343 | 344 | 345 | void E_ink_ESP8266::configureLUTRegister(void) 346 | { 347 | INT8U i; 348 | INT8U init_data[]={ 349 | 0x00,0x00,0x00,0x55,0x00,0x00,0x55,0x55,0x00,0x55,0x55,0x55,0xAA,0xAA,0xAA,0xAA, 350 | 0x15,0x15,0x15,0x15,0x05,0x05,0x05,0x05,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00, 351 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 352 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 353 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 354 | 0x22,0xFB,0x22,0x1B,0x00,0x00,0x00,0x00,0x00,0x00,}; 355 | writeComm(0x32); //write data to LUT register 356 | for(i=0;i<90;i++) 357 | writeData(init_data[i]); 358 | } 359 | 360 | 361 | /*convert the matrix data: 362 | origital_data:it is a 8 bit data 363 | return value:16 bit data 364 | for example:origital_data is 10100010,and the return data will be 11001100 00001100*/ 365 | INT16U E_ink_ESP8266::convertData(INT8U Original_data) 366 | { 367 | INT8U i,j; 368 | INT8U data_L,data_H; 369 | INT8U temp; 370 | INT16U final_data; 371 | temp=Original_data; 372 | data_L=0; /* save low 4 bit convert result */ 373 | data_H=0; /* save high 4 bit convert result */ 374 | 375 | /*--------- convert low 4 bit--------*/ 376 | for(i=0;i<4;i++) 377 | { 378 | if(temp&(0x01<>8; //save data at matrixdata_conver[0]~matrixdata_conver[7] 409 | matrixdata_conver[i+8]=tempData; //save data at matrixdata_conver[8]~matrixdata_conver[15] 410 | } 411 | for(i=8;i<16;i++) //convert the last 8 byte data 412 | { 413 | tempData=convertData(matrixdata[i]); 414 | matrixdata_conver[i+8]=tempData>>8; //save data at matrixdata_conver[16]~matrixdata[23] 415 | matrixdata_conver[i+16]=tempData; //save data at matrixdata_conver[24]~matrixdata_conver[31] 416 | } 417 | 418 | } 419 | 420 | 421 | 422 | 423 | /* 424 | conver the two-dimensional data: 425 | convert the array dimensionalData[] data,and save convert result in array matrixdata_conver[]; 426 | */ 427 | void E_ink_ESP8266::converDimensionalCode(void) 428 | { 429 | int tempData; 430 | INT8U i,j; 431 | INT8U adder,Adder; 432 | 433 | for(j=0;j<4;j++) 434 | { 435 | adder=25*j; 436 | Adder=adder+25; 437 | for(i=adder;i>8; 441 | matrixdata_conver[i+Adder]=tempData; 442 | } 443 | 444 | } 445 | 446 | } 447 | 448 | E_ink_ESP8266 Eink; 449 | -------------------------------------------------------------------------------- /EinkESP8266.h: -------------------------------------------------------------------------------- 1 | /* 2 | 2012 Copyright (c) Seeed Technology Inc. 3 | 4 | Author: Zhangkun 5 | 6 | This library is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU Lesser General Public 8 | License as published by the Free Software Foundation; either 9 | version 2.1 of the License, or (at your option) any later version. 10 | 11 | This library is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | Lesser General Public License for more details. 15 | 16 | You should have received a copy of the GNU Lesser General Public 17 | License along with this library; if not, write to the Free Software 18 | Foundation, Inc.,51 Franklin St,Fifth Floor, Boston, MA 02110-1301 USA 19 | 20 | Converted from STM32 to ESP8266 by Catalin Batrinu 21 | 2016 Copyright (c) bcatalin@gmail.com 22 | 23 | */ 24 | 25 | #ifndef Eink_h 26 | #define Eink_h 27 | 28 | #ifndef INT8U 29 | #define INT8U unsigned char 30 | #endif 31 | #ifndef INT16U 32 | #define INT16U unsigned int 33 | #endif 34 | #ifndef INT32U 35 | #define INT32U unsigned long 36 | #endif 37 | 38 | #define CS 15 39 | #define DC 5 40 | 41 | #define Eink_CS1_LOW digitalWrite(CS,LOW) //{DDRD |= 0x40;PORTD &=~ 0x40;} 42 | #define Eink_CS1_HIGH digitalWrite(CS,HIGH)//{DDRD |= 0x40;PORTD |= 0x40;} 43 | #define Eink_DC_LOW digitalWrite(DC,LOW) //{DDRD |= 0x20;PORTD &=~ 0x20;} 44 | #define Eink_DC_HIGH digitalWrite(DC,HIGH) //{DDRD |= 0x20;PORTD |= 0x20;} 45 | 46 | 47 | class E_ink_ESP8266 48 | { 49 | public: 50 | void clearScreen(void); 51 | void refreshScreen(void); 52 | void getCharMatrixData(INT16U unicode_Char); 53 | void converCharMatrixData (void); 54 | void converChineseMatrixData(void); 55 | void displayChar(INT8U x1,INT8U y1,INT16U unicode_Char); 56 | void displayTwoDimensionalCode(INT8U x,INT8U y); 57 | void E_Ink_P8x16Str(INT8U y,INT8U x,char ch[]); 58 | private: 59 | INT8U matrixdata[32]; 60 | INT8U matrixdata_conver[200]; 61 | 62 | void writeComm(INT8U Command); 63 | void writeData(INT8U data); 64 | INT16U GTRead(INT32U Address); 65 | INT16U convertData(INT8U Original_data); 66 | void converDimensionalCode(void); 67 | 68 | void initEink(void); 69 | void closeBump(void); 70 | void configureLUTRegister(void); 71 | void setPositionXY(INT8U Xs, INT8U Xe,INT8U Ys,INT8U Ye); 72 | 73 | }; 74 | 75 | //extern E_ink_ESP8266 Eink_ESP8266; 76 | extern INT8U dimensionalData[]; 77 | #endif 78 | /********************************************************************************************************* 79 | END FILE 80 | *********************************************************************************************************/ 81 | 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP8266Eink 2 | 3 | This is the ESP8266 connectivity to my E-ink display. 4 | 5 | At the end the module will stay in low power and every 10 minutes will do: 6 | 7 | 1. Measure the battery level 8 | 2. Measure the temperature from DS18B20 9 | 3. Publish the temperature to the thinkspeak account 10 | 4. Publish the ip address, SDK version, B/G/N connectivity, it type as JSON over MQTT 11 | 5. Publish the temperature as JSON over MQTT on the temperature topic 12 | 6. Read the current time and show it on E-ink display 13 | 7. Go to sleep for another 10 minutes. 14 | 15 | The purpose of this is to have a mobile device that can be moved around the house to publish temperature to my chronothermostat (of course ESP8266 based). 16 | 17 | During the heating time device will update itself every minute otherwise every 10 minutes. 18 | 19 | The chronothermostat will have an PID controller that will receive temperature from my module. 20 | 21 | More details on myblog myesp8266.blogspot.com 22 | 23 | https://www.youtube.com/watch?v=vmFylHQmATc 24 | 25 | IMAGE ALT TEXT HERE 28 | 29 | -------------------------------------------------------------------------------- /einkLowPowerDS1820B.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Catalin Batrinu bcatalin@gmail.com 2016 Feb 3 | 4 | Read temperature from a DALLAS DS18B20 sensor and 5 | 1. Publish it to thingspeak.com 6 | 2. Send it as JSON ( along with other info) over MQTT to my BROKER 7 | 3. Display it on E-ink with info about time, VCC and IP address 8 | 9 | Then go to sleep for 10 minutes. Wake up again and start over. 10 | 11 | Connections: 12 | DS18B20 is connected to pin GPIO4 13 | E-ink Display is connected: 14 | BS1 - GND 15 | RES - VCC 16 | SDA - GPIO13 17 | SCL - GPIO14 18 | CS1(SS) - GPIO15 19 | D/C - GPIO5 20 | 21 | */ 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | ADC_MODE(ADC_VCC); 33 | 34 | unsigned int localPort = 2390; 35 | IPAddress timeServerIP; 36 | const char* ntpServerName = "time.nist.gov"; 37 | const int NTP_PACKET_SIZE = 48; 38 | byte packetBuffer[ NTP_PACKET_SIZE]; 39 | WiFiUDP udp; 40 | 41 | #define UTC_OFFSET 2 42 | 43 | #define wifi_ssid "XXXXXX" 44 | #define wifi_password "XXXXXXXX" 45 | #define mqtt_server "XXX.XXX.XXX.XXX" 46 | #define mqtt_port "XXXX" 47 | #define mqtt_user "XXXXXX" 48 | #define mqtt_password "XXXXX" 49 | #define dth_topic "/62/dth" 50 | #define device_status_topic "/62/device/status" 51 | 52 | #define DEBUG false 53 | #define Serial if(DEBUG)Serial 54 | #define DEBUG_OUTPUT Serial 55 | 56 | // Time to sleep (in seconds): 57 | const int sleepTimeS = 600; 58 | 59 | String apiKey = "....Your API KEY...."; 60 | const char* server = "api.thingspeak.com"; 61 | 62 | WiFiClient espClient; 63 | PubSubClient client(espClient); 64 | 65 | #define ONE_WIRE_BUS 4 // DS18B20 pin 66 | OneWire oneWire(ONE_WIRE_BUS); 67 | DallasTemperature DS18B20(&oneWire); 68 | float temp; 69 | 70 | E_ink_ESP8266 Eink_ESP8266; 71 | #define SPI_FREQ 1e4 72 | #define CS 15 73 | #define DC 5 74 | 75 | 76 | char dev_name[50]; 77 | char temperature[6]; 78 | char display_vcc[40]; 79 | char convertTempChar[50]; 80 | char json_buffer[512]; 81 | char json_buffer_status[512]; 82 | 83 | char my_ip_s[16]; 84 | char my_ip_display[40]; 85 | 86 | char show_time[9]; 87 | char show_time_display[40]; 88 | 89 | char hour_c[2]; 90 | char mnt_c[2]; 91 | char sec_c[2]; 92 | StaticJsonBuffer<512> jsonBuffer; 93 | JsonObject& root = jsonBuffer.createObject(); 94 | 95 | StaticJsonBuffer<512> jsonDeviceStatus; 96 | JsonObject& jsondeviceStatus = jsonDeviceStatus.createObject(); 97 | 98 | int wifi_reconn = 0; 99 | int mqtt_reconn = 0; 100 | 101 | char *ftoa(char *a, double f, int precision) 102 | { 103 | long p[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000}; 104 | 105 | char *ret = a; 106 | long heiltal = (long)f; 107 | itoa(heiltal, a, 10); 108 | while (*a != '\0') a++; 109 | *a++ = '.'; 110 | long desimal = abs((long)((f - heiltal) * p[precision])); 111 | itoa(desimal, a, 10); 112 | return ret; 113 | } 114 | 115 | void gettemperature() 116 | { 117 | int runs=0; 118 | do { 119 | DS18B20.requestTemperatures(); 120 | temp = DS18B20.getTempCByIndex(0); 121 | Serial.print("Temperature: "); 122 | Serial.println(temp); 123 | } while (temp == 85.0 || temp == (-127.0)); 124 | } 125 | 126 | 127 | 128 | void setup_wifi() { 129 | delay(10); 130 | // We start by connecting to a WiFi network 131 | Serial.println(); 132 | Serial.print("Connecting to "); 133 | Serial.println(wifi_ssid); 134 | 135 | WiFi.mode(WIFI_STA); 136 | WiFi.begin(wifi_ssid, wifi_password); 137 | 138 | while (WiFi.status() != WL_CONNECTED) { 139 | delay(500); 140 | Serial.print("."); 141 | wifi_reconn++; 142 | 143 | if(wifi_reconn == 30) 144 | ESP.deepSleep(sleepTimeS * 1000000);//10minutes 145 | } 146 | 147 | Serial.println(""); 148 | Serial.println("WiFi connected"); 149 | Serial.println("IP address: "); 150 | Serial.println(WiFi.localIP()); 151 | } 152 | 153 | void reconnect() { 154 | // Loop until we're reconnected 155 | while (!client.connected()) { 156 | Serial.print("Attempting MQTT connection..."); 157 | // Attempt to connect 158 | // If you do not want to use a username and password, change next line to 159 | // if (client.connect("ESP8266Client")) { 160 | if (client.connect(dev_name, mqtt_user, mqtt_password)) { 161 | Serial.println("connected"); 162 | } else { 163 | Serial.print("failed, rc="); 164 | Serial.print(client.state()); 165 | 166 | mqtt_reconn++; 167 | 168 | if(mqtt_reconn == 6) 169 | ESP.deepSleep(sleepTimeS * 1000000);//10minutes 170 | 171 | Serial.println(" try again in 5 seconds"); 172 | // Wait 5 seconds before retrying 173 | delay(5000); 174 | } 175 | } 176 | } 177 | 178 | 179 | 180 | // send an NTP request to the time server at the given address 181 | unsigned long sendNTPpacket(IPAddress& address) 182 | { 183 | Serial.println("sending NTP packet..."); 184 | // set all bytes in the buffer to 0 185 | memset(packetBuffer, 0, NTP_PACKET_SIZE); 186 | // Initialize values needed to form NTP request 187 | // (see URL above for details on the packets) 188 | packetBuffer[0] = 0b11100011; // LI, Version, Mode 189 | packetBuffer[1] = 0; // Stratum, or type of clock 190 | packetBuffer[2] = 6; // Polling Interval 191 | packetBuffer[3] = 0xEC; // Peer Clock Precision 192 | // 8 bytes of zero for Root Delay & Root Dispersion 193 | packetBuffer[12] = 49; 194 | packetBuffer[13] = 0x4E; 195 | packetBuffer[14] = 49; 196 | packetBuffer[15] = 52; 197 | 198 | // all NTP fields have been given values, now 199 | // you can send a packet requesting a timestamp: 200 | udp.beginPacket(address, 123); //NTP requests are to port 123 201 | udp.write(packetBuffer, NTP_PACKET_SIZE); 202 | udp.endPacket(); 203 | } 204 | 205 | void setup() 206 | { 207 | Serial.begin(115200); 208 | double vcc = ESP.getVcc(); 209 | Serial.println(vcc); 210 | Serial.println(vcc/1000); 211 | 212 | sprintf(dev_name, "ESP_%d", ESP.getChipId()); 213 | pinMode(DC,OUTPUT); 214 | pinMode(CS, OUTPUT); 215 | SPI.begin(); 216 | SPI.setHwCs(true); 217 | 218 | Eink_ESP8266.clearScreen();// clear the screen 219 | Eink_ESP8266.E_Ink_P8x16Str(14,8," Wellcome! I am "); 220 | Eink_ESP8266.E_Ink_P8x16Str(8,8," ESP8266 with E-ink"); 221 | Eink_ESP8266.E_Ink_P8x16Str(4,8,"by bcatalin@gmail.com"); 222 | Eink_ESP8266.E_Ink_P8x16Str(0,8,"Wait! Connecting....."); 223 | Eink_ESP8266.refreshScreen(); 224 | 225 | setup_wifi(); 226 | client.setServer(mqtt_server, mqtt_port); 227 | client.connect(dev_name, mqtt_user, mqtt_password); 228 | 229 | if (!client.connected()) 230 | { 231 | reconnect(); 232 | } 233 | client.loop(); 234 | 235 | 236 | IPAddress my_ip_addr = WiFi.localIP(); 237 | sprintf(my_ip_s, "%d.%d.%d.%d", my_ip_addr[0],my_ip_addr[1],my_ip_addr[2],my_ip_addr[3]); 238 | jsondeviceStatus ["device_name"] = dev_name; 239 | jsondeviceStatus["type"] = "dth"; 240 | jsondeviceStatus["ipaddress"] = String(my_ip_s).c_str(); 241 | jsondeviceStatus["bgn"] = 3; 242 | jsondeviceStatus["sdk"] = ESP.getSdkVersion();//"1.4.0"; 243 | jsondeviceStatus["version"] = "1"; 244 | jsondeviceStatus["uptime"] = 0; 245 | 246 | jsondeviceStatus.printTo(json_buffer_status, sizeof(json_buffer_status)); 247 | client.publish(device_status_topic, json_buffer_status , false); 248 | Serial.println(json_buffer_status); 249 | 250 | 251 | 252 | gettemperature(); 253 | 254 | root["device_name"] = dev_name; 255 | root["type"] = "dth"; 256 | root["temperature"] = String(temp).c_str(); 257 | 258 | root.printTo(json_buffer, sizeof(json_buffer)); 259 | client.publish(dth_topic, json_buffer , false); 260 | Serial.println(json_buffer); 261 | 262 | //publish 263 | if (espClient.connect(server,80)) { // "184.106.153.149" or api.thingspeak.com 264 | String postStr = apiKey; 265 | postStr +="&field1="; 266 | postStr += String(temp); 267 | //postStr +="&field2="; 268 | //postStr += String(0); 269 | //postStr +="&field3="; 270 | //postStr += String(0);//String(bmp.pressureToAltitude(SENSORS_PRESSURE_SEALEVELHPA, event.pressure)); 271 | postStr +="&field4="; 272 | postStr += String(vcc); 273 | postStr += "\r\n\r\n"; 274 | 275 | espClient.print("POST /update HTTP/1.1\n"); 276 | espClient.print("Host: api.thingspeak.com\n"); 277 | espClient.print("Connection: close\n"); 278 | espClient.print("X-THINGSPEAKAPIKEY: "+apiKey+"\n"); 279 | espClient.print("Content-Type: application/x-www-form-urlencoded\n"); 280 | espClient.print("Content-Length: "); 281 | espClient.print(postStr.length()); 282 | espClient.print("\n\n"); 283 | espClient.print(postStr); 284 | espClient.stop(); 285 | } 286 | 287 | 288 | udp.begin(localPort); 289 | //get a random server from the pool 290 | WiFi.hostByName(ntpServerName, timeServerIP); 291 | 292 | sendNTPpacket(timeServerIP); // send an NTP packet to a time server 293 | // wait to see if a reply is available 294 | delay(1000); 295 | 296 | int cb = udp.parsePacket(); 297 | if (!cb) { 298 | Serial.println("no packet yet"); 299 | } 300 | else { 301 | Serial.print("packet received, length="); 302 | Serial.println(cb); 303 | // We've received a packet, read the data from it 304 | udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer 305 | 306 | //the timestamp starts at byte 40 of the received packet and is four bytes, 307 | // or two words, long. First, esxtract the two words: 308 | 309 | unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); 310 | unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); 311 | // combine the four bytes (two words) into a long integer 312 | // this is NTP time (seconds since Jan 1 1900): 313 | unsigned long secsSince1900 = highWord << 16 | lowWord; 314 | 315 | // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: 316 | const unsigned long seventyYears = 2208988800UL; 317 | // subtract seventy years: 318 | unsigned long epoch = secsSince1900 - seventyYears; 319 | 320 | int hour_i = ((epoch % 86400L) / 3600) + UTC_OFFSET; 321 | 322 | if (hour_i >= 24) 323 | hour_i = hour_i - 24; 324 | 325 | Serial.println(hour_i); 326 | 327 | sprintf(hour_c,"%s:", String(hour_i).c_str() ); 328 | 329 | if ( ((epoch % 3600) / 60) < 10 ) 330 | sprintf(mnt_c,"0%s:",String((epoch % 3600) / 60).c_str() ); 331 | else 332 | sprintf(mnt_c,"%s:",String((epoch % 3600) / 60).c_str() ); 333 | 334 | 335 | if ( (epoch % 60) < 10 ) 336 | sprintf(sec_c, "0%s",String(epoch % 60).c_str() ); 337 | else 338 | sprintf(sec_c, "%s",String(epoch % 60).c_str() ); 339 | 340 | sprintf(show_time,"%s%s%s",hour_c, mnt_c, sec_c ); 341 | Serial.println(show_time); 342 | } 343 | 344 | 345 | 346 | //show 347 | Eink_ESP8266.clearScreen();// clear the screen 348 | 349 | //Temperature 350 | sprintf(temperature,"Temperature: %s C",ftoa(convertTempChar,temp,2)); 351 | Eink_ESP8266.E_Ink_P8x16Str(14,8, temperature); 352 | 353 | //Battery 354 | sprintf(display_vcc,"Battery: %s V", ftoa(convertTempChar,vcc/1000,2)); 355 | Eink_ESP8266.E_Ink_P8x16Str(9,8, display_vcc); 356 | 357 | //My IP 358 | sprintf(my_ip_display,"My IP: %s", String(my_ip_s).c_str()); 359 | Eink_ESP8266.E_Ink_P8x16Str(4,8, my_ip_display); 360 | 361 | sprintf(show_time_display,"Time: %s",show_time); 362 | Eink_ESP8266.E_Ink_P8x16Str(0,8, show_time_display); 363 | 364 | Eink_ESP8266.refreshScreen(); 365 | 366 | ESP.deepSleep(sleepTimeS * 1000000);//10minutes 367 | } 368 | 369 | 370 | void loop() 371 | { 372 | //Nothing to do here.... 373 | } 374 | --------------------------------------------------------------------------------