Breadboard - Indoor Air Quality Monitor


#21

@peekay123
Interesting the DHT22 must be on the 3.3V rail. I changed it and it started working.

Does this mean that the Indoor Air Quality shield wont support plugging a DHT22 into
a digital grove port ? I have one plugged in but it gives incorrect readings. I guess
those work fine on the Arduino because they are 5V.

Is there something which can be done to fix that on the PCB ?


#22

So I got enough parts together to solder up the board.


#24

Hi @peekay123 @epierre
I have my handmade perfboard next to the original IAQ shield and by changing the calibration values I can get quite similar WSP2110 and TGS2602 values. Temperature tracks within a couple of degrees.

The problem is the grove dust sensor - the values are wildly erratic. I wasn’t sure if its the new grove dust sensor - I tried swapping the grove dust sensors between the boards and they behave the same (e.g. still looks fine on the original IAQ shield).

I looked at Mohits Eagle schematic (Grove dust is plugged into Grove port pin D1)


I think he has a 10k pullup resistor on the D1 line - although I’m not sure I’m reading it right. I think there may also be a capacitor.

I tried adding in a 10k pullup resistor to my board (in the same manner as the other sensors), but since then when its time to read the dust sensor the core goes offline. I couldn’t find a wiring diagram online for the dust sensor since most people just buy Arduino grove shields.


#25

@Rockvole How erratic are your values ? have you a graph ? In any case, the value should go up quite like a mountain and then go down quietly, there should be no drop.


#26

This is mohits board :

This is my board :

At 9:00 am I swapped the dust sensors between the 2 boards.
At 10:30 I put the pulldown in my own board and it stopped responding.

My board is turned off at 11am but my graphing spreads it over the whole day. Most of the graphs are fairly similar until that point.


#27

I did some more investigating. It seems that my board was offline because it was stuck in the DHT acquire loop. Somehow the DHT was broken during the soldering. I tried reseating it but nothing. I put in a known working DHT and the board came back to life.

I will let it run for a few hours and see how the values compare now.


#28

So I have tried a couple of things but it hasn’t improved the dust sensor readings.

IAQ shield yesterday :

My board yesterday :

At 9am I put in a 100nf capacitor across the WSP2110 (I think this is called a low pass filter or a decoupling capacitor) which is the same as the Grove HCHO board. I think there may be a small improvement on the formaldehyde sensor.

At 3pm I put in a 10nf capacitor across the dust sensor - I think this is what is in the original shield although Im no expert in reading Eagle PCB’s.

I can try a couple of different USB power supplies to see if they are causing noise. Does anyone have any suggestions I can try ?


#29

So I looked into where I could get a high quality USB power supply and it seems that the simplest way was to buy a genuine apple PSU from an Apple store - so that’s what I did.

This is Mohits board this morning :

This is my board this morning with the Apple PSU :

I didn’t include the other sensors since it looks like I will need to recalibrate for the new power supply.

Interesting how closely the two DHT22’s correlate now - it looks like clean power has a big effect on the DHT22 - @mtnscott


#30

@mohit - here is an example of the different results obtained with different PSUs.

On the left is your original PCB, on the right is my handmade board. On day 1 my handmade board has a $2 USB PSU 2.1A. On day 2 I swapped in the Apple PSU 2.4A - you can see it is much more similar to yours then.

The other sensors also give poor results with the cheap PSU, they have a lot of spikes in the results. Also when changing to the apple PSU the TGS2602 values jumped up a lot and had to be pulled down by re-calibrating. I also found the PSU supplied with my ASUS infinity (expensive tablet when I first bought it) gave poor results.


Since these tests I have been trying to find a way to make the results more similar with any PSU - my friend who has done a small amount of electronics suggested a capacitor. Originally I tried a 470 micro-farad which improved things somewhat with the cheap PSU, now I’m using a 2200 micro-farad which has improved things more. I don’t know if this is really the best way to achieve consistency. It might not always be easy to supply the PSU with the devices - I have friends in other countries who I want to send shields, and I would prefer to calibrate them here then send them and have them not change.


#31

Thats is amazing work there @Rockvole ! Thanks for all the analysis. We can try our best to clean out the supply line by adding filters at the input but we can’t guarantee that it will work with every shitty power supply out there.When dealing with AC-DC convertors its best to stick with branded ones for both safety and quality issues. I’ve included a 47uF cap and will add more bypass caps everywhere.


#32

@mohit I don’t expect we should support every crappy PSU. I’m just letting you know what I find in-case it has any effect on your design. Your Shield V1 design is stellar - I don’t get artifacts and the data is clean.

This mornings graphs - your shield :

My breadboard with a 2200 micro-farad capacitor and the crappy $2 PSU :

