2016年12月29日 星期四

Internal ADC - ESP8266 ESP-12 ADC 類比10bit 電壓輸入 0~1V

ADC 問題  5V --> 1V

ESP-12  的ADC,支援的類比為10bit,但電壓範為是0~1V,這點比較特別,一開始輸入2V怎麼都輸出1024,查了很多文才發現這個重點。

10bits = 0....1023

When your potentiometer is near 0V it prints 0 and when it reaches 1V it should print 1024.

資料來源:

http://randomnerdtutorials.com/esp8266-adc-reading-analog-values-with-nodemcu/

PM2.5的感測器 output 為0~5V analog data

源自於

http://www.esp8266-projects.com/2015/03/internal-adc-esp8266.html

Internal ADC - ESP8266

----------------------------------  UPDATE  --------------------------------------

For a ADC Input Frontend with Auto-range capabilities in the 0-40V Input range take a look also at the new ADC Input related article

---------------------------------  UPADTE  ----------------------------------------

Added also a new example for a 0-5V input range with Voltage divider and LSB calculation, "the easy way": ESP8266 internal ADC 2 - the easy way example


 ---------------------------------------------------------------------------------------


    After talking in the previous article about DAC (Digital to analog conversion) let's take a look also to the ADC (Analog to Digital Conversion) process story.

   What is the purpose of an ADC ? 
    The ADC translates an analog input signal to a digital output value representing the size of the input relative to a reference.

   One of the good news about is that ESP8266 has an ADC inside and at least ESP-07ESP-12Olimex MOD-WIFI-ESP8266-DEV modules have the ADC Pin available.


ESP8266 - ESP-07 Module

Olimex MOD-WIFI-ESP8266-DEV

   Some not so good news about ESP8266 internal ADC, at least until now:
  •   Documentation available it's at a very poor level. More like a leaflet combined with a marketing presentation. If you were able to find anything more than this one please feel free to share.  
  •  Only one ADC, one analog input pin, resolution probably determined by the ESP8266 community as been a 10 Bit one thru trial and error or some internal data leakage and has a not so clear range from 0 to about 1V. No other technical specifications. None. Engineering fun :)
  •  Should I ask about the voltage reference? :)

    So, the legitimate Question arrived: it is any good for anything or just a fancy added function for marketing purposes ? Well...will see below

    The first simple application that has come in my mind was to use the new builded Li-ion Battery Module to power up ESP8266 module and in the same time to read the Li-ion Cell voltage thru a long period of time. A voltage logger for the Li-ion Cell if you want. 10 Bits resolution must be enough for the purpose of the experiment, to see some trending data for the Li-ion Cell.


What we will need:


General considerations :

     As maximum voltage input is expected to be 1V only and because our Li-ion Cell fully charged voltage goes up to 4.2-4.3V it's obviously that we need to find a way to "translate" the voltage domain between 0-4.3V to 0-1V. They are many different techniques available for doing that but the easiest one and the one that we will use here is the Resistive Voltage Divider (RVD).

    A RVD (also known as a potential divider) is a passive linear circuit that produces an output voltage (Vout) that is a fraction of its input voltage (Vin). Voltage division is the result of distributing the input voltage among the components of the divider.

  We will use for our project the simpler example of a voltage divider: two resistors connected in series, with the input voltage applied across the resistor pair and the output voltage emerging from the connection between them.

Voltage divider schematic and Vout formula

The result:
Voltage divider


  Few observations about:
  • use high quality resistors, 1% or less with as small as possible ppm/C. In this case were used metal film resistors, 1%, 50ppm/C. Try to avoid carbon ones.
  • avoid long wires that can produce itself a voltage drop due to internal resistance. For a quick explanation and calculation take a look here and for PCB traces here
  • yes, I know, pedants might say breadboard is not a good idea for something like that but believe me, in this case, for a quick test, will make no difference. It's a 10 Bit ADC and we are doing trending measurement.

  Let's find out what resistor values we will need for our RVD:
  • Vinmax = 4.3 V
  • Voutmax = VADCin_max = 1V
  •  Vout=Vin*R2/(R1+R2)
   From the resistor ratio calculation choosed values are: R1=33K and R2=10k. You can choose also other values as long as you keep accurate the ratio between, better go upper that that. 330k and 100k should give the same result for example.


