1204 views|10 replies

46

Posts

0

Resources
The OP
 

[Digi-Key Follow me Issue 1] + Task 2: Driving peripherals [Copy link]

 
 

1. Hardware Construction

I found a 1*40pin 2.54mm pin header, split it in two, and soldered it to the development board so that it can be inserted into the expansion board, as shown in Figure 1.

Figure 1

In this way, we can connect peripherals such as LED, OLED display, buzzer, etc. to the corresponding ports for testing.

2. Driving RGB LED Stick (10-WS2813 Mini)

视频3

The Grove-RGB LED Stick (10-WS2813 Mini) can operate in a voltage range of 3.3V to 5V, supports continuous transmission of signal breakpoints , and when one LED is damaged, the other LEDs can work normally. It has a built-in control circuit with 265 gray levels, 3535 components, and dual signal wires.

Key Features:

  • The control circuit and RGB chip are integrated into a 3535 component to form an externally controlled pixel.
  • Intelligent reverse connection protection.
  • The built-in signal shaping circuit is used to achieve signal waveform shaping, and the waveform is not distorted.
  • The grayscale level of each pixel is 256, realizing "256*256*256=16777216" full-color display with a refresh rate of 2KHz.
  • Serial cascade interface, data reception and decoding rely on only one signal line.
  • Dual signal line version, signal breakpoint continuous transmission.
  • There is no additional circuit for the transmission signal between any two points with a distance greater than 5M.
  • When the refresh rate is 30fps, the number of cascades is at least 1024 pixels.
  • The data transmission speed can reach up to 800Kbps.
  • Good color consistency and reliability, high cost performance.

As long as two consecutive lights on the light stick are not broken, the other lights can light up normally, as shown in Figure 2.

Figure 2

链接已隐藏,如需查看请登录或者注册
of WS2812 LEDs, we can modify it to write a light bar with 10 lamp beads. The modified code is as follows:

# Example using PIO to drive a set of 10-WS2813 LEDs.

import array, time
from machine import Pin
import rp2

# Configure the number of WS2813 LEDs.
NUM_LEDS = 10
PIN_NUM = 16
brightness = 0.2

@rp2.asm_pio(sideset_init=rp2.PIO.OUT_LOW, out_shiftdir=rp2.PIO.SHIFT_LEFT, autopull=True, pull_thresh=24)
def ws2813():
    T1 = 2
    T2 = 5
    T3 = 3
    wrap_target()
    label("bitloop")
    out(x, 1)               .side(0)    [T3 - 1]
    jmp(not_x, "do_zero")   .side(1)    [T1 - 1]
    jmp("bitloop")          .side(1)    [T2 - 1]
    label("do_zero")
    nop()                   .side(0)    [T2 - 1]
    wrap()


# Create the StateMachine with the ws2813 program, outputting on pin
sm = rp2.StateMachine(0, ws2813, freq=8_000_000, sideset_base=Pin(PIN_NUM))

# Start the StateMachine, it will wait for data on its FIFO.
sm.active(1)

# Display a pattern on the LEDs via an array of LED RGB values.
ar = array.array("I", [0 for _ in range(NUM_LEDS)])

##########################################################################
def pixels_show():
    dimmer_ar = array.array("I", [0 for _ in range(NUM_LEDS)])
    for i,c in enumerate(ar):
        r = int(((c >> 8) & 0xFF) * brightness)
        g = int(((c >> 16) & 0xFF) * brightness)
        b = int((c & 0xFF) * brightness)
        dimmer_ar[i] = (g<<16) + (r<<8) + b
    sm.put(dimmer_ar, 8)
    time.sleep_ms(10)

def pixels_set(i, color):
    ar[i] = (color[1]<<16) + (color[0]<<8) + color[2]

def pixels_fill(color):
    for i in range(len(ar)):
        pixels_set(i, color)

def color_chase(color, wait):
    for i in range(NUM_LEDS):
        pixels_set(i, color)
        time.sleep(wait)
        pixels_show()
    time.sleep(0.2)

def wheel(pos):
    # Input a value 0 to 255 to get a color value.
    # The colours are a transition r - g - b - back to r.
    if pos < 0 or pos > 255:
        return (0, 0, 0)
    if pos < 85:
        return (255 - pos * 3, pos * 3, 0)
    if pos < 170:
        pos -= 85
        return (0, 255 - pos * 3, pos * 3)
    pos -= 170
    return (pos * 3, 0, 255 - pos * 3)


