树莓派传感器数据上传ThingSpeak报错:SGP30对象无closed属性
Hey there, let's work through why your code stops after one successful data send and throws that 'SGP30' has no attribute 'closed' error. Here's a breakdown of the issues and a fixed version of your code:
1. The Main Error Cause
That chip.closed line at the end of your sensors() function is the problem. The SGP30 class from the sgp30 library doesn’t have a closed attribute at all. Even better—you don’t need this line! The with statement automatically handles closing the SGP30 resource when the block exits, so manual checks or calls like this are unnecessary.
2. Other Hidden Issues to Fix
- Infinite Loop Inside
withBlock: Nesting yourwhile Trueinside thewithblock keeps the SGP30 connection open indefinitely, which can cause resource leaks if the loop breaks unexpectedly. - ThingSpeak Rate Limit: The free ThingSpeak tier only allows one update every 15 seconds. Without a delay, you’ll hit this limit immediately, leading to failed requests.
- Typo in HTTP Header:
Content-typZZeshould beContent-Type—this could have caused silent failures in data sending. - No Sensor Initialization: Most SGP30 implementations require an initialization step to get accurate readings.
Fixed Code
import httplib import urllib import time import sys import Adafruit_DHT from sgp30 import SGP30 from smbus import SMBus # Replace with your actual ThingSpeak API key THINGSPEAK_API_KEY = "xxxxxxx" SMBUS_BUS_NUMBER = 1 def read_sensor_data(chip): """Read and return data from SGP30 and DHT11 sensors""" # Read air quality from SGP30 air_quality = chip.measure_air_quality() voc_ppb = air_quality.voc_ppb co2_ppm = air_quality.co2_ppm # Read temp/humidity from DHT11 humidity, temperature = Adafruit_DHT.read_retry(11, 4) # Handle cases where DHT11 read fails if humidity is None or temperature is None: print("Warning: Failed to read DHT11 data!") return None, None, None, None return temperature, humidity, voc_ppb, co2_ppm def send_to_thingspeak(temp, hum, voc, co2): """Send sensor data to ThingSpeak""" params = urllib.urlencode({ 'field1': temp, 'field2': hum, 'field3': voc, 'field4': co2, 'key': THINGSPEAK_API_KEY }) headers = { "Content-Type": "application/x-www-form-urlencoded", "Accept": "text/plain" } try: conn = httplib.HTTPConnection("api.thingspeak.com:80") conn.request("POST", "/update", params, headers) response = conn.getresponse() print(f"Sent data: Temp={temp}°C | Hum={hum}% | VOC={voc}ppb | CO2={co2}ppm") print(f"ThingSpeak response: {response.status} {response.reason}") conn.close() return True except Exception as e: print(f"Failed to connect: {str(e)}") return False def main(): smbus = SMBus(SMBUS_BUS_NUMBER) # Use with statement to auto-manage SGP30 resource with SGP30(smbus) as sgp_chip: # Initialize SGP30 for accurate readings sgp_chip.initialise() print("Sensors initialized. Starting continuous data upload...") while True: temp, hum, voc, co2 = read_sensor_data(sgp_chip) # Only send data if all sensor readings are valid if all(value is not None for value in [temp, hum, voc, co2]): send_to_thingspeak(temp, hum, voc, co2) # Wait 15 seconds to comply with ThingSpeak's free tier limit time.sleep(15) if __name__ == "__main__": try: main() except KeyboardInterrupt: print("\nProgram stopped by user.") sys.exit(0)
Key Changes Explained
- Removed
chip.closed: Thewithstatement takes care of closing the SGP30 connection automatically when the program exits the block. - Restructured Code: Split sensor reading and data sending into separate functions for better readability and reusability.
- Added SGP30 Initialization: The
sgp_chip.initialise()call ensures the sensor calibrates itself for accurate air quality readings. - 15-Second Delay: Prevents hitting ThingSpeak’s rate limit, which is critical for consistent data uploads.
- Fixed Header Typo: Corrected the misspelled
Content-Typeheader to ensure proper HTTP request formatting. - DHT11 Error Handling: Skips sending data if the DHT11 fails to read, avoiding invalid entries in ThingSpeak.
- Clean Exit Handling: Lets you stop the program safely with
Ctrl+Cwithout leaving resources hanging.
This code should run continuously, sending data to ThingSpeak every 15 seconds without hitting the original closed attribute error.
内容的提问来源于stack exchange,提问作者Marcello Ianni

