diff --git a/datasheets/CD_DS_SCD4x_Datasheet_D1.pdf b/datasheets/CD_DS_SCD4x_Datasheet_D1.pdf new file mode 100644 index 00000000..4d31654e Binary files /dev/null and b/datasheets/CD_DS_SCD4x_Datasheet_D1.pdf differ diff --git a/devices/SCD40.js b/devices/SCD40.js new file mode 100644 index 00000000..3c98dc40 --- /dev/null +++ b/devices/SCD40.js @@ -0,0 +1,216 @@ +/* Copyright (c) 2025 Hywel Warsop. See the file LICENSE for copying permission. */ +/* +Module for Sensiron SCD40, SCD41 and SCD43. + +I2C2.setup({scl:B10,sda:B3}); +var scd = require("SCD40").connectI2C(I2C2); + +//single measurement +scd.measure_single_shot(); +scd.get_data_ready_status(); +readings = scd.read_measurement(); +console.log({readings}); + +//continous measurement (5 sec interval) +scd.start_periodic_measurement(); +readings = scd.read_measurement(); +console.log({readings}); + +scd.stop_periodic_measurement() +*/ + +var C = { + I2C_ADDR : 0x62, + + REQUEST_SINGLE_LOOKUP : [0x21,0x9d], + REQUEST_SINGLE_LOOKUP_RHT : [0x21,0x96], + START_MEASUREMENTS : [0x21,0xb1], + START_LOW_POWER_MEASUREMENTS : [0x21,0xac], + STOP_MEASUREMENTS : [0x3f,0x86], + IS_DATA_READY : [0xe4,0xb8], + READ_DATA : [0xec,0x05], + + PERFORM_FORCED_RECALIBARTION : 0x362f, + GET_AUTOMATIC_SELF_CALIBRATION_ENABLED : [0x23,0x13], + SET_AUTOMATIC_SELF_CALIBRATION_ENABLED : 0x2416, + GET_AUTOMATIC_SELF_CALIBRATION_TARGET : [0x23,0x3f], + SET_AUTOMATIC_SELF_CALIBRATION_TARGET : 0x243a, + + GET_TEMP_OFFSET : [0x23,0x18], + SET_TEMP_OFFSET : 0x241d, + GET_SENSOR_ALTITUDE : [0x23,0x22], + SET_SENSOR_ALTITUDE : 0x2427, + GET_AMBIENT_PRESSURE : [0xe0,0x00], + SET_AMBIENT_PRESSURE : 0xe000, + + PERSIST_SETTINGS : [0x36,0x15], + GET_SERIAL_NUMBER : [0x36,0x82], + PERfORM_SELF_TEST : [0x36,0x39], + FACTORY_RESET : [0x36,0x32], + RE_INIT : [0x36,0x46], + + /** Chip identifier */ + CHIP_GET_VARIANT : [0x20,0x2f], + CHIP_VARIANT : [0x0441,0x1440,0x5441],//scd40,scd41,scd43 + + POWER_DOWN : [0x36,0xe0], + WAKE_UP : [0x36,0xf6], + + GET_CALIBRATION_INITIAL_PERIOD : [0x23,0x40], + SET_CALIBRATION_INITIAL_PERIOD : 0x2445, + GET_CALIBRATION_STANDARD_PERIOD : [0x23,0x4b], + SET_CALIBRATION_STANDARD_PERIOD : 0x244e +}; + +function SCD40(options,read,simpleRead,write) { + this.w = write; + this.r = read; + this.sr = simpleRead; + this.getValue = function(ref) { + resp = this.r(ref,3); + v = new DataView(resp.buffer); + return v.getInt16(0); + }; + if ( ! C.CHIP_VARIANT.includes(this.getValue(C.CHIP_GET_VARIANT)) ) { + throw new Error("SCDXX not found"); + } + this.crc = function(data) { + "jit"; + bytes=[data>>8,data]; + var crc=0xff; + for (j=0;j<2;++j){ + crc ^= (bytes[j]); + for (var i=8;i>0;i--) { + if (crc & 0x80) { + crc=(crc<<1) ^ 0x31; + } else { + crc=(crc<<1); + } + } + } + return crc; + }; + this.updateValue = function(command,data) { + arr = Uint8Array(5); + update = new DataView(arr.buffer); + update.setInt16(0,command); + update.setInt16(2,data); + update.setInt8(4,this.crc(data)); + this.w(arr); + }; + this.delay_ms = function(d) { + var t = getTime()+d/1000; while(getTime()>8,val}; + int i,j; + unsigned char crc = 0xFF; + for (i = 0; i < 2; ++i) { + crc ^= (data[i]); + for (j = 8; j > 0; --j) { + if (crc & 0x80) + crc = (crc << 1) ^ 0x31; + else + crc = (crc << 1); + } + } + return crc; +} +`); + +*/ + +exports.connectI2C = function(i2c, options) { + var a = (options&&options.addr)||C.I2C_ADDR; + return (new SCD40(options, function(reg, len) { // read + i2c.writeTo(a, reg); +// var t = getTime()+1; while(getTime() +SCD40 +===================== + +* KEYWORDS: Module,SCD40,SCD41,SCD43,Temperature,Humidity,C02 + +This module should work with Sensirons SDC40, SCD41 and SCD43 sensors, although it has only been tested on the SDC40. Use the [SCD40](/modules/SCD40.js) ([About Modules](/Modules)) module for it. + +You can wire this up as follows: + +| Device Pin | Espruino | +| ---------- | -------- | +| 1 (GND) | GND | +| 2 (VCC) | 3.3 | +| 3 (SCL) | B10 | +| 4 (SDA) | B3 | + +How to use my module: + +To Set up the module + +```JavaScript + I2C2.setup({scl:B10,sda:B3}); + var scd = require("SCD40").connectI2C(I2C2); +``` + +To make a single measurement + +```JavaScript + scd.measure_single_shot(); + scd.get_data_ready_status(); + readings = scd.read_measurement(); + console.log({readings}); +``` + +To make a continous measurements + +```JavaScript + scd.start_periodic_measurement(); + readings = scd.read_measurement(); + console.log({readings}); + + scd.stop_periodic_measurement(); +``` + +The other calls as defined in the datasheet have all been set up in the module. + +The module also contains a commented out version of the C code to calculate the crc-8 checksum used for these chips. It runs in around 1.2 ms on the pico, where as the Javascript version takes around 4.5 ms. If performance is an issue this can be used instead. + + Reference + --------- + + * APPEND_JSDOC: MOD123.js + + Using + ----- + + * APPEND_USES: MOD123 \ No newline at end of file