create new tag
view all tags

Seven Segment Display and Keypad

The Seven Segment Display and its TM1637 controller

There is a nice and simple seven segment display controlled by a TM1637 controller, which can be used e.g. as a clock display. It provides 4 digits and a colon dividing digits 1 and 2 from digits 3 and 4, such that the first two digits can be used to display hours, the last two digits to display minutes and the colon can be set blinking at a 1 Hz rate. Of course you can also use it for other purposes like displaying the voltage values of a voltmeter.

seven_seg_front.png seven_seg_back.png

As can be seen from the back view of the module, interfacing to the ESP32 is pretty simple. Here are the connections I use:

Pins on display module Pins on ESP32
VCC 3.3V
The data sheet for the TM1637 controller can be found at https://www.mcielectronics.cl/website_MCI/static/documents/Datasheet_TM1637.pdf.

The TM1637 uses a proprietary 2-wire serial protocol with a data line (dio) and a clock line.

Exercise 1:

Carefully read the data sheet.

Write a driver implementing the serial protocol. Implement the driver as class TM1637 with the following methods:

  • start_transfer: implements the start sequence (dio going low when clk is high)
  • stop transfer: implements the "end of transfer" sequence (dio going high when clk is high)
  • write_bit: write a single bit: with clk low, set dio to the bit value, then send a pulse (high followed by low) on the clk pin
  • write byte: send 8 bits. After the eights bit, check the acknowledge signal. Switch dio to input, check acq, switch dio back to output after the falling edge of the nineth clock pulse
  • display on: switch the display on: start_transfer, send display_on command, stop transfer
  • create a table with the led setting of the seven segments for all hex digits and a clear digit (all segments off). dp means decimal point, which is only used on the second digit, where it controls the following colon.
  F |   | B      dp,g,f,e, d,c,b,a: the data byte
  E |   | C
  • write_digit(digit_num,digit,colon=False): sets digit number digit_num to the value digit. If colon is true and the digit number is 1 (start counting from zero) the switch the colon on.
  • clear_digits(colon=False): clear all digits. Only the colon stays on if colon == True
  • write_hex(number,colon=False): write a hex number to the display
  • write_dec(number,colon=False): write a decimal number to the display.
Write a test routine that exercises all the above methods

Exercise 2:

Read the current time from the ntp and implement a clock displaying hours and minutes. Make the colon blink at a 1 Hz rate.

The Keypad

The keypad has a total of 16 switches. These are connected to 8 pins organized as 4 rows and 4 columns.

keypad.png 4X4-Keypad-Schematic.png
The job will be to find out which row makes a connection to which column in order to find out which switch is closed. This can be done by connecting e.g. the 4 row pins to GPIO outputs and the 4 column pins to GPIO inputs with pull-ups.

Set the first row pin to low and check on each column pin if you read a zero. If you do, you have found the switch closed. If not, continue the same procedure on the other row pins.

I made the connections as follows:

Row 1 D7: GPIO 23
Row 2 D6: GPIO 19
Row 3 D5: GPIO 18
Row 4 D0: GPIO 26
Col 1 D4: GPIO 16 on WROVER: GPIO 25 with patch to D4 on CPU board
Col 2 D3: GPIO 17 on WROVER: GPIO 4 with patch to D3 on CPU board
Col 3 D2: GPIO 21
Col 4 D1: GPIO 22

Exercise 1:

Scan the keyboard in intervals of 100 ms and print the key that is pressed. This will result in printing the key as long as it is pressed.

Exercise 2:

Wait until the key is released and only then print the key. This will result in a single key value for each button press.

Exercise 3:

Write a CircularBuffer class in which you can keep key presses. This will allow to read the keypad completely asynchronously (see exercise 4).

The CircularBuffer class should implement a buffer of 32 elements with the following methods:

  • write: add an element to the end of the buffer. Check if the buffer is full before writing and set the overrun flag if this is the case
  • available: check if new data have arrived in the buffer
  • read: read data from the buffer if it is not empty
  • is_full: tells if the buffer is full
  • overrun: tells if an overrun error has occurred in the past
  • clr_overrun: clear the overrun flag
  • flush: clears the buffer
Write a test script exercising the CircularBuffer class.

Exercise 4:

Read the keypad in an interrupt driven routine. Keep the pressed keys in the circular buffer written in exercise 3.

Write a test program that starts the interrupt driven keypad driver and reads data from the circular buffer in rather large intervals (e.g. every 5s or 10s)

Topic attachments
I Attachment History Action Size Date Who Comment
PNGpng 4X4-Keypad-Schematic.png r1 manage 14.6 K 2021-01-20 - 21:58 UliRaich  
PNGpng keypad.png r1 manage 115.6 K 2021-01-20 - 21:41 UliRaich  
PNGpng seven_seg_back.png r1 manage 117.4 K 2021-01-20 - 21:40 UliRaich  
PNGpng seven_seg_front.png r1 manage 115.2 K 2021-01-20 - 21:40 UliRaich  
Edit | Attach | Watch | Print version | History: r7 < r6 < r5 < r4 < r3 | Backlinks | Raw View | Raw edit | More topic actions
Topic revision: r7 - 2021-01-24 - UliRaich
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2021 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback