RC2026 – Part 2 – Using a BME280 environmental sensor on a RC2014

I previously controlled a MAX7219 LED matrix over SPI from my RC2014 computer. Now I want to try another SPI device, the BM280 environmental sensor from Bosch. The code in this article builds on the previous work, so take a moment to read it if you haven’t already.

The BME280 can read temperature, pressure, and humidity. It is a 3.3V device, so I will need a voltage level converter to use it with a 5V RC2014.

The SPI communication will also need to be two-way, as I will need to tell the sensor what values to send me.

I used the following parts (note: Amazon affiliate links)

The regulator allowed me to generate a 3.3v power supply from the RC2014’s 5v supply. I was then able to use this on the low-voltage side of the level shifter to allow the signals to convert between 5v and 3.3v.

As before, I am using the SC129 Digital IO module on my RC2014 to bit-bang the SPI protocol. This is wired up via the level shifters and 3.3V regulator as follows…

SC129BME280
GNDGND
5V3.3V (via 3.3 regulator)
OUT D0SDA / SDI (via level shifter)
OUT D1SCL / SCK (via level shifter)
OUT D3CSB (via level shifter)
IN D0SDO (via level shifter)

The BME280 gives us the following timing diagram for SPI communication.

BME280 SPI timing diagram

Looking at the timing diagram, we can see that before we start any communication, the SCL / SCK and CSB lines both need to be high. We can use a subroutine to do this.

deselect_bme280:
    ld a, 0 | SELECT | CLK | MOSI
    out (OUTPUT_PORT),a
    ret

Sending and receiving take place on the transition of the SCK line from high to low.

This code is similar to the code for the LED matrix in my earlier post. I have added some additional code to handle the input. This reads the bit, rotates it right into the carry flag, then rotates that value into the E register. By the end of the routine, the byte in register D will have been sent, and the byte returned will be in register E.

send_receive_byte:
    push bc
    ld b, 8
    ld a, 0 &~SELECT &~CLK | MOSI
    rra
    ld c, a
.transmit_bme280_bit:
    ld a, c
    rl d
    rla 
    out (OUTPUT_PORT), a.  ; CLK low
    in a, (INPUT_PORT)
    rra
    rl e
    ld a, c
    or a, CLK
    out (OUTPUT_PORT), a   ; CLK high
    djnz .transmit_bme280_bit
    pop bc
    ret

To test that this is working, we can send the value 0xD0 to the BME280. It should send back the value 0x60. To read the returned byte, we send 0x00. While this is being sent, the result byte will be returned simultaneously. We will then output this byte to the SC129 so the display LEDs will show the returned value in binary.

bme280_getId:
    call deselect_bme280
    ld d, 0xD0
    call send_receive_byte
    ld d, 0x00
    call send_receive_byte 
    call deselect_bme280

    ld a, e
    out (OUTPUT_PORT), a
    ret

After running, the LEDs correctly show 01100000 – 0x60.

The next step will be to get actual temperature readings. That will be the subject of the next post.