Software implementation

For programming CBDB Board and uploading the driver and the software we will continue to use the LuaUploader as before. 


We will implement 3 different type of ADC Read functions,  to see if any notable difference:

 1. READ_ADC function: 

       function readADC()                 -- simple read adc function
           ad = 0
          ad=ad+adc.read(0)*4/978   -- calibrate it based on your voltage divider AND Vref!
          print(ad)
         return ad
     end



 2. READ_AVG ADC function: 

      function readADC_avg()                 -- read 10 consecutive values and calculate average.
           ad1 = 0
           i=0
           while (i<10) do
                ad1=ad1+adc.read(0)*4/978 --calibrate based on your voltage divider AND Vref!
                --print(ad1)
                i=i+1
           end
           ad1 = ad1/10
           print(ad1)
           return ad1
      end



 2. READ_ DCM function: 

    As probably Read_ADC() and Read_AVG() are pretty straigh forward things I will not insist on them. Read_DCM() function it's a little bit special, as is using a special technique called oversampling and decimation. 

    The theory behind oversampling and decimation is rather complex, but using the method is fairly easy. The technique requires a higher amount of samples. These extra samples can be achieved by oversampling the signal. For each additional bit of resolution, n, the signal must be oversampled four times. To get the best possible representation of a analog input signal, it is necessary to oversample the signal this much, because a larger amount of samples will give a better representation of the input signal, when averaged.

   That means that in our case if we want to increase resolution from 10 to 12 bit we will need to take 16 samples.

    Another requirement to make this method work properly is that the signal-component of interest should not vary during a conversion. However another criteria for a successful enhancement of the resolution is that the input signal has to vary when sampled. This may look like a contradiction, but in this case variation means just a few LSB. The variation should be seen as the noise-component of the signal. When oversampling a signal, there should be noise present to satisfy this demand of small variations in the signal.

   As a conclusion from other ADC related work, IF Read_ADC() will give us very good and accurate results Read_DCM() will go bad and vice-versa. 

     function readADC_dcm()
         ad2 = 0
         i=0
         while (i<16) do
               ad2=ad2+adc.read(0)
               --print(ad2)
               i=i+1
          end
          ad2 = bit.rshift(ad2, 2)
          ad2= ad2*0.001020880 -- 12Bit step value-calibrate based on your voltage divider AND Vref!
          print(ad2)
          return ad2
     end
 


Some first time run results:




Not bad at all! 

Adding a Web interface it's an easy task :

srv=net.createServer(net.TCP)
  srv:listen(80,
     function(conn)
           conn:on("receive",function(conn,payload)
            --print(payload)
           conn:send("HTTP/1.1 200 OK\n\n")
           conn:send("<META HTTP-EQUIV=\"REFRESH\" CONTENT=\"5\">")
           conn:send("<html><title>LOG Server - ESP8266</title><body>")
           conn:send("<h1>Data Logger Server - ESP8266</h1><BR>")
           conn:send("Voltage    :<B><font color=red size=4>"..string.format("%g",ad)..

                            " V</font></b><br>")
           conn:send("Voltage AVG:<B><font color=red size=4>"..string.format("%g",ad1)..

                            " V</font></b><br>")
           conn:send("Voltage DCM:<B><font color=red size=4>"..string.format("%g",ad2)..

                            " V</font></b><br>")
           conn:send("<BR><BR><BR>Node.HEAP     : <b>" .. node.heap() .. "</b><BR>")
           conn:send("IP ADDR    :<b>".. wifi.sta.getip() .. "</b><BR>")
           conn:send("TMR.NOW    :<b>" .. tmr.now() .. "</b><BR<BR><BR>")
           conn:send("</html></body>")
           conn:on("sent",function(conn) conn:close() end)
           conn = nil   
      end)
end)


