The Pilogger project [1] [2] centralize the data of several sensors around the house. It is based on Raspberry pi and it is kept plugged on the network with a backup battery. The device is quite large and not the most elegant.
This is tests about using the famous ESP8266 and low consumption Sharp Memory LCD. Is it possible to have a compact remote display battery powered ?
The station runs Java and the code has to be update. NodeMCU and LUA is chosen for the ESP8266 mainly because it is the first project I started on this tiny wifi chip.
I'm still thinking about the different ways to make a clean and nice looking enclosure for the 4.4" display. Meanwhile I made a very simple aluminium frame, which is not so bad in my opinion.
I have put some unconnected plated holes on the PCB is order to fix it to a future mount, then some small copper plates do the job fairly well:
The frame is just an aluminium plate, it probably needs a bit more of polishing :
With these 3 AAA batteries and a 2 minutes refresh period, it lasts around a week. Some code tweaking is probably still possible on the ESP8266 side, and I'm sure I can adjust the refresh rate according to the time of the day. (do I need a 2 minutes refresh rate at 03:00 am ?)
First of all, a big thank you to @oshpark. I heard plenty of good things about them, and for a first experience, I'm really satisfied ! The boards took exactly 20 day from the kicad file upload to my french mail box, and the quality is spotless. Very nice, keep this good work really !
After ordering the board, I was a bit worried about a via a bit close to a track:
But it went very well !
I populated one board and stick it behind the LCD screen as I planned. That's why I put the components only in one side, even if as a counter part the board is larger.
Next step is to make a nice frame/case and make two new instance !
The project prototype works reasonably well. The ESP wakes up every 5 mins to refresh the screen. It connects to the wifi hotspot, open a socket with the pilogger, refresh the screen and go to deep sleep. The hotspot connection process lasts around 5 seconds, event with fix IP. I should investigate to shorter that. However it stayed up for more than a week with a big 3200 mAh battery.
By looking at the tests I made, I have to make something simpler (indeed). Java uploading an image using FTP which is translated to hex by a PHP script, to be received on the ESP8266 and interpreted in LUA to be sent to the SPI screen...
Sockets
Why use the web server ? I should focus, I digress. It could be nice to have a LCD screen showing whatever an image from internet, but it's another project.
From what I have, I could simplify by open a socket server on the Pilogger Java program and connect to it with the ESP to retrieve the image data.
On java side I not used sockets often, but it is not so complicated.
serverServer = new ServerSocket(9999);
clientSocket = serverServer.accept();
inputStream = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
outputStream = new PrintStream(clientSocket.getOutputStream());
while (true) {
line = inputStream.readLine();
if (line.contains("LCD")) {
outputStream.write(capture());
break;
}
}
clientSocket.close();
On port 9999, if I receive the string "LCD", I send the raw data for the LCD. it is even nicer as I could directly send the bytes needed by the LCD, in the correct format. All the processing is done in Java on the raspberry pi. What still to be done on the ESP is the socket connection, and the CS line logic. The LUA script is as short as :
-- GPIO 2 is the CS line of the LCD SPI connection
gpio.mode(2, gpio.OUTPUT)
gpio.write(2, gpio.LOW)
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 50, spi.HALFDUPLEX)
srv = net.createConnection(net.TCP, 0)
srv:on("receive", function(sck, c)spi.send(1, c)end)
srv:on("connection", function(sck, c)
print("socket connected")
sck:send("LCD\n")
gpio.write(2, gpio.HIGH)
end)srv:on("disconnection", function(sck, c)
gpio.write(2, gpio.LOW)
print("socket disconnected")
wifi.sta.disconnect()
end)srv:connect(9999, "192.168.xxx.xxx")
And it works really well, the screen is refreshed in about 100ms !
The 'memory' LCD from sharp are somehow fascinating. Their main advantage is the low power consumption, but they are one of the rare passive reflective monochrome LCD. They are nearly as readable on sun light as the eink displays. I first had this module http://www.ebay.com/itm/201596712057, where the board had to be fixed (the ground does not cross from one side to the other... Cheap products... ) I finally opt for the larger 4.4" 320x240 version (http://www.digikey.com/product-detail/en/sharp-microelectronics/LS044Q7DH01/425-2910-ND/5054070) .
NodeMCU speaks SPI
LUA SPI module is nice, it is possible to use the hardware SPI at high speed. But I did not found a way to invert the CS line logic neither to send little endian bytes as the screen require. I had to use a GPIO for the ChipSelect line and do some trick to invert the byte reading:
gpio.mode(2, gpio.OUTPUT)
gpio.write(2, gpio.LOW)
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, 8, 400, spi.HALFDUPLEX)
function printLine(line_nb)
gpio.write(2, gpio.HIGH)
spi.send(1, 128)
spi.send(1, bit_invert(line_nb+1))
for i=0,39 do
spi.send(1, array[i])
end
spi.send(1, 0)
spi.send(1, 0)
gpio.write(2, gpio.LOW)
endfunction clear()
gpio.write(2, gpio.HIGH)
spi.send(1, 32)
spi.send(1, 0)
gpio.write(2, gpio.LOW)
endfunction bit_invert(byte)
inv = 0if (bit.isset(byte, 0)) then inv = bit.set(inv, 7) endif (bit.isset(byte, 1)) then inv = bit.set(inv, 6) endif (bit.isset(byte, 2)) then inv = bit.set(inv, 5) endif (bit.isset(byte, 3)) then inv = bit.set(inv, 4) endif (bit.isset(byte, 4)) then inv = bit.set(inv, 3) endif (bit.isset(byte, 5)) then inv = bit.set(inv, 2) endif (bit.isset(byte, 6)) then inv = bit.set(inv, 1) endif (bit.isset(byte, 7)) then inv = bit.set(inv, 0) endreturn inv
end
Performances
Putting things all together, it works. But it is slow. Very slow. But it is not surprising. I used several heavy functions such as string operation string.gmatch(c, "%S+") and array[index] = encoder.fromHex(i).
Refreshing the entier screen takes approximately 30 seconds... Not really conceivable for a battery application. We have to simplify that!
This is a big question, where to start with the ESP8266. There is the official SDK path, for the brave. There is the Arduino, Espruino... Well, I tried NodeMCU. Starting with this page https://nodemcu.readthedocs.io/en/master/, there is a lot explained to start from scratch.
The raspberry pi regularly send datasets to an online web server using FTP, a solution could be so send an image as well and retrieve it on the ESP from internet. But it is rather difficult to interpret an image file directly on the ESP. So a PHP script could convert an image file to raw data. I realize the online serve does not like sending real raw bytes, so I had to convert bytes in their hex ascii form.
Now it is time to get these data on the ESP. In LUA there is a high level HTTP client to directly do GET over http. The problem is it is limited to 1400 bytes. At this point I was a bit frustrated, my image is monochrome 320x240 pixels, 9600 bytes.
srv = net.createConnection(net.TCP, 0)
srv:on("receive", function(sck, c)print(c)end)
srv:on("connection", function(sck, c)
-- Wait for connection before sending.
sck:send("GET /pilogger/getPNG.php HTTP/1.1\r\nHost: muth.inc.free.fr\r\nConnection: keep-alive\r\nAccept: */*\r\n\r\n")
end)srv:connect(80,"muth.inc.free.fr")
At this point the ESP receive all the data by blocks of ~1400 bytes ! We can reconstruct the bytes array from the hex chars with the 'encoder' LUA module :
for i in string.gmatch(c, "%S+") do
array[index] = encoder.fromHex(i)
print(array[index])
index = index +1
end
Hey, this project is awesome! I'm considering using the same 4.4" memory LCD screen in a project of mine. I want to hook it up to a Raspberry Pi Zero. What did you use to break out the ribbon cable that comes out of the display? (I'm new to this stuff—sorry!)
Hey, this project is awesome! I'm considering using the same 4.4" memory LCD screen in a project of mine. I want to hook it up to a Raspberry Pi Zero. What did you use to break out the ribbon cable that comes out of the display? (I'm new to this stuff—sorry!)