Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use MicroPython in SensorTile

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article will explain in detail how to use MicroPython in SensorTile. The content of the article is of high quality, so the editor shares it for you as a reference. I hope you will have a certain understanding of the relevant knowledge after reading this article.

Introduction to SensotTile

The SensorTile core board is very compact and looks like a wearable prototype (smartwatch), so its sensors are also motion-related. There are four sensors on the SensorTile core board. They are:

LPS22HB, air pressure + temperature sensor

LSM6DSM, three-axis acceleration + three-axis angular velocity sensor

LSM303AGR, three-axis angular velocity + three-axis magnetic field sensor

MP34DT04,MEMS microphone sensor

Let's start with the simplest LPS22HB and introduce the use and transplantation of the sensor step by step. The MP34DT04 sensor is not used this time, and its interface is different from other sensors, so I won't look at it for the time being.

LPS22HB air pressure sensor

Hardware interface

The schematic diagram of LPS22HB is as above, from which we can see that the sensor uses SPI connection mode, but only CS, SCL/SPC, SDA/SDI/SDO feet are used, and SDO foot is not used, indicating that it does not use the standard SPI interface. In addition, you can see that the INT signal is not connected, so the INT mode cannot be used. Usually in INT mode, a threshold parameter can be set in advance. When the output of the sensor exceeds this threshold, an INT signal is automatically generated to wake up the MCU, and then read and process the parameters, which helps to simplify programming and reduce system power consumption.

As can be seen from the sensor's user manual, the sensor supports both SPI/I2C interfaces. These two interface modes are switched through the CS pin, when the CS is low, it is the SPI mode, and the CS is the high power level, it is the I2C mode. SensorTile uses a half-duplex SPI interface (also known as 3-wire mode) in hardware design, in which the host only uses MOSI as the data line and the slave uses MISO. Its advantage is that it can save a data line, but the disadvantage is that it sacrifices speed.

Because MicroPython does not support half-duplex SPI interface mode (hardware SPI and software SPI do not support this way), if you want to drive the sensor in SPI mode, you can only simulate this SPI mode by software, which not only increases the complexity of the software, but also slows down, so I adopted the I2C interface mode. Because SPI_SDA (PB15) and SPI_CLK (PB13) pins are not hardware I2C interfaces, software I2C mode is required. Fortunately, the bottom layer of micropython already supports software I2C, using the same method as hardware I2C, and the speed is not slow.

Here first introduce the software I2C. In order to use the software I2C, we need to use micropython's machine library instead of the pyb library. You may have noticed that CC3200, ESP8266, STM32 and other branches have many differences in hardware underlying function interfaces, which brings a lot of inconvenience to our programming and program migration. Starting with v1.8, micropython began to enhance the functionality of the machine library, which helps to unify the underlying interface. The use of software I2C is as follows:

Import machinei2c = machine.I2C (- 1, sda=machine.Pin ('PB15'), scl=machine.Pin (' PB13'))

Among them-1 represents the use of the software I2C scl SDA and scl is the use of GPIO, you can use any GPIO, on the SensorTile must use PB15 and PB13.

After defining I2C directly, we will find that I2C still does not work. This is because the pull-up resistor of I2C is not set inside the SensorTile, so the state of the I2C bus can not be determined, so we also need to enable the pull-up resistor inside the GPIO. Note that this step needs to be placed after I2C initialization, because the GPIO state and parameters will be reset during I2C initialization. Adding the pull-up resistance definition directly to the sda=machine.Pin ('PB15', pull=Pin.PULL_UP) in the I2C definition also does not work because this parameter is ignored when setting I2C. After the definition of I2C, add the following definition, I2C can work properly, if you use the i2c.scan () function at this time, you can search for 4 devices.

Sda=machine.Pin ('PB15', Pin.OPEN_DRAIN, pull=Pin.PULL_UP) scl=machine.Pin (' PB13', Pin.OPEN_DRAIN, pull=Pin.PULL_UP)

Sensor register

