Skip to content

Commit

Permalink
📚 Add examples related to GPIO and SPI
Browse files Browse the repository at this point in the history
  • Loading branch information
ronisbr committed Jun 14, 2020
1 parent 909f25f commit 45b9d96
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 4 deletions.
12 changes: 8 additions & 4 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ makedocs(
sitename = "BaremetalPi",
authors = "Ronan Arraes Jardim Chagas",
pages = [
"Home" => "index.md",
"GPIO" => "man/gpio.md",
"SPI" => "man/spi.md",
"Library" => "lib/library.md",
"Home" => "index.md",
"GPIO" => "man/gpio.md",
"SPI" => "man/spi.md",
"Examples" => Any[
"LED" => "man/examples/led.md",
"Temperature" => "man/examples/temperature.md",
],
"Library" => "lib/library.md",
]
)

Expand Down
Binary file added docs/schematics/Example LED.key
Binary file not shown.
Binary file added docs/schematics/Example temperature.key
Binary file not shown.
Binary file added docs/src/assets/Schematic_example_LED.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions docs/src/man/examples/led.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
LED
===

This example shows how to use **BaremetalPi.jl** to blink a LED. First, connect
a LED to the GPIO #4 of the Raspberry Pi as shown in the following figure.

!!! warning

We are using the Raspberry Pi Zero W as an example. You **must** modify it
according to your model.

```@raw html
<img src="../../../assets/Schematic_example_LED.png" width="65%"/>
```

After that, the following code turn on the LED during 0.5s and then turn it off
during another 0.5s indefinitely:

```julia
using BaremetalPi

# Initialize the GPIOs.
init_gpio()

# Make sure that the GPIO #4 is set as output.
gpio_set_mode(4, :out)

# Blink the LED indefinitely.
while(true)
gpio_set(4)
sleep(0.5)
gpio_clear(4)
sleep(0.5)
end
```
175 changes: 175 additions & 0 deletions docs/src/man/examples/temperature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
Temperature
===========

This example shows how to use **BaremetalPi.jl** together with a AD converter
MCP3008 and a 103 thermistor to read the ambient temperature. The connections
between the components are shown in the following figure:

!!! warning

We are using the Raspberry Pi Zero W as an example. You **must** modify it
according to your model.

```@raw html
<img src="../../../assets/Schematic_example_temperature.png" width="85%"/>
```

The MCP3008 is a 8-channel 10-bit analog to digital converted that communicates
using the SPI interface. Thus, the first thing is to make sure that SPI is
enabled in your Linux distribution so that the devices `/dev/spidevX.Y` exists
(`X` and `Y` are integers related to the SPI numbering). Please, check the
manual of your distribution for more information.

After the connection, we need to start the SPI interface in **BaremetalPi.jl**.
Here, we consider that the device in which the MCP3008 was connected is called
`/dev/spidev0.0`.

```julia
using BaremetalPi

init_spi("/dev/spidev0.0", max_speed_hz = 1000)
```

Notice that we limit the sampling speed to 1000 Hz to improve the
signal-to-noise ratio of the AD conversion as per MCP3008 datasheet.

To acquire a new measurement, we need to perform a full-duplex SPI transfer.
Three bytes must be sent to the device: `0x01 0x80 0x00`, which asks for a new
measurement of the channel 0. For more information about how MCP3008 works,
please, see the datasheet. This full-duplex transfer can be accomplished using
**BaremetalPi.jl** as follows:

```julia
tx_buf = [0x01, 0x80, 0x00]
rx_buf = zeros(UInt8, 3)

ret = spi_transfer!(1, tx_buf, rx_buf)
```

`ret` must be 3 indicating that the device returned 3 bytes. The 10-bit AD
measurement is then stored in `rx_buf[2:3]`. The conversion to voltage is
performed as follows:

```julia
V = ( (UInt16(rx_buf[2] & 3) << 8) + rx_buf[3] )*3.3/1024
```

Now, we need to obtain the resistance of the thermistor using the equation of
the voltage divider:

```julia
R_div = 10_000 # ............. Resistor value at the voltage divider [Ω]
th_R = R_div*(3.3/V - 1)
```

