宜城龙山 发表于 2022-12-26 00:32

【微雪 RP2040双核开发板测试】——MAX30100血氧传感器

<div class='showpostmsg'><p align="center"><b>【微雪 RP2040双核开发板测试】&mdash;&mdash;MAX30100血氧传感器</b></p>

<p >&nbsp;</p>

<p >《微雪 RP2040双核开发板》具有丰富的外部接口,给用户进行硬件开发提供了方便,上篇文章已经对硬件接口进行了介绍,本文主要介绍MAX0100血氧传感器的应用开发。</p>

<p align="center" >&nbsp;</p>

<ul>
        <li ><b>MAX0100</b><b>血氧传感器介绍</b></li>
</ul>

<p >Max30100是一款集成的脉搏血氧和心率检测传感器。采样集成化的两个LED灯设计,一个用来优化光学的光电探测器,和低噪声模拟信号处理器,提高了测量性能,可用来检测脉搏的血氧和心率信号。</p>

<p >Max30100的运行电压在1.8V到3.3V之间,并且可以通过软件来控制,待机电流极小,可以忽略不计,超低功耗操作增加电池寿命,适合可穿戴设备。</p>

<p >具体性能参数如下:</p>

<p >1、引脚定义</p>

<p align="center" > &nbsp;</p>

<p align="center" > &nbsp;</p>

<p >2、MAX30100内部功能框图</p>

<p align="center" >&nbsp;</p>

<p align="center" > &nbsp;</p>

<p >3、寄存器图表及其描述</p>

<p align="center" > &nbsp;</p>

<p >各寄存器介绍:</p>

<ul>
        <li ><b>中断状态寄存器(基地址0x00)</b></li>
</ul>

<p > &nbsp;</p>

<p >总共有5个中断状态,每个中断状态控制都是一样的:高电平的相关中断使能,直到中断被清除,中断才停止。</p>

<p >Bit7~ Bit0各位的具体意义不再赘述,可参考产品数据手册。</p>

<ul>
        <li ><b>中断使能寄存器(基地址0x01)</b></li>
</ul>

<p > &nbsp;</p>

<p >在MAX30100 IC里,每一个硬件中断的来源都可以使用软件寄存器来控制其不使能状态,除了电源准备完成中断。开机中断不能被打断,因为在MAX30100复位时,默认状态下是不使能的。</p>

<p >当中断使能位被设置成0的时候,相应的中断在其寄存器中是1(上一个介绍),但是INT引脚不是低电平(相反电平)。(B3:B0设置为0)</p>

<ul>
        <li ><b>FIFO</b><b>寄存器(基地址 0x02&mdash;0x05)</b></li>
</ul>

<p > &nbsp;</p>

<p >①、FIFO写指针寄存器(FIFO Write Pointer)(FIFO_WR_PTR基地址 0x02)</p>

<p >FIFO写指针指向MAX30100写的下一个数据或命令的位置。这个指针把每一个数据或者命令放进FIFO中。当 MOD被设置的时候,也可以通过IIC总线的方式进行改变。</p>

<p >②、FIFO溢出计数器寄存器(OVF_COUNTER基地址 0x03)</p>

<p >当FIFO寄存器的数据记满数据,采样的数据将溢出FIFO寄存器,并且数据将会丢失。OVF_COUNTER 会保存溢出的数据。保存在0xF中。当所有的数据从FIFO中取出,OVF_COUNTER就会被置零。</p>

<p >③、FIFO 读指针寄存器(FIFO_RD_PTR基地址 0x04)</p>

<p >FIFO读指针指向处理器通过IIC总线从FIFO通道获取的下一个数据。每次只从FIFO取出一个数据。当在读数据的时候,控制器也可以使用这个寄存器来写命令或者数据到FIFO中,如果FIFO的数据传输出现错误,也可以重新从其读出样本。</p>

<p >④、FIFO数据寄存器(FIFO_DATA基地址 0x05)</p>