def rainbow_cycle(wait):
    for j in range(255):
        for i in range(NUM_LEDS):
            rc_index = (i * 256 // NUM_LEDS) + j
            pixels_set(i, wheel(rc_index & 255))
        pixels_show()
        time.sleep(wait)

BLACK = (0, 0, 0)
RED = (255, 0, 0)
YELLOW = (255, 150, 0)
GREEN = (0, 255, 0)
CYAN = (0, 255, 255)
BLUE = (0, 0, 255)
PURPLE = (180, 0, 255)
WHITE = (255, 255, 255)
COLORS = (BLACK, RED, YELLOW, GREEN, CYAN, BLUE, PURPLE, WHITE)

print("fills")
for color in COLORS:
    pixels_fill(color)
    pixels_show()
    time.sleep(0.2)

print("chases")
for color in COLORS:
    color_chase(color, 0.01)

print("rainbow")
rainbow_cycle(0)

Connect the device to the computer, run neopixel_ring_10.py in the Mu software, connect the light board to the D16 port, and you will see the light bar as shown in Video 3.

The Mu port output is shown in Figure 3.

Figure 3

Figure 4

3. OLED display

Grove - OLED Display 0.96" (SSD1315) The Grove-OLED Display 0.96" (SSD1315) is a monochrome (white) 128×64 pixel passive display matrix module with Grove I2C interface. The Grove-OLED Display 0.96" has better performance and is a quarter of the price.

feature

  • Monochrome clear display: While inheriting the characteristics of high contrast, high brightness and low power consumption, the display effect has been improved
  • Industrial-grade operating temperature: wide operating temperature range: -40°C~+85°C
  • High cost performance: The monitor adopts the upgraded SSD1315 chip, which has stronger performance and lower price.
  • Grove Unified Socket: This product ensures "plug and play" and can be used in various applications.

When modifying the code in the demo, Mu does not know how to import the ssd1306.py driver, resulting in the problem shown in Figure 5 below. (I still did not understand it after the live broadcast, but the forum friends shared and supplemented it and I understood it instantly)

Figure 5

Then add the OLED driver directly to the file header, as follows:

# 在这里写上你的代码 :-)
 # Display Image & text on I2C driven ssd1315 OLED display
from machine import Pin, I2C
from micropython import const
import framebuf
#from ssd1306 import SSD1306_I2C
#import framebuf
# register definitions
SET_CONTRAST = const(0x81)
SET_ENTIRE_ON = const(0xA4)
SET_NORM_INV = const(0xA6)
SET_DISP = const(0xAE)
SET_MEM_ADDR = const(0x20)
SET_COL_ADDR = const(0x21)
SET_PAGE_ADDR = const(0x22)
SET_DISP_START_LINE = const(0x40)
SET_SEG_REMAP = const(0xA0)
SET_MUX_RATIO = const(0xA8)
SET_COM_OUT_DIR = const(0xC0)
SET_DISP_OFFSET = const(0xD3)
SET_COM_PIN_CFG = const(0xDA)
SET_DISP_CLK_DIV = const(0xD5)
SET_PRECHARGE = const(0xD9)
SET_VCOM_DESEL = const(0xDB)
SET_CHARGE_PUMP = const(0x8D)

# Subclassing FrameBuffer provides support for graphics primitives
# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html
class SSD1306(framebuf.FrameBuffer):
    def __init__(self, width, height, external_vcc):
        self.width = width
        self.height = height
        self.external_vcc = external_vcc
        self.pages = self.height // 8
        self.buffer = bytearray(self.pages * self.width)
        super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)
        self.init_display()

    def init_display(self):
        for cmd in (
            SET_DISP | 0x00,  # off
            # address setting
            SET_MEM_ADDR,
            0x00,  # horizontal
            # resolution and layout
            SET_DISP_START_LINE | 0x00,
            SET_SEG_REMAP | 0x01,  # column addr 127 mapped to SEG0
            SET_MUX_RATIO,
            self.height - 1,
            SET_COM_OUT_DIR | 0x08,  # scan from COM[N] to COM0
            SET_DISP_OFFSET,
            0x00,
            SET_COM_PIN_CFG,
            0x02 if self.width > 2 * self.height else 0x12,
            # timing and driving scheme
            SET_DISP_CLK_DIV,
            0x80,
            SET_PRECHARGE,
            0x22 if self.external_vcc else 0xF1,
            SET_VCOM_DESEL,
            0x30,  # 0.83*Vcc
            # display
            SET_CONTRAST,
            0xFF,  # maximum
            SET_ENTIRE_ON,  # output follows RAM contents
            SET_NORM_INV,  # not inverted
            # charge pump
            SET_CHARGE_PUMP,
            0x10 if self.external_vcc else 0x14,
            SET_DISP | 0x01,
        ):  # on
            self.write_cmd(cmd)
        self.fill(0)
        self.show()

    def poweroff(self):
        self.write_cmd(SET_DISP | 0x00)

    def poweron(self):
        self.write_cmd(SET_DISP | 0x01)

    def contrast(self, contrast):
        self.write_cmd(SET_CONTRAST)
        self.write_cmd(contrast)

    def invert(self, invert):
        self.write_cmd(SET_NORM_INV | (invert & 1))

    def show(self):
        x0 = 0
        x1 = self.width - 1
        if self.width == 64:
            # displays with width of 64 pixels are shifted by 32
            x0 += 32
            x1 += 32
        self.write_cmd(SET_COL_ADDR)
        self.write_cmd(x0)
        self.write_cmd(x1)
        self.write_cmd(SET_PAGE_ADDR)
        self.write_cmd(0)
        self.write_cmd(self.pages - 1)
        self.write_data(self.buffer)


