Skip to content
Browse files

Migrate back to shortcodes.

  • Loading branch information
Richard Drake
Richard Drake committed Feb 5, 2020
1 parent b62b913 commit c01d76efb1bd2aea0392adfd216fa5da7be12842
@@ -31,5 +31,5 @@ unsafe = true
definitionList = true
table = true

resampleFilter = "lanczos"
#resampleFilter = "linear" #"lanczos"
@@ -22,7 +22,9 @@ The most important component is the RPi itself. Remove it from its Mylar bag an

We will use this breadboard in future labs, but not this time. To start, we'll need keyboard, mouse, network, and display connections. Start by plugging in an HDMI cable. Ensure the monitor is on.

![Raspberry Pi 3 Model B+ wired](pi_wired.jpg)
{{<figure caption="Raspberry Pi 3 Model B+ wired">}}
{{<img src="pi_wired.jpg">}}

Next, plug in the network cable into the RPi and one of the ethernet ports in the lab. The RPi is powered over the network. Wait for the boot screen to appear on the monitor (approximately 30s after plugging in the network cable) before plugging in the keyboard and mouse. This is a bug in the RPi's firmware.

@@ -87,7 +89,7 @@ print(x)
print(x * 2)

Save this program over your program from part 2 and execute it with F5. Notice that this program does not execute line-by-line, but executes the entire program when you hit F5.
Save this program over your program from part 2 and execute it with <kbd>F5</kbd>. Notice that this program does not execute line-by-line, but executes the entire program when you hit <kbd>F5</kbd>.

Let's add some other variables to the end of our program:

@@ -119,11 +121,11 @@ Now, let's try out conditionals.
x = 8
if x < 10:
print("x is small")
print("x is small")
elif X < 20:
print("x is medium")
print("x is medium")
print("x is large")
print("x is large")

Try experimenting with different values for X until you understand how the conditional works.
@@ -137,16 +139,16 @@ Let's examine a while loop now. Again, the major difference with C++ is the use
x = 8
while x > 0:
x = x - 1
x = x - 1

In Python, for loops work using lists so let's examine those in more detail before we learn the for loop syntax. A list is merely a collection of elements of the same type surrounded by square brackets (e.g. `[1, 2, 3, 4, 5]`). We can loop over any list:

names = ["Bob", "Sally", "Kunal", "Ahmed", "Carla"]
for name in names:

There is a function `range()` that can generate a list, that is very useful in for loops. You can pass 3 values to range: the minimum, the maximum, and the step size, and `range()` will generate a list that starts at the minimum value (default 0), proceeds to the next by adding the step size (default 1), until the maximum value is reached. The maximum value is not included in the resulting list. Try out `range()` a bit in the Python shell:
@@ -161,7 +163,7 @@ We are finally ready to use a familiar form of for loop:

for val in range(0, 20):

There is a lot more to Python, but this should be enough to get us through these labs.
@@ -11,7 +11,9 @@ An *analog-to-digital converter* (ADC, A/D, or A to D) is a device that converts

The MCP3008 chip is an SPI-based analogue to digital converter (ADC). It has 8 analog input channels that can be configured, so it can handle up to 8 ADC conversions. The MCP3008 is a 10-bit ADC so its output will vary from 0 to 1023. The pinout of the MCP3008 is the following:

![MCP3008 SDI ADC Pinout](mcp3008pin.png "[Tony DiCola [CC BY 3.0]](")
{{<figure width="400" caption="MCP3008 SDI ADC Pinout" attr="[Tony DiCola [CC BY 3.0]](">}}
{{<img src="mcp3008pin.png">}}

Typically the VDD pin is connected to 3.3V power. The AGND and DGND pins can be connected directly to the ground reference point. The VREF pin is the reference voltage which is the largest possible voltage that the ADC can interpret. In our scenario we will connect the VREF pin to 3.3V (same as VDD). So if 3.3V was sampled on any of the ADC's channels it would be interpreted as the maximum digital value that can be represented by this 10-bit ADC i.e. $2^{10} – 1 = 1023$. Similarly the smallest analog voltage that the ADC can detect (also known as the 'LSB size') is VREF/1024. Which in our case is $\frac{3.3\text{V}}{1024}= 3.22\text{mV}$ and represents a digital value of 1. The equation that converts between the analog voltage and its digital interpretation is given by "Digital output code = 1024*VIN/VREF"; where VIN is the analog input voltage and VREF is the reference voltage.