<p >循环的FIFO是16位的数据存储,能够存储16个SPO2通道数据(Red 和 IR)。FIFO_DATA寄存器在IIC寄存器的映射下指向从FIFO中读出的下一个数据。FIFO_RD_PTR(FIFO读数据指针)指向这个数据。FIFO_DATA寄存器不会自动增加其地址值,因此会反复读取这个地址的数据。每一个样本是4字节的数据,因此得到一个样本需要读取4次的FIFO_DATA寄存器。理论上上面的所有寄存器都可以进行读取或者写入数据,但是在实际上,只有FIFO_RD_PTR寄存器才可以进行写入操作。其他的寄存器的数据只能自动增加或者由MAX30100进行填充(填满)。当开始一个新的SPO2或者心率转换,我们希望FIFO_RD_PTR、OVF_COUNTE、FIFO_WR_PTR寄存器能够被清零,以确保FIFO是空并且是已知的状态。当从IIC读取MAX30100寄存器时,地址指针寄存器就会自动的增加,那么读取的字节就是下一个寄存器发送的。FIFO_DATA寄存器不是这样的,他的指针不会增加。在FIFO数据寄存器中下一个被发送的数据就是下一个可用的数据。</p>

<ul>
        <li ><b>关于FIFO数据结构</b></li>
</ul>

<p >FIFO的数据存储器由16个IR和RED的ADC数据样本存储块组成。每一个样本由一个IR字和一个RED字,总共有4个这样的字节数据组成。因此FIFO数据由4*16=64字节的数据组成。</p>

<p >每一个样本数据由一个IR和一个RED数据字(2个寄存器)组成,因此每次读取一个样本,需要4个IIC字节数据读一行。当4字节样本被读取完毕,FIFO的读指针就会自动增加。</p>

<p >在心率模式下,每个样本的第3和第4字节会被置0,但是其他的FIFO配置都是一样的。</p>

<ul>
        <li ><b>MAX30100</b><b>与RP2040的连接</b></li>
</ul>

<p >由于MAX30100血氧传感器常用I2C总线接口,分别为VCC、GND、SCL、SDA和RED、IR灯的电压调节输入端、中断信号,本项目仅使用I2C数据通信接口,其他开支端不使用,悬空处理。VCC、GND、SDA、SCL分别接RP2040的GPIO引出排母H1的第18、20、1(GPIO 8)、3(GPIO 9)即可。</p>

<ul>
        <li ><b>运行</b></li>
</ul>

<ol>
        <li >连接MAX30100血氧传感器</li>
        <li >MAX30100demo.py</li>
</ol>

<p >import max30100</p>

<p >mx30 = max30100.MAX30100()</p>

<p >mx30.refresh_temperature()</p>

<p >temp = mx30.get_temperature()</p>

