diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile.openwrt | 36 | ||||
-rw-r--r-- | README.md | 7 | ||||
-rw-r--r-- | build.sh | 9 | ||||
-rw-r--r-- | src/hih61xx.c | 155 | ||||
-rw-r--r-- | src/hih61xx.h | 19 | ||||
-rw-r--r-- | src/lm75.c | 163 | ||||
-rw-r--r-- | src/lm75.h | 20 | ||||
-rw-r--r-- | src/main.c | 161 |
9 files changed, 572 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6f31401 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +build/ +.vscode/ diff --git a/Makefile.openwrt b/Makefile.openwrt new file mode 100644 index 0000000..1c90cfc --- /dev/null +++ b/Makefile.openwrt @@ -0,0 +1,36 @@ +include $(TOPDIR)/rules.mk + +PKG_NAME:=i3ensors +PKG_VERSION:=1.0 +PKG_RELEASE=$(PKG_SOURCE_VERSION) +PKG_MAINTAINER:=AA <aa@aa.hu> +PKG_LICENSE:=ISC GPL-2.0 +## PKG_BUILD_DEPENDS:=+madplay + +include $(INCLUDE_DIR)/package.mk + +define Package/i2sensors/default + CATEGORY:=Sensors + SUBMENU:=I2C Sensors + TITLE:=Famous I2C Sensors reader +endef + +define Package/i2sensors + $(Package/i2sensors/default) + ##DEPENDS:=+uhttpd +uhttpd-mod-lua +uhttpd-mod-tls +kmod-sound-core +kmod-usb-audio +alsa-lib +endef + +define Package/i2sensors/description + i2sensors read some i2c devices +endef + +define Package/i2sensors/install + $(CP) ./files/* $(1)/ +endef + +define Build/Compile + true +endef + +$(eval $(call BuildPackage,webclient)) + diff --git a/README.md b/README.md new file mode 100644 index 0000000..1930ba4 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ + +Reader for some famous i2c sensor (LM75, HIH6121). +It uses the Linux Kernel i2c driver. + +Supported devices: +lm75 +hih61xx (ex: hih6131) diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..1e43724 --- /dev/null +++ b/build.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +#cd "i2sensors/" + +gcc -Wall src/main.c src/hih61xx.c src/lm75.c -o build/i2sensors + +build/i2sensors + + diff --git a/src/hih61xx.c b/src/hih61xx.c new file mode 100644 index 0000000..b68b653 --- /dev/null +++ b/src/hih61xx.c @@ -0,0 +1,155 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> + + +#include "hih61xx.h" + +extern int file; +extern void bus_err(int ern); +extern void print_help(void); +unsigned char buf[5]; + + + + +void hih61xx_list_all(void) +{ + printf( + "00: Relative Humidity [%%] (reg: 0x00)\n" + "01: Temperature [°C] (reg: 0x00)\n" + "02: Status [hex] (reg: 0x00)\n" + "\n"); +} + + + +void hih61xx_get_data(void) +{ + buf[0] = 0x00; + + if(write(file, buf, 1) != 1) //Start measure + { + bus_err(errno); + } + + usleep(60*1000); // Wait 60ms for measurement + + if(read(file, buf, 4) != 4) //Read the data + { + bus_err(errno); + } +} + + + +unsigned char hih61xx_read_status(void) +{ + return ((buf[0] & 0xc0) >> 6); +} + + + +float hih61xx_read_humidity(float offset) +{ + unsigned int raw = 0; + float humidity; + + if(hih61xx_read_status() != 0x01 ) + { + raw = ((buf[0] & 0x3f) << 8) + buf[1]; // two msb status, 14bit data + humidity = ((float)raw/(16384 - 2))*100; // humidity = (14bit data / (2^14 -2)) * 100% + } + else + { + humidity = -1.0 ; + } + + return (humidity + offset) ; +} + + + +float hih61xx_read_temp(float offset) +{ + unsigned int raw = 0; + float temp; + + if(hih61xx_read_status() != 0x01 ) + { + raw = ((buf[2] << 8) + buf[1]) >> 2; // 14bit temp data + temp = ((float)raw/(16384 - 2))*165 - 40 ; // temp = ((14bit data / (2^14 -2))*165) - 40 [°C] + } + else + { + temp = -40.0 ; + } + + return (temp + offset); +} + + + +void hih61xx_read_all(const char *opts) +{ + hih61xx_get_data(); + + if(opts != NULL) + { + char *ptr; + printf("00:%f\n", hih61xx_read_humidity(strtof(opts, &ptr))); + + ptr++; // One (,) character allowed for delimiter + + printf("01:%f\n", hih61xx_read_temp(strtof(ptr, NULL))); + } + else + { + printf("00:%f\n", hih61xx_read_humidity(0.0)); + printf("01:%f\n", hih61xx_read_temp(0.0)); + } + + printf("02:0x%x\n", hih61xx_read_status()); + +} + + + +void hih61xx_read_one(const char *opts) +{ + int id; + char *ptr; + + hih61xx_get_data(); + id = strtol (opts,&ptr,0); //all format allowed + ptr++; //one separator allowed + + switch (id) + { + case 0x00: + printf("00:%f\n", hih61xx_read_humidity(strtof(ptr, NULL))); + break; + case 0x01: + printf("01:%f\n", hih61xx_read_temp(strtof(ptr, NULL))); + break; + case 0x02: + printf("02:0x%x\n", hih61xx_read_status()); + break; + default: + print_help(); + } +} + + + + + + + + + + + diff --git a/src/hih61xx.h b/src/hih61xx.h new file mode 100644 index 0000000..25842a6 --- /dev/null +++ b/src/hih61xx.h @@ -0,0 +1,19 @@ + +#ifndef _HIH61XX_INCLUDED +#define _HIH61xx_INCLUDED +/* + +extern int file; + +void hih61xx_list_all(void); +void hih61xx_read_all(const char *opts); +*/ +void hih61xx_list_all(void); +void hih61xx_get_data(void); +unsigned char hih61xx_read_status(void); +float hih61xx_read_humidity(float offset); +float hih61xx_read_temp(float offset); +void hih61xx_read_all(const char *opts); +void hih61xx_read_one(const char *opts); + +#endif
\ No newline at end of file diff --git a/src/lm75.c b/src/lm75.c new file mode 100644 index 0000000..fac61c2 --- /dev/null +++ b/src/lm75.c @@ -0,0 +1,163 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> + + +#include "lm75.h" + +extern int file; +extern void bus_err(int ern); +extern void print_help(void); +unsigned char buf[5]; + + +void lm75_list_all(void) +{ + printf( + "00: Temperature data [°C] (reg: 0x00)\n" + "01: Configuration [hex] (reg: 0x01)\n" + "02: Tos (Overtemp) [°C] (reg: 0x03)\n" + "03: Thys (Hysteresis) [°C] (reg: 0x04)\n" + "\n"); +} + + + +void lm75_get_data(void) +{ + if(write(file, buf, 1) != 1) + { + bus_err(errno); + } + + if(read(file, buf, 2) != 2) + { + bus_err(errno); + } +} + + + +float lm75_read_temp(float offset) +{ + signed int rawtemp = 0; + float temp; + + buf[0] = 0x00; + + lm75_get_data(); + + rawtemp = (buf[0]*256 + buf[1]) >> 5; //(buf[0] << 8), and (>> 5), 11bit device is also supported + + if((rawtemp & 0x400) == 0x400) //check if the msb(bit11) is 1 (1024 = 0x400), 2'complement negative number + { + rawtemp = rawtemp - 2048; //2^11 = 2048 + } + + temp = rawtemp * 0.125 ; //11bit->0.125°C or 9bit->0.5°C + return (temp + offset); +} + + + +float lm75_read_tos(void) +{ + int rawtemp = 0; + + buf[0] = 0x02; + + lm75_get_data(); + + rawtemp = buf[0]*256 + buf[1]; + rawtemp = (rawtemp) >> 7; //9bit data + + if((rawtemp & 256) == 256) // check if the msb 2'complement negative number + { + rawtemp = rawtemp - 512 ; // 2^9 = 512; + } + + return (rawtemp * 0.5); //9bit -> 0.5 celsius +} + + + +float lm75_read_thys(void) +{ + int rawtemp = 0; + + buf[0] = 0x03; + + lm75_get_data(); + + rawtemp = buf[0]*256 + buf[1]; + rawtemp = (rawtemp) >> 7; //9bit data + + if((rawtemp & 256) == 256) // check if the msb 2'complement negative number + { + rawtemp = rawtemp - 512 ; // 2^9 = 512; + } + + return (rawtemp * 0.5); //9bit -> 0.5 celsius +} + + +char lm75_read_conf(void) +{ + + buf[0] = 0x01; + + lm75_get_data(); + + return buf[0]; +} + + + +void lm75_read_all(const char *opts) +{ + if(opts != NULL) + { + printf("00:%f\n", lm75_read_temp(strtof(opts, NULL))); + } + else + { + printf("00:%f\n", lm75_read_temp(0.0)); + } + + printf("01:0x%x\n", lm75_read_conf()); + printf("02:%f\n", lm75_read_tos()); + printf("03:%f\n", lm75_read_thys()); +} + + + +void lm75_read_one(const char *opts) +{ + int id; + char *ptr; + + id = strtol (opts,&ptr,0); //all format allowed + ptr++; //one separator allowed + + switch (id) + { + case 0x00: + printf("00:%f\n", lm75_read_temp(strtof(ptr, NULL))); + break; + case 0x01: + printf("01:0x%x\n", lm75_read_conf()); + break; + case 0x02: + printf("02:%f\n", lm75_read_tos()); + break; + case 0x03: + printf("03:%f\n", lm75_read_thys()); + break; + default: + print_help(); + } +} + diff --git a/src/lm75.h b/src/lm75.h new file mode 100644 index 0000000..ff31c6a --- /dev/null +++ b/src/lm75.h @@ -0,0 +1,20 @@ + +#ifndef _LM75_INCLUDED +#define _LM75_INCLUDED + +// extern int file; +// +// void lm75_list_all(void); +// void lm75_read_all(const char *opts); +// +void lm75_list_all(void); +void lm75_get_data(void); +float lm75_read_temp(float offset); +float lm75_read_tos(void); +float lm75_read_thys(void); +char lm75_read_conf(void); +void lm75_read_all(const char *opts); +void lm75_read_one(const char *opts); + + +#endif
\ No newline at end of file diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..c71c872 --- /dev/null +++ b/src/main.c @@ -0,0 +1,161 @@ + + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> + + +#include <linux/i2c-dev.h> +#include <sys/ioctl.h> + +#include "lm75.h" +#include "hih61xx.h" + +extern void lm75_list_all(void); +extern void lm75_read_all(const char *opts); +extern void lm75_read_one(const char *opts); +extern void hih61xx_list_all(void); +extern void hih61xx_read_all(const char *opts); +extern void hih61xx_read_one(const char *opts); + + +int file; +void (*list_all)(void) = NULL; +void (*read_all)(const char *opts) = NULL; +void (*read_one)(const char *opts) = NULL; + + +void print_help(void) +{ + printf ("Usage:\n" + " i2sensor <op> <bus> <dev_type> <dev_addr> (<options>)\n" + "Aviable options: <op>\n" + " list_all -- list all measured parameters off device\n" + " read_all -- read all measured parameters from device\n" + " read_one -- read the selected parameters from device\n" + "Exmples:\n" + " i2sensor read_all <bus> <device> <address> <offset_for_param-01,offset_for_param-02,...>\n" + " i2sensor read_one <bus> <device> <address> <param-id,offset_for_param-id>\n" + " i2sensor read_all 1 lm75 0x4f -1.35,\n" + " i2sensor read_one 1 lm75 0x4f 01,-1.35\n" + "" "\n"); +} + +void bus_err(int ern) +{ + printf("I2C communication(rd) error. errno: %d\n",errno); +} + +void preinit(const char *dev_type) +{ + if(!strcmp("lm75", dev_type)) + { + list_all = lm75_list_all; + read_all = lm75_read_all; + read_one = lm75_read_one; + } + + else if(!strcmp("hih61xx", dev_type)) + { + list_all = hih61xx_list_all; + read_all = hih61xx_read_all; + read_one = hih61xx_read_one; + } +} + + + +int main(int argc, char *argv[]) +{ + +// >> i2sensor <op> <bus> <dev_typ> <dev_addr> (<others>) +// >> i2sensor read_all 0 lm75 4f 1,-1.0;2,+0.2;3,+10;4,-2 +// read_all, list_all, +// ...read_all...<dev_addr>, <param_id,offs,param_id,offs> +// read_one...<dev_addr>, <param_id,offs> +// ...read_reg_hex... <dev_addr>, <reg_addr,b/w/dw> +// ...read_reg_dec... <dev_addr>, <reg_addr,b/w/dw> +// ...set_param... <dev_addr>, <param_id,value_dec> +// ...set_reg... <dev_addr>, <reg_addr,value_hex> + + + if(4 < argc && 7 > argc) //Minimal 5 argument passed + { + + char filename[32]; + int i; + preinit(argv[3]); + + for(i=0;i<strlen(argv[2]);i++) //Some test on bus address, for safety. + { + if(!isdigit(argv[2][i])) + { + printf("\n\tThe BUS Address must be an integer\n\n"); + print_help(); + exit (EXIT_FAILURE); + } + } + + snprintf(filename, 31, "/dev/i2c-%s", argv[2]); //Open i2c bus + file = open(filename, O_RDWR); + + if (file < 0) + { + printf("\n\tCan't open i2c BUS, are you root?\n\n"); + print_help(); + exit (EXIT_FAILURE); + } + + + if(argv[4][0]=='0' && argv[4][1]=='x') //? + { + + int addr = (int)strtol(argv[4], NULL, 0); //Open i2c device + + if (ioctl(file, I2C_SLAVE, addr) < 0) + { + printf("\n\tCan't open i2c DEVICE, errno: %d\n\n",errno); + print_help(); + exit (EXIT_FAILURE); + } + } + else + { + printf("\n\tThe DEVICE address must be a hexadecimal number\n\n"); + print_help(); + exit (EXIT_FAILURE); + } + + + + if(!strcmp("list_all",argv[1]) && list_all != NULL) // If list_all is selected. + { + list_all(); + } + else if(!strcmp("read_all",argv[1]) && read_all != NULL) + { + read_all(argv[5]); + } + else if(!strcmp("read_one",argv[1]) && read_one != NULL && argc == 5) + { + read_one(argv[5]); + } + else + { + // print_help(); + } + + close(file); + + } + else + { + print_help(); + } + return 0; +} |