Code Monkey home page Code Monkey logo

pms5003's People

Contributors

jbanaszczyk avatar per1234 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pms5003's Issues

how to read out pmsx003::pmsIdx?

Hi, this is probably a totally stupid beginner question, but I'm working with the basic sketch and want to publish the PM data with MQTT and want to add pmsIdx as part of the topic to get for each i the relevant topic such as /livingroom/PMS7003/PM1dot0 etc.
I tried (successfully) with dataNames but that is the description and not Idx...

for (size_t i = Pmsx003::PM1dot0; i < n; ++i) {
Serial.print(data[i]);
Serial.print("\t");
Serial.print(Pmsx003::dataNames[i]);
Serial.print(" [");
Serial.print(Pmsx003::metrics[i]);
Serial.println();
String topic_send = topic_root;
topic_send += Pmsx003::dataNames[i];
Serial.print("Sending via ");
Serial.println(topic_send);
client.publish(String(topic_send).c_str(), String(data[i]).c_str(),true);
}

Thanks for any help!

Question about sleep and wakeup

Hello,

I went through the spec sheet of the PMS5003 and I have a couple of question about sleep/wake that I couldn't find in the specsheet neither the lib documentation and I hope you can help me with them.

Question

  1. Does the WakeUp/Sleep works in active mode or only in passive mode ?
  2. Is the PIN 3 (SET) needed for that ? Or does the commands goes through the normal serial port ?

Read sensor's data in separate function (out of main loop)

If I use pm01basic sketch it works fine. But if I move read procedure out of void loop(void) to new readPMS() function I receiving CRC Error quite often. Even more: after 10 - 15 minutes I receiving "Pms error: CRC Error" all the time.
How can I move read procedure out of main loop?

Thank You!

Example name

Great job - thank you! Just chage name of examples from "01_Simple" to "Simple" due to Arduino IDE requirements.

Problem Including AltSoftSerial.h

Hello, I am trying to use this library for my PMS sensors and have run into a problem. I am using the modified AltSoftSerial Library as suggested. But when i try to compile i am getting this error.

Arduino: 1.6.5 (Windows 8.1), Board: "Arduino/Genuino Uno"

Build options changed, rebuilding all

In file included from C:\Program Files (x86)\Arduino\libraries\pms5003-master\src/pms.h:7:0,
from PMS5003_1.ino:3:
C:\Program Files (x86)\Arduino\libraries\pms5003-master\src/pmsConfig.h:37:27: fatal error: >AltSoftSerial.h: No such file or directory
#include <AltSoftSerial.h>
^
compilation terminated.
Error compiling.

Could you please help me as to what might be going wrong?

Thank you so much

ESP32 compatibility

Is this library compatible with ESP32? How to connect the sensor to ESP32?

Error compiling for board Arduino

Great work! Would you check the following error (in Arduino IDE version 1.8.1):
\Documents\Arduino\libraries\pms5003-master\src\pms.cpp: In member function 'bool Pms5003::begin()':

\Documents\Arduino\libraries\pms5003-master\src\pms.cpp:73:27: error: could not convert 'AltSoftSerial::begin(9600ul)' from 'void' to 'bool'

