Components

This page describes the components used in the project.

  1. M95080-RMN6TP EEPROM
  2. PEC12R rotary Encoder
  3. 3X4 Matrix Keypad
  4. ST7565 LCD
  5. Tower Pro SG90 servo motor
  6. SHT40 temperature and humidity sensor

EEPROM

We are using the M95080-RMN6TP SPI EEPROM: http://www.st.com/resource/en/datasheet/m95080-r.pdf

The device exposes SPI pins (MISO, MOSI, SCK) plus EEPROM chip‑select (CS), HOLD, and write‑protect (WP) control pins.

Pin STM32 Pin D3S Pin
SDI (MOSI) PB15 (MOSI) PTE2
SDO (MISO) PB14 (MISO) PTE1
SCK PB13 PTE0
CS PC13 PTA13
HOLD PE6 PTA11
Write Protect PE4 PTE6

Here is an example algorithm for reading and writing to the EEPROM:


PROCEDURE EEPROM_WriteEnable()
    SET command = 0x06 (WREN command)

    PULL CS line LOW
    SEND command over SPI
    PULL CS line HIGH
END PROCEDURE

PROCEDURE EEPROM_WriteByte(address, data_byte)
    IF address > 0x3FF THEN
        RETURN (address out of range)
    END IF

    CREATE command_array with 3 elements:
        command_array[0] = 0x02 (WRITE instruction)
        command_array[1] = upper 3 bits of address (A10-A8)
        command_array[2] = lower 8 bits of address (A7-A0)

    CALL EEPROM_WriteEnable() to enable writing
    PULL CS line LOW
    SEND command_array (3 bytes) over SPI
    SEND data_byte over SPI
    PULL CS line HIGH

    CALL EEPROM_WaitWriteComplete() to wait for completion
END PROCEDURE

PROCEDURE EEPROM_ReadByte(address) RETURNS byte
    IF address > 0x3FF THEN
        RETURN 0xFF (address out of range)
    END IF

    CREATE command_array with 3 elements:
        command_array[0] = 0x03 (READ instruction)
        command_array[1] = upper 3 bits of address (A10-A8)
        command_array[2] = lower 8 bits of address (A7-A0)

    INITIALIZE data_byte = 0

    PULL CS line LOW
    SEND command_array (3 bytes) over SPI
    READ data_byte from SPI
    PULL CS line HIGH

    RETURN data_byte
END PROCEDURE
  • Explanation:
  • EEPROM_WriteEnable sends the WREN (0x06) command so that the next write operation is accepted by the EEPROM.
  • EEPROM_WriteByte builds a 3‑byte command frame: the WRITE opcode (0x02) followed by the 11‑bit address split into high bits A10..A8 and low bits A7..A0. It then sends this frame and the data byte over SPI, and finally waits until the internal write cycle finishes.
  • EEPROM_ReadByte builds a similar 3‑byte frame with the READ opcode (0x03), sends it, and then reads back one data byte from the EEPROM.

The helper functions eeprom_spi_write, eeprom_spi_read, EEPROM_CS_LOW, EEPROM_CS_HIGH, and EEPROM_WaitWriteComplete are thin wrappers around the actual SPI and GPIO operations (for example, HAL or another driver), so the high‑level EEPROM logic remains clear.

Encoder

We are using a PEC12R rotary contacting encoder.

Documentation: https://componentsearchengine.com/Datasheets/5/PEC12R-4220F-S0024.pdf

The encoder is already mounted on the D3S board and can be accessed from the STM32 board.

The rotation is detected using two signals, A and B. When A is pulled low (active), it indicates movement; if B then goes low the rotation is clockwise, and if B stays high the rotation is counter‑clockwise.

There is also an integrated push button. All three pins can be used as normal GPIO inputs.

Pin STM32 Pin D3S Pin
ENC_A PE10 PTB13
ENC_B PE11 PTA6
ENC_BTN PE12 PTE7

Keypad

We are using a 3×4 matrix keypad. The datasheet is available here.

The keypad has 3 columns and 4 rows. Configure the column pins as inputs and the row pins as outputs.

Pin STM32 Pin D3S Pin
COL1 PD9 PTB3
COL2 PD10 PTC14
COL3 PD11 PTC15
ROW1 PE15 PTC9
ROW2 PB11 PTB0
ROW3 PB12 PTB1
ROW4 PD8 PTB2

Example C implementation for scanning the keypad:


DECLARE keypad_map as array:
    ['1', '2', '3',
     '4', '5', '6', 
     '7', '8', '9',
     '*', '0', '#']

FUNCTION read_keypad() RETURNS character
    FOR each row from 0 to ROWS-1:
        // Activate current row, deactivate others
        FOR each setup_row from 0 to ROWS-1:
            IF setup_row equals current row THEN
                SET row pin to ACTIVE_LEVEL
            ELSE
                SET row pin to INACTIVE_LEVEL
            END IF
        END FOR
        
        // Check each column for button press
        FOR each col from 0 to COLS-1:
            IF column pin reads LOW (button pressed) THEN
                CALCULATE key_index = row * COLS + col
                RETURN keypad_map[key_index]
            END IF
        END FOR
    END FOR
    
    RETURN null character (no key pressed)
