SPS30 미세먼지 센서를 사용하여 측정한 결과를 시리얼 모니터에서 실수형 숫자로 출력해 볼 수도 있지만 한편으로는 시리얼 플로터로 출력 그래프로 작성해보도록 하자. 파일 탭의 예제에서 SPS30에 Example6_sps30_plotter 아두이노 파일이 포함되어 있음을 알 수 있다, 오픈하여 약간의 정보를 수정하도록 하자.
setup()이 시작되기 전 헤더 영역에서 MASS, NUM, AVR 변수를 설정하는 부분이 있다. MASS = 1, NUM = 0, AVR = 0 으로 수정하여 컴파일 업로딩하자.
MASS = 1로 두면 PM 1.0, 2.5, 4.0, 10.0 의 값을 ugr/m3 단위로 그래프로 출력하게 된다.
//Example6_sps30_plotter_01.ino
/************************************************************************************
* Copyright (c) January 2019, version 1.0 Paul van Haastrecht
*
* Version 1.1 Paul van Haastrecht
* - Changed the I2C information / setup.
* ========================= Highlevel description ================================
*
* This basic reading example sketch will connect to an SPS30 for getting data and
* display the available data. use The plotter : Tools -> Serial Plotter OR Cntrl+Shift+L
* It will take about 10 seconds to start (also depending on the SKIPFIRST settings)
* You can test with normal serial monitor.
*
* ========================= Hardware connections =================================
* /////////////////////////////////////////////////////////////////////////////////
* ## UART UART UART UART UART UART UART UART UART UART UART UART UART UART UART ##
* /////////////////////////////////////////////////////////////////////////////////
*
* Sucessfully test has been performed on an ESP32:
*
* Using serial port1, setting the RX-pin(25) and TX-pin(26)
* Different setup can be configured in the sketch.
*
* SPS30 pin ESP32
* 1 VCC -------- VUSB
* 2 RX -------- TX pin 26
* 3 TX -------- RX pin 25
* 4 Select (NOT CONNECTED)
* 5 GND -------- GND
*
* Also successfully tested on Serial2 (default pins TX:17, RX: 16)
* NO level shifter is needed as the SPS30 is TTL 5V and LVTTL 3.3V compatible
* ..........................................................
* Successfully tested on ATMEGA2560
* Used SerialPort2. No need to set/change RX or TX pin
* SPS30 pin ATMEGA
* 1 VCC -------- 5V
* 2 RX -------- TX2 pin 16
* 3 TX -------- RX2 pin 17
* 4 Select (NOT CONNECTED)
* 5 GND -------- GND
*
* Also tested on SerialPort1 and Serialport3 successfully
* .........................................................
* Failed testing on UNO
* Had to use softserial as there is not a separate serialport. But as the SPS30
* is only working on 115K the connection failed all the time with CRC errors.
*
* Not tested ESP8266
* As the power is only 3V3 (the SPS30 needs 5V)and one has to use softserial,
* I have not tested this.
*
* //////////////////////////////////////////////////////////////////////////////////
* ## I2C I2C I2C I2C I2C I2C I2C I2C I2C I2C I2C I2C I2C I2C I2C I2C I2C I2C ##
* //////////////////////////////////////////////////////////////////////////////////
* NOTE 1:
* Depending on the Wire / I2C buffer size we might not be able to read all the values.
* The buffer size needed is at least 60 while on many boards this is set to 32. The driver
* will determine the buffer size and if less than 64 only the MASS values are returned.
* You can manually edit the Wire.h of your board to increase (if you memory is larg enough)
* one can check the expected number of bytes with the I2C_expect() call as in this example
* see detail document.
*
* NOTE 2:
* As documented in the datasheet, make sure to use external 10K pull-up resistor on
* both the SDA and SCL lines. Otherwise the communication with the sensor will fail random.
*
* ..........................................................
* Successfully tested on ESP32
*
* SPS30 pin ESP32
* 1 VCC -------- VUSB
* 2 SDA -------- SDA (pin 21)
* 3 SCL -------- SCL (pin 22)
* 4 Select ----- GND (select I2c)
* 5 GND -------- GND
*
* The pull-up resistors should be to 3V3
* ..........................................................
* Successfully tested on ATMEGA2560
*
* SPS30 pin ATMEGA
* 1 VCC -------- 5V
* 2 SDA -------- SDA
* 3 SCL -------- SCL
* 4 Select ----- GND (select I2c)
* 5 GND -------- GND
*
* ..........................................................
* Successfully tested on UNO R3
*
* SPS30 pin UNO
* 1 VCC -------- 5V
* 2 SDA -------- A4
* 3 SCL -------- A5
* 4 Select ----- GND (select I2c)
* 5 GND -------- GND
*
* When UNO-board is detected the UART code is excluded as that
* does not work on UNO and will save memory. Also some buffers
* reduced and the call to GetErrDescription() is removed to allow
* enough memory.
* ..........................................................
*
* Successfully tested on ESP8266
* SPS30 pin External ESP8266
* 1 VCC -------- 5V
* 2 SDA -----------------------SDA
* 3 SCL -----------------------SCL
* 4 Select ----- GND --------- GND (select I2c)
* 5 GND -------- GND --------- GND
*
* The pull-up resistors should be to 3V3 from the ESP8266.
*
* ================================= PARAMETERS =====================================
*
* From line 142 there are configuration parameters for the program
*
* ================================== SOFTWARE ======================================
* Sparkfun ESP32
*
* Make sure :
* - To select the Sparkfun ESP32 thing board before compiling
* - The serial monitor is NOT active (will cause upload errors)
* - Press GPIO 0 switch during connecting after compile to start upload to the board
*
*
* ================================ Disclaimer ======================================
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* ===================================================================================
*
* NO support, delivered as is, have fun, good luck !!
*/
#include "sps30.h"
/////////////////////////////////////////////////////////////
/*define communication channel to use for SPS30
valid options:
* I2C_COMMS use I2C communication
* SOFTWARE_SERIAL Arduino variants (NOTE)
* SERIALPORT onLY IF there is NO monitor attached
* SERIALPORT1 Arduino MEGA2560, Sparkfun ESP32 Thing : MUST define new pins as defaults are used for flash memory)
* SERIALPORT2 Arduino MEGA2560 and ESP32
* SERIALPORT3 Arduino MEGA2560 only for now
* NOTE: Softserial has been left in as an option, but as the SPS30 is only
* working on 115K the connection will probably NOT work on any device. */
/////////////////////////////////////////////////////////////
#define SP30_COMMS SERIALPORT2
/////////////////////////////////////////////////////////////
/* define RX and TX pin for softserial and Serial1 on ESP32
* can be set to zero if not applicable / needed */
/////////////////////////////////////////////////////////////
#define TX_PIN 26
#define RX_PIN 25
/////////////////////////////////////////////////////////////
/* define driver debug
* 0 : no messages
* 1 : request sending and receiving
* 2 : request sending and receiving + show protocol errors */
//////////////////////////////////////////////////////////////
#define DEBUG 0
//////////////////////////////////////////////////////////////
* define what you want to see plotted
* MASS 1: include MASS information 0: exclude
* NUM 1: include NUM information 0: exclude
* AVG 1: include average size 0: exclude
*
* In case communication is I2C see remark in top of example */
//////////////////////////////////////////////////////////////
#define MASS 1
#define NUM 0
#define AVG 0
//////////////////////////////////////////////////////////////
/* skip first x readings as they might be wrong
* due to start-up */
//////////////////////////////////////////////////////////////
#define SKIPFIRST 5
///////////////////////////////////////////////////////////////
/////////// NO CHANGES BEYOND THIS POINT NEEDED ///////////////
///////////////////////////////////////////////////////////////
// create constructors
SPS30 sps30;
void setup() {
Serial.begin(115200);
Serial.println(F("Trying to connect"));
// set driver debug level
sps30.EnableDebugging(DEBUG);
// set pins to use for softserial and Serial1 on ESP32
if (TX_PIN != 0 && RX_PIN != 0) sps30.SetSerialPin(RX_PIN,TX_PIN);
// Begin communication channel;
if (sps30.begin(SP30_COMMS) == false) {
Errorloop("could not initialize communication channel.", 0);
}
// check for SPS30 connection
if (sps30.probe() == false) {
Errorloop("could not probe / connect with SPS30", 0);
}
else
Serial.println(F("Detected SPS30"));
// reset SPS30 connection
if (sps30.reset() == false) {
Errorloop("could not reset", 0);
}
// start measurement
if (sps30.start() == true)
Serial.println(F("Measurement started"));
else
Errorloop("Could NOT start measurement", 0);
if (SP30_COMMS == I2C_COMMS) {
if (sps30.I2C_expect() == 4)
Serial.println(F(" !!! Due to I2C buffersize only the SPS30 MASS concentration is available !!! \n"));
}
}
void loop() {
read_all();
delay(1000);
}
/**
* @brief : read and display all values
*/
bool read_all()
{
uint8_t ret, error_cnt = 0;
struct sps_values val;
static uint8_t s_kip = SKIPFIRST;
// loop to get data
do {
ret = sps30.GetValues(&val);
// data might not have been ready
if (ret == ERR_DATALENGTH){
if (error_cnt++ > 3) {
ErrtoMess("Error during reading values: ",ret);
return(false);
}
delay(1000);
}
// if other error
else if(ret != ERR_OK) {
ErrtoMess("Error during reading values: ",ret);
return(false);
}
} while (ret != ERR_OK);
// skip first reading
if (s_kip > 0) {
s_kip--;
return;
}
if (MASS) {
Serial.print(val.MassPM1);
Serial.print(F("\t"));
Serial.print(val.MassPM2);
Serial.print(F("\t"));
Serial.print(val.MassPM4);
Serial.print(F("\t"));
Serial.print(val.MassPM10);
}
if (NUM) {
Serial.print(val.NumPM0);
Serial.print(F("\t"));
Serial.print(val.NumPM1);
Serial.print(F("\t"));
Serial.print(val.NumPM2);
Serial.print(F("\t"));
Serial.print(val.NumPM4);
Serial.print(F("\t"));
Serial.print(val.NumPM10);
}
if (AVG) {
Serial.print(val.PartSize);
}
Serial.print(F("\n"));
}
/**
* @brief : continued loop after fatal error
* @param mess : message to display
* @param r : error code
*
* if r is zero, it will only display the message
*/
void Errorloop(char *mess, uint8_t r)
{
if (r) ErrtoMess(mess, r);
else Serial.println(mess);
Serial.println(F("Program on hold"));
for(;;) delay(100000);
}
/**
* @brief : display error message
* @param mess : message to display
* @param r : error code
*
*/
void ErrtoMess(char *mess, uint8_t r)
{
char buf[80];
Serial.print(mess);
sps30.GetErrDescription(r, buf, 80);
Serial.println(buf);
}//끝
'미세먼지' 카테고리의 다른 글
3반 미세먼지 측정기 조 -아두이노 코드 포함 (0) | 2017.11.13 |
---|---|
미세먼지를 줄이기 위한 미국의 LNG 혼소 엔진 기관차 사례 (0) | 2015.03.31 |
미세먼지제로 LNG 혼소 엔진 인젝터 방식과 기관차 Retrofit(개조) (0) | 2015.03.31 |