Test Video:


  

ESP-12測試版 + 溫度溼度感測器 + ThingSpeak

課程-ThingSpeak + 溫度溼度感測器 

目的:

使用ESP-12測試版GPIO16 來讀取DHT11溫度溼度感測器的值,並每隔2秒中上傳至ThingSpeak

電子元件:

1)麵包板 x 1
2) ESP-12測試版主板 x 1
3) 5V , 3.3V 轉換板 x1
4) DHT11 溫度溼度感測器 x1

軟體: 
1)Arduino IDE 1.6.5版本
2) DHT.zip
3) 留意  ESP8266  ESP-12 Tools Board --uploading 接線










程式 :
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //參考 http://www.arduinesp.com/thingspeak #include <ESP8266WiFi.h> #include <dht.h> // replace with your channel's thingspeak API key, String apiKey = "TW60RSJ9YFYLQRGK"; const char* ssid = "74170287"; const char* password = "24063173"; const char* server = "api.thingspeak.com"; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #define dht_dpin 16 //定義訊號要從進來 dht DHT; WiFiClient client; void setup() { Serial.begin(115200); delay(10); pinMode(dht_dpin,INPUT); WiFi.begin(ssid, password); Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); } void loop() { //++++++++++++++++++++++++++++++++++++++++++++++ DHT.read11(dht_dpin); //去library裡面找DHT.read11 float h = DHT.humidity; float t = DHT.temperature; if (isnan(h) || isnan(t)) { Serial.println("Failed to read from DHT sensor!"); return; } if (client.connect(server,80)) { // "184.106.153.149" or api.thingspeak.com String postStr = apiKey; postStr +="&field1="; postStr += String(t); postStr +="&field2="; postStr += String(h); postStr += "\r\n\r\n"; client.print("POST /update HTTP/1.1\n"); client.print("Host: api.thingspeak.com\n"); client.print("Connection: close\n"); client.print("X-THINGSPEAKAPIKEY: "+apiKey+"\n"); client.print("Content-Type: application/x-www-form-urlencoded\n"); client.print("Content-Length: "); client.print(postStr.length()); client.print("\n\n"); client.print(postStr); Serial.print("Temperature: "); Serial.print(t); Serial.print(" degrees Celcius Humidity: "); Serial.print(h); Serial.println("% send to Thingspeak"); } client.stop(); Serial.println("Waiting..."); // thingspeak needs minimum 15 sec delay between updates delay(20000); }

2016年12月28日 星期三

Blynk + pm2.5空氣品質 + DH11 溫度 濕度 感測器

Blynk + pm2.5空氣品質 + DH11 溫度 濕度 感測器


目的:

使用ESP8266  ESP-12 Tools Board 類比輸入A0來讀取PM2.5感測器的電壓值,轉換成PM2.5 之值,GPIO16 讀取DHT11溫度溼度感測器


硬體 (電子元件):

1)麵包板 x 1
2)ESP8266  ESP-12 Tools Board 主板 x 1
3)DHT11 x1 溫度溼度感測器
4)SHARP 原裝夏普 GP2Y1010AU0F PM2.5感測器 x1

5) 3.3V/5V Linear Regulator Voltage x1

6) 220uf  150歐姆


軟體: 

1)Arduino IDE 1.6.5版本
2) DHT.zip
3) Blynk
4) Android 手機安裝Blynk 軟體  App程式
5) 留意  ESP8266  ESP-12 Tools Board --uploading 接線
6) Arduino IDE  ESP8266 board from Tools > Board > Generic ESP8266 Module

  http://www.whatimade.today/esp8266-easiest-way-to-program-so-far/





