class SSD1306_I2C(SSD1306):
    def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):
        self.i2c = i2c
        self.addr = addr
        self.temp = bytearray(2)
        self.write_list = [b"\x40", None]  # Co=0, D/C#=1
        super().__init__(width, height, external_vcc)

    def write_cmd(self, cmd):
        self.temp[0] = 0x80  # Co=1, D/C#=0
        self.temp[1] = cmd
        self.i2c.writeto(self.addr, self.temp)

    def write_data(self, buf):
        self.write_list[1] = buf
        self.i2c.writevto(self.addr, self.write_list)


class SSD1306_SPI(SSD1306):
    def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
        self.rate = 10 * 1024 * 1024
        dc.init(dc.OUT, value=0)
        res.init(res.OUT, value=0)
        cs.init(cs.OUT, value=1)
        self.spi = spi
        self.dc = dc
        self.res = res
        self.cs = cs
        import time

        self.res(1)
        time.sleep_ms(1)
        self.res(0)
        time.sleep_ms(10)
        self.res(1)
        super().__init__(width, height, external_vcc)

    def write_cmd(self, cmd):
        self.spi.init(baudrate=self.rate, polarity=0, phase=0)
        self.cs(1)
        self.dc(0)
        self.cs(0)
        self.spi.write(bytearray([cmd]))
        self.cs(1)

    def write_data(self, buf):
        self.spi.init(baudrate=self.rate, polarity=0, phase=0)
        self.cs(1)
        self.dc(1)
        self.cs(0)
        self.spi.write(buf)
        self.cs(1)

WIDTH  = 128                                            # oled display width
HEIGHT = 32                                             # oled display height

i2c = I2C(0)                                            # Init I2C using I2C0 defaults, SCL=Pin(GP9), SDA=Pin(GP8), freq=400000
print("I2C Address      : "+hex(i2c.scan()[0]).upper()) # Display device address
print("I2C Configuration: "+str(i2c))                   # Display I2C config


oled = SSD1306_I2C(WIDTH, HEIGHT, i2c)                  # Init oled display