@@ -31,18 +33,21 @@ The operation of the SPI bus is conceptually simple. Both the master controller
# ADC using SPI from a Raspberry Pi
In order to read analog data we need to use the following pins: VDD (power), DGND (digital ground) to power the MCP3008 chip. We also need four 'SPI' data pins: DOUT (Data Out from MCP3008), CLK (Clock pin), DIN (Data In from Raspberry Pi), and /CS (Chip Select). Finally of course, a source of analog data, we'll be using the basic 10k trim pot. A trimpot is a three-terminal resistor with a sliding or rotating contact that forms an adjustable voltage divider:

{{< figure caption="10k Ohm Trimpot" width="300px" >}}
![10k Ohm Trimpot](trimpot.jpg)
{{< /figure >}}
{{<figure caption="10k Ohm Trimpot" width="300">}}
{{<img src="trimpot.jpg">}}

The MCP3008 has a few more pins we need to connect: AGND (analog ground, used sometimes in precision circuitry, which this is not) connects to GND, and VREF (analog voltage reference, used for changing the 'scale' - we want the full scale so tie it to 3.3V)

Below is a wiring diagram:

![ADC circuit](ADC.png)
{{<figure caption="ADC circuit">}}
{{<img src="ADC.png">}}

The connections of the MCP3008 chip is the following:

{{<figure width="75%">}}
MCP 3008 Pin | RPi Pin
VDD | 3.3V (red)
@@ -53,6 +58,7 @@ DOUT | #13 (yellow)
DIN | #15 (blue)
CS | #19 (purple)
DGND | GND (black)

Next connect up the potentiometer. Pin #1 (left) goes to GND (black), #2 (middle) connects to MCP3008 CH0 (analog input #0) with a pink wire, and #3 (right) connects to 3.3V (red).

@@ -86,12 +86,12 @@ The *bit shifts* are sometimes considered bitwise operations, because they treat
= 1010

{{<img src="shift-left.png">}}

= 0010

{{<img src="shift-right.png">}}

## Bit shift in python
In python the left and right shift operators are `<<` and `>>`, respectively. The number of places to shift is given as the second argument to the shift operators. For example:
@@ -112,9 +112,9 @@ To test for different bits in python you can use the combination of the shift op
The result of the above operation will be 1 if the bit in the i-th position has value 1, zero otherwise.

# Representing binary numbers with LED on the Raspberry Pi
We are going to do a fun exercise. Lets create a circuit with 3 LEDs representing each one a bit in a binary number of size 3, and increment that number every second. The circuit would be the following:
We are going to do a fun exercise. Let's create a circuit with 3 LEDs representing each one a bit in a binary number of size 3, and increment that number every second. The circuit would be the following:

{{<img src="binary.png">}}

Notice that we are using GPIO pins 17, 27 and 22 as output pins for the LEDs. The following program will show the different binary numbers from 0 to 7 displayed using the LEDs:

@@ -10,6 +10,7 @@ In this lab we are going to experiment with gates and circuit design. We'll use

The 74xx series of chips generally contain logic gates and other components. For example, the 7402 chip contains 4 NOR gates on a single 14-pin chip. There are many variations, including some that have memory (flip-flops, latches). The table below summarizes some of these chips.

{{<figure width="75%">}}
Base Model | Description
7400 | Quad 2-input NAND gates
@@ -18,10 +19,13 @@ Base Model | Description
7408 | Quad 2-input AND gates
7432 | Quad 2-input OR gates
7486 | Quad 2-input XOR gates

Nearly all of the above chips have an identical pinout (the exceptions are the 7402 and the 7404). The diagram below illustrates the pinout of the 7400 chip.

![Pinout of the 7400 chip](7400_Quad_2-input_NAND_Gates.png "[By Tosaka [CC BY 3.0], via Wikimedia Commons](")
{{<figure width="75%" caption="Pinout of the 7400 chip" attr="[By Tosaka [CC BY 3.0], via Wikimedia Commons](">}}
{{<img src="7400_Quad_2-input_NAND_Gates.png">}}

To use one of these chips, connect pin #7 to ground, and pin #14 to +3.3V. You may then connect two inputs (either GPIO output ports or directly from power source) to pin #1 and pin #2, and connect the output (pin #3) to either an LED (with an appropriate resistor) or a GPIO input port.

@@ -39,16 +43,20 @@ A half adder is a circuit that adds two binary digits, producing a sum and a car