END FUNCTION

LCD

We are using an ST7565 graphical LCD: https://www.hpinfotech.ro/ST7565.pdf

The LCD is connected to the STM32 via the SPI2 interface.

The LCD uses SDI and SCK for SPI, plus DC (data/command select), CS (chip select), and RST (reset) control inputs.

There is a dedicated connector on the D3S board for the LCD module, so the STM32 can access it directly.

Pin STM32 Pin D3S Pin
SDI PB15 (MOSI) PTE2
SCK PB13 PTE0
DC PE2 PTC5
CS PE5 TPA12
RST PB7 PTA10

Example initialization code:


PROCEDURE ST7565_WriteCommand(command_byte)
    SET DC pin to LOW (command mode)
    SET CS pin to LOW (select device)
    SEND command_byte over SPI
    SET CS pin to HIGH (deselect device)
END PROCEDURE

PROCEDURE ST7565_WriteData(data_byte)
    SET DC pin to HIGH (data mode)
    SET CS pin to LOW (select device)
    SEND data_byte over SPI
    SET CS pin to HIGH (deselect device)
END PROCEDURE

PROCEDURE ST7565_Init()
    CALL ST7565_Reset() to toggle RST pin
    WAIT 50 milliseconds after reset
    
    // Send initialization commands
    SEND command 0xAE (Display OFF)
    SEND command 0xA2 (Set bias to 1/9)
    SEND command 0xA0 (ADC normal direction)
    SEND command 0xC8 (COM output reverse direction)
    SEND command 0x22 (Set resistor ratio)
    SEND command 0x2F (Power control: all circuits ON)
    SEND command 0x40 (Set start line to 0)
    SEND command 0xAF (Display ON)
    
    // Optional contrast setting
    SEND command (0x20 OR 0x06) to set resistor ratio for contrast
END PROCEDURE

Servo Motor

We are using a Tower Pro SG90 servo motor.

The servo is controlled using a PWM signal (e.g., from timer TIM1 on the STM32).

Documentation: http://www.ee.ic.ac.uk/pcheung/teaching/DE1_EE/stores/sg90_datasheet.pdf

On the D3S board the control pin is labeled orange, matching the orange wire of the servo cable.

Pin STM32 Pin D3S Pin
PWM PE9 PTB12

Temperature and Humidity Sensor

We are using an SHT40 temperature and humidity sensor. It is already mounted on the D3S board and can be accessed from the STM32 board.

For the sensor datasheet, see: https://www.laskakit.cz/user/related_files/sht4x.pdf

The sensor uses the I²C bus for communication (see the I²C specification here: https://www.nxp.com/docs/en/user-guide/UM10204.pdf).

Pin STM32 Pin D3S Pin
SCL PA8 PTA3
SDA PC9 PTA2

Note: the sensor I²C address is 0x45.

Example code on STM32:


PROCEDURE read_temperature_and_humidity(i2c_handle, temperature_pointer, humidity_pointer)
    DECLARE command_byte = 0xFD
    DECLARE sensor_address = 0x45
    
    // Send measurement command
    CALL i2c_write(i2c_handle, sensor_address shifted left by 1, command_byte, 1 byte, 100ms timeout)
    WAIT 30 milliseconds for measurement completion
    
    // Read measurement data (6 bytes total)
    DECLARE receive_buffer[6]
    CALL i2c_read(i2c_handle, sensor_address shifted left by 1, receive_buffer, 6 bytes, 100ms timeout)
    
    // Parse temperature data
    CALCULATE temperature_raw = receive_buffer[0] * 256 + receive_buffer[1]
    SET temperature_checksum = receive_buffer[2]
    
    // Parse humidity data  
    CALCULATE humidity_raw = receive_buffer[3] * 256 + receive_buffer[4]
    SET humidity_checksum = receive_buffer[5]
    
    // Handle checksum error case
    IF temperature_checksum equals 0 AND humidity_checksum equals 0 THEN
        SET humidity_pointer value to 0.0
    END IF
    
    // Convert raw values to actual temperature and humidity
    CALCULATE temperature_celsius = -45 + (175 * (temperature_raw / 65535.0))
    CALCULATE humidity_percent = -6 + (125 * (humidity_raw / 65535.0))
    
    // Clamp humidity to valid range [0, 100]
    IF humidity_percent > 100.0 THEN
        SET humidity_percent = 100.0
    END IF
    IF humidity_percent < 0.0 THEN
        SET humidity_percent = 0.0
    END IF
    
    // Store results
    SET temperature_pointer value to temperature_celsius
    SET humidity_pointer value to humidity_percent
END PROCEDURE

JOYSTICK

More details to be added.