Showing posts with label LCD. Show all posts
Showing posts with label LCD. Show all posts

Saturday, September 20, 2025

More wireless temperature displays: Low power LCD thermometer and ESP32 web server

Introduction

Previously, I had developed a simple wireless temperature display system using a network of battery-powered transmitters which transmit the temperature from their current location using low-cost 433MHz AM transmitters spread around the house to some custom-made display units, one of which was documented here: Wireless temperature display with bare glass LCDs

The transmitters were all built inside 4xAA battery boxes which had been modified to accept 2xAA batteries to power the stripboard circuit which occupied the other half. These units didn't have any display capability, but I thought it would be better if they did.

A small number of PIC microcontrollers have built-in LCD drivers, and after connecting an LCD to one on breadboard, I found that it was possible to achieve power consumption of only 20uA so it should be possible to have a display on it and still have a battery life measured in years. The PIC16LF1936 was used in this project.

All code and the PCB design for the transmitter can be found on GitHub here: wireless-thermometer-transmitter-dgl-lcd

All code and the PCB design for the receiver can be found on GitHub here: wireless-thermometer-display-esp32

The display

The DGL-0401YG-4EH LCD from the Wireless temperature display with bare glass LCDs would also be used here as it's a fairly large size and it also fits well in the space of 3xAA batteries.

Wireless communications

From the previous project: The 433MHz transmission system is a very simple system which does not define a protocol and is unidirectional, which means an unlimited amount of receivers can be added without any changes needing to be made to the firmware in the transmitters. The task of decoding and receiving the data was passed off to an NKM2401 to save time and due to reasons relating to the design of the temperature transmitters which was done previously, but it wouldn't be difficult to implement this directly in the PSoC...

The previous transmitters used a PICAXE microcontroller which included built-in support for the same protocol used by the NKM2401. No PICAXE microcontrollers have built-in LCD drivers, so that immediately ruled out the use of one of those. It would also be impractical to use an NKM2401 as that chip had no power saving optimisations and space was at a premium anyway. The only solution would be to reverse-engineer the protocol.

I captured a number of packets from the output of an NKM2401 with a logic analyser

From inspection of the waveform, we can see that each half bit is indeed exactly 200us and the packet format is as follows:

  • One-byte preamble of 0x00
  • Constant byte of 0x09
  • 8 data bytes in the same order as the input bytes, with no processing, scrambling or further encoding
  • CRC – and this is indeed a CRC not a simple checksum

I used the CRC RevEng program to determine that the CRC polynomial is 0xB3.

A more detailed explanation of my reverse engineering efforts can be found here.

I initially implemented the transmit sequence using C for loops, but this didn't work and the waveform showed that there was a longer delay between bytes than between bits, and the overhead of the C for loop was enough to make a difference at 4MHz. The solution was to use the rlf instruction in inline assembly as explained in the link above. The rlf instruction also makes implementing the CRC calculation much simpler than the typical C algorithm which uses a big lookup table.

Once implemented correctly, my PIC16LF1936-based transmitter project worked perfectly with the various receivers in the system.

The transmitter PCB

Photo of rear of PCB

I designed the PCB to fit in the same space as 3xAA batteries, so that it would be possible to use a modified battery box as the enclosure. I also tried to track out a PCB antenna but it didn't work very well and ultimately a wire was needed for this function.

It is difficult to find battery boxes which take 5xAA batteries, and a 6xAA battery box would just be too big, so I considered solutions which would allow the use of a 4xAA battery box. The first idea was to find a half AA sized battery and use two of them in series, but they were all 3.6V primary lithium types and very expensive anyway. How about a 3.6V primary lithium AA battery? Also very expensive. Eventually, I settled on using 3.2V rechargeable LiFePO4 14500 cells, which are still more expensive than alkalines, but less expensive than primary lithium and can also be recharged once the 600mAh capacity is depleted. They also have a much flatter discharge voltage curve than alkalines so the contrast of the LCD will be consistent over time.

600mAh doesn't sound like much but the voltage is much higher than a regular alkaline AA, so the volumetric energy density is similar. The specific energy (energy per unit mass) of the LiFePO4 cell is incidentally much higher than NiMH or alkaline, and the LiFePO4 cell weighs much less than an alkaline or NiMH cell. I did test the cell and it delivered the claimed capacity. The power consumption of the transmitter is so low that the 600mAh capacity should power it for over 5 years if the backlight is not used frequently.

PCB with battery
Assembled transmitter

The receiver

This used the same PCB as the improved version of my ESP32-based Octopus Tracker Unit Rate Display project. Ultra-low power consumption wasn't a requirement and reducing the effort was more of a priority, so an NKM2401 was used for reception duties with the output connected to the ESP32's UART instead of implementing the decoding in the ESP32.

The display code was also reused from the ESP32-based Octopus Tracker Unit Rate Display project, but slightly modified so that the number was only displayed to one decimal place when the temperature was a single-digit positive value. This display code was combined with the Espressif's ESP-IDF webserver example, suitably modified so that requests to a specific page on the webserver would have the live temperatures injected into it, or unknown in the case of temperature IDs which hadn't been received since the last power cycle for correct handling in Home Assistant.