/*
=================================================================
Connect the USB-TTL to pc and upload sketch to ESP-12
Note: GPIO0 should be LOW 
      CH_PD and RST should be HIGH for first time flashing the board

GPIO0 should be LOW when uploading sketches
Remember use a 3.3V USB-TTL 
connect RX of board to TX of usb and TX of board to RX
SKETCH: 
edit auth code, ssid and pass 
================================================================= 
*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include <dht.h>   
#define dht_dpin 16  //定義DHT11訊號要從GPIO16進來  
dht DHT;   
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
int measurePin = A0; // ADC  Connect dust sensor to Arduino A0 pin 
int ledPower = 14;   //Connect 3 led driver pins of dust sensor to Arduino D2
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 
int samplingTime = 280;
int deltaTime = 40;
int sleepTime = 9680;
long updateInterval = 250;               //傳送資料時間間隔)
float voMeasured = 0;
float calcVoltage = 0;
float dustDensity = 0;

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "605989b5204247989352d86301a4c4e9";    //Blynk Auth Token : 605989b5204247989352d86301a4c4e9
char ssid[] = "74170287";
char pass[] = "24063173";

void setup() {
  Serial.begin(9600); //Set console baud rate
  pinMode(ledPower,OUTPUT);
  pinMode(dht_dpin,OUTPUT);
  Blynk.begin(auth, ssid, pass);   // auth, ssid, pass ;
  }

void loop() {
  Blynk.run();

  digitalWrite(ledPower,LOW); // power on the LED
  delayMicroseconds(samplingTime);
  voMeasured = analogRead(measurePin); // read the dust value
  delayMicroseconds(deltaTime);
  digitalWrite(ledPower,HIGH); // turn the LED off
  delayMicroseconds(sleepTime);
  // 0 - 5V mapped to 0 - 1023 integer values
  // recover voltage
  calcVoltage = voMeasured *  (3.3 / 1024.0);    //5V change into 3,3V
  // linear eqaution taken from http://www.howmuchsnow.com/arduino/airquality/
  // Chris Nafis (c) 2012
  if (calcVoltage < 0.583) {
       dustDensity = 0;
       }
   else{
        dustDensity = 6 * calcVoltage / 35 - 0.1;
         }
   Serial.print("Raw Signal Value (0-1023): ");
   Serial.print(voMeasured);
   Serial.print(" - Voltage: ");
   Serial.print(calcVoltage);
   Serial.print(" - Dust Density: ");
   Serial.print(dustDensity * 1000); // 這裡將數值呈現改成較常用的單位( ug/m3 )
   Serial.println(" ug/m3 ");
   float T=dustDensity * 1000 ;
  
  Blynk.virtualWrite(V0, voMeasured);   
  Blynk.virtualWrite(V1, calcVoltage);   
  Blynk.virtualWrite(V2, T);

//++++++++++++++++++++++++++++++++++++++++++++++
  DHT.read11(dht_dpin);   //去library裡面找DHT.read11  
  float h = DHT.humidity;
  float t = DHT.temperature;
  float f = t * 9/5 + 32;
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
    }
  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.print("%\t");
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.print("*C\t");
  Serial.print(f);
  Serial.print("*F\n");

  Blynk.virtualWrite(V3, h);   
  Blynk.virtualWrite(V4, t);

//++++++++++++++++++++++++++++++++++++++++++++++
   
}

2016年12月22日 星期四

pm2.5空氣品質感測器






/*
=================================================================
Connect the USB-TTL to pc and upload sketch to ESP-12
Note: GPIO0 should be LOW
      CH_PD and RST should be HIGH for first time flashing the board

GPIO0 should be LOW when uploading sketches
Remember use a 3.3V USB-TTL
connect RX of board to TX of usb and TX of board to RX
SKETCH:
edit auth code, ssid and pass
=================================================================
*/
#define BLYNK_PRINT Serial    // Comment this out to disable prints and save space
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h>
SimpleTimer timer; //create a Timer object