One can easily construct a half adder for two input bits (X and Y) by drawing the truth table for both sum (S) and carry \(C), as shown below.

{{<figure width="75%">}}
A | B | S | C
0 | 0 | 0 | 0
0 | 1 | 1 | 0
1 | 0 | 1 | 0
1 | 1 | 0 | 1

Recognizing that the S column is identical to the truth table for XOR, and that the C column is identical to the truth table for AND, we can design a very simple circuit for a half adder.

![The circuit for a half adder](half-adder.png)
{{<figure width="50%" caption="The circuit for a half adder">}}
{{<img src="half-adder.png">}}

### Hardware Setup

@@ -58,7 +66,9 @@ Connect a red wire to a power supply of +3.3V on the GPIO header, and plug it in

Now, connect the inputs for both the first XOR gate and the first AND gate to the GPIO17 and GPIO22. Connect the output from the XOR gate to GPIO23, and the output from the AND gate to GPIO24. The completed circuit wiring is shown below.

![The circuit for a half adder](HalfAdder.png)
{{<figure caption="Half adder on a breadboard">}}
{{<img src="HalfAdder.png">}}

## Exercise

@@ -12,6 +12,7 @@ A full adder is a circuit that adds two binary digits, plus a carry in, producin

The same process used for the half adder can be used to design the circuit for a full adder, starting with the truth table (which is filled out by hand, based on what we know about the behaviour of the circuit).

{{<figure width="75%">}}
A | B | Carry in | Sum | Carry out
0 | 0 | 0 | 0 | 0
@@ -22,16 +23,17 @@ A | B | Carry in | Sum | Carry out
1 | 0 | 1 | 0 | 1
1 | 1 | 0 | 0 | 1
1 | 1 | 1 | 1 | 1

Using a Karnaugh map, and knowledge of XOR, we can get simplified Boolean algebraic expressions for each of the two output variables.

$$S = A \oplus B \oplus C\_{in}$$

$$C\_{out} = ((A \oplus B) \land C\_{in}) \lor (A \land B)$$
$$\begin{align*}S &= A \oplus B \oplus C\_{in} \\\\ C\_{out} &= ((A \oplus B) \land C\_{in}) \lor (A \land B)\end{align*}$$

The circuit corresponding to these Boolean algebraic expressions is shown below.

![The circuit for a full adder](full-adder.png)
{{<figure width="75%" caption="The circuit for a full adder">}}
{{<img src="full-adder.png">}}

### Hardware Setup

