【Digi-Jet Follow me Issue 3】Comprehensive Task Submission
[Copy link]
This post was last edited by xinmeng_wit on 2023-12-14 21:02
Part 1 (3-5 minute short video)
Part II (Task/Project Summary Report)
Required Task 1: Use MicroPython system
Task objectives: Be familiar with the basic operations of Seeed Studio XIAO ESP32C3 development board, install esptool, and flash the MicroPython system to the development board to complete the operation of the entry program.
The main task of this task is to learn how to build a Micro Python development environment and be able to run the first Micro Python program.
Including burning Micro Python firmware and installing PC software.
ESP32C3 supports development using MicroPython, but the factory firmware is not MicroPython firmware.
Therefore, you need to burn the development board into Micro Python firmware first.
According to official information, esptool can be used to burn MicroPython firmware.
The brief steps for setting up the environment are as follows. For a more detailed tutorial on setting up the environment, please see the post: https://en.eeworld.com/bbs/thread-1264550-1-1.html
1. Install esptool. If you already have esptool on your computer, you can skip this step.
2. Download MicroPython firmware from:https://micropython.org/download/esp32c3/
3. Put the downloaded firmware into the esptool tool directory for burning
Run the cmd command line in the esptool directory
And run the following command:
esptool.exe --chip esp32c3 --port COM10 --baud 921600 --before default_reset --after hard_reset --no-stub write_flash --flash_mode dio --flash_freq 80m 0x0 esp32c3-usb-20230426-v1.20.0.bin
Among them, COM10 needs to be replaced with the serial port number actually used by the computer, and esp32c3-usb-20230426-v1.20.0.bin needs to be replaced with the actual one used.
After the download is completed normally, restart the development board and the Micro Python firmware will be running.
4. Run the first MicroPython program
There are many tools for running MicroPython code. I am used to using Thonny for MicroPython development. There is nothing special about the installation of Thonny software. You can install it according to the installation method of ordinary software. I will not introduce it here.
Next, we will use Thonny to connect to ESP32C3 and run the first Hello World program.
Experience: The process of downloading MicroPython firmware is relatively complicated. You must use the esptool function to download it. I hope that a simpler way can be used to download the firmware in the future, such as USB drag and drop mode.
Required Task 2: Drive the OLED screen on the expansion board
Mission objective: Use OLED screen to display text, graphics, pictures and other information
According to the information on seeed's official website, a 0.96-inch OLED screen with an I2C interface is integrated on the XIAO expansion board, and the pins used are GPIO6 and GPIO7.
For OLED drivers, there are already many open source libraries written by experts on the Internet, so I won’t reinvent the wheel here.
Because the driver chip of the OLED screen is SSD1306, you can find the micropython library of ssd1306 on the Internet. There are so many of them that you can use any one.
Here is the direct link:
Text and graphic display is relatively simple, and can be achieved by directly calling the library function of ssd1306
For example, the following code displays text:
# 显示文字
oled.fill(0) # Clear the screen
oled.text("Hello, ESP32C3!", 10, 15)
oled.text("EEWORLD!", 30, 40)
oled.text("TEXT TESET...", 20, 55)
oled.show() # Show the text
time.sleep(2)
Graphic display can also directly call the oled library function:
#显示图形
oled.fill(0) # Clear the screen
oled.line(0, 0, 100, 100, 1) # 画线
oled.rect(60, 10, 50, 30, 1) # 画矩形
oled.show()
time.sleep(2)
The last step is image display, which is a little more complicated and involves simple image processing.
The first step is to prepare a picture within 128*64, because the screen pixel size of OLED is 128*64, so it cannot exceed this size
The second step is to set the picture to a monochrome picture, that is, a black and white picture.
The third step is to convert the image into .pbm format and upload it to the ESP32C3 device for backup.
The URL for image format conversion is: https://convertio.co/zh/
After completion:
The fourth step is to write code to display the pictures prepared above. The famebuf library will be used in the code. Students who are familiar with this library can take a look at the detailed introduction of this library.
# 显示图片
with open('MicroPython.pbm', 'rb') as f: # 读取图片文件
f.readline() # 读取文件第一行,图片格式
width, height = [int(v) for v in f.readline().split()] # 读取图片像素大小
data = bytearray(f.read()) # 读取图片数据
f.close()
fbuf = framebuf.FrameBuffer(data, width, height, framebuf.MONO_HLSB) # 指定图片数据,大小及格式
oled.fill(0) # 清屏
oled.blit(fbuf, 0, 0) # 数据放入缓冲区
oled.show() # 显示
time.sleep(2)
oled
Experience: The use of OLED screen is relatively simple with the support of ssd1306 library. It is not difficult to display English text, graphics, and pictures.
However, it cannot directly support the display of Chinese. Chinese display needs to be processed separately. If there is a need for Chinese display, it is necessary to study how to display Chinese.
Required Task 3: Control the buzzer to play music
Task objective: Learn to use the buzzer and be able to make the buzzer play the corresponding music according to the music score
A buzzer is integrated on the XIAO expansion board. According to the official information of seeed, the buzzer is connected to the A3 pin on the expansion board, and the corresponding pin of ESP32C3 is GPIO5.
Then, the pins can be configured according to the pin information.
Since we need to use the buzzer to emit sounds of different frequencies, we use the pwm function here to adjust the frequency.
GPIO5 pin initialization:
from machine import PWM,Pin
# Buzzer settings
buzzer = PWM(Pin(5),freq=1024,duty=512)
The initial frequency is specified as 1024Hz, and the duty cycle parameter is 512, i.e. 50% (range 0~1023). The initial freq and duty can be specified at will, because they will be dynamically adjusted according to the notes later.
After the initialization is completed, the buzzer can make a sound, but the sound is fixed.
In order for the buzzer to play music according to the music score, the music score must be quantified into numbers that can be recognized by the code. For the music score, there are basically two parameters that can be quantified, one is frequency and the other is duration.
Each note (1, 2, 3, 4, 5, 6, 7) corresponds to a frequency. These frequencies are known and relevant information can be found on the Internet.
One more thing to add is that each note is divided into treble, middle and bass, corresponding to different frequencies, that is, each note can correspond to three frequencies, which depends on the music score.
As for the length, it needs to correspond to the actual music score, as each song is different.
Below is the simplification of the song "A Laugh in the Sea". Based on this simplification, we can know the frequency and duration of each note.
Quantized frequency and duration:
X0 = -1 # 休止符
D5 = 262 # 低音(5)
D6 = 294 # 低音(6)
Z1 = 349 # 中音(1)
Z2 = 392 # 中音(2)
Z3 = 440 # 中音(3)
Z5 = 523 # 中音(5)
Z6 = 587 # 中音(6)
# 频率
tune = [ Z6,Z5,Z3,Z2,Z1, Z3,Z2,Z1,D6,D5,X0, D5,D6,D5,D6,Z1,Z2,Z3,Z5, Z6,Z5,Z3,Z2,Z1,Z2,
Z6,Z6,Z5,Z3,Z2,Z1, Z3,Z2,Z1,D6,D5,X0, D5,D6,D5,D6,Z1,Z2,Z3,Z5, Z6,Z5,Z3,Z2,Z1,Z2,
Z6,Z6,Z5,Z3,Z2,Z1, Z3,Z2,Z1,D6,D5,X0, D5,D6,D5,D6,Z1,Z2,Z3,Z5, Z6,Z5,Z3,Z2,Z1,Z2,
Z6,Z6,Z5,Z3,Z2,Z1, Z3,Z2,Z1,D6,D5,X0, D5,D6,D5,D6,Z1,Z2,Z3,Z5, Z6,Z5,Z3,Z2,Z1
]
# 时长
duration = [ 0.75,0.25,0.5,0.5,2, 0.75,0.25,0.5,0.5,1.8,0.2, 0.75,0.25,0.75,0.25,0.75,0.25,0.5,0.5, 0.75,0.25,0.5,0.25,0.25,2,
0.75,0.25,0.25,0.5,0.5,2, 0.75,0.25,0.5,0.5,1.8,0.2, 0.75,0.25,0.75,0.25,0.75,0.25,0.5,0.5, 0.75,0.25,0.5,0.25,0.25,2,
0.75,0.25,0.25,0.5,0.5,2, 0.75,0.25,0.5,0.5,1.8,0.2, 0.75,0.25,0.75,0.25,0.75,0.25,0.5,0.5, 0.75,0.25,0.5,0.25,0.25,2,
0.75,0.25,0.25,0.5,0.5,2, 0.75,0.25,0.5,0.5,1.8,0.2, 0.75,0.25,0.75,0.25,0.75,0.25,0.5,0.5, 0.75,0.25,0.5,0.5,2
]
By setting the frequency and duration of PWM according to these two tables, the buzzer can play the song "A Laugh in the Ocean".
The following is a program for dynamically setting pwm parameters based on these two tables, which is derived from the seeed official routine and slightly modified:
def buzzer_play():
total_notes = len(tune)
for i in range(total_notes):
current_note = tune[i]
wait = duration[i]
if current_note != -1:
buzzer.duty(512) # Set duty cycle for sound
buzzer.freq(current_note) # Set frequency of the note
else:
buzzer.duty(0) # Turn off the sound
time.sleep_ms(int(wait * 800))
buzzer.duty(0) # Turn off the sound
In addition, time.sleep_ms(int(wait * 800)) in the code is used to control the playback speed, which can be adjusted according to actual conditions.
In fact, to be more precise, this place actually controls the length of each beat of the music.
buzzer
Experience: Playing music with a buzzer actually means controlling the frequency and duration of the buzzer's sound. Once you understand this, playing music is very simple.
Must-do Task 4: Connect to a WiFi network
Mission objective: Use the development board to connect to the wifi network and access the Internet
The biggest advantage of ESP32 is networking. With MicroPython, networking becomes even more convenient.
It is really useful to use the network library for networking
Call the interface network.WLAN (network.STA_IF) to set the network mode
Call the interface station.scan() to scan for wifi hotspots
Call the interface station.connect(wifi_ssid, wifi_password) to connect to the wifi network
Yes, networking is that easy.
import network
import utime as time
# Network settings
wifi_ssid = "CMCC-eP9M"
wifi_password = "y634ybku"
def scan_and_connect():
station = network.WLAN(network.STA_IF)
station.active(True)
print("Scanning for WiFi networks, please wait...")
for ssid, bssid, channel, RSSI, authmode, hidden in station.scan():
print("* {:s}".format(ssid))
print(" - Channel: {}".format(channel))
print(" - RSSI: {}".format(RSSI))
print(" - BSSID: {:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}".format(*bssid))
print()
while not station.isconnected():
print("Connecting...")
station.connect(wifi_ssid, wifi_password)
time.sleep(10)
print("Connected!")
print("My IP Address:", station.ifconfig()[0])
After connecting to the Internet, you can get some information on the Internet, such as time, weather and so on.
The urequests library makes it easy to request information from the Internet
Get the time, date and time zone:
import urequests
import ujson
import oled
url = "http://worldtimeapi.org/api/timezone/Asia/Shanghai"
def get_date_time():
# Perform HTTP GET request on a non-SSL web
response = urequests.get(url)
# Check if the request was successful
if response.status_code == 200:
# Parse the JSON response
data = ujson.loads(response.text)
# Extract the "datetime" field for New York
ny_datetime = data["datetime"]
# Split the date and time components
date_part, time_part = ny_datetime.split("T")
# Get only the first two decimal places of the time
time_part = time_part[:8]
# Get the timezone
timezone = data["timezone"]
print("Date:\r\n" + date_part)
print("Time:\r\n" + time_part)
print("Timezone:\r\n" + timezone)
oled.oled.fill(0)
oled.oled.text("Date:", 0, 0)
oled.oled.text(date_part, 0, 10)
oled.oled.text("Time:", 0, 20)
oled.oled.text(time_part, 0, 30)
oled.oled.text("Timezone:", 0, 40)
oled.oled.text(timezone, 0, 50)
# Update the display
oled.oled.show()
else:
print("Failed to get the time")
The same is true for getting weather information:
import urequests
import ujson
import oled
url = 'https://api.seniverse.com/v3/weather/now.json?key={}&location={}&language=en&unit=c'
key = 'your key'
city = 'shanghai'
def get_weather():
result1=urequests.get(url.format(key, city))
j1=ujson.loads(result1.text)
city_name = "City:" + j1['results'][0]['location']['name']
weather = "Weather:" + j1['results'][0]['now']['text']
temp = "Temp:" + j1['results'][0]['now']['temperature'] + " C"
oled.oled.fill(0)
oled.oled.text(city_name, 0, 0)
# oled.oled.text(date_part, 0, 10)
oled.oled.text(weather, 0, 20)
# oled.oled.text(time_part, 0, 30)
oled.oled.text(temp, 0, 40)
# oled.oled.text(timezone, 0, 50)
# Update the display
oled.oled.show()
print(j1['results'][0]['location']['name'],end=' ')
print(j1['results'][0]['now']['text'],end=' ')
print(j1['results'][0]['now']['temperature'],end='℃ ')
print(j1['results'][0]['last_update'])
wifi
Experience: The networking application is very simple. Sometimes it takes some time to connect to the network. It may be a signal problem.
Required Task 5: Using External Sensors
Task objective: Connect the ambient light sensor and the temperature and humidity sensor, obtain the sensor values, and convert them into real physical quantities.
This time, follow me has selected two external sensor modules, namely the temperature and humidity sensor module AHT20 and the ambient light sensor module.
The former can measure the temperature and humidity of the environment and is an I2C interface, while the latter can measure the light intensity of the environment and is an analog interface.
It should be noted that AHT20 has a ready-made library that can be used. You only need to call the temperature/humidity reading interface to obtain the temperature/humidity, which is very easy to use.
AHT20 library download address:
The ambient light intensity is measured through the AD port. By calling the ADC reading interface, the digital quantity or voltage value can be obtained, which is also very simple.
Temperature and humidity readings:
import utime
from machine import Pin, I2C
import oled
import ahtx0
i2c = I2C(scl=Pin(7), sda=Pin(6))
# Create the sensor object using I2C
sensor = ahtx0.AHT10(i2c)
def get_temp_humi():
print("\nTemperature: %0.2f C" % sensor.temperature)
print("Humidity: %0.2f %%" % sensor.relative_humidity)
oled.oled.fill(0)
oled.oled.text("Temp: %0.2f C" % sensor.temperature, 0, 20)
oled.oled.text("Humi: %0.2f %%" % sensor.relative_humidity, 0, 40)
# Update the display
oled.oled.show()
Light intensity reading:
from machine import ADC,Pin
import utime
import oled
adc = ADC(2,atten = ADC.ATTN_11DB)
def get_light_voltage():
voltage = adc.read_uv() / 1000000
print("{}v ".format(voltage))
oled.oled.fill(0)
oled.oled.text(f'Voltage:{voltage:.3f}V', 0, 30)
# Update the display
oled.oled.show()
light_temp_humi
Experience: Temperature and humidity generally do not change very quickly, so the reading interval should be as long as possible. High-frequency reading is meaningless and not accurate enough.
Optional Task 6: Choose 1 out of 3 (optional, not required): Choose any one of the following task requirements to complete, or you can customize tasks of similar difficulty and complete them based on your own interests, hobbies and abilities.
■ Sub-task 1: Find the location of the WiFi transmitter
■ Sub-task 2: Temperature and humidity data logger
■ Sub-task 3: Light reminder
Mission objective: Realize the light-on reminder
The light reminder actually uses the ambient light sensor to detect the intensity of the surrounding ambient light. If the light is very dark, the detected light intensity will be very low, and if the light is very bright, the detected light intensity will be very high. In this way, a reminder can be given in very dark light conditions to remind the user to turn on the light. The alarm modes include screen display and sound reminder.
With the sensor usage in the previous Task 5 as a basis, the light-on reminder is actually very simple. After obtaining the sensor data, it can be implemented by simply performing simple judgment and processing.
from machine import ADC,Pin
import utime
import oled
import buzzer
VOLTAGE_THRESHOLD = 50
adc = ADC(2,atten = ADC.ATTN_11DB)
def light_check():
voltage = adc.read_uv() / 1000 # 获取电压mv
print("{}mv ".format(voltage))
if voltage < VOLTAGE_THRESHOLD:
buzzer.buzzer_alarm_on()
# oled.oled.fill(0)
oled.oled.text('Dim Light', 24, 50)
# Update the display
# oled.oled.show()
else:
buzzer.buzzer_alarm_off()
oled.oled.show()
When the single voltage is less than 50mv, it is considered that the light is relatively dim, and "Dim Light" is displayed. At the same time, the buzzer sounds to remind you that the light is too dim and you need to turn on the light.
In addition to this function, it also provides a circular display of AHT temperature and humidity and weather information obtained by wifi.
Dim_Light
Experience: Turning on the light reminder may be the simplest task among the three optional tasks. It only requires a little processing after obtaining the sensor data.
Of course, these three tasks are not very difficult with the support of MicroPython.
Part 3 (Compilable and downloadable code)
https://download.eeworld.com.cn/detail/xinmeng_wit/630259
|