Hello, I am working on a general use air quality setup which uses an SDS011 from Aliexpress.
It works well, seems very accurate, and is a nice little sensor..
However, all my programming experience is my little dabbling when I was in my mid teens, and now my actual job/business which is based in CNC.
I borrowed some code, but I don't understand it other than it uses the serial port for communication, and that it works nicely (also tried to use a different TX/RX on the Mega to no avail). I can take examples, combine them, and tweak them but my understanding of programming is limited.
In the end I find that the code interferes with otherwise working libraries such as the DT22, or say more complex ones such as Plot.ly over CC3000 wifi. The original code is here: http://www.instructables.com/id/Make-one-PM25-monitor-with-Arduino-UNO/
I've spent a while trying to get up to speed, and on some verions I removed all the display code whilst leraving the sensor code intact. But still issues with some devices.
I am not certain if RAM is a problem, or if it's just the fact that the code for the PM25/PM10 sensor wasn't written in a more contained manner.
Here is my somewhat obfuscated sketch, I tend to just run with things, have it work, and slowly add. It uses the sensor in question, a cheap OLED screen, and also limits how many times it addresses the screen since it appears the serial communication with the device is touchy. I don't program anything with complexity, this thing is bound to cause some annoyance since it's not organized, but it does work in it's current state.
const unsigned char dofly_DuanMa[10]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
//ä½�ç �
unsigned char const dofly_WeiMa[]={
0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
long previousMillis = 0;
unsigned char displayTemp[8];
unsigned int Pm25 = 0;
unsigned int Pm10 = 0;
void DisPm25data(unsigned int value)
{
int i;
if(value/1000)
{
displayTemp[0]=dofly_DuanMa[value/1000%10];//这里最å�Žæ˜¯åŠ å°�数点,共阳和共阴是相å��的。
displayTemp[1]=dofly_DuanMa[value/100%10];
displayTemp[2]=dofly_DuanMa[value/10%10];
}
else
{
if((value/100) != 0)
displayTemp[0]=dofly_DuanMa[value/100%10];//这里最å�Žæ˜¯åŠ å°�数点,共阳和共阴是相å��的。
displayTemp[1]=dofly_DuanMa[value/10%10]|0x80;
displayTemp[2]=dofly_DuanMa[value%10];
}
}
void DisPm10data(unsigned int value)
{
int i;
if(value/1000)
{
displayTemp[4]=dofly_DuanMa[value/1000%10];//这里最å�Žæ˜¯åŠ å°�数点,共阳和共阴是相å��的。
displayTemp[5]=dofly_DuanMa[value/100%10];
displayTemp[6]=dofly_DuanMa[value/10%10];
}
else
{
if((value/100) != 0)
displayTemp[4]=dofly_DuanMa[value/100%10];//这里最å�Žæ˜¯åŠ å°�数点,共阳和共阴是相å��的。
displayTemp[5]=dofly_DuanMa[value/10%10]|0x80;
displayTemp[6]=dofly_DuanMa[value%10];
}
}
void ProcessSerialData()
{
uint8_t mData = 0;
uint8_t i = 0;
uint8_t mPkt[10] = {0};
uint8_t mCheck = 0;
// from www.inovafitness.com
// packet format: AA C0 PM25_Low PM25_High PM10_Low PM10_High 0 0 CRC AB
mData = Serial.read(); delay(2);//wait until packet is received
if(mData == 0xAA)//head1 ok
{
mPkt[0] = mData;
mData = Serial.read();
if(mData == 0xc0)//head2 ok
{
mPkt[1] = mData;
mCheck = 0;
for(i=0;i < 6;i++)//data recv and crc calc
{
mPkt[i+2] = Serial.read();
delay(2);
mCheck += mPkt[i+2];
}
mPkt[8] = Serial.read();
delay(1);
mPkt[9] = Serial.read();
if(mCheck == mPkt[8])//crc ok
{
Serial.flush();
//Serial.write(mPkt,10);
Pm25 = (uint16_t)mPkt[2] | (uint16_t)(mPkt[3]<<8);
Pm10 = (uint16_t)mPkt[4] | (uint16_t)(mPkt[5]<<8);
if(Pm25 > 9999)
Pm25 = 9999;
if(Pm10 > 9999)
Pm10 = 9999;
//get one good packet
return;
}
}
}
}
//my code///////////////////////////////////////////////////////
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);
////////////////////////LCD Refresh Timer
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis1 = 0; // will store last time LED was updated
// constants won't change :
const long interval = 5000; // interval at which to blink (milliseconds)
void setup() {
Serial.begin(9600,SERIAL_8N1);
Pm25=0;
Pm10=0;
// by default, we'll generate the high voltage from the 3.3v line internally! (neat!)
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x64)
// init done
}
// 主循环
void loop() {
ProcessSerialData();
unsigned long currentMillis = millis();
if(currentMillis - previousMillis1 >= interval) {
display.clearDisplay();
// text display tests
display.setTextSize(2);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.print("Pm2.5:");
display.setCursor(75,0);
display.print(Pm25);
display.setCursor(0,15);
display.print("Pm10 :");
display.setCursor(75,15);
display.print(Pm10);
display.display();
}
}
In the end I'd like your opinion on the code written for the sensor, if it's causing a conflict, and so forth. If I were to just avoid problems and not care.. I guess IC2 for a temp/humidity sensor, then some sort of offloading of the Plot.ly VIA serial to another arduino would work. But I suspect it'll all work on one.
My end product or dream is a unit which sends the data to Plot.ly, also averages out the sensor readings (PM2.5,PM10, Temp, Humidity, and etc), and finally perhaps does a running line/Scope like plot over various intervals. The volcano is bad here in Hawai'i, and so it would be nice to have a practical device that I can mill up a nice wood case for if I manage to finish this simple project.