(looks like I need to calibrate the VOCs down and it would compare pretty well)


#33

@Rockvole - what’s your compiler environment? Your code won’t compile in Netbeans or with the Spark/Particle online compiler.

Too many errors to list!


#34

I tested the HCHO and the mesure spiked when I had 17 people in my home… meaning that either we all polluate or it is sensible not only to HCHO but to CO2 surely…

for PSU, I have them all on my HP screen USB side, so not in direct contact with the power grid.


#35

Hi,
I use Ubuntu command line to compile in the cloud. I never used the online compiler. Also,
the code I have on there is for the old Spark core build environment, I never tried it with the Photon.

The newer Photon code I am using (which is also command line) is for a TGS 2602, DHT-22 and
IIC I2C 128X64 OLED LCD Display Module Arduino/STM32 screen.


#36

Hi,
Are you using the WSP-2110 ? The off-gassing of Formaldehyde in the air is affected by temperature and humidity.
So you could get an increase since all those people would generate quite a bit of additional heat and humidity.
Also, perhaps if you are cooking for all those people it could be even more with the heat/steam produced by pots/ovens etc.


#37

@Rockvole - your code doesn’t compile in the cloud for the Spark Core.

I changed all Spark references to Particle and removed the deprecated “&” from your variables, eg:

// Register Spark variables
Spark.variable(“ip”, &ip_display, STRING);

Here are the cloud compiler errors:

firmware.cpp: In function 'void setup()':

firmware.cpp:105:63: error: no matching function for call to 'CloudClass::variable(const char [12], double&, const CloudVariableTypeDouble&)'
   pinMode(CALIBRATE_BTN, INPUT_PULLUP);
                                                               ^
firmware.cpp:105:63: note: candidates are:
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:48:24: note: static bool CloudClass::variable(const char*, const int&)
     static inline bool variable(const char* varKey, const int& var)
                        ^
../wiring/inc/spark_wiring_cloud.h:48:24: note:   candidate expects 2 arguments, 3 provided
../wiring/inc/spark_wiring_cloud.h:54:24: note: static bool CloudClass::variable(const char*, const int32_t&)
     static inline bool variable(const char* varKey, const int32_t& var)
                        ^
../wiring/inc/spark_wiring_cloud.h:54:24: note:   candidate expects 2 arguments, 3 provided
../wiring/inc/spark_wiring_cloud.h:59:24: note: static bool CloudClass::variable(const char*, const uint32_t&)
     static inline bool variable(const char* varKey, const uint32_t& var)
                        ^
../wiring/inc/spark_wiring_cloud.h:59:24: note:   candidate expects 2 arguments, 3 provided
../wiring/inc/spark_wiring_cloud.h:64:24: note: static bool CloudClass::variable(const char*, const double&)
     static inline bool variable(const char* varKey, const double& var)
                        ^
../wiring/inc/spark_wiring_cloud.h:64:24: note:   candidate expects 2 arguments, 3 provided
../wiring/inc/spark_wiring_cloud.h:69:24: note: static bool CloudClass::variable(const char*, const String&)
     static inline bool variable(const char* varKey, const String& var)
                        ^
../wiring/inc/spark_wiring_cloud.h:69:24: note:   candidate expects 2 arguments, 3 provided
../wiring/inc/spark_wiring_cloud.h:74:24: note: static bool CloudClass::variable(const char*, const char*)
     static inline bool variable(const char* varKey, const char* var)
                        ^
../wiring/inc/spark_wiring_cloud.h:74:24: note:   candidate expects 2 arguments, 3 provided
../wiring/inc/spark_wiring_cloud.h:80:24: note: template<unsigned int N> static bool CloudClass::variable(const char*, const char*)
     static inline bool variable(const char* varKey, const char var[N])
                        ^
../wiring/inc/spark_wiring_cloud.h:80:24: note:   template argument deduction/substitution failed:
firmware.cpp:105:63: note:   cannot convert 'reading.reading_struct::temperature' (type 'double') to type 'const char*'
   pinMode(CALIBRATE_BTN, INPUT_PULLUP);
                                                               ^
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:86:24: note: template<unsigned int N> static bool CloudClass::variable(const char*, const unsigned char*)
     static inline bool variable(const char* varKey, const unsigned char var[N])
                        ^