int measurePin = A0; // ADC  Connect dust sensor to Arduino A0 pin
int ledPower = 14;   //Connect 3 led driver pins of dust sensor to Arduino D2
int ledPower1 = 16;   //Connect 3 led driver pins of dust sensor to Arduino D2

int samplingTime = 280;
int deltaTime = 40;
int sleepTime = 9680;
long updateInterval = 250;               //傳送資料時間間隔,測試完請設定1800000(30分鐘)
float voMeasured = 0;
float calcVoltage = 0;
float dustDensity = 0;

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = "605989b5204247989352d86301a4c4e9";    //Blynk Auth Token : 605989b5204247989352d86301a4c4e9
char ssid[] = "74170287";
char pass[] = "24063173";

void setup() {
  Serial.begin(9600); //Set console baud rate
  pinMode(ledPower,OUTPUT);
  pinMode(ledPower1,OUTPUT);
  Blynk.begin(auth, ssid, pass);   // auth, ssid, pass ;
  }

void loop() {
  Blynk.run();

  digitalWrite(ledPower,LOW); // power on the LED
  delayMicroseconds(samplingTime);
  voMeasured = analogRead(measurePin); // read the dust value
  delayMicroseconds(deltaTime);
  digitalWrite(ledPower,HIGH); // turn the LED off
  delayMicroseconds(sleepTime);
  // 0 - 5V mapped to 0 - 1023 integer values
  // recover voltage
  calcVoltage = voMeasured * (3.3 / 1024.0);      //5V change into 3.3V
  // linear eqaution taken from http://www.howmuchsnow.com/arduino/airquality/
  // Chris Nafis (c) 2012
  if (calcVoltage < 0.583) {
       dustDensity = 0;
       }
   else{
        dustDensity = 6 * calcVoltage / 35 - 0.1;
         }
   Serial.print("Raw Signal Value (0-1023): ");
   Serial.print(voMeasured);
   Serial.print(" - Voltage: ");
   Serial.print(calcVoltage);
   Serial.print(" - Dust Density: ");
   Serial.print(dustDensity * 1000); // 這裡將數值呈現改成較常用的單位( ug/m3 )
   Serial.println(" ug/m3 ");
   float T=dustDensity * 1000 ;

  Blynk.virtualWrite(V0, voMeasured);
  Blynk.virtualWrite(V1, calcVoltage);
  Blynk.virtualWrite(V2, T);
  for (byte i=0;i<=9;i++)
   {
     digitalWrite(ledPower1,LOW); // turn the LED off
     delay(updateInterval);   // 設定傳送時間間隔
     digitalWrite(ledPower1,HIGH); // turn the LED off
     delay(updateInterval);   // 設定傳送時間間隔
   }
   
}

2016年12月21日 星期三

利用GP2Y1010AU0F偵測空氣懸浮微粒汙染PM2.5 (ESP8266- Test Board)







/*
 ESP8266 Read input from GPIO14, write to on-board LED
=================================================================
Connect the USB-TTL to pc and upload sketch to ESP-12
Note: GPIO0 should be LOW
      CH_PD and RST should be HIGH for first time flashing the board

GPIO0 should be LOW when uploading sketches
Remember use a 3.3V USB-TTL
connect RX of board to TX of usb and TX of board to RX
SKETCH:
edit auth code, ssid and pass
=================================================================
*/
int measurePin = A0; // ADC  Connect dust sensor to Arduino A0 pin
int ledPower = 14;   //Connect 3 led driver pins of dust sensor to Arduino D2

int samplingTime = 280;
int deltaTime = 40;
int sleepTime = 9680;

float voMeasured = 0;
float calcVoltage = 0;
float dustDensity = 0;

void setup(){
  Serial.begin(9600);
  pinMode(ledPower,OUTPUT);
}