Receiver PCB

After some testing, it was found that the temperatures would stop updating in Home Assistant after a few days unless the receiver was power cycled. Examination of the code revealed that the cause was obvious and that was the wifi connection code in the webserver example was only a very basic implementation which wouldn't reconnect if the connection ever dropped. I added the much more elaborate wifi connection code used previously in the ESP32-based Octopus Tracker Unit Rate Display project and this seems to have resolved the problem and the connection is very reliable now.

The receiver is working well in Home Assistant and each temperature sensor works like any other sensor would.

History graph from Home Assistant

Saturday, July 20, 2024

Insertomatic 6000 Part 1: Assembling some RF modulators into a case and making a controller

The Insertomatic 4000 is a one-off four-channel teletext generator by Alistair Cree designed to feed four different teletext services to a number of TVs. It contains four Raspberry Pi Zeros, four surplus RF modulators, and some switching electronics to allow the audio to be independently switched. My goal is to make an improved version which is tailored to my requirements, with the addition of two external video inputs that would allow two external sources to be turned into RF channels in addition to four channels generated by the Pis. The device will feature some additional controls on the front for RF channel and audio programme selection - the audio programme selection will be used for my device's added focus on internet radio playback.

RF modulators

The RF modulators will be sourced from Sky boxes, as I already know how to use these and it's a fairly abundant source, which means I'll be able to get several identical modulators for the project.

I posted on Freegle and Freecycle to ask for boxes, and this was quite effective.

Photo of Sky boxes

There were a couple of issues with the Sky boxes though; the first was that the RF modulator had been removed from the later boxes and replaced with a connector for the optional Sky IO Link, but this was a fairly obvious problem and could be avoided once I had learned from reliable sources that the presence of the WPS button on the front can be used to identify the boxes with this feature removed when only a photo of the front was available. The only frustration was that these boxes were super common, as they'd been the standard for over 10 years by this point.

The far less obvious problem was that in the DRX890, Amstrad (who else?) had discovered that they could cut costs by placing all the components for the RF modulator onto the main board instead of having them on a separate module. This meant that it was no longer practical to remove the modulator, as doing so would require the cutting of a multi-layer PCB without shorting any internal layers, then adding wires to tap into the various parts of the circuit, and this would just be too difficult and fragile.

DRX890 SKy Box RF modulator

Eventually, I had acquired just enough suitable Sky boxes and removed their modulators. The modulator came out quite easily from the Pace box so that survived, whereas the Amstrad boxes required a lot more heat, presumably because they didn't use thermal reliefs on the internal layers of the main PCB, and were destroyed.

Picture of 5 modulators

In the past, I turned this Arduino-based modulator project into a more permanent stripboard assembly, but I had been disappointed by the noisy quality of the picture compared to when the modulator was in a Sky box. To address this issue, I bought some tiny 0402 size ferrite beads, and added one inline with the power connection to the modulator. This delivered a significant reduction in noise, so I proceeded to modify all the modulators, opening them up and cutting the track from the +5V pin before adding the ferrite bead inline. With that done, the modulators were then ready for use.

Controller

The controller was to be responsible for programming the frequency of all six modulators and displaying 'now playing' info from each of the Raspberry Pis on a HD44780-compatible LCD which would be fitted to the front panel. Not a huge amount of processing power needed then, but the unusual requirement of controlling six I2C devices with the same address and having four UARTs meant that choosing a microcontroller wouldn't be easy. I decided to go with the Raspberry Pi Pico because its unique PIO feature would allow the implementation of the UARTs. They would also be able to handle the unusual I2C requirement, but I ultimately decided to just use a software bit-banging approach for that since the actual data is very simple and infrequent.

PCB

I used matrix board for the circuit. I fitted two switching regulator boards, one of which would power all the Raspberry Pis, and the other of which would power just the modulators through a separate linear regulator, minimising the possibility of noise entering the modulators from the Pis. I then added the Pi Pico along with headers for connecting the modulators.

The only unusual aspect of the circuit was the addition of a -5V rail. This would allow the HD44780-compatible LCD to operate from the 3.3V supply of the Pi Pico (regulator on board the Pi Pico), which creates a need for a negative voltage to drive the contrast pin. This avoids needing a 5V level shifter for the LCD as would be required if powering it from 5V, and the negative voltage would have been needed anyway since this particular 24x2 character LCD needs about -6V revative to Vdd to get good contrast as it's an extended temperature range LCD.

I2C

Since all six modulators would always be programmed at the same time, I decided that the best approach would be to share the same clock pin for all of them and just have separate data pins, meaning a total I/O requirement of 7 pins.

With AI being the trendiest thing in tech right now, I asked ChatGPT to write a code example for bit-banging the I2C bus for one device. I tested it and it actually worked first time, programming the modulator as expected. I noticed a flaw in the code which was that it drove the pin high and low, rather than only driving the pin low when needed and making it high-Z at other times, which we'd probably get away with since the slave doesn't appear to use clock stretching, but it's not really 'proper'. I pointed out this mistake to ChatGPT and it immediately produced correct code. I expanded the code myself to write different data to each of the modulators, and this also worked as expected.