../wiring/inc/spark_wiring_cloud.h:86:24: note:   template argument deduction/substitution failed:
firmware.cpp:105:63: note:   cannot convert 'reading.reading_struct::temperature' (type 'double') to type 'const unsigned char*'
   pinMode(CALIBRATE_BTN, INPUT_PULLUP);
                                                               ^
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:91:24: note: static bool CloudClass::variable(const char*, const uint8_t*, const CloudVariableTypeString&)
     static inline bool variable(const char *varKey, const uint8_t* userVar, const CloudVariableTypeString& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:91:24: note:   no known conversion for argument 2 from 'double' to 'const uint8_t* {aka const unsigned char*}'
../wiring/inc/spark_wiring_cloud.h:96:45: note: static bool CloudClass::variable(const char*, typename T::varref, const T&) [with T = CloudVariableTypeDouble; typename T::varref = const double*]
     template<typename T> static inline bool variable(const char *varKey, const typename T::varref userVar, const T& userVarType)
                                             ^
../wiring/inc/spark_wiring_cloud.h:96:45: note:   no known conversion for argument 2 from 'double' to 'CloudVariableTypeDouble::varref {aka const double*}'
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:101:24: note: static bool CloudClass::variable(const char*, const int32_t*, const CloudVariableTypeInt&)
     static inline bool variable(const char *varKey, const int32_t* userVar, const CloudVariableTypeInt& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:101:24: note:   no known conversion for argument 2 from 'double' to 'const int32_t* {aka const long int*}'
../wiring/inc/spark_wiring_cloud.h:106:24: note: static bool CloudClass::variable(const char*, const uint32_t*, const CloudVariableTypeInt&)
     static inline bool variable(const char *varKey, const uint32_t* userVar, const CloudVariableTypeInt& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:106:24: note:   no known conversion for argument 2 from 'double' to 'const uint32_t* {aka const long unsigned int*}'
../wiring/inc/spark_wiring_cloud.h:113:24: note: template<class T, unsigned int N> static bool CloudClass::variable(const char*, const T (*)[N], const CloudVariableTypeString&)
     static inline bool variable(const char *varKey, const T (*userVar)[N], const CloudVariableTypeString& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:113:24: note:   template argument deduction/substitution failed:
firmware.cpp:105:63: note:   mismatched types 'const T (*)[N]' and 'double'
   pinMode(CALIBRATE_BTN, INPUT_PULLUP);
                                                               ^
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:120:24: note: template<class T> static bool CloudClass::variable(const T*, const String*, const CloudVariableTypeString&)
     static inline bool variable(const T *varKey, const String *userVar, const CloudVariableTypeString& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:120:24: note:   template argument deduction/substitution failed:
firmware.cpp:105:63: note:   cannot convert 'reading.reading_struct::temperature' (type 'double') to type 'const String*'
   pinMode(CALIBRATE_BTN, INPUT_PULLUP);
                                                               ^
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:129:24: note: template<class T> static bool CloudClass::variable(const T*, const String&, const CloudVariableTypeString&)
     static inline bool variable(const T *varKey, const String &userVar, const CloudVariableTypeString& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:129:24: note:   template argument deduction/substitution failed:
firmware.cpp:105:63: note:   cannot convert 'reading.reading_struct::temperature' (type 'double') to type 'const String&'
   pinMode(CALIBRATE_BTN, INPUT_PULLUP);
                                                               ^
firmware.cpp:106:57: error: no matching function for call to 'CloudClass::variable(const char [9], double&, const CloudVariableTypeDouble&)'
   pinMode(USER_SAMPLING_BTN, INPUT_PULLUP);
                                                         ^
firmware.cpp:106:57: note: candidates are:
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:48:24: note: static bool CloudClass::variable(const char*, const int&)
     static inline bool variable(const char* varKey, const int& var)
                        ^
../wiring/inc/spark_wiring_cloud.h:48:24: note:   candidate expects 2 arguments, 3 provided
../wiring/inc/spark_wiring_cloud.h:54:24: note: static bool CloudClass::variable(const char*, const int32_t&)
     static inline bool variable(const char* varKey, const int32_t& var)
                        ^
../wiring/inc/spark_wiring_cloud.h:54:24: note:   candidate expects 2 arguments, 3 provided
../wiring/inc/spark_wiring_cloud.h:59:24: note: static bool CloudClass::variable(const char*, const uint32_t&)
     static inline bool variable(const char* varKey, const uint32_t& var)
                        ^
../wiring/inc/spark_wiring_cloud.h:59:24: note:   candidate expects 2 arguments, 3 provided
../wiring/inc/spark_wiring_cloud.h:64:24: note: static bool CloudClass::variable(const char*, const double&)
     static inline bool variable(const char* varKey, const double& var)
                        ^
../wiring/inc/spark_wiring_cloud.h:64:24: note:   candidate expects 2 arguments, 3 provided
../wiring/inc/spark_wiring_cloud.h:69:24: note: static bool CloudClass::variable(const char*, const String&)
     static inline bool variable(const char* varKey, const String& var)
                        ^
../wiring/inc/spark_wiring_cloud.h:69:24: note:   candidate expects 2 arguments, 3 provided
../wiring/inc/spark_wiring_cloud.h:74:24: note: static bool CloudClass::variable(const char*, const char*)
     static inline bool variable(const char* varKey, const char* var)
                        ^
../wiring/inc/spark_wiring_cloud.h:74:24: note:   candidate expects 2 arguments, 3 provided
../wiring/inc/spark_wiring_cloud.h:80:24: note: template<unsigned int N> static bool CloudClass::variable(const char*, const char*)
     static inline bool variable(const char* varKey, const char var[N])
                        ^
../wiring/inc/spark_wiring_cloud.h:80:24: note:   template argument deduction/substitution failed:
firmware.cpp:106:57: note:   cannot convert 'reading.reading_struct::humidity' (type 'double') to type 'const char*'
   pinMode(USER_SAMPLING_BTN, INPUT_PULLUP);
                                                         ^
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:86:24: note: template<unsigned int N> static bool CloudClass::variable(const char*, const unsigned char*)
     static inline bool variable(const char* varKey, const unsigned char var[N])
                        ^
../wiring/inc/spark_wiring_cloud.h:86:24: note:   template argument deduction/substitution failed:
firmware.cpp:106:57: note:   cannot convert 'reading.reading_struct::humidity' (type 'double') to type 'const unsigned char*'
   pinMode(USER_SAMPLING_BTN, INPUT_PULLUP);
                                                         ^
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:91:24: note: static bool CloudClass::variable(const char*, const uint8_t*, const CloudVariableTypeString&)
     static inline bool variable(const char *varKey, const uint8_t* userVar, const CloudVariableTypeString& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:91:24: note:   no known conversion for argument 2 from 'double' to 'const uint8_t* {aka const unsigned char*}'
../wiring/inc/spark_wiring_cloud.h:96:45: note: static bool CloudClass::variable(const char*, typename T::varref, const T&) [with T = CloudVariableTypeDouble; typename T::varref = const double*]
     template<typename T> static inline bool variable(const char *varKey, const typename T::varref userVar, const T& userVarType)
                                             ^
../wiring/inc/spark_wiring_cloud.h:96:45: note:   no known conversion for argument 2 from 'double' to 'CloudVariableTypeDouble::varref {aka const double*}'
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:101:24: note: static bool CloudClass::variable(const char*, const int32_t*, const CloudVariableTypeInt&)
     static inline bool variable(const char *varKey, const int32_t* userVar, const CloudVariableTypeInt& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:101:24: note:   no known conversion for argument 2 from 'double' to 'const int32_t* {aka const long int*}'
../wiring/inc/spark_wiring_cloud.h:106:24: note: static bool CloudClass::variable(const char*, const uint32_t*, const CloudVariableTypeInt&)
     static inline bool variable(const char *varKey, const uint32_t* userVar, const CloudVariableTypeInt& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:106:24: note:   no known conversion for argument 2 from 'double' to 'const uint32_t* {aka const long unsigned int*}'
../wiring/inc/spark_wiring_cloud.h:113:24: note: template<class T, unsigned int N> static bool CloudClass::variable(const char*, const T (*)[N], const CloudVariableTypeString&)
     static inline bool variable(const char *varKey, const T (*userVar)[N], const CloudVariableTypeString& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:113:24: note:   template argument deduction/substitution failed:
firmware.cpp:106:57: note:   mismatched types 'const T (*)[N]' and 'double'
   pinMode(USER_SAMPLING_BTN, INPUT_PULLUP);
                                                         ^
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:120:24: note: template<class T> static bool CloudClass::variable(const T*, const String*, const CloudVariableTypeString&)
     static inline bool variable(const T *varKey, const String *userVar, const CloudVariableTypeString& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:120:24: note:   template argument deduction/substitution failed:
firmware.cpp:106:57: note:   cannot convert 'reading.reading_struct::humidity' (type 'double') to type 'const String*'
   pinMode(USER_SAMPLING_BTN, INPUT_PULLUP);
                                                         ^
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:129:24: note: template<class T> static bool CloudClass::variable(const T*, const String&, const CloudVariableTypeString&)
     static inline bool variable(const T *varKey, const String &userVar, const CloudVariableTypeString& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:129:24: note:   template argument deduction/substitution failed:
firmware.cpp:106:57: note:   cannot convert 'reading.reading_struct::humidity' (type 'double') to type 'const String&'
   pinMode(USER_SAMPLING_BTN, INPUT_PULLUP);
                                                         ^
firmware.cpp:107:48: error: call of overloaded 'variable(const char [10], int&, const CloudVariableTypeInt&)' is ambiguous
   pinMode(BUZZER_PIN, OUTPUT); 
                                                ^
firmware.cpp:107:48: note: candidates are:
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:96:45: note: static bool CloudClass::variable(const char*, typename T::varref, const T&) [with T = CloudVariableTypeInt; typename T::varref = const int*] <near match>
     template<typename T> static inline bool variable(const char *varKey, const typename T::varref userVar, const T& userVarType)
                                             ^
../wiring/inc/spark_wiring_cloud.h:96:45: note:   no known conversion for argument 2 from 'int' to 'CloudVariableTypeInt::varref {aka const int*}'
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:101:24: note: static bool CloudClass::variable(const char*, const int32_t*, const CloudVariableTypeInt&) <near match>
     static inline bool variable(const char *varKey, const int32_t* userVar, const CloudVariableTypeInt& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:101:24: note:   no known conversion for argument 2 from 'int' to 'const int32_t* {aka const long int*}'
../wiring/inc/spark_wiring_cloud.h:106:24: note: static bool CloudClass::variable(const char*, const uint32_t*, const CloudVariableTypeInt&) <near match>
     static inline bool variable(const char *varKey, const uint32_t* userVar, const CloudVariableTypeInt& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:106:24: note:   no known conversion for argument 2 from 'int' to 'const uint32_t* {aka const long unsigned int*}'
firmware.cpp:108:40: error: call of overloaded 'variable(const char [6], int&, const CloudVariableTypeInt&)' is ambiguous
   pinMode(DUST_PIN, INPUT);
                                        ^
firmware.cpp:108:40: note: candidates are:
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:96:45: note: static bool CloudClass::variable(const char*, typename T::varref, const T&) [with T = CloudVariableTypeInt; typename T::varref = const int*] <near match>
     template<typename T> static inline bool variable(const char *varKey, const typename T::varref userVar, const T& userVarType)
                                             ^
../wiring/inc/spark_wiring_cloud.h:96:45: note:   no known conversion for argument 2 from 'int' to 'CloudVariableTypeInt::varref {aka const int*}'
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h:101:24: note: static bool CloudClass::variable(const char*, const int32_t*, const CloudVariableTypeInt&) <near match>
     static inline bool variable(const char *varKey, const int32_t* userVar, const CloudVariableTypeInt& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:101:24: note:   no known conversion for argument 2 from 'int' to 'const int32_t* {aka const long int*}'
../wiring/inc/spark_wiring_cloud.h:106:24: note: static bool CloudClass::variable(const char*, const uint32_t*, const CloudVariableTypeInt&) <near match>
     static inline bool variable(const char *varKey, const uint32_t* userVar, const CloudVariableTypeInt& userVarType)
                        ^
../wiring/inc/spark_wiring_cloud.h:106:24: note:   no known conversion for argument 2 from 'int' to 'const uint32_t* {aka const long unsigned int*}'
firmware.cpp: In function 'void loop()':
firmware.cpp:155:57: error: call of overloaded 'pulseIn(int, PinState)' is ambiguous
           wsp2110.startSampling(current_ms);            
                                                         ^
firmware.cpp:155:57: note: candidates are:
In file included from ./inc/application.h:36:0,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring.h:83:10: note: uint32_t pulseIn(pin_t, uint16_t)
 uint32_t pulseIn(pin_t pin, uint16_t value);
          ^
In file included from firmware.cpp:10:0:
function_pulseIn.h:40:15: note: long unsigned int pulseIn(uint16_t, uint8_t)
 unsigned long pulseIn(uint16_t pin, uint8_t state) {
               ^
In file included from ../wiring/inc/spark_wiring.h:35:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
firmware.cpp: In function 'bool resolveHost()':
../services/inc/spark_macros.h:55:47: warning: narrowing conversion of '(ip_addr >> 24)' from 'long unsigned int' to 'uint8_t {aka unsigned char}' inside { } [-Wnarrowing]
 #define BYTE_N(x,n)           ((x) >> ((n)*8) & 0x000000FF)
                                               ^
firmware.cpp:265:19: note: in expansion of macro 'BYTE_N'
     cnt++;
                   ^
../services/inc/spark_macros.h:55:47: warning: narrowing conversion of '((ip_addr >> 16) & 255ul)' from 'long unsigned int' to 'uint8_t {aka unsigned char}' inside { } [-Wnarrowing]
 #define BYTE_N(x,n)           ((x) >> ((n)*8) & 0x000000FF)
                                               ^
firmware.cpp:265:38: note: in expansion of macro 'BYTE_N'
     cnt++;
                                      ^
../services/inc/spark_macros.h:55:47: warning: narrowing conversion of '((ip_addr >> 8) & 255ul)' from 'long unsigned int' to 'uint8_t {aka unsigned char}' inside { } [-Wnarrowing]
 #define BYTE_N(x,n)           ((x) >> ((n)*8) & 0x000000FF)
                                               ^
firmware.cpp:265:57: note: in expansion of macro 'BYTE_N'
     cnt++;
                                                         ^
../services/inc/spark_macros.h:55:47: warning: narrowing conversion of '(ip_addr & 255ul)' from 'long unsigned int' to 'uint8_t {aka unsigned char}' inside { } [-Wnarrowing]
 #define BYTE_N(x,n)           ((x) >> ((n)*8) & 0x000000FF)
                                               ^
firmware.cpp:265:76: note: in expansion of macro 'BYTE_N'
     cnt++;
                                                                            ^
In file included from ../wiring/inc/spark_wiring.h:48:0,
                 from ./inc/application.h:36,
                 from firmware.cpp:2:
../wiring/inc/spark_wiring_cloud.h: In instantiation of 'static bool CloudClass::variable(const char*, const T (*)[N], const CloudVariableTypeString&) [with T = char; unsigned int N = 20u]':
firmware.cpp:112:56:   required from here
../wiring/inc/spark_wiring_cloud.h:115:9: error: static assertion failed: 

Use Particle.variable("name", myVar, STRING); without & in front of myVar


         static_assert(sizeof(T)==0, "\n\nUse Particle.variable(\"name\", myVar, STRING); without & in front of myVar\n\n");
         ^
make[2]: *** [../build/target/user/platform-0-lfirmware.o] Error 1
make[1]: *** [user] Error 2
make: *** [main] Error 2

#38

You can try to remove STRING as well.


#39

Hi @sneakthief,
I took a look at the code in the firmware directory. It looks like the main problem is that the pulseIn() function is now provided by particle. So I removed that function call, plus renaming Spark to Particle and it seems to compile now.
Is that the directory you were trying to compile ?

I added those changes to the GitHub repo.


#40

@kennethlimcp - thanks!

Did some other tweaks and got it to compile using both the online and cloud compilers.

@Rockvole - yes, I was trying to compile your github repo. I haven’t tried your latest code yet. I also had to find a compatible repo for Carbon and JpGraph. Not sure if the latter is working properly as I’m getting an error that says: “Your manually specified scale and ticks is not correct. The scale seems too small to hold any of the specified tick marks.” I just manually entered in some values so that may be the issue.

I did my own modifications based on kennethlimcp’s suggestions and got the following code to compile - but the core ends up quickly blinking cyan, then blinking yellow, then back to cyan. Eventually it blinks red. Not sure what’s up.

    #include <queue>
#include "ReadingSync.h"
#include "RgbLedControl.h"
#include "HttpClient.h"
#include "SimpleEeprom.h"
#include "PietteTech_DHT.h"
#include "TGS2602.h"
#include "WSP2110.h"
#include "ShinyeiPPD42NS.h"
#include "function_pulseIn.h"

#define INTERVAL_MINS 10
#define PRE_HEAT_SECS 100
#define CALIBRATION_SAMPLE_FREQUENCY 50
#define CALIBRATION_SAMPLE_INTERVAL 500
#define SAMPLING_FREQUENCY 5      // Number of times to sample sensor
#define SAMPLING_INTERVAL_MS 50   // Number of ms between samples

#define SENSOR_TGS2602          A0
#define SENSOR_WSP2110          A3
#define BUZZER_PIN              A4
#define RED_LED                 A5
#define GREEN_LED               A6
#define BLUE_LED                A7

#define DUST_PIN                D1
#define DHT_PIN                 D2 // D0 // use NOT_CONNECTED if needed  
#define USER_SAMPLING_BTN       D3
#define CALIBRATE_BTN           D4

ReadingSync rs (INTERVAL_MINS, PRE_HEAT_SECS, Time.now());
SimpleEeprom flash;

struct reading_struct {
    int    reading_time = 0;    
    double temperature = 0;
    double humidity = 0;
    int    wsp2110_hcho = 0;    
    int    tgs2602_sewer = 0; 
    float  dust_concentration = 0;    
};

std::queue<reading_struct> q;
reading_struct reading;
int unix_time = 0;
int delay_ms = 0;
int calibration_count=0;
int stage=0;
bool acquired_ip=true;
int uptime_start=0;
float temp_float;

// --------------------------------------------------------------------- RGB LED
RgbLedControl rgbLed (RED_LED, GREEN_LED, BLUE_LED);
RgbLedControl::Color color;

// --------------------------------------------------------------------- DHT22
void dht_wrapper();
PietteTech_DHT DHT(DHT_PIN, DHT22, dht_wrapper);

// --------------------------------------------------------------------- Shinyei PPD42NS
#define DUST_SAMPLE_INTERVAL_MS 30000
ShinyeiPPD42NS dust(DUST_SAMPLE_INTERVAL_MS);

// --------------------------------------------------------------------- WSP2110
WSP2110 wsp2110(SAMPLING_FREQUENCY, SAMPLING_INTERVAL_MS);
float wsp2110_Ro = 300000.0;
char  wsp2110_display[20];

// --------------------------------------------------------------------- TGS2602
TGS2602 tgs2602(SAMPLING_FREQUENCY, SAMPLING_INTERVAL_MS);
float tgs2602_Ro = 340000.0;
char  tgs2602_display[20];

// --------------------------------------------------------------------- HTTP
HttpClient http;
char url[200];
http_request_t request;
http_response_t response;
char hostname[] = "your-website.com";
char ip_display[16];

void setup()
{
  temp_float = flash.readFloat(0);
  if(temp_float==temp_float) // Valid Number
    wsp2110_Ro = temp_float;
  temp_float = flash.readFloat(4);
  if(temp_float==temp_float) // Valid Number
    tgs2602_Ro = temp_float;
  
  pinMode(D7, OUTPUT);
  pinMode(CALIBRATE_BTN, INPUT_PULLUP);
  pinMode(USER_SAMPLING_BTN, INPUT_PULLUP);
  pinMode(BUZZER_PIN, OUTPUT); 
  pinMode(DUST_PIN, INPUT);

  request.ip = {0,0,0,0}; // Fill in if you dont want to resolve host
  //request.ip = {192, 168, 1, 130}; // davidlub
  request.port = 80;  
  resolveHost();
  
  // Register Particle variables
  Particle.variable("ip", ip_display);  
  Particle.variable("temperature", reading.temperature);
  Particle.variable("humidity", reading.humidity);
  Particle.variable("unix_time", unix_time);
  Particle.variable("stage", stage);
  Particle.variable("url", url);  
  
  sprintf(wsp2110_display,"%.2f",wsp2110_Ro);
  Particle.variable("wsp2110", wsp2110_display);  
  //Particle.variable("tgs2602", &tgs2602_sample_avg, INT);
  sprintf(tgs2602_display,"%.2f",tgs2602_Ro);
  Particle.variable("tgs2602", tgs2602_display);    
  
  // Register Particle Functionsb
  Particle.function("calibrate", calibrate);
  Particle.function("sample", sample);
  Particle.function("setWspCalib", setWspCalib);  
  Particle.function("setTgsCalib", setTgsCalib);
  Serial.begin(9600);
}

void dht_wrapper() {
DHT.isrCallback();
}

void loop()
{
  if(color!=rgbLed.RED) color=rgbLed.OFF;
  unix_time=Time.now();
  if(uptime_start<1000000000) uptime_start = unix_time;  
  stage=rs.getStage(unix_time);
  delay_ms=200;  

  switch(stage) {
    case rs.USER_SAMPLING:
    case rs.SAMPLING:
      {
        unsigned long current_ms = millis();  
        if(rs.isFirstSamplingLoop()) {  
          wsp2110.startSampling(current_ms);            
          tgs2602.startSampling(current_ms);
          dust.startSampling(current_ms);
          reading.reading_time = unix_time;
        }
        if(!wsp2110.isSamplingComplete() && wsp2110.isTimeToRead(current_ms)) {
          wsp2110.setAnalogRead(analogRead(SENSOR_WSP2110), current_ms);
        }        
        if(!tgs2602.isSamplingComplete() && tgs2602.isTimeToRead(current_ms)) {
          tgs2602.setAnalogRead(analogRead(SENSOR_TGS2602), current_ms);
        }       
        if(!dust.isSamplingComplete()) {
          unsigned long duration = pulseIn((uint16_t)DUST_PIN, (uint8_t)LOW);
          
          reading.dust_concentration = dust.getConcentration(duration, current_ms);          
        }
        if(wsp2110.isSamplingComplete() && dust.isSamplingComplete() && tgs2602.isSamplingComplete()) {
          reading.wsp2110_hcho = wsp2110.getFormaldehydeGasPercentage(wsp2110_Ro);            
          reading.tgs2602_sewer = tgs2602.getSewerGasPercentage(tgs2602_Ro);            
          rs.setSamplingComplete();
          q.push(reading);
        }
        delay_ms=0;
      }
      break;
    case rs.SEND_READING:
      {
        if(resolveHost()) {
          reading_struct curr_reading;
          bool reading_sent;
          do {
            reading_sent=false;
            curr_reading = q.front();
            sprintf(url, "/iaq/get_reading.php?unix_time=%i&temp=%.2f&hum=%.2f&hcho=%i&sewer=%i&dust=%.2f&core_id=%s&uptime=%i", 
                         curr_reading.reading_time,  
                         curr_reading.temperature, curr_reading.humidity, curr_reading.wsp2110_hcho, 
                         curr_reading.tgs2602_sewer, curr_reading.dust_concentration,
                         Particle.deviceID().c_str(), (unix_time-uptime_start));  
            request.path = url;
            response.body = "";
            http.get(request, response);
            char read_time_chars[12];
            sprintf(read_time_chars, "%d", curr_reading.reading_time);
            String read_time_str(read_time_chars);
            if(read_time_str.equals(response.body)) {
              q.pop();
              reading_sent=true;
            }
          } while(reading_sent && !q.empty());
        } else { // Cant resolve host
            color=rgbLed.RED;
        }
        rs.setReadingSent();        
      }
      break;        
    case rs.CALIBRATING:
      {
        delay_ms=CALIBRATION_SAMPLE_INTERVAL;
        calibration_count++;
        if(calibration_count<=1) {
          wsp2110.startCalibrating();            
          tgs2602.startCalibrating();
        }
        wsp2110_Ro = wsp2110.calibrateInCleanAir(analogRead(SENSOR_WSP2110));        
        tgs2602_Ro = tgs2602.calibrateInCleanAir(analogRead(SENSOR_TGS2602));
        if(calibration_count==CALIBRATION_SAMPLE_FREQUENCY) { // Calibration Complete
          beep(200);
          rs.setCalibratingComplete();
          sprintf(wsp2110_display,"%.2f",wsp2110_Ro);         
          flash.writeFloat(wsp2110_Ro, 0);
          sprintf(tgs2602_display,"%.2f",tgs2602_Ro);         
          flash.writeFloat(tgs2602_Ro, 4);
        }
        color=rgbLed.INTERNAL;
      }
      break;
    case rs.PRE_HEAT_CALIBRATING:
      calibration_count=0;
    case rs.PRE_HEAT_USER_SAMPLING:
    case rs.PRE_HEATING:
      {
        color=rgbLed.ORANGE;
        if(rs.isFirstPreHeatLoop()) { // Take ambient temperature before pre-heating
          read_dht22();
        }
      }
      break;
    case rs.CONTINUE:
      break;            
    default:  
      delay(1);
  }  

  if(digitalRead(CALIBRATE_BTN)==LOW) {
    calibrate(NULL);
  }
  if(digitalRead(USER_SAMPLING_BTN)==LOW) {
    sample(NULL);
  }  

  rgbLed.setLedColor(delay_ms, 100, 3000, color);  
  delay(delay_ms);  
}

void read_dht22() {
    DHT.acquire();
    int cnt=0;
    while (DHT.acquiring())
        {
        if(cnt>100) break;
        delay(30);
        cnt++;
        }
  
reading.humidity = DHT.getHumidity();
reading.temperature = DHT.getCelsius(); 
}

bool resolveHost() {
  if((request.ip[0]+request.ip[1]+request.ip[2]+request.ip[3])==0) {
#if PLATFORM_ID == 0 // CORE
    uint32_t ip_addr = 0; 
    gethostbyname(hostname, strlen(hostname), &ip_addr);
    request.ip = {BYTE_N(ip_addr, 3),BYTE_N(ip_addr, 2),BYTE_N(ip_addr, 1),BYTE_N(ip_addr, 0)};
#elif PLATFORM_ID == 6 // PHOTON   
    request.ip = WiFi.resolve(hostname);   
#endif    
    sprintf(ip_display,"%d.%d.%d.%d",request.ip[0],request.ip[1],request.ip[2],request.ip[3]);
    if((request.ip[0]+request.ip[1]+request.ip[2]+request.ip[3])==0) return false;
  }
  return true;
}

void beep(int delay_ms) {
    analogWrite(BUZZER_PIN, 255);
    delay(delay_ms);
    analogWrite(BUZZER_PIN, 0);
}

int calibrate(String command) {
  rs.startCalibrating(unix_time);
  return 1;
}

int sample(String command) {
  rs.startUserSampling(unix_time);
  return 1;
}

int setWspCalib(String value) {
    char buf[20];
    value.toCharArray(buf,20);
    float f = atof(buf);
    flash.writeFloat(f, 0);
    sprintf(wsp2110_display,"%.2f",f);
    wsp2110_Ro=f;
    return value.length();
}

int setTgsCalib(String value) {
    char buf[20];
    value.toCharArray(buf,20);
    float f = atof(buf);
    flash.writeFloat(f, 4);
    sprintf(tgs2602_display,"%.2f",f); 
    tgs2602_Ro=f;
    return value.length();
}

#41

OK, compiled it and it’s doing something now - I had to change the DHT22 data pullup resistor from 10k to 1k.

The add-on RGB led was flashing orange and displaying “Orange” in the terminal. Then after a few minutes I got “HttpClient> Status Code: 404” so I have to see what the problem is now.