Help us understand the problem. What is going on with this article?

SPI 3軸加速度センサ(LIS3DH)と連携する

More than 1 year has passed since last update.

最初に見たティム・バートンの作品はシザー・ハンドだったと思う。ジョニー・ディップの怪演も魅力的であったが何よりストーリーが素晴らしかった。その後「The Nightmare Before Christmas」の DVD を購入するも、この時期に見ないと意味がない気がしてDVD はほこりをかぶったままだ。先生も走る時期にはなかなか DVD をゆっくり見る時間が取れない。

秋葉原で容易に入手可能な LIS3DH という3軸加速度センサと連携してみよう。SPI との連携はすでに書いている。

spi_lis3dh.py
import polyphony
from polyphony.io import Port
from polyphony.typing import bit, uint3, uint12, uint24
from polyphony.timing import clksleep, clkfence, wait_rising, wait_falling


CONVST_PULSE_CYCLE = 10
CONVERSION_CYCLE = 39

@polyphony.module
class spi_lis3dh:
    def __init__(self):
        self.sclk = Port(bit, 'out')
        self.mosi = Port(bit, 'out')
        self.miso = Port(bit, 'in')
        self.cs_n = Port(bit, 'out', init=1)

        self.x_led = Port(bit, 'out')
        self.y_led = Port(bit, 'out')
        self.z_led = Port(bit, 'out')

        self.data24  = Port(uint24, 'out', protocol='ready_valid')
        self.append_worker(self.worker)

    def set_addr(self, rw, ms, addr):
        clksleep(1)
        self.sclk.wr(0)
        self.mosi.wr(rw)

        clksleep(2)
        self.sclk.wr(1)

        clksleep(2)
        self.sclk.wr(0)
        self.mosi.wr(ms)

        clksleep(2)
        self.sclk.wr(1)

        clksleep(2)
        self.sclk.wr(0)

        for i in range(6):
            bit1 = (addr >> (5 - i)) & 1
            self.mosi.wr(bit1)
            clksleep(1)
            self.sclk.wr(1)

            clksleep(1)
            self.sclk.wr(0)

        clksleep(1)

    def read_data(self, addr):
        self.cs_n.wr(0)
        self.sclk.wr(0)
        clksleep(1)

        self.set_addr(1, 0, addr)
        data = 0

        for i in range(8):
            data <<= 1
            clksleep(1)
            self.sclk.wr(1)

            clksleep(1)
            bit1 = self.miso.rd() & 1
            clkfence()
            self.sclk.wr(0)
            data |= bit1

        clksleep(1)
        self.cs_n.wr(1)
        return data

    def write_data(self, addr, data):
        self.cs_n.wr(0)
        self.sclk.wr(0)
        clksleep(1)

        self.set_addr(0, 0, addr)

        for i in range(8):
            bit1 = (data >> (7 - i)) & 1
            self.mosi.wr(bit1)
            clksleep(1)
            self.sclk.wr(1)

            clksleep(1)
            self.sclk.wr(0)

        clksleep(2)
        self.cs_n.wr(1)
        self.mosi.wr(0)
        return data

    def worker(self):
        self.cs_n.wr(1)
        self.sclk.wr(0)
        clksleep(1)

        self.write_data(0x20, 0x7F)
        while polyphony.is_worker_running():
            clksleep(20)

            self.write_data(0x20, 0x7F)
            clksleep(10)

            data_who_am_i = self.read_data(0x0F)
            clksleep(10)

            data_x_l = self.read_data(0x29)
            clksleep(10)

            data_y_l = self.read_data(0x2B)
            clksleep(10)

            data_z_l = self.read_data(0x2D)
            clksleep(10)

            self.x_led.wr(1 if data_x_l > 0x30 else 0)
            self.y_led.wr(1 if data_y_l > 0x30 else 0)
            self.z_led.wr(1 if data_z_l > 0x30 else 0)

            data_xyz = ( data_x_l << 16 ) | ( data_y_l << 8 ) | data_z_l
            self.data24.wr(data_xyz)

@polyphony.testbench
def test(spic):
    data = spic.data24.rd()
    print("data0:" , data)
    data = spic.data24.rd()
    print("data1:" , data)

if __name__ == '__main__':
    spic = spi_lis3dh()
    test(spic)

Arty Z7 などにつなぐことで加速度センサからの情報を見て LED を光らせることが出来る。

image.png

肝となる関数は read_data と write_data そしてそこからよばれるset_addr であろう。SPI の sclk, mosi, miso, cs_n をコントロールしてLIS3DH とやりとりをする。

直接 SPI でやりとりしており CPU を介していないところが特徴だ。例えば加速度センサーを4つつけてもすべて(ほぼ)同じクロックで実行することが可能だろう。

SPI の信号線はタイミング制御があるのでソース上にはclksleep や clksleep が散在する結果となっている。この辺りはもう少し簡潔にかけるようにすべきなのだろう。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away