提高ADXL345采样率后向ThingSpeak上传JSON报400错误求助
问题描述
我开发了一款程序,从Adafruit ADXL345加速度计采集数据,按用户定义的采样率写入JSON文件,之后定期上传至ThingSpeak,采样率可通过变量update_interval调整:
- 设置
update_interval = 1时,程序每秒写入一次数据,每5秒能成功上传至ThingSpeak; - 设置
update_interval = 0.01时,数据可正常写入JSON,但上传至ThingSpeak返回400错误(请求语法错误); - 设置
update_interval = 0.5时可成功上传,采样率进一步提高则上传失败。
我是首次学习Python的机械工程师,未修改上传相关代码却出现此问题,完整代码如下:
#1. Import necessary libraries for the script import sys import json import time import os import psutil import requests import busio import board import adafruit_tca9548a import adafruit_bme680 import adafruit_adxl34x import adafruit_sgp40 #import adafruit_ads1x15.ads1015 as ADS import paho.mqtt.publish as publish import string import numpy as np #from adafruit_ads1x15.analog_in import AnalogIn i2c = busio.I2C(board.SCL, board.SDA) tca = adafruit_tca9548a.TCA9548A(i2c) #Define what channel each of the sensors are plugged into bme680 = adafruit_bme680.Adafruit_BME680_I2C(tca[0]) accelerometer = adafruit_adxl34x.ADXL345(tca[1]) sgp = adafruit_sgp40.SGP40(tca[2]) #ads = ADS.ADS1015(tca[3]) #Set the sampling rate of the accelerometer to 800 Hz accelerometer.data_rate = adafruit_adxl34x.DataRate.RATE_100_HZ bme680.oversample_humidity = 2 bme680.oversample_temperature = 2 bme680.oversample_pressure = 2 bme680.oversample_filter = 2 ADC_CHANNEL = 0 GAIN = 1 #2. Define global variabesl that track the last connection time and last update time. Define time intervals to update the data, and post the data to ThingSpeak last_connection_time = time.time() #Track the last connection time last_update_time = time.time() #Track the last update time posting_interval = 5 #Post data once every 5 seconds update_interval = 0.01 #Write data to a JSON file in a defined amount of time #3. Deinfe you ThingSpeak write API key and channel ID settings, along with the ThingSpeak server settings write_api_key = "Y1S2TKIM4XTQHESF" channel_ID = "2729406" url = "https://api.thingspeak.com/channels/" + channel_ID + "/bulk_update.json" #ThingSpeak server settings message_buffer = [] #4. Define the function httpRequest that sends data to ThingSpeak and prints the response code from the server. #The response code 202 indicates that the server has accepted the request and will process it. def httpRequest(): #Function to send the POST request to ThingSpeak channel for bulk update. global message_buffer bulk_data = json.dumps({'write_api_key':write_api_key,'updates':message_buffer}) #Format the json data buffer request_headers = {"User-Agent":"mw.doc.bulk-update (Raspberry Pi)","Content-Type":"application/json","Content-Length":str(len(bulk_data))} """ # Save JSON data to a file before sending timestamp = int(time.time()) filename = f"data_to_thingspeak_{timestamp}.json" with open(filename, "w") as file: file.write(bulk_data) print(f"Data saved to {filename}") """ #Make the request to ThingSpeak try: print(request_headers) response = requests.post(url,headers=request_headers,data=bulk_data) print (response) #A 202 indicates that the server has accpeted the request #input("Press enter to continue...") except e: print(e.code) #Print the error code message_buffer = [] #Reinitialize the message buffer input("Press enter to continue...") global last_connection_time last_connection_time = time.time() #Update the connection time #5. Define the fucntion getData that returns the data def getData(): #Function that returns the data from the array of sensors #bme680 humidity = bme680.relative_humidity temperature = bme680.temperature pressure = bme680.pressure gas_resistance = bme680.gas #sgp40 #voc = sgp.raw #adxl345 acc_x, acc_y, acc_z = accelerometer.acceleration #acc_x, acc_y, acc_z = acceleration_rms() #spw2430 and ADS1015 #channel = AnalogIn(ads, ADS.P0) #mic_value = channel.value return humidity,temperature, pressure, gas_resistance, acc_x, acc_y, acc_z #6. Define the function updatesJson to continuosuly update the message buffer every 15 seconds def updatesJson(): #Function to update the message buffer every 1 second with data. #And then call the httpRequest function every 1 minute. global last_update_time, last_connection_time if time.time() - last_update_time >= update_interval: # Create a message with sensor data message = {} message['delta_t'] = int(round(time.time() - last_update_time)) humidity, temperature, pressure, gas_resistance, acc_x, acc_y, acc_z = getData() #message['field1'] = humidity #message['field2'] = temperature #message['field3'] = pressure #message['field4'] = gas_resistance message['field5'] = acc_x message['field6'] = acc_y message['field7'] = acc_z #message['field8'] = mic_value global message_buffer message_buffer.append(message) #Add to buffer print(f"Data added to buffer: {message}") #Debugging output last_update_time = time.time() #Update last update time here # If posting interval time has crossed 2 minutes update the ThingSpeak channel with your data if time.time() - last_connection_time >= posting_interval: httpRequest() last_update_time = time.time() #7. Run an infinite loop to continously call the function updatesJson every 15 seconds. if __name__ == "__main__": #To ensure that this is run directly and does not run when imported while True: #If update interval time has crossed 1 second upates the message buffer with data if time.time() - last_update_time >= update_interval: updatesJson()
问题原因
delta_t字段不符合要求:ThingSpeak要求delta_t为正整数(代表与上一条数据的间隔秒数),当update_interval小于0.5时,round()会把间隔取为0,服务器直接判定请求语法错误。- 批量数据量超限:当
update_interval=0.01时,5秒内会生成500条数据,ThingSpeak的批量更新API对单请求数据量有限制,数据量过大时会触发400错误。
解决方案
1. 修复delta_t计算逻辑
确保delta_t为正整数,修改updatesJson函数中的对应代码:
# 替换原delta_t计算行 elapsed = time.time() - last_update_time message['delta_t'] = max(1, int(round(elapsed))) # 强制delta_t至少为1
2. 控制单批次数据量
在上传前拆分超量数据,避免单次请求数据过多:
# 修改updatesJson中的上传判断逻辑 if time.time() - last_connection_time >= posting_interval: # 限制单批次最多100条数据(可根据ThingSpeak调整) while len(message_buffer) > 100: batch = message_buffer[:100] # 临时替换缓冲区发送当前批次 temp_buffer = message_buffer message_buffer = batch httpRequest() message_buffer = temp_buffer[100:] # 发送剩余数据 if message_buffer: httpRequest() last_update_time = time.time()
3. 优化错误排查
修改httpRequest的异常处理,获取更详细的错误信息:
try: print(request_headers) response = requests.post(url, headers=request_headers, data=bulk_data) print(f"响应状态码: {response.status_code}") print(f"响应内容: {response.text}") # 打印服务器返回的具体错误 except Exception as e: print(f"请求异常: {str(e)}")
4. 匹配硬件与平台限制
你的加速度计设置为100Hz采样,可考虑对数据做降采样(比如每10条取平均值)后再上传,既保留数据趋势,又符合ThingSpeak的上传限制。
内容的提问来源于stack exchange,提问作者Nick Miller
相关产品推荐
相关产品推荐