@@ -47,7 +49,9 @@ OR | AND 1 output | AND 2 output | C<sub>out</sub> (GPIO24, pin #18)

The resulting circuit should look something like the following illustration.

![The hardware configuration for a full adder](FullAdder.png)
{{<figure caption="The hardware configuration for a full adder">}}
{{<img src="FullAdder.png">}}

## Exercise

@@ -10,11 +10,16 @@ In this lab we are going to introduce the GPIO interface of the Raspberry Pi.

In one corner of the Raspberry Pi is a 40-pin expansion header. The pins are numbered from 1 to 40, with the even numbers on the outside edge of the board as shown below.

![Raspberry Pi 3 Model B+ GPIO expansion headers](raspberry_pi_3bplus_top.jpg "[By Gareth Halfacree from Bradford, UK (Raspberry Pi 3B+) [CC BY-SA 2.0], via Wikimedia Commons](")

{{<figure caption="Raspberry Pi 3 Model B+ GPIO expansion headers" attr="[By Gareth Halfacree from Bradford, UK (Raspberry Pi 3B+) [CC BY-SA 2.0], via Wikimedia Commons](">}}
{{<img src="raspberry_pi_3bplus_top.jpg">}}

Each of these GPIO pins are identified below.

![Raspberry Pi B+ GPIO 40 Pin Block Pinout](gpio_pins.png "[Christopher Stanton, Element 14 Community](")
{{<figure width="75%" caption="Raspberry Pi B+ GPIO 40 Pin Block Pinout" attr="[Christopher Stanton, Element 14 Community](">}}
{{<img src="gpio_pins.png">}}

There are several different types of pins in the expansion header.

@@ -102,15 +107,15 @@ GPIO.output(12, GPIO.LOW)

A **light-emitting diode (LED)** is a two-lead semiconductor that emits light. It resembles a simple p-n junction diode, which emits light when activated

{{<img src="led.png">}}

As LEDs are diodes, current only flows in one direction. Thus you must connect the anode to the power source and the cathode to the ground. Reversing these connections will not permit current to flow through and thus it will not emit light.

In general the longest leg of the LED is the anode, while the shortest is the cathode. The flat side of the LED lens is always the cathode.

To control an LED from the Pi we are going to connect it to a GPIO pin. While any GPIO pin may be used, this example uses pin #12. As you can verify in the pinout diagram above, this corresponds to the GPIO #18 (as labelled in the header).

{{<img src="led_circuit_rev3.png">}}

As the output voltage of the GPIO pins is +3.3V and the LED only uses +2.1V, we must add a resistor. The specification of this LED says it consumes 20mA. Each pin supplies up to 16mA, so the actual forward current consumed by the LED is 16mA, not 20mA.

@@ -182,7 +187,7 @@ Start with the circuit from Example 1. Insert a momentary pushbutton switch int

Your circuit should be similar to the following.

{{<img src="led_button_circuit.png">}}

When the button is pressed, the circuit between the +3.3V pin and pin #11 is completed. This causes the input value of #11 to be `GPIO.HIGH`. As we want a value of `GPIO.HIGH` to be read when the button has been pressed, we use set the `pull_up_down` argument to `GPIO.PUD_DOWN`.

@@ -6,16 +6,16 @@ Weight = 7

A *Servomotor*, or servo, is a small device that has an output shaft. This shaft can be positioned to specific angular positions by sending the servo a coded signal. As long as the coded signal exists on the input line, the servo will maintain the angular position of the shaft. As the coded signal changes, the angular position of the shaft changes.

{{< figure width="300px" >}}
{{< /figure >}}
{{<img width="250" src="servo_motor.png">}}

Servos are extremely useful in practice. They may be used to operate remote-controlled toy cars, robots, or airplanes. Servos are also used in industrial applications, robotics, in-line manufacturing, pharmaceutics, and food services.

# How is a Servo Controlled?
Servos are controlled by sending an electrical pulse of variable width, or pulse width modulation (PWM), through the control wire. There is a minimum pulse, a maximum pulse, and a repetition rate. A servo motor can usually only turn 90 degrees in either direction for a total of 180 degree movement. The motor's neutral position is defined as the position where the servo has the same amount of potential rotation in the both the clockwise or counter-clockwise direction. The PWM sent to the motor determines position of the shaft, and based on the duration of the pulse sent via the control wire; the rotor will turn to the desired position. The servo motor expects to see a pulse every 20 milliseconds (ms) and the length of the pulse will determine how far the motor turns. For example, a 1.5ms pulse will make the motor turn to the 90-degree position. Shorter than 1.5ms moves it to 0 degrees, and any longer than 1.5ms will turn the servo to 180 degrees, as diagrammed below:

![PWM control example](Graphs_PWM_web.png "[Backyard Brains [CC BY-SA 3.0]](")
{{<figure caption="PWM control example" attr="[Backyard Brains [CC BY-SA 3.0]](">}}
{{<img width="75%" src="Graphs_PWM_web.png">}}

When these servos are commanded to move, they will move to the position and hold that position. If an external force pushes against the servo while the servo is holding a position, the servo will resist from moving out of that position. The maximum amount of force the servo can exert is called the torque rating of the servo. Servos will not hold their position forever though; the position pulse must be repeated to instruct the servo to stay in position.

@@ -41,17 +41,11 @@ $$

Since the servo uses 20ms cycles, we can calculate the duty cycle of the 3 turns of the servo motor:

\text{dc} = \frac{0.5}{20} \times 100 = 2.5\%

\text{dc} = \frac{1.5}{20} \times 100 = 7.5\%

\text{dc} = \frac{2.5}{20} \times 100 = 12.5\%
\text{dc} &= \frac{0.5}{20} \times 100 = 2.5\\% \\\\
\text{dc} &= \frac{1.5}{20} \times 100 = 7.5\\% \\\\
\text{dc} &= \frac{2.5}{20} \times 100 = 12.5\\%

To change the duty cycle we can use:

@@ -68,7 +62,7 @@ p.stop()
# Example of controlling a servo from the Raspberry Pi
The following diagram shows how to connect the servo to the Raspberry Pi:

{{<img src="circuit_servo_breadboard.png">}}

The following program will control the servo making it move to its neutral position (90 degrees), wait 1 second and then move to its 0 degrees, wait 1 second and finally move to its 180 degrees. The cycle continues until interrupted:

0 comments on commit c01d76e

Please sign in to comment.
You can’t perform that action at this time.