├── LICENSE.md ├── Makefile ├── README.md ├── d6t-1a.c ├── d6t-32l.c ├── d6t-44l.c ├── d6t-8l.c └── d6t-8lh.c /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 - present OMRON Corporation 4 | 5 | All rights reserved. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | .PHONY: d6t-1a d6t-8l d6t-8lh d6t-44l d6t-32l 3 | 4 | cpplint_flags:=--filter=-readability/casting,-build/include_subdir 5 | ifeq (x$(cpplint),x) 6 | cpplint := @echo lint with cpplint, option: 7 | endif 8 | ifeq (x$(cppcheck),x) 9 | cppcheck := @echo lint with cppcheck, option: 10 | endif 11 | 12 | all: d6t-1a d6t-8l d6t-8lh d6t-44l d6t-32l 13 | 14 | d6t-1a: d6t-1a.c 15 | $(cpplint) $(cpplint_flags) $^ 16 | $(cppcheck) --enable=all $^ 17 | gcc $(CFLAGS) $^ -o $@ 18 | 19 | d6t-8l: d6t-8l.c 20 | $(cpplint) $(cpplint_flags) $^ 21 | $(cppcheck) --enable=all $^ 22 | gcc $(CFLAGS) $^ -o $@ 23 | 24 | d6t-8lh: d6t-8lh.c 25 | $(cpplint) $(cpplint_flags) $^ 26 | $(cppcheck) --enable=all $^ 27 | gcc $(CFLAGS) $^ -o $@ 28 | 29 | d6t-44l: d6t-44l.c 30 | $(cpplint) $(cpplint_flags) $^ 31 | $(cppcheck) --enable=all $^ 32 | gcc $(CFLAGS) $^ -o $@ 33 | 34 | d6t-32l: d6t-32l.c 35 | $(cpplint) $(cpplint_flags) $^ 36 | $(cppcheck) --enable=all $^ 37 | gcc $(CFLAGS) $^ -o $@ 38 | 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # d6t-2jcieev01-raspberrypi 2 | It is a sample projects for D6T OMRON MEMS Thermal Sensors with 3 | evaluation kit **2JCIE-EV01-RP1** and some Raspberry Pi boards. 4 | 5 | D6T sensor series are High Sensitivity Enables Detection 6 | of Stationary Human Presence, 7 | 8 | - OMRON's unique MEMS and ASIC technology achieve a high SNR. 9 | - Superior noise immunity with a digital output. 10 | - High-precision area temperature detection with low cross-talk field of 11 | view characteristics 12 | 13 | 14 | ## Description 15 | this Raspberry Pi sample projects for acquiring data from sensors on 2JCIE-EV01. 16 | sample projects output the sensor data. 17 | 18 | | example | sensor type | pixel number | board | 19 | |:-------:|:---------------------------|:-----------------------|:-----------------------| 20 | | d6t-1a | D6T-1A-01 / D6T-1A-02 | 1x1 | Raspberry-Pi ZERO-W | 21 | | d6t-8l | D6T-8L-09 | 1x8 | Raspberry-Pi ZERO-W | 22 | | d6t-8lh | D6T-8L-09H | 1x8 | Raspberry-Pi ZERO-W | 23 | | d6t-44l | D6T-44L-06 / D6T-44L-06H | 4x4 | Raspberry-Pi ZERO-W | 24 | | d6t-32l | D6T-32L-01A | 32x32 | Raspberry-Pi ZERO-W | 25 | 26 | 27 | ## DEMO 28 | sample output from D6T-44L 29 | 30 | ``` 31 | PTAT: 27.2[degC], Temperature: 27.5, 27.3, 27.3, 27.3, 27.2, 27.1, 27.1, 27.2, 27.1, 27.1, 27.3, 27.3, 27.0, 27.2, 27.3, 27.0, [degC] 32 | PTAT: 27.2[degC], Temperature: 27.4, 27.2, 27.3, 27.2, 27.2, 27.2, 27.3, 27.2, 27.2, 27.1, 27.3, 27.3, 27.0, 27.3, 27.3, 27.1, [degC] 33 | PTAT: 27.2[degC], Temperature: 27.5, 27.2, 27.5, 27.1, 27.2, 27.1, 27.2, 27.1, 27.1, 27.1, 27.3, 28.1, 28.2, 27.5, 27.2, 27.0, [degC] 34 | ``` 35 | 36 | ## Installation 37 | ### Prerequisite 38 | - gcc (pre-installed in standard Raspbian) 39 | - **Required** change I2C speed to 100kHz for D6T-1A/8L/44L (see below) 40 | 41 | 42 | ### Procedure 43 | this procedure shows the procedure to use the sensors on 44 | **2JCIE-EV01-RP1** . 45 | 46 | 1. download the archive from github [releases](releases) or 47 | [master](archive/d6t-2jcieev01-raspberrypi-master.zip) 48 | 49 | ```shell 50 | $ unzip d6t-2jcieev01-raspberrypi-master.zip 51 | ``` 52 | 53 | or, with git: 54 | 55 | ```shell 56 | $ git clone https://github.com/omron-devhub/d6t-2jcieev01-raspberrypi 57 | ``` 58 | 59 | 2. make 60 | 61 | ```shell 62 | $ cd d6t-2jcieev01-raspberrypi-master 63 | $ make all 64 | ``` 65 | 66 | 3. run 67 | 68 | ```shell 69 | $ ./d6t-1a 70 | ``` 71 | 72 | ```shell 73 | $ ./d6t-8l 74 | ``` 75 | 76 | ```shell 77 | $ ./d6t-8lh 78 | ``` 79 | 80 | ```shell 81 | $ ./d6t-44l 82 | ``` 83 | 84 | ```shell 85 | $ ./d6t-32l 86 | ``` 87 | 88 | 89 | ### Change I2C speed to 100kHz or less 90 | 1. edit /boot/config, find below string 91 | 92 | ``` 93 | dtparam=i2c_arm=on 94 | ``` 95 | 96 | 2. change i2c speed: append the parameter `,i2c_arm_baudrate=n` , 97 | /boot/config will be changed as below. 98 | 99 | ``` 100 | dtparam=i2c_arm=on,i2c_arm_baudrate=100000 101 | ``` 102 | 103 | 3. **Required** ) then reboot 104 | 105 | 106 | ## Links 107 | - [Arduino samples for 2JCIE-01-AR1/FT1](https://github.com/omron-devhub/2jcieev01-arduino) 108 | - [RaspberryPi samples for 2JCIE-01-RP1](https://github.com/omron-devhub/2jcieev01-raspberrypi) 109 | - [Arduino sample for D6T on 2JCIE-01-AR1/FT1](https://github.com/omron-devhub/d6t-2jcieev01-arduino) 110 | - [Arduino sample for D6F on 2JCIE-01-AR1/FT1](https://github.com/omron-devhub/d6f-2jcieev01-arduino) 111 | - [RaspberryPi sample for D6F on 2JCIE-01-RP1](https://github.com/omron-devhub/d6f-2jcieev01-raspberrypi) 112 | - [Arduino sample for B5W on 2JCIE-01-AR1/FT1](https://github.com/omron-devhub/b5w-2jcieev01-arduino) 113 | 114 | projects by another authors. 115 | 116 | - [d6t-grove-tinkerboard project](https://github.com/omron-devhub/d6t-grove-tinkerboard) 117 | - [d6t-grove-m5stack project](https://github.com/omron-devhub/d6t-grove-m5stack) 118 | - [d6t-grove-arduino project](https://github.com/omron-devhub/d6t-grove-arduino) 119 | only for element 4x4 type, but libralized. 120 | 121 | 122 | ## Licence 123 | Copyright (c) OMRON Corporation. All rights reserved. 124 | 125 | Licensed under the MIT License. 126 | 127 | -------------------------------------------------------------------------------- /d6t-1a.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2019, 2018 - present OMRON Corporation 4 | * All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /* includes */ 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | /* defines */ 38 | #define D6T_ADDR 0x0A // for I2C 7bit address 39 | #define D6T_CMD 0x4C // for D6T-44L-06/06H, D6T-8L-09/09H, for D6T-1A-01/02 40 | 41 | #define N_ROW 1 42 | #define N_PIXEL 1 43 | #define N_READ ((N_PIXEL + 1) * 2 + 1) 44 | #define RASPBERRY_PI_I2C "/dev/i2c-1" 45 | #define I2CDEV RASPBERRY_PI_I2C 46 | 47 | uint8_t rbuf[N_READ]; 48 | double ptat; 49 | double pix_data[N_PIXEL]; 50 | 51 | /* I2C functions */ 52 | /** I2C read function for bytes transfer. 53 | */ 54 | uint32_t i2c_read_reg8(uint8_t devAddr, uint8_t regAddr, 55 | uint8_t *data, int length 56 | ) { 57 | int fd = open(I2CDEV, O_RDWR); 58 | 59 | if (fd < 0) { 60 | fprintf(stderr, "Failed to open device: %s\n", strerror(errno)); 61 | return 21; 62 | } 63 | int err = 0; 64 | do { 65 | if (ioctl(fd, I2C_SLAVE, devAddr) < 0) { 66 | fprintf(stderr, "Failed to select device: %s\n", strerror(errno)); 67 | err = 22; break; 68 | } 69 | if (write(fd, ®Addr, 1) != 1) { 70 | fprintf(stderr, "Failed to write reg: %s\n", strerror(errno)); 71 | err = 23; break; 72 | } 73 | int count = read(fd, data, length); 74 | if (count < 0) { 75 | fprintf(stderr, "Failed to read device(%d): %s\n", 76 | count, strerror(errno)); 77 | err = 24; break; 78 | } else if (count != length) { 79 | fprintf(stderr, "Short read from device, expected %d, got %d\n", 80 | length, count); 81 | err = 25; break; 82 | } 83 | } while (false); 84 | close(fd); 85 | return err; 86 | } 87 | 88 | /** I2C read function for bytes transfer. 89 | */ 90 | uint32_t i2c_write_reg8(uint8_t devAddr, 91 | uint8_t *data, int length 92 | ) { 93 | int fd = open(I2CDEV, O_RDWR); 94 | if (fd < 0) { 95 | fprintf(stderr, "Failed to open device: %s\n", strerror(errno)); 96 | return 21; 97 | } 98 | int err = 0; 99 | do { 100 | if (ioctl(fd, I2C_SLAVE, devAddr) < 0) { 101 | fprintf(stderr, "Failed to select device: %s\n", strerror(errno)); 102 | err = 22; break; 103 | } 104 | if (write(fd, data, length) != length) { 105 | fprintf(stderr, "Failed to write reg: %s\n", strerror(errno)); 106 | err = 23; break; 107 | } 108 | } while (false); 109 | close(fd); 110 | return err; 111 | } 112 | 113 | uint8_t calc_crc(uint8_t data) { 114 | int index; 115 | uint8_t temp; 116 | for (index = 0; index < 8; index++) { 117 | temp = data; 118 | data <<= 1; 119 | if (temp & 0x80) {data ^= 0x07;} 120 | } 121 | return data; 122 | } 123 | 124 | /** D6T PEC(Packet Error Check) calculation. 125 | * calculate the data sequence, 126 | * from an I2C Read client address (8bit) to thermal data end. 127 | */ 128 | bool D6T_checkPEC(uint8_t buf[], int n) { 129 | int i; 130 | uint8_t crc = calc_crc((D6T_ADDR << 1) | 1); // I2C Read address (8bit) 131 | for (i = 0; i < n; i++) { 132 | crc = calc_crc(buf[i] ^ crc); 133 | } 134 | bool ret = crc != buf[n]; 135 | if (ret) { 136 | fprintf(stderr, 137 | "PEC check failed: %02X(cal)-%02X(get)\n", crc, buf[n]); 138 | } 139 | return ret; 140 | } 141 | 142 | 143 | /** convert a 16bit data from the byte stream. 144 | */ 145 | int16_t conv8us_s16_le(uint8_t* buf, int n) { 146 | uint16_t ret; 147 | ret = (uint16_t)buf[n]; 148 | ret += ((uint16_t)buf[n + 1]) << 8; 149 | return (int16_t)ret; // and convert negative. 150 | } 151 | 152 | 153 | void delay(int msec) { 154 | struct timespec ts = {.tv_sec = msec / 1000, 155 | .tv_nsec = (msec % 1000) * 1000000}; 156 | nanosleep(&ts, NULL); 157 | } 158 | 159 | void initialSetting(void) { 160 | } 161 | 162 | /** 163 | * Read data 164 | */ 165 | int main() { 166 | int i; 167 | int16_t itemp; 168 | 169 | delay(220); 170 | 171 | while(1){ 172 | // Read data via I2C 173 | memset(rbuf, 0, N_READ); 174 | uint32_t ret = i2c_read_reg8(D6T_ADDR, D6T_CMD, rbuf, N_READ); 175 | D6T_checkPEC(rbuf, N_READ - 1); 176 | 177 | //Convert to temperature data (degC) 178 | ptat = (double)conv8us_s16_le(rbuf, 0) / 10.0; 179 | for (i = 0; i < N_PIXEL; i++) { 180 | itemp = conv8us_s16_le(rbuf, 2 + 2*i); 181 | pix_data[i] = (double)itemp / 10.0; 182 | } 183 | 184 | //Output results 185 | printf("PTAT: %4.1f [degC], Temperature: ", ptat); 186 | for (i = 0; i < N_PIXEL; i++) { 187 | printf("%4.1f, ", pix_data[i]); 188 | } 189 | printf("[degC]\n"); 190 | 191 | delay(100); 192 | } 193 | } 194 | // vi: ft=c:fdm=marker:et:sw=4:tw=80 195 | -------------------------------------------------------------------------------- /d6t-32l.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2019, 2018 - present OMRON Corporation 4 | * All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /* includes */ 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include //add 37 | 38 | /* defines */ 39 | #define D6T_ADDR 0x0A // for I2C 7bit address 40 | #define D6T_CMD 0x4D // for D6T-32L-01A, compensated output. 41 | #define D6T_SET_ADD 0x01 42 | 43 | #define N_ROW 32 44 | #define N_PIXEL (32 * 32) 45 | #define N_READ ((N_PIXEL + 1) * 2 + 1) 46 | #define RASPBERRY_PI_I2C "/dev/i2c-1" 47 | #define I2CDEV RASPBERRY_PI_I2C 48 | 49 | uint8_t rbuf[N_READ]; 50 | double ptat; 51 | double pix_data[N_PIXEL]; 52 | 53 | /******* setting parameter *******/ 54 | #define D6T_IIR 0x00 55 | #define D6T_AVERAGE 0x04 56 | /*********************************/ 57 | 58 | /* I2C functions */ 59 | /** I2C read function for bytes transfer. 60 | */ 61 | uint32_t i2c_read_reg8(uint8_t devAddr, uint8_t regAddr, 62 | uint8_t *data, int length 63 | ) { 64 | int fd = open(I2CDEV, O_RDWR); 65 | if (fd < 0) { 66 | fprintf(stderr, "Failed to open device: %s\n", strerror(errno)); 67 | return 21; 68 | } 69 | int err = 0; 70 | do { 71 | struct i2c_msg messages[] = { 72 | { devAddr, 0, 1, ®Addr }, 73 | { devAddr, I2C_M_RD, length, data }, 74 | }; 75 | struct i2c_rdwr_ioctl_data ioctl_data = { messages, 2 }; 76 | if (ioctl(fd, I2C_RDWR, &ioctl_data) != 2) { 77 | fprintf(stderr, "i2c_read: failed to ioctl: %s\n", strerror(errno)); 78 | } 79 | 80 | } while (false); 81 | close(fd); //change 82 | return err; 83 | } 84 | 85 | uint32_t i2c_write_reg8(uint8_t devAddr, 86 | uint8_t *data, int length) { 87 | int fd = open(I2CDEV, O_RDWR); 88 | if (fd < 0) { 89 | fprintf(stderr, "Failed to open device: %s\n", strerror(errno)); 90 | return 21; 91 | } 92 | int err = 0; 93 | do { 94 | if (ioctl(fd, I2C_SLAVE, devAddr) < 0) { 95 | fprintf(stderr, "Failed to select device: %s\n", strerror(errno)); 96 | err = 22; break; 97 | } 98 | if (write(fd, data, length) != length) { 99 | fprintf(stderr, "Failed to write reg: %s\n", strerror(errno)); 100 | err = 23; break; 101 | } 102 | } while (false); 103 | close(fd); 104 | return err; 105 | } 106 | 107 | uint8_t calc_crc(uint8_t data) { 108 | int index; 109 | uint8_t temp; 110 | for (index = 0; index < 8; index++) { 111 | temp = data; 112 | data <<= 1; 113 | if (temp & 0x80) { data ^= 0x07; } 114 | } 115 | return data; 116 | } 117 | 118 | /** D6T PEC(Packet Error Check) calculation. 119 | * calculate the data sequence, 120 | * from an I2C Read client address (8bit) to thermal data end. 121 | */ 122 | bool D6T_checkPEC(uint8_t buf[], int n) { 123 | int i; 124 | uint8_t crc = calc_crc((D6T_ADDR << 1) | 1); // I2C Read address (8bit) 125 | for (i = 0; i < n; i++) { 126 | crc = calc_crc(buf[i] ^ crc); 127 | } 128 | bool ret = crc != buf[n]; 129 | if (ret) { 130 | fprintf(stderr, 131 | "PEC check failed: %02X(cal)-%02X(get)\n", crc, buf[n]); 132 | } 133 | return ret; 134 | } 135 | 136 | /** convert a 16bit data from the byte stream. 137 | */ 138 | int16_t conv8us_s16_le(uint8_t* buf, int n) { 139 | uint16_t ret; 140 | ret = (uint16_t)buf[n]; 141 | ret += ((uint16_t)buf[n + 1]) << 8; 142 | return (int16_t)ret; // and convert negative. 143 | } 144 | 145 | void delay(int msec) { 146 | struct timespec ts = { .tv_sec = msec / 1000, 147 | .tv_nsec = (msec % 1000) * 1000000 }; 148 | nanosleep(&ts, NULL); 149 | } 150 | 151 | void initialSetting(void) { 152 | uint8_t dat1[] = {D6T_SET_ADD, (((uint8_t)D6T_IIR << 4)&&0xF0) | (0x0F && (uint8_t)D6T_AVERAGE)}; 153 | i2c_write_reg8(D6T_ADDR, dat1, sizeof(dat1)); 154 | } 155 | 156 | /** 157 | * 1. Initialize. 158 | * 2. Read data 159 | */ 160 | int main() { 161 | int i; 162 | int16_t itemp; 163 | 164 | delay(350); 165 | // 1. Initialize 166 | initialSetting(); 167 | delay(390); 168 | 169 | while(1){ 170 | // 2. Read data 171 | // Read data via I2C 172 | memset(rbuf, 0, N_READ); 173 | for (i = 0; i < 10; i++) { 174 | uint32_t ret = i2c_read_reg8(D6T_ADDR, D6T_CMD, rbuf, N_READ); 175 | if (ret == 0) { 176 | break; 177 | } 178 | else if (ret == 23) { // write error 179 | delay(60); 180 | } 181 | else if (ret == 24) { // read error 182 | delay(60); 183 | } 184 | } 185 | D6T_checkPEC(rbuf, N_READ - 1); 186 | 187 | //Convert to temperature data (degC) 188 | ptat = (double)conv8us_s16_le(rbuf, 0) / 10.0; 189 | for (i = 0; i < N_PIXEL; i++) { 190 | itemp = conv8us_s16_le(rbuf, 2 + 2*i); 191 | pix_data[i] = (double)itemp / 10.0; 192 | } 193 | 194 | //Output results 195 | printf("PTAT: %4.1f [degC], Temperature: ", ptat); 196 | for (i = 0; i < N_PIXEL; i++) { 197 | printf("%4.1f, ", pix_data[i]); 198 | } 199 | printf("[degC]\n"); 200 | 201 | delay(200); 202 | } 203 | } 204 | // vi: ft=c:fdm=marker:et:sw=4:tw=80 205 | -------------------------------------------------------------------------------- /d6t-44l.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2019, 2018 - present OMRON Corporation 4 | * All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /* includes */ 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include //add 37 | 38 | /* defines */ 39 | #define D6T_ADDR 0x0A // for I2C 7bit address 40 | #define D6T_CMD 0x4C // for D6T-44L-06/06H, D6T-8L-09/09H, for D6T-1A-01/02 41 | 42 | #define N_ROW 4 43 | #define N_PIXEL (4 * 4) 44 | #define N_READ ((N_PIXEL + 1) * 2 + 1) 45 | #define RASPBERRY_PI_I2C "/dev/i2c-1" 46 | #define I2CDEV RASPBERRY_PI_I2C 47 | 48 | uint8_t rbuf[N_READ]; 49 | double ptat; 50 | double pix_data[N_PIXEL]; 51 | 52 | void delay(int msec) { 53 | struct timespec ts = {.tv_sec = msec / 1000, 54 | .tv_nsec = (msec % 1000) * 1000000}; 55 | nanosleep(&ts, NULL); 56 | } 57 | 58 | /* I2C functions */ 59 | /** I2C read function for bytes transfer. 60 | */ 61 | uint32_t i2c_read_reg8(uint8_t devAddr, uint8_t regAddr, 62 | uint8_t *data, int length 63 | ) { 64 | int fd = open(I2CDEV, O_RDWR); 65 | 66 | if (fd < 0) { 67 | fprintf(stderr, "Failed to open device: %s\n", strerror(errno)); 68 | return 21; 69 | } 70 | int err = 0; 71 | do { 72 | if (ioctl(fd, I2C_SLAVE, devAddr) < 0) { 73 | fprintf(stderr, "Failed to select device: %s\n", strerror(errno)); 74 | err = 22; break; 75 | } 76 | if (write(fd, ®Addr, 1) != 1) { 77 | err = 23; break; 78 | } 79 | delay(1); //add 80 | int count = read(fd, data, length); 81 | if (count < 0) { 82 | err = 24; break; 83 | } else if (count != length) { 84 | fprintf(stderr, "Short read from device, expected %d, got %d\n", 85 | length, count); 86 | err = 25; break; 87 | } 88 | } while (false); 89 | close(fd); 90 | return err; 91 | } 92 | 93 | /** I2C read function for bytes transfer. 94 | */ 95 | uint32_t i2c_write_reg8(uint8_t devAddr, 96 | uint8_t *data, int length 97 | ) { 98 | int fd = open(I2CDEV, O_RDWR); 99 | if (fd < 0) { 100 | fprintf(stderr, "Failed to open device: %s\n", strerror(errno)); 101 | return 21; 102 | } 103 | int err = 0; 104 | do { 105 | if (ioctl(fd, I2C_SLAVE, devAddr) < 0) { 106 | fprintf(stderr, "Failed to select device: %s\n", strerror(errno)); 107 | err = 22; break; 108 | } 109 | if (write(fd, data, length) != length) { 110 | fprintf(stderr, "Failed to write reg: %s\n", strerror(errno)); 111 | err = 23; break; 112 | } 113 | } while (false); 114 | close(fd); 115 | return err; 116 | } 117 | 118 | uint8_t calc_crc(uint8_t data) { 119 | int index; 120 | uint8_t temp; 121 | for (index = 0; index < 8; index++) { 122 | temp = data; 123 | data <<= 1; 124 | if (temp & 0x80) {data ^= 0x07;} 125 | } 126 | return data; 127 | } 128 | 129 | /** D6T PEC(Packet Error Check) calculation. 130 | * calculate the data sequence, 131 | * from an I2C Read client address (8bit) to thermal data end. 132 | */ 133 | bool D6T_checkPEC(uint8_t buf[], int n) { 134 | int i; 135 | uint8_t crc = calc_crc((D6T_ADDR << 1) | 1); // I2C Read address (8bit) 136 | for (i = 0; i < n; i++) { 137 | crc = calc_crc(buf[i] ^ crc); 138 | } 139 | bool ret = crc != buf[n]; 140 | if (ret) { 141 | fprintf(stderr, 142 | "PEC check failed: %02X(cal)-%02X(get)\n", crc, buf[n]); 143 | } 144 | return ret; 145 | } 146 | 147 | /** convert a 16bit data from the byte stream. 148 | */ 149 | int16_t conv8us_s16_le(uint8_t* buf, int n) { 150 | uint16_t ret; 151 | ret = (uint16_t)buf[n]; 152 | ret += ((uint16_t)buf[n + 1]) << 8; 153 | return (int16_t)ret; // and convert negative. 154 | } 155 | 156 | void initialSetting(void) { 157 | } 158 | 159 | /** 160 | * Read data 161 | */ 162 | int main() { 163 | int i; 164 | int16_t itemp; 165 | 166 | delay(620); 167 | 168 | while(1){ 169 | // Read data via I2C 170 | memset(rbuf, 0, N_READ); 171 | uint32_t ret = i2c_read_reg8(D6T_ADDR, D6T_CMD, rbuf, N_READ); 172 | D6T_checkPEC(rbuf, N_READ - 1); 173 | 174 | //Convert to temperature data (degC) 175 | ptat = (double)conv8us_s16_le(rbuf, 0) / 10.0; 176 | for (i = 0; i < N_PIXEL; i++) { 177 | itemp = conv8us_s16_le(rbuf, 2 + 2*i); 178 | pix_data[i] = (double)itemp / 10.0; 179 | } 180 | 181 | //Output results 182 | printf("PTAT: %4.1f [degC], Temperature: ", ptat); 183 | for (i = 0; i < N_PIXEL; i++) { 184 | printf("%4.1f, ", pix_data[i]); 185 | } 186 | printf("[degC]\n"); 187 | 188 | delay(300); 189 | } 190 | } 191 | // vi: ft=c:fdm=marker:et:sw=4:tw=80 192 | -------------------------------------------------------------------------------- /d6t-8l.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2019, 2018 - present OMRON Corporation 4 | * All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /* includes */ 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | /* defines */ 38 | #define D6T_ADDR 0x0A // for I2C 7bit address 39 | #define D6T_CMD 0x4C // for D6T-44L-06/06H, D6T-8L-09/09H, for D6T-1A-01/02 40 | 41 | #define N_ROW 8 42 | #define N_PIXEL 8 43 | #define N_READ ((N_PIXEL + 1) * 2 + 1) 44 | #define RASPBERRY_PI_I2C "/dev/i2c-1" 45 | #define I2CDEV RASPBERRY_PI_I2C 46 | 47 | uint8_t rbuf[N_READ]; 48 | double ptat; 49 | double pix_data[N_PIXEL]; 50 | 51 | /* I2C functions */ 52 | /** I2C read function for bytes transfer. 53 | */ 54 | uint32_t i2c_read_reg8(uint8_t devAddr, uint8_t regAddr, 55 | uint8_t *data, int length 56 | ) { 57 | int fd = open(I2CDEV, O_RDWR); 58 | 59 | if (fd < 0) { 60 | fprintf(stderr, "Failed to open device: %s\n", strerror(errno)); 61 | return 21; 62 | } 63 | int err = 0; 64 | do { 65 | if (ioctl(fd, I2C_SLAVE, devAddr) < 0) { 66 | fprintf(stderr, "Failed to select device: %s\n", strerror(errno)); 67 | err = 22; break; 68 | } 69 | if (write(fd, ®Addr, 1) != 1) { 70 | fprintf(stderr, "Failed to write reg: %s\n", strerror(errno)); 71 | err = 23; break; 72 | } 73 | int count = read(fd, data, length); 74 | if (count < 0) { 75 | fprintf(stderr, "Failed to read device(%d): %s\n", 76 | count, strerror(errno)); 77 | err = 24; break; 78 | } else if (count != length) { 79 | fprintf(stderr, "Short read from device, expected %d, got %d\n", 80 | length, count); 81 | err = 25; break; 82 | } 83 | } while (false); 84 | close(fd); 85 | return err; 86 | } 87 | 88 | /** I2C read function for bytes transfer. 89 | */ 90 | uint32_t i2c_write_reg8(uint8_t devAddr, 91 | uint8_t *data, int length 92 | ) { 93 | int fd = open(I2CDEV, O_RDWR); 94 | if (fd < 0) { 95 | fprintf(stderr, "Failed to open device: %s\n", strerror(errno)); 96 | return 21; 97 | } 98 | int err = 0; 99 | do { 100 | if (ioctl(fd, I2C_SLAVE, devAddr) < 0) { 101 | fprintf(stderr, "Failed to select device: %s\n", strerror(errno)); 102 | err = 22; break; 103 | } 104 | if (write(fd, data, length) != length) { 105 | fprintf(stderr, "Failed to write reg: %s\n", strerror(errno)); 106 | err = 23; break; 107 | } 108 | } while (false); 109 | close(fd); 110 | return err; 111 | } 112 | 113 | uint8_t calc_crc(uint8_t data) { 114 | int index; 115 | uint8_t temp; 116 | for (index = 0; index < 8; index++) { 117 | temp = data; 118 | data <<= 1; 119 | if (temp & 0x80) {data ^= 0x07;} 120 | } 121 | return data; 122 | } 123 | 124 | /** D6T PEC(Packet Error Check) calculation. 125 | * calculate the data sequence, 126 | * from an I2C Read client address (8bit) to thermal data end. 127 | */ 128 | bool D6T_checkPEC(uint8_t buf[], int n) { 129 | int i; 130 | uint8_t crc = calc_crc((D6T_ADDR << 1) | 1); // I2C Read address (8bit) 131 | for (i = 0; i < n; i++) { 132 | crc = calc_crc(buf[i] ^ crc); 133 | } 134 | bool ret = crc != buf[n]; 135 | if (ret) { 136 | fprintf(stderr, 137 | "PEC check failed: %02X(cal)-%02X(get)\n", crc, buf[n]); 138 | } 139 | return ret; 140 | } 141 | 142 | 143 | /** convert a 16bit data from the byte stream. 144 | */ 145 | int16_t conv8us_s16_le(uint8_t* buf, int n) { 146 | uint16_t ret; 147 | ret = (uint16_t)buf[n]; 148 | ret += ((uint16_t)buf[n + 1]) << 8; 149 | return (int16_t)ret; //and convert negative. 150 | } 151 | 152 | 153 | void delay(int msec) { 154 | struct timespec ts = {.tv_sec = msec / 1000, 155 | .tv_nsec = (msec % 1000) * 1000000}; 156 | nanosleep(&ts, NULL); 157 | } 158 | 159 | void initialSetting(void) { 160 | uint8_t dat1[] = {0x02, 0x00, 0x01, 0xee}; 161 | i2c_write_reg8(D6T_ADDR, dat1, sizeof(dat1)); 162 | uint8_t dat2[] = {0x05, 0x90, 0x3a, 0xb8}; 163 | i2c_write_reg8(D6T_ADDR, dat2, sizeof(dat2)); 164 | uint8_t dat3[] = {0x03, 0x00, 0x03, 0x8b}; 165 | i2c_write_reg8(D6T_ADDR, dat3, sizeof(dat3)); 166 | uint8_t dat4[] = {0x03, 0x00, 0x07, 0x97}; 167 | i2c_write_reg8(D6T_ADDR, dat4, sizeof(dat4)); 168 | uint8_t dat5[] = {0x02, 0x00, 0x00, 0xe9}; 169 | i2c_write_reg8(D6T_ADDR, dat5, sizeof(dat5)); 170 | } 171 | 172 | /** 173 | * 1. Initialize. 174 | * 2. Read data 175 | */ 176 | int main() { 177 | int i; 178 | int16_t itemp; 179 | 180 | delay(20); 181 | // 1. Initialize 182 | initialSetting(); 183 | delay(500); 184 | 185 | while(1){ 186 | // 2. Read data 187 | // Read data via I2C 188 | memset(rbuf, 0, N_READ); 189 | uint32_t ret = i2c_read_reg8(D6T_ADDR, D6T_CMD, rbuf, N_READ); 190 | D6T_checkPEC(rbuf, N_READ - 1); 191 | 192 | //Convert to temperature data (degC) 193 | ptat = (double)conv8us_s16_le(rbuf, 0) / 10.0; 194 | for (i = 0; i < N_PIXEL; i++) { 195 | itemp = conv8us_s16_le(rbuf, 2 + 2*i); 196 | pix_data[i] = (double)itemp / 10.0; 197 | } 198 | 199 | //Output results 200 | printf("PTAT: %4.1f [degC], Temperature: ", ptat); 201 | for (i = 0; i < N_PIXEL; i++) { 202 | printf("%4.1f, ", pix_data[i]); 203 | } 204 | printf("[degC]\n"); 205 | 206 | delay(250); 207 | } 208 | } 209 | // vi: ft=c:fdm=marker:et:sw=4:tw=80 210 | -------------------------------------------------------------------------------- /d6t-8lh.c: -------------------------------------------------------------------------------- 1 | /* 2 | * MIT License 3 | * Copyright (c) 2019, 2018 - present OMRON Corporation 4 | * All rights reserved. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | /* includes */ 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | /* defines */ 38 | #define D6T_ADDR 0x0A // for I2C 7bit address 39 | #define D6T_CMD 0x4C // for D6T-44L-06/06H, D6T-8L-09/09H, for D6T-1A-01/02 40 | 41 | #define N_ROW 8 42 | #define N_PIXEL 8 43 | #define N_READ ((N_PIXEL + 1) * 2 + 1) 44 | #define RASPBERRY_PI_I2C "/dev/i2c-1" 45 | #define I2CDEV RASPBERRY_PI_I2C 46 | 47 | uint8_t rbuf[N_READ]; 48 | double ptat; 49 | double pix_data[N_PIXEL]; 50 | 51 | /* I2C functions */ 52 | /** I2C read function for bytes transfer. 53 | */ 54 | uint32_t i2c_read_reg8(uint8_t devAddr, uint8_t regAddr, 55 | uint8_t *data, int length 56 | ) { 57 | int fd = open(I2CDEV, O_RDWR); 58 | 59 | if (fd < 0) { 60 | fprintf(stderr, "Failed to open device: %s\n", strerror(errno)); 61 | return 21; 62 | } 63 | int err = 0; 64 | do { 65 | if (ioctl(fd, I2C_SLAVE, devAddr) < 0) { 66 | fprintf(stderr, "Failed to select device: %s\n", strerror(errno)); 67 | err = 22; break; 68 | } 69 | if (write(fd, ®Addr, 1) != 1) { 70 | fprintf(stderr, "Failed to write reg: %s\n", strerror(errno)); 71 | err = 23; break; 72 | } 73 | int count = read(fd, data, length); 74 | if (count < 0) { 75 | fprintf(stderr, "Failed to read device(%d): %s\n", 76 | count, strerror(errno)); 77 | err = 24; break; 78 | } else if (count != length) { 79 | fprintf(stderr, "Short read from device, expected %d, got %d\n", 80 | length, count); 81 | err = 25; break; 82 | } 83 | } while (false); 84 | close(fd); 85 | return err; 86 | } 87 | 88 | /** I2C read function for bytes transfer. 89 | */ 90 | uint32_t i2c_write_reg8(uint8_t devAddr, 91 | uint8_t *data, int length 92 | ) { 93 | int fd = open(I2CDEV, O_RDWR); 94 | if (fd < 0) { 95 | fprintf(stderr, "Failed to open device: %s\n", strerror(errno)); 96 | return 21; 97 | } 98 | int err = 0; 99 | do { 100 | if (ioctl(fd, I2C_SLAVE, devAddr) < 0) { 101 | fprintf(stderr, "Failed to select device: %s\n", strerror(errno)); 102 | err = 22; break; 103 | } 104 | if (write(fd, data, length) != length) { 105 | fprintf(stderr, "Failed to write reg: %s\n", strerror(errno)); 106 | err = 23; break; 107 | } 108 | } while (false); 109 | close(fd); 110 | return err; 111 | } 112 | 113 | uint8_t calc_crc(uint8_t data) { 114 | int index; 115 | uint8_t temp; 116 | for (index = 0; index < 8; index++) { 117 | temp = data; 118 | data <<= 1; 119 | if (temp & 0x80) {data ^= 0x07;} 120 | } 121 | return data; 122 | } 123 | 124 | /** D6T PEC(Packet Error Check) calculation. 125 | * calculate the data sequence, 126 | * from an I2C Read client address (8bit) to thermal data end. 127 | */ 128 | bool D6T_checkPEC(uint8_t buf[], int n) { 129 | int i; 130 | uint8_t crc = calc_crc((D6T_ADDR << 1) | 1); // I2C Read address (8bit) 131 | for (i = 0; i < n; i++) { 132 | crc = calc_crc(buf[i] ^ crc); 133 | } 134 | bool ret = crc != buf[n]; 135 | if (ret) { 136 | fprintf(stderr, 137 | "PEC check failed: %02X(cal)-%02X(get)\n", crc, buf[n]); 138 | } 139 | return ret; 140 | } 141 | 142 | 143 | /** convert a 16bit data from the byte stream. 144 | */ 145 | int16_t conv8us_s16_le(uint8_t* buf, int n) { 146 | uint16_t ret; 147 | ret = (uint16_t)buf[n]; 148 | ret += ((uint16_t)buf[n + 1]) << 8; 149 | return (int16_t)ret; // and convert negative. 150 | } 151 | 152 | void delay(int msec) { 153 | struct timespec ts = {.tv_sec = msec / 1000, 154 | .tv_nsec = (msec % 1000) * 1000000}; 155 | nanosleep(&ts, NULL); 156 | } 157 | 158 | void initialSetting(void) { 159 | uint8_t dat1[] = {0x02, 0x00, 0x01, 0xee}; 160 | i2c_write_reg8(D6T_ADDR, dat1, sizeof(dat1)); 161 | uint8_t dat2[] = {0x05, 0x90, 0x3a, 0xb8}; 162 | i2c_write_reg8(D6T_ADDR, dat2, sizeof(dat2)); 163 | uint8_t dat3[] = {0x03, 0x00, 0x03, 0x8b}; 164 | i2c_write_reg8(D6T_ADDR, dat3, sizeof(dat3)); 165 | uint8_t dat4[] = {0x03, 0x00, 0x07, 0x97}; 166 | i2c_write_reg8(D6T_ADDR, dat4, sizeof(dat4)); 167 | uint8_t dat5[] = {0x02, 0x00, 0x00, 0xe9}; 168 | i2c_write_reg8(D6T_ADDR, dat5, sizeof(dat5)); 169 | delay(500); 170 | } 171 | 172 | /** 173 | * 1. Initialize. 174 | * 2. Read data 175 | */ 176 | int main() { 177 | int i; 178 | int16_t itemp; 179 | 180 | delay(20); 181 | // 1. Initialize 182 | initialSetting(); 183 | delay(500); 184 | 185 | while(1){ 186 | // 2. Read data 187 | // Read data via I2C 188 | memset(rbuf, 0, N_READ); 189 | uint32_t ret = i2c_read_reg8(D6T_ADDR, D6T_CMD, rbuf, N_READ); 190 | D6T_checkPEC(rbuf, N_READ - 1); 191 | 192 | //Convert to temperature data (degC) 193 | ptat = (double)conv8us_s16_le(rbuf, 0) / 10.0; 194 | for (i = 0; i < N_PIXEL; i++) { 195 | itemp = conv8us_s16_le(rbuf, 2 + 2*i); 196 | pix_data[i] = (double)itemp / 5.0; 197 | } 198 | 199 | //Output results 200 | printf("PTAT: %4.1f [degC], Temperature: ", ptat); 201 | for (i = 0; i < N_PIXEL; i++) { 202 | printf("%4.1f, ", pix_data[i]); 203 | } 204 | printf("[degC]\n"); 205 | 206 | delay(250); 207 | } 208 | } 209 | // vi: ft=c:fdm=marker:et:sw=4:tw=80 210 | --------------------------------------------------------------------------------