ST provides several routines for SensorTile kit, which include the underlying driving functions of the sensor. If you use C++ to program, you can use these driver functions. And we have to use micropython for programming, so we can not directly use the underlying functions of ST, we need to operate on the registers (in fact, the underlying driver function of ST also operates on these registers, but it has been encapsulated, so there is no need to look at the register instructions). In order to use LPS22HB, you need to have a preliminary understanding of the sensor's registers.

The picture above is a list of registers for LPS22HB, which does not have too many registers. Except for the reserved registers (Reserved), there are about two dozen of them. Each register has an address, the register output is 8 bits, most registers can be read and write (RW), and a few registers are read-only (R). If divided according to function, the registers of the sensor can be roughly divided into the following categories:

Function settin

Sensor statu

Parameter output

The function setting register can set the working mode, parameter output frequency, parameter range, interrupt and other parameters of the sensor. Only when the correct parameters are set, the sensor can work. After power on / reset, we also need to set the function register (initialization) first, otherwise the sensor has no output because the sensor is in power-down mode (Power down) by default.

The status register is usually read-only and can be used to query the current state of the sensor or some flag bit. Especially in the interrupt working mode, the interrupt needs to be queried through the status register.

The parameter output is the output of the sensor, such as air pressure, temperature and other parameters. Many parameters use double bytes or more bytes, which need to be read and combined.

Because there are many registers, we only introduce the sensors that are mainly used, and you can study other sensors slowly (see section 9 of the LPS22HB data manual: Register description for register instructions).

Device identification register: WHO_AM_I (0Fh)

Can be used to identify the model of the chip. The register is read-only and the output is 0xB1, the decimal 177s.

Control register: CTRL_REG1 (10h)

This is the most important register, where the main parameters are set.

seven

six

five

four

three

two

one

0

0

ODR2

ODR1

ODR0

EN_LPFP

LPFP_CFG

BDU

SIM

ODR represents the sampling frequency. When ODR=0, the sensor enters the power-off mode and when it is set to other parameters, the sensor starts sampling according to the specified frequency.

EN_LPFP represents the use of an internal low-pass filter, which is off by default.

LPFP_CFG is a low-pass filter bandwidth setting, which needs to be used in conjunction with EN_LPFP.

BDU is the reduction of Block data update, which means that the register is updated only after the output data has been read.

SIM is to choose 3-wire / 4-wire SPI mode.

Air pressure register

The air pressure parameter consists of three registers, namely PRESS_OUT_XL (28h), PRESS_OUT_L (29h) and PRESS_OUT_H (2Ah).

The air pressure is calculated as follows

Air pressure = PRESS_OUT_ H ·PRESS _ OUT_ L ·PRESS _ OUT_XL / 4096

Is to combine the values of the three registers and divide them by 4096. If precision is not required, you can also take only PRESS_OUT_H and PRESS_OUT_L, and then divide by 16. The accuracy of the barometric sensor is ±0.1hPa, so just keep one decimal place.

If you want to calculate the height by air pressure, it is usually calculated by looking up the table. However, because the air pressure is easily affected by temperature, humidity, wind and other conditions, the error of calculating the absolute height through the air pressure is larger, so the relative height is usually measured (height change).

Temperature register

The temperature parameter consists of two registers:

The temperature is calculated as follows:

Temperature = TEMP_OUT_ H ·TEMP _ OUT_L / 100

Considering that it is negative when it is less than 0 °, you need to treat this parameter as a signed number. The accuracy of the temperature sensor is ±1.5℃.

If there are no special requirements, the basic data acquisition function can be realized by using the above registers. If you want to further reduce power consumption, change mode, use interrupts, use FIFO, use reference values, and so on, you need to further study other registers.

Porting Micropython programs of LPS22HB

The interface, main registers and parameter calculation of the sensor are introduced. The method of using MicroPython to drive LPS22HB is introduced below.

In order to make the program universal and the system modular, we will create a separate Module for LPS22HB, which is also convenient for other programs to use. In the python language, a module is similar to a subroutine of C++. It can contain multiple objects (class), each providing a series of functions or methods. But the python language is not as complex as C++, nor is it an object-oriented language, so it is much easier to use.