void loop(){
  digitalWrite(ledPower,LOW); // power on the LED
  delayMicroseconds(samplingTime);

  voMeasured = analogRead(measurePin); // read the dust value

  delayMicroseconds(deltaTime);
  digitalWrite(ledPower,HIGH); // turn the LED off
  delayMicroseconds(sleepTime);

  // 0 - 5V mapped to 0 - 1023 integer values
  // recover voltage
  calcVoltage = voMeasured * (5.0 / 1024.0);

  // linear eqaution taken from http://www.howmuchsnow.com/arduino/airquality/
  // Chris Nafis (c) 2012
  dustDensity = 0.17 * calcVoltage - 0.1;

  Serial.print("Raw Signal Value (0-1023): ");
  Serial.print(voMeasured);

  Serial.print(" - Voltage: ");
  Serial.print(calcVoltage);

  Serial.print(" - Dust Density: ");
  Serial.print(dustDensity * 1000); // 這裡將數值呈現改成較常用的單位( ug/m3 )
  Serial.println(" ug/m3 ");
  delay(1000);
}

Standalone: Sharp Dust Sensor

源自於
http://arduinodev.woofex.net/2012/12/01/standalone-sharp-dust-sensor/

We based our work on the excellent post over here but contrary to the author, we did not try out multiple sensors and we are using an Arduino Fio.
In this tutorial, we’ll focus on how to get your Sharp Optical Dust Sensor to work and what to watch out for.
In addition, we will try to provide European shop references and prices in € where possible.

Components

  • Arduino Fio (BoxTec) – ~21.57 €
  • FTDI Basic Breakout 3.3V (BoxTec) – ~14.52 €
  • Sharp Optical Dust Sensor (Robotshop) #GP2Y1010AU0F – 10.75 € – Datasheet
  • 6-pin TE 1.5mm pitch connector cable (DigiKey) #A100196-ND – 1.2 €
  • 220 uF Capacitor
  • 150 Ω Resistor
  • Breadboard
  • M/M jumper cables

Setup

Prerequisites

  • Able to upload sketches via the Arduino IDE to your Arduino
In the figure below you can see the overall setup using an Arduino Fio and the Sharp Dust sensor using a classical Breadboard.
Even though you may use an Xbee shield to load your sketches wirelessly, we use a FTDI breakout board here to connect to our PC.

Overview of the Dust Sensor and the Arduino Fio


  1. Hook up the sensor using the 6 pins in the following way (see Figure below):


Pin numbering on the Sensor


Close-up of breadboard with Dust Sensor and Arduino

You may use the following schema from Sharp and our own drawing to help you in the task:


Official schema from Sharp


Fritzing schema of the Setup using an Arduino Fio

Pins Assignments

Sharp Dust SensorAttached To
1 (V-LED)3.3V Pin (150 Ohm in between)
2 (LED-GND)GND Pin
3 (LED)Digital Pin 12
4 (S-GND)GND Pin
5 (Vo)Analog Pin A6
6 (Vcc)3.3V Pin (Direct)

Code

All updated code and schematics can be found on our github dust module project page.
Before launching the code, there are couple of points which are important.

1. How to interpret the output signal

In the figure below taken from the datasheet, you can see that the Dust density grows linearly with respect to the output voltage (Vo).
In line 52 of the code, we implemented the formula of the linear regression that approximatively follows this curve (courtesy of Chris Nafis).
This will allow us to map output voltages to Dust densities in mg/m³.


Linear range of the Sharp sensor
In addition, on an Arduino, any analog pin will map voltages between integer values from 0-1023 which can be mapped back to a “real” voltage value.
For the Fio, we therefore multiply the analog reading by 3.3/1024.0 and for the Uno, you will want to multiply the reading by 5.0/1024.0.
Important: Be sure to add the trailing zero in these calculations, because if you do not put at least one, you will end up with a nasty bug where all your results will be 0. (Hint: integer division in C)

2. Sampling times

According to the datasheet, we need to switch on the internal LED and wait for 280 µs (microsecond) before measuring the output signal and the duration of the whole excitation pulse should be 320 µs.
We therefore pause for another 40 µs before switching off the LED again.


Pulse-driven wave form