Finally, using the relationship between resistance and temperature for the
selected thermistor, we can get a measurement of the ambient temperature:

```julia
th_β = 3380 # ................ Beta coefficient of the thermistor [K]
th_R₀ = 10_000 # ............. Reference thermistor resistance at T₀ [Ω]
th_T₀ = 25 # ....... Reference temperature T₀ of the thermistor [°C]

T = 1/( log(th_R / th_R₀)/th_β + 1/(th_T₀ + 273.15) ) - 273.15
```

The following code prints the temperature every 5s:

```julia
using Dates
using Printf
using BaremetalPi

################################################################################
# Configuration
################################################################################

const R_div = 10_000 # ............. Resistor value at the voltage divider [Ω]
const th_β = 3380 # ................ Beta coefficient of the thermistor [K]
const th_R₀ = 10_000 # ............. Reference thermistor resistance at T₀ [Ω]
const th_T₀ = 25 # ....... Reference temperature T₀ of the thermistor [°C]

################################################################################
# Functions
################################################################################

function acquire_temperature()
# Acquire the AD measurement
# ==========================================================================

tx_buf = [0x01, 0x80, 0x00]
rx_buf = zeros(UInt8, 3)
V = 0

ret = spi_transfer!(1, tx_buf, rx_buf)

if ret != 3
@warn("The data received from MCP3008 does not have 3 bytes.")
return NaN
end

# AD measurement.
V = ( (UInt16(rx_buf[2] & 3) << 8) + rx_buf[3] )*3.3/1024

if V == 0
@warn("The MCP3008 measured 0V.")
return NaN
end

if V > 3.25
@warn("The MCP3008 measured a too high voltage (> 3.25V).")
return NaN
end

# Convert the measurement to temperature
# ==========================================================================

th_R = R_div*(3.3/V - 1)
T = 1/( log(th_R / th_R₀)/th_β + 1/(th_T₀ + 273.15) ) - 273.15

return T
end

function run()
# Let's sample at 1kHz to improve the accuracy of MCP3008.
init_spi("/dev/spidev0.0", max_speed_hz = 1000)

while true
T = acquire_temperature()

if !isnan(T)
@printf("%-30s %3.2f\n", string(now()), T)
else
println("[ERROR] Problem when acquiring AD measurement.")
end
sleep(5)
end
end

run()
```

**Result:**

```
2020-06-14T19:36:40.564 22.65
2020-06-14T19:36:46.235 22.65
2020-06-14T19:36:51.264 22.65
2020-06-14T19:36:56.286 22.65
2020-06-14T19:37:01.32 22.65
2020-06-14T19:37:06.354 22.65
2020-06-14T19:37:11.381 22.65
2020-06-14T19:37:16.415 22.65
2020-06-14T19:37:21.443 22.65
2020-06-14T19:37:26.465 23.57 -> I placed my finger on the thermistor.
2020-06-14T19:37:31.497 23.57
2020-06-14T19:37:36.525 23.16
2020-06-14T19:37:41.547 22.86
2020-06-14T19:37:46.581 22.76
```

!!! info

To improve the accuracy, measure the resistance of the voltage divider
resistor and update the constant `R_div`. Furthermore, check the β of your
thermistor and update the value in the constant `th_β`.
4 changes: 4 additions & 0 deletions docs/src/man/gpio.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,7 @@ julia> gpio_set(0xAAAAAAAA) # .... Sets the even GPIOs and clears the odd GPIOs.
!!! note

The bits higher than 27, which are the number of GPIOs, are just ignored.

## Example

See the example [LED](@ref).
4 changes: 4 additions & 0 deletions docs/src/man/spi.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,7 @@ julia> tx_buf = [ [0x01, 0x80, 0x00] for i = 1:3 ]
julia> spi_transfer(1, tx_buf)
(Array{UInt8,1}[[0x00, 0x01, 0xf2], [0x9f, 0x00, 0x00], [0x00, 0x00, 0x00]], 9)
```
## Example
See the example [Temperature](@ref).

0 comments on commit 45b9d96

Please sign in to comment.