The structure of a typical mudule is as follows, it consists of several class, and each class is composed of multiple functions. One of the more special is the _ _ init__ () function, which is similar to C++ 's constructor initialization. The _ _ init__ () function is called automatically after the class variable is defined. All the contents that need to be initialized are placed in this function by default. In addition, the default first parameter for each function under class is self, but you don't need to use it when calling it, and the self parameter is used internally by the python system. For more information about python grammar, please refer to python tutorials or reference books, which will not be repeated here.

For LPS22HB sensors, let's first define a basic LPS22HB class:

Class LPS22HB (object): def _ _ init__ (self): xxxx def func1 (): xxxx def func2 (): xxxx

Then initialization and other functions are added step by step, and finally a complete driver is added.

The first thing you need to add is the initialization part. In the _ _ init__ () function, add the GPIO part first, set the GPIO of CS to output and set it to high level, so that I2C can work properly:

# set CS high CS_LPS22HB = Pin (LPS22HB_CS_PIN, Pin.OUT) CS_LPS22HB (1) CS_AG = Pin (LSM6DSM_CS_PIN, Pin.OUT) CS_AG (1) CS_A = Pin (LSM303AGR_CS_A_PIN, Pin.OUT) CS_A (1) CS_M = Pin (LSM303AGR_CS_M_PIN, Pin.OUT) CS_M (1)

Then add the code for the I2C initialization part:

# soft I2C self.i2c = machine.I2C (- 1, sda=machine.Pin ('PB15'), scl=machine.Pin (' PB13')) # set open drain and pull up sda=machine.Pin ('PB15', Pin.OPEN_DRAIN, pull=Pin.PULL_UP) scl=machine.Pin (' PB13', Pin.OPEN_DRAIN, pull=Pin.PULL_UP)

Then set the CTRL1_REG register of LPS22HB to leave LPS22HB in working mode by default:

# start LPS22HB self.setreg (0x18, LPS22HB_CTRL_REG1, LPS22HB_ADDRESS) self.temp0 = 0 self.press = 0 self.LPS22HB_ON = True

Self.temp0, self.press, and self.LPS22HB_ON are internal variables for subsequent parameter calculations and state settings. They are not necessary, they are defined here mainly to facilitate other function calls under the same module.

After the initialization part is complete, it is time to add other functions. You can find that in the initialization section above, we use a function to set the register. Because setting and reading the register is a universal operation, we also set the operation of the register to a function. It is also convenient to separate the underlying layer from the application layer. In order to facilitate reading parameters, we also set up a function get2reg that reads two adjacent registers. This function does not use the function of automatically incrementing the register address of the sensor, because in the BUD mode of the sensor, the function of automatic increment of the address is invalid, so the performance is sacrificed a little in order to make the program have better compatibility.

Def setreg (self, dat, reg, addr): buf = bytearray (2) buf [0] = reg buf [1] = dat self.i2c.writeto (addr, buf) def getreg (self, reg, addr): buf = bytearray (1) buf [0] = reg self.i2c.writeto (addr, buf) t = self.i2c.readfrom (addr) 1) return t [0] def get2reg (self, reg, addr): l = self.getreg (reg, addr) h = self.getreg (reg+1, addr) return l+h*256

To increase the readability and maintainability of the program, we define the name of the register as a constant and put it in front of class, which is similar to # define in C language. The register name is preceded by a LPS22HB prefix to prevent conflicts with other chip definitions when there are multiple chip definitions in one Module.