Sampling strategy
 For convenienve, we provide a code snippet here:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*
 Standalone Sketch to use with a Arduino Fio and a
 Sharp Optical Dust Sensor GP2Y1010AU0F
 For Pin connections, please check the Blog or the github project page
 Authors: Cyrille Médard de Chardon (serialC), Christophe Trefois (Trefex)
 Changelog:
   2012-Dec-01:  Cleaned up code
 This work is licensed under the
 Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/
 or send a letter to Creative Commons, 444 Castro Street, Suite 900,
 Mountain View, California, 94041, USA.
*/
int measurePin = 6;
int ledPower = 12;
int samplingTime = 280;
int deltaTime = 40;
int sleepTime = 9680;
float voMeasured = 0;
float calcVoltage = 0;
float dustDensity = 0;
void setup(){
  Serial.begin(9600);
  pinMode(ledPower,OUTPUT);
}
void loop(){
  digitalWrite(ledPower,LOW); // power on the LED
  delayMicroseconds(samplingTime);
  voMeasured = analogRead(measurePin); // read the dust value
  delayMicroseconds(deltaTime);
  digitalWrite(ledPower,HIGH); // turn the LED off
  delayMicroseconds(sleepTime);
  // 0 - 3.3V mapped to 0 - 1023 integer values
  // recover voltage
  calcVoltage = voMeasured * (3.3 / 1024);
  // linear eqaution taken from http://www.howmuchsnow.com/arduino/airquality/
  // Chris Nafis (c) 2012
  dustDensity = 0.17 * calcVoltage - 0.1;
  Serial.print("Raw Signal Value (0-1023): ");
  Serial.print(voMeasured);
  Serial.print(" - Voltage: ");
  Serial.print(calcVoltage);
  Serial.print(" - Dust Density: ");
  Serial.println(dustDensity);
  delay(1000);
}

Running