At this point, I had just a bare minimum demo which proved that the modulators could be programmed and would work as expected. I still needed to add the user interface for programming them, the ability to remember the setting when turned off, and the display of 'now playing' info, but all that could come later.

Testing all the modulators together

I daisy-chained the six modulators, and they all worked as expected. I was aware that these modulators have a little loop-through gain, and with six in series, this could mean quite a significant difference between the strongest and weakest channel. I used an RTL-SDR to measure the strength of each channel, and found that the loop-through gain was exactly 6dB, so a 6dB attenuator would be needed on the input of each modulator to make them all have the same strength. I also decided to split them into two sets of three with a splitter in reverse to combine them, ensuring that the signal wouldn't travel through too many attenuation and amplification cycles before reaching the output.

Mechanical design

The project will ultimately go inside a rack-mount case, but to keep all the components in place, a laser cut panel was made.

Photo of the main components mounted on the laser cut panel

A very basic setup was made; the video inputs of the modulators were connected to the Pis but the audio was not. The picture became noisy once the Pi Zeros were powered up; almost certainly due to the setup of the ground paths, which will need to be improved to ensure that the Pis all have a good return path which isn't shared with the modulators.

Next steps

The next steps from a mechanical perspective will be to cut holes for all the connectors and buttons in the front and back panels of the case using the CNC.

From an electrical perspective, the next step to work on is the audio switching. The circuits for this will go in the empty space on the matrix board.

For the controller, the next feature to add is memory for the set channel numbers.

Monday, December 27, 2021

Wireless temperature display with bare glass LCDs

First completed: 2018

Introduction

I had previously developed a simple wireless temperature display system using a network of battery-powered transmitters which transmit the temperature from their current location using low-cost 433MHz AM transmitters spread around the house to a custom-made display unit. I wanted to add a second display to show the temperatures from the same transmitters in another location, and also wanted to take the opportunity to experiment with the LCD drivers that are built into selected Cypress PSoC microcontrollers.

The PSoC 4 is a microcontroller based around the ARM Cortex-M0 processor core which features a comprehensive range of built-in peripherals and a small amount of programmable logic.

The LCD

The DGL-0401YG-4EH LCD was included in the Kemo Electronic S043 "lucky bag" of surplus displays and likely originated as a heating controller display. Such a supply method would be completely inappropriate for a commercial product due to no guarantee of supply, but for a hobby project it's fine.

the LCD has 4 common pins and 12 segment pins, meaning it is designed for 1/4 duty cycle multiplexed operation. The waveforms for multiplexing an LCD are more complex than for multiplexing LED displays because intermediate voltages are required and DC bias must be eliminated to avoid long-term damage to the LCD, so they're usually generated using a dedicated driver IC or by an LCD driver peripheral built into certain microcontrollers.

The PSoC's LCD driver is capable of up to 1/8 duty or 1/16 duty depending on the part chosen, so driving this LCD is no problem. In theory, multiple 1/4 duty LCDs could be wired for 1/8 or 1/16 duty to save I/O compared to using 1/4 duty, but there's a catch! The lower the duty (higher the denominator), the smaller the viewing angle becomes, which means that the LCD only has good contrast over a smaller range of viewing positions.

Ultimately, due to the amount of I/O available on the CY8CKIT-042, 1/8 duty was chosen as a good compromise between the viewing angle and number of I/O used. Some of the heating-related symbols were unused, so not all of the segments needed to be connected either. The segment lines for the °C symbol could also be commoned to save a further I/O line as there would be no need to control these symbols individually.

The one button added to the front switches the backlight brightness between three levels.

Wireless communications

The 433MHz transmission system is a very simple system which does not define a protocol and is unidirectional, which means an unlimited amount of receivers can be added without any changes needing to be made to the firmware in the transmitters. The task of decoding and receiving the data was passed off to an NKM2401 to save time and due to reasons relating to the design of the temperature transmitters which was done previously, but it wouldn't be difficult to implement this directly in the PSoC. For debugging, the 3.5mm jack in the bottom left corner can be connected to a computer serial port with a PICAXE programming cable and serves the dual purpose of allowing the monitoring of the received packets and the generation of test packets.

The data is transmitted in 8 byte packets. The first byte represents the ID of the temperature transmitter and is unique to each transmitter; the display unit uses this ID to decide which of the four LCDs should be updated with the newly received temperature. The second byte represents the type, allowing for future expansion with types other than temperature (e.g. humidity). Bytes 3 and 4 contain the temperature, bytes 5 to 7 are unused/reserved, and byte 8 is a very simple checksum which augments the error detection already implemented in the NKM2401.

Large dot matrix clock, timer and scrolling message display

First completed: August 2014. Additional work carried out late 2025/early 2026. Introduction Previously, the author had made a very small ...