# Raspberry Pi logo as 32x32 bytearray
buffer = bytearray(b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|?\x00\x01\x86@\x80\x01\x01\x80\x80\x01\x11\x88\x80\x01\x05\xa0\x80\x00\x83\xc1\x00\x00C\xe3\x00\x00~\xfc\x00\x00L'\x00\x00\x9c\x11\x00\x00\xbf\xfd\x00\x00\xe1\x87\x00\x01\xc1\x83\x80\x02A\x82@\x02A\x82@\x02\xc1\xc2@\x02\xf6>\xc0\x01\xfc=\x80\x01\x18\x18\x80\x01\x88\x10\x80\x00\x8c!\x00\x00\x87\xf1\x00\x00\x7f\xf6\x00\x008\x1c\x00\x00\x0c \x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")

# Load the raspberry pi logo into the framebuffer (the image is 32x32)
fb = framebuf.FrameBuffer(buffer, 32, 32, framebuf.MONO_HLSB)

# Clear the oled display in case it has junk on it.
oled.fill(0)

# Blit the image from the framebuffer to the oled display
oled.blit(fb, 96, 0)

# Add some text
oled.text("Raspberry Pi",5,5)
oled.text("Pico",5,15)

# Finally update the oled display so the image & text is displayed
oled.show()

After running, the result is as shown in the figure. How to add it to the Mu environment requires further information and subsequent supplements from netizens . Copy the ssd1306 part into a separate file and operate it through the file on Mu.

4. Buzzer

The operation of the buzzer is to test turning on/off the buzzer according to the buzzer test code of the live class teacher. My buzzer is connected to D18, and the code is as follows:

# 在这里写上你的代码 :-)
import time,machine
from machine import Pin, I2C
from ssd1306 import SSD1306_I2C

i2c=I2C(0,sda=Pin(8),scl=Pin(9),freq=400000)
oled = SSD1306_I2C(128, 64, i2c)

buzzer_pin = machine.Pin(18,machine.Pin.OUT)
while True:
    buzzer_pin.value(1)
    oled.fill(0)
    oled.text('buzzer on',0,12,1)
    oled.show()
    time.sleep(0.3)
    
    buzzer_pin.value(0)
    oled.fill(0)
    oled.text('buzzer off',0,12,1)
    oled.show()
    time.sleep(0.7)

First, click the file on the Mu software, drag ssd1306.py to the PICO, click the file again, run it, edit the code, and run it directly to hear the buzzer sound. The status of the buzzer is displayed on the OLED.

视频4

V. Summary

Through this activity, I learned a lot of knowledge. Through practice, I figured out what I didn't understand, and then with the explanations from the teachers and guidance from the forum friends, I got twice the result with half the effort. I am very grateful to EEWORLD and the teachers.

This post is from DigiKey Technology Zone

Latest reply

I brought a mobile hard drive and a USB flash drive, as well as a mouse and keyboard, and a 1.5A mobile phone charger. Sometimes the computer would restart after using it.   Details Published on 2023-6-1 15:21
 
 

4764

Posts

12

Resources
2
 
Is the load capacity OK? The power supply must be sufficient, otherwise it will easily restart for no reason.
This post is from DigiKey Technology Zone

Comments

Currently, only one test has been conducted and no power shortage problem has been encountered.  Details Published on 2023-6-1 10:58
 
 
 

6748

Posts

2

Resources
3
 

[As long as two lights on the light stick are not broken in a row, the other lights can light up normally] Why is this?

This post is from DigiKey Technology Zone

Comments

To be honest, I am still studying this WS2813 light stick. You can focus on the breakpoint resume function. I am still confused about it now. I will add more information when I figure it out.  Details Published on 2023-6-1 11:10
 
 
 

6748

Posts

2

Resources
4
 

It seems that driving this peripheral is quite simple.

This post is from DigiKey Technology Zone
 
 
 

30

Posts

0

Resources
5
 

Awesome!!!! I just wanted to learn about this, thanks for sharing! Awesome!!!! I just wanted to learn about this, thanks for sharing!

This post is from DigiKey Technology Zone
 
 
 

55

Posts

4

Resources
6
 

I copied the OLED code directly into mu but it doesn't work. It will prompt various format errors. I wonder if the original poster's code doesn't prompt?

This post is from DigiKey Technology Zone

Comments

I didn't encounter any problems. If there are any problems, read the error message carefully and you can usually locate the problem based on the error description.  Details Published on 2023-6-1 10:59
 
 
 

6824

Posts

11

Resources
7
 

The tutorial is very good, I learned a lot!

This post is from DigiKey Technology Zone
 
 
 

46

Posts

0

Resources
8
 
Azuma Simeng posted on 2023-5-31 15:26 Is the load capacity okay? The power supply must be sufficient, otherwise it will easily restart for no reason

Currently, only one test has been conducted and no power shortage problem has been encountered.

This post is from DigiKey Technology Zone

Comments

I brought a mobile hard drive and a USB flash drive, as well as a mouse and keyboard, and a 1.5A mobile phone charger. Sometimes the computer would restart after using it.  Details Published on 2023-6-1 15:21
 
 
 

46

Posts

0

Resources
9
 
Posted by Garfield who loves fish on 2023-6-1 00:01 I copied the OLED code directly into mu, but it doesn't work. It will prompt various format errors. I wonder if the original poster doesn't prompt it?

I didn't encounter any problems. If there are any problems, read the error message carefully and you can usually locate the problem based on the error description.

This post is from DigiKey Technology Zone
 
 
 

46

Posts

0

Resources
10
 
wangerxian posted on 2023-5-31 17:15 [As long as two consecutive lights on the light stick are broken, the other lights can light up normally] Why is this?

To be honest, I'm still working on this WS2813 light stick.

You can focus on studying the function of resuming breakpoint downloads. I am still confused about it now. Please provide more information when you understand it clearly.

This post is from DigiKey Technology Zone
 
 
 

4764

Posts

12

Resources
11
 
lingxin_yuhe posted on 2023-6-1 10:58 Currently, I have tested it alone and have not encountered any power shortage problems

I brought a mobile hard drive and a USB flash drive, as well as a mouse and keyboard, and a 1.5A mobile phone charger. Sometimes the computer would restart after using it.

This post is from DigiKey Technology Zone
 
 
 

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list