This snippet was captured using an Arduino Uno. While the setup works with an Arduino Fio, we noticed that we are not able to reach all the values possible by the dust sensor. Looking at figure 3 above (the voltage / dust density graph) the Fio’s maximum signal was about 2V with a corresponding maximum dust density of .25 mg/m³. This is a tolerable limitation as the ambient air quality is unlikely to get that high unless you work in proximity to high airborne particle generating activities such as construction.
In the snippet below you can see that by using a 5V input, we are able to reach the maximum readings outlined by Sharp (around 3.75V, cf linear curve above) by completely blocking the sensor, eg we inserted a pen to simulate absolute horrific air (very dense). The values around 0.8-1V were our baseline in our office.
Whilst with a 5V input you will reach your max at around 3.75Vo, you will reach the maximum already at around 2.25 Vo with a 3.3V input.
We will try to use a 5V-3V logic converter breakout board on the Fio to see if similar results can be obtained.
The table below was obtained using an Arduino Uno, and as expected we reached full capacity on this device.
1
2
3
4
5
6
7
8
9
10
11
12
13
Raw Signal Value (0-1023): 170.00 - Voltage:    0.8330 - Dust Density:    0.0416
Raw Signal Value (0-1023): 188.00 - Voltage:    0.9212 - Dust Density:    0.0566
Raw Signal Value (0-1023): 22.00 - Voltage:    0.1078 - Dust Density:   -0.0817
Raw Signal Value (0-1023): 321.00 - Voltage:    1.5729 - Dust Density:    0.1674
Raw Signal Value (0-1023): 767.00 - Voltage:    3.7583 - Dust Density:    0.5389
Raw Signal Value (0-1023): 767.00 - Voltage:    3.7583 - Dust Density:    0.5389
Raw Signal Value (0-1023): 767.00 - Voltage:    3.7583 - Dust Density:    0.5389
Raw Signal Value (0-1023): 772.00 - Voltage:    3.7828 - Dust Density:    0.5431
Raw Signal Value (0-1023): 768.00 - Voltage:    3.7632 - Dust Density:    0.5397
Raw Signal Value (0-1023): 766.00 - Voltage:    3.7534 - Dust Density:    0.5381
Raw Signal Value (0-1023): 767.00 - Voltage:    3.7583 - Dust Density:    0.5389
Raw Signal Value (0-1023): 767.00 - Voltage:    3.7583 - Dust Density:    0.5389
Raw Signal Value (0-1023): 767.00 - Voltage:    3.7583 - Dust Density:    0.5389
The table below is a readout using the 3.3V supply on the Arduino Fio. As you can, when simulating a completely polluted air, by inserting a pen in the hole, we max out at 2.06V which is equivalent to 250 ug/m^3. As mentioned above, we do not foresee to ever reach these kind of values in Luxembourg, so we will consider this to be acceptable. Keep in mind though that if you want to use this sensor with the full range on an Arduino Fio, you will need a DC-DC step-up/step-down converter in order to supply the 5V input.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Raw Signal Value (0-1023): 192.00 - Voltage: 0.62 - Dust Density [ug/m3]: 5.19
Raw Signal Value (0-1023): 204.00 - Voltage: 0.66 - Dust Density [ug/m3]: 11.76
Raw Signal Value (0-1023): 205.00 - Voltage: 0.66 - Dust Density [ug/m3]: 12.31
Raw Signal Value (0-1023): 640.00 - Voltage: 2.06 - Dust Density [ug/m3]: 250.63
Raw Signal Value (0-1023): 640.00 - Voltage: 2.06 - Dust Density [ug/m3]: 250.63
Raw Signal Value (0-1023): 640.00 - Voltage: 2.06 - Dust Density [ug/m3]: 250.63
Raw Signal Value (0-1023): 639.00 - Voltage: 2.06 - Dust Density [ug/m3]: 250.08
Raw Signal Value (0-1023): 640.00 - Voltage: 2.06 - Dust Density [ug/m3]: 250.63
Raw Signal Value (0-1023): 639.00 - Voltage: 2.06 - Dust Density [ug/m3]: 250.08
Raw Signal Value (0-1023): 640.00 - Voltage: 2.06 - Dust Density [ug/m3]: 250.63
Raw Signal Value (0-1023): 640.00 - Voltage: 2.06 - Dust Density [ug/m3]: 250.63
Raw Signal Value (0-1023): 341.00 - Voltage: 1.10 - Dust Density [ug/m3]: 86.82
Raw Signal Value (0-1023): 640.00 - Voltage: 2.06 - Dust Density [ug/m3]: 250.63
Raw Signal Value (0-1023): 640.00 - Voltage: 2.06 - Dust Density [ug/m3]: 250.63
Raw Signal Value (0-1023): 192.00 - Voltage: 0.62 - Dust Density [ug/m3]: 5.19
Raw Signal Value (0-1023): 245.00 - Voltage: 0.79 - Dust Density [ug/m3]: 34.22

Conclusion

The sensor seems to be quite sensitive and shows relatively consistent results. We suggest to define some ranges that define your air quality, eg from 0.5V-1V Good, 1V-1.5V Poor etc… but it is up to you to define this scale. We suggest getting a baseline in an as clean as possible environment and simulate the maximum by inserting (carefully) a pen filling the whole hole. With the boundaries you can discreetly map the values in between to your preference.
An annoying part is that we cannot reach the maximum using the 3.3V input on the Arduino Fio and had to use the Arduino Uno to reach what was written in the datasheet. We will update this post once we get our hands on a 3.3V-5V logic converter.

MQTT 協定與 Modbus 通訊的遠端監控與控制系統架構

MQTT 協定與 Modbus 通訊的遠端監控與控制系統架構 這張圖片展示了一個 結合 MQTT 協定與 Modbus 通訊的遠端監控與控制系統架構 (主要透過 Node-RED 進行資料整合)。 系統包含三個核心部分,其運作功能說明如下: 1. ESP32 終端設備(硬體控制層...