# LPS22HB register LPS22HB_INTERRUPT_CFG= const (0x0B) LPS22HB_THS_P_L = const (0x0C) LPS22HB_THS_P_H = const (0x0D) LPS22HB_WHO_AM_I = const (0x0F) LPS22HB_CTRL_REG1 = const (0x10) LPS22HB_CTRL_REG2 = const (0x11) LPS22HB_CTRL_REG3 = const (0x12) LPS22HB_FIFO_CTRL = const (0x14) LPS22HB_REF_P_XL = const (0x15) LPS22HB_REF_P_L = const (0x16) LPS22HB_REF_P_H = const (0x17) LPS22HB_RPDS_L = const (0x18) LPS22HB_RPDS_H = const (0x19) LPS22HB_RES_CONF = const (0x1A) LPS22HB_INT_SOURCE = const (0x25) LPS22HB_FIFO_STATUS = const (0x26) LPS22HB_STATUS = const (0x27) LPS22HB_PRESS_OUT_XL = const (0x28) LPS22HB_PRESS_OUT_L = const (0x29) LPS22HB_PRESS_OUT_ H = const (0x2A) LPS22HB_TEMP_OUT_L = const (0x2B) LPS22HB_TEMP_OUT_H = const (0x2C) LPS22HB_LPFP_RES = const (0x33)

The previous register operation and initialization can be regarded as preparatory work, and when the preparatory work is completed, it is the operation of the specific sensor. The most important purpose of using the sensor is to obtain the parameters of the sensor, so we define two more functions, one to obtain the air pressure and the other to obtain the temperature.

Def LPS22HB_temp (self): self.temp0 = self.get2reg (LPS22HB_TEMP_OUT_L, LPS22HB_ADDRESS) if (self.temp0 > 0x7FFF): self.temp0-= 65536 return self.temp0/100 def LPS22HB_press (self): self.press = self.getreg (LPS22HB_PRESS_OUT_XL, LPS22HB_ADDRESS) self.press + = self.get2reg (LPS22HB_PRESS_OUT_L LPS22HB_ADDRESS) * 256 return self.press/4096

The air pressure function first reads the parameters of the three registers, and then divides the result by 4096, which is converted according to the calculation method introduced earlier. The temperature function is a little bit more troublesome because there is a problem of negative numbers. In python language, type conversion can not be carried out automatically as in C language, and the parameters of the register can not be converted directly to negative numbers, so you need to judge and convert yourself. Because this is a double-byte data, the highest bit is the symbol bit, so if the data is greater than 0x7FFF or the highest bit is 1, then it is considered to be negative.

In addition, in some cases, both temperature and pressure data need to be read at the same time, so we can put two parameters into a function and return through a list. Here you can put the first two functions directly in the list of return.

Def LPS22HB (self): return [self.LPS22HB_temp (), self.LPS22HB_press ()]

Finally, in order to reduce power consumption, we also need to allow the sensor to enter power-down mode, so we need to add two more power management functions:

Def LPS22HB_poweron (self): t = self.getreg (LPS22HB_CTRL_REG1, LPS22HB_ADDRESS) & 0x0F self.setreg (t | 0x10, LPS22HB_CTRL_REG1, LPS22HB_ADDRESS) self.LPS22HB_ON = True def LPS22HB_poweroff (self): t = self.getreg (LPS22HB_CTRL_REG1, LPS22HB_ADDRESS) & 0x0F self.setreg (t, LPS22HB_CTRL_REG1, LPS22HB_ADDRESS) self.LPS22HB_ON = False

In power-off mode (Power down), the lowest power consumption of the sensor is 1uA. In fact, the power consumption of LPS22HB is not high, and there is only 3uA when both ODR and LC_EN are 1.

After completing the above work, we have implemented a basic LPS22HB driver. We can save it to a LPS22HB.py file and use it in the following ways:

> from LPS22HB import LPS22HB

> > lp=LPS22HB ()

> > lp.LPS22HB_temp ()

16.17

> > lp.LPS22HB_press ()

1025.827

> > lp.LPS22HB ()

[16.14, 1025.839]

If you use dir (LPS22HB), you can view all the functions

> dir (LPS22HB)

['_ qualname__', 'LPS22HB_poweron',' _ _ module__', 'LPS22HB_press',' LPS22HB_temp', 'LPS22HB',' getreg', 'setreg',' get2reg', 'LPS22HB_poweroff',' _ _ init__']

On how to use MicroPython in SensorTile to share here, I hope the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report