SunFounder Euler Kit for Raspberry Pi Pico¶
Thank you for choosing the SunFounder Euler Kit
This is an advanced learning kit based on the Raspberry Pi Pico. It contains a variety of components, including displays, sounds, drivers, controllers and sensors, which allows you to gain a comprehensive understanding of electronic devices.
For you, we have prepared a number of interesting and useful projects as well as a great deal of relevant and authoritative information. All you need to do is turn on your computer, and you can learn programming in no time at all.
Additionally, we offer three programming languages. MicroPython, C/C++ (Arduino) and Piper Make are all available. To help you get started quickly, each language has targeted and interesting projects, so you can pick one that meets your needs.
Please feel free to e-mail us if you are interested in learning other projects we don’t have. We will update our online tutorials as soon as possible.
Here is the email: cs@sunfounder.com.
About the display language
In addition to English, we are working on other languages for this course. Please contact service@sunfounder.com if you are interested in helping, and we will give you a free product in return. In the meantime, we recommend using Google Translate to convert English to the language you want to see.
The steps are as follows.
In this course page, right-click and select Translate to xx. If the current language is not what you want, you can change it later.

There will be a language popup in the upper right corner. Click on the menu button to choose another language.

Select the language from the inverted triangle box, and then click Done.

Source Code
Or check out the code at Euler Kit - GitHub
Content
Introduction to Raspberry Pi Pico¶
The Raspberry Pi Pico is a microcontroller board based on the Raspberry Pi RP2040 microcontroller chip.
With Raspberry Pi Pico, you can learn MicroPython programming, take your first step into physical computing, or build a hardware project. This amazing community - will support you every step of the way. In the project, it can control anything, from LEDs and buttons to sensors, motors, and even other microcontrollers.
Features¶
21 mm × 51 mm form factor
RP2040 microcontroller chip designed by Raspberry Pi in the UK
Dual-core Arm Cortex-M0+ processor, flexible clock running up to 133 MHz
264KB on-chip SRAM
2MB on-board QSPI Flash
26 multifunction GPIO pins, including 3 analog inputs
2 × UART, 2 × SPI controllers, 2 × I2C controllers, 16 × PWM channels
1 × USB 1.1 controller and PHY, with host and device support
8 × Programmable I/O (PIO) state machines for custom peripheral support
Supported input power 1.8–5.5V DC
Operating temperature -20°C to +85°C
Castellated module allows soldering direct to carrier boards
Drag-and-drop programming using mass storage over USB
Low-power sleep and dormant modes
Accurate on-chip clock
Temperature sensor
Accelerated integer and floating-point libraries on-chip
Pico’s Pins¶
Name |
Description |
Function |
---|---|---|
GP0-GP28 |
General-purpose input/output pins |
Act as either input or output and have no fixed purpose of their own |
GND |
0 volts ground |
Several GND pins around Pico to make wiring easier. |
RUN |
Enables or diables your Pico |
Start and stop your Pico from another microcontroller. |
GPxx_ADCx |
General-purpose input/output or analog input |
Used as an analog input as well as a digital input or output – but not both at the same time. |
ADC_VREF |
Analog-to-digital converter (ADC) voltage reference |
A special input pin which sets a reference voltage for any analog inputs. |
AGND |
Analog-to-digital converter (ADC) 0 volts ground |
A special ground connection for use with the ADC_VREF pin. |
3V3(O) |
3.3 volts power |
A source of 3.3V power, the same voltage your Pico runs at internally, generated from the VSYS input. |
3v3(E) |
Enables or disables the power |
Switch on or off the 3V3(O) power, can also switches your Pico off. |
VSYS |
2-5 volts power |
A pin directly connected to your Pico’s internal power supply, which cannot be switched off without also switching Pico off. |
VBUS |
5 volts power |
A source of 5 V power taken from your Pico’s micro USB port, and used to power hardware which needs more than 3.3 V. |
The best place to find everything you need to get started with your Raspberry Pi Pico is here
Or you can click on the links below:
What is Included in This Kit¶
The following is a list of this kit so you can check the contents of the kit once you receive it.
There are some components in the kit that are very small and look the same, and staff may miss or send them by mistake when packing the kit. You are welcome to send us the name of the missing or incorrect component if you find one.
Here is the email: cs@sunfounder.com.
Basic
Breadboard¶
A breadboard is a construction base for prototyping of electronics. Originally the word referred to a literal bread board, a polished piece of wood used for slicing bread. In the 1970s the solderless breadboard (a.k.a. plugboard, a terminal array board) became available and nowadays the term “breadboard” is commonly used to refer to these.
It is used to build and test circuits quickly before finishing any circuit design. And it has many holes into which components mentioned above can be inserted like ICs and resistors as well as jumper wires. The breadboard allows you to plug in and remove components easily.
The picture shows the internal structure of a breadboard. Although these holes on the breadboard appear to be independent of each other, they are actually connected to each other through metal strips internally.
If you want to know more about breadboard, refer to: How to Use a Breadboard - Science Buddies
Example
Jumper Wires¶
Wires that connect two terminals are called jumper wires. There are various kinds of jumper wires. Here we focus on those used in breadboard. Among others, they are used to transfer electrical signals from anywhere on the breadboard to the input/output pins of a microcontroller.
Jump wires are fitted by inserting their “end connectors” into the slots provided in the breadboard, beneath whose surface there are a few sets of parallel plates that connect the slots in groups of rows or columns depending on the area. The “end connectors” are inserted into the breadboard, without soldering, in the particular slots that need to be connected in the specific prototype.
There are three types of jumper wire: Female-to-Female, Male-to-Male, and Male-to-Female. The reason we call it Male-to-Female is because it has the outstanding tip in one end as well as a sunk female end. Male-to-Male means both side are male and Female-to-Female means both ends are female.
Note
More than one type of them may be used in a project.
The color of the jump wires is different but it doesn’t mean their function is different accordingly; it’s just designed so to better identify the connection between each circuit.
Resistor¶
Resistor is an electronic element that can limit the branch current. A fixed resistor is a kind of resistor whose resistance cannot be changed, while that of a potentiometer or a variable resistor can be adjusted.
Two generally used circuit symbols for resistor. Normally, the resistance is marked on it. So if you see these symbols in a circuit, it stands for a resistor.
Ω is the unit of resistance and the larger units include KΩ, MΩ, etc. Their relationship can be shown as follows: 1 MΩ=1000 KΩ, 1 KΩ = 1000 Ω. Normally, the value of resistance is marked on it.
When using a resistor, we need to know its resistance first. Here are two methods: you can observe the bands on the resistor, or use a multimeter to measure the resistance. You are recommended to use the first method as it is more convenient and faster.
As shown in the card, each color stands for a number.
Black |
Brown |
Red |
Orange |
Yellow |
Green |
Blue |
Violet |
Grey |
White |
Gold |
Silver |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
0.1 |
0.01 |
The 4- and 5-band resistors are frequently used, on which there are 4 and 5 chromatic bands.
Normally, when you get a resistor, you may find it hard to decide which end to start for reading the color. The tip is that the gap between the 4th and 5th band will be comparatively larger.
Therefore, you can observe the gap between the two chromatic bands at one end of the resistor; if it’s larger than any other band gaps, then you can read from the opposite side.
Let’s see how to read the resistance value of a 5-band resistor as shown below.
So for this resistor, the resistance should be read from left to right. The value should be in this format: 1st Band 2nd Band 3rd Band x 10^Multiplier (Ω) and the permissible error is ±Tolerance%. So the resistance value of this resistor is 2(red) 2(red) 0(black) x 10^0(black) Ω = 220 Ω, and the permissible error is ± 1% (brown).
You can learn more about resistor from Wiki: Resistor - Wikipedia.
Transistor¶
Transistor is a semiconductor device that controls current by current. It functions by amplifying weak signal to larger amplitude signal and is also used for non-contact switch.
A transistor is a three-layer structure composed of P-type and N-type semiconductors. They form the three regions internally. The thinner in the middle is the base region; the other two are both N-type or P-type ones – the smaller region with intense majority carriers is the emitter region, when the other one is the collector region. This composition enables the transistor to be an amplifier. From these three regions, three poles are generated respectively, which are base (b), emitter (e), and collector (c). They form two P-N junctions, namely, the emitter junction and collection junction. The direction of the arrow in the transistor circuit symbol indicates that of the emitter junction.
Based on the semiconductor type, transistors can be divided into two groups, the NPN and PNP ones. From the abbreviation, we can tell that the former is made of two N-type semiconductors and one P-type and that the latter is the opposite. See the figure below.
Note
s8550 is PNP transistor and the s8050 is the NPN one, They look very similar, and we need to check carefully to see their labels.
When a High level signal goes through an NPN transistor, it is energized. But a PNP one needs a Low level signal to manage it. Both types of transistor are frequently used for contactless switches, just like in this experiment.
Put the label side facing us and the pins facing down. The pins from left to right are emitter(e), base(b), and collector(c).
Note
The base is the gate controller device for the larger electrical supply.
In the NPN transistor, the collector is the larger electrical supply and the emitter is the outlet for that supply, the PNP transistor is just the opposite.
Example
2.15 Two Kinds of Transistors (For MicroPython User)
2.16 Control Another Circuit (For MicroPython User)
3.1 Beep (For MicroPython User)
3.2 Custom Tone (For MicroPython User)
7.1 Light Theremin (For MicroPython User)
7.3 Alarm Siren Lamp (For MicroPython User)
7.8 RFID Music Player (For MicroPython User)
7.9 Fruit Piano (For MicroPython User)
7.10 Reversing Aid (For MicroPython User)
3.1 - Beep (For Arduino User)
3.2 - Custom Tone (For Arduino User)
2.15 - Two Kinds of Transistors (For Arduino User)
2.16 - Control Another Circuit (For Arduino User)
2.3 Service Bell (For Piper Make User)
2.11 Reversing System (For Piper Make User)
2.13 Reaction Game (For Piper Make User)
Capacitor¶
Capacitance, refers to the amount of charge storage under a given potential difference, denoted as C, and the international unit is farad (F). Generally speaking, electric charges move under force in an electric field. When there is a medium between conductors, the movement of electric charges is hindered and the electric charges accumulate on the conductors, resulting in accumulation of electric charges.
The amount of stored electric charges is called capacitance. Because capacitors are one of the most widely used electronic components in electronic equipment, they are widely used in direct current isolation, coupling, bypass, filtering, tuning loops, energy conversion, and control circuits. Capacitors are divided into electrolytic capacitors, solid capacitors, etc.
According to material characteristics, capacitors can be divided into: aluminum electrolytic capacitors, film capacitors, tantalum capacitors, ceramic capacitors, super capacitors, etc.
In this kit, ceramic capacitors and electrolytic capacitors are used.
There are 103 or 104 label on the ceramic capacitors, which represent the capacitance value, 103=10x10^3pF, 104=10x10^4pF
- Unit Conversion
1F=10^3mF=10^6uF=10^9nF=10^12pF
Diode¶
A diode is an electronic component with two electrodes. It allows current to flow in only one direction, which is often called the “Rectifying” function. Thus, a diode can be thought of as an electronic version of a check valve.
The two terminals of a diode are polarized, with the positive end called anode and the negative end called cathode. The cathode is usually made of silver or has a color band. Controlling the direction of current flow is one of the key features of diodes — the current in a diode flows from anode to cathode. The behavior of a diode is similar to the behavior of a check valve. One of the most important characteristics of a diode is the non-linear current voltage. If higher voltage is connected to the anode, then current flows from anode to cathode, and the process is known as forward bias. However, if the higher voltage is connected to the cathode, then the diode does not conduct electricity, and the process is called reverse bias.
Because of its unidirectional conductivity, the diode is used in almost all electronic circuits of some complexity. It was one of the first semiconductor devices to be created, and its applications are widespread.
However in reality diodes do not exhibit such perfect on and off directionality, but rather more complex non-linear electronic characteristics - which are determined by the specific type of diode technology.
A diode is a p-n junction formed by a p-type semiconductor and an n-type semiconductor, with a space charge layer formed on both sides at its interface and a self-built electric field, which is in electrical equilibrium when no applied voltage is present because the diffusion current due to the difference in carrier concentration between the two sides of the p-n junction and the drift current due to the self-built electric field are equal. When the forward voltage bias is generated, the mutual suppression of the external electric field and the self-built electric field increases the diffusion current of the carriers causing the forward current (that is, the reason for the conductivity). When the reverse voltage bias is generated, the external electric field and the self-built electric field are further strengthened to form a reverse saturation current I0 in a certain reverse voltage range independent of the value of the reverse bias voltage (which is the reason for non-conductivity). When the applied reverse voltage is high to a certain extent, the electric field strength in the p-n junction space charge layer reaches a critical value to produce a multiplication process of carriers, generating a large number of electron-hole pairs, resulting in a large value of the reverse breakdown current, called the diode breakdown phenomenon.
1. Forward Characteristic
When the external forward voltage is applied, in the beginning of the forward characteristic, the forward voltage is very small, not enough to overcome the blocking effect of the electric field in the p-n junction, the forward current is almost zero, this section is called the dead zone. This forward voltage that does not allow the diode to conduct is called the deadband voltage. When the forward voltage is greater than the deadband voltage, p-n junction electric field is overcome, the diode forward conduction, the current increases with the voltage and rises rapidly. In the normal use of the current range, the terminal voltage of the diode during conduction remains almost constant, this voltage is called the forward voltage of the diode.
2. Reverse Characteristic
When the applied reverse voltage, and does not exceed a certain range, the current through the diode is a few carriers drifting movement formed by the reverse current. As the reverse current is very small, the diode is in the cutoff state. This reverse current is also known as reverse saturation current or leakage current, and is greatly influenced by temperature.
3. Breakdown
When the applied reverse voltage exceeds a certain value, the reverse current will suddenly increase, a phenomenon known as electrical breakdown. The critical voltage that causes electrical breakdown is called the reverse breakdown voltage, the diode will loses its unidirectional conductivity at the time of electrical breakdown. Therefore, the use of the diode should be avoided when the applied reverse voltage is too high.
Early diodes consisted of “Cat’s Whisker” Crystals and Vacuum tubes (also called “Thermionic Valves”). Most of today’s most common diodes use semiconductor materials such as silicon or germanium.
Chip
74HC595¶
The 74HC595 consists of an 8−bit shift register and a storage register with three−state parallel outputs. It converts serial input into parallel output so you can save IO ports of an MCU.
When MR (pin10) is high level and OE (pin13) is low level, data is input in the rising edge of SHcp and goes to the memory register through the rising edge of SHcp.
If the two clocks are connected together, the shift register is always one pulse earlier than the memory register.
There is a serial shift input pin (Ds), a serial output pin (Q) and an asynchronous reset button (low level) in the memory register.
The memory register outputs a Bus with a parallel 8-bit and in three states.
When OE is enabled (low level), the data in memory register is output to the bus(Q0 ~ Q7).
Pins of 74HC595 and their functions:
Q0-Q7: 8-bit parallel data output pins, able to control 8 LEDs or 8 pins of 7-segment display directly.
Q7’: Series output pin, connected to DS of another 74HC595 to connect multiple 74HC595s in series
MR: Reset pin, active at low level;
SHcp: Time sequence input of shift register. On the rising edge, the data in shift register moves successively one bit, i.e. data in Q1 moves to Q2, and so forth. While on the falling edge, the data in shift register remain unchanged.
STcp: Time sequence input of storage register. On the rising edge, data in the shift register moves into memory register.
CE: Output enable pin, active at low level.
DS: Serial data input pin
VCC: Positive supply voltage.
GND: Ground.
Example
5.1 Microchip - 74HC595 (For MicroPython User)
5.2 Number Display (For MicroPython User)
5.3 Time Counter (For MicroPython User)
5.4 8x8 Pixel Graphics (For MicroPython User)
7.4 Passager Counter (For MicroPython User)
7.5 GAME - 10 Second (For MicroPython User)
7.6 Traffic Light (For MicroPython User)
7.12 Digital Bubble Level (For MicroPython User)
5.1 - Microchip - 74HC595 (For Arduino User)
5.2 - Number Display (For Arduino User)
5.3 - Time Counter (For Arduino User)
5.4 - 8x8 Pixel Graphics (For Arduino User)
IC L293D¶
L293D is a 4-channel motor driver integrated by chip with high voltage and high current. It’s designed to connect to standard DTL, TTL logic level, and drive inductive loads (such as relay coils, DC, Stepper Motors) and power switching transistors etc. DC Motors are devices that turn DC electrical energy into mechanical energy. They are widely used in electrical drive for their superior speed regulation performance.
See the figure of pins below. L293D has two pins (Vcc1 and Vcc2) for power supply. Vcc2 is used to supply power for the motor, while Vcc1 to supply for the chip. Since a small-sized DC motor is used here, connect both pins to +5V.
The following is the internal structure of L293D. Pin EN is an enable pin and only works with high level; A stands for input and Y for output. You can see the relationship among them at the right bottom. When pin EN is High level, if A is High, Y outputs high level; if A is Low, Y outputs Low level. When pin EN is Low level, the L293D does not work.
Example
3.5 Small Fan (For MicroPython User)
3.5 - Small Fan (For Arduino User)
3.6 Pumping (For MicroPython User)
3.6 - Pumping (For Arduino User)
2.12 Smart Fan (For Piper Make User)
Display
LED¶
Semiconductor light-emitting diode is a type of component which can turn electric energy into light energy via PN junctions. By wavelength, it can be categorized into laser diode, infrared light-emitting diode and visible light-emitting diode which is usually known as light-emitting diode (LED).
Diode has unidirectional conductivity, so the current flow will be as the arrow indicates in figure circuit symbol. You can only provide the anode with a positive power and the cathode with a negative. Thus the LED will light up.
An LED has two pins. The longer one is the anode, and shorter one, the cathode. Pay attention not to connect them inversely. There is fixed forward voltage drop in the LED, so it cannot be connected with the circuit directly because the supply voltage can outweigh this drop and cause the LED to be burnt. The forward voltage of the red, yellow, and green LED is 1.8 V and that of the white one is 2.6 V. Most LEDs can withstand a maximum current of 20 mA, so we need to connect a current limiting resistor in series.
The formula of the resistance value is as follows:
R = (Vsupply – VD)/I
R stands for the resistance value of the current limiting resistor, Vsupply for voltage supply, VD for voltage drop and I for the working current of the LED.
Here is the detailed introduction for the LED: LED - Wikipedia.
Example
2.1 Hello, LED! (For MicroPython User)
2.3 Fading LED (For MicroPython User)
7.3 Alarm Siren Lamp (For MicroPython User)
7.6 Traffic Light (For MicroPython User)
7.10 Reversing Aid (For MicroPython User)
2.1 - Hello, LED! (For Arduino User)
2.3 - Fading LED (For Arduino User)
2.1 Blink LED (For Piper Make User)
2.2 Button (For Piper Make User)
2.3 Service Bell (For Piper Make User)
2.11 Reversing System (For Piper Make User)
2.13 Reaction Game (For Piper Make User)
RGB LED¶
RGB LEDs emit light in various colors. An RGB LED packages three LEDs of red, green, and blue into a transparent or semitransparent plastic shell. It can display various colors by changing the input voltage of the three pins and superimpose them, which, according to statistics, can create 16,777,216 different colors.
RGB LEDs can be categorized into common anode and common cathode ones. In this kit, the latter is used. The common cathode, or CC, means to connect the cathodes of the three LEDs. After you connect it with GND and plug in the three pins, the LED will flash the corresponding color.
Its circuit symbol is shown as figure.
An RGB LED has 4 pins: the longest pin is the common cathode pin, which is usually connected to GND, the left pin next to the longest pin is Red, and the 2 pins on the right are Green and Blue.
Example
2.4 Colorful Light (For MicroPython User)
7.9 Fruit Piano (For MicroPython User)
2.4 - Colorful Light (For Arduino User)
2.4 Rainbow Light (For Piper Make User)
LED Bar Graph¶
LED Bar Graph is an LED array, which is used to connect with electronic circuit or microcontroller. It’s easy to connect LED bar graph with the circuit like as connecting 10 individual LEDs with 10 output pins. Generally we can use the LED bar graph as a Battery level Indicator, Audio equipments, and Industrial Control panels. There are many other applications of LED bar graphs.
The following is the internal schematic diagram of LED Bar Graph. Generally speaking, the side with the label is the anode and the other side is the cathode.
Example
2.2 Display the Level (For MicroPython User)
2.2 - Display the Level (For Arduino User)
2.8 Light Intensity Display (For Piper Make User)
7-segment Display¶
A 7-segment display is an 8-shaped component which packages 7 LEDs. Each LED is called a segment - when energized, one segment forms part of a numeral to be displayed.
There are two types of pin connection: Common Cathode (CC) and Common Anode (CA). As the name suggests, a CC display has all the cathodes of the 7 LEDs connected when a CA display has all the anodes of the 7 segments connected.
In this kit, we use the Common Cathode 7-segment display, here is the electronic symbol.
Each of the LEDs in the display is given a positional segment with one of its connection pins led out from the rectangular plastic package. These LED pins are labeled from “a” through to “g” representing each individual LED. The other LED pins are connected together forming a common pin. So by forward biasing the appropriate pins of the LED segments in a particular order, some segments will brighten and others stay dim, thus showing the corresponding character on the display.
Display Codes
To help you get to know how 7-segment displays(Common Cathode) display Numbers, we have drawn the following table. Numbers are the number 0-F displayed on the 7-segment display; (DP) GFEDCBA refers to the corresponding LED set to 0 or 1, For example, 00111111 means that DP and G are set to 0, while others are set to 1. Therefore, the number 0 is displayed on the 7-segment display, while HEX Code corresponds to hexadecimal number.
Numbers |
Binary Code |
Hex Code |
---|---|---|
0 |
00111111 |
0x3f |
1 |
00000110 |
0x06 |
2 |
01011011 |
0x5b |
3 |
01001111 |
0x4f |
4 |
01100110 |
0x66 |
5 |
01101101 |
0x6d |
6 |
01111101 |
0x7d |
7 |
00000111 |
0x07 |
8 |
01111111 |
0x7f |
9 |
01101111 |
0x6f |
A |
01110111 |
0x77 |
B |
01111100 |
0x7c |
C |
00111001 |
0x39 |
D |
01011110 |
0x5e |
E |
01111001 |
0x79 |
F |
01110001 |
0x71 |
Example
5.2 Number Display (For MicroPython User)
5.2 - Number Display (For Arduino User)
4-Digit 7-Segment Display¶
4-Digit 7-segment display consists of four 7- segment displays working together.
The 4-digtal 7-segment display works independently. It uses the principle of human visual persistence to quickly display the characters of each 7-segment in a loop to form continuous strings.
For example, when “1234” is displayed on the display, “1” is displayed on the first 7-segment, and “234” is not displayed. After a period of time, the second 7-segment shows “2”, the 1st 3th 4th of 7-segment does not show, and so on, the four digital display show in turn. This process is very short (typically 5ms), and because of the optical afterglow effect and the principle of visual residue, we can see four characters at the same time.
Display Codes
To help you get to know how 7-segment displays(Common Cathode) display Numbers, we have drawn the following table. Numbers are the number 0-F displayed on the 7-segment display; (DP) GFEDCBA refers to the corresponding LED set to 0 or 1, For example, 00111111 means that DP and G are set to 0, while others are set to 1. Therefore, the number 0 is displayed on the 7-segment display, while HEX Code corresponds to hexadecimal number.
Numbers |
Binary Code |
Hex Code |
---|---|---|
0 |
00111111 |
0x3f |
1 |
00000110 |
0x06 |
2 |
01011011 |
0x5b |
3 |
01001111 |
0x4f |
4 |
01100110 |
0x66 |
5 |
01101101 |
0x6d |
6 |
01111101 |
0x7d |
7 |
00000111 |
0x07 |
8 |
01111111 |
0x7f |
9 |
01101111 |
0x6f |
A |
01110111 |
0x77 |
B |
01111100 |
0x7c |
C |
00111001 |
0x39 |
D |
01011110 |
0x5e |
E |
01111001 |
0x79 |
F |
01110001 |
0x71 |
Example
5.3 Time Counter (For MicroPython User)
7.4 Passager Counter (For MicroPython User)
7.5 GAME - 10 Second (For MicroPython User)
7.6 Traffic Light (For MicroPython User)
5.3 - Time Counter (For Arduino User)
LED Matrix¶
Generally, LED dot matrix can be categorized into two types: common cathode (CC) and common anode (CA). They look much alike, but internally the difference lies. You can tell by test. A CA one is used in this kit. You can see 788BS labeled at the side.
See the figure below. The pins are arranged at the two ends at the back. Take the label side for reference: pins on this end are pin 1-8, and oh the other are pin 9-16.
The external view:
Below the figures show their internal structure. You can see in a CA LED dot matrix, ROW represents the anode of the LED, and COL is cathode; it’s contrary for a CC one. One thing in common: for both types, pin 13, 3, 4, 10, 6, 11, 15, and 16 are all COL, when pin 9, 14, 8, 12, 1, 7, 2, and 5 are all ROW. If you want to turn on the first LED at the top left corner, for a CA LED dot matrix, just set pin 9 as High and pin 13 as Low, and for a CC one, set pin 13 as High and pin 9 as Low. If you want to light up the whole first column, for CA, set pin 13 as Low and ROW 9, 14, 8, 12, 1, 7, 2, and 5 as High, when for CC, set pin 13 as High and ROW 9, 14, 8, 12, 1, 7, 2, and 5 as Low. Consider the following figures for better understanding.
The internal view:
Pin numbering corresponding to the above rows and columns:
COL |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
Pin No. |
13 |
3 |
4 |
10 |
6 |
11 |
15 |
16 |
ROW |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
Pin No. |
9 |
14 |
8 |
12 |
1 |
7 |
2 |
5 |
In addition, two 74HC595 chips are used here. One is to control the rows of the LED dot matrix while the other, the columns.
Example
5.4 8x8 Pixel Graphics (For MicroPython User)
7.12 Digital Bubble Level (For MicroPython User)
5.4 - 8x8 Pixel Graphics (For Arduino User)
I2C LCD1602¶
GND: Ground
VCC: Voltage supply, 5V.
SDA: Serial data line. Connect to VCC through a pullup resistor.
SCL: Serial clock line. Connect to VCC through a pullup resistor.
As we all know, though LCD and some other displays greatly enrich the man-machine interaction, they share a common weakness. When they are connected to a controller, multiple IOs will be occupied of the controller which has no so many outer ports. Also it restricts other functions of the controller.
Therefore, LCD1602 with an I2C module is developed to solve the problem. The I2C module has a built-in PCF8574 I2C chip that converts I2C serial data to parallel data for the LCD display.
I2C Address
The default address is basically 0x27, in a few cases it may be 0x3F.
Taking the default address of 0x27 as an example, the device address can be modified by shorting the A0/A1/A2 pads; in the default state, A0/A1/A2 is 1, and if the pad is shorted, A0/A1/A2 is 0.
Backlight/Contrast
Backlight can be enabled by jumper cap, unplugg the jumper cap to disable the backlight. The blue potentiometer on the back is used to adjust the contrast (the ratio of brightness between the brightest white and the darkest black).
Shorting Cap: Backlight can be enabled by this cap,unplugg this cap to disable the backlight.
Potentiometer: It is used to adjust the contrast (the clarity of the displayed text), which is increased in the clockwise direction and decreased in the counterclockwise direction.
Example
3.4 Liquid Crystal Display (For MicroPython User)
7.2 Room Temperature Meter (For MicroPython User)
7.7 Guess Number (For MicroPython User)
3.4 - Liquid Crystal Display (For Arduino User)
WS2812 RGB 8 LEDs Strip¶
The WS2812 RGB 8 LEDs Strip is composed of 8 RGB LEDs. Only one pin is required to control all the LEDs. Each RGB LED has a WS2812 chip, which can be controlled independently. It can realize 256-level brightness display and complete true color display of 16,777,216 colors. At the same time, the pixel contains an intelligent digital interface data latch signal shaping amplifier drive circuit, and a signal shaping circuit is built in to effectively ensure the color height of the pixel point light Consistent.
It is flexible, can be docked, bent, and cut at will, and the back is equipped with adhesive tape, which can be fixed on the uneven surface at will, and can be installed in a narrow space.
Features
Work Voltage: DC5V
IC: One IC drives one RGB LED
Consumption: 0.3w each LED
Working Temperature: -15-50
Color: Full color RGB
RGB Type:5050RGB(Built-in IC WS2812B)
Light Strip Thickness: 2mm
Each LED can be controlled individually
WS2812B Introdction
WS2812B is a intelligent control LED light source that the control circuit and RGB chip are integrated in a package of 5050 components. It internal include intelligent digital port data latch and signal reshaping ampli fication drive circuit. Also include a precision internal oscillator and a 12V voltage programmable constant curr e-nt control part, effectively ensuring the pixel point light color height consistent.
The data transfer protocol use single NZR communication mode. After the pixel power-on reset, the DIN port receive data from controller, the first pixel collect initial 24bit data then sent to the internal data latch, the other data which reshaping by the internal signal reshaping amplification circuit sent to the next cascade pixel through the DO port. After transmission for each pixel,the signal to reduce 24bit. pixel adopt auto resha -ping transmit technology, making the pixel cascade number is not limited the signal transmission, only depend on the speed of signal transmission.
LED with low driving voltage, environmental protection and energy saving, high brightness, scattering angl e is large, good consistency, low power, long life and other advantages. The control chip integrated in LED above becoming more simple circuit, small volume, convenient installation.
Example
3.3 RGB LED Strip (For MicroPython User)
7.8 RFID Music Player (For MicroPython User)
3.3 - RGB LED Strip (For Arduino User)
2.10 Flowing LEDs (For Piper Make User)
Sound
Buzzer¶
As a type of electronic buzzer with an integrated structure, buzzers, which are supplied by DC power, are widely used in computers, printers, photocopiers, alarms, electronic toys, automotive electronic devices, telephones, timers and other electronic products or voice devices.
Buzzers can be categorized as active and passive ones (see the following picture). Turn the buzzer so that its pins are facing up, and the buzzer with a green circuit board is a passive buzzer, while the one enclosed with a black tape is an active one.
The difference between an active buzzer and a passive buzzer:
An active buzzer has a built-in oscillating source, so it will make sounds when electrified. But a passive buzzer does not have such source, so it will not beep if DC signals are used; instead, you need to use square waves whose frequency is between 2K and 5K to drive it. The active buzzer is often more expensive than the passive one because of multiple built-in oscillating circuits.
The following is the electrical symbol of a buzzer. It has two pins with positive and negative poles. With a + in the surface represents the anode and the other is the cathode.
You can check the pins of the buzzer, the longer one is the anode and the shorter one is the cathode. Please don’t mix them up when connecting, otherwise the buzzer will not make sound.
Example
3.1 Beep (For MicroPython User)
3.2 Custom Tone (For MicroPython User)
7.1 Light Theremin (For MicroPython User)
7.3 Alarm Siren Lamp (For MicroPython User)
7.8 RFID Music Player (For MicroPython User)
7.9 Fruit Piano (For MicroPython User)
7.10 Reversing Aid (For MicroPython User)
3.1 - Beep (For Arduino User)
3.2 - Custom Tone (For Arduino User)
2.3 Service Bell (For Piper Make User)
2.11 Reversing System (For Piper Make User)
2.13 Reaction Game (For Piper Make User)
Actuators
DC Motor¶
This is a 3V DC motor. When you give a high level and a low level to each of the 2 terminals, it will rotate.
Size: 25*20*15MM
Operation Voltage: 1-6V
Free-run Current (3V): 70m
A Free-run Speed (3V): 13000RPM
Stall Current (3V): 800mA
Shaft Diameter: 2mm
Direct current (DC) motor is a continuous actuator that converts electrical energy into mechanical energy. DC motors make rotary pumps, fans, compressors, impellers, and other devices work by producing continuous angular rotation.
A DC motor consists of two parts, the fixed part of the motor called the stator and the internal part of the motor called the rotor (or armature of a DC motor) that rotates to produce motion. The key to generating motion is to position the armature within the magnetic field of the permanent magnet (whose field extends from the north pole to the south pole). The interaction of the magnetic field and the moving charged particles (the current-carrying wire generates the magnetic field) produces the torque that rotates the armature.
Current flows from the positive terminal of the battery through the circuit, through the copper brushes to the commutator, and then to the armature. But because of the two gaps in the commutator, this flow reverses halfway through each complete rotation. This continuous reversal essentially converts the DC power from the battery to AC, allowing the armature to experience torque in the right direction at the right time to maintain rotation.
Example
3.5 Small Fan (For MicroPython User)
3.5 - Small Fan (For Arduino User)
2.12 Smart Fan (For Piper Make User)
Servo¶
A servo is generally composed of the following parts: case, shaft, gear system, potentiometer, DC motor, and embedded board.
It works like this: The microcontroller sends out PWM signals to the servo, and then the embedded board in the servo receives the signals through the signal pin and controls the motor inside to turn. As a result, the motor drives the gear system and then motivates the shaft after deceleration. The shaft and potentiometer of the servo are connected together. When the shaft rotates, it drives the potentiometer, so the potentiometer outputs a voltage signal to the embedded board. Then the board determines the direction and speed of rotation based on the current position, so it can stop exactly at the right position as defined and hold there.
The angle is determined by the duration of a pulse that is applied to the control wire. This is called Pulse width Modulation. The servo expects to see a pulse every 20 ms. 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 (neutral position). When a pulse is sent to a servo that is less than 1.5 ms, the servo rotates to a position and holds its output shaft some number of degrees counterclockwise from the neutral point. When the pulse is wider than 1.5 ms the opposite occurs. The minimal width and the maximum width of pulse that will command the servo to turn to a valid position are functions of each servo. Generally the minimum pulse will be about 0.5 ms wide and the maximum pulse will be 2.5 ms wide.
Example
3.7 Swinging Servo (For MicroPython User)
7.11 Somatosensory Controller (For MicroPython User)
3.7 - Swinging Servo (For Arduino User)
2.6 Smart Water Tank (For Piper Make User)
2.7 Swing Servo (For Piper Make User)
2.9 Lucky Cat (For Piper Make User)
Centrifugal Pump¶
The centrifugal pump converts rotational kinetic energy into hydrodynamic energy to transport fluid. The rotation energy comes from the electric motor. The fluid enters the pump impeller along or near the rotating shaft, is accelerated by the impeller, flows radially outward into the diffuser or volute chamber, and then flows out from there.
Common uses of centrifugal pumps include water, sewage, agricultural, petroleum, and petrochemical pumping.
- Features
Voltage Scope: DC 3 ~ 4.5V
Operating Current: 120 ~ 180mA
Power: 0.36 ~ 0.91W
Max Water Head: 0.35 ~ 0.55M
Max Flow Rate: 80 ~ 100 L/H
Continuous Working Life: 100 hours
Water Fing Grade: IP68
Driving Mode: DC, Magnetic Driving
Material: Engineering Plastic
Outlet Outside Diameter: 7.8 mm
Outlet Inside Diameter: 6.5 mm
It is a submersible pump and should be used that way. It tends to heat too much that there’s a risk of overheating if you turn it on unsubmerged.
Example
3.6 Pumping (For MicroPython User)
3.6 - Pumping (For Arduino User)
Relay¶
As we may know, relay is a device which is used to provide connection between two or more points or devices in response to the input signal applied. In other words, relays provide isolation between the controller and the device as devices may work on AC as well as on DC. However, they receive signals from a microcontroller which works on DC hence requiring a relay to bridge the gap. Relay is extremely useful when you need to control a large amount of current or voltage with small electrical signal.
There are 5 parts in every relay:
Electromagnet - It consists of an iron core wounded by coil of wires. When electricity is passed through, it becomes magnetic. Therefore, it is called electromagnet.
Armature - The movable magnetic strip is known as armature. When current flows through them, the coil is it energized thus producing a magnetic field which is used to make or break the normally open (N/O) or normally close (N/C) points. And the armature can be moved with direct current (DC) as well as alternating current (AC).
Spring - When no currents flow through the coil on the electromagnet, the spring pulls the armature away so the circuit cannot be completed.
Set of electrical contacts - There are two contact points:
Normally open - connected when the relay is activated, and disconnected when it is inactive.
Normally close - not connected when the relay is activated, and connected when it is inactive.
Molded frame - Relays are covered with plastic for protection.
The working principle of relay is simple. When power is supplied to the relay, currents start flowing through the control coil; as a result, the electromagnet starts energizing. Then the armature is attracted to the coil, pulling down the moving contact together thus connecting with the normally open contacts. So the circuit with the load is energized. Then breaking the circuit would a similar case, as the moving contact will be pulled up to the normally closed contacts under the force of the spring. In this way, the switching on and off of the relay can control the state of a load circuit.
Example
2.16 Control Another Circuit (For MicroPython User)
2.16 - Control Another Circuit (For Arduino User)
Power Supply Module¶
A 3.3V and 5V breadboard power module with series diode and reverse polarity protection. The module can accept 6.5V to 12V input, and can generate 3.3V and +5V. For experimenters who must test/prototype electronic circuits on breadboards or perforated/veroboards, this is a must-have power supply module.
- Features
Plug directly to MB102 Standard breadboard.
Input voltage: 6.5-12 V (DC) or 5V USB power supply.
Output voltage: 3.3V and 5V can switch over.
Maximum output current: <700 mA.
External Input voltage ON/OFF switch.
Independent control of upper and Lower Bread Board Power Rails. Can switch over to 0V, 3.3V, 5V using jumpers on any rail.
On-board two groups of 3.3V, 5V DC output plug pin, convenient external lead use.
USB device connector onboard for power output to external device.
Size: 5.3cm x 3.5cm.
Example
3.5 Small Fan (For MicroPython User)
3.5 - Small Fan (For Arduino User)
2.16 Control Another Circuit (For MicroPython User)
2.16 - Control Another Circuit (For Arduino User)
3.6 Pumping (For MicroPython User)
3.6 - Pumping (For Arduino User)
Controller
Button¶
Buttons are a common component used to control electronic devices. They are usually used as switches to connect or break circuits. Although buttons come in a variety of sizes and shapes, the one used here is a 6mm mini-button as shown in the following pictures. Pin 1 is connected to pin 2 and pin 3 to pin 4. So you just need to connect either of pin 1 and pin 2 to pin 3 or pin 4.
The following is the internal structure of a button. The symbol on the right below is usually used to represent a button in circuits.
Since the pin 1 is connected to pin 2, and pin 3 to pin 4, when the button is pressed, the 4 pins are connected, thus closing the circuit.
Example
2.5 Reading Button Value (For MicroPython User)
2.5 - Reading Button Value (For Arduino User)
2.2 Button (For Piper Make User)
2.4 Rainbow Light (For Piper Make User)
2.5 Drum Kit (For Piper Make User)
2.13 Reaction Game (For Piper Make User)
Micro Switch¶
The construction of a micro switch is really simple. The main parts of the switch are:
1.Plunger (Actuator)
2.Cover
3.Moving piece
4.Support
5.Case
6.NO terminal: normally open
7.NC terminal: normally closed
8.Contact
9.Moving arm
After a micro switch makes physical contact with an object, its contacts change position. The basic working principle is as follows.
When the plunger is in the released or rest position.
The normally closed circuit can carry current.
The normally open circuit is electrically insulated.
When the plunger is depressed or switched.
The normally closed circuit is open.
The normally open circuit is closed.
Example
2.8 Press Gently (For MicroPython User)
2.8 - Press Gently (For Arduino User)
2.3 Service Bell (For Piper Make User)
Slide Switch¶
A slide switch, just as its name implies, is to slide the switch bar to connect or break the circuit, and further switch circuits. The common-used types are SPDT, SPTT, DPDT, DPTT etc. The slide switch is commonly used in low-voltage circuit. It has the features of flexibility and stability, and applies in electric instruments and electric toys widely. How it works: Set the middle pin as the fixed one. When you pull the slide to the left, the two pins on the left are connected; when you pull it to the right, the two pins on the right are connected. Thus, it works as a switch connecting or disconnecting circuits. See the figure below:
The circuit symbol of the slide switch is shown as below. The pin2 in the figure refers to the middle pin.
Example
2.7 Toggle Left and Right (For MicroPython User)
7.3 Alarm Siren Lamp (For MicroPython User)
2.7 - Toggle Left and Right (For Arduino User)
2.5 Drum Kit (For Piper Make User)
Potentiometer¶
Potentiometer is also a resistance component with 3 terminals and its resistance value can be adjusted according to some regular variation.
Potentiometers come in various shapes, sizes, and values, but they all have the following things in common:
They have three terminals (or connection points).
They have a knob, screw, or slider that can be moved to vary the resistance between the middle terminal and either one of the outer terminals.
The resistance between the middle terminal and either one of the outer terminals varies from 0 Ω to the maximum resistance of the pot as the knob, screw, or slider is moved.
Here is the circuit symbol of potentiometer.
The functions of the potentiometer in the circuit are as follows:
Serving as a voltage divider
Potentiometer is a continuously adjustable resistor. When you adjust the shaft or sliding handle of the potentiometer, the movable contact will slide on the resistor. At this point, a voltage can be output depending on the voltage applied onto the potentiometer and the angle the movable arm has rotated to or the travel it has made.
Serving as a rheostat
When the potentiometer is used as a rheostat, connect the middle pin and one of the other 2 pins in the circuit. Thus you can get a smoothly and continuously changed resistance value within the travel of the moving contact.
Serving as a current controller
When the potentiometer acts as a current controller, the sliding contact terminal must be connected as one of the output terminals.
If you want to know more about potentiometer, refer to: Potentiometer - Wikipedia
Example
2.11 Turn the Knob (For MicroPython User)
2.11 - Turn the Knob (For Arduino User)
2.7 Swing Servo (For Piper Make User)
Infrared-Receiver¶
IR Receiver Module¶
S: Signal output
+:VCC
-: GND
An infrared-receiver is a component which receives infrared signals and can independently receive infrared rays and output signals compatible with TTL level. It is similar with a normal plastic-packaged transistor in size and is suitable for all kinds of infrared remote control and infrared transmission.
Infrared, or IR, communication is a popular, low-cost, easy-to-use wireless communication technology. Infrared light has a slightly longer wavelength than visible light, so it is imperceptible to the human eye - ideal for wireless communication. A common modulation scheme for infrared communication is 38KHz modulation.
Adopted HX1838 IR Receiver Sensor, high sensitivity
Can be used for remote control
Power Supply: 3.3~5V
Interface: Digital
Modulate Frequency: 38Khz
Remote Control¶
This is a Mini thin infrared wireless remote control with 21 function buttons and a transmitting distance of up to 8 meters, which is suitable for operating a wide range of devices in a kid’s room.
Size: 85x39x6mm
Remote control range: 8-10m
Battery: 3V button type lithium manganese battery
Infrared carrier frequency: 38KHz
Surface paste material: 0.125mm PET
Effective life: more than 20,000 times
Example
6.4 IR Remote Control (For MicroPython User)
6.4 - IR Remote Control (For Arduino User)
Joystick¶
The basic idea of a joystick is to translate the movement of a stick into electronic information that a computer can process.
In order to communicate a full range of motion to the computer, a joystick needs to measure the stick’s position on two axes – the X-axis (left to right) and the Y-axis (up and down). Just as in basic geometry, the X-Y coordinates pinpoint the stick’s position exactly.
To determine the location of the stick, the joystick control system simply monitors the position of each shaft. The conventional analog joystick design does this with two potentiometers, or variable resistors.
The joystick also has a digital input that is actuated when the joystick is pressed down.
Example
4.1 Toggle the Joystick (For MicroPython User)
4.1 - Toggle the Joystick (For Arduino User)
Keypad¶
Microcontroller system, if the use of more keys such as electronic code lock, telephone keypad, etc. generally have at least 12 to 16 keys, usually using a matrix keyboard.
Matrix keypad is also called row keypad, it is a keypad with four I/O lines as row lines and four I/O lines as column lines. One key is set at each intersection of the row and column lines. Thus the number of keys on the keyboard is 4*4. This row and column keyboard structure can effectively improve the utilization of I/O ports in a microcontroller system.
Their contacts are accessed via a header suitable for connection with a ribbon cable or insertion into a printed circuit board. In some keypads, each button connects with a separate contact in the header, while all the buttons share a common ground.
More often, the buttons are matrix encoded, meaning that each of them bridges a unique pair of conductors in a matrix. This configuration is suitable for polling by a microcontroller, which can be programmed to send an output pulse to each of the four horizontal wires in turn. During each pulse, it checks the remaining four vertical wires in sequence, to determine which one, if any, is carrying a signal. Pullup or pulldown resistors should be added to the input wires to prevent the inputs of the microcontroller from behaving unpredictably when no signal is present.
Example
4.2 4x4 Keypad (For MicroPython User)
7.7 Guess Number (For MicroPython User)
4.2 - 4x4 Keypad (For Arduino User)
MPR121¶
3.3V: Power supply
IRQ: Open Collector Interrupt Output Pin, active low
SCL: I2C Clock
SDA: I2C Data
ADD: I2C Address Select Input Pin. Connect the ADDR pin to the VSS, VDD, SDA or SCL line, the resulting I2C addresses are 0x5A, 0x5B, 0x5C and 0x5D respectively
GND: Ground
0~11: Electrode 0~11, electrode is a touch sensor. Typically, electrodes can just be some piece of metal, or a wire. But some times depending on the length of our wire, or the material the electrode is on, it can make triggering the sensor difficult. For this reason, the MPR121 allows you to configure what is needed to trigger and untrigger an electrode.
MPR121 OVERVIEW
The MPR121 is the second generation capacitive touch sensor controller after the initial release of the MPR03x series devices. The MPR121 features increased internal intelligence, some of the major additions include an increased electrode count, a hardware configurable I2C address, an expanded filtering system with debounce, and completely independent electrodes with auto-configuration built in. The device also features a 13th simulated sensing channel dedicated for near proximity detection using the multiplexed sensing inputs.
Features
- Low power operation
1.71 V to 3.6 V supply operation
29 μA supply current at 16 ms sampling interval period
3 μA Stop mode current
- 12 capacitance sensing inputs
8 inputs are multifunctional for LED driver and GPIO
- Complete touch detection
Auto-configuration for each sensing input
Auto-calibration for each sensing input
Touch/release threshold and debounce for touch detection
I2C interface, with Interrupt output
3 mm x 3 mm x 0.65 mm 20 lead QFN package
-40°C to +85°C operating temperature range
Example
4.3 Electrode Keyboard (For MicroPython User)
7.9 Fruit Piano (For MicroPython User)
4.3 - Electrode Keyboard (For Arduino User)
MFRC522 Module¶
MFRC522 is a kind of integrated read and write card chip. It is commonly used in the radio at 13.56MHz. Launched by the NXP Company, it is a low-voltage, low-cost, and small-sized non-contact card chip, a best choice of intelligent instrument and portable handheld device.
The MF RC522 uses advanced modulation and demodulation concept which fully presented in all types of 13.56MHz passive contactless communication methods and protocols. In addition, it supports rapid CRYPTO1 encryption algorithm to verify MIFARE products. MFRC522 also supports MIFARE series of high-speed non-contact communication, with a two-way data transmission rate up to 424kbit/s. As a new member of the 13.56MHz highly integrated reader card series, MF RC522 is much similar to the existing MF RC500 and MF RC530 but there also exists great differences. It communicates with the host machine via the serial manner which needs less wiring. You can choose between SPI, I2C and serial UART mode (similar to RS232), which helps reduce the connection, save PCB board space (smaller size), and reduce cost.
Example
6.5 Radio Frequency Identification (For MicroPython User)
7.8 RFID Music Player (For MicroPython User)
6.5 - Radio Frequency Identification (For Arduino User)
Sensor
Photoresistor¶
A photoresistor or photocell is a light-controlled variable resistor. The resistance of a photoresistor decreases with increasing incident light intensity; in other words, it exhibits photo conductivity.
A photoresistor can be applied in light-sensitive detector circuits and light-activated and dark-activated switching circuits acting as a resistance semiconductor. In the dark, a photoresistor can have a resistance as high as several megaohms (MΩ), while in the light, a photoresistor can have a resistance as low as a few hundred ohms.
Here is the electronic symbol of photoresistor.
Example
2.12 Feel the Light (For MicroPython User)
7.1 Light Theremin (For MicroPython User)
2.12 - Feel the Light (For Arduino User)
2.8 Light Intensity Display (For Piper Make User)
Thermistor¶
A thermistor is a type of resistor whose resistance is strongly dependent on temperature, more so than in standard resistors. The word is a combination of thermal and resistor. Thermistors are widely used as inrush current limiters, temperature sensors (negative temperature coefficient or NTC type typically), self-resetting overcurrent protectors, and self-regulating heating elements (positive temperature coefficient or PTC type typically).
Here is the electronic symbol of thermistor.
Thermistors are of two opposite fundamental types:
With NTC thermistors, resistance decreases as temperature rises usually due to an increase in conduction electrons bumped up by thermal agitation from valency band. An NTC is commonly used as a temperature sensor, or in series with a circuit as an inrush current limiter.
With PTC thermistors, resistance increases as temperature rises usually due to increased thermal lattice agitations particularly those of impurities and imperfections. PTC thermistors are commonly installed in series with a circuit, and used to protect against overcurrent conditions, as resettable fuses.
In this kit we use an NTC one. Each thermistor has a normal resistance. Here it is 10k ohm, which is measured under 25 degree Celsius.
Here is the relation between the resistance and temperature:
RT = RN * expB(1/TK – 1/TN)
RT is the resistance of the NTC thermistor when the temperature is TK.
RN is the resistance of the NTC thermistor under the rated temperature TN. Here, the numerical value of RN is 10k.
TK is a Kelvin temperature and the unit is K. Here, the numerical value of TK is 273.15 + degree Celsius.
TN is a rated Kelvin temperature; the unit is K too. Here, the numerical value of TN is 273.15+25.
And B(beta), the material constant of NTC thermistor, is also called heat sensitivity index with a numerical value 3950.
exp is the abbreviation of exponential, and the base number e is a natural number and equals 2.7 approximately.
Convert this formula TK=1/(ln(RT/RN)/B+1/TN) to get Kelvin temperature that minus 273.15 equals degree Celsius.
This relation is an empirical formula. It is accurate only when the temperature and resistance are within the effective range.
Example
2.13 Thermometer (For MicroPython User)
7.2 Room Temperature Meter (For MicroPython User)
2.13 - Thermometer (For Arduino User)
Tilt Switch¶
The tilt switch used here is a ball one with a metal ball inside. It is used to detect inclinations of a small angle.
The principle is very simple. When the switch is tilted in a certain angle, the ball inside rolls down and touches the two contacts connected to the pins outside, thus triggering circuits. Otherwise the ball will stay away from the contacts, thus breaking the circuits.
Example
2.6 Tilt It! (For MicroPython User)
7.5 GAME - 10 Second (For MicroPython User)
2.6 - Tilt It! (For Arduino User)
2.10 Flowing LEDs (For Piper Make User)
Reed Switch¶
The Reed Switch is an electrical switch that operates by means of an applied magnetic field. It was invented by Walter B. Ellwood of Bell Telephone Laboratories in 1936 and patented in the United States on June 27, 1940, under patent number 2264746 .
The principle of operation of a reed switch is very simple. Two reeds (usually made of iron and nickel, two metals) that overlap at the end points are sealed in a glass tube, with the two reeds overlapping and separated by a small gap (only about a few microns). The glass tube is filled with a high purity inert gas (such as nitrogen), and some reed switches are made to have a vacuum inside to enhance their high voltage performance.
The reed acts as a magnetic flux conductor. The two reeds are not in contact when not yet in operation; when passing through a magnetic field generated by a permanent magnet or electromagnetic coil, the applied magnetic field causes the two reeds to have different polarities near their endpoints, and when the magnetic force exceeds the spring force of the reeds themselves, the two reeds will be drawn together to conduct the circuit; when the magnetic field weakens or disappears, the reeds are released due to their own elasticity, and the contact surfaces will separate to open the circuit.
Example
2.9 Feel the Magnetism (For MicroPython User)
2.9 - Feel the Magnetism (For Arduino User)
PIR Motion Sensor¶
The PIR sensor detects infrared heat radiation that can be used to detect the presence of organisms that emit infrared heat radiation.
The PIR sensor is split into two slots that are connected to a differential amplifier. Whenever a stationary object is in front of the sensor, the two slots receive the same amount of radiation and the output is zero. Whenever a moving object is in front of the sensor, one of the slots receives more radiation than the other , which makes the output fluctuate high or low. This change in output voltage is a result of detection of motion.
After the sensing module is wired, there is a one-minute initialization. During the initialization, module will output for 0~3 times at intervals. Then the module will be in the standby mode. Please keep the interference of light source and other sources away from the surface of the module so as to avoid the misoperation caused by the interfering signal. Even you’d better use the module without too much wind, because the wind can also interfere with the sensor.
Distance Adjustment
Turning the knob of the distance adjustment potentiometer clockwise, the range of sensing distance increases, and the maximum sensing distance range is about 0-7 meters. If turn it anticlockwise, the range of sensing distance is reduced, and the minimum sensing distance range is about 0-3 meters.
Delay adjustment
Rotate the knob of the delay adjustment potentiometer clockwise, you can also see the sensing delay increasing. The maximum of the sensing delay can reach up to 300s. On the contrary, if rotate it anticlockwise, you can shorten the delay with a minimum of 5s.
Two Trigger Modes
Choosing different modes by using the jumper cap.
H: Repeatable trigger mode, after sensing the human body, the module outputs high level. During the subsequent delay period, if somebody enters the sensing range,the output will keep being the high level.
L: Non-repeatable trigger mode, outputs high level when it senses the human body. After the delay, the output will change from high level into low level automatically.
Example
2.10 Detect Human Movement (For MicroPython User)
7.4 Passager Counter (For MicroPython User)
2.10 - Detect Human Movement (For Arduino User)
2.9 Lucky Cat (For Piper Make User)
Water Level Sensor¶
The water level sensor transmits the sensed water level signal to the controller, and the computer in the controller compares the measured water level signal with the set signal to derive the deviation, and then issues “on” and “off” commands to the feedwater electric valve according to the nature of the deviation to ensure that the vessel reaches the set water level.
The water level sensor has ten exposed copper traces, five for the Power traces and five for the Sensor traces, which are crossed and bridged by water when flooded. The circuit board has a power LED that lights up when the board is energized.
The combination of these traces acts like a variable resistor, changing the resistance value according to the water level. To be more precise, the more water the sensor is immersed in, the better the conductivity and the lower the resistance. Conversely, the less conductive it is, the higher the resistance. Next, the sensor will process the output signal voltage which will be sent to the microcontroller, thus helping us to determine the water level.
Warning
The sensor cannot be fully submerged in water, please only leave the part where the ten traces are located in contact with water. In addition, energizing the sensor in a humid environment will speed up the corrosion of the probe and cut the life of the sensor, so we recommend that you only supply power when taking readings.
Example
2.14 Feel the Water Level (For MicroPython User)
2.14 - Feel the Water Level (For Arduino User)
2.6 Smart Water Tank (For Piper Make User)
Ultrasonic Module¶
Ultrasonic ranging module provides 2cm - 400cm non-contact measurement function, and the ranging accuracy can reach to 3mm. It can ensure that the signal is stable within 5m, and the signal is gradually weakened after 5m, till the 7m position disappears.
The module includes ultrasonic transmitters, receiver and control circuit. The basic principles are as follows:
Use an IO flip-flop to process a high level signal of at least 10us.
The module automatically sends eight 40khz and detects if there is a pulse signal return.
If the signal returns, passing the high level, the high output IO duration is the time from the transmission of the ultrasonic wave to the return of it. Here, test distance = (high time x sound speed (340 m / s) / 2.
The timing diagram is shown below. You only need to supply a short 10us pulse for the trigger input to start the ranging, and then the module will send out an 8 cycle burst of ultrasound at 40 kHz and raise its echo. You can calculate the range through the time interval between sending trigger signal and receiving echo signal.
Formula: us / 58 = centimeters or us / 148 =inch; or: the range = high level time * velocity (340M/S) / 2; you are suggested to use measurement cycle over 60ms in order to prevent signal collisions of trigger signal and the echo signal.
Example
6.1 Measuring Distance (For MicroPython User)
7.10 Reversing Aid (For MicroPython User)
6.1 - Measuring Distance (For Arduino User)
2.11 Reversing System (For Piper Make User)
DHT11 Humiture Sensor¶
The digital temperature and humidity sensor DHT11 is a composite sensor that contains a calibrated digital signal output of temperature and humidity. The technology of a dedicated digital modules collection and the temperature and humidity sensing technology are applied to ensure that the product has high reliability and excellent long-term stability.
The sensor includes a resistive sense of wet component and an NTC temperature measurement device, and is connected with a high-performance 8-bit microcontroller.
Only three pins are available for use: VCC, GND, and DATA. The communication process begins with the DATA line sending start signals to DHT11, and DHT11 receives the signals and returns an answer signal. Then the host receives the answer signal and begins to receive 40-bit humiture data (8-bit humidity integer + 8-bit humidity decimal + 8-bit temperature integer + 8-bit temperature decimal + 8-bit checksum).
Features
Humidity measurement range: 20 - 90%RH
Temperature measurement range: 0 - 60℃
Output digital signals indicating temperature and humidity
Working voltage:DC 5V; PCB size: 2.0 x 2.0 cm
Humidity measurement accuracy: ±5%RH
Temperature measurement accuracy: ±2℃
Example
6.2 Temperature - Humidity (For MicroPython User)
6.2 - Temperature - Humidity (For Arduino User)
MPU6050¶
MPU6050
The MPU-6050 is a 6-axis(combines 3-axis Gyroscope, 3-axis Accelerometer) motion tracking devices.
Its three coordinate systems are defined as follows:
Put MPU6050 flat on the table, assure that the face with label is upward and a dot on this surface is on the top left corner. Then the upright direction upward is the z-axis of the chip. The direction from left to right is regarded as the X-axis. Accordingly the direction from back to front is defined as the Y-axis.
3-axis Accelerometer
The accelerometer works on the principle of piezo electric effect, the ability of certain materials to generate an electric charge in response to applied mechanical stress.
Here, imagine a cuboidal box, having a small ball inside it, like in the picture above. The walls of this box are made with piezo electric crystals. Whenever you tilt the box, the ball is forced to move in the direction of the inclination, due to gravity. The wall with which the ball collides, creates tiny piezo electric currents. There are totally, three pairs of opposite walls in a cuboid. Each pair corresponds to an axis in 3D space: X, Y and Z axes. Depending on the current produced from the piezo electric walls, we can determine the direction of inclination and its magnitude.
We can use the MPU6050 to detect its acceleration on each coordinate axis (in the stationary desktop state, the Z-axis acceleration is 1 gravity unit, and the X and Y axes are 0). If it is tilted or in a weightless/overweight condition, the corresponding reading will change.
There are four kinds of measuring ranges that can be selected programmatically: +/-2g, +/-4g, +/-8g, and +/-16g (2g by default) corresponding to each precision. Values range from -32768 to 32767.
The reading of accelerometer is converted to an acceleration value by mapping the reading from the reading range to the measuring range.
Acceleration = (Accelerometer axis raw data / 65536 * full scale Acceleration range) g
Take the X-axis as an example, when Accelerometer X axis raw data is 16384 and the range is selected as +/-2g:
Acceleration along the X axis = (16384 / 65536 * 4) g =1g
3-axis Gyroscope
Gyroscopes work on the principle of Coriolis acceleration. Imagine that there is a fork like structure, that is in constant back and forth motion. It is held in place using piezo electric crystals. Whenever, you try to tilt this arrangement, the crystals experience a force in the direction of inclination. This is caused as a result of the inertia of the moving fork. The crystals thus produce a current in consensus with the piezo electric effect, and this current is amplified.
The Gyroscope also has four kinds of measuring ranges: +/- 250, +/- 500, +/- 1000, +/- 2000. The calculation method and Acceleration are basically consistent.
The formula for converting the reading into angular velocity is as follows:
Angular velocity = (Gyroscope axis raw data / 65536 * full scale Gyroscope range) °/s
The X axis, for example, the Accelerometer X axis raw data is 16384 and ranges + / - 250°/ s:
Angular velocity along the X axis = (16384 / 65536 * 500)°/s =125°/s
Example
6.3 6-axis Motion Tracking (For MicroPython User)
7.11 Somatosensory Controller (For MicroPython User)
7.12 Digital Bubble Level (For MicroPython User)
6.3 - 6-axis Motion Tracking (For Arduino User)
Communication
ESP8266 Module¶
The ESP8266 is a low-cost Wi-Fi microchip, with built-in TCP/IP networking software, and microcontroller capability, produced by Espressif Systems in Shanghai, China.
The chip first came to the attention of Western makers in August 2014 with the ESP-01 module, made by a third-party manufacturer Ai-Thinker. This small module allows microcontrollers to connect to a Wi-Fi network and make simple TCP/IP connections using Hayes-style commands. However, at first, there was almost no English-language documentation on the chip and the commands it accepted. The very low price and the fact that there were very few external components on the module, which suggested that it could eventually be very inexpensive in volume, attracted many hackers to explore the module, the chip, and the software on it, as well as to translate the Chinese documentation.
Example
Electronic Circuit¶
There are many things you use every day that are powered by electricity, such as the lights in your home and the computer you are reading this on.
In order to use electricity, you must create an electrical circuit. An electric circuit consists of metal wires and electrical and electronic components.
Circuits require power from somewhere. In your home, most appliances (e.g., TVs, lights) are powered by wall outlets. But many smaller, portable circuits (e.g., electronic toys, cell phones) are powered by batteries. A battery has two terminals, one of which is called the positive terminal and is marked with a plus sign (+). Negative terminals are symbolized by minus signs (-), but are not usually printed on batteries.
For current to flow, a conductive path must connect the positive terminal of the battery to the negative terminal, which is referred to as a closed circuit(If it is disconnected, it is called an open circuit.). Electric current will flow through appliances such as lamps to make them work (e.g., light up).
A Pico has some power output pins (positive) and some ground pins (negative). You can use these pins as the positive and negative sides of the power supply by plugging the Pico into a power source.
With electricity, you can create works with light, sound, and motion. You can light up an LED by connecting the long pin to the positive terminal and the short pin to the negative terminal. The LED will break down very quickly if you do this, so you need to add a 220* resistor inside the circuit to protect it.
The circuit they form is shown below.
You may have questions this time: how do I build this circuit? Hold the wires by hand, or tape the pins and wires?
In this situation, solderless breadboards will be your strongest allies.
Hello, Breadboard!¶
A breadboard is a rectangular plastic plate with a bunch of small holes. These holes allow us to easily insert electronic components and build electronic circuits. Breadboards do not permanently fix electronic components, so we can easily repair a circuit and start over if something goes wrong.
Note
There is no need for special tools to use breadboards. However, many electronic components are very small, and a pair of tweezers can help us to pick up small parts better.
On the Internet, we can find a lot of information about breadboards.
Here are some things you should know about breadboards.
Each half-row group (such as column A-E in row 1 or column F-J in row 3) is connected. Therefore, if an electrical signal flows in from A1, it can flow out from B1, C1, D1, E1, but not from F1 or A2.
In most cases, both sides of the breadboard are used as power buses, and the holes in each column (about 50 holes) are connected together. As a general rule, positive power supplies are connected to the holes near the red wire, and negative power supplies are connected to the holes near the blue wire.
In a circuit, current flows from the positive pole to the negative pole after passing through the load. In this case, a short circuit may occur.
Let us follow the direction of the current to build the circuit!
In this circuit, we use the 3V3 pin of the Pico board to power the LED. Use a male-to-male (M2M) jumper wire to connect it to the red power bus.
To protect the LED, the current must pass through a 220 ohm resistor. Connect one end (either end) of the resistor to the red power bus, and the other end to the free row of the breadboard (row 24 in my circuit).
Note
The color ring of the 220 ohm resistor is red, red, black, black and brown.
If you pick up the LED, you will see that one of its leads is longer than the other. Connect the longer lead to the same row as the resistor, and the shorter lead to the same row across the middle gap on the breadboard.
Note
The longer lead is the anode, which represents the positive side of the circuit; the shorter lead is the cathode, which represents the negative side.
The anode needs to be connected to the GPIO pin through a resistor; the cathode needs to be connected to the GND pin.
Using a male-to-male (M2M) jumper wire, connect the LED short pin to the breadboard’s negative power bus.
Connect the GND pin of Pico to the negative power bus using a jumper.
Beware of short circuits¶
Short circuits can occur when two components that shouldn’t be connected are “accidentally” connected. This kit includes resistors, transistors, capacitors, LEDs, etc. that have long metal pins that can bump into each other and cause a short. Some circuits are simply prevented from functioning properly when a short occurs. Occasionally, a short circuit can damage components permanently, especially between the power supply and the ground bus, causing the circuit to get very hot, melting the plastic on the breadboard and even burning the components!
Therefore, always make sure that the pins of all the electronics on the breadboard are not touching each other.
Direction of the circuit¶
There is an orientation to circuits, and the orientation plays a significant role in certain electronic components. There are some devices with polarity, which means they must be connected correctly based on their positive and negative poles. Circuits built with the wrong orientation will not function properly.
If you reverse the LED in this simple circuit that we built earlier, you will find that it no longer works.
In contrast, some devices have no direction, such as the resistors in this circuit, so you can try inverting them without affecting the LEDs’ normal operation.
Most components and modules with labels such as “+”, “-“, “GND”, “VCC” or have pins of different lengths must be connected to the circuit in a specific way.
Protection of the circuit¶
Current is the rate at which electrons flow past a point in a complete electrical circuit. At its most basic, current = flow. An ampere (AM-pir), or amp, is the international unit used for measuring current. It expresses the quantity of electrons (sometimes called “electrical charge”) flowing past a point in a circuit over a given time.
The driving force (voltage) behind the flow of current is called voltage and is measured in volts (V).
Resistance (R) is the property of the material that restricts the flow of current, and it is measured in ohms (Ω).
According to Ohm’s law (as long as the temperature remains constant), current, voltage, and resistance are proportional. A circuit’s current is proportional to its voltage and inversely proportional to its resistance.
Therefore, current (I) = voltage (V) / resistance (R).
About Ohm’s law we can do a simple experiment.
By changing the wire connecting 3V3 to 5V (i.e. VBUS, the 40th pin of Pico), the LED will become brighter. If you change the resistor from 220ohm to 1000ohm (color ring: brown, black, black, brown and brown), you will notice that the LED becomes dimmer than before. The larger the resistor, the dimmer the LED.
Note
For an introduction to resistors and how to calculate resistance values, see Resistor.
Most packaged modules only require access to the proper voltage (usually 3.3V or 5V), such as ultrasonic module.
However, in your self-built circuits, you need to be aware of the supply voltage and resistor usage for electrical devices.
As an example, LEDs usually consume 20mA of current, and their voltage drop is about 1.8V. According to Ohm’s law, if we use 5V power supply, we need to connect a minimum of 160ohm ((5-1.8)/20mA) resistor in order not to burn out the LED.
For MicroPython User¶
In this section, you will learn the history of MicroPython, how to install MicroPython in Pico, the basic syntax, and a dozen interesting and practical projects to help you learn MicroPython quickly.
We recommend that you read the chapters in order.
1. Get Started
1.1 Introduction of MicroPython¶
MicroPython is a software implementation of a programming language largely compatible with Python 3, written in C, that is optimized to run on a microcontroller.[3][4]
MicroPython consists of a Python compiler to bytecode and a runtime interpreter of that bytecode. The user is presented with an interactive prompt (the REPL) to execute supported commands immediately. Included are a selection of core Python libraries; MicroPython includes modules which give the programmer access to low-level hardware.
Reference: MicroPython - Wikipedia
The Story Starts Here¶
Things changed in 2013 when Damien George launched a crowdfunding campaign (Kickstarter).
Damien was an undergraduate student at Cambridge University and an avid robotics programmer. He wanted to reduce the world of Python from a gigabyte machine to a kilobyte. His Kickstarter campaign was to support his development while he turned his proof of concept into a finished implementation.
MicroPython is supported by a diverse Pythonista community that has a keen interest in seeing the project succeed.
Apart from testing and supporting the code base, the developers provided tutorials, code libraries, and hardware porting, so Damien was able to focus on other aspects of the project.
Reference: realpython
Why MicroPython?¶
Although the original Kickstarter campaign released MicroPython as a development board “pyboard” with STM32F4, MicroPython supports many ARM-based product architectures. The mainline supported ports are ARM Cortex-M (many STM32 boards, TI CC3200/WiPy, Teensy boards, Nordic nRF series, SAMD21 and SAMD51), ESP8266, ESP32, 16bit PIC, Unix, Windows, Zephyr and JavaScript. Second, MicroPython allows for fast feedback. This is because you can use REPL to enter commands interactively and get responses. You can even tweak code and run it immediately instead of traversing the code-compile-upload-execute cycle.
While Python has the same advantages, for some Microcontroller boards like the Raspberry Pi Pico, they are small, simple and have little memory to run the Python language at all. That’s why MicroPython has evolved, keeping the main Python features and adding a bunch of new ones to work with these Microcontroller boards.
Next you will learn to install MicroPython into the Raspberry Pi Pico.
Reference: MicroPython - Wikipedia
Reference: realpython
1.2 Install and Introduce Thonny IDE¶
To program Pico with MicroPython, you need an integrated development environment (IDE), here we recommend Thonny. Python 3.7 is pre-installed in Thonny, so all you need to do is install it.
Download from Web¶
Before you can start to program Pico with MicroPython, you need an integrated development environment (IDE), here we recommend Thonny. Thonny comes with Python 3.7 built in, just one simple installer is needed and you’re ready to learn programming.
Note
Since the Raspberry Pi Pico interpreter only works with Thonny version 3.3.3 or later, you can skip this chapter if you have it; otherwise, please update or install it.
You can download it by visiting the Thonny website. Once open the page, you will see a light gray box in the upper right corner, click on the link that applies to your operating system.
The installers have been signed with a new certificate which hasn’t built up its reputation yet. You may need to click through your browser warning (e.g. choose “Keep” instead of “Discard” in Chrome) and Windows Defender warning (More info ⇒ Run anyway).
Next, click Next and Install to finish installing Thonny.
Thonny IDE Introduction¶
Ref: realpython
A: The menu bar containing New, Save, Edit, View, Run, Debug, etc.
B: This paper icon allows you to create a new file.
C: If your Raspberry Pi Pico is already plugged into your computer, you can open files that already exist on your computer or Pico.
D: Click on the floppy disk icon to save the code. You can also choose whether to save the code to your computer or the Raspberry Pi Pico.
E: The play icon allows you to run the code. Before running the code, save it if you have not already done so.
F: The Debug icon allows you to debug your code. When writing code, you will inevitably encounter errors. There are many forms of errors, including incorrect syntax and logical errors. Debugging is the tool for finding and investigating errors.
Note
When MicroPython (Raspberry Pi Pico) is selected as the interpreter, the Debug tool cannot be used.
To debug your code, select the interpreter as the default interpreter and save it to your computer after debugging.
You can now save the debugged code to your Raspberry Pi Pico by selecting the MicroPython (Raspberry Pi Pico) interpreter again, clicking the save as button, and clicking the save button again.
When you click on the Degug icon, you can run the program step by step using the G, H, and I arrow icons. When you click on each arrow, a yellow highlighted bar will appear to indicate which Python line or section is being evaluated.
G: Take a big step, which means jumping to the next line or block of code.
H: Take a small step means expressing each component in depth.
I: Exit out of the debugger.
J: Click it to return from debug mode to play mode.
K: Use the stop icon to stop running code.
L: Script Area, where you can write your Python code.
M: Python Shell, where you can type a single command, and when you press the Enter key, the single command will run and provide information about the running program. This is also known as REPL, which means “Read, Evaluate, Print, and Loop.”
N: Interpreter, where the current version of Python used to run your program is displayed, can be changed manually to another version by clicking on it.
Note
NO MicroPython(Raspberry Pi Pico) Interpreter Option ?
Make sure your Pico is plugged into your computer via a USB cable.
The Raspberry Pi Pico interpreter is only available in version 3.3.3 or higher version of Thonny. If you are running an older version, please update.
1.3 Install MicroPython Firmware on Your Pico¶
Now come to install MicroPython Firmware into Raspberry Pi Pico, Thonny IDE provides a very convenient way for you to install it with one click.
Note
If you do not wish to upgrade Thonny, you can use the Raspberry Pi official method by dragging and dropping an rp2_pico_xxxx.uf2
file into Raspberry Pi Pico.
Open Thonny IDE.
Press and hold the BOOTSEL button and then connect the Pico to computer via a Micro USB cable. Release the BOOTSEL button after your Pico is mount as a Mass Storage Device called RPI-RP2.
In the bottom right corner, click the interpreter selection button and select Install Micropython.
Note
If your Thonny does not have this option, please update to the latest version.
In the Target volume, the volume of the Pico you just plugged in will automatically appear, and in the Micropython variant, select Raspberry Pi.Pico/Pico H.
Click the Install button, wait for the installation to complete and then close this page.
Congratulations, now your Raspberry Pi Pico is ready to go.
1.4 Download and Upload the Code¶
Download the Code
Download the relevant code from the link below.
Or check out the code at Euler Kit - GitHub
Upload the Libraries to Pico¶
In some projects, you will need additional libraries. So here we upload these libraries to Raspberry Pi Pico first, and then we can run the code directly later.
Click View -> Files in the top navigation bar of Thonny IDE.
Go to the folder where you downloaded the code package before, and then go to the
micropython/
folder.Select “MicroPython (Raspberry Pi Pico)” from the interpreter selection button in the bottom right corner, but make sure that your Raspberry Pi Pico is connected to your computer via a Micro USB cable.
The drive Raspberry Pi Pico/ will appear, and the next step is to upload all the code and library files to it.
Each project has its own .py file with serial numbers. To avoid increasing Pico’s usage, only select
.py
files and folders without serial numbers.It will take a while for the file to upload after clicking Upload to.
Now you will see the files you just uploaded inside your drive
Raspberry Pi Pico
.
1.5 Quick Guide on Thonny¶
Open and Run Code Directly¶
The code section in the projects tells you exactly which code is used, so double-click on the .py file with the serial number in the euler-kit/micropython/ path to open it.
However, you must first download the package and upload the library, as described in 1.4 Download and Upload the Code.
Open Code
For example,
2.1_hello_led.py
.If you double click on it, a new window will open on the right. You can open more than one code at the same time.
Select Correct Interpreter
Use a micro USB cable to connect the Pico to your computer and select the “MicroPython (Raspberry Pi Pico)” interpreter.
Run the Code
To run the script, click the Run current script button or press F5.
If the code contains any information that needs to be printed, it will appear in the Shell; otherwise, only the following information will appear.
Click View -> Edit to open the Shell window if it doesn’t appear on your Thonny.
MicroPython v1.17 on 2021-09-02; Raspberry Pi Pico with RP2040 Type "help()" for more information. >>> %Run -c $EDITOR_CONTENT
The first line shows the version of MicroPython, the date, and your device information.
The second line prompts you to enter “help()” to get some help.
The third line is a command from Thonny telling the MicroPython interpreter on your Pico to run the contents of the script area - “EDITOR_CONTENT”.
If there is any message after the third line, it is usually a message that you tell MicroPython to print, or an error message for the code.
Stop Running
To stop the running code, click the Stop/Restart backend button. The %RUN -c $EDITOR_CONTENT command will disappear after stopping.
Save or Save as
You can save changes made to the open example by pressing Ctrl+S or clicking the Save button on Thonny.
The code can be saved as a separate file within the Raspberry Pi Pico by clicking on File -> Save As.
Select Raspberry Pi Pico.
Then click OK after entering the file name and extension .py. On the Raspberry Pi Pico drive, you will see your saved file.
Note
Regardless of what name you give your code, it’s best to describe what type of code it is, and not give it a meaningless name like
abc.py
. When you save the code asmain.py
, it will run automatically when the power is turned on.
Create File and Run it¶
The code is shown directly in the code section. You can copy it to Thonny and run it as follows.
Create a new file
Open Thonny IDE, click New button to create a new blank file.
Copy Code
Copy the code from the project to the Thonny IDE.
Select Correct Interpreter
Plug the Pico into your computer with a micro USB cable and select the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
Run and Save the Code
You need click Run Current Script or simply press F5 to run it. If your code has not been saved, a window will pop up asking to save to This computer or Raspberry Pi Pico.
Note
Thonny saves your program on the Raspberry Pi Pico when you tell him to, so if you unplug the Pico and plug it into someone else’s computer, your program remains intact.
Click OK after selecting the location, naming the file and adding the extension .py.
Note
Regardless of what name you give your code, it’s best to describe what type of code it is, and not give it a meaningless name like
abc.py
. When you save the code asmain.py
, it will run automatically when the power is turned on.Once your program is saved, it will run automatically and you will see the following information in the Shell area.
Click View -> Edit to open the Shell window if it does not appear on your Thonny.
MicroPython v1.17 on 2021-09-02; Raspberry Pi Pico with RP2040 Type "help()" for more information. >>> %Run -c $EDITOR_CONTENT
The first line shows the version of MicroPython, the date, and your device information.
The second line prompts you to enter “help()” to get some help.
The third line is a command from Thonny telling the MicroPython interpreter on your Pico to run the contents of the script area - “EDITOR_CONTENT”.
If there is any message after the third line, it is usually a message that you tell MicroPython to print, or an error message for the code.
Stop Running
To stop the running code, click the Stop/Restart backend button. The %RUN -c $EDITOR_CONTENT command will disappear after stopping.
Open File
Here are two ways to open a saved code file.
The first method is to click the open icon on the Thonny toolbar, just like when you save a program, you will be asked if you want to open it from this computer or Raspberry Pi Pico, for example, click Raspberry Pi Pico and you will see a list of all the programs you have saved on the Pico.
The second is to open the file preview directly by clicking View->**File**-> and then double-clicking on the corresponding
.py
file to open it.
1.6 (Optional) MicroPython Basic Syntax¶
Indentation¶
Indentation refers to the spaces at the beginning of a code line. Like standard Python programs, MicroPython programs usually run from top to bottom: It traverses each line in turn, runs it in the interpreter, and then continues to the next line, Just like you type them line by line in the Shell. A program that just browses the instruction list line by line is not very smart, though – so MicroPython, just like Python, has its own method to control the sequence of its program execution: indentation.
You must put at least one space before print(), otherwise an error message “Invalid syntax” will appear. It is usually recommended to standardise spaces by pressing the Tab key uniformly.
if 8 > 5:
print("Eight is greater than Five!")
>>> %Run -c $EDITOR_CONTENT
Traceback (most recent call last):
File "<stdin>", line 2
SyntaxError: invalid syntax
You must use the same number of spaces in the same block of code, or Python will give you an error.
if 8 > 5:
print("Eight is greater than Five!")
print("Eight is greater than Five")
>>> %Run -c $EDITOR_CONTENT
Traceback (most recent call last):
File "<stdin>", line 2
SyntaxError: invalid syntax
Comments¶
The comments in the code help us understand the code, make the entire code more readable and comment out part of the code during testing, so that this part of the code does not run.
Single-line Comment¶
Single-line comments in MicroPython begin with #, and the following text is considered a comment until the end of the line. Comments can be placed before or after the code.
print("hello world") #This is a annotationhello world
>>> %Run -c $EDITOR_CONTENT
hello world
Comments are not necessarily text used to explain the code. You can also comment out part of the code to prevent micropython from running the code.
#print("Can't run it!")
print("hello world") #This is a annotationhello world
>>> %Run -c $EDITOR_CONTENT
hello world
Multi-line comment¶
If you want to comment on multiple lines, you can use multiple # signs.
#This is a comment
#written in
#more than just one line
print("Hello, World!")
>>> %Run -c $EDITOR_CONTENT
Hello, World!
Or, you can use multi-line strings instead of expected.
Since MicroPython ignores string literals that are not assigned to variables, you can add multiple lines of strings (triple quotes) to the code and put comments in them:
"""
This is a comment
written in
more than just one line
"""
print("Hello, World!")
>>> %Run -c $EDITOR_CONTENT
Hello, World!
As long as the string is not assigned to a variable, MicroPython will ignore it after reading the code and treat it as if you made a multi-line comment.
Print()¶
The print()
function prints the specified message to the screen, or other standard output device.
The message can be a string, or any other object, the object will be converted into a string before written to the screen.
Print multiple objects:
print("Welcome!", "Enjoy yourself!")
>>> %Run -c $EDITOR_CONTENT
Welcome! Enjoy yourself!
Print tuples:
x = ("pear", "apple", "grape")
print(x)
>>> %Run -c $EDITOR_CONTENT
('pear', 'apple', 'grape')
Print two messages and specify the separator:
print("Hello", "how are you?", sep="---")
>>> %Run -c $EDITOR_CONTENT
Hello---how are you?
Variables¶
Variables are containers used to store data values.
Creating a variable is very simple. You only need to name it and assign it a value. You don’t need to specify the data type of the variable when assigning it, because the variable is a reference, and it accesses objects of different data types through assignment.
Naming variables must follow the following rules:
Variable names can only contain numbers, letters, and underscores
The first character of the variable name must be a letter or underscore
Variable names are case sensitive
Create Variable¶
There is no command for declaring variables in MicroPython. Variables are created when you assign a value to it for the first time. It does not need to use any specific type declaration, and you can even change the type after setting the variable.
x = 8 # x is of type int
x = "lily" # x is now of type str
print(x)
>>> %Run -c $EDITOR_CONTENT
lily
Casting¶
If you want to specify the data type for the variable, you can do it by casting.
x = int(5) # y will be 5
y = str(5) # x will be '5'
z = float(5) # z will be 5.0
print(x,y,z)
>>> %Run -c $EDITOR_CONTENT
5 5 5.0
Get the Type¶
You can get the data type of a variable with the type() function.
x = 5
y = "hello"
z = 5.0
print(type(x),type(y),type(z))
>>> %Run -c $EDITOR_CONTENT
<class 'int'> <class 'str'> <class 'float'>
Single or Double Quotes?¶
In MicroPython, single quotes or double quotes can be used to define string variables.
x = "hello"
# is the same as
x = 'hello'
Case-Sensitive¶
Variable names are case-sensitive.
a = 5
A = "lily"
#A will not overwrite a
print(a, A)
>>> %Run -c $EDITOR_CONTENT
5 lily
If Else¶
Decision making is required when we want to execute a code only if a certain condition is satisfied.
if¶
if test expression:
statement(s)
Here, the program evaluates the test expression and executes the statement only when the test expression is True.
If test expression is False, then statement(s) will not be executed.
In MicroPython, indentation means the body of the if statement. The body starts with an indentation and ends with the first unindented line.
Python interprets non-zero values as “True”. None and 0 are interpreted as “False”.
if Statement Flowchart

Example
num = 8
if num > 0:
print(num, "is a positive number.")
print("End with this line")
>>> %Run -c $EDITOR_CONTENT
8 is a positive number.
End with this line
if…else¶
if test expression:
Body of if
else:
Body of else
The if..else statement evaluates test expression and will execute the body of if only when the test condition is True.
If the condition is False, the body of else is executed. Indentation is used to separate the blocks.
if…else Statement Flowchart

Example
num = -8
if num > 0:
print(num, "is a positive number.")
else:
print(num, "is a negative number.")
>>> %Run -c $EDITOR_CONTENT
-8 is a negative number.
if…elif…else¶
if test expression:
Body of if
elif test expression:
Body of elif
else:
Body of else
Elif is short for else if. It allows us to check multiple expressions.
If the condition of the if is False, the condition of the next elif block is checked, and so on.
If all conditions are False, the body of else is executed.
Only one of several if…elif…else blocks is executed according to the conditions.
The if block can only have one else block. But it can have multiple elif blocks.
if…elif…else Statement Flowchart

Example
x = 10
y = 9
if x > y:
print("x is greater than y")
elif x == y:
print("x and y are equal")
else:
print("x is greater than y")
>>> %Run -c $EDITOR_CONTENT
x is greater than y
Nested if¶
We can embed an if statement into another if statement, and then call it a nested if statement.
Example
x = 67
if x > 10:
print("Above ten,")
if x > 20:
print("and also above 20!")
else:
print("but not above 20.")
>>> %Run -c $EDITOR_CONTENT
Above ten,
and also above 20!
While Loops¶
The while
statement is used to execute a program in a loop, that is, to execute a program in a loop under certain conditions to handle the same task that needs to be processed repeatedly.
Its basic form is:
while test expression:
Body of while
In the while
loop, first check the test expression
. Only when test expression
evaluates to True
, enter the body of the while. After one iteration, check the test expression
again. This process continues until test expression
evaluates to False
.
In MicroPython, the body of the while
loop is determined by indentation.
The body starts with an indentation and ends with the first unindented line.
Python interprets any non-zero value as True
. None and 0 are interpreted as False
.
while Loop Flowchart

x = 10
while x > 0:
print(x)
x -= 1
>>> %Run -c $EDITOR_CONTENT
10
9
8
7
6
5
4
3
2
1
Break Statement¶
With the break statement we can stop the loop even if the while condition is true:
x = 10
while x > 0:
print(x)
if x == 6:
break
x -= 1
>>> %Run -c $EDITOR_CONTENT
10
9
8
7
6
While Loop with Else¶
Like the if loop, the while loop can also have an optional else block.
If the condition in the while loop is evaluated as False, the else part is executed.
x = 10
while x > 0:
print(x)
x -= 1
else:
print("Game Over")
>>> %Run -c $EDITOR_CONTENT
10
9
8
7
6
5
4
3
2
1
Game Over
For Loops¶
The for loop can traverse any sequence of items, such as a list or a string.
The syntax format of for loop is as follows:
for val in sequence:
Body of for
Here, val is a variable that gets the value of the item in the sequence in each iteration.
The loop continues until we reach the last item in the sequence. Use indentation to separate the body of the for loop from the rest of the code.
Flowchart of for Loop

numbers = [1, 2, 3, 4]
sum = 0
for val in numbers:
sum = sum+val
print("The sum is", sum)
>>> %Run -c $EDITOR_CONTENT
The sum is 10
The break Statement¶
With the break statement we can stop the loop before it has looped through all the items:
numbers = [1, 2, 3, 4]
sum = 0
for val in numbers:
sum = sum+val
if sum == 6:
break
print("The sum is", sum)
>>> %Run -c $EDITOR_CONTENT
The sum is 6
The continue Statement¶
With the continue statement we can stop the current iteration of the loop, and continue with the next:
numbers = [1, 2, 3, 4]
for val in numbers:
if val == 3:
continue
print(val)
>>> %Run -c $EDITOR_CONTENT
1
2
4
The range() function¶
We can use the range() function to generate a sequence of numbers. range(6) will produce numbers between 0 and 5 (6 numbers).
We can also define start, stop and step size as range(start, stop, step_size). If not provided, step_size defaults to 1.
In a sense of range, the object is “lazy” because when we create the object, it does not generate every number it “contains”. However, this is not an iterator because it supports in, len and __getitem__ operations.
This function will not store all values in memory; it will be inefficient. So it will remember the start, stop, step size and generate the next number during the journey.
To force this function to output all items, we can use the function list().
print(range(6))
print(list(range(6)))
print(list(range(2, 6)))
print(list(range(2, 10, 2)))
>>> %Run -c $EDITOR_CONTENT
range(0, 6)
[0, 1, 2, 3, 4, 5]
[2, 3, 4, 5]
[2, 4, 6, 8]
We can use range() in a for loop to iterate over a sequence of numbers. It can be combined with the len() function to use the index to traverse the sequence.
fruits = ['pear', 'apple', 'grape']
for i in range(len(fruits)):
print("I like", fruits[i])
>>> %Run -c $EDITOR_CONTENT
I like pear
I like apple
I like grape
Else in For Loop¶
The for loop can also have an optional else block. If the items in the sequence used for the loop are exhausted, the else part is executed.
The break keyword can be used to stop the for loop. In this case, the else part will be ignored.
Therefore, if no interruption occurs, the else part of the for loop will run.
for val in range(5):
print(val)
else:
print("Finished")
>>> %Run -c $EDITOR_CONTENT
0
1
2
3
4
Finished
The else block will NOT be executed if the loop is stopped by a break statement.
for val in range(5):
if val == 2: break
print(val)
else:
print("Finished")
>>> %Run -c $EDITOR_CONTENT
0
1
Functions¶
In MicroPython, a function is a group of related statements that perform a specific task.
Functions help break our program into smaller modular blocks. As our plan becomes larger and larger, functions make it more organized and manageable.
In addition, it avoids duplication and makes the code reusable.
Create a Function¶
def function_name(parameters):
"""docstring"""
statement(s)
A function is defined using the
def
keywordA function name to uniquely identify the function. Function naming is the same as variable naming, and both follow the following rules.
Can only contain numbers, letters, and underscores.
The first character must be a letter or underscore.
Case sensitive.
Parameters (arguments) through which we pass values to a function. They are optional.
The colon (:) marks the end of the function header.
Optional docstring, used to describe the function of the function, we usually use triple quotes so that the docstring can be expanded to multiple lines.
One or more valid Micropython statements that make up the function body. Statements must have the same indentation level (usually 4 spaces).
Each function needs at least one statement, but if for some reason there is a function that does not contain any statement, please put in the pass statement to avoid errors.
An optional
return
statement to return a value from the function.
Calling a Function¶
To call a function, add parentheses after the function name.
def my_function():
print("Your first function")
my_function()
>>> %Run -c $EDITOR_CONTENT
Your first function
The return Statement¶
The return statement is used to exit a function and return to the place where it was called.
Syntax of return
return [expression_list]
The statement can contain an expression that is evaluated and returns a value. If there is no expression in the statement, or the return
statement itself does not exist in the function, the function will return a None
object.
def my_function():
print("Your first function")
print(my_function())
>>> %Run -c $EDITOR_CONTENT
Your first function
None
Here, None
is the return value, because the return
statement is not used.
Arguments¶
Information can be passed to the function as arguments.
Specify arguments in parentheses after the function name. You can add as many arguments as you need, just separate them with commas.
def welcome(name, msg):
"""This is a welcome function for
the person with the provided message"""
print("Hello", name + ', ' + msg)
welcome("Lily", "Welcome to China!")
>>> %Run -c $EDITOR_CONTENT
Hello Lily, Welcome to China!
Number of Arguments¶
By default, a function must be called with the correct number of arguments. Meaning that if your function expects 2 parameters, you have to call the function with 2 arguments, not more, and not less.
def welcome(name, msg):
"""This is a welcome function for
the person with the provided message"""
print("Hello", name + ', ' + msg)
welcome("Lily", "Welcome to China!")
Here,the function welcome() has 2 parameters.
Since we called this function with two arguments, the function runs smoothly without any errors.
If it is called with a different number of arguments, the interpreter will display an error message.
The following is the call to this function, which contains one and one no arguments and their respective error messages.
welcome("Lily")#Only one argument
>>> %Run -c $EDITOR_CONTENT
Traceback (most recent call last):
File "<stdin>", line 6, in <module>
TypeError: function takes 2 positional arguments but 1 were given
welcome()#No arguments
>>> %Run -c $EDITOR_CONTENT
Traceback (most recent call last):
File "<stdin>", line 6, in <module>
TypeError: function takes 2 positional arguments but 0 were given
Default Arguments¶
In MicroPython, we can use the assignment operator (=) to provide a default value for the parameter.
If we call the function without argument, it uses the default value.
def welcome(name, msg = "Welcome to China!"):
"""This is a welcome function for
the person with the provided message"""
print("Hello", name + ', ' + msg)
welcome("Lily")
>>> %Run -c $EDITOR_CONTENT
Hello Lily, Welcome to China!
In this function, the parameter name
has no default value and is required (mandatory) during the call.
On the other hand, the default value of the parameter msg
is “Welcome to China!”. Therefore, it is optional during the call. If a value is provided, it will overwrite the default value.
Any number of arguments in the function can have a default value. However, once there is a default argument, all arguments on its right must also have default values.
This means that non-default arguments cannot follow default arguments.
For example, if we define the above function header as:
def welcome(name = "Lily", msg):
We will receive the following error message:
>>> %Run -c $EDITOR_CONTENT
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
SyntaxError: non-default argument follows default argument
Keyword Arguments¶
When we call a function with certain values, these values will be assigned to arguments based on their position.
For example, in the above function welcome(), when we called it as welcome(“Lily”, “Welcome to China”), the value “Lily” gets assigned to the name
and similarly “Welcome to China” to parameter msg
.
MicroPython allows calling functions with keyword arguments. When we call the function in this way, the order (position) of the arguments can be changed.
# keyword arguments
welcome(name = "Lily",msg = "Welcome to China!")
# keyword arguments (out of order)
welcome(msg = "Welcome to China!",name = "Lily")
#1 positional, 1 keyword argument
welcome("Lily", msg = "Welcome to China!")
As we can see, we can mix positional arguments and keyword arguments during function calls. But we must remember that the keyword arguments must come after the positional arguments.
Having a positional argument after a keyword argument will result in an error.
For example, if the function call as follows:
welcome(name="Lily","Welcome to China!")
Will result in an error:
>>> %Run -c $EDITOR_CONTENT
Traceback (most recent call last):
File "<stdin>", line 5, in <module>
SyntaxError: non-keyword arg after keyword arg
Arbitrary Arguments¶
Sometimes, if you do not know the number of arguments that will be passed to the function in advance.
In the function definition, we can add an asterisk (*) before the parameter name.
def welcome(*names):
"""This function welcomes all the person
in the name tuple"""
#names is a tuple with arguments
for name in names:
print("Welcome to China!", name)
welcome("Lily","John","Wendy")
>>> %Run -c $EDITOR_CONTENT
Welcome to China! Lily
Welcome to China! John
Welcome to China! Wendy
Here, we have called the function with multiple arguments. These arguments are packed into a tuple before being passed into the function.
Inside the function, we use a for loop to retrieve all the arguments.
Recursion¶
In Python, we know that a function can call other functions. It is even possible for the function to call itself. These types of construct are termed as recursive functions.
This has the benefit of meaning that you can loop through data to reach a result.
The developer should be very careful with recursion as it can be quite easy to slip into writing a function which never terminates, or one that uses excess amounts of memory or processor power. However, when written correctly recursion can be a very efficient and mathematically-elegant approach to programming.
def rec_func(i):
if(i > 0):
result = i + rec_func(i - 1)
print(result)
else:
result = 0
return result
rec_func(6)
>>> %Run -c $EDITOR_CONTENT
1
3
6
10
15
21
In this example, rec_func() is a function that we have defined to call itself (“recursion”). We use the i
variable as the data, and it will decrement (-1) every time we recurse. When the condition is not greater than 0 (that is, 0), the recursion ends.
For new developers, it may take some time to determine how it works, and the best way to test it is to test and modify it.
Advantages of Recursion
Recursive functions make the code look clean and elegant.
A complex task can be broken down into simpler sub-problems using recursion.
Sequence generation is easier with recursion than using some nested iteration.
Disadvantages of Recursion
Sometimes the logic behind recursion is hard to follow through.
Recursive calls are expensive (inefficient) as they take up a lot of memory and time.
Recursive functions are hard to debug.
Data Types¶
Built-in Data Types¶
MicroPython has the following data types:
Text Type: str
Numeric Types: int, float, complex
Sequence Types: list, tuple, range
Mapping Type: dict
Set Types: set, frozenset
Boolean Type: bool
Binary Types: bytes, bytearray, memoryview
Getting the Data Type¶
You can get the data type of any object by using the type() function:
a = 6.8
print(type(a))
>>> %Run -c $EDITOR_CONTENT
<class 'float'>
Setting the Data Type¶
MicroPython does not need to set the data type specifically, it has been determined when you assign a value to the variable.
x = "welcome"
y = 45
z = ["apple", "banana", "cherry"]
print(type(x))
print(type(y))
print(type(z))
>>> %Run -c $EDITOR_CONTENT
<class 'str'>
<class 'int'>
<class 'list'>
>>>
Setting the Specific Data Type¶
If you want to specify the data type, you can use the following constructor functions:
Example |
Date Type |
---|---|
x = int(20) |
int |
x = float(20.5) |
float |
x = complex(1j) |
complex |
x = str(“Hello World”) |
str |
x = list((“apple”, “banana”, “cherry”)) |
list |
x = tuple((“apple”, “banana”, “cherry”)) |
tuple |
x = range(6) |
range |
x = dict(name=”John”, age=36) |
dict |
x = set((“apple”, “banana”, “cherry”)) |
set |
x = frozenset((“apple”, “banana”, “cherry”)) |
frozenset |
x = bool(5) |
bool |
x = bytes(5) |
bytes |
x = bytearray(5) |
bytearray |
x = memoryview(bytes(5)) |
memoryview |
You can print some of them to see the result.
a = float(20.5)
b = list(("apple", "banana", "cherry"))
c = bool(5)
print(a)
print(b)
print(c)
>>> %Run -c $EDITOR_CONTENT
20.5
['apple', 'banana', 'cherry']
True
>>>
Type Conversion¶
You can convert from one type to another with the int(), float(), and complex() methods: Casting in python is therefore done using constructor functions:
int() - constructs an integer number from an integer literal, a float literal (by removing all decimals), or a string literal (providing the string represents a whole number)
float() - constructs a float number from an integer literal, a float literal or a string literal (providing the string represents a float or an integer)
str() - constructs a string from a wide variety of data types, including strings, integer literals and float literals
a = float("5")
b = int(3.7)
c = str(6.0)
print(a)
print(b)
print(c)
Note: You cannot convert complex numbers into another number type.
Operators¶
Operators are used to perform operations on variables and values.
Arithmetic Operators¶
You can use arithmetic operators to do some common mathematical operations.
Operator |
Name |
---|---|
+ |
Addition |
- |
Subtraction |
* |
Multiplication |
/ |
Division |
% |
Modulus |
** |
Exponentiation |
// |
Floor division |
x = 5
y = 3
a = x + y
b = x - y
c = x * y
d = x / y
e = x % y
f = x ** y
g = x // y
print(a)
print(b)
print(c)
print(d)
print(e)
print(f)
print(g)
>>> %Run -c $EDITOR_CONTENT
8
2
15
1.666667
2
125
1
8
2
15
>>>
Assignment operators¶
Assignment operators can used to assign values to variables.
Operator |
Example |
Same As |
---|---|---|
= |
a = 6 |
a =6 |
+= |
a += 6 |
a = a + 6 |
-= |
a -= 6 |
a = a - 6 |
*= |
a *= 6 |
a = a * 6 |
/= |
a /= 6 |
a = a / 6 |
%= |
a %= 6 |
a = a % 6 |
**= |
a **= 6 |
a = a ** 6 |
//= |
a //= 6 |
a = a // 6 |
&= |
a &= 6 |
a = a & 6 |
|= |
a |= 6 |
a = a | 6 |
^= |
a ^= 6 |
a = a ^ 6 |
>>= |
a >>= 6 |
a = a >> 6 |
<<= |
a <<= 6 |
a = a << 6 |
a = 6
a *= 6
print(a)
>>> %Run test.py
36
>>>
Comparison Operators¶
Comparison operators are used to compare two values.
Operator |
Name |
---|---|
== |
Equal |
!= |
Not equal |
< |
Less than |
> |
Greater than |
>= |
Greater than or equal to |
<= |
Less than or equal to |
a = 6
b = 8
print(a>b)
>>> %Run test.py
False
>>>
Return False, beause the a is less than the b.
Logical Operators¶
Logical operators are used to combine conditional statements.
Operator |
Description |
---|---|
and |
Returns True if both statements are true |
or |
Returns True if one of the statements is true |
not |
Reverse the result, returns False if the result is true |
a = 6
print(a > 2 and a < 8)
>>> %Run -c $EDITOR_CONTENT
True
>>>
Identity Operators¶
Identity operators are used to compare the objects, not if they are equal, but if they are actually the same object, with the same memory location.
Operator |
Description |
---|---|
is |
Returns True if both variables are the same object |
is not |
Returns True if both variables are not the same object |
a = ["hello", "welcome"]
b = ["hello", "welcome"]
c = a
print(a is c)
# returns True because z is the same object as x
print(a is b)
# returns False because x is not the same object as y, even if they have the same content
print(a == b)
# returns True because x is equal to y
>>> %Run -c $EDITOR_CONTENT
True
False
True
>>>
Membership Operators¶
Membership operators are used to test if a sequence is presented in an object.
Operator |
Description |
---|---|
in |
Returns True if a sequence with the specified value is present in the object |
not in |
Returns True if a sequence with the specified value is not present in the object |
a = ["hello", "welcome", "Goodmorning"]
print("welcome" in a)
>>> %Run -c $EDITOR_CONTENT
True
>>>
Bitwise Operators¶
Bitwise operators are used to compare (binary) numbers.
Operator |
Name |
Description |
---|---|---|
& |
AND |
Sets each bit to 1 if both bits are 1 |
OR |
Sets each bit to 1 if one of two bits is 1 |
|
^ |
XOR |
Sets each bit to 1 if only one of two bits is 1 |
~ |
NOT |
Inverts all the bits |
<< |
Zero fill left shift |
Shift left by pushing zeros in from the right and let the leftmost bits fall off |
>> |
Signed right shift |
Shift right by pushing copies of the leftmost bit in from the left, and let the rightmost bits fall off |
num = 2
print(num & 1)
print(num | 1)
print(num << 1)
>>> %Run -c $EDITOR_CONTENT
0
3
4
>>>
Lists¶
Lists are used to store multiple items in a single variable, and are created using square brackets:
B_list = ["Blossom", "Bubbles","Buttercup"]
print(B_list)
List items are changeable, ordered, and allow duplicate values. The list items are indexed, with the first item having index [0], the second item having index [1], and so on.
C_list = ["Red", "Blue", "Green", "Blue"]
print(C_list) # duplicate
print(C_list[0])
print(C_list[1]) # ordered
C_list[2] = "Purple" # changeable
print(C_list)
>>> %Run -c $EDITOR_CONTENT
['Red', 'Blue', 'Green', 'Blue']
Red
Blue
['Red', 'Blue', 'Purple', 'Blue']
A list can contain different data types:
A_list = ["Banana", 255, False, 3.14]
print(A_list)
>>> %Run -c $EDITOR_CONTENT
['Banana', 255, False, 3.14]
List Length¶
To determine how many items are in the list, use the len() function.
A_list = ["Banana", 255, False, 3.14]
print(len(A_list))
>>> %Run -c $EDITOR_CONTENT
4
Check List items¶
Print the second item of the list:
A_list = ["Banana", 255, False, 3.14]
print(A_list[1])
>>> %Run -c $EDITOR_CONTENT
[255]
Print the last one item of the list:
A_list = ["Banana", 255, False, 3.14]
print(A_list[-1])
>>> %Run -c $EDITOR_CONTENT
[3.14]
Print the second, third item:
A_list = ["Banana", 255, False, 3.14]
print(A_list[1:3])
>>> %Run -c $EDITOR_CONTENT
[255, False]
Change List Items¶
Change the second, third item:
A_list = ["Banana", 255, False, 3.14]
A_list[1:3] = [True,"Orange"]
print(A_list)
>>> %Run -c $EDITOR_CONTENT
['Banana', True, 'Orange', 3.14]
Change the second value by replacing it with two values:
A_list = ["Banana", 255, False, 3.14]
A_list[1:2] = [True,"Orange"]
print(A_list)
>>> %Run -c $EDITOR_CONTENT
['Banana', True, 'Orange', False, 3.14]
Add List Items¶
Using the append() method to add an item:
C_list = ["Red", "Blue", "Green"]
C_list.append("Orange")
print(C_list)
>>> %Run -c $EDITOR_CONTENT
['Red', 'Blue', 'Green', 'Orange']
Insert an item as the second position:
C_list = ["Red", "Blue", "Green"]
C_list.insert(1, "Orange")
print(C_list)
>>> %Run -c $EDITOR_CONTENT
['Red', 'Orange', 'Blue', 'Green']
Remove List Items¶
The remove() method removes the specified item.
C_list = ["Red", "Blue", "Green"]
C_list.remove("Blue")
print(C_list)
>>> %Run -c $EDITOR_CONTENT
['Red', 'Green']
The pop() method removes the specified index. If you do not specify the index, the pop() method removes the last item.
A_list = ["Banana", 255, False, 3.14, True,"Orange"]
A_list.pop(1)
print(A_list)
A_list.pop()
print(A_list)
>>> %Run -c $EDITOR_CONTENT
255
['Banana', False, 3.14, True, 'Orange']
'Orange'
['Banana', False, 3.14, True]
The del
keyword also removes the specified index:
C_list = ["Red", "Blue", "Green"]
del C_list[1]
print(C_list)
>>> %Run -c $EDITOR_CONTENT
['Red', 'Green']
The clear() method empties the list. The list still remains, but it has no content.
C_list = ["Red", "Blue", "Green"]
C_list.clear()
print(C_list)
>>> %Run -c $EDITOR_CONTENT
[]
2. Output & Input
2.1 Hello, LED!¶
Just as printing “Hello, world!” is the first step in learning to program, using a program to drive an LED is the traditional introduction to learning physical programming.
Schematic
This circuit works on a simple principle, and the current direction is shown in the figure. The LED will light up after the 220ohm current limiting resistor when GP15 outputs high level (3.3v). The LED will turn off when GP15 outputs low level (0v).
Wiring
To build the circuit, let’s follow the current’s direction!
The LED is powered by the GP15 pin of the Pico board, and the circuit begins here.
To protect the LED, the current must pass through a 220 ohm resistor. One end of the resistor should be inserted into the same row as the Pico GP15 pin (row 20 in my circuit), and the other end should be inserted into the free row of the breadboard (row 24).
Note
The color ring of the 220 ohm resistor is red, red, black, black and brown.
If you pick up the LED, you will see that one of its leads is longer than the other. Connect the longer lead to the same row as the resistor, and the shorter lead to the same row across the middle gap on the breadboard.
Note
The longer lead is the anode, which represents the positive side of the circuit; the shorter lead is the cathode, which represents the negative side.
The anode needs to be connected to the GPIO pin through a resistor; the cathode needs to be connected to the GND pin.
Using a male-to-male (M2M) jumper wire, connect the LED short pin to the breadboard’s negative power bus.
Connect the GND pin of Pico to the negative power bus using a jumper.
Code
Note
Open the
2.1_hello_led.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
led = machine.Pin(15, machine.Pin.OUT)
while True:
led.value(1)
utime.sleep(2)
led.value(0)
utime.sleep(2)
After the code runs, you will see the LED blinking.
How it works?
The machine library is required to use GPIO.
import machine
The library contains all the instructions needed to communicate between MicroPython and Pico. In the absence of this line of code, we will not be able to control any GPIOs.
The next thing to notice is this line:
led = machine.Pin(15, machine.Pin.OUT)
The object led
is defined here. Technically, it can be any name, such as x, y, banana, Michael_Jackson, or any character.
To ensure that the program is easy to read, it is best to use a name that describes the purpose.
In the second part of this line (the part after the equal sign), we call the Pin function found in the machine
library. It is used to tell Pico’s GPIO pins what to do.
A Pin
function has two parameters: the first (15) represents the pin to set;
The second parameter (machine.Pin.OUT) specifies that the pin should be output rather than input.
The above code has “set” the pin, but it will not light up the LED. To do this, we also need to “use” the pin.
led.value(1)
The GP15 pin has been set up previously and named led
. The function of this statement is to set the value of led
to 1 to turn the LED on.
All in all, to use GPIO, these steps are necessary:
import machine library: This is necessary, and it is only executed once.
Set GPIO: Before using, each pin should be set.
Use: Change the working state of the pin by assigning a value to it.
If we follow the above steps to write an example, then you will get code like this:
import machine
led = machine.Pin(15, machine.Pin.OUT)
led.value(1)
Run it and you will be able to light up the LED.
Next, we try to add the “extinguished” statement:
import machine
led = machine.Pin(15, machine.Pin.OUT)
led.value(1)
led.value(0)
Based on the code line, this program will turn on the LED first, then turn it off. But when you use it, you will find that this is not the case. There is no light coming from the LED. This is due to the very rapid execution speed between the two lines, much faster than the human eye can react. When the LED lights up, we don’t perceive the light instantly. This can be fixed by slowing down the program.
The second line of the program should contain the following statement:
import utime
Similarly to machine
, the utime
library is imported here, which handles all things time-related.
The delays we need to use are included in this. Add a delay statement between led.value(1)
and led.value(0)
and let them be separated by 2 seconds.
utime.sleep(2)
This is how the code should look now. We will see that the LED turns on first, then turns off when we run it:
import machine
import utime
led = machine.Pin(15, machine.Pin.OUT)
led.value(1)
utime.sleep(2)
led.value(0)
Finally, we should make the LED blink. Create a loop, rewrite the program, and it will be what you saw at the beginning of this chapter.
import machine
import utime
led = machine.Pin(15, machine.Pin.OUT)
while True:
led.value(1)
utime.sleep(2)
led.value(0)
utime.sleep(2)
Learn More
There will usually be an API (Application Programming Interface) file associated with the library. It contains all the information necessary to use this library, including detailed descriptions of functions, classes, return types, parameter types, etc.
In this article, we used MicroPython’s machine
and utime
libraries, we can find more ways to use them here.
Please read the API file to understand this example of making the LED blink!
Note
Open the
2.1_hello_led_2.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
led = machine.Pin(15, machine.Pin.OUT)
while True:
led.toggle()
utime.sleep(1)
2.2 Display the Level¶
The first project is simply to make the LED blink. For this project, let’s use the LED Bar Graph, which contains 10 LEDs in a plastic enclosure, generally used to display power or volume levels.
Schematic
In the LED Bar Graph, there are 10 LEDs, each of which can be controlled individually. Each LED’s anode is connected to GP6*GP15, and its cathode to a 220ohm resistor, and then to GND.
Wiring
Code
Note
Open the
2.2_display_the_level.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
pin = [6,7,8,9,10,11,12,13,14,15]
led= []
for i in range(10):
led.append(None)
led[i] = machine.Pin(pin[i], machine.Pin.OUT)
while True:
for i in range(10):
led[i].toggle()
utime.sleep(0.2)
On the LED Bar Graph, you’ll see LEDs lighting up and then turning off in sequence when the program is running.
How it works?
The LED Bar consists of ten LEDs that are controlled by ten pins, which means that we must define these pins.
The process would be too tedious if we defined them one by one. So, here we use Lists
.
Note
Python lists are one of the most versatile data types that allow us to work with multiple elements at once, and created by placing elements inside square brackets [], separated by commas.
pin = [6,7,8,9,10,11,12,13,14,15]
A list pin
is defined by this line of code, which contains the ten elements 6,7,8,9,10,11,12,13,14,15
.
We can use the index operator [] to access an item in a list. In Python, indices start at 0. So, a list having 10 elements will have an index from 0 to 9.
Using this list as an example, pin[0]
is 6
and pin[4]
is 10
.
Next, declare an empty list led
that will be used to define ten LED objects.
led = []
Due to the length of the list, which is 0, direct operations on the array, such as printing led[0]**, won’t work. There are new items we need to add.
led.append(None)
As a result of this append()
method, the list led
has its first item, of length 1, and led[0]
becomes a valid element despite its current value of None
(which stands for null).
Our next step is to define led[0]
, the LED connected to pin 6, as the first LED object.
led[0] = machine.Pin(6, machine.Pin.OUT)
The first LED object has now been defined.
As you can see, we have created the ten pin numbers as a list pin, which we can substitute into this line to make it easier to do bulk operations.
led[0] = machine.Pin(pin[0], machine.Pin.OUT)
Use a for
statement to have all 10 pins execute the above statement.
import machine
pin = [6,7,8,9,10,11,12,13,14,15]
led= []
for i in range(10):
led.append(None)
led[i] = machine.Pin(pin[i], machine.Pin.OUT)
Use another for
loop to make the ten LEDs on the LED Bar switch states one by one.
for i in range(10):
led[i].toggle()
utime.sleep(0.2)
The code is finished by putting the above piece of code in a while loop.
import machine
import utime
pin = [6,7,8,9,10,11,12,13,14,15]
led= []
for i in range(10):
led.append(None)
led[i] = machine.Pin(pin[i], machine.Pin.OUT)
while True:
for i in range(10):
led[i].toggle()
utime.sleep(0.2)
2.3 Fading LED¶
As of now, we have only used two output signals: high level and low level (also called ON and OFF), which is called digital output. However, in actual use, many devices do not simply ON/OFF to work, for example, adjusting the speed of the motor, adjusting the brightness of the desk lamp, and so on. To achieve this goal, a slider that adjusts resistance was used in the past, but it is unreliable and inefficient. Therefore, Pulse width modulation (PWM) has emerged as a feasible solution to such complex problems.
A pulse is a digital output that contains a high level and a low level. The pulse width of these pins can be adjusted by changing the ON/OFF speed.
When we are in a short period of time (like 20ms, which is most people’s visual retention period), let the LED turn on, turn off, and turn on again, we won’t see it has been turned off, but the brightness of the light will be slightly weaker. During this period, the more time the LED is on, the brighter it becomes. In other words, in the cycle, the wider the pulse, the greater the “electric signal strength” output by the microcontroller. This is how PWM controls LED brightness (or motor speed).
There are some points to pay attention to when Pico uses PWM. Let’s take a look at this picture.
Pico supports PWM on each GPIO pin, but there are actually 16 independent PWM outputs (instead of 30), distributed between GP0 to GP15 on the left, and the right GPIO’s PWM output is identical to the left.
It is important to avoid setting the same PWM channel for different purposes during programming. For example, GP0 and GP16 are both PWM_0A.
Let’s try to achieve the faded LED effect after understanding this knowledge.
Schematic
This project is the same circuit as the first project 2.1 Hello, LED!, but the signal type is different. The first project is to output digital high and low levels (0&1) directly from GP15 to make the LEDs light up or turn off, this project is to output PWM signal from GP15 to control the brightness of the LED.
Wiring
Code
Note
Open the
2.3_fading_led.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
led = machine.PWM(machine.Pin(15))
led.freq(1000)
for brightness in range(0,65535,50):
led.duty_u16(brightness)
utime.sleep_ms(10)
led.duty_u16(0)
The LED will gradually become brighter as the code runs.
How it works?
Here, we change the brightness of the LED by changing the duty cycle of the GP15’s PWM output. Let’s take a look at these lines.
import machine
import utime
led = machine.PWM(machine.Pin(15))
led.freq(1000)
for brightness in range(0,65535,50):
led.duty_u16(brightness)
utime.sleep_ms(10)
led.duty_u16(0)
led = machine.PWM(machine.Pin(15))
sets the GP15 pin as PWM output.The line
led.freq(1000)
is used to set the PWM frequency, here it is set to 1000Hz, which means 1ms (1/1000) is a cycle.The
led.duty_u16()
line is used to set the duty cycle, which is a 16-bit interger(2^16=65536). A 0 indicates 0% duty cycle, which means each cycle has 0% time to output a high level, i.e., all pulses are turned off. The value 65535 indicates a duty cycle of 100%, which means the whole pulse is turned on, and the result is ‘1’. When it is 32768, it will turn on half a pulse, so the LED will be half as bright when fully on.
2.4 Colorful Light¶
As we know, light can be superimposed. For example, mix blue light and green light give cyan light, red light and green light give yellow light. This is called “The additive method of color mixing”.
Based on this method, we can use the three primary colors to mix the visible light of any color according to different specific gravity. For example, orange can be produced by more red and less green.
In this chapter, we will use RGB LED to explore the mystery of additive color mixing!
RGB LED is equivalent to encapsulating Red LED, Green LED, Blue LED under one lamp cap, and the three LEDs share one cathode pin. Since the electric signal is provided for each anode pin, the light of the corresponding color can be displayed. By changing the electrical signal intensity of each anode, it can be made to produce various colors.
Schematic
The PWM pins GP13, GP14 and GP15 control the Red, Green and Blue pins of the RGB LED respectively, and connect the common cathode pin to GND. This allows the RGB LED to display a specific color by superimposing light on these pins with different PWM values.
Wiring
The RGB LED has 4 pins: the long pin is the common cathode pin, which is usually connected to GND; the left pin next to the longest pin is Red; and the two pins on the right are Green and Blue.
Code
Note
Open the
2.4_colorful_light.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
red = machine.PWM(machine.Pin(13))
green = machine.PWM(machine.Pin(14))
blue = machine.PWM(machine.Pin(15))
red.freq(1000)
green.freq(1000)
blue.freq(1000)
def interval_mapping(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
def color_to_duty(rgb_value):
rgb_value = int(interval_mapping(rgb_value,0,255,0,65535))
return rgb_value
def color_set(red_value,green_value,blue_value):
red.duty_u16(color_to_duty(red_value))
green.duty_u16(color_to_duty(green_value))
blue.duty_u16(color_to_duty(blue_value))
color_set(255,128,0)
Here, we can choose our favorite color in drawing software (such as paint) and display it with RGB LED.
Write the RGB value into color_set()
, you will be able to see the RGB light up the colors you want.
How it works?
To allow the three primary colors to work together, we defined a color_set()
function.
At present, pixels in computer hardware usually use 24-bit representations. Each primary color is divided into 8 bits, and the color value range is 0 to 255. There are 256 possible combinations of each of the three primary colors (don’t forget to count 0! ), so 256 x 256 x 256 = 16,777,216 colors.
The color_set()
function also uses 24-bit notation, so we can choose a color more easily.
And since the value range of duty_u16()
is 0~65535 (instead of 0 to 255) when the output signals to RGB LED through PWM, we have defined color_to_duty()
and interval_mapping ()
function to map the color values to the duty values.
2.5 Reading Button Value¶
These pins have both input and output functions, as indicated by their name GPIO (General-purpose input/output). Previously, we used the output function; in this chapter, we will use the input function to input the button value.
Schematic
As long as one side of the button pin is connected to 3.3v, and the other side pin is connected to GP14, then when the button is pressed, GP14 will be high. However, when the button is not pressed, GP14 is in a suspended state and may be high or low. In order to get a stable low level when the button is not pressed, GP14 needs to be reconnected to GND through a 10K pull-down resistor.
Wiring
Note
A four-pin button is shaped like an H. Its left two pins or right two pins are connected, which means that when it crosses the central gap, it connects two half rows with the same row number. (For example, in my circuit, E23 and F23 are already connected, as are E25 and F25).
Until the button is pressed, the left and right pins are independent of each other and current cannot flow from one side to the other.
Code
Note
Open the
2.5_read_button_value.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
button = machine.Pin(14, machine.Pin.IN)
while True:
if button.value() == 1:
print("You pressed the button!")
utime.sleep(1)
As soon as the code runs, the shell prints “You pressed the button!”
Pull-up Working Mode
The next part is the wiring and code when you use the button in the pull-up mode.
The only difference you will see with the pull-down mode is that the 10K resistor is connected to 3.3V and the button is connected to GND, so that when the button is pressed, GP14 will get a low level, which is the opposite of the value obtained in pull-down mode.
So just change this code to if button.value() == 0:
.
Also see the reference here:
2.6 Tilt It!¶
The tilt switch is a 2-pin device with a metal ball in the middle. When the switch is upright, the two pins are connected; when it is tilted, the two pins are disconnected.
Schematic
When you put it upright, GP14 will get high; after tilting it, GP14 will get low.
The purpose of the 10K resistor is to keep the GP14 in a stable low state when the tilt switch is in a tilted state.
Wiring
Code
Note
Open the
2.6_tilt_switch.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
button = machine.Pin(14, machine.Pin.IN)
while True:
if button.value() == 0:
print("The switch works!")
utime.sleep(1)
After the program runs, when you tilt the breadboard (tilt switch), “The switch works!” will appear in the shell.
2.7 Toggle Left and Right¶
The slide switch is a 3-pin device, with pin 2 (middle) being the common pin. When the switch is toggled to the left, the left two pins are connected together, and when toggled to the right, the right two pins are connected together.
Schematic
GP14 will get a different level, when you toggle the slide switch to the right or left.
The purpose of the 10K resistor is to keep the GP14 low during toggling (not toggling to the far left and not toggling to the far right).
The 104 ceramic capacitor is used here to eliminate jitter.
Wiring
Code
Note
Open the
2.7_slide_switch.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
button = machine.Pin(14, machine.Pin.IN)
while True:
if button.value() == 0:
print("The switch works!")
utime.sleep(1)
After the program runs, when you toggle the slide switch to the right, “The switch works!” will appear in the shell.
2.8 Press Gently¶
Micro Switch is also a 3-pin device, the sequence of the 3 pins are C (common pin), NO (normally open) and NC (normally closed) .
When the micro switch is not pressed, 1 (C) and 3 (NC) are connected together, when pressed 1 (C) and 2 (NO) are connected together.
Schematic
By default, GP14 is low and when pressed, GP14 is high.
The purpose of the 10K resistor is to keep the GP14 low during pressing.
The 104 ceramic capacitor is used here to eliminate jitter.
Wiring
Code
Note
Open the
2.8_micro_switch.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
button = machine.Pin(14, machine.Pin.IN)
while True:
if button.value() == 1:
print("The switch works!")
utime.sleep(1)
After the program runs, when you toggle the slide switch to the right, “The switch works!” will appear in the shell.
2.9 Feel the Magnetism¶
The most common type of reed switch contains a pair of magnetizable, flexible, metal reeds whose end portions are separated by a small gap when the switch is open.
A magnetic field from an electromagnet or a permanent magnet will cause the reeds to attract each other, thus completing an electrical circuit. The spring force of the reeds causes them to separate, and open the circuit, when the magnetic field ceases.
A common example of a reed switch application is to detect the opening of a door or windows, for a security alarm.
Schematic
By default, GP14 is low; and will go high when the magnet is near the reed switch.
The purpose of the 10K resistor is to keep the GP14 at a steady low level when no magnet is near.
Wiring
Code
Note
Open the
2.9_feel_the_magnetism.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
reed = machine.Pin(14, machine.Pin.IN)
while True:
if reed.value() == 1:
print("There are magnets here!!")
utime.sleep(1)
When the code is run, GP14 goes high when a magnet is near the reed switch, otherwise it goes low. Just like the button in the 2.5 Reading Button Value chapter.
Learn More
This time, we tried a flexible way of using switches: interrupt requests, or IRQs.: interrupt requests, or IRQs.
For example, you are reading a book page by page, as if a program is executing a thread. At this time, someone came to you to ask a question and interrupted your reading. Then the person is executing the interrupt request: asking you to stop what you are doing, answer his questions, and then let you return to reading the book after the end.
MicroPython interrupt request also works in the same way, it allows certain operations to interrupt the main program.
Note
Open the
2.9_feel_the_magnetism_irq.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
reed_switch = machine.Pin(14, machine.Pin.IN)
def detected(pin):
print("Magnet!")
reed_switch.irq(trigger=machine.Pin.IRQ_RISING, handler=detected)
Here first a callback function detected(pin)
is defined, called the interrupt handler. It will be executed when an interrupt request is triggered. Then, an interrupt request is set up in the main program, which contains two parts: the trigger
and the handler
.
In this program, trigger
is IRQ_RISING
, which indicates that the value of the pin is raised from low to high (i.e., button press).
handler
is detected
, the callback function we defined before.
2.10 Detect Human Movement¶
Passive infrared sensor (PIR sensor) is a common sensor that can measure infrared (IR) light emitted by objects in its field of view. Simply put, it will receive infrared radiation emitted from the body, thereby detecting the movement of people and other animals. More specifically, it tells the main control board that someone has entered your room.
Schematic
When the PIR module detects someone passing by, GP14 will be high, otherwise it will be low.
Note
The PIR module has two potentiometers: one adjusts sensitivity, the other adjusts detection distance. To make the PIR module work better, you need to turn both of them counterclockwise to the end.
Wiring
Code
Note
Open the
2.10_detect_human_movement.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
pir_sensor = machine.Pin(14, machine.Pin.IN)
def motion_detected(pin):
print("Somebody here!")
pir_sensor.irq(trigger=machine.Pin.IRQ_RISING, handler=motion_detected)
After the program runs, if the PIR module detects someone nearby, the Shell will print out “Somebody here!”
Learn More
PIR is a very sensitive sensor. In order to adapt it to the environment of use, it needs to be adjusted. Let the side with the 2 potentiometers facing you, turn both potentiometers counterclockwise to the end and insert the jumper cap on the pin with L and the middle pin.
Note
Open the
2.10_pir_adjustment.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
pir_sensor = machine.Pin(14, machine.Pin.IN)
global timer_delay
timer_delay = utime.ticks_ms()
print("start")
def pir_in_high_level(pin):
global timer_delay
pir_sensor.irq(trigger=machine.Pin.IRQ_FALLING, handler=pir_in_low_level)
intervals = utime.ticks_diff(utime.ticks_ms(), timer_delay)
timer_delay = utime.ticks_ms()
print("the dormancy duration is " + str(intervals) + "ms")
def pir_in_low_level(pin):
global timer_delay
pir_sensor.irq(trigger=machine.Pin.IRQ_RISING, handler=pir_in_high_level)
intervals2 = utime.ticks_diff(utime.ticks_ms(), timer_delay)
timer_delay = utime.ticks_ms()
print("the duration of work is " + str(intervals2) + "ms")
pir_sensor.irq(trigger=machine.Pin.IRQ_RISING, handler=pir_in_high_level)
Let us analyze its adjustment method along with the experimental results.
Trigger Mode
Let’s take a look at the pins with jumper cap at the corner. It allows PIR to enter Repeatable trigger mode or Non-repeatable trigger mode
At present, our jumper cap connects the middle Pin and L Pin, which makes the PIR in non-repeatable trigger mode. In this mode, when the PIR detects the movement of the organism, it will send a high-level signal for about 2.8 seconds to the main control board. We can see in the printed data that the duration of work will always be around 2800ms.
Next, we modify the position of the lower jumper cap and connect it to the middle Pin and H Pin to make the PIR in repeatable trigger mode. In this mode, when the PIR detects the movement of the organism (note that it is movement, not static in front of the sensor), as long as the organism keeps moving within the detection range, the PIR will continue to send a high-level signal to the main control board. We can see in the printed data that the duration of work is an uncertain value.
Delay Adjustment
The potentiometer on the left is used to adjust the interval between two jobs.
At present, we screw it counterclockwise to the end, which makes the PIR need to enter a sleep time of about 5 seconds after finishing sending the high level work. During this time, the PIR will no longer detect the infrared radiation in the target area. We can see in the printed data that the dormancy duration is always no less than 5000ms.
If we turn the potentiometer clockwise, the sleep time will also increase. When it is turned clockwise to the end, the sleep time will be as high as 300s.
Distance Adjustment
The centered potentiometer is used to adjust the sensing distance range of the PIR.
Turn the knob of the distance adjustment potentiometer clockwise to increase the sensing distance range, and the maximum sensing distance range is about 0-7 meters. If it rotates counterclockwise, the sensing distance range is reduced, and the minimum sensing distance range is about 0-3 meters.
2.11 Turn the Knob¶
In the previous projects, we have used the digital input on the Pico. For example, a button can change the pin from low level (off) to high level (on). This is a binary working state.
However, Pico can receive another type of input signal: analog input. It can be in any state from fully closed to fully open, and has a range of possible values. The analog input allows the microcontroller to sense the light intensity, sound intensity, temperature, humidity, etc. of the physical world.
Usually, a microcontroller needs an additional hardware to implement analog input-the analogue-to-digital converter (ADC). But Pico itself has a built-in ADC for us to use directly.
Pico has three GPIO pins that can use analog input, GP26, GP27, GP28. That is, analog channels 0, 1, and 2. In addition, there is a fourth analog channel, which is connected to the built-in temperature sensor and will not be introduced here.
In this project, we try to read the analog value of potentiometer.
Schematic
The potentiometer is an analog device and when you turn it in 2 different directions.
Connect the middle pin of the potentiometer to the analog pin GP28. The Raspberry Pi Pico contains a multi-channel, 16-bit analog-to-digital converter. This means that it maps the input voltage between 0 and the operating voltage (3.3V) to an integer value between 0 and 65535, so the GP28 value ranges from 0 to 65535.
The calculation formula is shown below.
(Vp/3.3V) x 65535 = Ap
Then program the value of GP28 (potentiometer) as the PWM value of GP15 (LED). This way you will find that by rotating the potentiometer, the brightness of the LED will change at the same time.
Wiring
Code
Note
Open the
2.11_turn_the_knob.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
potentiometer = machine.ADC(28)
led = machine.PWM(machine.Pin(15))
led.freq(1000)
while True:
value=potentiometer.read_u16()
print(value)
led.duty_u16(value)
utime.sleep_ms(200)
When the program is running, we can see the analog value currently read by the GP28 pin in the shell. Turn the knob, and the value will change from 0 to 65535. At the same time, the brightness of the LED will increase as the analog value increases.
How it works?
potentiometer = machine.ADC(28)
Access the ADC associated with a source identified by id. In this example it is GP28.
potentiometer.read_u16()
Take an analog reading and return an integer in the range 0-65535. The return value represents the raw reading taken by the ADC, scaled such that the minimum value is 0 and the maximum value is 65535.
2.12 Feel the Light¶
The photoresistor is a typical device for analog inputs and it is used in a very similar way to a potentiometer. Its resistance value depends on the intensity of the light, the stronger the irradiated light, the smaller its resistance value; conversely, it increases.
Schematic
In this circuit, the 10K resistor and the photoresistor are connected in series, and the current passing through them is the same. The 10K resistor acts as a protection, and the GP28 reads the value after the voltage conversion of the photoresistor.
When the light is enhanced, the resistance of the photoresistor decreases, then its voltage decreases, so the value from GP28 will decrease; if the light is strong enough, the resistance of the photoresistor will be close to 0, and the value of GP28 will be close to 0. At this time, the 10K resistor plays a protective role, so that 3.3V and GND are not connected together, resulting in a short circuit.
If you place the photoresistor in a dark situation, the value of GP28 will increase. In a dark enough situation, the resistance of the photoresistor will be infinite, and its voltage will be close to 3.3v (the 10K resistor is negligible), and the value of GP28 will be close to the maximum value of 65535.
The calculation formula is shown below.
(Vp/3.3V) x 65535 = Ap
Wiring
Code
Note
Open the
2.12_feel_the_light.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
photoresistor = machine.ADC(28)
while True:
light_value = photoresistor.read_u16()
print(light_value)
utime.sleep_ms(10)
After the program runs, the Shell prints out the photoresistor values. You can shine a flashlight on it or cover it up with your hand to see how the value will change.
2.13 Thermometer¶
A thermometer is a device that measures temperature or a temperature gradient (the degree of hotness or coldness of an object). A thermometer has two important elements: (1) a temperature sensor (e.g. the bulb of a mercury-in-glass thermometer or the pyrometric sensor in an infrared thermometer) in which some change occurs with a change in temperature; and (2) some means of converting this change into a numerical value (e.g. the visible scale that is marked on a mercury-in-glass thermometer or the digital readout on an infrared model). Thermometers are widely used in technology and industry to monitor processes, in meteorology, in medicine, and in scientific research.
A thermistor is a type of temperature sensor whose resistance is strongly dependent on temperature, and it has two types: Negative Temperature Coefficient (NTC) and Positive Temperature Coefficient (PTC), also known as NTC and PTC. The resistance of PTC thermistor increases with temperature, while the condition of NTC is opposite to the former.
In this experiment we use an NTC thermistor to make a thermometer.
Schematic
In this circuit, the 10K resistor and the thermistor are connected in series, and the current passing through them is the same. The 10K resistor acts as a protection, and the GP28 reads the value after the voltage conversion of the thermistor.
When the temperature increases, the resistance value of NTC thermistor decreases, then its voltage decreases, so the value from GP28 will decrease; If the temperature is high enough, the resistance of the thermistor will be close to 0, and the value of GP28 will be close to 0. At this time, the 10K resistor plays a protective role, so that 3.3V and GND are not connected together, resulting in a short circuit.
When the temperature drops, the value of GP28 will increase. When the temperature is low enough, the resistance of the thermistor will be infinite, and its voltage will be close to 3.3v (the 10K resistor is negligible), and the value of GP28 will be close to the maximum value of 65535.
The calculation formula is shown below.
(Vp/3.3V) x 65535 = Ap
Wiring
Note
The thermistor is black and marked 103.
The color ring of the 10K ohm resistor is red, black, black, red and brown.
Code
Note
Open the
2.13_thermometer.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
import math
thermistor = machine.ADC(28)
while True:
temperature_value = thermistor.read_u16()
Vr = 3.3 * float(temperature_value) / 65535
Rt = 10000 * Vr / (3.3 - Vr)
temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
Cel = temp - 273.15
Fah = Cel * 1.8 + 32
print ('Celsius: %.2f C Fahrenheit: %.2f F' % (Cel, Fah))
utime.sleep_ms(200)
After the program runs, the Shell will print out the Celsius and Fahrenheit temperatures.
How it works?
Each thermistor has a normal resistance. Here it is 10k ohm, which is measured under 25 degree Celsius.
When the temperature gets higher, the resistance of the thermistor decreases. Then the voltage data is converted to digital quantities by the A/D adapter.
The temperature in Celsius or Fahrenheit is output via programming.
import math
There is a numerics library which declares a set of functions to compute common mathematical operations and transformations.
temperature_value = thermistor.read_u16()
This function is used to read the value of the thermistor.
Vr = 3.3 * float(temperature_value) / 65535
Rt = 10000 * Vr / (3.3 - Vr)
temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
Cel = temp - 273.15
Fah = Cel * 1.8 + 32
print ('Celsius: %.2f C Fahrenheit: %.2f F' % (Cel, Fah))
utime.sleep_ms(200)
These calculations convert the thermistor values into centigrade degree and Fahrenheit degree.
Vr = 3.3 * float(temperature_value) / 65535
Rt = 10000 * Vr / (3.3 - Vr)
In the two lines of code above, the voltage is first calculated using the read analoge value, and then get Rt (the resistance of the thermistor).
temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
Note
Here is the relation between the resistance and temperature:
RT =RN expB(1/TK – 1/TN)
RT is the resistance of the NTC thermistor when the temperature is TK.
RN is the resistance of the NTC thermistor under the rated temperature TN. Here, the numerical value of RN is 10k.
TK is a Kelvin temperature and the unit is K. Here, the numerical value of TK is 273.15 + degree Celsius.
TN is a rated Kelvin temperature; the unit is K too. Here, the numerical value of TN is 273.15+25.
And B(beta), the material constant of NTC thermistor, is also called heat sensitivity index with a numerical value 3950.
exp is the abbreviation of exponential, and the base number e is a natural number and equals 2.7 approximately.
Convert this formula TK=1/(ln(RT/RN)/B+1/TN) to get Kelvin temperature that minus 273.15 equals degree Celsius.
This relation is an empirical formula. It is accurate only when the temperature and resistance are within the effective range.
This code refers to plugging Rt into the formula TK=1/(ln(RT/RN)/B+1/TN) to get Kelvin temperature.
temp = temp - 273.15
Convert Kelvin temperature into centigrade degree.
Fah = Cel * 1.8 + 32
Convert the centigrade degree into Fahrenheit degree.
print ('Celsius: %.2f °C Fahrenheit: %.2f ℉' % (Cel, Fah))
Print centigrade degree, Fahrenheit degree and their units in the shell.
2.14 Feel the Water Level¶
Water sensor is designed for water detection, which can be widely used in sensing rainfall, water level, and even liquid leakage.
It measures the water level by having a series of exposed parallel wire traces to measure the size of the water drops/volume. The water volume is easily converted to an analog signal, and the output analog value can be read directly by the main control board to achieve the water level alarm effect.
Warning
The sensor cannot be fully submerged in water, please only leave the part where the ten Traces are located in contact with water. Also, energizing the sensor in a humid environment will accelerate the corrosion of the probe and reduce the life of the sensor, so it is recommended that you only supply power when taking readings.
Schematic
Wiring
Code
Note
Open the
2.14_feel_the_water_level.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
sensor = machine.ADC(28)
while True:
value=sensor.read_u16()
print(value)
utime.sleep_ms(200)
After the program is run, submerge the Water Sensor module slowly into the water, and as the depth increases, the Shell will print a larger value.
Learn More
There is a way to use the analog input module as a digital module.
First, take a reading of the Water Sensor in a dry environment first, record it, and use it as a threshold value. Then, complete the programming and re-read the reading of the water sensor. When the reading of the water sensor deviates significantly from the reading in a dry environment, it is exposed to liquid. In other words, by placing this device near a water pipe, it can detect if a water pipe is leaking.
Note
Open the
2.14_water_level_threshold.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
sensor = machine.ADC(28)
threshold = 30000 #This value needs to be modified with the environment.
while True:
value=sensor.read_u16()
if value > threshold :
print("Liquid leakage!")
utime.sleep_ms(200)
2.15 Two Kinds of Transistors¶
This kit is equipped with two types of transistors, S8550 and S8050, the former is PNP and the latter is NPN. They look very similar, and we need to check carefully to see their labels. When a High level signal goes through an NPN transistor, it is energized. But a PNP one needs a Low level signal to manage it. Both types of transistor are frequently used for contactless switches, just like in this experiment.
Let’s use LED and button to understand how to use transistor!
Way to connect NPN (S8050) transistor
In this circuit, when the button is pressed, GP14 is high.
By programming GP15 to output high, after a 1k current limiting resistor (to protect the transistor), the S8050 (NPN transistor) is allowed to conduct, thus allowing the LED to light up.
Way to connect PNP(S8550) transistor
In this circuit, GP14 is low by the default and will change to high when the button is pressed.
By programming GP15 to output low, after a 1k current limiting resistor (to protect the transistor), the S8550 (PNP transistor) is allowed to conduct, thus allowing the LED to light up.
The only difference you will notice between this circuit and the previous one is that in the previous circuit the cathode of the LED is connected to the collector of the S8050 (NPN transistor), while this one is connected to the emitter of the S8550 (PNP transistor).
Code
Note
Open the
2.15_transistor.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
button = machine.Pin(14, machine.Pin.IN)
signal = machine.Pin(15, machine.Pin.OUT)
while True:
button_status = button.value()
if button_status== 1:
signal.value(1)
elif button_status == 0:
signal.value(0)
Two kinds of transistors can be controlled with the same code. When we press the button, Pico will send a high-level signal to the transistor; when we release it, it will send a low-level signal. We can see that diametrically opposite phenomena have occurred in the two circuits.
The circuit using the S8050 (NPN transistor) will light up when the button is pressed, which means it is receiving a high-level conduction circuit;
The circuit that uses the S8550 (PNP transistor) will light up when it is released, which means it is receiving a low-level conduction circuit.
2.16 Control Another Circuit¶
In our daily life, we can press the switch to light up or turn off the lamp. But what if you want to control the lamp with Pico so that it can turn off automatically after ten minutes?
A relay can help you accomplish this idea.
A relay is actually a special kind of switch that is controlled by one side of the circuit (usually a low-voltage circuit) and used to control the other side of the circuit (usually a high-voltage circuit). This makes it practical to modify our home appliances to be controlled by a program, to become smart devices, or even to access the Internet.
Warning
Modification of electrical appliances comes with great danger, do not try it lightly, please do it under the guidance of professionals.
Here we only use a simple circuit powered by a breadboard power module as an example to show how to control it using relay.
Wiring
First, build a low-voltage circuit for controlling a relay. Driving the relay requires a high current, so a transistor is needed, and here we use the S8050.
A diode (continuity diode) is used here to protect the circuit. The cathode is the end with the silver ribbon connected to the power supply, and the anode is connected to the transistor.
When the voltage input changes from High (5V) to Low (0V), the transistor changes from saturation (amplification, saturation, and cutoff) to cutoff, and there is suddenly no way for current to flow through the coil.
At this point, if this freewheeling diode does not exist, the coil will produce a self-induced electric potential at both ends that is several times higher than the supply voltage, and this voltage plus the voltage from the transistor power supply is enough to burn it.
After adding the diode, the coil and the diode instantly form a new circuit powered by the energy stored in the coil to discharge, thus avoiding the excessive voltage will damage devices such as transistors on the circuit.
At this point the program is ready to run, and after running you will hear the “tik tok” sound, which is the sound of the contactor coil inside the relay sucking and breaking.
Then we connect the two ends of the load circuit to pins 3 and 6 of the relay respectively.
..(Take the simple circuit powered by the breadboard power module described in the previous article as an example.)
At this point, the relay will be able to control the load circuit on and off.
Code
Note
Open the
2.16_control_another_circuit.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
relay = machine.Pin(15, machine.Pin.OUT)
while True:
relay.value(1)
utime.sleep(2)
relay.value(0)
utime.sleep(2)
When the code is run, the relay will switch the operating state of the controlled circuit every two seconds. You can manually comment out one of the lines to further clarify the correspondence between the relay circuit and the load circuit.
Learn More
Pin 3 of the relay is normally open and only turns on when the contactor coil is operating; pin 4 is normally closed and turns on when the contactor coil is energized. Pin 1 is connected to pin 6 and is the common terminal of the load circuit.
By switching one end of the load circuit from pin 3 to pin 4, you will be able to get exactly the opposite operating state.
3. Sound & Display & Movement
3.1 Beep¶
The active buzzer is a typical digital output device that is as easy to use as lighting up an LED!
Schematic
When the GP15 output is high, after the 1K current limiting resistor (to protect the transistor), the S8050 (NPN transistor) will conduct, so that the buzzer will sound.
The role of S8050 (NPN transistor) is to amplify the current and make the buzzer sound louder. In fact, you can also connect the buzzer directly to GP15, but you will find that the buzzer sound is smaller.
Wiring
Two types of buzzers are included in the kit. We need to use active buzzer. Turn them around, the sealed back (not the exposed PCB) is the one we want.
The buzzer needs to use a transistor when working, here we use S8050 (NPN Transistor).
Code
Note
Open the
3.1_beep.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
buzzer = machine.Pin(15, machine.Pin.OUT)
while True:
for i in range(4):
buzzer.value(1)
utime.sleep(0.3)
buzzer.value(0)
utime.sleep(0.3)
utime.sleep(1)
After the code runs, you will hear a beep every second.
3.2 Custom Tone¶
We have used active buzzer in the previous project, this time we will use passive buzzer.
Like the active buzzer, the passive buzzer also uses the phenomenon of electromagnetic induction to work. The difference is that a passive buzzer does not have oscillating source, so it will not beep if DC signals are used. But this allows the passive buzzer to adjust its own oscillation frequency and can emit different notes such as “doh, re, mi, fa, sol, la, ti”.
Let the passive buzzer emit a melody!
Schematic
When the GP15 output is high, after the 1K current limiting resistor (to protect the transistor), the S8050 (NPN transistor) will conduct, so that the buzzer will sound.
The role of S8050 (NPN transistor) is to amplify the current and make the buzzer sound louder. In fact, you can also connect the buzzer directly to GP15, but you will find that the buzzer sound is smaller.
Wiring
Two buzzers are included in the kit, we use a passive buzzer (one with an exposed PCB on the back).
The buzzer needs a transistor to work, here we use S8050.
Code
Note
Open the
3.2_custom_tone.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
buzzer = machine.PWM(machine.Pin(15))
def tone(pin,frequency,duration):
pin.freq(frequency)
pin.duty_u16(30000)
utime.sleep_ms(duration)
pin.duty_u16(0)
tone(buzzer,440,250)
utime.sleep_ms(500)
tone(buzzer,494,250)
utime.sleep_ms(500)
tone(buzzer,523,250)
How it works?
If the passive buzzer given a digital signal, it can only keep pushing the diaphragm without producing sound.
Therefore, we use the tone()
function to generate the PWM signal to make the passive buzzer sound.
This function has three parameters:
pin, the GPIO pin that controls the buzzer.
frequency, the pitch of the buzzer is determined by the frequency, the higher the frequency, the higher the pitch.
Duration, the duration of the tone.
We use the duty_u16()
function to set the duty cycle to 30000(about 50%). It can be other numbers, and it only needs to generate a discontinuous electrical signal to oscillate.
Learn More
We can simulate the specific tone according to the fundamental frequency of the piano, so as to play a complete piece of music.
Note
Open the
3.2_custom_tone_2.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
NOTE_C4 = 262
NOTE_G3 = 196
NOTE_A3 = 220
NOTE_B3 = 247
melody =[NOTE_C4,NOTE_G3,NOTE_G3,NOTE_A3,NOTE_G3,NOTE_B3,NOTE_C4]
buzzer = machine.PWM(machine.Pin(15))
def tone(pin,frequency,duration):
pin.freq(frequency)
pin.duty_u16(30000)
utime.sleep_ms(duration)
pin.duty_u16(0)
for note in melody:
tone(buzzer,note,250)
utime.sleep_ms(150)
3.3 RGB LED Strip¶
WS2812 is a intelligent control LED light source that the control circuit and RGB chip are integrated in a package of 5050 components. It internal include intelligent digital port data latch and signal reshaping amplification drive circuit. Also include a precision internal oscillator and a programmable constant current control part, effectively ensuring the pixel point light color height consistent.
The data transfer protocol use single NZR communication mode. After the pixel power-on reset, the DIN port receive data from controller, the first pixel collect initial 24bit data then sent to the internal data latch, the other data which reshaping by the internal signal reshaping amplification circuit sent to the next cascade pixel through the DO port. After transmission for each pixel,the signal to reduce 24bit. pixel adopt auto reshaping transmit technology, making the pixel cascade number is not limited the signal transmission, only depend on the speed of signal transmission.
Schematic
Wiring
Warning
One thing you need to pay attention to is current.
Although the LED Strip with any number of LEDs can be used in Pico, the power of its VBUS pin is limited. Here, we will use eight LEDs, which are safe. But if you want to use more LEDs, you need to add a separate power supply.
Code
Note
Open the
3.3_rgb_led_strip.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
Here you need to use the library called
ws2812.py
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Upload the Libraries to Pico.
import machine
from ws2812 import WS2812
ws = WS2812(machine.Pin(0),8)
ws[0] = [64,154,227]
ws[1] = [128,0,128]
ws[2] = [50,150,50]
ws[3] = [255,30,30]
ws[4] = [0,128,255]
ws[5] = [99,199,0]
ws[6] = [128,128,128]
ws[7] = [255,100,0]
ws.write()
Let’s select some favorite colors and display them on the RGB LED Strip!
How it works?
In the ws2812 library, we have integrated related functions into the WS2812 class.
You can use the RGB LED Strip with the following statement.
from ws2812 import WS2812
Declare a WS2812 type object, named “ws”, it is connected to “pin”, there are “number” RGB LEDs on the WS2812 strip.
ws = WS2812(pin,number)
ws is an array object, each element corresponds to one RGB LED on the WS2812 strip, for example, ws[0] is the first one, ws[7] is the eighth.
We can assign color values to each RGB LED, these values must be 24-bit color (represented with six hexadecimal digits) or list of 3 8-bit RGB.
For example, the red value is “0xFF0000” or “[255,0,0]”.
ws[i] = color value
Then use this statement to write the color for the LED Strip and light it up.
ws.write()
You can also directly use the following statement to make all LEDs light up the same color.
ws.write_all(color value)
Learn More
We can randomly generate colors and make a colorful flowing light.
Note
Open the
3.3_rgb_led_strip_2.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
from ws2812 import WS2812
import utime
import urandom
ws = WS2812(machine.Pin(0),8)
def flowing_light():
for i in range(7,0,-1):
ws[i] = ws[i-1]
ws[0] = int(urandom.uniform(0, 0xFFFFFF))
ws.write()
utime.sleep_ms(80)
while True:
flowing_light()
print(ws[0])
3.4 Liquid Crystal Display¶
LCD1602 is a character type liquid crystal display, which can display 32 (16*2) characters at the same time.
As we all know, though LCD and some other displays greatly enrich the man-machine interaction, they share a common weakness. When they are connected to a controller, multiple IOs will be occupied of the controller which has no so many outer ports. Also it restricts other functions of the controller. Therefore, LCD1602 with an I2C bus is developed to solve the problem.
Here we will use the I2C0 interface to control the LCD1602 and display text.
Schematic
Wiring
Code
Note
Open the
3.4_liquid_crystal_display.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
Here you need to use the library called
lcd1602.py
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Upload the Libraries to Pico.
from lcd1602 import LCD
import utime
lcd = LCD()
string = " Hello!\n"
lcd.message(string)
utime.sleep(2)
string = " Sunfounder!"
lcd.message(string)
utime.sleep(2)
lcd.clear()
After the program runs, you will be able to see two lines of text appear on the LCD in turn, and then disappear.
Note
If the code and wiring are fine, but the LCD still does not display content, you can turn the potentiometer on the back to increase the contrast.
How it works?
In the lcd1602 library, we integrate the relevant functions of lcd1602 into the LCD class.
Import lcd1602 library
from lcd1602 import LCD
Declare an object of the LCD class and name it lcd.
lcd = LCD()
This statement will display the text on the LCD. It should be noted that the argument must be a string type. If we want to pass an integer or float, we must use the forced conversion statement str()
.
lcd.message(string)
If you call this statement multiple times, lcd will superimpose the texts. This requires the use of the following statement to clear the display.
lcd.clear()
3.5 Small Fan¶
Now we use the L293D to drive the DC motor to make it rotate clockwise and counterclockwise. Since the DC motor requires a relatively large current, for safety reasons, here we use a power module to supply power to the motor.
Schematic
In this circuit, you will see that the button is connected to the RUN pin. This is because the motor is operating with too much current, which may cause the Pico to disconnect from the computer, and the button needs to be pressed (for the Pico’s RUN pin to receive a low level) to reset.
L293D is a motor driver chip, EN is connected to 5V to make L293D work. 1A and 2A are the inputs connected to GP15 and GP14 respectively; 1Y and 2Y are the outputs connected to the two ends of the motor.
Y (output) is in phase with A (input), so if GP15 and GP14 are given different levels respectively, the direction of motor rotation can be changed.
Wiring
Since DC motors require a high current, we use a power supply module to power the motor here for safety reasons.
Code
Note
Open the
3.5_small_fan.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
motor1A = machine.Pin(14, machine.Pin.OUT)
motor2A = machine.Pin(15, machine.Pin.OUT)
def clockwise():
motor1A.high()
motor2A.low()
def anticlockwise():
motor1A.low()
motor2A.high()
def stopMotor():
motor1A.low()
motor2A.low()
while True:
clockwise()
utime.sleep(1)
stopMotor()
utime.sleep(1)
anticlockwise()
utime.sleep(1)
stopMotor()
utime.sleep(1)
Once the program is running, the motor will rotate back and forth in a regular pattern.
Note
If the motor is still spinning after you click the Stop button, you need to reset the RUN pin on the Pico with a wire to GND at this time, and then unplug this wire to run the code again.
This is because the motor is operating with too much current, which may cause the Pico to disconnect from the computer.
3.6 Pumping¶
Small centrifugal pumps are suitable for projects with automatic plant watering. It can also be used to make tiny smart water features.
Its power component is an electric motor, driven in exactly the same way as a normal motor.
Note
Connect the tube to the motor outlet, submerge the pump in water, and then power it on.
You need to make sure that the water level is always higher than the motor. Idling may damage the motor due to heat generation and will also generate noise.
If you are watering plants, you need to avoid soil being drawn in, as this can clog the pump.
If water does not come out of the tube, there may be residual water in the tube blocking the air flow and needs to be drained first.
Schematic
In this circuit, you will see that the button is connected to the RUN pin. This is because the motor is operating with too much current, which may cause the Pico to disconnect from the computer, and the button needs to be pressed (for the Pico’s RUN pin to receive a low level) to reset.
L293D is a motor driver chip, EN is connected to 5V to make L293D work. 1A and 2A are the inputs connected to GP15 and GP14 respectively; 1Y and 2Y are the outputs connected to the two ends of the motor.
Y (output) is in phase with A (input), so if GP15 and GP14 are given different levels respectively, the direction of motor rotation can be changed.
Wiring
Code
Note
Open the
3.6_pumping.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
motor1A = machine.Pin(14, machine.Pin.OUT)
motor2A = machine.Pin(15, machine.Pin.OUT)
while True:
motor1A.high()
motor2A.low()
After the code is run, the pump starts working and you will see water flowing out of the tube at the same time.
Note
If the motor is still spinning after you click the Stop button, you need to reset the RUN pin on the Pico with a wire to GND at this time, and then unplug this wire to run the code again.
This is because the motor is operating with too much current, which may cause the Pico to disconnect from the computer.
3.7 Swinging Servo¶
In this kit, in addition to LED and passive buzzer, there is also a device controlled by PWM signal, Servo.
Servo is a position (angle) servo device, which is suitable for those control systems that require constant angle changes and can be maintained. It has been widely used in high-end remote control toys, such as airplanes, submarine models, and remote control robots.
Now, try to make the servo sway!
Schematic
Wiring
Orange wire is signal and connected to GP15.
Red wire is VCC and connected to VBUS(5V).
Brown wire is GND and connected to GND.
Code
Note
Open the
3.7_swinging_servo.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
servo = machine.PWM(machine.Pin(15))
servo.freq(50)
def interval_mapping(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
def servo_write(pin,angle):
pulse_width=interval_mapping(angle, 0, 180, 0.5,2.5)
duty=int(interval_mapping(pulse_width, 0, 20, 0,65535))
pin.duty_u16(duty)
while True:
for angle in range(180):
servo_write(servo,angle)
utime.sleep_ms(20)
for angle in range(180,-1,-1):
servo_write(servo,angle)
utime.sleep_ms(20)
When the program is running, we can see the Servo Arm swinging back and forth from 0° to 180°.
The program will always run because of the while True
loop, we need to press the Stop button to end the program.
How it works?
We defined the servo_write()
function to make the servo run.
This function has two parameters:
pin
, the GPIO pin that controls the servo.Angle
, the angle of the shaft output.
In this function, interval_mapping()
is called to map the angle range 0 ~ 180 to the pulse width range 0.5 ~ 2.5ms.
pulse_width=interval_mapping(angle, 0, 180, 0.5,2.5)
Why is it 0.5~2.5? This is determined by the working mode of the Servo.
Next, convert the pulse width from period to duty. Since duty_u16()
cannot have decimals when used (the value cannot be a float type), we used int()
to force the duty to be converted to an int type.
duty=int(interval_mapping(pulse_width, 0, 20, 0,65535))
Finally, write the duty value into duty_u16()
.
4. Controller
4.1 Toggle the Joystick¶
If you play a lot of video games, then you should be very familiar with the Joystick. It is usually used to move the character around, rotate the screen, etc.
The principle behind Joystick’s ability to allow the computer to read our actions is very simple. It can be thought of as consisting of two potentiometers that are perpendicular to each other. These two potentiometers measure the analog value of the joystick vertically and horizontally, resulting in a value (x,y) in a planar right-angle coordinate system.
The joystick of this kit also has a digital input, which is activated when the joystick is pressed.
Schematic
The SW pin is connected to a 10K pull-up resistor, the reason is to be able to get a stable high level on the SW pin (Z axis) when the joystick is not pressed; otherwise the SW is in a suspended state and the output value may vary between 0/1.
Wiring
Code
Note
Open the
4.1_toggle_the_joystick.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
x_joystick = machine.ADC(27)
y_joystick = machine.ADC(26)
z_switch = machine.Pin(22,machine.Pin.IN)
while True:
x_value = x_joystick.read_u16()
y_value = y_joystick.read_u16()
z_value = z_switch.value()
print(x_value,y_value,z_value)
utime.sleep_ms(200)
After the program runs, the Shell prints out the x,y,z values of joystick.
The x-axis and y-axis values are analog values that vary from 0 to 65535.
The Z-axis is a digital value with a status of 1 or 0.
4.2 4x4 Keypad¶
The 4x4 keyboard, also known as the matrix keyboard, is a matrix of 16 keys excluded in a single panel.
The keypad can be found on devices that mainly require digital input, such as calculators, TV remote controls, push-button phones, vending machines, ATMs, combination locks, and digital door locks.
In this project, we will learn how to determine which key is pressed and get the related key value.
Schematic
4 pull-down resistors are connected to each of the columns of the matrix keyboard, so that G6 ~ G9 get a stable low level when the keys are not pressed.
The rows of the keyboard (G2 ~ G5) are programmed to go high; if one of G6 ~ G9 is read high, then we know which key is pressed.
For example, if G6 is read high, then numeric key 1 is pressed; this is because the control pins of numeric key 1 are G2 and G6, when numeric key 1 is pressed, G2 and G6 will be connected together and G6 is also high.
Wiring
To make the wiring easier, in the above diagram, the column row of the matrix keyboard and the 10K resistors are inserted into the holes where G6 ~ G9 are located at the same time.
Code
Note
Open the
4.2_4x4_keypad.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import time
characters = [["1","2","3","A"],["4","5","6","B"],["7","8","9","C"],["*","0","#","D"]]
pin = [2,3,4,5]
row = []
for i in range(4):
row.append(None)
row[i] = machine.Pin(pin[i], machine.Pin.OUT)
pin = [6,7,8,9]
col = []
for i in range(4):
col.append(None)
col[i] = machine.Pin(pin[i], machine.Pin.IN)
def readKey():
key = []
for i in range(4):
row[i].high()
for j in range(4):
if(col[j].value() == 1):
key.append(characters[i][j])
row[i].low()
if key == [] :
return None
else:
return key
last_key = None
while True:
current_key = readKey()
if current_key == last_key:
continue
last_key = current_key
if current_key != None:
print(current_key)
time.sleep(0.1)
After the program runs, the Shell will print out the keys you pressed on the Keypad.
How it works
import machine
import time
characters = [["1","2","3","A"],["4","5","6","B"],["7","8","9","C"],["*","0","#","D"]]
pin = [2,3,4,5]
row = []
for i in range(4):
row.append(None)
row[i] = machine.Pin(pin[i], machine.Pin.OUT)
pin = [6,7,8,9]
col = []
for i in range(4):
col.append(None)
col[i] = machine.Pin(pin[i], machine.Pin.IN)
Declare each key of the matrix keyboard to the array characters[]
and define the pins on each row and column.
last_key = None
while True:
current_key = readKey()
if current_key == last_key:
continue
last_key = current_key
if current_key != None:
print(current_key)
time.sleep(0.1)
This is the part of the main function that reads and prints the button value.
The function readKey()
will read the state of every button.
The statement if current_key != None
and if current_key == last_key
is used to judge whether a key is pressed and the state of the pressed button.
(If you press ‘3’ when you press ‘1’, the judgement is tenable.)
Prints the value of the currently pressed key when the condition is tenable.
The statement last_key = current_key
assigns the state of each judgment
to an array last_key
to facilitate the next round of conditional judgment.
def readKey():
key = []
for i in range(4):
row[i].high()
for j in range(4):
if(col[j].value() == 1):
key.append(characters[i][j])
row[i].low()
if key == [] :
return None
else:
return key
This function assigns a high level to each row in turn, and when the button is pressed,
the column in which the key is located gets a high level.
After the two-layer loop is judged, the value of the button whose state is 1 is stored in the array key
.
If you press the key ‘3’:
row[0]
is written in high level, and col[2]
gets high level.
col[0]
, col[1]
, col[3]
get low level.
There are four states:0, 0, 1, 0; and we write ‘3’ into pressed_keys
.
When row[1]
, row[2]
, row[3]
are written into high level,
col[0]
~ col[4]
get low level.
The loop stopped, there returns key = ‘3’.
If you press the buttons ‘1’ and ‘3’, there will return key = [‘1’,’3’].
4.3 Electrode Keyboard¶
The MPR121 is a good choice when you want to add a large number of touch switches to your project. It has electrodes that can be extended with conductors. If you connect the electrodes to a banana, you can turn the banana into a touch switch.
Schematic
Wiring
Code
Note
Open the
4.3_electrode_keyboard.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
Here you need to use the library called
mpr121.py
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Upload the Libraries to Pico.
from mpr121 import MPR121
from machine import Pin, I2C
import time
i2c = I2C(1, sda=Pin(6), scl=Pin(7))
mpr = MPR121(i2c)
# check all keys
while True:
value = mpr.get_all_states()
if len(value) != 0:
print(value)
time.sleep_ms(100)
After the program runs, you can touch the twelve electrodes on the MPR121 with your hand and the touched electrodes will be printed out.
You can extend the electrodes to connect other conductors such as fruit, wire, foil, etc. This will give you more ways to trigger these electrodes.
How it works?
In the mpr121 library, we have integrated the functionality into the MPR121
class.
from mpr121 import MPR121
MPR121 is an I2C module that requires a set of I2C pins to be defined to initialize the MPR121
object. At this point the state of the module’s electrodes will be recorded as initial values. If the electrodes are extended, the example needs to be rerun to reset the initial values.
from machine import Pin, I2C
i2c = I2C(1, sda=Pin(6), scl=Pin(7))
mpr = MPR121(i2c)
Then use mpr.get_all_states()
to read if the electrodes are triggered. If electrodes 2 and 3 are triggered, the value [2, 3]
will be generated.
while True:
value = mpr.get_all_states()
if len(value) ! = 0:
print(value)
time.sleep_ms(100)
You can also use mpr.is_touched(electrode)
to detect a specific electrode. When triggered, it returns True
, otherwise it returns False
.
while True:
value = mpr.is_touched(0)
print(value)
time.sleep_ms(100)
5. Microchip
5.1 Microchip - 74HC595¶
Integrated circuit (integrated circuit) is a kind of miniature electronic device or component, which is represented by the letter “IC” in the circuit.
A certain process is used to interconnect the transistors, resistors, capacitors, inductors and other components and wiring required in a circuit, fabricate on a small or several small semiconductor wafers or dielectric substrates, and then package them in a package , it has become a micro-structure with the required circuit functions; all of the components have been structured as a whole, making electronic components a big step towards micro-miniaturization, low power consumption, intelligence and high reliability.
The inventors of integrated circuits are Jack Kilby (integrated circuits based on germanium (Ge)) and Robert Norton Noyce (integrated circuits based on silicon (Si)).
This kit is equipped with an IC, 74HC595, which can greatly save the use of GPIO pins. Specifically, it can replace 8 pins for digital signal output by writing an 8-bit binary number.
Schematic
When MR (pin10) is high level and OE (pin13) is low level, data is input in the rising edge of SHcp and goes to the memory register through the rising edge of SHcp.
If the two clocks are connected together, the shift register is always one pulse earlier than the memory register.
There is a serial shift input pin (Ds), a serial output pin (Q) and an asynchronous reset button (low level) in the memory register.
The memory register outputs a Bus with a parallel 8-bit and in three states.
When OE is enabled (low level), the data in memory register is output to the bus(Q0 ~ Q7).
Wiring
Code
Note
Open the
5.1_microchip_74hc595.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import time
sdi = machine.Pin(0,machine.Pin.OUT)
rclk = machine.Pin(1,machine.Pin.OUT)
srclk = machine.Pin(2,machine.Pin.OUT)
def hc595_shift(dat):
rclk.low()
time.sleep_ms(5)
for bit in range(7, -1, -1):
srclk.low()
time.sleep_ms(5)
value = 1 & (dat >> bit)
sdi.value(value)
time.sleep_ms(5)
srclk.high()
time.sleep_ms(5)
time.sleep_ms(5)
rclk.high()
time.sleep_ms(5)
num = 0
for i in range(16):
if i < 8:
num = (num<<1) + 1
elif i>=8:
num = (num & 0b01111111)<<1
hc595_shift(num)
print("{:0>8b}".format(num))
time.sleep_ms(200)
When the program is running, num
will be written into the 74HC595 chip as an eight-bit binary number to control the on and off of the 8 LEDs.
We can see the current value of num
in the shell.
How it works?
hc595_shift()
will make 74HC595 output 8 digital signals. It outputs the last bit of the binary number to Q0, and the output of the first bit to Q7. In other words, writing the binary number “00000001” will make Q0 output high level and Q1~Q7 output low level.
5.2 Number Display¶
7 Segment Display can be seen everywhere in life. For example, on an air conditioner, it can be used to display temperature; on a traffic indicator, it can be used to display a timer.
The 7 Segment Display is essentially a device packaged by 8 LEDs, of which 7 strip-shaped LEDs form an “8” shape, and there is a slightly smaller dotted LED as a decimal point. These LEDs are marked as a, b, c, d, e, f, g, and dp. They have their own anode pins and share cathodes. Their pin locations are shown in the figure below.
This means that it needs to be controlled by 8 digital signals at the same time to fully work and the 74HC595 can do this.
Schematic
Here the wiring principle is basically the same as 5.1 Microchip - 74HC595, the only difference is that Q0-Q7 are connected to the a ~ g pins of the 7 Segment Display.
74HC595 |
LED Segment Display |
---|---|
Q0 |
a |
Q1 |
b |
Q2 |
c |
Q3 |
d |
Q4 |
e |
Q5 |
f |
Q6 |
g |
Q7 |
dp |
Wiring
Code
Note
Open the
5.2_number_display.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import time
SEGCODE = [0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f]
sdi = machine.Pin(0,machine.Pin.OUT)
rclk = machine.Pin(1,machine.Pin.OUT)
srclk = machine.Pin(2,machine.Pin.OUT)
def hc595_shift(dat):
rclk.low()
time.sleep_ms(5)
for bit in range(7, -1, -1):
srclk.low()
time.sleep_ms(5)
value = 1 & (dat >> bit)
sdi.value(value)
time.sleep_ms(5)
srclk.high()
time.sleep_ms(5)
time.sleep_ms(5)
rclk.high()
time.sleep_ms(5)
while True:
for num in range(10):
hc595_shift(SEGCODE[num])
time.sleep_ms(500)
When the program is running, you will be able to see the LED Segment Display display 0~9 in sequence.
How it works?
hc595_shift()
will make 74HC595 output 8 digital signals.
It outputs the last bit of the binary number to Q0, and the output of the first bit to Q7. In other words, writing the binary number “00000001” will make Q0 output high level and Q1~Q7 output low level.
Suppose that the 7-segment Display display the number “1”, we need to write a high level for b, c, and write a low level for a, d, e, f, g, and dg.
That is, the binary number “00000110” needs to be written. For readability, we will use hexadecimal notation as “0x06”.
Similarly, we can also make the LED Segment Display display other numbers in the same way. The following table shows the codes corresponding to these numbers.
Numbers |
Binary Code |
Hex Code |
---|---|---|
0 |
00111111 |
0x3f |
1 |
00000110 |
0x06 |
2 |
01011011 |
0x5b |
3 |
01001111 |
0x4f |
4 |
01100110 |
0x66 |
5 |
01101101 |
0x6d |
6 |
01111101 |
0x7d |
7 |
00000111 |
0x07 |
8 |
01111111 |
0x7f |
9 |
01101111 |
0x6f |
Write these codes into hc595_shift()
to make the LED Segment Display display the corresponding numbers.
5.3 Time Counter¶
4-digit 7-segment display consists of four 7-segment displays working together.
The 4-digtal 7-segment display works independently. It uses the principle of human visual persistence to quickly display the characters of each 7-segment in a loop to form continuous strings.
For example, when “1234” is displayed on the display, “1” is displayed on the first 7-segment, and “234” is not displayed. After a period of time, the second 7-segment shows “2”, the 1st 3th 4th of 7-segment does not show, and so on, the four digital display show in turn. This process is very short (typically 5ms), and because of the optical afterglow effect and the principle of visual residue, we can see four characters at the same time.
Schematic
Here the wiring principle is basically the same as 5.1 Microchip - 74HC595, the only difference is that Q0-Q7 are connected to the a ~ g pins of the 4-digit 7-segment display.
Then G10 ~ G13 will select which 7-segment display to work.
Wiring
Code
Note
Open the
5.3_time_counter.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import time
SEGCODE = [0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f]
sdi = machine.Pin(18,machine.Pin.OUT)
rclk = machine.Pin(19,machine.Pin.OUT)
srclk = machine.Pin(20,machine.Pin.OUT)
placePin = []
pin = [10,13,12,11]
for i in range(4):
placePin.append(None)
placePin[i] = machine.Pin(pin[i], machine.Pin.OUT)
timerStart=time.ticks_ms()
def timer1():
return int((time.ticks_ms()-timerStart)/1000)
def pickDigit(digit):
for i in range(4):
placePin[i].value(1)
placePin[digit].value(0)
def clearDisplay():
hc595_shift(0x00)
def hc595_shift(dat):
rclk.low()
time.sleep_us(200)
for bit in range(7, -1, -1):
srclk.low()
time.sleep_us(200)
value = 1 & (dat >> bit)
sdi.value(value)
time.sleep_us(200)
srclk.high()
time.sleep_us(200)
time.sleep_us(200)
rclk.high()
time.sleep_us(200)
while True:
count = timer1()
#print(count)
pickDigit(0)
hc595_shift(SEGCODE[count%10])
pickDigit(1)
hc595_shift(SEGCODE[count%100//10])
pickDigit(2)
hc595_shift(SEGCODE[count%1000//100])
pickDigit(3)
hc595_shift(SEGCODE[count%10000//1000])
After the program is run, you will see the 4-digit 7-segment display become a counter and the number increases by 1 per second.
How it works?
Writing signals to each 7-segment display is done in the same way as 5.2 Number Display, using the hc595_shift()
function.
The core point of the 4-digit 7-segment display is to selectively activate each 7-segment display. The code associated with this is as follows.
placePin = []
pin = [13,12,11,10]
for i in range(4):
placePin.append(None)
placePin[i] = machine.Pin(pin[i], machine.Pin.OUT)
def pickDigit(digit):
for i in range(4):
placePin[i].value(1)
placePin[digit].value(0)
while True:
hc595_shift(SEGCODE[count%10])
pickDigit(0)
hc595_shift(SEGCODE[count%100//10])
pickDigit(1)
hc595_shift(SEGCODE[count%1000//100])
pickDigit(2)
hc595_shift(SEGCODE[count%10000//1000])
pickDigit(3)
Here, four pins (GP10, GP11, GP12, GP13) are used to control each bit of the 4-digit 7-segment display individually.
When the state of these pins is 0
, the corresponding 7-segment display is active; when the state is 1
, the opposite is true.
Here the pickDigit(digit)
function is used to unable all four digits and then enable a particular digit individually.
After that, hc595_shift()
is used to write the corresponding 8 bits code for the 7-segment display.
The 4-digit 7-segment display needs to be continuously activated in turn so that we can see it display four digits, which means that the main program cannot easily add code that would affect the timing.
However, we need to add a timing function to this example, and if we add a sleep(1)
, we will know that it has four digits.
we will see through the illusion of 4-digit 7-segment display working at the same time, exposing the fact that only one 7-segment display is illuminated at a time.
Then, using the time.ticks_ms()
function in the time
library is an excellent way to do this.
import time
timerStart=time.ticks_ms()
def timer1():
return int((time.ticks_ms()-timerStart)/1000)
while True:
count = timer1()
The time.ticks_ms()
function gets a (non-explicit) time, and we record the first time value we get as timerStart
.
Subsequently, when the time is needed, the time.ticks_ms()
function is called again, and the value is subtracted from timerStart
to get how long the program has been running (in milliseconds).
Finally, convert and output this time value to the 4-digit 7-segment display and you’re done.
5.4 8x8 Pixel Graphics¶
LED matrix is a low-resolution dot-matrix display. it uses an array of light-emitting diodes as pixels for patterned displays.
They are bright enough to be visible in outdoor sunlight, and you can see them on some stores, billboards, signs, and variable message displays (such as those on public transit vehicles).
Used in this kit is an 8x8 dot matrix with 16 pins. Their anodes are connected in rows and their cathodes are connected in columns (at the circuit level), which together control these 64 LEDs.
To light the first LED, you should provide a high level for Row1 and a low level for Col1. To light the second LED, it should provide a high level for Row1, a low level for Col2, and so on. By controlling the current through each pair of rows and columns, each LED can be controlled individually to display characters or pictures.
Schematic
The 8x8 dot matrix is controlled by two 74HC595 chips, one controlling the rows and one controlling the columns, while these two chips share G18~G20, which can greatly save the I/O ports of the Pico board.
Pico needs to output a 16-bit binary number at a time, the first 8 bits are given to the 74HC595 which controls the rows, and the last 8 bits are given to the 75HC595 which controls the columns, so that the dot matrix can display a specific pattern.
Q7’: Series output pin, connected to DS of another 74HC595 to connect multiple 74HC595s in series.
Wiring
Build the circuit. Since the wiring is complicated, let’s make it step by step.
Step 1: First, insert the pico, the LED dot matrix and two 74HC595 chips into breadboard. Connect the 3.3V and GND of the pico to holes on the two sides of the board, then hook up pin16 and 10 of the two 74HC595 chips to VCC, pin 13 and pin 8 to GND.
Note
In the Fritzing image above, the side with label is at the bottom.
Step 2: Connect pin 11 of the two 74HC595 together, and then to GP20; then pin 12 of the two chips, and to GP19; next, pin 14 of the 74HC595 on the left side to GP18 and pin 9 to pin 14 of the second 74HC595.
Step 3: The 74HC595 on the right side is to control columns of the LED dot matrix. See the table below for the mapping. Therefore, Q0-Q7 pins of the 74HC595 are mapped with pin 13, 3, 4, 10, 6, 11, 15, and 16 respectively.
74HC595 |
Q0 |
Q1 |
Q2 |
Q3 |
Q4 |
Q5 |
Q6 |
Q7 |
LED Dot Matrix |
13 |
3 |
4 |
10 |
6 |
11 |
15 |
16 |
Step 4: Now connect the ROWs of the LED dot matrix. The 74HC595 on the left controls ROW of the LED dot matrix. See the table below for the mapping. We can see, Q0-Q7 of the 74HC595 on the left are mapped with pin 9, 14, 8, 12, 1, 7, 2, and 5 respectively.
74HC595 |
Q0 |
Q1 |
Q2 |
Q3 |
Q4 |
Q5 |
Q6 |
Q7 |
LED Dot Matrix |
9 |
14 |
8 |
12 |
1 |
7 |
2 |
5 |
Code
Note
Open the
5.4_8x8_pixel_graphics.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import time
sdi = machine.Pin(18,machine.Pin.OUT)
rclk = machine.Pin(19,machine.Pin.OUT)
srclk = machine.Pin(20,machine.Pin.OUT)
glyph = [0xFF,0xBB,0xD7,0xEF,0xD7,0xBB,0xFF,0xFF]
# Shift the data to 74HC595
def hc595_in(dat):
for bit in range(7,-1, -1):
srclk.low()
time.sleep_us(30)
sdi.value(1 & (dat >> bit))
time.sleep_us(30)
srclk.high()
def hc595_out():
rclk.high()
time.sleep_us(200)
rclk.low()
while True:
for i in range(0,8):
hc595_in(glyph[i])
hc595_in(0x80>>i)
hc595_out()
Once the program is running, you will see a x graphic displayed on the 8x8 dot matrix.
How it works?
Here we use two 74HC595s to provide signals for the rows and columns of the dot matrix.
The method of providing signals is the same as hc595_shift(dat)
in the previous chapters, but the difference is that here we need to write a 16-bit binary number at a time.
So we split hc595_shift(dat)
into two functions hc595_in(dat)
and hc595_out()
.
def hc595_in(dat):
for bit in range(7,-1, -1):
srclk.low()
time.sleep_us(30)
sdi.value(1 & (dat >> bit))
time.sleep_us(30)
srclk.high()
def hc595_out():
rclk.high()
time.sleep_us(200)
rclk.low()
Then, call hc595_in(dat)
twice in the main loop, write two 8-bit binary numbers and then call hc595_out()
so that a pattern can be displayed.
However, since the LEDs in the dot matrix use common poles, controlling multiple rows/multiple columns at the same time will interfere with each other (e.g., if you light up (1,1) and (2,2) at the same time, (1,2) and (2,1) will inevitably be lit up together). Therefore, it is necessary to activate one column (or one row) at a time, cycle 8 times, and use the residual image principle to make the human eye merge 8 patterns, so as to get a pair of patterns containing 8x8 amount of information.
while True:
for i in range(0,8):
hc595_in(glyph[i])
hc595_in(0x80>>i)
hc595_out()
In this example, the main function nests a for
loop, and when i
is 1, only the first line is activated (the chip in the control line gets the value 0x80
) and the image of the first line is written.
When i
is 2, the second line is activated (the chip of the control line gets the value 0x40
) and the image of the second line is written. And so on, completing 8 outputs.
Incidentally, like the 4-digit 7-segment display, it has to maintain the refresh rate to prevent flickering by the human eye, so the extra sleep()
in the main loop should be avoided as much as possible.
Learn More
Try replacing glyph
with the following array and see what comes up!
glyph1 = [0xFF,0xEF,0xC7,0xAB,0xEF,0xEF,0xEF,0xFF]
glyph2 = [0xFF,0xEF,0xEF,0xEF,0xAB,0xC7,0xEF,0xFF]
glyph3 = [0xFF,0xEF,0xDF,0x81,0xDF,0xEF,0xFF,0xFF]
glyph4 = [0xFF,0xF7,0xFB,0x81,0xFB,0xF7,0xFF,0xFF]
glyph5 = [0xFF,0xBB,0xD7,0xEF,0xD7,0xBB,0xFF,0xFF]
glyph6 = [0xFF,0xFF,0xF7,0xEB,0xDF,0xBF,0xFF,0xFF]
Or, you can try drawing your own graphics.
6. Advanced
6.1 Measuring Distance¶
The ultrasonic sensor module works on the principle of sonar and radar systems for determining the distance to an object.
Schematic
Wiring
Code
Note
Open the
6.1_measuring_distance.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import time
TRIG = machine.Pin(17,machine.Pin.OUT)
ECHO = machine.Pin(16,machine.Pin.IN)
def distance():
TRIG.low()
time.sleep_us(2)
TRIG.high()
time.sleep_us(10)
TRIG.low()
while not ECHO.value():
pass
time1 = time.ticks_us()
while ECHO.value():
pass
time2 = time.ticks_us()
during = time.ticks_diff(time2,time1)
return during * 340 / 2 / 10000
while True:
dis = distance()
print ('Distance: %.2f' % dis)
time.sleep_ms(300)
Once the program is running, the Shell will print out the distance of the ultrasonic sensor from the obstacle ahead.
How it works?
Ultrasonic sensors produce high frequency sound waves (ultrasonic waves) emitted by the transmitting probe. When this ultrasonic wave hits an object, it is reflected as an echo, which is detected by the receiving probe. By calculating the time from transmission to reception, the distance can be calculated.
Based on this principle, the function distance()
can be derived.
def distance():
TRIG.low()
time.sleep_us(2)
TRIG.high()
time.sleep_us(10)
TRIG.low()
while not ECHO.value():
pass
time1 = time.ticks_us()
while ECHO.value():
pass
time2 = time.ticks_us()
during = time.ticks_diff(time2,time1)
return during * 340 / 2 / 10000
Among them, the first few lines are used to transmit a 10us ultrasonic wave.
TRIG.low()
time.sleep_us(2)
TRIG.high()
time.sleep_us(10)
TRIG.low()
Then, the program is paused and the current time is recorded when the ultrasonic wave has been emitted.
while not ECHO.value():
pass
time1 = time.ticks_us()
Subsequently, the program is suspended again. After the echo is received, the current time is recorded once again.
while ECHO.value():
pass
time2 = time.ticks_us()
Finally, based on the time difference between the two recordings, the speed of sound (340m/s) is multiplied by the time to obtain double the distance between the ultrasonic module and the obstacle (i.e., one round trip of the ultrasonic waves from the module to the obstacle). Converting the units to centimeters gives us the return value we need.
during = time.ticks_diff(time2,time1)
return during * 340 / 2 / 10000
Note that the ultrasonic sensor will pause the program when it is working, which may cause some lagging when writing complex projects.
6.2 Temperature - Humidity¶
Humidity and temperature are closely related from the physical quantity itself to the actual people’s life. The temperature and humidity of human environment will directly affect the thermoregulatory function and heat transfer effect of human body. It will further affect the thinking activity and mental state, thus affecting the efficiency of our study and work.
Temperature is one of the seven basic physical quantities in the International System of Units, which is used to measure the degree of hot and cold of an object. Celsius is one of the more widely used temperature scales in the world, expressed by the symbol “℃”.
Humidity is the concentration of water vapor present in the air. The relative humidity of air is commonly used in life and is expressed in %RH. Relative humidity is closely related to temperature. For a certain volume of sealed gas, the higher the temperature, the lower the relative humidity, and the lower the temperature, the higher the relative humidity.
A basic digital temperature and humidity sensor, the DHT11, is provided in this kit. It uses a capacitive humidity sensor and thermistor to measure the surrounding air and outputs a digital signal on the data pins (no analog input pins are required).
Schematic
Wiring
Code
Note
Open the
6.2_temperature_humidity.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
Here you need to use the library called
dht.py
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Upload the Libraries to Pico.
from machine import Pin, I2C
import utime as time
from dht import DHT11
pin = Pin(16, Pin.OUT, Pin.PULL_DOWN)
sensor = DHT11(pin)
while True:
sensor.measure()
print("Temperature: {}, Humidity: {}".format(sensor.temperature, sensor.humidity))
time.sleep(1)
After the code is run, you will see the Shell continuously print out the temperature and humidity, and as the program runs steadily, these two values will become more and more accurate.
How it works?
In the dht library, we have integrated the relevant functionality into the DHT11
class.
from mpr121 import MPR121
Initialize the DHT11
object. This device only needs a digital input to be used.
pin = Pin(16, Pin.OUT, Pin.PULL_DOWN)
sensor = DHT11(pin)
Use sensor.measure()
to read the current temperature and humidity, which will be stored in sensor.temperature
, sensor.humidity
.
They are then printed out.
Finally the DHT11 sampling rate is 1HZ, a time.sleep(1)
is needed in the loop.
while True:
sensor.measure()
print("Temperature: {}, Humidity: {}".format(sensor.temperature, sensor.humidity))
time.sleep(1)
6.3 6-axis Motion Tracking¶
The MPU-6050 is a 6-axis(combines 3-axis Gyroscope, 3-axis Accelerometer) motion tracking devices.
An accelerometer is a tool that measures proper acceleration.For example, an accelerometer at rest on the surface of the Earth will measure an acceleration due to Earth’s gravity, straight upwards[3] (by definition) of g ≈ 9.81 m/s2.
Accelerometers have many uses in industry and science. For example: inertial navigation systems for aircraft and missiles, for keeping images on tablets and digital cameras vertical, etc.
Gyroscopes are used to measure orientation and angular velocity of a device or maintenance. Applications of gyroscopes include anti-rollover and airbag systems for automobiles, motion sensing systems for smart devices, attitude stabilization systems for drones, and more.
Schematic
Wiring
Code
Note
Open the
6.3_6axis_motion_tracking.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
Here you need to use the
imu.py
andvector3d.py
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Upload the Libraries to Pico.
from imu import MPU6050
from machine import I2C, Pin
import time
i2c = I2C(1, sda=Pin(6), scl=Pin(7), freq=400000)
mpu = MPU6050(i2c)
while True:
print("x: %s, y: %s, z: %s"%(mpu.accel.x, mpu.accel.y, mpu.accel.z))
time.sleep(0.1)
print("A: %s, B: %s, Y: %s"%(mpu.gyro.x, mpu.gyro.y, mpu.gyro.z))
time.sleep(0.1)
After running the program, you can see the 3-axis accelerometer values and 3-axis gyroscope values cycling through the output. At this point you rotate the MPU6050 at random, and these values will appear to change accordingly. To make it easier to see the changes, you can comment out one of the print lines and concentrate on another set of data.
How it works?
In the imu library, we have integrated the relevant functions into the MPU6050
class.
MPU6050 is an I2C module and requires a set of I2C pins to be defined for initialization.
from imu import MPU6050
from machine import I2C, Pin
i2c = I2C(1, sda=Pin(6), scl=Pin(7), freq=400000)
mpu = MPU6050(i2c)
Subsequently, you will be able to get real-time acceleration and angular velocity values in mpu.accel.x
, mpu.accel.y
, mpu.accel.z
, mpu.gyro.x
, mpu.gyro.y
, mpu.gyro.z
.
while True:
print("x: %s, y: %s, z: %s"%(mpu.accel.x, mpu.accel.y, mpu.accel.z))
time.sleep(0.1)
print("A: %s, B: %s, Y: %s"%(mpu.gyro.x, mpu.gyro.y, mpu.gyro.z))
time.sleep(0.1)
6.4 IR Remote Control¶
In consumer electronics, remote controls are used to operate devices such as televisions and DVD players. In some cases, remote controls allow people to operate devices that are out of their reach, such as central air conditioners.
IR Receiver is a component with photocell that is tuned to receive to infrared light. It is almost always used for remote control detection - every TV and DVD player has one of these in the front to receive for the IR signal from the clicker. Inside the remote control is a matching IR LED, which emits IR pulses to tell the TV to turn on, off or change channels.
Schematic
Wiring
Code
Note
Open the
6.4_ir_remote_control.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
Here you need to use the libraries in
ir_rx
folder, please check if it has been uploaded to Pico, for a detailed tutorial refer to Upload the Libraries to Pico.
import time
from machine import Pin, freq
from ir_rx.print_error import print_error
from ir_rx.nec import NEC_8
pin_ir = Pin(17, Pin.IN)
def decodeKeyValue(data):
if data == 0x16:
return "0"
if data == 0x0C:
return "1"
if data == 0x18:
return "2"
if data == 0x5E:
return "3"
if data == 0x08:
return "4"
if data == 0x1C:
return "5"
if data == 0x5A:
return "6"
if data == 0x42:
return "7"
if data == 0x52:
return "8"
if data == 0x4A:
return "9"
if data == 0x09:
return "+"
if data == 0x15:
return "-"
if data == 0x7:
return "EQ"
if data == 0x0D:
return "U/SD"
if data == 0x19:
return "CYCLE"
if data == 0x44:
return "PLAY/PAUSE"
if data == 0x43:
return "FORWARD"
if data == 0x40:
return "BACKWARD"
if data == 0x45:
return "POWER"
if data == 0x47:
return "MUTE"
if data == 0x46:
return "MODE"
return "ERROR"
# User callback
def callback(data, addr, ctrl):
if data < 0: # NEC protocol sends repeat codes.
pass
else:
print(decodeKeyValue(data))
ir = NEC_8(pin_ir, callback) # Instantiate receiver
ir.error_function(print_error) # Show debug information
try:
while True:
pass
except KeyboardInterrupt:
ir.close()
The new remote control has a plastic piece at the end to isolate the battery inside. You need to pull out this plastic piece to power up the remote when you are using it. Once the program is running, when you press the remote control, the Shell will print out the key you pressed.
How it works?
This program looks slightly complicated, but it actually does the basic functions of the IR receiver with just a few lines.
import time
from machine import Pin, freq
from ir_rx.nec import NEC_8
pin_ir = Pin(17, Pin.IN)
# User callback
def callback(data, addr, ctrl):
if data < 0: # NEC protocol sends repeat codes.
pass
else:
print(decodeKeyValue(data))
ir = NEC_8(pin_ir, callback) # Instantiate receiver
Here an ir
object is instantiated, which reads the signals acquired by the IR receiver at any time.
The result will be recorded in data
of the callback function.
If the IR receiver receives duplicate values (e.g. pressing a key and not releasing it), then data < 0 and this data needs to be filtered.
Otherwise data would be a usable value, but some unspeakable code, and the decodeKeyValue(data)
function is used to decode it.
def decodeKeyValue(data):
if data == 0x16:
return "0"
if data == 0x0C:
return "1"
if data == 0x18:
return "2"
if data == 0x5E:
return "3"
if data == 0x08:
return "4"
if data == 0x1C:
return "5"
if data == 0x5A:
return "6"
if data == 0x42:
return "7"
if data == 0x52:
return "8"
if data == 0x4A:
return "9"
if data == 0x09:
return "+"
if data == 0x15:
return "-"
if data == 0x7:
return "EQ"
if data == 0x0D:
return "U/SD"
if data == 0x19:
return "CYCLE"
if data == 0x44:
return "PLAY/PAUSE"
if data == 0x43:
return "FORWARD"
if data == 0x40:
return "BACKWARD"
if data == 0x45:
return "POWER"
if data == 0x47:
return "MUTE"
if data == 0x46:
return "MODE"
return "ERROR"
If we press key 1, the IR receiver outputs a value like 0x0C
, which needs to be decoded to correspond to the specific key.
Next are some debug functions. They are important, but not related to the effect we need to achieve, so we just put them in the program.
from ir_rx.print_error import print_error
ir.error_function(print_error) # Show debug information
Finally, we use an empty loop as the main program. And use try-except to make the program exit with the ir
object terminated.
try:
while True:
pass
except KeyboardInterrupt:
ir.close()
6.5 Radio Frequency Identification¶
Radio Frequency Identification (RFID) is a technology that uses wireless communication between an object (or tag) and an interrogating device (or reader) to track and identify it. The tag’s transmission range is limited to several meters. Readers and tags do not necessarily require a line of sight.
An integrated circuit (IC) and an antenna are usually present on most tags. As well as storing information, the microchip manages communication with the reader via radio frequency (RF). In passive tags, there is no independent energy source and they rely on an external electromagnetic signal from the reader for power. An active tag is powered by an independent energy source, such as a battery. As a result, they may be more powerful in terms of processing, transmission, and range.
Schematic
Wiring
Code
Here you need to use the libraries in mfrc522
folder, please check if it has been uploaded to Pico, for a detailed tutorial refer to Upload the Libraries to Pico.
The main function is divided into two:
6.5_rfid_write.py
: Used to write information to the card (or key).6.5_rfid_read.py
: used to read the information in the card (or key)
Open the 6.5_rfid_write.py
file under the path of euler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.
After running you will be able to type message in the shell and then put the card (or key) close to the MFRC522 module to write the message in.
from mfrc522 import SimpleMFRC522
reader = SimpleMFRC522(spi_id=0,sck=2,miso=4,mosi=3,cs=5,rst=0)
def write():
to_write = input("Please enter the message: ")
print("Writing...Please place the card...")
id, text = reader.write(to_write)
print("ID: %s\nText: %s" % (id,text))
write()
Open the 6.5_rfid_read.py
file under the path of euler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.
After running, you will be able to read the message stored in the card (or key).
from mfrc522 import SimpleMFRC522
reader = SimpleMFRC522(spi_id=0,sck=2,miso=4,mosi=3,cs=5,rst=0)
def read():
print("Reading...Please place the card...")
id, text = reader.read()
print("ID: %s\nText: %s" % (id,text))
read()
How it works?
from mfrc522 import SimpleMFRC522
reader = SimpleMFRC522(spi_id=0,sck=2,miso=4,mosi=3,cs=5,rst=0)
Instantiate SimpleMFRC522()
class.
id, text = reader.read()
This function is used to read card data. If the reading is successful, id and text will be returned.
id, text = reader.write("text")
This function is used to write information to the card, press Enter key to finish writing.
text
is the information to be written to the card.
7. Funny Project
7.1 Light Theremin¶
Theremin is an electronic musical instrument that does not require physical contact. Based on the position of the player’s hand, it produces different tones.
Its controlling section is usually made up of two metal antennas that sense the position of the thereminist’s hands and control oscillators with one hand and volume with the other. The electric signals from the theremin are amplified and sent to a loudspeaker.
We cannot reproduce the same instrument through Pico, but we can use photoresistor and passive buzzer to achieve similar gameplay.
Schematic
Before starting the project, wave your hand up and down over the photoresistor to calibrate the range of light intensity. The LED connected in GP16 is used to indicate the debugging time, and the LED is lit to indicate the start of debugging and off to indicate the end of debugging.
When GP15 outputs high level, S8050 (NPN transistor) conducts and the passive buzzer starts to sound.
When the light is stronger, GP28’s value is smaller; vice versa, it is larger when the light is weaker. By programming the value of the photoresistor to affect the frequency of the passive buzzer, a photosensitive device can be simulated.
Wiring
Code
Note
Open the
7.1_light_theremin.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import utime
led = machine.Pin(16, machine.Pin.OUT)
photoresistor = machine.ADC(28)
buzzer = machine.PWM(machine.Pin(15))
light_low=65535
light_high=0
def interval_mapping(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
def tone(pin,frequency,duration):
pin.freq(frequency)
pin.duty_u16(30000)
utime.sleep_ms(duration)
pin.duty_u16(0)
# calibrate the photoresistor max & min values.
timer_init_start = utime.ticks_ms()
led.value(1)
while utime.ticks_diff(utime.ticks_ms(), timer_init_start)<5000:
light_value = photoresistor.read_u16()
if light_value > light_high:
light_high = light_value
if light_value < light_low:
light_low = light_value
led.value(0)
# play
while True:
light_value = photoresistor.read_u16()
pitch = int(interval_mapping(light_value,light_low,light_high,50,6000))
if pitch > 50 :
tone(buzzer,pitch,20)
utime.sleep_ms(10)
As soon as the program runs, the LED will light up, and we will have five seconds to calibrate the photoresistor’s detection range.
This is due to the different light environments we may have when we use it (e.g., different light intensities at noon and dusk), as well as our hands’ height above the photoresistor. You need to set the maximum and minimum height of your hand from the photoresistor, which is also the height at which you play the instrument.
After five seconds, the LED will turn off, at which point we can wave our hands over the photoresistor and play.
7.2 Room Temperature Meter¶
Using a thermistor and an I2C LCD1602, we can create a room temperature meter.
This project is very simple, it is based on 2.13 Thermometer with I2C LCD1602 to display the temperature.
Schematic
Wiring
Code
Note
Open the
7.2_room_temperature_meter.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
from lcd1602 import LCD
import machine
import utime
import math
thermistor = machine.ADC(28)
lcd = LCD()
while True:
temperature_value = thermistor.read_u16()
Vr = 3.3 * float(temperature_value) / 65535
Rt = 10000 * Vr / (3.3 - Vr)
temp = 1/(((math.log(Rt / 10000)) / 3950) + (1 / (273.15+25)))
Cel = temp - 273.15
#Fah = Cel * 1.8 + 32
#print ('Celsius: %.2f C Fahrenheit: %.2f F' % (Cel, Fah))
#utime.sleep_ms(200)
string = " Temperature is \n " + str('{:.2f}'.format(Cel))+ " C"
lcd.message(string)
utime.sleep(1)
lcd.clear()
The LCD will display the temperature value in the current environment after the program runs.
Note
If the code and wiring are fine, but the LCD still does not display content, you can turn the potentiometer on the back to increase the contrast.
7.3 Alarm Siren Lamp¶
Police lights are often visible in real life (or in movies). Usually, it is used to maintain traffic, serve as a warning device, and serve as an important safety prop for officers, emergency vehicles, fire trucks, and engineering vehicles. When you see its lights or hear its sound, you must be careful, which means you (or those around you) may be in danger.
An LED and buzzer are used here to create a small warning light, which is activated by a slide switch.
Schematic
GP17 is connected to the middle pin of the slider, along with a 10K resistor and a capacitor (filter) in parallel to GND, which allows the slider to output a steady high or low level when toggled to the left or right.
As soon as GP15 is high, the NPN transistor conducts, causing the passive buzzer to start sounding. This passive buzzer is programmed to gradually increase in frequency to produce a siren sound.
An LED is connected to GP16 and is programmed to periodically change its brightness in order to simulate a siren.
Wiring
Code
Note
Open the
7.3_alarm_siren_lamp.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import time
buzzer = machine.PWM(machine.Pin(15))
led = machine.PWM(machine.Pin(16))
led.freq(1000)
switch = machine.Pin(17,machine.Pin.IN)
def noTone(pin):
pin.duty_u16(0)
def tone(pin,frequency):
pin.freq(frequency)
pin.duty_u16(30000)
def interval_mapping(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
def toggle(pin):
global bell_flag
bell_flag = not bell_flag
print(bell_flag)
if bell_flag:
switch.irq(trigger=machine.Pin.IRQ_FALLING, handler=toggle)
else:
switch.irq(trigger=machine.Pin.IRQ_RISING, handler=toggle)
bell_flag = False
switch.irq(trigger=machine.Pin.IRQ_RISING, handler=toggle)
while True:
if bell_flag == True:
for i in range(0,100,2):
led.duty_u16(int(interval_mapping(i,0,100,0,65535)))
tone(buzzer,int(interval_mapping(i,0,100,130,800)))
time.sleep_ms(10)
else:
noTone(buzzer)
led.duty_u16(0)
Once the program is running, toggle the slide switch to the left (yours may be to the right, depending on how your slide switch is wired) and the buzzer will emit a progressive warning tone and the LED will change its brightness accordingly; toggle the slide switch to the right and the buzzer and LED will stop working.
7.4 Passager Counter¶
For large shopping malls, shopping centers, chain stores, airports, stations, museums, and public places such as exhibition halls, passenger traffic is an indispensable data.
In airports and stations, for example, the number of people needs to be strictly controlled to ensure safety and smooth flow. It is also possible to know when there are more visitors in shopping centers and chain stores, how many orders each user can generate, etc. As a result, we can analyze people’s consumption habits and increase turnover.
Passenger counters can help people understand the operation of these public places and organize their operations efficiently.
A simple passager counter is created using a PIR sensor and a 4-digit 7-segment display.
Schematic
This circuit is based on the 5.3 Time Counter with the addition of a PIR module.
The PIR will send a high signal of about 2.8s long when someone passes by.
The PIR module has two potentiometers: one adjusts sensitivity, the other adjusts detection distance. To make the PIR module work better, you need to turn both of them counterclockwise to the end.
Wiring
Code
Note
Open the
7.4_passager_counter.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import time
pir_sensor = machine.Pin(16, machine.Pin.IN)
SEGCODE = [0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f]
sdi = machine.Pin(18,machine.Pin.OUT)
rclk = machine.Pin(19,machine.Pin.OUT)
srclk = machine.Pin(20,machine.Pin.OUT)
placePin = []
pin = [10,13,12,11]
for i in range(4):
placePin.append(None)
placePin[i] = machine.Pin(pin[i], machine.Pin.OUT)
count = 0
def pickDigit(digit):
for i in range(4):
placePin[i].value(1)
placePin[digit].value(0)
def clearDisplay():
hc595_shift(0x00)
def hc595_shift(dat):
rclk.low()
time.sleep_us(200)
for bit in range(7, -1, -1):
srclk.low()
time.sleep_us(200)
value = 1 & (dat >> bit)
sdi.value(value)
time.sleep_us(200)
srclk.high()
time.sleep_us(200)
time.sleep_us(200)
rclk.high()
def motion_detected(pin):
global count
count = count+1
pir_sensor.irq(trigger=machine.Pin.IRQ_RISING, handler=motion_detected)
while True:
#print(count)
pickDigit(0)
hc595_shift(SEGCODE[count%10])
pickDigit(1)
hc595_shift(SEGCODE[count%100//10])
pickDigit(2)
hc595_shift(SEGCODE[count%1000//100])
pickDigit(3)
hc595_shift(SEGCODE[count%10000//1000])
When the code is run, the number on the 4-digit 7-segment display will be added by one if someone passes in front of the PIR module.
7.5 GAME - 10 Second¶
To challenge your concentration, follow me next to make a game device. Make a magic wand by connecting the tilt switch with a stick. When you shake the wand, the 4-digit segment display will start counting, and when you shake it again, it will stop counting. In order to win, you must keep the displayed count at 10.00. You can play the game with your friends to see who is the time wizard.
Schematic
This circuit is based on 5.3 Time Counter with the addition of a tilt switch.
GP16 is high when the tilt switch is upright; low when tilted.
Wiring
Code
Note
Open the
7.5_game_10_second.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import time
SEGCODE = [0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f]
sdi = machine.Pin(18,machine.Pin.OUT)
rclk = machine.Pin(19,machine.Pin.OUT)
srclk = machine.Pin(20,machine.Pin.OUT)
placePin = []
pin = [10,13,12,11]
for i in range(4):
placePin.append(None)
placePin[i] = machine.Pin(pin[i], machine.Pin.OUT)
def pickDigit(digit):
for i in range(4):
placePin[i].value(1)
placePin[digit].value(0)
def clearDisplay():
hc595_shift(0x00)
def hc595_shift(dat):
rclk.low()
time.sleep_us(200)
for bit in range(7, -1, -1):
srclk.low()
time.sleep_us(200)
value = 1 & (dat >> bit)
sdi.value(value)
time.sleep_us(200)
srclk.high()
time.sleep_us(200)
time.sleep_us(200)
rclk.high()
#time.sleep_us(200)
def display(num):
pickDigit(0)
hc595_shift(SEGCODE[num%10])
pickDigit(1)
hc595_shift(SEGCODE[num%100//10])
pickDigit(2)
hc595_shift(SEGCODE[num%1000//100]+0x80)
pickDigit(3)
hc595_shift(SEGCODE[num%10000//1000])
tilt_switch = machine.Pin(16,machine.Pin.IN)
count_flag = False
def shake(pin):
global timeStart,count_flag
count_flag = not count_flag
if count_flag == True:
timeStart = time.ticks_ms()
tilt_switch.irq(trigger=machine.Pin.IRQ_RISING, handler=shake)
count = 0
while True:
if count_flag == True:
count = int((time.ticks_ms()-timeStart)/10)
display(count)
The 4-digit 7-segment display will begin counting when you shake the wand, and will stop counting when you shake it again. You win if you manage to keep the displayed count at 10.00. The game will continue after one more shake.
7.6 Traffic Light¶
Traffic Light is a signal device located at roadway intersections, crosswalks and other locations to control the flow of traffic.
Traffic signals are standardized by the Vienna Convention on Road Signs and Signals. Provides users with the right-of-way by alternating LEDs in three standard colors.
Red light: Traffic should stop if it sees a flashing red light, equivalent to a stop sign.
Yellow light: A warning signal is about to turn red. Yellow lights are interpreted differently in different countries (regions).
Green light: Allows traffic to move in the indicated direction.
In this project, we will use three colors of LEDs to implement traffic light changes and a 4-digit 7-segment display to show the time of each traffic state.
Schematic
This circuit is based on the 5.3 Time Counter with the addition of 3 LEDs.
The 3 red, yellow and green LEDs are connected to GP7~GP9 respectively.
Wiring
Code
Note
Open the
7.6_traffic_light.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import time
from machine import Timer
# [Green, Yellow, Red]
lightTime=[30, 5, 30]
# display
SEGCODE = [0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f]
sdi = machine.Pin(18,machine.Pin.OUT)
rclk = machine.Pin(19,machine.Pin.OUT)
srclk = machine.Pin(20,machine.Pin.OUT)
placePin = []
pin = [10,13,12,11]
for i in range(4):
placePin.append(None)
placePin[i] = machine.Pin(pin[i], machine.Pin.OUT)
def pickDigit(digit):
for i in range(4):
placePin[i].value(1)
placePin[digit].value(0)
def clearDisplay():
hc595_shift(0x00)
def hc595_shift(dat):
rclk.low()
time.sleep_us(200)
for bit in range(7, -1, -1):
srclk.low()
time.sleep_us(200)
value = 1 & (dat >> bit)
sdi.value(value)
time.sleep_us(200)
srclk.high()
time.sleep_us(200)
time.sleep_us(200)
rclk.high()
def display(num):
pickDigit(0)
hc595_shift(SEGCODE[num%10])
pickDigit(1)
hc595_shift(SEGCODE[num%100//10])
pickDigit(2)
hc595_shift(SEGCODE[num%1000//100])
pickDigit(3)
hc595_shift(SEGCODE[num%10000//1000])
# led
# 9Red, 8Yellow,7Green
pin = [7,8,9]
led=[]
for i in range(3):
led.append(None)
led[i] = machine.Pin(pin[i], machine.Pin.OUT)
def lightup(state):
for i in range(3):
led[i].value(0)
led[state].value(1)
# timer
counter = 0
color_state= 0
def time_count(ev):
global counter, color_state
counter -= 1
if counter <= 0:
color_state = (color_state+1) % 3
counter = lightTime[color_state]
tim = Timer(period=1000, mode=Timer.PERIODIC, callback=time_count)
while True:
display(counter)
lightup(color_state)
When the code runs, the green LED stays on for 30 seconds, the yellow LED stays on for 5 seconds, and the green LED stays on for 30 seconds.
7.7 Guess Number¶
Guessing Numbers is a fun party game where you and your friends input numbers (0-99). With each input of the number, the range will shrink until a player answers the riddle correctly. Then the player is defeated and punished.
As an example, if the lucky number is 51, which the players cannot see, and the player 1 inputs 50, the prompt changes to 50 - 99; if the player 2 inputs 70, the range changes to 50 - 70; if the player 3 inputs 51, the player is unlucky. In this case, numbers are inputted through the keypad, and outcomes are displayed on a LCD screen.
Schematic
This circuit is based on 4.2 4x4 Keypad with the addition of an I2C LCD1602 to display the pressed keys.
Wiring
To make the wiring easier, in the above diagram, the column row of the matrix keyboard and the 10K resistors are inserted into the holes where G10 ~ G13 are located at the same time.
Code
Note
Open the
7.7_game_guess_number.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
from lcd1602 import LCD
import machine
import time
import urandom
# keypad function
characters = [["1","2","3","A"],["4","5","6","B"],["7","8","9","C"],["*","0","#","D"]]
pin = [21,20,19,18]
row = []
for i in range(4):
row.append(None)
row[i] = machine.Pin(pin[i], machine.Pin.OUT)
pin = [13,12,11,10]
col = []
for i in range(4):
col.append(None)
col[i] = machine.Pin(pin[i], machine.Pin.IN)
def readKey():
key = []
for i in range(4):
row[i].high()
for j in range(4):
if(col[j].value() == 1):
key.append(characters[i][j])
row[i].low()
if key == [] :
return None
else:
return key
# init/reset number
# reset the result as False for lcd show
def init_new_value():
global pointValue,upper,count,lower
pointValue = int(urandom.uniform(0, 99))
print(pointValue)
upper = 99
lower = 0
count = 0
return False
# lcd show message
# If target, show game over.
# If not target, or not detected, show guess number.
def lcd_show(result):
lcd.clear()
if result == True:
string ="GAME OVER!\n"
string +="Point is "+ str(pointValue)
else :
string ="Enter number: " + str(count) +"\n"
string += str(lower)+ " < Point < " + str(upper)
lcd.message(string)
return
# detect number & reflesh show message
# if not target, reflesh number (upper or lower) and return False
# if target, return True
def number_processing():
global upper,count,lower
if count > pointValue:
if count < upper:
upper = count
elif count < pointValue:
if count > lower:
lower = count
elif count == pointValue:
return True
count = 0
return False
## start
lcd = LCD()
string = "Welcome!\n"
string = "Press A to Start!"
lcd.message(string)
result=init_new_value()
# read key & display
last_key = None
while True:
current_key = readKey()
if current_key == last_key:
continue
last_key = current_key
if current_key != None:
# print(current_key)
if current_key ==["A"]: # reset number
result=init_new_value()
elif current_key==["D"]: # check
result=number_processing()
elif current_key[0] in list(["1","2","3","4","5","6","7","8","9","0"]) and count < 10: #check validity & limit digits
count = count * 10 + int(current_key[0])
lcd_show(result) # show
time.sleep(0.1)
After the code runs, press
A
to start the game. A random numberpoint
is produced but not displayed on the LCD, and what you need to do is to guess it.The number you have typed appears at the end of the first line till the final calculation is finished. (Press
D
to start the comparation.)The number range of
point
is displayed on the second line. And you must type the number within the range.When you type a number, the range narrows; if you got the lucky number luckily or unluckily, there will appear
GAME OVER!
.
Note
If the code and wiring are fine, but the LCD still does not display content, you can turn the potentiometer on the back to increase the contrast.
7.8 RFID Music Player¶
Through our previous project, 6.5 Radio Frequency Identification, we learned that the MFRC522 module allows us to write up to 48 letters of information to the card (or key), including both the key and identity information, as well as the music score.
As an example, if you write EEFGGFEDCCDEEDD EEFGGFEDCCDEDCC
, the buzzer will play the music when the card (or key) is read again. It can also be equipped with an WS2812 to display amazing effects.
You can find more sheet music on the Internet, or even write your own music, put them into the card (or key), and share them with your friends!
Schematic
Wiring
Code
Open the
6.5_rfid_write.py
file under the path ofeuler-kit/micropython
, then click “Run Current Script” or simply press F5 to run it.After running, type
EEFGGFEDCCDEEDD EEFGGFEDCCDEDCC
in the Shell and then put the card (or key) close to the MFRC522 module, this way an Ode an Joy score is stored in.Open the
7.8_rfid_music_player.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.from mfrc522 import SimpleMFRC522 import machine import time from ws2812 import WS2812 import urandom # ws2812 ws = WS2812(machine.Pin(16),8) # mfrc522 reader = SimpleMFRC522(spi_id=0,sck=2,miso=4,mosi=3,cs=5,rst=0) # buzzer NOTE_C4 = 262 NOTE_D4 = 294 NOTE_E4 = 330 NOTE_F4 = 349 NOTE_G4 = 392 NOTE_A4 = 440 NOTE_B4 = 494 NOTE_C5 = 523 buzzer = machine.PWM(machine.Pin(15)) note=[NOTE_C4,NOTE_D4,NOTE_E4,NOTE_F4,NOTE_G4,NOTE_A4,NOTE_B4,NOTE_C5] def tone(pin,frequency,duration): pin.freq(frequency) pin.duty_u16(30000) time.sleep_ms(duration) pin.duty_u16(0) # lightup def lumi(index): for i in range(8): ws[i] = 0x000000 ws[index] = int(urandom.uniform(0, 0xFFFFFF)) ws.write() # encode text to index words=["C","D","E","F","G","A","B","N"] def take_text(text): string=text.replace(' ','').upper() while len(string)>0: index=words.index(string[0]) tone(buzzer,note[index],250) lumi(index) new_str="" for i in range(0, len(string)): if i != 0: new_str = new_str + string[i] string=new_str # read card def read(): print("Reading...Please place the card...") id, text = reader.read() print("ID: %s\nText: %s" % (id,text)) take_text(text) read()
By putting the card (or key) close to the MFRC522 module again, the buzzer will play the music stored on the card (or key), and the RGB strip will light up in a random color.
7.9 Fruit Piano¶
Electrical conductivity is found in many metal objects, as well as in the human body and fruits. This property can be used to create a fun little project: a fruit piano. In other words, we turn fruits into keyboards that can play music just by touching them.
Schematic
To turn the fruit into a piano key, you still need to connect the electrodes on the MPR121 to the fruit (e.g. into the banana handle).
In the beginning, MPR121 will initialize and each electrode will get a value based on the current charge; when a conductor (such as a human body) touches an electrode, the charge will shift and rebalance. As a result, the electrode’s value is different from its initial value, telling the main control board that it has been touched. During this process, ensure that the wiring of each electrode is stable so that its charge is balanced when initializing.
Wiring
Code
Note
Open the
7.9_fruit_piano.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
Here you need to use the library called
mpr121.py
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Upload the Libraries to Pico.
from mpr121 import MPR121
from machine import Pin, I2C
import time
import urandom
# mpr121
i2c = I2C(1, sda=Pin(6), scl=Pin(7))
mpr = MPR121(i2c)
# buzzer
NOTE_A3 = 220
NOTE_B3 = 247
NOTE_C4 = 262
NOTE_D4 = 294
NOTE_E4 = 330
NOTE_F4 = 349
NOTE_G4 = 392
NOTE_A4 = 440
NOTE_B4 = 494
NOTE_C5 = 523
NOTE_D5 = 587
NOTE_E5 = 659
buzzer = machine.PWM(machine.Pin(15))
note = [NOTE_A3,NOTE_B3,NOTE_C4,NOTE_D4,NOTE_E4,NOTE_F4,NOTE_G4,NOTE_A4,NOTE_B4,NOTE_C5,NOTE_D5,NOTE_E5]
def tone(pin,frequency):
pin.freq(frequency)
pin.duty_u16(30000)
def noTone(pin):
pin.duty_u16(0)
# rgb led
red = machine.PWM(machine.Pin(13))
green = machine.PWM(machine.Pin(12))
blue = machine.PWM(machine.Pin(11))
red.freq(1000)
green.freq(1000)
blue.freq(1000)
def interval_mapping(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
def lightup():
red.duty_u16(int(urandom.uniform(0, 65535)))
green.duty_u16(int(urandom.uniform(0, 65535)))
blue.duty_u16(int(urandom.uniform(0, 65535)))
def dark():
red.duty_u16(0)
green.duty_u16(0)
blue.duty_u16(0)
# main project
lastState=mpr.get_all_states()
touchMills=time.ticks_ms()
beat=500
while True:
currentState=mpr.get_all_states()
if currentState != lastState:
for i in range(12):
if i in list(currentState) and not i in list(lastState):
tone(buzzer,note[i])
lightup()
touchMills=time.ticks_ms()
if time.ticks_diff(time.ticks_ms(),touchMills)>=beat or len(currentState) == 0:
noTone(buzzer)
dark()
lastState = currentState
Please do not touch the fruit before the program runs to avoid getting a non-correct reference during initialization. After the program runs, touch the fruit gently, the buzzer will sound the corresponding tone and the RGB light will flash once randomly.
7.10 Reversing Aid¶
This project uses an LED, a buzzer and an ultrasonic module to create a reversing assist system. We can put it on a remote control car to simulate the the actual process of reversing a car into a garage.
Schematic
Wiring
Code
Note
Open the
7.10_reversing_aid.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
import machine
import time
import _thread
buzzer = machine.Pin(15, machine.Pin.OUT)
led = machine.Pin(14, machine.Pin.OUT)
TRIG = machine.Pin(17,machine.Pin.OUT)
ECHO = machine.Pin(16,machine.Pin.IN)
dis = 100
def distance():
timeout=10000*5/340
TRIG.low()
time.sleep_us(2)
TRIG.high()
time.sleep_us(10)
TRIG.low()
timeout_start = time.ticks_ms() # For timeout, re-read distance
while not ECHO.value():
waiting_time = time.ticks_ms()
if waiting_time - timeout_start > timeout:
return -1
time1 = time.ticks_us()
while ECHO.value():
waiting_time = time.ticks_ms()
if waiting_time - timeout_start > timeout:
return -1
time2 = time.ticks_us()
during = time.ticks_diff(time2 ,time1)
return during * 340 / 2 / 10000
def ultrasonic_thread():
global dis
while True:
dis = distance()
_thread.start_new_thread(ultrasonic_thread, ())
def beep():
buzzer.value(1)
led.value(1)
time.sleep(0.1)
buzzer.value(0)
led.value(0)
time.sleep(0.1)
intervals = 10000000
previousMills=time.ticks_ms()
time.sleep(1)
while True:
if dis<0:
pass
elif dis <= 10:
intervals = 300
elif dis <= 20:
intervals =500
elif dis <=50:
intervals =1000
else:
intervals = 2000
if dis!=-1:
print ('Distance: %.2f' % dis)
time.sleep_ms(100)
currentMills=time.ticks_ms()
if time.ticks_diff(currentMills,previousMills)>=intervals:
beep()
previousMills=currentMills
As soon as the program runs, the ultrasonic sensor will continuously read the distance to the obstacle in front of you, and you will be able to see the exact distance value on the shell.
The LED and buzzer will change the frequency of blinking and beeping depending on the distance value, thus indicating the approach of the obstacle.
The 6.1 Measuring Distance article mentioned that when the ultrasonic sensor works, the program will be paused.
To avoid interfering with the LED or buzzer timing, we created a separate thread for ranging in this example.
7.11 Somatosensory Controller¶
If you watch a lot of robot movies, you’ve probably seen images like this. The protagonist turned his wrist and the giant robot followed; the protagonist shakes his fist, and the robot follows, which is very cool.
The use of this technology is already common in universities and research institutes, and the arrival of 5G will greatly expand its application areas. “Surgical robot da Vinci” remote surgery medical is a typical example.
A robotic system of this type is typically composed of two modules: a human motion capture module and a robotic arm actuation module (some application scenarios also include a data communication module).
The MPU6050 is used here to implement human motion capture (by mounting it on a glove) and the servo is used to represent robotic arm motion.
Schematic
The MPU6050 calculates the attitude angle based on the acceleration values in each direction.
The program will control the servo to make the corresponding deflection angle as the attitude angle changes.
Wiring
Code
Note
Open the
7.11_somatosensory_controller.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
Here you need to use the
imu.py
andvector3d.py
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Upload the Libraries to Pico.
from imu import MPU6050
from machine import I2C, Pin
import time
import math
# mpu6050
i2c = I2C(1, sda=Pin(6), scl=Pin(7), freq=400000)
mpu = MPU6050(i2c)
# servo
servo = machine.PWM(machine.Pin(16))
servo.freq(50)
def interval_mapping(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
# get rotary angle
def dist(a,b):
return math.sqrt((a*a)+(b*b))
def get_y_rotation(x,y,z):
radians = math.atan2(x, dist(y,z))
return -math.degrees(radians)
def get_x_rotation(x,y,z):
radians = math.atan2(y, dist(x,z))
return math.degrees(radians)
# servo work
def servo_write(pin,angle):
pulse_width=interval_mapping(angle, 0, 180, 0.5,2.5)
duty=int(interval_mapping(pulse_width, 0, 20, 0,65535))
pin.duty_u16(duty)
times=25
while True:
total=0
for i in range(times):
angle=get_y_rotation(mpu.accel.x, mpu.accel.y, mpu.accel.z) #get rotation value
total+=angle
average_angle=int(total/times) # make the value smooth
servo_write(servo,interval_mapping(average_angle,-90,90,0,180))
As soon as the program runs, the servo will turn left and right as you tilt the MPU6050 (or turn your wrist if it is mounted on a glove).
7.12 Digital Bubble Level¶
A bubble Level, is an instrument designed to indicate whether a surface is horizontal (level) or vertical (plumb). There are different types of spirit levels used by carpenters, stonemasons, bricklayers, other building trades workers, surveyors, millwrights, and other metalworkers, as well as in some photographic and videographic work.
Here we make a digital bubble level using MPU6050 and 8x8 LED matrix. When you deflect the MPU6050, the bubble on the LED matrix will also be deflected.
Schematic
The MPU6050 takes the acceleration values in each direction and calculates the attitude angle.
As a result, the program draws a 2x2 dot on the dot matrix based on data from the two 74HC595 chips.
As the attitude angle changes, the program sends different data to the 74HC595 chips, and the position of the dot changes, creating a bubble effect.
Wiring
Code
Note
Open the
7.12_digital_bubble_level.py
file under the path ofeuler-kit/micropython
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
Here you need to use the
imu.py
andvector3d.py
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Upload the Libraries to Pico.
import machine
from machine import I2C, Pin
import time
import math
from imu import MPU6050
### mpu6050
i2c = I2C(1, sda=Pin(6), scl=Pin(7), freq=400000)
mpu = MPU6050(i2c)
# get rotary angle
def dist(a,b):
return math.sqrt((a*a)+(b*b))
def get_y_rotation(x,y,z):
radians = math.atan2(x, dist(y,z))
return -math.degrees(radians)
def get_x_rotation(x,y,z):
radians = math.atan2(y, dist(x,z))
return math.degrees(radians)
def get_angle():
y_angle=get_y_rotation(mpu.accel.x, mpu.accel.y, mpu.accel.z)
x_angle=get_x_rotation(mpu.accel.x, mpu.accel.y, mpu.accel.z)
return x_angle,y_angle
### led matrix display
sdi = machine.Pin(18,machine.Pin.OUT)
rclk = machine.Pin(19,machine.Pin.OUT)
srclk = machine.Pin(20,machine.Pin.OUT)
def hc595_in(dat):
for bit in range(7,-1, -1):
srclk.low()
time.sleep_us(30)
sdi.value(1 & (dat >> bit))
time.sleep_us(30)
srclk.high()
def hc595_out():
rclk.high()
time.sleep_us(200)
rclk.low()
def display(glyph):
for i in range(0,8):
hc595_in(glyph[i])
hc595_in(0x80>>i)
hc595_out()
# data transformation
def matrix_2_glyph(matrix):
glyph= [0 for i in range(8)] # glyph code for display()
for i in range(8):
for j in range(8):
glyph[i]+=matrix[i][j]<<j
return glyph
def clamp_number(val, min, max):
return min if val < min else max if val > max else val
def interval_mapping(x, in_min, in_max, out_min, out_max):
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
# Calculate the position of the bubble
sensitivity=4 # The higher the number, the more sensitive
matrix_range=7 # The size of the matrix is 8, so the coordinate range is 0~7
point_range=matrix_range-1 # The x, y value of the bubble's marker point (upper left point) should be between 0-6
def bubble_position():
x,y=get_angle()
x=int(clamp_number(interval_mapping(x,-90,90,0-sensitivity,point_range+sensitivity),0,point_range))
y=int(clamp_number(interval_mapping(y,-90,90,point_range+sensitivity,0-sensitivity),0,point_range))
return [x,y]
# Drop the bubble into empty matrix
def drop_bubble(matrix,bubble):
matrix[bubble[0]][bubble[1]]=0
matrix[bubble[0]+1][bubble[1]]=0
matrix[bubble[0]][bubble[1]+1]=0
matrix[bubble[0]+1][bubble[1]+1]=0
return matrix
while True:
matrix= [[1 for i in range(8)] for j in range(8)] # empty matrix
bubble=bubble_position() # bubble coordinate
matrix=drop_bubble(matrix,bubble) # drop the bubble into empty matrix
display(matrix_2_glyph(matrix)) # show matrix
Once you have run the program, place the breadboard on a level surface. A dot will appear in the center of the LED matrix (if it isn’t in the center, the MPU6050 may not be level). When you deflect the breadboard, the dot will move in the direction you deflected.
Play Pico with APP¶
This section will guide you through building a remote project using the Sunfounder Controller APP, which means you can use your phone/tablet to control your circuit.
This play is based on micropython and it is recommended to do it after completing the micropython tutorial.
The ESP8266 module provides wifi functionality for the pico, and they communicate with each other via the uart protocol.
Here are some examples that teach you how to implement communication between Raspberry Pi Pico and SunFounder Controller, as well as some interesting projects.
1.1 First-time Use the APP¶
This section will guide you to complete the communication between Sunfounder Controller APP and Pico, you can read the value of the potentiometer on the APP, and you can also control the LED on and off through the APP.
How to do?
Build a circuit.
Upload the library.
Reference 1.4 Download and Upload the Code to download the code and upload the library. But in this project, you need to upload
ws.py
from theeuler-kit/esp8266/
path to the Raspberry Pi Pico.Run
1.1_ws_test.py
file.Double click the
1.1_ws_test.py
file under theeuler-kit/esp8266/
path, then click run current script button or just press F5 to run it.After running the program, you will see the IP address and the
start
prompt in the Shell.Warning
If the wiring is OK, but still no successful connection prompt after several runs, the firmware of ESP8266 module may need to be re-burned, please refer to How to re-burn the firmware for ESP8266 module? for details.
Connect to ESP8266.
Find my_esp8266 on the WLAN of the mobile phone (tablet), enter the password (12345678) and connect to it.
The default used in
1.1_ws_test.py
is AP mode. So after you connect, there will be a prompt telling you that there is no Internet access on this WLAN network, please choose to continue connecting.Install Sunfounder Controller.
Search for Sunfounder Controller in APP Store (or Google Play) and download it.
Connect to SunFounder Controller.
Now open SunFounder Controller and click Disconnected in the upper right corner.
Because it is AP mode, it will connect automatically here.
Note
If the connection has not been successful, please make sure the
1.1_ws_test.py
file is running properly and connect your device’s Wi-Fi tomy_esp8266
.After the connection is successful, the Thonny script will show the IP of the newly connected device:
>>> %Run -c $EDITOR_CONTENT Connecting WebServer started on ws://192.168.4.1:8765 start Connected from 192.168.4.3
Create a controller.
Click the + button in the middle of the page, then the Create controller page will pop up. Enter the name of the controller, select Blank -> Dual Stick and click Confirm.
You will be able to see boxes (some are rectangles, some are squares), we need to adjust them to apply to
1.1_ws_test.py
.Click on area G and select the Number widget.
Click on area H and sclect the Slider widget.
Save and Run the controller.
Click the Save/Edit button and the controller will be saved. At the same time it enters the working state, and the empty widget box is hidden.
Then click the Run/Stop button to get this controller running!
The value of the potentiometer will displayed on the G area.
If you slide the slider of the H box, the brightness of the LED will change.
Note
If it does not work as expected, or if it shows disconnected, make sure that the
1.1_ws_test.py
file is running properly and that your mobile device’s Wi-Fi is connected to themy_esp8266
.
FAQ
Error during running code.
When the following error occurs, please check if the ESP8266 connection is stable.
Traceback (most recent call last): File "<stdin>", line 43, in <module> File "<stdin>", line 41, in main File "ws.py", line 115, in loop File "ws.py", line 46, in read UnicodeError:
Then hit Stop to stop running the code, and then run the code again.
Each time you re-run the code, you need to reconnect your device (phone/tablet) WIFI to
my_esp8266
, and then go to SunFounder Controller and click Disconnnected to reconnect.If the connection has not been successful, or suddenly disconnect.please make sure the
1.1_ws_test.py
file is running properly and your mobile device is connected tomy_esp8266
.
1.2 How ws_test.py
Works?¶
The communication between Pico and Sunfounder Controller is based on the websocket protocol
.
The specific workflow of APP Control gameplay is as follows:
from ws import WS_Server
import json
import time
NAME = 'my_esp8266'
## Client Mode
# WIFI_MODE = "sta"
# SSID = "YOUR SSID HERE"
# PASSWORD = "YOUR PASSWORD HERE"
## AP Mode
WIFI_MODE = "ap"
SSID = ""
PASSWORD = "12345678"
ws = WS_Server(name=NAME, mode=WIFI_MODE, ssid=SSID, password=PASSWORD)
ws.start()
led = machine.PWM(machine.Pin(15))
led.freq(1000)
potentiometer = machine.ADC(28)
def on_receive(data):
print(data)
# output
value = data['H']
led.duty_u16(value*655)
# input
value=potentiometer.read_u16()
ws.send_dict['G'] = value
ws.on_receive = on_receive
def main():
print("start")
while True:
ws.loop()
main()
This code constitutes the basic framework of APP control. Here, you need to pay attention to the following two parts:
Setup websocket
There are two connection mode between Sunfounder Controller and Pico: One is AP mode, the other is STA mode.
AP Mode: You need to connect Sunfounder Contorller to the hotspot released by pico.
STA Mode: You need to connect Sunfounder Controller and pico to the same LAN.
The default connection mode is AP Mode: The Pico releases the hotspot (the Wifi name is
NAME
in the code, here ismy_esp8266
), the mobile phone (tablet) is connected to this WLAN. This mode allows you to remotely control pico in any situation, but will make your phone (tablet) temporarily unable to connect to the Internet.NAME = 'my_esp8266' ## Client Mode # WIFI_MODE = "sta" # SSID = "YOUR SSID HERE" # PASSWORD = "YOUR PASSWORD HERE" ## AP Mode WIFI_MODE = "ap" SSID = "" PASSWORD = "12345678" ws = WS_Server(name=NAME, mode=WIFI_MODE, ssid=SSID, password=PASSWORD) ws.start()
You can also use STA mode: Let the pico connects to your home WLAN, and your mobile phone (tablet) should also be connected to the same WLAN.
This mode is opposite to the AP mode and will not affect the normal use of the mobile phone (tablet), but will limit your pico from leaving the WLAN radiation range.
The way to start this mode is to comment out the three lines under
## AP Mode
, uncomment the three lines under## Client Mode
, and change theSSID
andPASSWORD
to your home WIFI at the same time.NAME = 'my_esp8266' ## Client Mode WIFI_MODE = "sta" SSID = "YOUR SSID HERE" PASSWORD = "YOUR PASSWORD HERE" ## AP Mode # WIFI_MODE = "ap" # SSID = "" # PASSWORD = "12345678" ws = WS_Server(name=NAME, mode=WIFI_MODE, ssid=SSID, password=PASSWORD) ws.start()
After completing the connection mode settings, Websocket will set up and start the server.
ws = WS_Server(name=NAME, mode=WIFI_MODE, ssid=SSID, password=PASSWORD) ws.start()
Responding
The specific operation code of Pico and Sunfounder Controller is written on the
on_receive()
function. Usually, we need to write the codes for APP to control Pico on the front and the codes for APP to show Pico sensor data on the back.def on_receive(data): print(data) # output value = data['H'] led.duty_u16(value*655) # input value=potentiometer.read_u16() ws.send_dict['G'] = value ws.on_receive = on_receive
Finally,
on_receive()
will be assigned tows.on_receive
and then called byws.loop
.
1.3 What Data is Transferred between APP & Pico?¶
From APP to Pico
Let’s take a look at what kind of data Pico will get from the APP. Print
data
directly inon_receive
.Note
Open the
1.3_ws_test_print.py
file under the path ofeuler-kit\esp8266
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
- For detailed tutorials, please refer to Open and Run Code Directly.
Each time you rerun the code, you need to connect your device’s Wi-Fi to
my_esp8266
, then turn on SunFounder Controller and reconnect.
from ws import WS_Server import json import time NAME = 'my_esp8266' ## Client Mode # WIFI_MODE = "sta" # SSID = "YOUR SSID HERE" # PASSWORD = "YOUR PASSWORD HERE" ## AP Mode WIFI_MODE = "ap" SSID = "" PASSWORD = "12345678" ws = WS_Server(name=NAME, mode=WIFI_MODE, ssid=SSID, password=PASSWORD) ws.start() def on_receive(data): print(data) # output # input ws.on_receive = on_receive def main(): print("start") while True: ws.loop() main()
You will see the data for each area in the Shell. When we drag the Slider in the H area, the value of the H area will change. This is because we only add one control widget (H area). The widget in the G area is not used for control but only for show.
We can also add other control widgets, and use the same method to view the values sent by these widgets to Pico.
You can get the value of the corresponding widget by just using the label. As shown below, print the value of the H widget:
Note
Open the
1.3_ws_test_print_h.py
file under the path ofeuler-kit\esp8266
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
- For detailed tutorials, please refer to Open and Run Code Directly.
Each time you rerun the code, you need to connect your device’s Wi-Fi to
my_esp8266
, then turn on SunFounder Controller and reconnect.
from ws import WS_Server import json import time NAME = 'my_esp8266' ## Client Mode # WIFI_MODE = "sta" # SSID = "YOUR SSID HERE" # PASSWORD = "YOUR PASSWORD HERE" ## AP Mode WIFI_MODE = "ap" SSID = "" PASSWORD = "12345678" ws = WS_Server(name=NAME, mode=WIFI_MODE, ssid=SSID, password=PASSWORD) ws.start() def on_receive(data): print(data['H']) # output # input ws.on_receive = on_receive def main(): print("start") while True: ws.loop() main()
>>> %Run -c $EDITOR_CONTENT Connecting WebServer started on ws://192.168.4.1:8765 start Connected from 192.168.4.3 34 50 87
From Pico to APP
Use the
send_dict
function to show the value in G Widget.Note
Open the
1.3_ws_test_input.py
file under the path ofeuler-kit\esp8266
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
- For detailed tutorials, please refer to Open and Run Code Directly.
Each time you rerun the code, you need to connect your device’s Wi-Fi to
my_esp8266
, then turn on SunFounder Controller and reconnect.
from ws import WS_Server import json import time NAME = 'my_esp8266' ## Client Mode # WIFI_MODE = "sta" # SSID = "YOUR SSID HERE" # PASSWORD = "YOUR PASSWORD HERE" ## AP Mode WIFI_MODE = "ap" SSID = "" PASSWORD = "12345678" ws = WS_Server(name=NAME, mode=WIFI_MODE, ssid=SSID, password=PASSWORD) ws.start() led = machine.PWM(machine.Pin(15)) led.freq(1000) potentiometer = machine.ADC(28) def on_receive(data): # output # input value=potentiometer.read_u16() ws.send_dict['G'] = value # the value show on the G area ws.on_receive = on_receive def main(): print("start") while True: ws.loop() main()
After running the code, turn the potentiometer and you will be able to see the value of the G widget change.
Widget List
Control Widgets
Show Widgets
1.4 APP Display Widgets¶
Build the circuit.
Create a new controller and add the following widgets.
Run
1.4_ws_display.py
.Note
Open the
1.4_ws_display.py
file under the path ofeuler-kit/esp8266
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
Each time you rerun the code, you need to connect your device’s Wi-Fi to
my_esp8266
, then turn on SunFounder Controller and reconnect.After clicking the Run/Stop button, you can try to press a button or rotate a potentiometer and see how the values of the widgets in area B and area C on the app change.
Widget List
1.5 APP Actuator Widgets¶
Create a new controller and add the following widgets.
Run
1.5_ws_actuator.py
.Note
Open the
1.5_ws_actuator.py
file under the path ofeuler-kit/esp8266
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
Each time you rerun the code, you need to connect your device’s Wi-Fi to
my_esp8266
, then turn on SunFounder Controller and reconnect.After clicking the Run/Stop button, you can try to toggle these widgets and you can see the corresponding value changes in the Thonny shell.
Widget List
1.6 Electronic Piano¶
In this project, we use the button widget on the SunFounder Controller as the piano keys and connect a passive buzzer to the Pico to simulate an electronic piano.
Build the circuit.
Create a new controller, note that Single Stick is selected.
Add a Button widget to the G area, and click the Set button in the upper right corner to change the name.
Add a Slider widget to the H area and set its name, maximum, minimum and initial value.
Add a Button widget in NOPSMQR area and change their names to note C ~ note B respectively.
After saving, the effect of the remote control is shown below.
Run
1.6_ws_piano.py
.Note
Open the
1.6_ws_piano.py
file under the path ofeuler-kit/esp8266
or copy this code into Thonny, then click “Run Current Script” or simply press F5 to run it.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
Each time you rerun the code, you need to connect your device’s Wi-Fi to
my_esp8266
, then turn on SunFounder Controller and reconnect.Now, click the Run/Stop button in the upper right corner.
If you press the Button widget in G area, the buzzer will play a melody.
You can use the Slider widget in the H area to adjust the speed of this melody.
If you press the button in NOPSMQR area separately, the passive buzzer will sound different notes, and the LED will light up and fade out when you press each button.
How it works?
led = machine.PWM(machine.Pin(15))
led.freq(1000)
buzzer = machine.PWM(machine.Pin(14))
Define the connection pins for the LED and buzzer, and the frequency of the LED.
#note
note = [262,294,330,349,392,440,494,523]
#melody
NOTE_C4 = 262
NOTE_G3 = 196
NOTE_A3 = 220
NOTE_B3 = 247
melody =[NOTE_C4,NOTE_G3,NOTE_G3,NOTE_A3,NOTE_G3,NOTE_B3,NOTE_C4]
Define the frequency of CDEFGAB and a melody here.
def light_led():
global brightness
brightness = 65535
led.duty_u16(brightness)
The light_led()
function is used to let the LED display the maximum brightness(65535).
def tone(pin,frequency):
pin.freq(frequency)
pin.duty_u16(30000)
light_led()
The tone()
function can generate a square wave of the specified frequency (and 50% duty cycle) on a pin, also let the LED light up.
def noTone(pin):
pin.duty_u16(0)
The notone()
function is used to stop the generation of a square wave triggered by tone()
.
def music_box(duration):
for n in melody:
tone(buzzer,n)
time.sleep_ms(duration)
noTone(buzzer)
time.sleep_ms(duration)
noTone(buzzer)
The music_box()
function is to make the passive buzzer play the melody in the melody[]
array with a specific beat.
def on_receive(data):
global bpm_flag,gap,brightness
bpm = data['H']
bpm_flag = data['G']
gap = 60 * 1000 / bpm
# fade led
if brightness >= 6000:
brightness = brightness-30000
led.duty_u16(brightness)
# music box
if data['G'] == True:
music_box(int(gap/4))
return
# piano
if data['N'] == True:
tone(buzzer,note[0])
elif data['O'] == True:
tone(buzzer,note[1])
elif data['P'] == True:
tone(buzzer,note[2])
elif data['S'] == True:
tone(buzzer,note[3])
elif data['M'] == True:
tone(buzzer,note[4])
elif data['Q'] == True:
tone(buzzer,note[5])
elif data['R'] == True:
tone(buzzer,note[6])
else:
noTone(buzzer)
ws.on_receive = on_receive
Here, the on_receive()
function can be divided into 3 parts.
fade led: Make the LED light up and then turn off after an intermediate brightness.
music box: When the button widget in the G area is pressed, the buzzer plays the melody in the
melody[]
array in 1/4 beats.piano: When the buttons in NOPSMQR area are pressed separately, the passive buzzer will play different notes.
1.7 Plant Monitor¶
This is a smart watering system, it will detect the current temperature and humidity of the environment and show them on the SunFounder Controller. When you press the pump button on the APP, it will replenish water for the plants. When it reaches a certain position (detected by water level sensor), it will stop pumping automatically.
Build the circuit.
Create a new controller, add the following widgets and change their names.
Run
1.7_ws_plant_monitor.py
.Note
Open the
1.7_ws_plant_monitor.py
file under the path ofeuler-kit/esp8266
.Don’t forget to click on the “MicroPython (Raspberry Pi Pico)” interpreter in the bottom right corner.
For detailed tutorials, please refer to Open and Run Code Directly.
Each time you rerun the code, you need to connect your device’s Wi-Fi to
my_esp8266
, then turn on SunFounder Controller and reconnect.After clicking the Run/Stop button in the upper right corner. You will see the current temperature, humidity and water level value on the SunFounder controller. When you press the pump button on the APP, it will replenish water for the plants.
Note
If the motor is still spinning after you click the Stop button, you need to reset the RUN pin on the Pico with a wire to GND at this time, and then unplug this wire to run the code again.
This is because the motor is operating with too much current, which may cause the Pico to disconnect from the computer.
How it works?
def on_receive(data):
# input
# show dht11 message
try:
sensor.measure()
value = sensor.temperature
ws.send_dict['G'] = value
value = sensor.humidity
ws.send_dict['H'] = value
except:
pass
# show water level sensor message
value = water_sensor.read_u16()
ws.send_dict['P'] = value
# output
# start pumping
if 'M' in data.keys() and data['M'] is True and value<15000:
motor1A.high()
motor2A.low()
# stop pumping
if value>=15000 or 'M' in data.keys() and data['M'] is False:
motor1A.low()
motor2A.low()
ws.on_receive = on_receive
Here, the on_receive()
function can be divided into 3 parts.
start pumping: When the button in area G is pressed, let the pump start working.
show dht11 message: Show the temperature and humidity on the widgets in area C and area B respectively.
show water level sensor message: The water level message is displayed on the widget in area P. When the water level message is greater than 10000, let the pump stop working.
Learn More
If you want Pico to run this 1.7_ws_plant_monitor.py
file automatically after booting, refer to the following steps.
Open the
1.7_ws_plant_monitor.py
file under the path ofeuler-kit/esp8266
, then click File -> Save as.Select Raspberry Pi Pico.
Set it name to
main.py
, this way the Raspberry Pi Pico will run this code automatically.
For Arduino User¶
This chapter includes installing Arduino IDE, uploading code to Raspberry Pi with Arduino IDE and a dozen interesting and practical projects to help you learn Arduino code quickly.
We recommend that you read the chapters in order.
1. Get Started
1.1 Install and Introdudce the Arduino¶
Arduino is an open source platform with simple software and hardware. You can pick it up in short time even if you are a beginner. It provides an integrated development environment (IDE) for code compiling, compatible with multiple control boards. So you can just download the Arduino IDE, upload the sketches (i.e. the code files) to the board, and then you can see relative experimental phenomena.
For more information, refer to Arduino Website.
Install Arduino IDE
Go to Arduino Software Page to download the Arduino IDE accordingly to your operating system,then follow the instructions to install it.
Click here to get step-by-step instructions accordingly to your operating system.
Introduction the Arduino Software (IDE)
Double-click the Arduino icon (arduino.exe) created by the installation process. Then the Arduino IDE will appear. Let’s check details of the software.
Verify: Compile your code. Any syntax problem will be prompted with errors.
Upload: Upload the code to your board. When you click the button, the RX and TX LEDs on the board will flicker fast and won’t stop until the upload is done.
New: Create a new code editing window.
Open: Open an .ino sketch.
Save: Save the sketch.
Serial Monitor: Click the button and a window will appear. It receives the data sent from your control board. It is very useful for debugging.
File: Click the menu and a drop-down list will appear, including file creating, opening, saving, closing, some parameter configuring, etc.
Edit: Click the menu. On the drop-down list, there are some editing operations like Cut, Copy, Paste, Find, and so on, with their corresponding shortcuts.
Sketch: Includes operations like Verify, Upload, Add files, etc. More important function is Include Library – where you can add libraries.
Tool: Includes some tools – the most frequently used Board (the board you use) and Port (the port your board is at). Every time you want to upload the code, you need to select or check them.
Help: If you’re a beginner, you may check the options under the menu and get the help you need, including operations in IDE, introduction information, troubleshooting, code explanation, etc.
In this message area, no matter when you compile or upload, the summary message will always appear.
Detailed messages during compile and upload. For example, the file used lies in which path, the details of error prompts.
Board and Port: Here you can preview the board and port selected for code upload. You can select them again by Tools -> Board / Port if any is incorrect.
The editing area of the IDE. You can write code here.
1.2 Setup the Raspberry Pi Pico¶
Open the Boards Manager by clicking Tools -> Board -> Boards Manager.
Search for Pico and click install button.
Once the installation is complete, you can select the board as Raspberry Pi Pico.
Now open a example - blink.
Click on the upload icon to run the code
When the compiling message shown in the figure below appears, press BOOTSEL immediately and connect Pico to the computer with a Micro USB cable.
Note
This step is very important and only necessary for the first use on the Arduino IDE, otherwise your code will upload unsuccessfully.
After the upload is successful this time, Pico will be recognized by the computer as COMxx (Raspberry Pi Pico).
You only need to plug it into the computer the next time you use it.
After the Done Uploading appear, you will see the LED on the Pico blinking.
1.3 Download and Add Libraries¶
Download the Code
Download the relevant code from the link below.
Or check out the code at Euler Kit - GitHub
Add libraries¶
A library, gathering some function definitions and header files, usually contains two files: .h (header file, including function statement, Macro definition, constructor definition, etc.) and .cpp (execution file, with function implementation, variable definition, and so on). When you need to use a function in some library, you just need to add a header file (e.g. #include <dht.h>), and then call that function. This can make your code more concise. If you don’t want to use the library, you can also write that function definition directly. Though as a result, the code will be long and inconvenient to read.
Some libraries are already built in the Arduino IDE, when some others may need to be added. So now let’s see how to add one. There are 2 methods for that.
Method 1
Directly import the library in Arduino IDE (take Dht as an example below). The advantage of this method is easy to understand and operate, but on the other hand, only one library can be imported at a time. So it is inconvenient when you need to add quite a lot of libraries.
Step 1: Select Sketch -> Include Library -> Add ZIP Library.
Step 2: Find Library folder , They are under the path arduino\libraries
. Then click Open.
Step 3: When you see Library added to your libraries. Check “Include library” menu, it means you have added the library successfully. Please use the same method to add other libraries then.
Method 2
Directly copy the library to libraries/Arduino
path. This method can
copy all libraries and add them at a time, but the drawback is that it
is difficult to find libraries/Arduino
.
Step 1: Click File -> Preferences and on the pop-up window you can see the path of the libraries folder in the text box as shown below.
Step 2: Copy all Libraries in the library
folder.
Step 3: Go to the path above and you will see there is a libraries folder, click to open it.
Step 4: Paste all the libraries copied before to the folder. Then you can see them in libraries folder.
1.4 Quick Guide on Arduino¶
In the next projects,
the code section tells you which code is used,
so you can open them by going to the euler-kit/arduino/
path and
double-clicking on the .ino
file with the serial number.
But first you need to do:
Make sure you have downloaded the package and uploaded the library by referring to Add libraries.
Open & Run Code Directly¶
Open Code
For example,
2.1_hello_led.ino
.Double click on it.
Select the board as Raspberry Pi Pico.
Click on the upload icon to run the code
After the Done Uploading appear, you will see the LED blinking.
2. Output & input
2.1 - Hello, LED!¶
Just as printing “Hello, world!” is the first step in learning to program, using a program to drive an LED is the traditional introduction to learning physical programming.
Schematic
The principle of this circuit is simple and the current direction is shown in the figure. When GP15 outputs high level(3.3v), the LED will light up after the 220ohm current limiting resistor. When GP15 outputs low level (0v), the LED will turn off.
Wiring
Let us follow the direction of the current to build the circuit!
Here we use the electrical signal from the GP15 pin of the Pico board to make the LED work, and the circuit starts from here.
The current needs to pass through a 220 ohm resistor (used to protect the LED). Insert one end (either end) of the resistor into the same row as the Pico GP15 pin (row 20 in my circuit), and insert the other end into the free row of the breadboard (row 24 in my circuit).
Pick up the LED, you will see that one of its leads is longer than the other. Insert the longer lead into the same row as the end of the resistor, and connect the shorter lead across the middle gap of the breadboard to the same row.
Insert the male-to-male (M2M) jumper wire into the same row as the LED short pin, and then connect it to the negative power bus of the breadboard.
Use a jumper to connect the negative power bus to the GND pin of Pico.
Code
Note
You can open the file
2.1_hello_led.ino
under the path ofeuler-kit/arduino/2.1_hello_led
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After the code runs, you will see the LED blinking.
How it works?
Here, we connect the LED to the digital pin 15, so we need to declare an int variable called ledpin at the beginning of the program and assign a value of 15.
const int ledPin = 15;
Now, initialize the pin in the setup()
function, where you need to initialize the pin to OUTPUT
mode.
void setup() {
pinMode(ledPin, OUTPUT);
}
In loop()
, digitalWrite()
is used to provide 3.3V high level signal for ledpin, which will cause voltage difference between LED pins and light LED up.
digitalWrite(ledPin, HIGH);
If the level signal is changed to LOW, the ledPin’s signal will be returned to 0 V to turn LED off.
digitalWrite(ledPin, LOW);
An interval between on and off is required to allow people to see the change,
so we use a delay(1000)
code to let the controller do nothing for 1000 ms.
delay(1000);
2.2 - Display the Level¶
The first project is simply to make the LED blink. In this project let’s use the LED Bar Graph, which is made up of 10 LEDs packaged into a plastic case, generally used to display power or volume levels.
Schematic
The LED Bar Graph contains 10 LEDs, each of which is individually controllable. Here, the anode of each of the 10 LEDs is connected to GP6~GP15, and the cathode is connected to a 220ohm resistor, and then to GND.
Wiring
Code
Note
You can open the file
2.2_display_the_level.ino
under the path ofeuler-kit/arduino/2.2_display_the_level
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
When the program is running, you will see the LEDs on the LED Bar Graph light up and then turn off in sequence.
How it works?
Each of the ten LEDs on the LED Bar needs to be controlled by a pin, which means that we define these ten pins.
The codes in setup()
use the for loop to initialize pins 6~15 to output mode in turn.
for(int i=6;i<=15;i++)
{
pinMode(i,OUTPUT);
}
The for loop is used in loop()
to make the LED flash(turn on 0.5s, then turn off 0.5s) in sequence.
for(int i=6;i<=15;i++)
{
digitalWrite(i,HIGH);
delay(500);
digitalWrite(i,LOW);
delay(500);
}
2.3 - Fading LED¶
So far, we have used only two output signals: high level and low level (or called 1 & 0, ON & OFF), which is called digital output. However, in actual use, many devices do not simply ON/OFF to work, for example, adjusting the speed of the motor, adjusting the brightness of the desk lamp, and so on. In the past, a slider that can adjust the resistance was used to achieve this goal, but this is always unreliable and inefficient. Therefore, Pulse width modulation (PWM) has emerged as a feasible solution to such complex problems.
A digital output composed of a high level and a low level is called a pulse. The pulse width of these pins can be adjusted by changing the ON/OFF speed.
Simply put, when we are in a short period (such as 20ms, most people’s visual retention time), Let the LED turn on, turn off, and turn on again, we won’t see it has been turned off, but the brightness of the light will be slightly weaker. During this period, the more time the LED is turned on, the higher the brightness of the LED. In other words, in the cycle, the wider the pulse, the greater the “electric signal strength” output by the microcontroller. This is how PWM controls LED brightness (or motor speed).
There are some points to pay attention to when Pico uses PWM. Let’s take a look at this picture.
Each GPIO pin of Pico supports PWM, but it actually has a total of 16 independent PWM outputs (instead of 30), distributed between GP0 to GP15 on the left, and the PWM output of the right GPIO is equivalent to the left copy.
What we need to pay attention to is to avoid setting the same PWM channel for different purposes during programming. (For example, GP0 and GP16 are both PWM_0A)
After understanding this knowledge, let us try to achieve the effect of Fading LED.
Schematic
This project is the same circuit as the first project 2.1 - Hello, LED!, but the signal type is different. The first project is to output digital high and low levels (0&1) directly from GP15 to make the LEDs light up or turn off, this project is to output PWM signal from GP15 to control the brightness of the LED.
Wiring
Code
Note
You can open the file
2.3_fading_led.ino
under the path ofeuler-kit/arduino/2.3_fading_led
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
The LED will gradually become brighter as the program runs.
How it works?
Declare pin 15 as ledPin.
const int ledPin = 15;
analogWrite()
in loop()
assigns ledPin an analog value (PWM wave) between 0 and 255 to change the brightness of LED.
analogWrite(ledPin, value);
Using a for loop, the value of analogWrite()
can be changed step by step between the minimum value (0) and the maximum value (255).
for (int value = 0 ; value <= 255; value += 5) {
analogWrite(ledPin, value);
}
In order to see the experimental phenomenon clearly, a delay(30)
needs to be added to the for cycle to control the brightness change time.
for (int value = 0 ; value <= 255; value += 5) {
analogWrite(ledPin, value);
delay(30);
}
2.4 - Colorful Light¶
As we know, light can be superimposed. For example, mix blue light and green light give cyan light, red light and green light give yellow light. This is called “The additive method of color mixing”.
Based on this method, we can use the three primary colors to mix the visible light of any color according to different specific gravity. For example, orange can be produced by more red and less green.
In this chapter, we will use RGB LED to explore the mystery of additive color mixing!
RGB LED is equivalent to encapsulating Red LED, Green LED, Blue LED under one lamp cap, and the three LEDs share one cathode pin. Since the electric signal is provided for each anode pin, the light of the corresponding color can be displayed. By changing the electrical signal intensity of each anode, it can be made to produce various colors.
Schematic
The PWM pins GP13, GP14 and GP15 control the Red, Green and Blue pins of the RGB LED respectively, and connect the common cathode pin to GND. This allows the RGB LED to display a specific color by superimposing light on these pins with different PWM values.
Wiring
An RGB LED has 4 pins: the longest pin is the common cathode pin, which is usually connected to GND, the left pin next to the longest pin is Red, and the 2 pins on the right are Green and Blue.
Code
Here, we can choose our favorite color in drawing software (such as paint) and display it with RGB LED.
Note
You can open the file
2.4_colorful_light.ino
under the path ofeuler-kit/arduino/2.4_colorful_light
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
Write the RGB value into color_set()
, you will be able to see the RGB light up the colors you want.
How it works?
In this example, the function used to assign values to the three pins of RGB is packaged in an independent subfunction color()
.
void color (unsigned char red, unsigned char green, unsigned char blue)
{
analogWrite(redPin, red);
analogWrite(greenPin, green);
analogWrite(bluePin, blue);
}
In loop()
, RGB value works as an input argument to call the function color()
to realize that the RGB can emit different colors.
void loop()
{
color(255, 0, 0); // red
delay(1000);
color(0,255, 0); // green
delay(1000);
color(0, 0, 255); // blue
delay(1000);
}
2.5 - Reading Button Value¶
From the name of GPIO (General-purpose input/output), we can see that these pins have both input and output functions. In the previous lessons, we used the output function, in this chapter we will use the input function to input read the button value.
Schematic
One side of the button pin is connected to 3.3v, and the other side pin is connected to GP14, so when the button is pressed, GP14 will be high. However, when the button is not pressed, GP14 is in a suspended state and may be high or low. In order to get a stable low level when the button is not pressed, GP14 needs to be reconnected to GND through a 10K pull-down resistor.
Wiring
Note
We can think of the four-legged button as an H-shaped button. Its left (right) two feet are connected, which means that after it straddles the central dividing line, it will connect the two half rows of the same row number together. (For example, in my circuit, E23 and F23 have been connected, as are E25 and F25).
Before the button is pressed, the left and right sides are independent of each other, and current cannot flow from one side to the other.
Code
Note
You can open the file
2.5_reading_button_value.ino
under the path ofeuler-kit/arduino/2.5_reading_button_value
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After the code runs, Click the magnifying glass icon in the upper right corner of the Arduino IDE (Serial Monitor).
Now, when you press the button, the Serial Monitor will print “You pressed the button!”.
How it works?
To enable Serial Monitor, you need to start serial communication in setup()
and set the datarate to 9600.
Serial.begin(115200);
For button, we need to set their mode to INPUT
in order to be able to get their values.
pinMode(buttonPin, INPUT);
Read the status of the buttonPin
in loop()
and assign it to the variable buttonState
.
buttonState = digitalRead(buttonPin);
If the buttonState
is HIGH, the LED will flash.
print “You pressed the button!” on the Serial monitor.
if (buttonState == HIGH) {
Serial.println("You pressed the button!");
}
Pull-up Working Mode
Next is the wiring and code when the button in the pull-up working mode, please try it.
The only difference you will see with the pull-down mode is that the 10K resistor is connected to 3.3V and the button is connected to GND, so that when the button is pressed, GP14 will get a low level, which is the opposite of the value obtained in pull-down mode.
So just change this code to if (buttonState == LOW)
.
2.6 - Tilt It!¶
The tilt switch is a 2-pin device with a metal ball in the middle. When you put it upright, the 2 pins are connected together; when you tilt the switch, 2 pins will be disconnected.
Schematic
When you put it upright, GP14 will get high; after tilting it, GP14 will get low.
The purpose of the 10K resistor is to keep the GP14 in a stable low state when the tilt switch is in a tilted state.
Wiring
Code
Note
You can open the file
2.6_tilt_it.ino
under the path ofeuler-kit/arduino/2.4_colorful_light
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After the program runs, when you tilt the breadboard (tilt switch), “The switch works!” will appear in the shell.
2.7 - Toggle Left and Right¶
The slide switch is a 3-pin device, with pin 2 (middle) being the common pin. When the switch is toggled to the left, the left two pins are connected together, and when toggled to the right, the right two pins are connected together.
Schematic
GP14 will get a different level, when you toggle the slide switch to the right or left.
The purpose of the 10K resistor is to keep the GP14 low during toggling (not toggling to the far left and not toggling to the far right).
The 104 ceramic capacitor is used here to eliminate jitter.
Wiring
Code
Note
You can open the file
2.7_toggle_left_right.ino
under the path ofeuler-kit/arduino/2.7_toggle_left_right
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
When the program is running, the serial monitor will show “ON” or “OFF” when you toggle the switch to the left or right.
2.8 - Press Gently¶
Micro Switch is also a 3-pin device, the sequence of the 3 pins are C (common pin), NO (normally open) and NC (normally closed) .
When the micro switch is not pressed, 1 (C) and 3 (NC) are connected together, when pressed 1 (C) and 2 (NO) are connected together.
Schematic
By default, GP14 is low and when pressed, GP14 is high.
The purpose of the 10K resistor is to keep the GP14 low during pressing.
The 104 ceramic capacitor is used here to eliminate jitter.
Wiring
Code
Note
You can open the file
2.8_press_gently.ino
under the path ofeuler-kit/arduino/2.8_press_gently
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After the program runs, when you toggle the slide switch to the right, “The switch works!” will appear in the Serial Monitor.
2.9 - Feel the Magnetism¶
The most common type of reed switch contains a pair of magnetizable, flexible, metal reeds whose end portions are separated by a small gap when the switch is open.
A magnetic field from an electromagnet or a permanent magnet will cause the reeds to attract each other, thus completing an electrical circuit. The spring force of the reeds causes them to separate, and open the circuit, when the magnetic field ceases.
A common example of a reed switch application is to detect the opening of a door or windows, for a security alarm.
Schematic
By default, GP14 is low; and will go high when the magnet is near the reed switch.
The purpose of the 10K resistor is to keep the GP14 at a steady low level when no magnet is near.
Wiring
Code
Note
You can open the file
2.9_feel_the_magnetism.ino
under the path ofeuler-kit/arduino/2.9_feel_the_magnetism
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
When a magnet approaches, the circuit will be closed. Just like the button in the 2.5 - Reading Button Value chapter.
2.10 - Detect Human Movement¶
Passive infrared sensor (PIR sensor) is a common sensor that can measure infrared (IR) light emitted by objects in its field of view. Simply put, it will receive infrared radiation emitted from the body, thereby detecting the movement of people and other animals. More specifically, it tells the main control board that someone has entered your room.
Schematic
When the PIR module detects someone passing by, GP14 will be high, otherwise it will be low.
Wiring
Code
Note
You can open the file
2.10_detect_human_movement.ino
under the path ofeuler-kit/arduino/2.10_detect_human_movement
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After the program runs, if the PIR module detects someone nearby, the Serial Monitor will print out “Somebody here!”
Learn More
PIR is a very sensitive sensor. In order to adapt it to the environment of use, it needs to be adjusted. Let the side with the 2 potentiometers facing you, turn both potentiometers counterclockwise to the end and insert the jumper cap on the pin with L and the middle pin.
Trigger Mode
Let’s take a look at the pins with jumper cap at the corner. It allows PIR to enter Repeatable trigger mode or Non-repeatable trigger mode
At present, our jumper cap connects the middle Pin and L Pin, which makes the PIR in non-repeatable trigger mode. In this mode, when the PIR detects the movement of the organism, it will send a high-level signal for about 2.8 seconds to the main control board. .. We can see in the printed data that the duration of work will always be around 2800ms.
Next, we modify the position of the lower jumper cap and connect it to the middle Pin and H Pin to make the PIR in repeatable trigger mode. In this mode, when the PIR detects the movement of the organism (note that it is movement, not static in front of the sensor), as long as the organism keeps moving within the detection range, the PIR will continue to send a high-level signal to the main control board. .. We can see in the printed data that the duration of work is an uncertain value.
Delay Adjustment
The potentiometer on the left is used to adjust the interval between two jobs.
At present, we screw it counterclockwise to the end, which makes the PIR need to enter a sleep time of about 5 seconds after finishing sending the high level work. During this time, the PIR will no longer detect the infrared radiation in the target area. .. We can see in the printed data that the dormancy duration is always no less than 5000ms.
If we turn the potentiometer clockwise, the sleep time will also increase. When it is turned clockwise to the end, the sleep time will be as high as 300s.
Distance Adjustment
The centered potentiometer is used to adjust the sensing distance range of the PIR.
Turn the knob of the distance adjustment potentiometer clockwise to increase the sensing distance range, and the maximum sensing distance range is about 0-7 meters. If it rotates counterclockwise, the sensing distance range is reduced, and the minimum sensing distance range is about 0-3 meters.
2.11 - Turn the Knob¶
In the previous projects, we have used the digital input on the Pico. For example, a button can change the pin from low level (off) to high level (on). This is a binary working state.
However, Pico can receive another type of input signal: analog input. It can be in any state from fully closed to fully open, and has a range of possible values. The analog input allows the microcontroller to sense the light intensity, sound intensity, temperature, humidity, etc. of the physical world.
Usually, a microcontroller needs an additional hardware to implement analog input-the analogue-to-digital converter (ADC). But Pico itself has a built-in ADC for us to use directly.
Pico has three GPIO pins that can use analog input, GP26, GP27, GP28. That is, analog channels 0, 1, and 2. In addition, there is a fourth analog channel, which is connected to the built-in temperature sensor and will not be introduced here.
In this project, we try to read the analog value of potentiometer.
Schematic
The potentiometer is an analog device and when you turn it in 2 different directions.
Connect the middle pin of the potentiometer to the analog pin GP28. The Raspberry Pi Pico contains a multi-channel, 16-bit analog-to-digital converter. This means that it maps the input voltage between 0 and the operating voltage (3.3V) to an integer value between 0 and 65535, so the GP28 value ranges from 0 to 65535.
The calculation formula is shown below.
(Vp/3.3V) x 65535 = Ap
Then program the value of GP28 (potentiometer) as the PWM value of GP15 (LED). This way you will find that by rotating the potentiometer, the brightness of the LED will change at the same time.
Wiring
Code
Note
You can open the file
2.11_turn_the_knob.ino
under the path ofeuler-kit/arduino/2.11_turn_the_knob
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
When the program is running, we can see the analog value currently read by the GP28 pin in the Serial monitor. Turn the knob, and the value will change from 0 to 1023. At the same time, the brightness of the LED will increase as the analog value increases.
How it works?
To enable Serial Monitor, you need to start serial communication in setup()
and set the datarate to 9600.
void setup() {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
}
In the loop function, the value of the potentiometer is read, then the value is mapped from 0-1023 to 0-255 and finally the value after the mapping is used to control the brightness of the LED.
void loop() {
int sensorValue = analogRead(sensorPin);
Serial.println(sensorValue);
int brightness = map(sensorValue, 0, 1023, 0, 255);
analogWrite(ledPin, brightness);
}
analogRead() is used to read the value of the sensorPin (potentiometer) and assigns it to the variable
sensorValue
.
int sensorValue = analogRead(sensorPin);
Print the value of SensorValue in Serial Monitor.
Serial.println(sensorValue);
Here, the map(value, fromLow, fromHigh, toLow, toHigh) function is required as the potentiometer value read is in the range 0-1023 and the value of a PWM pin is in the range 0-255. It is used to Re-maps a number from one range to another. That is, a value of fromLow would get mapped to toLow, a value of fromHigh to toHigh, values in-between to values in-between, etc.
int brightness = map(sensorValue, 0, 1023, 0, 255);
Now we can use this value to control the brightness of the LED.
analogWrite(ledPin,brightness);
2.12 - Feel the Light¶
The photoresistor is a typical device for analog inputs and it is used in a very similar way to a potentiometer. Its resistance value depends on the intensity of the light, the stronger the irradiated light, the smaller its resistance value; conversely, it increases.
Schematic
In this circuit, the 10K resistor and the photoresistor are connected in series, and the current passing through them is the same. The 10K resistor acts as a protection, and the GP28 reads the value after the voltage conversion of the photoresistor.
When the light is enhanced, the resistance of the photoresistor decreases, then its voltage decreases, so the value from GP28 will decrease; if the light is strong enough, the resistance of the photoresistor will be close to 0, and the value of GP28 will be close to 0. At this time, the 10K resistor plays a protective role, so that 3.3V and GND are not connected together, resulting in a short circuit.
If you place the photoresistor in a dark situation, the value of GP28 will increase. In a dark enough situation, the resistance of the photoresistor will be infinite, and its voltage will be close to 3.3v (the 10K resistor is negligible), and the value of GP28 will be close to the maximum value of 65535.
The calculation formula is shown below.
(Vp/3.3V) x 65535 = Ap
Wiring
code
Note
You can open the file
2.12_feel_the_light.ino
under the path ofeuler-kit/arduino/2.12_feel_the_light
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After the program runs, the Serial Monitor prints out the photoresistor values. You can shine a flashlight on it or cover it up with your hand to see how the value will change.
2.13 - Thermometer¶
A thermometer is a device that measures temperature or a temperature gradient (the degree of hotness or coldness of an object). A thermometer has two important elements: (1) a temperature sensor (e.g. the bulb of a mercury-in-glass thermometer or the pyrometric sensor in an infrared thermometer) in which some change occurs with a change in temperature; and (2) some means of converting this change into a numerical value (e.g. the visible scale that is marked on a mercury-in-glass thermometer or the digital readout on an infrared model). Thermometers are widely used in technology and industry to monitor processes, in meteorology, in medicine, and in scientific research.
A thermistor is a type of temperature sensor whose resistance is strongly dependent on temperature, and it has two types: Negative Temperature Coefficient (NTC) and Positive Temperature Coefficient (PTC), also known as NTC and PTC. The resistance of PTC thermistor increases with temperature, while the condition of NTC is opposite to the former.
In this experiment we use an NTC thermistor to make a thermometer.
Schematic
In this circuit, the 10K resistor and the thermistor are connected in series, and the current passing through them is the same. The 10K resistor acts as a protection, and the GP28 reads the value after the voltage conversion of the thermistor.
When the temperature increases, the resistance value of NTC thermistor decreases, then its voltage decreases, so the value from GP28 will decrease; If the temperature is high enough, the resistance of the thermistor will be close to 0, and the value of GP28 will be close to 0. At this time, the 10K resistor plays a protective role, so that 3.3V and GND are not connected together, resulting in a short circuit.
When the temperature drops, the value of GP28 will increase. When the temperature is low enough, the resistance of the thermistor will be infinite, and its voltage will be close to 3.3v (the 10K resistor is negligible), and the value of GP28 will be close to the maximum value of 65535.
The calculation formula is shown below.
(Vp/3.3V) x 65535 = Ap
Wiring
Note
The thermistor is black and marked 103.
The color ring of the 10K ohm resistor is red, black, black, red and brown.
Code
Note
You can open the file
2.13_thermometer.ino
under the path ofeuler-kit/arduino/2.13_thermometer
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After the program runs, the Serial Monitor will print out the Celsius and Fahrenheit temperatures.
How it works?
Each thermistor has a normal resistance. Here it is 10k ohm, which is measured under 25 degree Celsius.
When the temperature gets higher, the resistance of the thermistor decreases. Then the voltage data is converted to digital quantities by the A/D adapter.
The temperature in Celsius or Fahrenheit is output via programming.
long a = analogRead(analogPin);
This line is used to read the value of the thermistor.
float tempC = beta / (log((1025.0 * 10 / a - 10) / 10) + beta / 298.0) - 273.0;
float tempF = 1.8 * tempC + 32.0;
These calculations convert the thermistor values into centigrade degree and Fahrenheit degree.
Note
Here is the relation between the resistance and temperature:
RT =RN expB(1/TK – 1/TN)
RT is the resistance of the NTC thermistor when the temperature is TK.
RN is the resistance of the NTC thermistor under the rated temperature TN. Here, the numerical value of RN is 10k.
TK is a Kelvin temperature and the unit is K. Here, the numerical value of TK is 273.15 + degree Celsius.
TN is a rated Kelvin temperature; the unit is K too. Here, the numerical value of TN is 273.15+25.
And B(beta), the material constant of NTC thermistor, is also called heat sensitivity index with a numerical value 3950.
exp is the abbreviation of exponential, and the base number e is a natural number and equals 2.7 approximately.
Convert this formula TK=1/(ln(RT/RN)/B+1/TN) to get Kelvin temperature that minus 273.15 equals degree Celsius.
This relation is an empirical formula. It is accurate only when the temperature and resistance are within the effective range.
This code refers to plugging Rt into the formula TK=1/(ln(RT/RN)/B+1/TN) to get Kelvin temperature.
2.14 - Feel the Water Level¶
Water sensor is designed for water detection, which can be widely used in sensing rainfall, water level, and even liquid leakage.
It measures the water level by having a series of exposed parallel wire traces to measure the size of the water drops/volume. The water volume is easily converted to an analog signal, and the output analog value can be read directly by the main control board to achieve the water level alarm effect.
Warning
The sensor cannot be fully submerged in water, please only leave the part where the ten Traces are located in contact with water. Also, energizing the sensor in a humid environment will accelerate the corrosion of the probe and reduce the life of the sensor, so it is recommended that you only supply power when taking readings.
Schematic
Wiring
Code
Note
You can open the file
2.14_feel_the_water_level.ino
under the path ofeuler-kit/arduino/2.14_feel_the_water_level
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After the program is run, submerge the Water Sensor module slowly into the water, and as the depth increases, the Shell will print a larger value.
Learn More
There is a way to use the analog input module as a digital module.
First, take a reading of the Water Sensor in a dry environment first, record it, and use it as a threshold value. Then, complete the programming and re-read the reading of the water sensor. When the reading of the water sensor deviates significantly from the reading in a dry environment, it is exposed to liquid. In other words, by placing this device near a water pipe, it can detect if a water pipe is leaking.
Note
You can open the file
2.14_water_level_threshold.ino
under the path ofeuler-kit/arduino/2.14_water_level_threshold
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
2.15 - Two Kinds of Transistors¶
This kit is equipped with two types of transistors, S8550 and S8050, the former is PNP and the latter is NPN. They look very similar, and we need to check carefully to see their labels. When a High level signal goes through an NPN transistor, it is energized. But a PNP one needs a Low level signal to manage it. Both types of transistor are frequently used for contactless switches, just like in this experiment.
Let’s use LED and button to understand how to use transistor!
Way to connect NPN (S8050) transistor
In this circuit, when the button is pressed, GP14 is high.
By programming GP15 to output high, after a 1k current limiting resistor (to protect the transistor), the S8050 (NPN transistor) is allowed to conduct, thus allowing the LED to light up.
Way to connect PNP(S8550) transistor
In this circuit, GP14 is low by the default and will change to high when the button is pressed.
By programming GP15 to output low, after a 1k current limiting resistor (to protect the transistor), the S8550 (PNP transistor) is allowed to conduct, thus allowing the LED to light up.
The only difference you will notice between this circuit and the previous one is that in the previous circuit the cathode of the LED is connected to the collector of the S8050 (NPN transistor), while this one is connected to the emitter of the S8550 (PNP transistor).
Code
Note
You can open the file
2.15_transistor.ino
under the path ofeuler-kit/arduino/2.15_transistor
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
Two kinds of transistors can be controlled with the same code. When we press the button, Pico will send a high-level signal to the transistor; when we release it, it will send a low-level signal. We can see that diametrically opposite phenomena have occurred in the two circuits.
The circuit using the S8050 (NPN transistor) will light up when the button is pressed, which means it is receiving a high-level conduction circuit;
The circuit that uses the S8550 (PNP transistor) will light up when it is released, which means it is receiving a low-level conduction circuit.
2.16 - Control Another Circuit¶
In our daily life, we can press the switch to light up or turn off the lamp. But what if you want to control the lamp with Pico so that it can turn off automatically after ten minutes?
A relay can help you accomplish this idea.
A relay is actually a special kind of switch that is controlled by one side of the circuit (usually a low-voltage circuit) and used to control the other side of the circuit (usually a high-voltage circuit). This makes it practical to modify our home appliances to be controlled by a program, to become smart devices, or even to access the Internet.
Warning
Modification of electrical appliances comes with great danger, do not try it lightly, please do it under the guidance of professionals.
Here we only use a simple circuit powered by a breadboard power module as an example to show how to control it using relay.
Wiring
First, build a low-voltage circuit for controlling a relay. Driving the relay requires a high current, so a transistor is needed, and here we use the S8050.
A diode (continuity diode) is used here to protect the circuit. The cathode is the end with the silver ribbon connected to the power supply, and the anode is connected to the transistor.
When the voltage input changes from High (5V) to Low (0V), the transistor changes from saturation (amplification, saturation, and cutoff) to cutoff, and there is suddenly no way for current to flow through the coil.
At this point, if this freewheeling diode does not exist, the coil will produce a self-induced electric potential at both ends that is several times higher than the supply voltage, and this voltage plus the voltage from the transistor power supply is enough to burn it.
After adding the diode, the coil and the diode instantly form a new circuit powered by the energy stored in the coil to discharge, thus avoiding the excessive voltage will damage devices such as transistors on the circuit.
At this point the program is ready to run, and after running you will hear the “tik tok” sound, which is the sound of the contactor coil inside the relay sucking and breaking.
Then we connect the two ends of the load circuit to pins 3 and 6 of the relay respectively.
..(Take the simple circuit powered by the breadboard power module described in the previous article as an example.)
At this point, the relay will be able to control the load circuit on and off.
Code
Note
You can open the file
2.16_relay.ino
under the path ofeuler-kit/arduino/2.16_relay
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
When the code is run, the relay will switch the operating state of the controlled circuit every two seconds. You can manually comment out one of the lines to further clarify the correspondence between the relay circuit and the load circuit.
Learn More
Pin 3 of the relay is normally open and only turns on when the contactor coil is operating; pin 4 is normally closed and turns on when the contactor coil is energized. Pin 1 is connected to pin 6 and is the common terminal of the load circuit.
By switching one end of the load circuit from pin 3 to pin 4, you will be able to get exactly the opposite operating state.
3. Sound & Display & Movement
3.1 - Beep¶
The active buzzer is a typical digital output device that is as easy to use as lighting up an LED!
Schematic
When the GP15 output is high, after the 1K current limiting resistor (to protect the transistor), the S8050 (NPN transistor) will conduct, so that the buzzer will sound.
The role of S8050 (NPN transistor) is to amplify the current and make the buzzer sound louder. In fact, you can also connect the buzzer directly to GP15, but you will find that the buzzer sound is smaller.
Wiring
Two types of buzzers are included in the kit. We need to use active buzzer. Turn them around, the sealed back (not the exposed PCB) is the one we want.
The buzzer needs to use a transistor when working, here we use S8050 (NPN Transistor).
Code
Note
You can open the file
3.1_beep.ino
under the path ofeuler-kit/arduino/3.1_beep
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After the code runs, you will hear a beep every second.
3.2 - Custom Tone¶
We have used active buzzer in the previous project, this time we will use passive buzzer.
Like the active buzzer, the passive buzzer also uses the phenomenon of electromagnetic induction to work. The difference is that a passive buzzer does not have oscillating source, so it will not beep if DC signals are used. But this allows the passive buzzer to adjust its own oscillation frequency and can emit different notes such as “doh, re, mi, fa, sol, la, ti”.
Let the passive buzzer emit a melody!
Schematic
When the GP15 output is high, after the 1K current limiting resistor (to protect the transistor), the S8050 (NPN transistor) will conduct, so that the buzzer will sound.
The role of S8050 (NPN transistor) is to amplify the current and make the buzzer sound louder. In fact, you can also connect the buzzer directly to GP15, but you will find that the buzzer sound is smaller.
Wiring
Two buzzers are included in the kit, we use a passive buzzer (one with an exposed PCB on the back).
The buzzer needs a transistor to work, here we use S8050.
Code
Note
You can open the file
3.2_custom_tone.ino
under the path ofeuler-kit/arduino/3.2_custom_tone
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
How it works?
If the passive buzzer given a digital signal, it can only keep pushing the diaphragm without producing sound.
Therefore, we use the tone()
function to generate the PWM signal to make the passive buzzer sound.
This function has three parameters:
pin, the GPIO pin that controls the buzzer.
frequency, the pitch of the buzzer is determined by the frequency, the higher the frequency, the higher the pitch.
Duration, the duration of the tone.
Learn More
We can simulate the specific tone according to the fundamental frequency of the piano, so as to play a complete piece of music.
Note
You can open the file
3.2_custom_tone_2.ino
under the path ofeuler-kit/arduino/3.2_custom_tone_2
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
3.3 - RGB LED Strip¶
WS2812 is a intelligent control LED light source that the control circuit and RGB chip are integrated in a package of 5050 components. It internal include intelligent digital port data latch and signal reshaping amplification drive circuit. Also include a precision internal oscillator and a programmable constant current control part, effectively ensuring the pixel point light color height consistent.
The data transfer protocol use single NZR communication mode. After the pixel power-on reset, the DIN port receive data from controller, the first pixel collect initial 24bit data then sent to the internal data latch, the other data which reshaping by the internal signal reshaping amplification circuit sent to the next cascade pixel through the DO port. After transmission for each pixel,the signal to reduce 24bit. pixel adopt auto reshaping transmit technology, making the pixel cascade number is not limited the signal transmission, only depend on the speed of signal transmission.
Schematic
Wiring
Warning
One thing you need to pay attention to is current.
Although the LED Strip with any number of LEDs can be used in Pico, the power of its VBUS pin is limited. Here, we will use eight LEDs, which are safe. But if you want to use more LEDs, you need to add a separate power supply.
Code
Note
You can open the file
3.3_rgb_led_strip.ino
under the path ofeuler-kit/arduino/3.3_rgb_led_strip
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
Here you need to use the library called Adafruit_NeoPixel
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Add libraries.
Let’s select some favorite colors and display them on the RGB LED Strip!
How it works?
Declare a Adafruit_NeoPixel type object, it is connected to PIXEL_PIN
,
there are PIXEL_COUNT
RGB LEDs on the strip.
#define PIXEL_PIN 0
#define PIXEL_COUNT 8
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
Initialize strip object and initialize all pixels to ‘off’.
- Function
strip.begin()
: Initialize NeoPixel strip object (REQUIRED).strip.setPixelColor(index, color)
: Set pixel’s color (in RAM), thecolor
must be a single ‘packed’ 32-bit value.strip.Color(red, green, blue)
: Color as a single ‘packed’ 32-bit value.strip.show()
: Update strip with new contents.
Learn More
We can randomly generate colors and make a colorful flowing light.
Note
You can open the file
3.3_rgb_led_strip_flowing.ino
under the path ofeuler-kit/arduino/3.3_rgb_led_strip_flowing
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
Or have this WS2812 LED Strip rainbow cycle around the color wheel (range 65535).
Note
You can open the file
3.3_rgb_led_strip_rainbow.ino
under the path ofeuler-kit/arduino/3.3_rgb_led_strip_rainbow
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
strip.getPixelColor(index)
: Query the color of a previously-set pixel.strip.ColorHSV(pixelHue)
: Convert hue, saturation and value into a packed 32-bit RGB color that can be passed tosetPixelColor()
or other RGB-compatible functions.strip.gamma32()
: Provides a “truer” color before assigning to each pixel.
3.4 - Liquid Crystal Display¶
LCD1602 is a character type liquid crystal display, which can display 32 (16*2) characters at the same time.
As we all know, though LCD and some other displays greatly enrich the man-machine interaction, they share a common weakness. When they are connected to a controller, multiple IOs will be occupied of the controller which has no so many outer ports. Also it restricts other functions of the controller. Therefore, LCD1602 with an I2C bus is developed to solve the problem.
Here we will use the I2C0 interface to control the LCD1602 and display text.
Schematic
Wiring
Code
Note
You can open the file
3.4_liquid_crystal_display.ino
under the path ofeuler-kit/arduino/3.4_liquid_crystal_display
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
The libraries Wire
and LiquidCrystal_I2C
are used here, please check if it has been uploaded to Pico, for a detailed tutorial refer to Add libraries.
After the program runs, you will be able to see two lines of text appear on the LCD in turn, and then disappear.
Note
If the code and wiring are fine, but the LCD still does not display content, you can turn the potentiometer on the back to increase the contrast.
How it works?
By calling the library LiquidCrystal_I2C.h
, you can easily drive the LCD.
#include "LiquidCrystal_I2C.h"
Library Functions:
LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows)
Creates a new instance of the LiquidCrystal_I2
C class that represents a particular LCD attached to your Arduino board.
lcd_AddR: The address of the LCD defaults to 0x27. lcd_cols: The LCD1602 has 16 columns. lcd_rows: The LCD1602 has 2 rows.
void init()
Initialize the lcd.
void backlight()
Turn the (optional) backlight on.
void nobacklight()
Turn the (optional) backlight off.
void display()
Turn the LCD display on.
void nodisplay()
Turn the LCD display off quickly.
void clear()
Clear display, set cursor position to zero.
void setCursor(uint8_t col,uint8_t row)
Set the cursor position to col,row.
void print(data,BASE)
Prints text to the LCD.
data: The data to print (char, byte, int, long, or string).
BASE (optional): The base in which to print numbers: BIN for binary (base 2), DEC for decimal (base 10), OCT for octal (base 8), HEX for hexadecimal (base 16).
Learn More
Upload the codes to the Pico, the content that you input in the serial monitor will be printed on the LCD.
Note
You can open the file
3.4_liquid_crystal_display_2.ino
under the path ofeuler-kit/arduino/3.4_liquid_crystal_display_2
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
In addition to reading data from the electronic components, the Pico
can read the data input in the serial port monitor, and you can
use Serial.read()
as the controller of the circuit experiment.
Run the serial communication in setup()
and set the data rate to 9600.
Serial.begin(9600);
The state of serial port monitor is judged in loop()
, and the information processing will be carried out only when the data are received.
if (Serial.available() > 0){}
Clear the screen.
lcd.clear();
Reads the input value in the serial port monitor and stores it to the variable incomingByte.
char incomingByte = Serial.read();
Display each character to the LCD and skip the line-feed character.
while (Serial.available() > 0) {
char incomingByte=Serial.read();
if(incomingByte==10){break;}// skip the line-feed character
lcd.print(incomingByte);// display each character to the LCD
}
3.5 - Small Fan¶
Now we use the L293D to drive the DC motor to make it rotate clockwise and counterclockwise. Since the DC motor requires a relatively large current, for safety reasons, here we use a power module to supply power to the motor.
Schematic
In this circuit, you will see that the button is connected to the RUN pin. This is because the motor is operating with too much current, which may cause the Pico to disconnect from the computer, and the button needs to be pressed (for the Pico’s RUN pin to receive a low level) to reset.
L293D is a motor driver chip, EN is connected to 5V to make L293D work. 1A and 2A are the inputs connected to GP15 and GP14 respectively; 1Y and 2Y are the outputs connected to the two ends of the motor.
Y (output) is in phase with A (input), so if GP15 and GP14 are given different levels respectively, the direction of motor rotation can be changed.
Wiring
Since DC motors require a high current, we use a power supply module to power the motor here for safety reasons.
Code
Note
You can open the file
3.5_small_fan.ino
under the path ofeuler-kit/arduino/3.5_small_fan
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
Once the program is running, the motor will rotate back and forth in a regular pattern.
Note
If you can not upload the code again, this time you need to connect the RUN pin on the Pico with a wire to GND to reset it, and then unplug this wire to run the code again.
This is because the motor is operating with too much current, which may cause the Pico to disconnect from the computer.
3.6 - Pumping¶
Small centrifugal pumps are suitable for projects with automatic plant watering. It can also be used to make tiny smart water features.
Its power component is an electric motor, driven in exactly the same way as a normal motor.
Note
Connect the tube to the motor outlet, submerge the pump in water, and then power it on.
You need to make sure that the water level is always higher than the motor. Idling may damage the motor due to heat generation and will also generate noise.
If you are watering plants, you need to avoid soil being drawn in, as this can clog the pump.
If water does not come out of the tube, there may be residual water in the tube blocking the air flow and needs to be drained first.
Schematic
In this circuit, you will see that the button is connected to the RUN pin. This is because the motor is operating with too much current, which may cause the Pico to disconnect from the computer, and the button needs to be pressed (for the Pico’s RUN pin to receive a low level) to reset.
L293D is a motor driver chip, EN is connected to 5V to make L293D work. 1A and 2A are the inputs connected to GP15 and GP14 respectively; 1Y and 2Y are the outputs connected to the two ends of the motor.
Y (output) is in phase with A (input), so if GP15 and GP14 are given different levels respectively, the direction of motor rotation can be changed.
Wiring
Code
Note
You can open the file
3.6_pumping.ino
under the path ofeuler-kit/arduino/3.6_pumping
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After the code is run, the pump starts working and you will see water flowing out of the tube at the same time.
Note
If you can not upload the code again, this time you need to connect the RUN pin on the Pico with a wire to GND to reset it, and then unplug this wire to run the code again.
This is because the motor is operating with too much current, which may cause the Pico to disconnect from the computer.
3.7 - Swinging Servo¶
In this kit, in addition to LED and passive buzzer, there is also a device controlled by PWM signal, Servo.
Servo is a position (angle) servo device, which is suitable for those control systems that require constant angle changes and can be maintained. It has been widely used in high-end remote control toys, such as airplanes, submarine models, and remote control robots.
Now, try to make the servo sway!
Schematic
Wiring
Orange wire is signal and connected to GP15.
Red wire is VCC and connected to VBUS(5V).
Brown wire is GND and connected to GND.
Code
Note
You can open the file
3.7_swinging_servo.ino
under the path ofeuler-kit/arduino/3.7_swinging_servo
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
When the program is running, we can see the Servo Arm swinging back and forth from 0° to 180°.
How it works?
By calling the library Servo.h
, you can drive the servo easily.
#include <Servo.h>
Library Functions:
Servo
Create Servo object to control a servo.
uint8_t attach(int pin);
Turn a pin into a servo driver. Calls pinMode. Returns 0 on failure.
void detach();
Release a pin from servo driving.
void write(int value);
Set the angle of the servo in degrees, 0 to 180.
int read();
Return that value set with the last write().
bool attached();
Return 1 if the servo is currently attached.
4. Controller
4.1 - Toggle the Joystick¶
If you play a lot of video games, then you should be very familiar with the Joystick. It is usually used to move the character around, rotate the screen, etc.
The principle behind Joystick’s ability to allow the computer to read our actions is very simple. It can be thought of as consisting of two potentiometers that are perpendicular to each other. These two potentiometers measure the analog value of the joystick vertically and horizontally, resulting in a value (x,y) in a planar right-angle coordinate system.
The joystick of this kit also has a digital input, which is activated when the joystick is pressed.
Schematic
The SW pin is connected to a 10K pull-up resistor, the reason is to be able to get a stable high level on the SW pin (Z axis) when the joystick is not pressed; otherwise the SW is in a suspended state and the output value may vary between 0/1.
Wiring
Code
Note
You can open the file
4.1_toggle_the_joyostick.ino
under the path ofeuler-kit/arduino/4.1_toggle_the_joyostick
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After the program runs, the Shell prints out the x,y,z values of joystick.
The x-axis and y-axis values are analog values that vary from 0 to 65535.
The Z-axis is a digital value with a status of 1 or 0.
4.2 - 4x4 Keypad¶
The 4x4 keyboard, also known as the matrix keyboard, is a matrix of 16 keys excluded in a single panel.
The keypad can be found on devices that mainly require digital input, such as calculators, TV remote controls, push-button phones, vending machines, ATMs, combination locks, and digital door locks.
In this project, we will learn how to determine which key is pressed and get the related key value.
Schematic
4 pull-down resistors are connected to each of the columns of the matrix keyboard, so that G6 ~ G9 get a stable low level when the keys are not pressed.
The rows of the keyboard (G2 ~ G5) are programmed to go high; if one of G6 ~ G9 is read high, then we know which key is pressed.
For example, if G6 is read high, then numeric key 1 is pressed; this is because the control pins of numeric key 1 are G2 and G6, when numeric key 1 is pressed, G2 and G6 will be connected together and G6 is also high.
Wiring
To make the wiring easier, in the above diagram, the column row of the matrix keyboard and the 10K resistors are inserted into the holes where G6 ~ G9 are located at the same time.
Code
Note
You can open the file
4.2_4x4_keypad.ino
under the path ofeuler-kit/arduino/4.2_4x4_keypad
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
Here you need to use the library called Keypad
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Add libraries.
After the program runs, the Shell will print out the keys you pressed on the Keypad.
How it works
By calling the Keypad.h
library, you can easily use Keypad.
#include <Keypad.h>
Library Functions:
Keypad(char *userKeymap, byte *row, byte *col, byte numRows, byte numCols)
Initializes the internal keymap to be equal to userKeymap
.
userKeymap
: The symbols on the buttons of the keypads.
row
, col
: Pin configuration.
numRows
, numCols
: Keypad sizes.
char getKey()
Returns the key that is pressed, if any. This function is non-blocking.
4.3 - Electrode Keyboard¶
The MPR121 is a good choice when you want to add a large number of touch switches to your project. It has electrodes that can be extended with conductors. If you connect the electrodes to a banana, you can turn the banana into a touch switch.
Schematic
Wiring
Code
Note
You can open the file
4.3_electrode_keyboard.ino
under the path ofeuler-kit/arduino/4.3_electrode_keyboard
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
Here you need to use two libraries Adafruit_MPR121
and Adafruit_BusIO
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Add libraries.
After the program runs, you can touch the twelve electrodes on the MPR121 module by hand and the touch status of these electrodes will be recorded in a 12-bit Boolean type array that will be printed on the serial monitor.
If the first and eleventh electrodes are touched, 100000000010
is printed.
You can extend the electrodes by connecting other conductors such as fruit, wire, foil, etc. This will give you more ways to trigger these electrodes.
How it works?
Initialize the MPR121
object. At this point the state of the module’s electrodes will be recorded as initial values.
If you extend the electrodes, you need to rerun the example to reset the initial values.
#include "Adafruit_MPR121.h"
Adafruit_MPR121 cap = Adafruit_MPR121();
void setup() {
Serial.begin(9600);
int check = cap.begin(0x5A);
if (!check) {
Serial.println("MPR121 not found, check wiring?");
while (1);
}
Serial.println("MPR121 found!");
}
Gets the value of the current electrode, it will get a 12-bit binary value. If you touch the first and the eleventh electrode, it gets 100000000010
.
// Get the currently touched pads
currtouched = cap.touched();
Determine if the electrode state has changed.
void loop() {
currtouched = cap.touched();
if (currtouched != lasttouched) {}
// reset our state
lasttouched = currtouched;
}
If a change in electrode state is detected, the values of currtouched
are stored in the touchStates[12]
array bit by bit. Finally, the array is printed.
if (currtouched != lasttouched) {
for (int i = 0; i < 12; i++) {
if (currtouched & (1 << i)) touchStates[i] = 1;
else touchStates[i] = 0;
}
for (int i = 0; i < 12; i++){
Serial.print(touchStates[i]);
}
Serial.println();
}
5. Microchip
5.1 - Microchip - 74HC595¶
Integrated circuit (integrated circuit) is a kind of miniature electronic device or component, which is represented by the letter “IC” in the circuit.
A certain process is used to interconnect the transistors, resistors, capacitors, inductors and other components and wiring required in a circuit, fabricate on a small or several small semiconductor wafers or dielectric substrates, and then package them in a package , it has become a micro-structure with the required circuit functions; all of the components have been structured as a whole, making electronic components a big step towards micro-miniaturization, low power consumption, intelligence and high reliability.
The inventors of integrated circuits are Jack Kilby (integrated circuits based on germanium (Ge)) and Robert Norton Noyce (integrated circuits based on silicon (Si)).
This kit is equipped with an IC, 74HC595, which can greatly save the use of GPIO pins. Specifically, it can replace 8 pins for digital signal output by writing an 8-bit binary number.
Schematic
When MR (pin10) is high level and OE (pin13) is low level, data is input in the rising edge of SHcp and goes to the memory register through the rising edge of SHcp.
If the two clocks are connected together, the shift register is always one pulse earlier than the memory register.
There is a serial shift input pin (Ds), a serial output pin (Q) and an asynchronous reset button (low level) in the memory register.
The memory register outputs a Bus with a parallel 8-bit and in three states.
When OE is enabled (low level), the data in memory register is output to the bus(Q0 ~ Q7).
Wiring
Code
Note
You can open the file
5.1_microchip_74hc595.ino
under the path ofeuler-kit/arduino/5.1_microchip_74hc595
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
When the program is running, you can see the LEDs turning on one after another.
How it works?
Declare an array, store several 8 bit binary numbers that are used to change the working state of the eight LEDs controlled by 74HC595.
int datArray[] = {0b00000000, 0b00000001, 0b00000011, 0b00000111, 0b00001111, 0b00011111, 0b00111111, 0b01111111, 0b11111111};
Set STcp
to low level first and then high level. It will generate a rising edge pulse of STcp
.
digitalWrite(STcp,LOW);
shiftOut()
is used to shift out a byte of data one bit at a time, which means to shift a byte of data in datArray[num] to the shifting register with the DS pin. MSBFIRST means to move from high bits.
shiftOut(DS,SHcp,MSBFIRST,datArray[num]);
After digitalWrite(STcp,HIGH)
is run, the STcp will be at the rising edge. At this time, the data in the shift register will be moved to the memory register.
digitalWrite(STcp,HIGH);
A byte of data will be transferred into the memory register after 8 times. Then the data of memory register are output to the bus (Q0-Q7). For example, shiftout B00000001
will light up the LED controlled by Q0 and turn off the LED controlled by Q1~Q7.
5.2 - Number Display¶
LED Segment Display can be seen everywhere in life. For example, on an air conditioner, it can be used to display temperature; on a traffic indicator, it can be used to display a timer.
The LED Segment Display is essentially a device packaged by 8 LEDs, of which 7 strip-shaped LEDs form an “8” shape, and there is a slightly smaller dotted LED as a decimal point. These LEDs are marked as a, b, c, d, e, f, g, and dp. They have their own anode pins and share cathodes. Their pin locations are shown in the figure below.
This means that it needs to be controlled by 8 digital signals at the same time to fully work and the 74HC595 can do this.
Schematic
Wiring
74HC595 |
LED Segment Display |
---|---|
Q0 |
a |
Q1 |
b |
Q2 |
c |
Q3 |
d |
Q4 |
e |
Q5 |
f |
Q6 |
g |
Q7 |
dp |
Code
Note
You can open the file
5.2_number_display.ino
under the path ofeuler-kit/arduino/5.2_number_display
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
When the program is running, you will be able to see the LED Segment Display display 0~9 in sequence.
How it works?
shiftOut()
will make 74HC595 output 8 digital signals.
It outputs the last bit of the binary number to Q0, and the output of the first bit to Q7. In other words, writing the binary number “00000001” will make Q0 output high level and Q1~Q7 output low level.
Suppose that the 7-segment Display display the number “1”, we need to write a high level for b, c, and write a low level for a, d, e, f, g, and dg. That is, the binary number “00000110” needs to be written. For readability, we will use hexadecimal notation as “0x06”.
Similarly, we can also make the LED Segment Display display other numbers in the same way. The following table shows the codes corresponding to these numbers.
Numbers |
Binary Code |
Hex Code |
---|---|---|
0 |
00111111 |
0x3f |
1 |
00000110 |
0x06 |
2 |
01011011 |
0x5b |
3 |
01001111 |
0x4f |
4 |
01100110 |
0x66 |
5 |
01101101 |
0x6d |
6 |
01111101 |
0x7d |
7 |
00000111 |
0x07 |
8 |
01111111 |
0x7f |
9 |
01101111 |
0x6f |
Write these codes into shiftOut()
to make the LED Segment Display display the corresponding numbers.
5.3 - Time Counter¶
4-Digit 7-segment display consists of four 7- segment displays working together.
The 4-digtal 7-segment display works independently. It uses the principle of human visual persistence to quickly display the characters of each 7-segment in a loop to form continuous strings.
For example, when “1234” is displayed on the display, “1” is displayed on the first 7-segment, and “234” is not displayed. After a period of time, the second 7-segment shows “2”, the 1st 3th 4th of 7-segment does not show, and so on, the four digital display show in turn. This process is very short (typically 5ms), and because of the optical afterglow effect and the principle of visual residue, we can see four characters at the same time.
Schematic
Here the wiring principle is basically the same as 5.1 - Microchip - 74HC595, the only difference is that Q0-Q7 are connected to the a ~ g pins of the 4-digit 7-segment display.
Then G10 ~ G13 will select which 7-segment display to work.
Wiring
Code
Note
You can open the file
5.3_time_counter.ino
under the path ofeuler-kit/arduino/5.3_time_counter
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After the program is run, you will see the 4-digit 7-segment display become a counter and the number increases by 1 per second.
How it works?
Writing signals to each 7-segment display is done in the same way as 5.2 - Number Display, using the hc595_shift()
function.
The core point of the 4-digit 7-segment display is to selectively activate each 7-segment display. The code associated with this is as follows.
const int placePin[4] = {13,12,11,10};
void setup ()
{
for (int i = 0; i<4;i++){
pinMode(placePin[i],OUTPUT);
}
}
void loop()
{
pickDigit(0);
hc595_shift(count%10/1);
pickDigit(1);
hc595_shift(count%100/10);
pickDigit(2);
hc595_shift(count%1000/100);
pickDigit(3);
hc595_shift(count%10000/1000);
}
void pickDigit(int digit){
for(int i = 0; i < 4; i++){
digitalWrite(placePin[i],HIGH);
}
digitalWrite(placePin[digit],LOW);
}
Here, four pins (GP10, GP11, GP12, GP13) are used to control each bit of the 4-digit 7-segment display individually.
When the status of these pins is LOW
, the corresponding 7-segment display is active; when the status is HIGH
, the 7-segment display does not work.
Here the pickDigit(digit)
function is used to unable all 7-segment displays and then enable a particular digit individually.
After that, hc595_shift()
is used to write the corresponding 8 bits code for the 7-segment display.
The 4-digit 7-segment display needs to be continuously activated in turn so that we can see it display four digits, which means that the main program cannot easily add code that would affect the timing.
However, we need to add a timing function to this example, if we add a delay (1000)
, we will be able to detect the illusion of its four 7-segment displays working at the same time, exposing the fact that only one 7-segment display at a time to light.
Then, using the millis()
function is an excellent way to do this.
void setup ()
{
timerStart = millis();
}
void loop()
{
unsigned int count = (millis()-timerStart)/1000;
}
The millis()
function gets the number of milliseconds that have passed since the current program was started. We record the first time value as timerStart
;
then when we need to get the time again, we call the millis()
function again and subtract timerStart
from the value to get how long the program has been running.
Finally, convert this time value and let the 4-digit 7-segment display to display it.
5.4 - 8x8 Pixel Graphics¶
ED matrix is a low-resolution dot-matrix display. it uses an array of light-emitting diodes as pixels for patterned displays.
They are bright enough to be visible in outdoor sunlight, and you can see them on some stores, billboards, signs, and variable message displays (such as those on public transit vehicles).
Used in this kit is an 8x8 dot matrix with 16 pins. Their anodes are connected in rows and their cathodes are connected in columns (at the circuit level), which together control these 64 LEDs.
To light the first LED, you should provide a high level for Row1 and a low level for Col1. To light the second LED, it should provide a high level for Row1, a low level for Col2, and so on. By controlling the current through each pair of rows and columns, each LED can be controlled individually to display characters or pictures.
Schematic
The 8x8 dot matrix is controlled by two 74HC595 chips, one controlling the rows and one controlling the columns, while these two chips share G18~G20, which can greatly save the I/O ports of the Pico board.
Pico needs to output a 16-bit binary number at a time, the first 8 bits are given to the 74HC595 which controls the rows, and the last 8 bits are given to the 75HC595 which controls the columns, so that the dot matrix can display a specific pattern.
Q7’: Series output pin, connected to DS of another 74HC595 to connect multiple 74HC595s in series.
Wiring
Build the circuit. Since the wiring is complicated, let’s make it step by step.
Step 1: First, insert the pico, the LED dot matrix and two 74HC595 chips into breadboard. Connect the 3.3V and GND of the pico to holes on the two sides of the board, then hook up pin16 and 10 of the two 74HC595 chips to VCC, pin 13 and pin 8 to GND.
Note
In the Fritzing image above, the side with label is at the bottom.
Step 2: Connect pin 11 of the two 74HC595 together, and then to GP20; then pin 12 of the two chips, and to GP19; next, pin 14 of the 74HC595 on the left side to GP18 and pin 9 to pin 14 of the second 74HC595.
Step 3: The 74HC595 on the right side is to control columns of the LED dot matrix. See the table below for the mapping. Therefore, Q0-Q7 pins of the 74HC595 are mapped with pin 13, 3, 4, 10, 6, 11, 15, and 16 respectively.
74HC595 |
Q0 |
Q1 |
Q2 |
Q3 |
Q4 |
Q5 |
Q6 |
Q7 |
LED Dot Matrix |
13 |
3 |
4 |
10 |
6 |
11 |
15 |
16 |
Step 4: Now connect the ROWs of the LED dot matrix. The 74HC595 on the left controls ROW of the LED dot matrix. See the table below for the mapping. We can see, Q0-Q7 of the 74HC595 on the left are mapped with pin 9, 14, 8, 12, 1, 7, 2, and 5 respectively.
74HC595 |
Q0 |
Q1 |
Q2 |
Q3 |
Q4 |
Q5 |
Q6 |
Q7 |
LED Dot Matrix |
9 |
14 |
8 |
12 |
1 |
7 |
2 |
5 |
Code
Note
You can open the file
5.4_8x8_pixel_graphics.ino
under the path ofeuler-kit/arduino/5.4_8x8_pixel_graphics
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
Once the program is running, you will see a x graphic displayed on the 8x8 dot matrix.
How it works?
Here we use two 74HC595s to provide signals for the rows and columns of the dot matrix.
The method of supplying signals is the same as shiftOut()
in the previous chapters, except that here we need to write the 16-bit binary number at a time.
The main loop calls shiftOut()
twice, writes two 8-bit binary numbers and then outputs them to the bus, so that a pattern can be displayed.
However, since the LEDs in the dot matrix use common poles, controlling multiple rows/multiple columns at the same time will interfere with each other (e.g., if (1,1) and (2,2) are lit at the same time, (1,2) and (2,1) will inevitably be lit together). Therefore, it is necessary to activate one column (or one row) at a time, cycle 8 times, and use the residual image principle to let the human eye merge 8 patterns, so as to let get a pair of patterns containing 8x8 amount of information.
for(int num = 0; num <=8; num++)
{
digitalWrite(STcp,LOW); //ground ST_CP and hold low for as long as you are transmitting
shiftOut(DS,SHcp,MSBFIRST,datArray[num]);
shiftOut(DS,SHcp,MSBFIRST,0x80>>num);
//return the latch pin high to signal chip that it
//no longer needs to listen for information
digitalWrite(STcp,HIGH); //pull the ST_CPST_CP to save the data
}
In this example, the main function nests a for
loop, and when i
is 1, only the first line is activated (the chip in the control line gets the value 0x80
) and the image of the first line is written.
When i
is 2, the second line is activated (the chip of the control line gets the value 0x40
) and the image of the second line is written. And so on, completing 8 outputs.
Incidentally, like the 4-digit 7-segment display, it has to maintain the refresh rate to prevent flickering by the human eye, so the extra sleep()
in the main loop should be avoided as much as possible.
Learn More
Try replacing datArray
with the following array and see what images appear!
int datArray1[] = {0xFF,0xEF,0xC7,0xAB,0xEF,0xEF,0xEF,0xFF};
int datArray2[] = {0xFF,0xEF,0xEF,0xEF,0xAB,0xC7,0xEF,0xFF};
int datArray3[] = {0xFF,0xEF,0xDF,0x81,0xDF,0xEF,0xFF,0xFF};
int datArray4[] = {0xFF,0xF7,0xFB,0x81,0xFB,0xF7,0xFF,0xFF};
int datArray5[] = {0xFF,0xBB,0xD7,0xEF,0xD7,0xBB,0xFF,0xFF};
int datArray6[] = {0xFF,0xFF,0xF7,0xEB,0xDF,0xBF,0xFF,0xFF};
Or, you can try drawing your own graphics.
6. Advanced
6.1 - Measuring Distance¶
The ultrasonic sensor module works on the principle of sonar and radar systems for determining the distance to an object.
Schematic
Wiring
Code
Note
You can open the file
6.1_ultrasonic.ino
under the path ofeuler-kit/arduino/6.1_ultrasonic
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Or run this code directly in the Arduino Web Editor.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
Once the program is running, the Serial Monitor will print out the distance of the ultrasonic sensor from the obstacle ahead.
How it works?
About the application of ultrasonic sensor, we can directly check the subfunction.
float readSensorData(){// ...}
PING
is triggered by a HIGH pulse of 2 or more microseconds. (Give a
short LOW
pulse beforehand to ensure a clean HIGH
pulse.)
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
The echo pin is used to read signal from PING, a HIGH
pulse whose
duration is the time (in microseconds) from the sending of the ping to
the reception of echo of the object.
microsecond=pulseIn(echoPin, HIGH);
The speed of sound is 340 m/s or 29 microseconds per centimeter.
This gives the distance travelled by the ping, outbound and return, so we divide by 2 to get the distance of the obstacle.
float distance = microsecond / 29.00 / 2;
Note that the ultrasonic sensor will pause the program when it is working, which may cause some lagging when writing complex projects.
6.2 - Temperature - Humidity¶
Humidity and temperature are closely related from the physical quantity itself to the actual people’s life. The temperature and humidity of human environment will directly affect the thermoregulatory function and heat transfer effect of human body. It will further affect the thinking activity and mental state, thus affecting the efficiency of our study and work.
Temperature is one of the seven basic physical quantities in the International System of Units, which is used to measure the degree of hot and cold of an object. Celsius is one of the more widely used temperature scales in the world, expressed by the symbol “℃”.
Humidity is the concentration of water vapor present in the air. The relative humidity of air is commonly used in life and is expressed in %RH. Relative humidity is closely related to temperature. For a certain volume of sealed gas, the higher the temperature, the lower the relative humidity, and the lower the temperature, the higher the relative humidity.
A basic digital temperature and humidity sensor, the DHT11, is provided in this kit. It uses a capacitive humidity sensor and thermistor to measure the surrounding air and outputs a digital signal on the data pins (no analog input pins are required).
Schematic
Wiring
Code
Note
You can open the file
6.2_dht11.ino
under the path ofeuler-kit/arduino/6.2_dht11
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After the code is run, you will see the Serial Monitor continuously print out the temperature and humidity, and as the program runs steadily, these two values will become more and more accurate.
How it works?
Initialize the DHT11 object. This device requires only a digital input to be used.
int pinDHT11 = 16;
SimpleDHT11 dht11(pinDHT11);
Reads the current temperature and humidity, which are stored in the variables temperature
and humidity
. err
is used to determine the validity of the data.
byte temperature = 0;
byte humidity = 0;
int err = dht11.read(&temperature, &humidity, NULL);
Filter invalid data.
if (err != SimpleDHTErrSuccess) {
Serial.print("Read DHT11 failed, err=");
Serial.print(SimpleDHTErrCode(err));
Serial.print(",");
Serial.println(SimpleDHTErrDuration(err));
delay(1000);
return;
}
Print temperature and humidity.
Serial.print((int)temperature);
Serial.print(" *C, ");
Serial.print((int)humidity);
Serial.println(" H");
Finally, the DHT11 sampling rate is 1HZ, a delay(1500)
is needed in the loop.
delay(1500);
6.3 - 6-axis Motion Tracking¶
The MPU-6050 is a 6-axis(combines 3-axis Gyroscope, 3-axis Accelerometer) motion tracking devices.
An accelerometer is a tool that measures proper acceleration.For example, an accelerometer at rest on the surface of the Earth will measure an acceleration due to Earth’s gravity, straight upwards[3] (by definition) of g ≈ 9.81 m/s2.
Accelerometers have many uses in industry and science. For example: inertial navigation systems for aircraft and missiles, for keeping images on tablets and digital cameras vertical, etc.
Gyroscopes are used to measure orientation and angular velocity of a device or maintenance. Applications of gyroscopes include anti-rollover and airbag systems for automobiles, motion sensing systems for smart devices, attitude stabilization systems for drones, and more.
Schematic
Wiring
Code
Note
You can open the file
6.3_6axis_motion_tracking.ino
under the path ofeuler-kit/arduino/6.3_6axis_motion_tracking
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
Here you need to use the library called Adafruit_MPU6050
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Add libraries.
After running the program, you can see the 3-axis accelerometer values and 3-axis gyroscope values cycling through the output. At this point you rotate the MPU6050 at random, and these values will appear to change accordingly. To make it easier to see the changes, you can comment out one of the print lines and concentrate on another set of data.
How it works?
Instantiate an MPU6050
object.
#include <Adafruit_MPU6050.h>
#include <Wire.h>
Adafruit_MPU6050 mpu;
Initialize the MPU6050 and set its accuracy.
void setup(void) {
Serial.begin(115200);
while (!Serial)
delay(10); // will pause Zero, Leonardo, etc until serial console opens
Serial.println("Adafruit MPU6050 test!");
// Try to initialize!
if (!mpu.begin()) {
Serial.println("Failed to find MPU6050 chip");
while (1) {
delay(10);
}
}
Serial.println("MPU6050 Found!");
// Set range
mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
mpu.setGyroRange(MPU6050_RANGE_500_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
Serial.println("");
delay(100);
}
Get new sensor events with the readings.
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
Subsequently, you will be able to get real-time acceleration and angular velocity values in the data a.acceleration.x
, a.acceleration.y
, a.acceleration.z
, g.gyro.x
, g.gyro.y
, g.gyro.z
.
Serial.print("Acceleration X: ");
Serial.print(a.acceleration.x);
Serial.print(", Y: ");
Serial.print(a.acceleration.y);
Serial.print(", Z: ");
Serial.print(a.acceleration.z);
Serial.println(" m/s^2");
Serial.print("Rotation X: ");
Serial.print(g.gyro.x);
Serial.print(", Y: ");
Serial.print(g.gyro.y);
Serial.print(", Z: ");
Serial.print(g.gyro.z);
Serial.println(" rad/s");
6.4 - IR Remote Control¶
In consumer electronics, remote controls are used to operate devices such as televisions and DVD players. In some cases, remote controls allow people to operate devices that are out of their reach, such as central air conditioners.
IR Receiver is a component with photocell that is tuned to receive to infrared light. It is almost always used for remote control detection - every TV and DVD player has one of these in the front to receive for the IR signal from the clicker. Inside the remote control is a matching IR LED, which emits IR pulses to tell the TV to turn on, off or change channels.
Schematic
Wiring
Code
Note
You can open the file
6.4_ir_remote_control.ino
under the path ofeuler-kit/arduino/6.4_ir_remote_control
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
Here you need to use the library called IRsmallDecoder
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Add libraries.
The new remote control has a plastic piece at the end to isolate the battery inside. You need to pull out this plastic piece to power up the remote when you are using it. Once the program is running, when you press the remote control, the Serial Monitor will print out the key you pressed.
6.5 - Radio Frequency Identification¶
Radio Frequency Identification (RFID) refers to technologies that involve using wireless communication between an object (or tag) and an interrogating device (or reader) to automatically track and identify such objects. The tag transmission range is limited to several meters from the reader. A clear line of sight between the reader and tag is not necessarily required.
Most tags contain at least one integrated circuit (IC) and an antenna. The microchip stores information and is responsible for managing the radio frequency (RF) communication with the reader. Passive tags do not have an independent energy source and depend on an external electromagnetic signal, provided by the reader, to power their operations. Active tags contain an independent energy source, such as a battery. Thus, they may have increased processing, transmission capabilities and range.
Schematic
Wiring
Code
Note
You can open the file
6.5_rfid_write.ino
under the path ofeuler-kit/arduino/6.5_rfid_write
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
Here you need to use the library called MFRC522
, please check if it has been uploaded to Pico, for a detailed tutorial refer to Add libraries.
The main function is divided into two:
6.5_rfid_write.ino
: Used to write information to the card (or key).6.5_rfid_read.ino
: used to read the information in the card (or key)
Note
You can open the file
6.5_rfid_write.ino
under the path ofeuler-kit/arduino/6.5_rfid_write
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After running you will be able to enter message in the serial monitor, ending with #
, and then write the message to the card by placing the card (or key) close to the MFRC522 module.
Note
You can open the file
6.5_rfid_read.ino
under the path ofeuler-kit/arduino/6.5_rfid_read
.Or copy this code into Arduino IDE.
For detailed tutorials, please refer to Open & Run Code Directly.
Don’t forget to select the Raspberry Pi Pico board and the correct port before clicking the Upload button.
After running, you will be able to read the message stored in the card (or key).
How it works?
#include <MFRC522.h>
#define RST_PIN 0
#define SS_PIN 5
MFRC522 mfrc522(SS_PIN, RST_PIN);
First, instantiate MFRC522()
class.
For simplicity of use, the MFRC522
library is further encapsulated with the following functions.
void simple_mfrc522_init()
: Starts SPI communication and initializes the mfrc522 module.void simple_mfrc522_get_card()
: Suspends the program until the card (or key) is detected, prints the card UID and PICC type.void simple_mfrc522_write(String text)
: Write a string for the card (or key).void simple_mfrc522_write(byte* buffer)
: Writes information for the card (or key), which usually comes from the serial port.void simple_mfrc522_write(byte section, String text)
: Writes a string for a specific sector.section
is set to 0 to write sectors 1-2;section
is set to 1 to write sectors 3-4.void simple_mfrc522_write(byte section, byte* buffer)
: Writes information for a specific sector, usually from the serial port.section
set to 0, writes 1-2 sectors;section
set to 1, writes 3-4 sectors.String simple_mfrc522_read()
: Reads the information in the card (or key), returns a string.String simple_mfrc522_read(byte section)
: Reads the information in a specific sector, returns a string.section
is set to 0, writes 1-2 sectors;section
is set to 1, writes 3-4 sectors.
In the 6.5_rfid_write.ino
example, the Serial.readBytesUntil()
function is used, which is a common serial input method.
For Piper Make¶
This chapter contains an introduction to Piper Make, how to connect and program Pico in Piper Make, and several interesting projects to help you get up and running with Piper quickly.
We recommend that you read this chapter in order.
Piper Make is a super easy and fun way to make projects using Raspberry Pi Pico. It uses blocks like Scratch, so you don’t need any programming experience to use it. The underlying principle is to use CircuitPython with auxiliary libraries.
1. Get Started
1.1 Set up the Pico¶
First, visit Piper Make through the following link:
In the pop-up page, if you don’t need to subscribe for more tutorials, you can just click Let’s Go! or the x button.
Note
If you see a different pop-up window, your browser version is not supported, please update your browser and try again.
Find the SETUP MY PICO
button, click it, and follow the prompts to configure it.
Click Next to start configuring your Pico, even if you have set it up before, these are the same steps you will use to update your Pico firmware.
In this step, you need to make sure that your Pico is unplugged from your computer, as it needs to be plugged in in a specific way in the next step. Make sure your cable can handle power and data, as many micro USB cables only have power.
Now, press and hold the RST (white) button on the Pico and plug the Pico into your computer. Once plugged in, you can release the button.
Your Pico will appear as a USB drive, click Next after that select RPI-RP2 drive.
Note
After select RPI-RP2 drive, there will be a pop up window at the top that you need to allow the web page to view files.
Now Piper Make will load the firmware to your Pico, again you need to allow save changes to the hard drive where the Pico is located.
When this prompt appears, it means your Pico is set up and you can start using it.
1.2 Quick Guide on Piper Make¶
1. Create New Project¶
Now that you have set up Pico, it is time to learn how to program it. Now let’s light up the onboard LED.
Switch to CREATIVE MODE
and click on the New Project button,
and a new project will appear in the MY PROJECTS section and
will be assigned a random name that can be changed from the programming page.
Then open the new project just created.
Now go to the Piper Make programming page.
START: Used to run the code, if it’s gray, it’s not connected to Pico at this time.
Block palette: contains different types of blocks.
CONNECT: Used to connect to Pico, it is green when not connected to Pico, when connected it will become DISCONNECT(red).
Programming Area: Drag blocks here to finish programming by stacking them.
Tools Area: You can click DIGITAL VIEW to see the pin distribution of Pico; you can view the print information in CONSOLE; you can read data from DATA, and you can click Python to view the Python source code.
Project name and description: You can change the project name and description.
DOWNLOAD: You can click the DOWNLOAD button to save it locally, usually in | format. Next time you can import it via the Import Project button on the home page.
Click on the Chip palette and drag the [start] block to the Programming Area.
Then drag the [loop] block in loops palette to the bottom of the [start] block, and set the loop interval to 1 second.
The Raspberry Pi Pico’s onboard LED is at pin25, so we use the [turn pin () ON/OFF] block on the Chip palette to control it.
2. Connect to Pico¶
Now click on the CONNECT button to connect to pico, after clicking on it a new popup will appear.
Select the recognized CircuitPython CDC control (COMXX) port, then click on Connect.
When the connection is successful, the green CONNECT in the bottom left corner will change to a red DISCONNECT.
3. Run the Code¶
Now click on the START button to run this code and you will see the LED on the Pico lit up. If yours is gray, it means that the Pico is not connected, please reconnect it.
Then turn off pin25 every second in the cycle, and click START on the upper left again, so that you can see the onboard LED lights flashing.
1.3 How to Save or Import Code?¶
Save the Code¶
After writing the code, you can change the code name and description, and then click the Download button to save the code locally or share it with others.
Then enter the file name and click the Download button again to save the code as a .png
file.
Import the Code¶
In Piper Make’s home page, click Import Project.
Select the .png
file in the path euler-kit\piper
and click Import.
Note that you need to download the SunFounder Euler Kit package first.
Or check out the code at Euler Kit - GitHub.
Now you can see the file you imported.
2. Projects
2.1 Blink LED¶
For this project, we intend to make the extended LED light blink. To use extended electronic components, a solderless breadboard will be the most powerful partner for novice users.
The breadboard is a rectangular plastic plate with a bunch of small holes in it. These holes allow us to easily insert electronic components and build electronic circuits. The breadboard does not permanently fix the electronic components, which makes it easy for us to repair the circuit and start over when we make a mistake.
Wiring
The color ring of the 220 ohm resistor is red, red, black, black and brown.
The longer lead of the LED is known as the anode (+), the shorter lead is the cathode (-).
Code
Note
You can refer to the image below to write code by dragging and dropping.
Import
2.1_blink_led.png
from the path ofeuler-kit\piper
. For detailed tutorials, please refer to Import the Code.
After connecting Pico, click the Start button and you will see the LED blinking. For more details, you can refer to 1.2 Quick Guide on Piper Make.
How it Works?
This is the body of the loop: turn the pin15 on to light up the LED, wait one second, then turn the pin15 off to make the LED go off. Wait 1 second and then re-run the previous cycle, so you can see the LED has been in the state of alternating between light and off.
[start]: This block is the basic framework of the program and represents the beginning of the program.
[repeat forever do() wait()seconds]: Means that the blocks in it will be executed repeatedly, and the execution time interval is defined by yourself.
[turn pin () ON/OFF]: Indicates that a certain pin is placed in a high level (ON) or a low level (OFF).
[wait () seconds]: Set the execution interval between blocks.
2.2 Button¶
In this project, we will learn how to turn on or off the LED by using a button.
Wiring
One side of the button pin is connected to 3.3v, and the other side pin is connected to GP14, so when the button is pressed, GP14 will be high.
However, when the button is not pressed, GP14 is in a suspended state and may be high or low. In order to get a stable low level when the button is not pressed, GP14 needs to be reconnected to GND through a 10K pull-down resistor.
Code
Note
You can refer to the image below to write code by dragging and dropping.
Import
2.2_button.png
from the path ofeuler-kit\piper
. For detailed tutorials, please refer to Import the Code.
After connecting Pico, click the Start button and the code starts to run. When the button is pressed, the LED will be lit. When the button is released, the LED will go out.
How it Works?
When the button is pressed, pin14 is high. So if the read pin14 is high, turn the pin15 on (LED is lit); else, turn off the pin15 (LED is off).
[if () do () else ()]: This is a judgment block, depending on the condition after the [if] block to determine whether to run the blocks inside the [do] block, or the blocks inside the [else] block.
[is pin () HIGH]: This is used to read the level of a specific pin, if the level read is the same as the set HIGH/LOW, then execute the blocks inside [do] block, otherwise execute the blocks inside [else].
2.3 Service Bell¶
For this project we used a microswitch and an active buzzer to create a service bell. Tap the switch and the buzzer makes a sound.
Micro Switch is also a 3-pin device, the sequence of the 3 pins are C (common pin), NO (normally open) and NC (normally closed).
When the micro switch is not pressed, 1 (C) and 3 (NC) are connected together, when pressed 1 (C) and 2 (NO) are connected together.
Wiring
By default, pins 1 and 3 of the Micro Switch are connected together and GP14 is low. When the Micro Switch is pressed, GP14 is high.
GP15 outputs high to make the buzzer sound.
Code
Note
You can refer to the image below to write code by dragging and dropping.
Import
2.3_service_bell.png
from the path ofeuler-kit\piper
. For detailed tutorials, please refer to Import the Code.
After connecting Pico, click the Start button and the code starts to run. Tap the switch and the buzzer makes a sound.
Note
This project code is exactly the same as the previous project 2.2 Button.
2.4 Rainbow Light¶
In this project, we will make the RGB LEDs display a rainbow of colors.
RGB LED is equivalent to encapsulating Red LED, Green LED, Blue LED under one lamp cap, and the three LEDs share one cathode pin. Since the electric signal is provided for each anode pin, the light of the corresponding color can be displayed. By changing the electrical signal intensity of each anode, it can be made to produce various colors.
Wiring
An RGB LED has 4 pins: the longest pin is the common cathode pin, which is usually connected to GND, the left pin next to the longest pin is Red, and the 2 pins on the right are Green and Blue.
When using the same power supply intensity, the Red LED will be brighter than the other two, and a slightly larger resistor(330Ω) needs to be used to reduce its brightness.
The 3 buttons are used to control the lighting of the Red, Green and Blue LEDs respectively.
Code
Note
You can refer to the image below to write code by dragging and dropping.
Import
2.4_rainbow_light.png
from the path ofeuler-kit\piper
. For detailed tutorials, please refer to Import the Code.
After connecting Pico, click the Start button and the code starts to run. Pressing these buttons individually will emit a single color of light, but if two of the buttons are pressed at the same time, or all 3 buttons are pressed at the same time, the RGB LEDs will emit a variety of different colors, up to a maximum of 7.
Note
In fact, RGB LED can emit up to 16 million colors, but since Piper Make does not have a block to output PWM signal, here we just use the [turn pin() (ON/OFF)] block to make RGB LEDs show 7 colors.
How it Works?
You can think of this project as using three buttons to control the RGB LED, and setting three if judgment conditions to determine whether the three buttons are pressed or not. When the buttons are pressed, the levels of the corresponding pins are pulled high, causing the RGB LED to display different colors.
2.5 Drum Kit¶
For this project, let’s make a drum kit with three buttons and a slide switch. Now, play your own drums.
Wiring
When the slide switch is toggled to the right, GP12 is high; when toggled to the left, GP12 is low.
Each of the three buttons is connected to a pull-down resistor, GP13~GP15 are low by default; when the button is pressed, GP13~GP15 are high.
Code
Note
You can refer to the image below to write code by dragging and dropping.
Import
2.5_drum_kit.png
from the path ofeuler-kit\piper
. For detailed tutorials, please refer to Import the Code.
After connecting Pico, click the Start button and the code starts to run. Pressing different buttons or toggling the slide switch will produce different drum sounds, just like a drum kit.
Note
If you are using a computer, you will need to plug in headphones or audio to your computer to hear the sound emitted.
2.6 Smart Water Tank¶
In this project, we use a water level sensor module and a servo to simulate a smart water tank. The water level sensor is fixed inside the tank to measure the water level, and when the water level is below a threshold, the valve controlled by the servo is allowed to open to let water in.
Wiring
Pico has three GPIO pins that can use analog input, GP26, GP27, GP28. That is, analog channels 0, 1, and 2. In addition, there is a fourth analog channel, which is connected to the built-in temperature sensor and will not be introduced here.
S of water level sensor is connected to GP26(A0), + to VBUS, - pin to GND.
The orange wire (signal) of the servo is connected to GP15, the red wire (power) is connected to VBUS, and the brown wire (ground) is connected to GND.
Code
Note
You can refer to the image below to write code by dragging and dropping.
Import
2.6_water_tank.png
from the path ofeuler-kit\piper
. For detailed tutorials, please refer to Import the Code.
After connecting Pico, click the Start button and the code starts to run. When the water level is lower than 1/3 of the water level sensor, the servo rotates to 180 degrees to simulate the inlet opening; when the water level is higher than 1/3 of the water level sensor, the servo rotates to 0 degrees to imitate the inlet closing.
How it Works?
Set the rotation speed of pin15 (servo) to 15%.
[servo pin() set speed to ()%]:Used to set the rotation speed of the servo pin, the range is 0%~100%.
Reads the value of pin A0 and stores it in the variable [water_level].
[set (water_level) to]: Used to set the value of the variable, you need to create the variable from the Variables palette.
[read voltage from pin ()]: Used to read the voltage of the analog pins (A0~A2), the range is 0 ~ 3.3V.
Set the voltage threshold to 1. When the voltage of water level sensor is less than 1, let the servo rotate to 180° position, otherwise rotate to 0° position.
[servo pin () set angle to ()]: Set the angle of servo pin to, the range is 0 ~ 180°.
2.7 Swing Servo¶
In this project, we use a servo and a potentiometer to simulate a steering wheel. Rotating the potentiometer will drive the servo to turn together.
Wiring
The orange wire (signal) of the servo is connected to GP15, the red wire (power) is connected to VBUS, and the brown wire (ground) is connected to GND.
Potentiometer is a resistive element with 3 terminals, the 2 side pins are connected to 5V and GND, and the middle pin is connected to GP26(A0).
Code
Note
You can refer to the image below to write code by dragging and dropping.
Import
2.7_swing_servo.png
from the path ofeuler-kit\piper
. For detailed tutorials, please refer to Import the Code.
After connecting Pico, click the Start button and the code starts to run.
Turn the potentiometer and the servo will follow. To see it clearly, you can insert a rocker arm in the servo shaft.
How it Works?
Set the rotation speed of pin15 (servo) to 15%.
[servo pin() set speed to ()%]:Used to set the rotation speed of the servo pin, the range is 0%~100%.
Create a variable [angle], then read the voltage of A0. Use the [map value () from () to ()] block, map the voltage of A0 from 0 to 3.3V voltage range to 0 to 180°, and then use the mapped angle as the rotation angle of the servo.
[map value () from () to ()]: map a value from one range to another.
Note
The voltage of A0~A2 takes the range of 0~3.3V, even if your power supply is connected to VBUS (5V).
2.8 Light Intensity Display¶
In this project, we use a photoresistor and the LED Bar Graph to make a light intensity display, where the stronger the light is the more the number of the LED Bar Graph lights up.
Wiring
The LED Bar Graph consists of 10 LEDs, with the side with the label as the anode and the other side as the cathode.
The anode of the LED Bar Graph are connected to GP6~GP15. The cathode are connected to a 220 ohm resistor and then to GND.
Connect one end of the photoresistor to 3.3V and the other end to GP26 (A0). At the same time, GP26 needs to be connected to another 10K resistor to GND. This way, when the light is stronger, the resistance of the photoresistor decreases and the voltage of A0 increases.
Code
Note
You can refer to the image below to write code by dragging and dropping.
Import
2.8_light_intensity_display.png
from the path ofeuler-kit\piper
. For detailed tutorials, please refer to Import the Code.
After connecting Pico, click the Start button and the code starts to run.
When the light is stronger, more LEDs are lit on the LED Bar Graph.
If running the code does not light up properly, you can try flipping the led bar.
How it Works?
Set the pins of LED Bar Graph connected to GP6 ~ GP15.
Store the voltage value of A0 (GP26) read into the variable [photo_vol]. Use the [map value () from () to ()] block to map the variable [photo_vol] from 0 to 3.3V to 0 to 10 (the number of LEDs on the LED Bar Graph).
[map value () from () to ()]: map a value from one range to another.
2.9 Lucky Cat¶
In this project, we use pir and servo to make a lucky cat. The PIR Module is used to detect the visitors and servo is used to imitate the beckoning motion of the lucky cat.
Wiring
The orange wire (signal) of the servo is connected to GP15, the red wire (power) is connected to VBUS, and the brown wire (ground) is connected to GND.
The middle pin of the PIR module is connected to the GP3.
Code
Note
You can refer to the image below to write code by dragging and dropping.
Import
2.9_lucky_cat.png
from the path ofeuler-kit\piper
. For detailed tutorials, please refer to Import the Code.
After connecting Pico, click the Start button and the code starts to run.
When the PIR module detects a customer arrival, the servo oscillates back and forth five times and then stops.
How it Works?
Set the rotation speed of pin15 (servo) to 15%.
If GP14 is low, set the variable [prestate] to 0. When the variable [prestate] is 0 and GP14 is high (human detected), set the variable [prestate] to 1.
The purpose of this is to make the main code work only when the GP14 changes from low to high, and to respond only once if the PIR module keeps detecting people.
Make the servo cycle 5 times from 0 to 180 degrees rotation.
[repeat () times do]: Loop through the code inside the do block a finite number of times.
2.10 Flowing LEDs¶
The kit is equipped with a WS2812 RGB LED Strip, which can display colorful colors, and each LED can be independently controlled.
Here we try to use the tilt switch to control the flow direction of the LEDs on the WS2812 RGB LED Strip.
Wiring
Code
Note
You can refer to the image below to write code by dragging and dropping.
Import
2.10_flowing_led.png
from the path ofeuler-kit\piper
. For detailed tutorials, please refer to Import the Code.
After connecting Pico, click the Start button and the code starts to run.
When the tilt switch is placed vertically, it makes the LEDs on the WS2812 RGB LED Strip light up one by one in green, and when the tilt switch is placed horizontally, the LEDs light up one by one in the opposite direction in green.
Programming
Step 1: Use the [setup neopixel pin() pixels()] block in the Actions palette to initialize the WS2812 RGB LED Strip. 0 means the connected pin is GP0 and 8 means there are 8 RGB LEDs on the WS2812 RGB LED Strip.
Step 2: In the Variables palette, click the Create variable button to create a variable called i to represent the LEDs on the WS2812 RGB LED Strip.
Step 3: Set the initial value of variable i to 1 (the LED near the wires), then in [repeat forever] block, use [() mod ()] to set the value of i from 0 to 7. e.g. 1 mod 8 = 1… 8 mod 8 =0, 9 mod 8 =1, etc.
[() mod ()]: This is the modulo operator block, from the Loops palette, drop down [() = ()] to select mod.
Step 4: Set all neopixels to black to make all LEDs go off, then use [updates neopixels] to make this effect update to the WS2812 RGB LED Strip.
[set all neopixels to ()]: Use to set a color for all LEDs, there are 13*9 colors, the top right color is black to make LEDs to go off.
[updates neopixels]: Update the effect to the WS2812 RGB LED Strip.
Step 5: If pin14 is read high, let the LEDs on the WS2812 RGB LED Strip light up one by one in green, otherwise light up green one by one in the opposite direction.
[change () by ()]: Used to increase (positive) or decrease (negative) the value of a variable by a specific step.
2.11 Reversing System¶
For this project we used an ultrasonic module and an active buzzer to create a reversing alarm system. The ultrasonic module is used to detect the distance, and the buzzer emits different frequencies of alarm sounds depending on the distance.
Wiring
The Echo and Trig pins of the ultrasonic module are connected to GP15 at the same time, so that the ultrasonic module sends and receives signals from GP15.
The middle pin of the transistor connected to the buzzer is connected to GP14 through a 1kΩ resistor.
Code
Note
You can refer to the image below to write code by dragging and dropping.
Import
2.11_reversing_system.png
from the path ofeuler-kit\piper
. For detailed tutorials, please refer to Import the Code.
After connecting Pico, click the Start button and the code starts to run.
When the ultrasonic detection distance is less than 5cm, the buzzer emits a sharp sound (0.1s).
When the detection distance is between 5~10cm, the buzzer emits a slightly slow sound (0.5s).
When the detection distance is greater than 10cm, there is a sound prompt every 1 second.
How it Works?
Read the distance (in cm) of the ultrasonic detection, and store it in the variable [distance].
When distance is less than or equal to 5, set the variable intervals to 0.1s. The variable [intervals] is the interval between buzzer sounds.
When distance is greater than 5 and less than or equal to 10, set the [intervals] to 0.5s.
When distance is greater than 10, set the [intervals] time to 1s.
Finally, make the buzzer sound every [intervals] seconds.
2.12 Smart Fan¶
Here we make a temperature controlled smart fan with thermistor, L293D, motor, and power module. The fan rotates automatically when the set temperature is reached.
Wiring
Connect one end of the thermistor to GND and the other end to GP26 (A0). At the same time, GP26 needs to be connected to a 10K resistor to 5V. This way, the higher the temperature, the lower the voltage of A0.
L293D is a motor driver chip, EN is connected to 5V to make L293D work. 1A and 2A are the inputs connected to GP15 and GP14 respectively; 1Y and 2Y are the outputs connected to the two ends of the motor.
Y (output) is in phase with A (input), so if GP15 and GP14 are given different levels respectively, the direction of motor rotation can be changed.
Since DC motors require a high current, we use a power supply module to power the motor here for safety reasons.
Code
Note
You can refer to the image below to write code by dragging and dropping.
Import
2.12_smart_fan.png.png
from the path ofeuler-kit\piper
. For detailed tutorials, please refer to Import the Code.
After connecting Pico, click the Start button and the code starts to run.
Click CONSLE, you will see the current temperature in Celsius.
The fan starts spinning when it is above 25 degrees, and stops spinning when it is below 25 degrees.
Note
If the motor is still spinning after you click the Stop button, you need to reset the Run pin on the Pico with a wire to GND at this time, and then unplug this wire to run the code again.
This is because the motor is operating with too much current, which may cause the Pico to disconnect from the computer.
How it Works?
The voltage of A0 (GP26) is read and assigned to the variable [Vr].
These calculations convert the thermistor values into centigrade degree.
Note
Here is the relation between the resistance and temperature:
RT =RN expB(1/TK – 1/TN)
RT is the resistance of the NTC thermistor when the temperature is TK.
RN is the resistance of the NTC thermistor under the rated temperature TN. Here, the numerical value of RN is 10k.
TK is a Kelvin temperature and the unit is K. Here, the numerical value of TK is 273.15 + degree Celsius.
TN is a rated Kelvin temperature; the unit is K too. Here, the numerical value of TN is 273.15+25.
And B(beta), the material constant of NTC thermistor, is also called heat sensitivity index with a numerical value 3950.
exp is the abbreviation of exponential, and the base number e is a natural number and equals 2.7 approximately.
Convert this formula TK=1/(ln(RT/RN)/B+1/TN) to get Kelvin temperature that minus 273.15 equals degree Celsius.
This relation is an empirical formula. It is accurate only when the temperature and resistance are within the effective range.
When the temperature is higher than 25 degrees Celsius, set GP14 to ON and GP15 to OFF to make the motor rotate, or you can reverse their levels. When the temperature is lower than 25 degrees Celsius, set GP14 and GP15 both low to stop the motor.
2.13 Reaction Game¶
Here we use several buttons, buzzer and LEDs to make a reaction game.Press the referee button to start the game, the buzzer will also keep ringing to prompt the game to continue; press the 2 player buttons quickly respectively; when the referee button is pressed again, the game is over the buzzer stops working. At this point, look at the CONSOLE on Piper Make to see whose hand speed is fast.
Wiring
Define 2 buttons as player1 (GP14) and player2 (GP12), both have a pull-up resistor connected. When the buttons are pressed, GP14 and GP12 are each low.
Their indicators are connected to GP15 and GP13, and output high to light them up.
Define a referee button connected to GP10, when the button is pressed, GP10 goes low.
Active buzzer is connected to GP11, when GP11 output high, the buzzer will sound.
Code
Note
You can refer to the image below to write code by dragging and dropping.
Import
2.13_reaction_game.png
from the path ofeuler-kit\piper
. For detailed tutorials, please refer to Import the Code.
After connecting Pico, click the Start button and the code starts to run.
Press the referee button and the buzzer starts to sound (continuously), representing the start of the game.
At this point, press the player buttons separately and quickly, and the corresponding LEDs will light up.
When the referee button is pressed again, the buzzer stops, which means the game is over.
Click CONSOLE at this point to see who presses it more times.
How it Works?
GP10 is the referee button, when the referee button is not pressed it is high, the game has not started yet. When GP10 is low (referee button pressed), the game starts; set GP11 to high (buzzer), create variables and set initial values.
When flag equals to 1 for game start, then read the value of GP14 (player1); if player1 button is pressed, store the number of presses in variable [count1], and make the indicator of GP15 light up.
Read the number of presses of GP12(player2) in the same way.
Print the number of presses for player1 and player2 respectively.
When the referee button is pressed again, the buzzer stops working and the game ends.
FAQ¶
Arduino¶
- Code upload failed in Arduino IDE?
Check that your Pico is correctly recognised by the Arduino IDE, the port should be COMXX (Raspberry Pi Pico), for instructions please refer to 1.2 Setup the Raspberry Pi Pico.
Check that the Board(Raspberry Pi Pico) or port(COMXX (Raspberry Pi Pico))is selected correctly.
If your code is OK and you have selected the correct board and port, but the upload is still not successful. At this point you can click on the Upload icon again, when the progress below shows “Upload…”, unplug the USB cable, then press and hold the BOOTSEL button to plug it in and the code will be uploaded successfully.
MicroPython¶
- How to open and run the code?
For detailed tutorials, please refer to Open and Run Code Directly.
- How to upload library to Raspberry Pi Pico?
For detailed tutorials, please refer to Upload the Libraries to Pico.
- NO MicroPython(Raspberry Pi Pico) Interpreter Option on Thonny IDE?
Check that your Pico is plugged into your computer via a USB cable.
Check that you have installed MicroPython for Pico (1.3 Install MicroPython Firmware on Your Pico).
The Raspberry Pi Pico interpreter is only available in version 3.3.3 or higher version of Thonny. If you are running an older version, please update (1.2 Install and Introduce Thonny IDE).
Plug in/out the micro USB cable sveral times.
- Cannot open Pico code or save code to Pico via Thonny IDE?
Check that your Pico is plugged into your computer via a USB cable.
Check that you have selected the Interpreter as MicroPython (Raspberry Pi Pico).
- Can Raspberry Pi Pico be used on Thonny and Arduino at the same time?
NO, you need to do some different operations.
If you used it on Arduino first, and now you want to use it on Thonny IDE, you need to 1.3 Install MicroPython Firmware on Your Pico on it.
If you used it on Thonny first, and now you want to use it on Arduino IDE, you need to 1.2 Setup the Raspberry Pi Pico.
- If your computer is win7 and pico cannot be detected.
Download the USB CDC driver from http://aem-origin.microchip.com/en-us/mindi-sw-library?swsearch=Atmel%2520USB%2520CDC%2520Virtual%2520COM%2520Driver
Unzip the
amtel_devices_cdc.inf
file to a folder namedpico-serial
.Change the name of
amtel_devices_cdc.inf
file topico-serial.inf
.Open/edit the
pico-serial.inf
in a basic editor like notepadRemove and replace the lines under the following headings:
[DeviceList] %PI_CDC_PICO%=DriverInstall, USB\VID_2E8A&PID_0005&MI_00 [DeviceList.NTAMD64] %PI_CDC_PICO%=DriverInstall, USB\VID_2E8A&PID_0005&MI_00 [DeviceList.NTIA64] %PI_CDC_PICO%=DriverInstall, USB\VID_2E8A&PID_0005&MI_00 [DeviceList.NT] %PI_CDC_PICO%=DriverInstall, USB\VID_2E8A&PID_0005&MI_00 [Strings] Manufacturer = "ATMEL, Inc." PI_CDC_PICO = "Pi Pico Serial Port" Serial.SvcDesc = "Pi Pico Serial Driver"
Close and save and make sure your retain the name as pico-serial.inf
Go to your pc device list, find the pico under Ports, named something like CDC Device. A yellow exclamation mark indicates it.
Right click on the CDC Device and update or install driver choosing the file you created from the location you saved it at.
Piper Make¶
- How to set up the Pico on Piper Make?
For detailed tutorials, please refer to 1.1 Set up the Pico.
- How to download or import code?
For detailed tutorials, please refer to 1.3 How to Save or Import Code?.
- How to connect to Pico?
For detailed tutorials, please refer to 2. Connect to Pico.
How to re-burn the firmware for ESP8266 module?¶
1. Download firmwre and burn-in tool
After unzipping, you will see 3 files.

esp8266-uart-wsserver-v1.0.2.bin
: The firmware to burn to the ESP8266 module.esptool.exe
: This is a command-line utility for Windows.install.bat
: This is the command package for Windows system, double click this file will run all the commands inside the file.picoprobe.uf2
: This file allows a Pico to act as a USB → SWD and UART converter.
2. Set Pico as a USB → SWD and UART converter
Hold down the BOOTSEL button and connect the Pico to your computer with a Micro USB cable.
Once your Pico is mounted as a Mass Storage Device called RPI-RP2, release the BOOTSEL button.
Go to the Downloads folder and find the file you just downloaded, then drag
picoprobe.uf2
to the RPI-RP2 storage drive.The Pico will reboot and disappear from the File Manager, then Pico’s USB will be recognized as a serial port and you can see it in the Device Manager.
Replug the Raspberry Pi Pico (without holding down the BOOTSEL button) to get ready for the next steps.
3. Build the circuit
Connect ESP8266 module and Raspberry Pi Pico.
4. Burn the firmware
Follow the steps below to burn the firmware if you are using Windows.
Double click
install.bat
to start the firmware burning. If you see the following prompt, the firmware has been installed successfully.Note
If the burn-in fails, please check the following points.
If it does not work the first time, close the window and open
install.bat
again.Reset the ESP8266 module by inserting the RST to GND and then unplugging it.
Check if the wiring is correct.
Make sure the port is not occupied.
To burn the firmware, follow these steps if you are using a Mac OS system.
Use the following commands to install Esptool. Esptool is a Python-based, open-source, platform-independent utility to communicate with the ROM bootloader in Espressif chips.
python3 -m pip install --upgrade pip python3 -m pip install esptool
If esptool is properly installed, it will output a message such as [usage: esptool] if you run
python3 -m esptool
.Open a terminal and use the
cd
command to go into the firmware folder you just downloaded, then run the following command to erase the existing firmware and re-burn the new firmware.esptool.exe --chip esp8266 --before no_reset_no_sync erase_flash esptool.exe --chip esp8266 --before no_reset_no_sync write_flash 0 "esp8266-uart-wsserver-v1.0.2.bin"
If you get the prompt message like this, the firmware is burned successfully.
Note
If the burn-in fails, please check the following points.
Reset the ESP8266 module by inserting the RST to GND and then unplugging it.
Check if the wiring is correct.
Make sure the port is not occupied.
5. Test after burning firmware
Note
If you confirm that the firmware has been burned successfully and you don’t want to test it again, you can also go ahead and finish the project - 1.1 First-time Use the APP.
The Raspberry Pi Pico here uses the serial firmware, you need to 1.3 Install MicroPython Firmware on Your Pico before you can run the MicroPython script.
On the basis of the original wiring, leave IO0 and RST hanging.
As Thonny doesn’t come with a serial port tool, you’ll need to use the Arduino IDE’s serial monitor or another serial port tool to test it. The Arduino IDE 2.0 will be used here, open it and select the port. Note that your port is different from mine.
Click on the Serial Monitor icon to open it and select the display mode (New line) and baud rate (115200 baud).
Type
SET+RESET
, and pressCtrl+Enter
to send this command. Once the firmware has been burned successfully, you will see a string of characters + OK.At this point you can go ahead and finish the project - 1.1 First-time Use the APP.
Note
The Raspberry Pi Pico here uses the serial firmware, you need to 1.3 Install MicroPython Firmware on Your Pico before you can run the MicroPython script.
Copyright Notice¶
All contents including but not limited to texts, images, and code in this manual are owned by the SunFounder Company. You should only use it for personal study,investigation, enjoyment, or other non-commercial or nonprofit purposes, under therelated regulations and copyrights laws, without infringing the legal rights of the author and relevant right holders. For any individual or organization that uses these for commercial profit without permission, the Company reserves the right to take legal action.