<p >print(&#39;TEMP=%d&#39;%temp)</p>

<p >reg = mx30.get_registers()</p>

<p >print(reg)</p>

<p >mx30.enable_spo2()</p>

<p >aa=mx30.read_sensor()</p>

<p >&nbsp;</p>

<p >mx30.ir, mx30.red</p>

<p >print(mx30.buffer_red[-10:])</p>

<p >&nbsp;</p>

<ol start="3">
        <li >MAX30100数据采集程序MAX30100.py如下:</li>
</ol>

<p >&quot;&quot;&quot;&quot;</p>

<p >&nbsp; MicroPythonb Library for the Maxim MAX30100 pulse oximetry system</p>

<p >&nbsp; &quot;&quot;&quot;</p>

<p >&nbsp;</p>

<p >from machine import Pin,I2C</p>

<p >&nbsp;</p>

<p >INT_STATUS&nbsp;&nbsp; = 0x00&nbsp; # Which interrupts are tripped</p>

<p >INT_ENABLE&nbsp;&nbsp; = 0x01&nbsp; # Which interrupts are active</p>

<p >FIFO_WR_PTR&nbsp; = 0x02&nbsp; # Where data is being written</p>

<p >OVRFLOW_CTR&nbsp; = 0x03&nbsp; # Number of lost samples</p>

<p >FIFO_RD_PTR&nbsp; = 0x04&nbsp; # Where to read from</p>

<p >FIFO_DATA&nbsp;&nbsp;&nbsp; = 0x05&nbsp; # Ouput data buffer</p>

<p >MODE_CONFIG&nbsp; = 0x06&nbsp; # Control register</p>

<p >SPO2_CONFIG&nbsp; = 0x07&nbsp; # Oximetry settings</p>

<p >LED_CONFIG&nbsp;&nbsp; = 0x09&nbsp; # Pulse width and power of LEDs</p>

<p >TEMP_INTG&nbsp;&nbsp;&nbsp; = 0x16&nbsp; # Temperature value, whole number</p>

<p >TEMP_FRAC&nbsp;&nbsp;&nbsp; = 0x17&nbsp; # Temperature value, fraction</p>

<p >REV_ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0xFE&nbsp; # Part revision</p>

<p >PART_ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 0xFF&nbsp; # Part ID, normally 0x11</p>

<p >&nbsp;</p>

<p >I2C_ADDRESS&nbsp; = 0x57&nbsp; # I2C address of the MAX30100 device</p>

<p >&nbsp;</p>

<p >&nbsp;</p>

<p >PULSE_WIDTH = {</p>

<p >&nbsp;&nbsp;&nbsp; 200: 0,</p>

<p >&nbsp;&nbsp;&nbsp; 400: 1,</p>

<p >&nbsp;&nbsp;&nbsp; 800: 2,</p>

<p >&nbsp;&nbsp; 1600: 3,</p>

<p >}</p>

<p >&nbsp;</p>

<p >SAMPLE_RATE = {</p>

<p >&nbsp;&nbsp;&nbsp; 50: 0,</p>

<p >&nbsp;&nbsp; 100: 1,</p>

<p >&nbsp;&nbsp; 167: 2,</p>

<p >&nbsp;&nbsp; 200: 3,</p>

<p >&nbsp;&nbsp; 400: 4,</p>

<p >&nbsp;&nbsp; 600: 5,</p>

<p >&nbsp;&nbsp; 800: 6,</p>

<p >&nbsp; 1000: 7,</p>

<p >}</p>

<p >&nbsp;</p>

<p >LED_CURRENT = {</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 0: 0,</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp; 4.4: 1,</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp; 7.6: 2,</p>

<p >&nbsp;&nbsp;&nbsp; 11.0: 3,</p>

<p >&nbsp;&nbsp;&nbsp; 14.2: 4,</p>

<p >&nbsp;&nbsp;&nbsp; 17.4: 5,</p>

<p >&nbsp;&nbsp;&nbsp; 20.8: 6,</p>

<p >&nbsp;&nbsp;&nbsp; 24.0: 7,</p>

<p >&nbsp;&nbsp;&nbsp; 27.1: 8,</p>

<p >&nbsp;&nbsp;&nbsp; 30.6: 9,</p>

<p >&nbsp;&nbsp;&nbsp; 33.8: 10,</p>

<p >&nbsp;&nbsp;&nbsp; 37.0: 11,</p>

<p >&nbsp;&nbsp;&nbsp; 40.2: 12,</p>

<p >&nbsp;&nbsp;&nbsp; 43.6: 13,</p>

<p >&nbsp;&nbsp;&nbsp; 46.8: 14,</p>

<p >&nbsp;&nbsp;&nbsp; 50.0: 15</p>

<p >}</p>

<p >&nbsp;</p>

<p >def _get_valid(d, value):</p>

<p >&nbsp;&nbsp;&nbsp; try:</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return d</p>

<p >&nbsp;&nbsp;&nbsp; except KeyError:</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; raise KeyError(&quot;Value %s not valid, use one of: %s&quot; % (value, &#39;, &#39;.join()))</p>

<p >&nbsp;</p>

<p >def _twos_complement(val, bits):</p>

<p >&nbsp;&nbsp;&nbsp; &quot;&quot;&quot;compute the 2&#39;s complement of int value val&quot;&quot;&quot;</p>

<p >&nbsp;&nbsp;&nbsp; if (val &amp; (1 &lt;&lt; (bits - 1))) != 0: # if sign bit is set e.g., 8bit: 128-255</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; val = val - (1 &lt;&lt; bits)</p>

<p >&nbsp;&nbsp;&nbsp; return val</p>

<p >&nbsp;</p>

<p >INTERRUPT_SPO2 = 0</p>

<p >INTERRUPT_HR = 1</p>

<p >INTERRUPT_TEMP = 2</p>

<p >INTERRUPT_FIFO = 3</p>

<p >MODE_HR = 0x02</p>

<p >MODE_SPO2 = 0x03</p>

<p >class MAX30100(object):</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def __init__(self,</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i2c=None,</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mode=MODE_HR,</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sample_rate=100,</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; led_current_red=11.0,</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; led_current_ir=11.0,</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pulse_width=1600,</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max_buffer_len=10000</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.i2c =I2C(id=0,scl=Pin(9),sda=Pin(8),freq=100_000)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.set_mode(MODE_HR)&nbsp; # Trigger an initial temperature read.</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.set_led_current(led_current_red, led_current_ir)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.set_spo_config(sample_rate, pulse_width)</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Reflectance data (latest update)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.buffer_red = []</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.buffer_ir = []</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.max_buffer_len = max_buffer_len</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self._interrupt = None</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; @property</p>

<p >&nbsp;&nbsp;&nbsp; def red(self):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return self.buffer_red[-1] if self.buffer_red else None</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; @property</p>

<p >&nbsp;&nbsp;&nbsp; def ir(self):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return self.buffer_ir[-1] if self.buffer_ir else None</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def set_led_current(self, led_current_red=11.0, led_current_ir=11.0):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Validate the settings, convert to bit values.</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; led_current_red = _get_valid(LED_CURRENT, led_current_red)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; led_current_ir = _get_valid(LED_CURRENT, led_current_ir)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.write_byte_data(I2C_ADDRESS, LED_CONFIG, chr((led_current_red &lt;&lt; 4) | led_current_ir))</p>

<p >&nbsp;&nbsp;&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def set_mode(self, mode):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reg = self.read_byte_data(I2C_ADDRESS, MODE_CONFIG)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.write_byte_data(I2C_ADDRESS, MODE_CONFIG, chr(reg &amp; 0x74))# mask the SHDN bit</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.write_byte_data(I2C_ADDRESS, MODE_CONFIG, chr(reg | mode))</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def set_spo_config(self, sample_rate=100, pulse_width=1600):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reg = self.read_byte_data(I2C_ADDRESS, SPO2_CONFIG)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reg = reg &amp; 0xFC&nbsp; # Set LED pulsewidth to 00</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.write_byte_data(I2C_ADDRESS, SPO2_CONFIG, chr(reg | pulse_width))</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def read_byte_data(self, i2c_addr, addr):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bval =&nbsp; self.i2c.readfrom_mem(i2c_addr, addr, 1)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return bval&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def read_bytes_data(self, i2c_addr, addr, len = 1):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bval =&nbsp; self.i2c.readfrom_mem(i2c_addr, addr, len)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return bval</p>

<p >&nbsp;&nbsp;&nbsp; def write_byte_data(self, i2c_addr, addr, chs):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.i2c.writeto_mem(i2c_addr,addr, chs)</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def enable_spo2(self):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.set_mode(MODE_SPO2)</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def disable_spo2(self):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.set_mode(MODE_HR)</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def enable_interrupt(self, interrupt_type):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.write_byte_data(I2C_ADDRESS, INT_ENABLE, chr((interrupt_type + 1)&lt;&lt;4))</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.read_byte_data(I2C_ADDRESS, INT_STATUS)</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def get_number_of_samples(self):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; write_ptr = self.read_byte_data(I2C_ADDRESS, FIFO_WR_PTR)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; read_ptr = self.read_byte_data(I2C_ADDRESS, FIFO_RD_PTR)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return abs(16+write_ptr - read_ptr) % 16</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def read_sensor(self):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #bytes = self.i2c.read_i2c_block_data(I2C_ADDRESS, FIFO_DATA, 4)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bytes = self.read_bytes_data(I2C_ADDRESS, FIFO_DATA, 4)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Add latest values.</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.buffer_ir.append(bytes&lt;&lt;8 | bytes)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.buffer_red.append(bytes&lt;&lt;8 | bytes)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Crop our local FIFO buffer to length.</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.buffer_red = self.buffer_red[-self.max_buffer_len:]</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.buffer_ir = self.buffer_ir[-self.max_buffer_len:]</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def shutdown(self):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reg = self.read_byte_data(I2C_ADDRESS, MODE_CONFIG)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.write_byte_data(I2C_ADDRESS, MODE_CONFIG, chr(reg | 0x80))</p>

<p >&nbsp;&nbsp;&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def reset(self):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reg = self.read_byte_data(I2C_ADDRESS, MODE_CONFIG)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.write_byte_data(I2C_ADDRESS, MODE_CONFIG, chr(reg | 0x40))</p>

<p >&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def refresh_temperature(self):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; reg = self.read_byte_data(I2C_ADDRESS, MODE_CONFIG)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; self.write_byte_data(I2C_ADDRESS, MODE_CONFIG, chr(reg | (1 &lt;&lt; 3)))</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def get_temperature(self):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #intg = _twos_complement(self.read_byte_data(I2C_ADDRESS, TEMP_INTG))</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; intg = self.read_byte_data(I2C_ADDRESS, TEMP_INTG)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; frac = self.read_byte_data(I2C_ADDRESS, TEMP_FRAC)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return intg + (frac * 0.0625)</p>

<p >&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def get_rev_id(self):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return self.read_byte_data(I2C_ADDRESS, REV_ID)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def get_part_id(self):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return self.read_byte_data(I2C_ADDRESS, PART_ID)</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>

<p >&nbsp;&nbsp;&nbsp; def get_registers(self):</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return {</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;INT_STATUS&quot;: self.read_byte_data(I2C_ADDRESS, INT_STATUS),</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;INT_ENABLE&quot;: self.read_byte_data(I2C_ADDRESS, INT_ENABLE),</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;FIFO_WR_PTR&quot;: self.read_byte_data(I2C_ADDRESS, FIFO_WR_PTR),</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;OVRFLOW_CTR&quot;: self.read_byte_data(I2C_ADDRESS, OVRFLOW_CTR),</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;FIFO_RD_PTR&quot;: self.read_byte_data(I2C_ADDRESS, FIFO_RD_PTR),</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;FIFO_DATA&quot;: self.read_byte_data(I2C_ADDRESS, FIFO_DATA),</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;MODE_CONFIG&quot;: self.read_byte_data(I2C_ADDRESS, MODE_CONFIG),</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;SPO2_CONFIG&quot;: self.read_byte_data(I2C_ADDRESS, SPO2_CONFIG),</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;LED_CONFIG&quot;: self.read_byte_data(I2C_ADDRESS, LED_CONFIG),</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;TEMP_INTG&quot;: self.read_byte_data(I2C_ADDRESS, TEMP_INTG),</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;TEMP_FRAC&quot;: self.read_byte_data(I2C_ADDRESS, TEMP_FRAC),</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;REV_ID&quot;: self.read_byte_data(I2C_ADDRESS, REV_ID),</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &quot;PART_ID&quot;: self.read_byte_data(I2C_ADDRESS, PART_ID),</p>

<p >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>

<p >&nbsp;</p>

<p >&nbsp;</p>

<ol start="4">
        <li >运行结果:</li>
</ol>

<p > &nbsp;</p>

<p >由于RP2040的I2C0引脚8,9已经用作屏幕的CS和DC引脚,故这里我们只能选择PRINT语句输出数据。</p>

<p > &nbsp;</p>

<ul>
        <li ><b>总结</b></li>
</ul>

<p >本文未对测量的数据做进一步的处理,要精确得到血液含氧量数据需要进行FFT处理,由于需要处理的数据量较大,且需要使用到micropython的数据处理模块,这里不做进一步处理。如读者需要进行数据处理和查阅相关资料。</p>
</div><script>                                        var loginstr = '<div class="locked">查看本帖全部内容,请<a href="javascript:;"   style="color:#e60000" class="loginf">登录</a>或者<a href="https://bbs.eeworld.com.cn/member.php?mod=register_eeworld.php&action=wechat" style="color:#e60000" target="_blank">注册</a></div>';
                                       
                                        if(parseInt(discuz_uid)==0){
                                                                                                (function($){
                                                        var postHeight = getTextHeight(400);
                                                        $(".showpostmsg").html($(".showpostmsg").html());
                                                        $(".showpostmsg").after(loginstr);
                                                        $(".showpostmsg").css({height:postHeight,overflow:"hidden"});
                                                })(jQuery);
                                        }                </script><script type="text/javascript">(function(d,c){var a=d.createElement("script"),m=d.getElementsByTagName("script"),eewurl="//counter.eeworld.com.cn/pv/count/";a.src=eewurl+c;m.parentNode.insertBefore(a,m)})(document,523)</script>

吾妻思萌 发表于 2022-12-26 06:40

<p>期待成品 血氧蛮关键的对于新冠这种小传染病来说</p>

dcexpert 发表于 2022-12-26 08:23

<p>在加上心率就是一个完整产品了</p>

Jacktang 发表于 2022-12-26 08:38

<p>MAX30100血氧传感器看来可以试用一下</p>

秦天qintian0303 发表于 2022-12-26 09:18

<p>文章后边是不是少了部分东西</p>

soso 发表于 2022-12-26 10:08

<p>现在血氧这个太应景了。:)</p>
页: [1]
查看完整版本: 【微雪 RP2040双核开发板测试】——MAX30100血氧传感器