if (!pmsSerial.begin(9600)) {

                       ^

C:\Users\Robert\Documents\Arduino\libraries\pms5003-master\src\pms.cpp:73:27: error: in argument to unary !

#include <arduino.h> should be <Arduino.h>

So minor but took me a while to figure out. On case sensitive file systems it uses arduino.h in one of the installed packages instead of Arduino.h which cased confusing errors.

PMS5003I and PMS7003I I2C sensors

I'll need a bit of help to adapt/make this library working with
PMS5003I and PMS7003I, but I am mostly hardware guy and don't
really have expereince with write/modify libraries.
I wrote in the Arduino forum and understood it is not impossible
but will need some work to be done.
I do connect 5003I to Arduino Uno (via level adapter) and I2C
scanner successfully found 0x12 address which those sensors have.
How can advice me to go further?

compile: use of enum error

lib/pms5003/src/pms.h:44:7: error: use of enum 'PmsCmd' without previous declaration
enum PmsCmd : __uint24 {
^
lib/pms5003/src/pms.h:44:16: error: '__uint24' was not declared in this scope
enum PmsCmd : __uint24 {
^

On PlatformIO ESP8266

Compatibility with Arduino Mega 2560

Do you plan to make library compatible with Arduino Mega 2560? If i use it on Mega i cannot retrieve data from the sensor (case Pms5003::noData:). Is there any special requirements for Mega? Thank you!

PmsStatus - CRC Error

As it is listed in PMSStatus codes there is all codes except CRC Error. It happens quite often in my case. Do you have any idea what is the cause of this error and how can I avoid it?

Anyway, thank you for excellent library!

Compatibility ESP8266?

It'd be great if an ESP8266-compatible version could be made in the future, as these sensors are great for wireless sensor stations.

PM1 value of 16973

I made a modification to the 1.0 version of the library to remove dependencies on Software serial and replaced it with "Serial1" to use hardware serial provided by Adafruit feather.

Sometimes, the library returns PM1.0 value of 16973 (i.e. 0x424d)... is this a side effect of switching to hardware serial or is this an issue with the core library code? As I understand it, 0x424d is a special value of some kind.

I also intermittently receive other oddly high (but random) values, which I assume are value transcription errors as well.

Any information would be appreciated.

Modified code, below:

#include "pms.h"

////////////////////////////////////////

#if defined NOMINMAX

#if defined min
#undef min
#endif
template <class T> inline const T& __attribute__((always_inline)) min(const T& a, const T& b);
template <class T> inline const T& __attribute__((always_inline)) min(const T& a, const T& b) {
  return !(b < a) ? a : b;
}

#endif

////////////////////////////////////////

inline void __attribute__((always_inline)) swapEndianBig16(uint16_t *x) {
  constexpr union {
    // endian.test16 == 0x0001 for low endian
    // endian.test16 == 0x0100 for big endian
    // should be properly optimized by compiler
    uint16_t test16;
    uint8_t test8[2];
  } endian = { .test8 = { 1,0 } };

  if (endian.test16 != 0x0100) {
    uint8_t hi = (*x & 0xff00) >> 8;
    uint8_t lo = (*x & 0xff);
    *x = lo << 8 | hi;
  }
}

////////////////////////////////////////

void sumBuffer(uint16_t *sum, const uint8_t *buffer, uint16_t cnt) {
  for (; cnt > 0; --cnt, ++buffer) {
    *sum += *buffer;
  }
}

inline void sumBuffer(uint16_t *sum, const uint16_t data) {
  *sum += (data & 0xFF) + (data >> 8);
}

////////////////////////////////////////

void Pms5003::setTimeout(const decltype(timeout) timeout) {
  Serial1.setTimeout(timeout);
  this->timeout = timeout;
};

decltype(Pms5003::timeout) Pms5003::getTimeout(void) const {
  return timeout;
};

Pms5003::Pms5003() : passive(tribool(unknown)), sleep(tribool(unknown)) {
#if defined PMS_DYNAMIC
  begin();
#endif
};

Pms5003::~Pms5003() {
#if defined PMS_DYNAMIC
  end();
#endif
}

bool Pms5003::begin(void)
{
  Serial1.setTimeout(Pms5003::timeoutPassive);
  Serial1.begin(9600);
  
  return true;
};

void Pms5003::end(void) {
  Serial1.end();
};

size_t Pms5003::available(void) {
  while (Serial1.available()) {
    if (Serial1.peek() != sig[0]) {
      Serial1.read();
    } else {
      break;
    }
  }
  return static_cast<size_t>(Serial1.available());
}

Pms5003::PmsStatus Pms5003::read(pmsData *data, const size_t nData, const uint8_t dataSize) {

  if (available() < (dataSize + 2) * sizeof(pmsData) + sizeof(sig)) {
    return noData;
  }

  Serial1.read(); // Value is equal to sig[0]. There is no need to check the value, it was checked by prior peek()

  if (Serial1.read() != sig[1]) // The rest of the buffer will be invalidated during the next read attempt
    return readError;

  uint16_t sum{ 0 };
  sumBuffer(&sum, (uint8_t *)&sig, sizeof(sig));

  pmsData thisFrameLen{ 0x1c };
  if (Serial1.readBytes((uint8_t*)&thisFrameLen, sizeof(thisFrameLen)) != sizeof(thisFrameLen)) {
    return readError;
  };

  if (thisFrameLen % 2 != 0) {
    return frameLenMismatch;
  }
  sumBuffer(&sum, thisFrameLen);

  const decltype(thisFrameLen) maxFrameLen{ 2 * 0x1c };    // arbitrary

  swapEndianBig16(&thisFrameLen);
  if (thisFrameLen > maxFrameLen) {
    return frameLenMismatch;
  }

  size_t toRead{ min(thisFrameLen - 2, nData * sizeof(pmsData)) };
  if (data == nullptr) {
    toRead = 0;
  }

  if (toRead) {
    if (Serial1.readBytes((uint8_t*)data, toRead) != toRead) {
      return readError;
    }
    sumBuffer(&sum, (uint8_t*)data, toRead);

    for (size_t i = 0; i < nData; ++i) {
      swapEndianBig16(&data[i]);
    }
  }

  pmsData crc;
  for (; toRead < thisFrameLen; toRead += 2) {
    if (Serial1.readBytes((uint8_t*)&crc, sizeof(crc)) != sizeof(crc)) {
      return readError;
    };

    if (toRead < thisFrameLen - 2)
      sumBuffer(&sum, crc);
  }

  swapEndianBig16(&crc);

  if (sum != crc) {
    return sumError;
  }

  return OK;
}

void Pms5003::flushInput(void) {
  
}

bool Pms5003::waitForData(const unsigned int maxTime, const size_t nData) {
  const auto t0 = millis();
  if (nData == 0) {
    for (; (millis() - t0) < maxTime; delay(1)) {
      if (Serial1.available()) {
        return true;
      }
    }
    return Serial1.available();
  }

  for (; (millis() - t0) < maxTime; delay(1)) {
    if (available() >= nData) {
      return true;
    }
  }
  return available() >= nData;
}

bool Pms5003::write(const PmsCmd cmd) {
  static_assert(sizeof(cmd) >= 3, "Wrong definition of PmsCmd (too short)");

  if ((cmd != cmdReadData) && (cmd != cmdWakeup)) {
    flushInput();
  }

  if (Serial1.write(sig, sizeof(sig)) != sizeof(sig)) {
    return false;
  }
  const size_t cmdSize = 3;
  if (Serial1.write((uint8_t*)&cmd, cmdSize) != cmdSize) {
    return false;
  }

  uint16_t sum{ 0 };
  sumBuffer(&sum, sig, sizeof(sig));
  sumBuffer(&sum, (uint8_t*)&cmd, cmdSize);
  swapEndianBig16(&sum);
  if (Serial1.write((uint8_t*)&sum, sizeof(sum)) != sizeof(sum)) {
    return false;
  }

  switch (cmd) {
    case cmdModePassive:
      passive = tribool(true);
      break;
    case cmdModeActive:
      passive = tribool(false);
      break;
    case cmdSleep:
      sleep = tribool(true);
      break;
    case cmdWakeup:
      sleep = tribool(false);
      passive = tribool(false);
      // waitForData(wakeupTime);
      break;
    default:
      break;
  }
  if ((cmd != cmdReadData) && (cmd != cmdWakeup)) {
    const auto responseFrameSize = 8;
    if (!waitForData(ackTimeout, responseFrameSize)) {
      
      return true;
    }
    Pms5003::pmsData response = 0xCCCC;
    read(&response, 1, 1);
  }

  /*
    if ((cmd != cmdReadData) && (cmd != cmdWakeup)) {
      const auto responseFrameSize = 8;
      if (!waitForData(ackTimeout, responseFrameSize)) {
        Serial1.flushInput();
        return false;
      }
      Pms5003::pmsData response = 0xCCCC;
      if (read(&response, 1, 1) != OK) {
        return false;
      }
      if ((response >> 8) != (cmd & 0xFF)) {
        return false;
      }
    }
  */

  return true;
}

const char *Pms5003::getMetrics(const pmsIdx idx) {
  return idx < nValues_PmsDataNames ? Pms5003::metrics[idx] : "???";
}

const char *Pms5003::getDataNames(const pmsIdx idx) {
  return idx < nValues_PmsDataNames ? Pms5003::dataNames[idx] : "???";
}

const char * Pms5003::errorMsg[nValues_PmsStatus]{
  "OK",
  "noData",
  "readError",
  "frameLenMismatch",
  "sumError"
};

const char *Pms5003::metrics[]{
  "mcg/m3",
  "mcg/m3",
  "mcg/m3",

  "mcg/m3",
  "mcg/m3",
  "mcg/m3",

  "/0.1L",
  "/0.1L",
  "/0.1L",
  "/0.1L",
  "/0.1L",
  "/0.1L",

  "???"
};

const char *Pms5003::dataNames[]{
  "PM1.0, CF=1",
  "PM2.5, CF=1",
  "PM10.  CF=1",
  "PM1.0",
  "PM2.5",
  "PM10.",

  "Particles > 0.3 micron",
  "Particles > 0.5 micron",
  "Particles > 1.0 micron",
  "Particles > 2.5 micron",
  "Particles > 5.0 micron",
  "Particles > 10. micron",

  "Reserved_0"
};

Sleep/deep sleep/wakeuptime

Hi,
I love the library and try to put together a script that allows to have the PMS sleep for a while. I simply want to measure PM only every - say - 10min and then go to (deep) sleep.

But I am struggling to realize this. At the moment I am working with delay() but that has the effect, that "something times out" and I do not get ANY readings.

I want to realize that the ESP8266 wakes up, waits an appropriate time so the sensor can get ready to get proper readings and then pulls data, maybe waits 30 sec to get another data sample, and another sample after 30 sec and then sleeps (fan off) and the ESP8266 goes to deep sleep, too.

How could I realize this properly without using delay()?

Many thanks in advance!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.