有什么办法可以让我的Mcp3008采样统一吗?
Is there any way to make my Mcp3008 sampling uniform?
我正在做一项工作,使用 ADC mcp3008 样本传感器数据并收集它们,直到 10k.Then 将其发送到 influxdb。
所有这些工作应该在 1 秒内完成。就是这个意思。
现在的问题是,每条数据的时间戳很不均匀
如您所见:
我希望时间戳统一为 0.1 毫秒。我的意思是influsdb的时间精度应该是0.1ms。
但遗憾的是,写参数time_precision只有's'、'ms'、'u'或'n'。
所以我能做的就是让采样过程更加统一,对吧?
我使用多处理模块来完成这项工作。这是我的原始代码:
import Adafruit_GPIO.SPI as SPI # Import Adafruit GPIO_SPI Module
import Adafruit_MCP3008 # Import Adafruit_MCP3008
import serial
import time
import datetime
from influxdb import InfluxDBClient
from multiprocessing import Process, Queue
def producer(name):
i=0
while True:
begin=time.time()
body = []
while i<10000:
val = round(mcp.read_adc(0),4) #here read the data from SPI port
current_time = datetime.datetime.utcnow()
js = {
"measurement": "Double",
"time": current_time,
"tags": {
},
"fields": {
"sensor2": val
}
}
body.append(js)
i+=1
i=0
res = client.write_points(body) #Send influxdb 10k data at once
body.clear()
end=time.time()-begin
print(end,name)
if __name__ == "__main__":
HW_SPI_PORT = 0 # Set the SPI Port. Raspi has two.
HW_SPI_DEV = 0 # Set the SPI Device
mcp = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(HW_SPI_PORT, HW_SPI_DEV))
client = InfluxDBClient(host='XXXXX', port=8086, username='admin', password='admin', database= 'db',ssl=False, verify_ssl=False)
p1 = Process(target=producer,args=(0,))
p2 = Process(target=producer,args=(1,))
p3 = Process(target=producer,args=(2,))
p4 = Process(target=producer,args=(3,))
p5 = Process(target=producer,args=(4,))
p6 = Process(target=producer,args=(5,))
p1.start()
p2.start()
p3.start()
p4.start()
p5.start()
p6.start()
是啊...我不得不经历六个过程才能在平均一秒内完成..
那么有什么办法可以让采样统一呢?
像这样制作时间戳:
1603469938916'5'26000 -0.175
1603469938916'6'26000 -0.172
1603469938916'7'26000 -0.178
1603469938916'8'26000 -0.175
1603469938916'9'26000 -0.182
我的意思是时间精度0.1ms。
谢谢!这一定是个奇怪的问题。
PS:
我灵机一动,有什么方法可以让我的时间戳精度达到 0.1 毫秒吗?像 :
timestamp=datetime.datetime.utcnow()
...Some operation...
print(timestamp)
然后得到:1603469938916900000
可能有用。
是的,我找到了解决方案:
from datetime import datetime
import math
def format():
dt = datetime.utcnow()
dt_round_microsec = math.floor(dt.microsecond/100)*100
dt = dt.replace(microsecond=dt_round_microsec)
return dt
欢迎提出更好的建议
一些建议。
- 如果需要对ADC进行统一采样,这个问题就比较难了。
- 如果您“只需要”统一的时间戳间距,您可以随意采样,然后将时间戳设置为
begin + iteration * 0.1ms
。此选项不适用于任何类型的科学数据收集。 10k samples/sec 听起来你需要均匀间隔的采样(例如音频)。所以我会忽略选项 2.
对于选项 1,您需要循环具有一致的迭代时间。在 RPi 上使用 python 很难保证这一点(我假设您使用的是 Pi)。 RPi OS 不是实时的,因此您的循环可能会随机延迟。这里唯一真正的选择是使用外部微处理器以保证时序触发 ADC。
不过,我们可以尝试让您的采样循环写得更好一些。 datetime.datetime.utcnow()
可能是 slow-ish 系统调用。使用 time.perf_counter()
可能会获得更好的结果。您可能还想将 val
和 current_time
存储在循环内的列表中,而 assemble 完整的 json 正文存储在循环外的不同进程中,因为它看起来像您想要的永远 10ksps(并且也在单独的进程中发送到 influxdb)。
一般来说,raspberry pi 硬件未设置为在这些频率下对 ADC 进行连续 real-time 采样。
我正在做一项工作,使用 ADC mcp3008 样本传感器数据并收集它们,直到 10k.Then 将其发送到 influxdb。
所有这些工作应该在 1 秒内完成。就是这个意思。
现在的问题是,每条数据的时间戳很不均匀
如您所见:
我希望时间戳统一为 0.1 毫秒。我的意思是influsdb的时间精度应该是0.1ms。
但遗憾的是,写参数time_precision只有's'、'ms'、'u'或'n'。
所以我能做的就是让采样过程更加统一,对吧?
我使用多处理模块来完成这项工作。这是我的原始代码:
import Adafruit_GPIO.SPI as SPI # Import Adafruit GPIO_SPI Module
import Adafruit_MCP3008 # Import Adafruit_MCP3008
import serial
import time
import datetime
from influxdb import InfluxDBClient
from multiprocessing import Process, Queue
def producer(name):
i=0
while True:
begin=time.time()
body = []
while i<10000:
val = round(mcp.read_adc(0),4) #here read the data from SPI port
current_time = datetime.datetime.utcnow()
js = {
"measurement": "Double",
"time": current_time,
"tags": {
},
"fields": {
"sensor2": val
}
}
body.append(js)
i+=1
i=0
res = client.write_points(body) #Send influxdb 10k data at once
body.clear()
end=time.time()-begin
print(end,name)
if __name__ == "__main__":
HW_SPI_PORT = 0 # Set the SPI Port. Raspi has two.
HW_SPI_DEV = 0 # Set the SPI Device
mcp = Adafruit_MCP3008.MCP3008(spi=SPI.SpiDev(HW_SPI_PORT, HW_SPI_DEV))
client = InfluxDBClient(host='XXXXX', port=8086, username='admin', password='admin', database= 'db',ssl=False, verify_ssl=False)
p1 = Process(target=producer,args=(0,))
p2 = Process(target=producer,args=(1,))
p3 = Process(target=producer,args=(2,))
p4 = Process(target=producer,args=(3,))
p5 = Process(target=producer,args=(4,))
p6 = Process(target=producer,args=(5,))
p1.start()
p2.start()
p3.start()
p4.start()
p5.start()
p6.start()
是啊...我不得不经历六个过程才能在平均一秒内完成..
那么有什么办法可以让采样统一呢? 像这样制作时间戳:
1603469938916'5'26000 -0.175
1603469938916'6'26000 -0.172
1603469938916'7'26000 -0.178
1603469938916'8'26000 -0.175
1603469938916'9'26000 -0.182
我的意思是时间精度0.1ms。
谢谢!这一定是个奇怪的问题。
PS: 我灵机一动,有什么方法可以让我的时间戳精度达到 0.1 毫秒吗?像 :
timestamp=datetime.datetime.utcnow()
...Some operation...
print(timestamp)
然后得到:1603469938916900000
可能有用。
是的,我找到了解决方案:
from datetime import datetime
import math
def format():
dt = datetime.utcnow()
dt_round_microsec = math.floor(dt.microsecond/100)*100
dt = dt.replace(microsecond=dt_round_microsec)
return dt
欢迎提出更好的建议
一些建议。
- 如果需要对ADC进行统一采样,这个问题就比较难了。
- 如果您“只需要”统一的时间戳间距,您可以随意采样,然后将时间戳设置为
begin + iteration * 0.1ms
。此选项不适用于任何类型的科学数据收集。 10k samples/sec 听起来你需要均匀间隔的采样(例如音频)。所以我会忽略选项 2.
对于选项 1,您需要循环具有一致的迭代时间。在 RPi 上使用 python 很难保证这一点(我假设您使用的是 Pi)。 RPi OS 不是实时的,因此您的循环可能会随机延迟。这里唯一真正的选择是使用外部微处理器以保证时序触发 ADC。
不过,我们可以尝试让您的采样循环写得更好一些。 datetime.datetime.utcnow()
可能是 slow-ish 系统调用。使用 time.perf_counter()
可能会获得更好的结果。您可能还想将 val
和 current_time
存储在循环内的列表中,而 assemble 完整的 json 正文存储在循环外的不同进程中,因为它看起来像您想要的永远 10ksps(并且也在单独的进程中发送到 influxdb)。
一般来说,raspberry pi 硬件未设置为在这些频率下对 ADC 进行连续 real-time 采样。