├── NDIR_RasPi_C#
├── Assets
│ ├── StoreLogo.png
│ ├── SplashScreen.scale-200.png
│ ├── LockScreenLogo.scale-200.png
│ ├── Square44x44Logo.scale-200.png
│ ├── Wide310x150Logo.scale-200.png
│ ├── Square150x150Logo.scale-200.png
│ └── Square44x44Logo.targetsize-24_altform-unplated.png
├── NDIR_TemporaryKey.pfx
├── App.xaml
├── project.json
├── .gitattributes
├── NDIR.csproj.user
├── Properties
│ ├── AssemblyInfo.cs
│ └── Default.rd.xml
├── MainPage.xaml
├── Package.appxmanifest
├── NDIR.sln
├── App.xaml.cs
├── NDIR.csproj
└── MainPage.xaml.cs
├── .gitignore
├── NDIR_RasPi_Python
├── example.py
└── NDIR.py
├── NDIR_I2C
├── examples
│ └── ReadConcentration
│ │ └── ReadConcentration.ino
├── NDIR_I2C.h
└── NDIR_I2C.cpp
├── NDIR_SoftwareSerial
├── examples
│ └── ReadConcentration
│ │ └── ReadConcentration.ino
├── NDIR_SoftwareSerial.h
└── NDIR_SoftwareSerial.cpp
├── LICENSE
└── README.md
/NDIR_RasPi_C#/Assets/StoreLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SandboxElectronics/NDIR/master/NDIR_RasPi_C#/Assets/StoreLogo.png
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/NDIR_TemporaryKey.pfx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SandboxElectronics/NDIR/master/NDIR_RasPi_C#/NDIR_TemporaryKey.pfx
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/Assets/SplashScreen.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SandboxElectronics/NDIR/master/NDIR_RasPi_C#/Assets/SplashScreen.scale-200.png
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/Assets/LockScreenLogo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SandboxElectronics/NDIR/master/NDIR_RasPi_C#/Assets/LockScreenLogo.scale-200.png
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/Assets/Square44x44Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SandboxElectronics/NDIR/master/NDIR_RasPi_C#/Assets/Square44x44Logo.scale-200.png
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/Assets/Wide310x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SandboxElectronics/NDIR/master/NDIR_RasPi_C#/Assets/Wide310x150Logo.scale-200.png
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/Assets/Square150x150Logo.scale-200.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SandboxElectronics/NDIR/master/NDIR_RasPi_C#/Assets/Square150x150Logo.scale-200.png
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/Assets/Square44x44Logo.targetsize-24_altform-unplated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SandboxElectronics/NDIR/master/NDIR_RasPi_C#/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/project.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "Microsoft.NETCore.UniversalWindowsPlatform": "5.1.0"
4 | },
5 | "frameworks": {
6 | "uap10.0": {}
7 | },
8 | "runtimes": {
9 | "win10-arm": {},
10 | "win10-arm-aot": {},
11 | "win10-x86": {},
12 | "win10-x86-aot": {},
13 | "win10-x64": {},
14 | "win10-x64-aot": {}
15 | }
16 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled Object files
2 | *.slo
3 | *.lo
4 | *.o
5 | *.obj
6 |
7 | # Precompiled Headers
8 | *.gch
9 | *.pch
10 |
11 | # Compiled Dynamic libraries
12 | *.so
13 | *.dylib
14 | *.dll
15 |
16 | # Fortran module files
17 | *.mod
18 |
19 | # Compiled Static libraries
20 | *.lai
21 | *.la
22 | *.a
23 | *.lib
24 |
25 | # Executables
26 | *.exe
27 | *.out
28 | *.app
29 |
--------------------------------------------------------------------------------
/NDIR_RasPi_Python/example.py:
--------------------------------------------------------------------------------
1 | import NDIR
2 | import time
3 |
4 | sensor = NDIR.Sensor(0x4D)
5 |
6 | if sensor.begin() == False:
7 | print("Adaptor initialization FAILED!")
8 | exit()
9 |
10 | while True:
11 | if sensor.measure():
12 | print("CO2 Concentration: " + str(sensor.ppm) + "ppm")
13 | else:
14 | print("Sensor communication ERROR.")
15 |
16 | time.sleep(1)
17 |
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/NDIR_I2C/examples/ReadConcentration/ReadConcentration.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | NDIR_I2C mySensor(0x4D); //Adaptor's I2C address (7-bit, default: 0x4D)
5 |
6 | void setup()
7 | {
8 | Serial.begin(9600);
9 |
10 | if (mySensor.begin()) {
11 | Serial.println("Wait 10 seconds for sensor initialization...");
12 | delay(10000);
13 | } else {
14 | Serial.println("ERROR: Failed to connect to the sensor.");
15 | while(1);
16 | }
17 | }
18 |
19 | void loop() {
20 | if (mySensor.measure()) {
21 | Serial.print("CO2 Concentration is ");
22 | Serial.print(mySensor.ppm);
23 | Serial.println("ppm");
24 | } else {
25 | Serial.println("Sensor communication error.");
26 | }
27 |
28 | delay(1000);
29 | }
30 |
--------------------------------------------------------------------------------
/NDIR_SoftwareSerial/examples/ReadConcentration/ReadConcentration.ino:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | //Select 2 digital pins as SoftwareSerial's Rx and Tx. For example, Rx=2 Tx=3
5 | NDIR_SoftwareSerial mySensor(2, 3);
6 |
7 | void setup()
8 | {
9 | Serial.begin(9600);
10 |
11 | if (mySensor.begin()) {
12 | Serial.println("Wait 10 seconds for sensor initialization...");
13 | delay(10000);
14 | } else {
15 | Serial.println("ERROR: Failed to connect to the sensor.");
16 | while(1);
17 | }
18 | }
19 |
20 | void loop() {
21 | if (mySensor.measure()) {
22 | Serial.print("CO2 Concentration is ");
23 | Serial.print(mySensor.ppm);
24 | Serial.println("ppm");
25 | } else {
26 | Serial.println("Sensor communication error.");
27 | }
28 |
29 | delay(1000);
30 | }
31 |
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/NDIR.csproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 30F105C9-681E-420b-A277-7C086EAD8A4E
5 | false
6 | pi
7 | Universal
8 | true
9 |
10 |
11 | 30F105C9-681E-420b-A277-7C086EAD8A4E
12 | false
13 | pi
14 | Universal
15 | true
16 |
17 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Sandbox Electronics
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("NDIR")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("NDIR")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Version information for an assembly consists of the following four values:
18 | //
19 | // Major Version
20 | // Minor Version
21 | // Build Number
22 | // Revision
23 | //
24 | // You can specify all the values or you can default the Build and Revision Numbers
25 | // by using the '*' as shown below:
26 | // [assembly: AssemblyVersion("1.0.*")]
27 | [assembly: AssemblyVersion("1.0.0.0")]
28 | [assembly: AssemblyFileVersion("1.0.0.0")]
29 | [assembly: ComVisible(false)]
--------------------------------------------------------------------------------
/NDIR_SoftwareSerial/NDIR_SoftwareSerial.h:
--------------------------------------------------------------------------------
1 | /*
2 | Description:
3 | This is a example code for Sandbox Electronics NDIR CO2 sensor module.
4 | You can get one of those products on
5 | http://sandboxelectronics.com
6 |
7 | Version:
8 | V1.2
9 |
10 | Release Date:
11 | 2019-01-10
12 |
13 | Author:
14 | Tiequan Shao support@sandboxelectronics.com
15 |
16 | Lisence:
17 | CC BY-NC-SA 3.0
18 |
19 | Please keep the above information when you use this code in your project.
20 | */
21 |
22 | #ifndef _NDIR_SOFTWARE_SERIAL_H_
23 | #define _NDIR_SOFTWARE_SERIAL_H_
24 |
25 | class NDIR_SoftwareSerial {
26 | public:
27 | NDIR_SoftwareSerial(uint8_t rx_pin, uint8_t tx_pin);
28 |
29 | uint32_t ppm;
30 |
31 | uint8_t begin();
32 | uint8_t measure();
33 | void calibrateZero();
34 | void enableAutoCalibration();
35 | void disableAutoCalibration();
36 |
37 | private:
38 | SoftwareSerial serial;
39 |
40 | uint8_t parse(uint8_t *pbuf);
41 |
42 | static uint8_t cmd_measure[9];
43 | static uint8_t cmd_calibrateZero[9];
44 | static uint8_t cmd_enableAutoCalibration[9];
45 | static uint8_t cmd_disableAutoCalibration[9];
46 | };
47 | #endif
48 |
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/Properties/Default.rd.xml:
--------------------------------------------------------------------------------
1 |
17 |
18 |
19 |
20 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/NDIR_I2C/NDIR_I2C.h:
--------------------------------------------------------------------------------
1 | /*
2 | Description:
3 | This is a example code for Sandbox Electronics NDIR CO2 sensor module.
4 | You can get one of those products on
5 | http://sandboxelectronics.com
6 |
7 | Version:
8 | V1.2
9 |
10 | Release Date:
11 | 2018-10-16
12 |
13 | Author:
14 | Tiequan Shao support@sandboxelectronics.com
15 |
16 | Lisence:
17 | CC BY-NC-SA 3.0
18 |
19 | Please keep the above information when you use this code in your project.
20 | */
21 |
22 | #ifndef _NDIR_I2C_H_
23 | #define _NDIR_I2C_H_
24 |
25 | class NDIR_I2C {
26 | public:
27 | NDIR_I2C(uint8_t i2c_addr);
28 |
29 | uint8_t i2c_addr;
30 | uint32_t ppm;
31 |
32 | uint8_t begin();
33 | uint8_t measure();
34 | uint8_t reset();
35 | void calibrateZero();
36 | void enableAutoCalibration();
37 | void disableAutoCalibration();
38 |
39 | private:
40 | static uint8_t cmd_measure[9];
41 | static uint8_t cmd_calibrateZero[9];
42 | static uint8_t cmd_enableAutoCalibration[9];
43 | static uint8_t cmd_disableAutoCalibration[9];
44 |
45 | uint8_t send(uint8_t *pdata, uint8_t n);
46 | uint8_t receive(uint8_t *pbuf, uint8_t n);
47 | uint8_t read_register(uint8_t reg_addr, uint8_t *pval);
48 | uint8_t write_register(uint8_t reg_addr, uint8_t *pdata, uint8_t n);
49 | uint8_t write_register(uint8_t reg_addr, uint8_t val);
50 | uint8_t parse (uint8_t *pbuf);
51 | };
52 | #endif
53 |
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/MainPage.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/Package.appxmanifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
13 |
14 |
15 |
16 |
17 | NDIR
18 | Peng
19 | Assets\StoreLogo.png
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
34 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/NDIR.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NDIR", "NDIR.csproj", "{CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|ARM = Debug|ARM
11 | Debug|x64 = Debug|x64
12 | Debug|x86 = Debug|x86
13 | Release|ARM = Release|ARM
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Debug|ARM.ActiveCfg = Debug|ARM
19 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Debug|ARM.Build.0 = Debug|ARM
20 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Debug|ARM.Deploy.0 = Debug|ARM
21 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Debug|x64.ActiveCfg = Debug|x64
22 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Debug|x64.Build.0 = Debug|x64
23 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Debug|x64.Deploy.0 = Debug|x64
24 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Debug|x86.ActiveCfg = Debug|x86
25 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Debug|x86.Build.0 = Debug|x86
26 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Debug|x86.Deploy.0 = Debug|x86
27 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Release|ARM.ActiveCfg = Release|ARM
28 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Release|ARM.Build.0 = Release|ARM
29 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Release|ARM.Deploy.0 = Release|ARM
30 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Release|x64.ActiveCfg = Release|x64
31 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Release|x64.Build.0 = Release|x64
32 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Release|x64.Deploy.0 = Release|x64
33 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Release|x86.ActiveCfg = Release|x86
34 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Release|x86.Build.0 = Release|x86
35 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}.Release|x86.Deploy.0 = Release|x86
36 | EndGlobalSection
37 | GlobalSection(SolutionProperties) = preSolution
38 | HideSolutionNode = FALSE
39 | EndGlobalSection
40 | EndGlobal
41 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This repository contains Arduino Libraries for Sandbox Electronics NDIR CO2 Sensor with UART/I2C Interface:
2 | http://sandboxelectronics.com/?product=mh-z16-ndir-co2-sensor-with-i2cuart-5v3-3v-interface-for-arduinoraspeberry-pi
3 |
4 | It contains two libraries. Normally only one is needed.
5 | - NDIR_I2C: for communication with the sensor via I2C.
6 | - NDIR_SoftwareSerial: for communication with the sensor via UART (SoftwareSerial).
7 |
8 | Note: The dip switch on the adaptor should be set to I2C or UART accordingly to select I2C or UART mode communication.
9 |
10 | Installling the library (the automatic way)
11 | 1. Click "Download ZIP" button in the top right cornor of this github page and uncompress it.
12 | 2. From the Arduino IDE, Click Sketch->Include Library->Add .ZIP Library..., a file explorer window should popup.
13 | 3. In the popup windows, navigate to the folder what was just uncompressed.
14 | 4. Select one of the following folders:
15 | - NDIR_I2C (which contains NDIR_I2C.cpp and NDIR_I2C.h)
16 | - NDIR_SoftwareSerial (which contains NDIR_SoftwareSerial.cpp and NDIR_SoftwareSerial.h)
17 | 5. Click Open.
18 | 6. Restart the Arduino IDE. The library should now be ready for use.
19 |
20 | Installling the library (the manual way)
21 | 1. Click "Download ZIP" button in the top right cornor of this github page and uncompress it.
22 | 2. From the uncompressed folder, copy one of the following folders to the /libraries/ folder. You may need to create the libraries subfolder if it does not already exist.
23 | - NDIR_I2C (which contains NDIR_I2C.cpp and NDIR_I2C.h)
24 | - NDIR_SoftwareSerial (which contains NDIR_SoftwareSerial.cpp and NDIR_SoftwareSerial.h)
25 | 3. Restart the Arduino IDE. The library should now be ready for use.
26 |
27 | It is recommended to use the automatic way because it automatically places the libraries to the correct path. For manual installation, the path of folder can be found by clicking File->Preferences in the Arduino IDE. The Sketchbook location is on the top of the Preferences page.
28 | - On Windows, libraries folder is normally located at "My Documents\Arduino\libraries"
29 | - On Mac, libraries folder is normally located at "Documents/Arduino/libraries"
30 | - On Linux, libraries folder is normally located at "/home//sketchbook/libraries"
31 |
32 |
--------------------------------------------------------------------------------
/NDIR_RasPi_Python/NDIR.py:
--------------------------------------------------------------------------------
1 | import smbus
2 | import time
3 |
4 | class Sensor():
5 | cmd_measure = [0xFF,0x01,0x9C,0x00,0x00,0x00,0x00,0x00,0x63]
6 | ppm = 0
7 |
8 | IOCONTROL = 0X0E << 3
9 | FCR = 0X02 << 3
10 | LCR = 0X03 << 3
11 | DLL = 0x00 << 3
12 | DLH = 0X01 << 3
13 | THR = 0X00 << 3
14 | RHR = 0x00 << 3
15 | TXLVL = 0X08 << 3
16 | RXLVL = 0X09 << 3
17 |
18 | def __init__(self, i2c_addr):
19 | self.i2c_addr = i2c_addr
20 | self.i2c = smbus.SMBus(1)
21 |
22 | def begin(self):
23 | try:
24 | self.write_register(self.IOCONTROL, 0x08)
25 | except IOError:
26 | pass
27 |
28 | trial = 10
29 |
30 | while trial > 0:
31 | trial = trial - 1
32 |
33 | try:
34 | self.write_register(self.FCR, 0x07)
35 | self.write_register(self.LCR, 0x83)
36 | self.write_register(self.DLL, 0x60)
37 | self.write_register(self.DLH, 0x00)
38 | self.write_register(self.LCR, 0x03)
39 | return True
40 | except IOError:
41 | pass
42 |
43 | return False
44 |
45 | def measure(self):
46 | try:
47 | self.write_register(self.FCR, 0x07)
48 | self.send(self.cmd_measure)
49 | time.sleep(0.01)
50 | self.parse(self.receive())
51 | return True
52 | except IOError:
53 | return False
54 |
55 | def parse(self, response):
56 | checksum = 0
57 |
58 | if len(response) < 9:
59 | return
60 |
61 | for i in range (0, 9):
62 | checksum += response[i]
63 |
64 | if response[0] == 0xFF:
65 | if response[1] == 0x9C:
66 | if checksum % 256 == 0xFF:
67 | self.ppm = (response[2]<<24) + (response[3]<<16) + (response[4]<<8) + response[5]
68 |
69 | def read_register(self, reg_addr):
70 | time.sleep(0.001)
71 | return self.i2c.read_byte_data(self.i2c_addr, reg_addr)
72 |
73 | def write_register(self, reg_addr, val):
74 | time.sleep(0.001)
75 | self.i2c.write_byte_data(self.i2c_addr, reg_addr, val)
76 |
77 | def send(self, command):
78 | if self.read_register(self.TXLVL) >= len(command):
79 | self.i2c.write_i2c_block_data(self.i2c_addr, self.THR, command)
80 |
81 | def receive(self):
82 | n = 9
83 | buf = []
84 | start = time.clock()
85 |
86 | while n > 0:
87 | rx_level = self.read_register(self.RXLVL)
88 |
89 | if rx_level > n:
90 | rx_level = n
91 |
92 | buf.extend(self.i2c.read_i2c_block_data(self.i2c_addr, self.RHR, rx_level))
93 | n = n - rx_level
94 |
95 | if time.clock() - start > 0.2:
96 | break
97 |
98 | return buf
99 |
--------------------------------------------------------------------------------
/NDIR_SoftwareSerial/NDIR_SoftwareSerial.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Description:
3 | This is a example code for Sandbox Electronics NDIR CO2 sensor module.
4 | You can get one of those products on
5 | http://sandboxelectronics.com
6 |
7 | Version:
8 | V1.2
9 |
10 | Release Date:
11 | 2019-01-10
12 |
13 | Author:
14 | Tiequan Shao support@sandboxelectronics.com
15 |
16 | Lisence:
17 | CC BY-NC-SA 3.0
18 |
19 | Please keep the above information when you use this code in your project.
20 | */
21 |
22 | #include
23 | #include
24 | #define RECEIVE_TIMEOUT (100)
25 |
26 | #if ARDUINO >= 100
27 | #include "Arduino.h"
28 | #else
29 | #include "WProgram.h"
30 | #endif
31 |
32 | class SoftwareSerial;
33 |
34 | uint8_t NDIR_SoftwareSerial::cmd_measure[9] = {0xFF,0x01,0x9C,0x00,0x00,0x00,0x00,0x00,0x63};
35 | uint8_t NDIR_SoftwareSerial::cmd_calibrateZero[9] = {0xFF,0x01,0x87,0x00,0x00,0x00,0x00,0x00,0x78};
36 | uint8_t NDIR_SoftwareSerial::cmd_enableAutoCalibration[9] = {0xFF,0x01,0x79,0xA0,0x00,0x00,0x00,0x00,0xE6};
37 | uint8_t NDIR_SoftwareSerial::cmd_disableAutoCalibration[9] = {0xFF,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x86};
38 |
39 | NDIR_SoftwareSerial::NDIR_SoftwareSerial(uint8_t rx_pin, uint8_t tx_pin) : serial(rx_pin, tx_pin, false)
40 | {
41 | }
42 |
43 |
44 | uint8_t NDIR_SoftwareSerial::begin()
45 | {
46 | serial.begin(9600);
47 |
48 | if (measure()) {
49 | return true;
50 | } else {
51 | return false;
52 | }
53 | }
54 |
55 | uint8_t NDIR_SoftwareSerial::measure()
56 | {
57 | uint8_t i;
58 | uint8_t buf[9];
59 | uint32_t start = millis();
60 |
61 | serial.flush();
62 |
63 | for (i=0; i<9; i++) {
64 | serial.write(cmd_measure[i]);
65 | }
66 |
67 | for (i=0; i<9;) {
68 | if (serial.available()) {
69 | buf[i++] = serial.read();
70 | }
71 |
72 | if (millis() - start > RECEIVE_TIMEOUT) {
73 | return false;
74 | }
75 | }
76 |
77 | if (parse(buf)) {
78 | return true;
79 | }
80 |
81 | return false;
82 | }
83 |
84 |
85 | void NDIR_SoftwareSerial::calibrateZero()
86 | {
87 | uint8_t i;
88 |
89 | for (i=0; i<9; i++) {
90 | serial.write(cmd_calibrateZero[i]);
91 | }
92 | }
93 |
94 |
95 | void NDIR_SoftwareSerial::enableAutoCalibration()
96 | {
97 | uint8_t i;
98 |
99 | for (i=0; i<9; i++) {
100 | serial.write(cmd_enableAutoCalibration[i]);
101 | }
102 | }
103 |
104 |
105 | void NDIR_SoftwareSerial::disableAutoCalibration()
106 | {
107 | uint8_t i;
108 |
109 | for (i=0; i<9; i++) {
110 | serial.write(cmd_disableAutoCalibration[i]);
111 | }
112 | }
113 |
114 |
115 | uint8_t NDIR_SoftwareSerial::parse(uint8_t *pbuf)
116 | {
117 | uint8_t i;
118 | uint8_t checksum = 0;
119 |
120 | for (i=0; i<9; i++) {
121 | checksum += pbuf[i];
122 | }
123 |
124 | if (pbuf[0] == 0xFF && pbuf[1] == 0x9C && checksum == 0xFF) {
125 | ppm = (uint32_t)pbuf[2] << 24 | (uint32_t)pbuf[3] << 16 | (uint32_t)pbuf[4] << 8 | pbuf[5];
126 | return true;
127 | } else {
128 | return false;
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/App.xaml.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Description:
3 | This is the C# example code for Sandbox Electronics NDIR CO2 sensor module.
4 | You can get one of those products at
5 | http://sandboxelectronics.com
6 |
7 | Version:
8 | V0.5
9 |
10 | Release Date:
11 | 2017-01-17
12 |
13 | Author:
14 | Peng Wei
15 |
16 | Lisence:
17 | CC BY-NC-SA 3.0
18 |
19 | Please keep the above information when you use this code in your project.
20 | */
21 |
22 | using System;
23 | using System.Collections.Generic;
24 | using System.IO;
25 | using System.Linq;
26 | using System.Runtime.InteropServices.WindowsRuntime;
27 | using Windows.ApplicationModel;
28 | using Windows.ApplicationModel.Activation;
29 | using Windows.Foundation;
30 | using Windows.Foundation.Collections;
31 | using Windows.UI.Xaml;
32 | using Windows.UI.Xaml.Controls;
33 | using Windows.UI.Xaml.Controls.Primitives;
34 | using Windows.UI.Xaml.Data;
35 | using Windows.UI.Xaml.Input;
36 | using Windows.UI.Xaml.Media;
37 | using Windows.UI.Xaml.Navigation;
38 |
39 | namespace NDIR
40 | {
41 | ///
42 | /// Provides application-specific behavior to supplement the default Application class.
43 | ///
44 | sealed partial class App : Application
45 | {
46 | ///
47 | /// Initializes the singleton application object. This is the first line of authored code
48 | /// executed, and as such is the logical equivalent of main() or WinMain().
49 | ///
50 | public App()
51 | {
52 | this.InitializeComponent();
53 | this.Suspending += OnSuspending;
54 | }
55 |
56 | ///
57 | /// Invoked when the application is launched normally by the end user. Other entry points
58 | /// will be used such as when the application is launched to open a specific file.
59 | ///
60 | /// Details about the launch request and process.
61 | protected override void OnLaunched(LaunchActivatedEventArgs e)
62 | {
63 |
64 | #if DEBUG
65 | if (System.Diagnostics.Debugger.IsAttached)
66 | {
67 | this.DebugSettings.EnableFrameRateCounter = true;
68 | }
69 | #endif
70 |
71 | Frame rootFrame = Window.Current.Content as Frame;
72 |
73 | // Do not repeat app initialization when the Window already has content,
74 | // just ensure that the window is active
75 | if (rootFrame == null)
76 | {
77 | // Create a Frame to act as the navigation context and navigate to the first page
78 | rootFrame = new Frame();
79 | // Set the default language
80 | rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];
81 |
82 | rootFrame.NavigationFailed += OnNavigationFailed;
83 |
84 | if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
85 | {
86 | //TODO: Load state from previously suspended application
87 | }
88 |
89 | // Place the frame in the current Window
90 | Window.Current.Content = rootFrame;
91 | }
92 |
93 | if (rootFrame.Content == null)
94 | {
95 | // When the navigation stack isn't restored navigate to the first page,
96 | // configuring the new page by passing required information as a navigation
97 | // parameter
98 | rootFrame.Navigate(typeof(MainPage), e.Arguments);
99 | }
100 | // Ensure the current window is active
101 | Window.Current.Activate();
102 | }
103 |
104 | ///
105 | /// Invoked when Navigation to a certain page fails
106 | ///
107 | /// The Frame which failed navigation
108 | /// Details about the navigation failure
109 | void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
110 | {
111 | throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
112 | }
113 |
114 | ///
115 | /// Invoked when application execution is being suspended. Application state is saved
116 | /// without knowing whether the application will be terminated or resumed with the contents
117 | /// of memory still intact.
118 | ///
119 | /// The source of the suspend request.
120 | /// Details about the suspend request.
121 | private void OnSuspending(object sender, SuspendingEventArgs e)
122 | {
123 | var deferral = e.SuspendingOperation.GetDeferral();
124 | //TODO: Save application state and stop any background activity
125 | deferral.Complete();
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/NDIR.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x86
7 | {CA27CCD4-A81C-48CF-AEAB-25D45168C4E1}
8 | AppContainerExe
9 | Properties
10 | NDIR
11 | NDIR
12 | en-US
13 | UAP
14 | 10.0.14393.0
15 | 10.0.10240.0
16 | 14
17 | 512
18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
19 | NDIR_TemporaryKey.pfx
20 |
21 |
22 | true
23 | bin\x86\Debug\
24 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
25 | ;2008
26 | full
27 | x86
28 | false
29 | prompt
30 | true
31 |
32 |
33 | bin\x86\Release\
34 | TRACE;NETFX_CORE;WINDOWS_UWP
35 | true
36 | ;2008
37 | pdbonly
38 | x86
39 | false
40 | prompt
41 | true
42 | true
43 |
44 |
45 | true
46 | bin\ARM\Debug\
47 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
48 | ;2008
49 | full
50 | ARM
51 | false
52 | prompt
53 | true
54 |
55 |
56 | bin\ARM\Release\
57 | TRACE;NETFX_CORE;WINDOWS_UWP
58 | true
59 | ;2008
60 | pdbonly
61 | ARM
62 | false
63 | prompt
64 | true
65 | true
66 |
67 |
68 | true
69 | bin\x64\Debug\
70 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
71 | ;2008
72 | full
73 | x64
74 | false
75 | prompt
76 | true
77 |
78 |
79 | bin\x64\Release\
80 | TRACE;NETFX_CORE;WINDOWS_UWP
81 | true
82 | ;2008
83 | pdbonly
84 | x64
85 | false
86 | prompt
87 | true
88 | true
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 | App.xaml
97 |
98 |
99 | MainPage.xaml
100 |
101 |
102 |
103 |
104 |
105 | Designer
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 | MSBuild:Compile
122 | Designer
123 |
124 |
125 | MSBuild:Compile
126 | Designer
127 |
128 |
129 |
130 | 14.0
131 |
132 |
133 |
140 |
--------------------------------------------------------------------------------
/NDIR_I2C/NDIR_I2C.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | Description:
3 | This is a example code for Sandbox Electronics NDIR CO2 sensor module.
4 | You can get one of those products on
5 | http://sandboxelectronics.com
6 |
7 | Version:
8 | V1.2
9 |
10 | Release Date:
11 | 2018-10-16
12 |
13 | Author:
14 | Tiequan Shao support@sandboxelectronics.com
15 |
16 | Lisence:
17 | CC BY-NC-SA 3.0
18 |
19 | Please keep the above information when you use this code in your project.
20 | */
21 |
22 | #include
23 | #include
24 |
25 | //General Registers
26 | #define RHR (0x00)
27 | #define THR (0X00)
28 | #define IER (0X01)
29 | #define FCR (0X02)
30 | #define IIR (0X02)
31 | #define LCR (0X03)
32 | #define MCR (0X04)
33 | #define LSR (0X05)
34 | #define MSR (0X06)
35 | #define SPR (0X07)
36 | #define TCR (0X06)
37 | #define TLR (0X07)
38 | #define TXLVL (0X08)
39 | #define RXLVL (0X09)
40 | #define IODIR (0X0A)
41 | #define IOSTATE (0X0B)
42 | #define IOINTENA (0X0C)
43 | #define IOCONTROL (0X0E)
44 | #define EFCR (0X0F)
45 |
46 | //Special Registers
47 | #define DLL (0x00)
48 | #define DLH (0X01)
49 |
50 | //Enhanced Registers
51 | #define EFR (0X02)
52 | #define XON1 (0X04)
53 | #define XON2 (0X05)
54 | #define XOFF1 (0X06)
55 | #define XOFF2 (0X07)
56 |
57 | //Application Related
58 | #define SC16IS750_CRYSTCAL_FREQ (14745600UL)
59 | #define RECEIVE_TIMEOUT (100)
60 |
61 | #if ARDUINO >= 100
62 | #include "Arduino.h"
63 | #else
64 | #include "WProgram.h"
65 | #endif
66 |
67 | #define WIRE Wire
68 |
69 | uint8_t NDIR_I2C::cmd_measure[9] = {0xFF,0x01,0x9C,0x00,0x00,0x00,0x00,0x00,0x63};
70 | uint8_t NDIR_I2C::cmd_calibrateZero[9] = {0xFF,0x01,0x87,0x00,0x00,0x00,0x00,0x00,0x78};
71 | uint8_t NDIR_I2C::cmd_enableAutoCalibration[9] = {0xFF,0x01,0x79,0xA0,0x00,0x00,0x00,0x00,0xE6};
72 | uint8_t NDIR_I2C::cmd_disableAutoCalibration[9] = {0xFF,0x01,0x79,0x00,0x00,0x00,0x00,0x00,0x86};
73 |
74 | NDIR_I2C::NDIR_I2C(uint8_t i2c_addr)
75 | {
76 | if (i2c_addr >= 8 && i2c_addr < 120) {
77 | NDIR_I2C::i2c_addr = i2c_addr;
78 | } else {
79 | NDIR_I2C::i2c_addr = 0;
80 | }
81 | }
82 |
83 |
84 | uint8_t NDIR_I2C::begin()
85 | {
86 | if (i2c_addr) {
87 | WIRE.begin();
88 | write_register(IOCONTROL, 0x08);
89 |
90 | if (write_register(FCR, 0x07)) {
91 | if (write_register(LCR, 0x83)) {
92 | if (write_register(DLL, 0x60)) {
93 | if (write_register(DLH, 0x00)) {
94 | if (write_register(LCR, 0x03)) {
95 | if (measure()) {
96 | return true;
97 | }
98 | }
99 | }
100 | }
101 | }
102 | }
103 | }
104 |
105 | return false;
106 | }
107 |
108 | uint8_t NDIR_I2C::measure()
109 | {
110 | uint8_t buf[9];
111 |
112 | if (i2c_addr) {
113 | if (write_register(FCR, 0x07)) {
114 | delayMicroseconds(1);
115 |
116 | if (send(cmd_measure, 9)) {
117 | if (receive(buf, 9)) {
118 | if (parse(buf)) {
119 | return true;
120 | }
121 | }
122 | }
123 | }
124 | }
125 |
126 | return false;
127 | }
128 |
129 |
130 | uint8_t NDIR_I2C::reset()
131 | {
132 | if (i2c_addr) {
133 | if (write_register(IOSTATE, 0x00)) {
134 | if (write_register(IODIR, 0x01)) {
135 | delay(1000);
136 |
137 | if (write_register(IOSTATE, 0x01)) {
138 | return true;
139 | }
140 | }
141 | }
142 | }
143 |
144 | return false;
145 | }
146 |
147 |
148 | void NDIR_I2C::calibrateZero()
149 | {
150 | if (i2c_addr) {
151 | if (write_register(FCR, 0x07)) {
152 | delayMicroseconds(1);
153 | send(cmd_calibrateZero, 9);
154 | delay(100);
155 | }
156 | }
157 | }
158 |
159 |
160 | void NDIR_I2C::enableAutoCalibration()
161 | {
162 | if (i2c_addr) {
163 | if (write_register(FCR, 0x07)) {
164 | delayMicroseconds(1);
165 | send(cmd_enableAutoCalibration, 9);
166 | delay(100);
167 | }
168 | }
169 | }
170 |
171 |
172 | void NDIR_I2C::disableAutoCalibration()
173 | {
174 | if (i2c_addr) {
175 | if (write_register(FCR, 0x07)) {
176 | delayMicroseconds(1);
177 | send(cmd_disableAutoCalibration, 9);
178 | delay(100);
179 | }
180 | }
181 | }
182 |
183 |
184 | uint8_t NDIR_I2C::parse (uint8_t *pbuf)
185 | {
186 | uint8_t i;
187 | uint8_t checksum = 0;
188 |
189 | for (i=0; i<9; i++) {
190 | checksum += pbuf[i];
191 | }
192 |
193 | if (pbuf[0] == 0xFF && pbuf[1] == 0x9C && checksum == 0xFF) {
194 | ppm = (uint32_t)pbuf[2] << 24 | (uint32_t)pbuf[3] << 16 | (uint32_t)pbuf[4] << 8 | pbuf[5];
195 | return true;
196 | } else {
197 | return false;
198 | }
199 | }
200 |
201 |
202 | uint8_t NDIR_I2C::send(uint8_t *pdata, uint8_t n) {
203 | uint8_t result;
204 |
205 | if (read_register(TXLVL, &result)) {
206 | if (result >= n) {
207 | if (write_register(THR, pdata, n)) {
208 | return true;
209 | }
210 | }
211 | }
212 |
213 | return false;
214 | }
215 |
216 |
217 | uint8_t NDIR_I2C::receive(uint8_t *pbuf, uint8_t n) {
218 | uint8_t i;
219 | uint8_t rx_level;
220 | uint32_t start = millis();
221 |
222 | while (n) {
223 | if (read_register(RXLVL, &rx_level)) {
224 | if (rx_level > n) {
225 | rx_level = n;
226 | }
227 |
228 | if (rx_level) {
229 | WIRE.beginTransmission(i2c_addr);
230 | WIRE.write(RHR << 3);
231 |
232 | if (WIRE.endTransmission() != 0) {
233 | return false;
234 | }//delay(10);
235 |
236 | if (rx_level == WIRE.requestFrom(i2c_addr, rx_level)) {
237 | for (i=0; i RECEIVE_TIMEOUT) {
251 | return false;
252 | }
253 | }
254 |
255 | return true;
256 | }
257 |
258 |
259 | uint8_t NDIR_I2C::read_register(uint8_t reg_addr, uint8_t *pval)
260 | {
261 | uint8_t result;
262 |
263 | WIRE.beginTransmission(i2c_addr);
264 | WIRE.write(reg_addr << 3);
265 |
266 | if (WIRE.endTransmission() != 0) {
267 | return false;
268 | }
269 |
270 | if (WIRE.requestFrom(i2c_addr, (uint8_t)1) != 1) {
271 | return false;
272 | }
273 |
274 | *pval = WIRE.read();
275 | return true;
276 | }
277 |
278 |
279 | uint8_t NDIR_I2C::write_register(uint8_t reg_addr, uint8_t *pdata, uint8_t n)
280 | {
281 | uint8_t result;
282 |
283 | WIRE.beginTransmission(i2c_addr);
284 | WIRE.write(reg_addr << 3);
285 |
286 | while (n--) {
287 | WIRE.write(*pdata);
288 | pdata++;
289 | }
290 |
291 | if (WIRE.endTransmission() != 0) {
292 | return false;
293 | } else {
294 | return true;
295 | }
296 | }
297 |
298 |
299 | uint8_t NDIR_I2C::write_register(uint8_t reg_addr, uint8_t val)
300 | {
301 | return write_register(reg_addr, &val, 1);
302 | }
303 |
304 |
--------------------------------------------------------------------------------
/NDIR_RasPi_C#/MainPage.xaml.cs:
--------------------------------------------------------------------------------
1 | /*
2 | Description:
3 | This is the C# example code for Sandbox Electronics NDIR CO2 sensor module.
4 | You can get one of those products at
5 | http://sandboxelectronics.com
6 |
7 | Version:
8 | V0.5
9 |
10 | Release Date:
11 | 2017-01-17
12 |
13 | Author:
14 | Peng Wei
15 |
16 | Lisence:
17 | CC BY-NC-SA 3.0
18 |
19 | Please keep the above information when you use this code in your project.
20 | */
21 |
22 | using System;
23 | using System.Threading;
24 | using System.Linq;
25 | using Windows.UI.Xaml.Controls;
26 | using Windows.Devices.I2c;
27 |
28 | namespace NDIR
29 | {
30 | public sealed partial class MainPage : Page
31 | {
32 | private const byte ADAPTOR_I2C_ADDR = 0x4D; /* 7-bit I2C address of the Adaptor */
33 | private const byte IOCONTROL = (byte)(0x0E << 3);
34 | private const byte FCR = (byte)(0x02 << 3);
35 | private const byte LCR = (byte)(0x03 << 3);
36 | private const byte DLL = (byte)(0x00 << 3);
37 | private const byte DLH = (byte)(0x01 << 3);
38 | private const byte THR = (byte)(0x00 << 3);
39 | private const byte RHR = (byte)(0x00 << 3);
40 | private const byte TXLVL = (byte)(0x08 << 3);
41 | private const byte RXLVL = (byte)(0x09 << 3);
42 | private const byte SPR = (byte)(0x07 << 3);
43 | private byte[] CMD_READ_CONCENTRATION = {0xFF, 0x01, 0x9C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63};
44 |
45 | private I2cDevice Adaptor;
46 | private Timer PeriodicTimer;
47 |
48 | private byte[] Response = new byte[9];
49 | private int Concentration;
50 | private String TextError = "";
51 |
52 | public MainPage()
53 | {
54 | this.InitializeComponent();
55 |
56 | /* Register for the unloaded event so we can clean up upon exit */
57 | Unloaded += MainPage_Unloaded;
58 |
59 | /* Initialize the I2C bus, accelerometer, and timer */
60 | InitSensor();
61 | }
62 |
63 | private async void InitSensor()
64 | {
65 | var settings = new I2cConnectionSettings(ADAPTOR_I2C_ADDR);
66 | settings.BusSpeed = I2cBusSpeed.FastMode;
67 | var controller = await I2cController.GetDefaultAsync();
68 | Adaptor = controller.GetDevice(settings);
69 |
70 | /* Reset Adaptor */
71 | try
72 | {
73 | WriteRegister(IOCONTROL, 0x08);
74 | }
75 | catch
76 | {
77 | /* ignore NACK exception after software reset */
78 | }
79 |
80 | /* Ping Adaptor */
81 | try
82 | {
83 | WriteRegister(SPR, 0x5A);
84 |
85 | if (ReadRegister(SPR) != 0x5A)
86 | {
87 | Text_Error.Text = "Ping FAILED.";
88 | return;
89 | }
90 | }
91 | catch (Exception ex)
92 | {
93 | Text_Error.Text = "I2C Communication Failed: " + ex.Message;
94 | return;
95 | }
96 |
97 | /* Configure Adaptor (FIFO, Baudrate setting etc.) */
98 | try
99 | {
100 | WriteRegister(FCR, 0x07);
101 | WriteRegister(LCR, 0x83);
102 | WriteRegister(DLL, 0x60);
103 | WriteRegister(DLH, 0x00);
104 | WriteRegister(LCR, 0x03);
105 | }
106 | catch (Exception ex)
107 | {
108 | Text_Error.Text = "Failed to Initialize Adaptor: " + ex.Message;
109 | return;
110 | }
111 |
112 | /* Now that everything is initialized, create a timer so we read concentration every 2 seconds */
113 | PeriodicTimer = new Timer(this.TimerCallback, null, 0, 2000);
114 | }
115 |
116 | private void MainPage_Unloaded(object sender, object args)
117 | {
118 | /* Cleanup */
119 | Adaptor.Dispose();
120 | }
121 |
122 | private void TimerCallback(object state)
123 | {
124 | String textConcentration = "ERROR";
125 | String textResponse = "";
126 |
127 | if (ReadConcentration())
128 | {
129 | textConcentration = String.Format("{0:F0}", Concentration);
130 | textResponse = String.Format("[{0:F3}]: {1}", Environment.TickCount / 1000, BitConverter.ToString(Response));
131 | }
132 |
133 | /* UI updates must be invoked on the UI thread */
134 | var task = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
135 | {
136 | Text_Concentration.Text = textConcentration;
137 | Text_Response.Text = textResponse;
138 | Text_Error.Text = TextError;
139 | });
140 | }
141 |
142 | private bool ReadConcentration()
143 | {
144 | byte[] rhr = { RHR };
145 | int start;
146 |
147 | try
148 | {
149 | /* Clear Tx and Rx FIFO */
150 | WriteRegister(FCR, 0x07);
151 |
152 | /* Send command to read concentration */
153 | SendCommand(CMD_READ_CONCENTRATION);
154 |
155 | /* Mark a time in order to avoid dead loop */
156 | start = Environment.TickCount;
157 |
158 | while (true)
159 | {
160 | if (ReadRegister(RXLVL) >= 9)
161 | {
162 | Adaptor.WriteRead(rhr, Response);
163 |
164 | if (ValidateResponse())
165 | {
166 | Concentration = (Response[2] << 24) + (Response[3] << 16) + (Response[4] << 8) + Response[5];
167 | TextError = "";
168 | return true;
169 | }
170 | else
171 | {
172 | break;
173 | }
174 | }
175 |
176 | if (Environment.TickCount >= start)
177 | {
178 | if (Environment.TickCount - start > 200)
179 | {
180 | break;
181 | }
182 | }
183 | else
184 | {
185 | if (Environment.TickCount > 200)
186 | {
187 | break;
188 | }
189 | }
190 | }
191 |
192 | TextError = "Commnication Error.";
193 | return false;
194 | }
195 | catch (Exception ex)
196 | {
197 | TextError = "Commnication Error: " + ex.Message;
198 | return false;
199 | }
200 | }
201 |
202 | private byte ReadRegister(byte reg_addr)
203 | {
204 | byte[] RegAddrBuf = { reg_addr };
205 | byte[] ReadBuf = new byte[1];
206 |
207 | I2cTransferResult result = Adaptor.WriteReadPartial(RegAddrBuf, ReadBuf);
208 |
209 | if (result.Status == I2cTransferStatus.FullTransfer)
210 | {
211 | return ReadBuf[0];
212 | }
213 | else
214 | {
215 | return 0;
216 | }
217 | }
218 |
219 | private void WriteRegister(byte reg_addr, byte val)
220 | {
221 | byte[] WriteBuf = { reg_addr, val };
222 |
223 | Adaptor.Write(WriteBuf);
224 | }
225 |
226 | private void SendCommand(byte[] command)
227 | {
228 | byte[] WriteBuf = { THR };
229 | WriteBuf = WriteBuf.Concat(command).ToArray();
230 |
231 | if (ReadRegister(TXLVL) >= command.Length)
232 | {
233 | Adaptor.Write(WriteBuf);
234 | }
235 | }
236 |
237 | private bool ValidateResponse()
238 | {
239 | byte sum = 0;
240 |
241 | foreach (byte b in Response)
242 | {
243 | sum += b;
244 | }
245 |
246 | if (sum == 0xFF)
247 | {
248 | return true;
249 | }
250 | else
251 | {
252 | return false;
253 | }
254 | }
255 | }
256 | }
257 |
--------------------------------------------------------------------------------