From: Roman Bazalevskiy Date: Wed, 12 Apr 2017 17:05:42 +0000 (+0300) Subject: Initial fork + minor fixes for BMP085 (mBar output) + shell scripts for ADS1115 and... X-Git-Url: https://git.rvb.name/i2c-telemetry.git/commitdiff_plain/5347abf61b167f3014ec7e0d21c95a9284a58689?ds=inline Initial fork + minor fixes for BMP085 (mBar output) + shell scripts for ADS1115 and DS1307 --- 5347abf61b167f3014ec7e0d21c95a9284a58689 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..e27fcce --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ + +STAGING_DIR=/var/www/builder/data/trunk/build_ng/openwrt/staging_dir +export STAGING_DIR +CFLAGS=-I. +# +# Atheros +CC= ~/trunk/build_ng/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-uclibc-gcc +# +# Broadcom +#CC= ~/trunk/build_ng/openwrt/staging_dir/toolchain-mips_gcc-4.6-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-uclibc-gcc + + + +ina219: + $(CC) -o ina219 ina219.c + +bmp085: + $(CC) -o bmp085 bmp085.c smbus.c + +lm75: + $(CC) -o lm75 lm75.c + +ds1621: + $(CC) -o ds1621 ds1621.c + +bh1750: + $(CC) -o bh1750 bh1750.c smbus.c + +lcdd: + $(CC) -o lcdd lcdd.c + +mcp_rw: + $(CC) -o mcp mcp_rw.c smbus.c diff --git a/ad5602_test.c b/ad5602_test.c new file mode 100644 index 0000000..4b67a3d --- /dev/null +++ b/ad5602_test.c @@ -0,0 +1,60 @@ +/* + AD5602_test1.c + --------------------- + set the output voltage from the D/A + ----------------------------------- + + 1) send the i2c address + 2) send HI_byte + 3) send LO_byte + + usage :- type with spaces but without the < > +
+*/ + +#include +#include +#include +#include +#include + +int main(int argc, char** argv) +{ + int i2c; + int HI_byte; /* last 4 bits are output byte HI bits */ + int LO_byte; /* first 4 bits are output byte LO bits */ + int buf[1]; /* use to feed the i2c driver */ + int address; /* i2c bus address */ + + if (argc != 4) /* report error if we are not getting just 3 inputs after the program name */ + { + printf("Error. usage (decimal): %s AD5602_test1 address HI_byte LO_byte\n", argv[0]); + } + + address = atoi(argv[1]); /* address is the first number after the program name */ + // address bits are 0 0 0 1 1 1 0 R/W as per manual + // the 1 0 before R/W is for the address pin (pin 1) open-circuit + // the R/W is 0 for write. Linux see the chip address as 0000 1110 (0E) - shifts a bit to the left - odd! + HI_byte = atoi(argv[2]); /* HI_byte is 0 0 0 0 D7 D6 D5 D4 */ + LO_byte = atoi(argv[3]); /* LO_byte is D3 D2 D1 D0 X X X X (X = anything) */ + + i2c = open("/dev/i2c/0",O_RDWR); /* open the i2c-bus number 0 */ + + ioctl(i2c,I2C_SLAVE,address); /* set the i2c-bus address of the chip we will talk to */ + + buf[0] = HI_byte; /* HI_byte */ + buf[1] = LO_byte; /* LO_byte */ + + + write(i2c,buf,2); /* we send 2 bytes */ + + printf("%d\n", buf[0]); /* just to prove it ran!*/ + printf("%d\n", buf[1]); + + i2c = close(i2c); +} + +// AD5602_test1 14 0 0 gives 0 volts +// AD5602_test1 14 8 0 gives 2.5 volts 8 = 08 00001000 0 = 00 00000000 +// AD5602_test1 14 15 240 gives 5 volts 15 = 0F 00001111 240 = F0 11110000 + diff --git a/ads1115 b/ads1115 new file mode 100644 index 0000000..2f1e824 --- /dev/null +++ b/ads1115 @@ -0,0 +1,33 @@ +#!/bin/sh + +I2CBUS=0 +I2CADDR=0x48 + +if [ "$1" == "" ] +then + pin=0 +else + pin=$1 +fi + +case "$pin" in + "0") CFG="0xc583" ;; + "1") CFG="0xc593" ;; + "2") CFG="0xc5a3" ;; + "3") CFG="0xc5b3" ;; + *) echo "Bad pin number $pin, must be 0..3" ; exit 1 ;; +esac + +i2cset -y 0 0x48 1 $CFG w +RES=`i2cget -y 0 0x48 1 w` +until [ "$RES" = "$CFG" ] ; do + RES=`i2cget -y 0 0x48 1 w` +done +X=`i2cget -y 0 0x48 0 w` + +XX="0x0`echo $X | cut -c 5-6``echo $X | cut -c 3`" +VIND=$(( ( $XX + 32768 / 40960 ) * 20480 / 32768 )) +VIN=$(( $VIND / 10 )) +VINF=$(( $VIND - $VIN * 10 )) + +printf "VIN$pin (mv) %d.%01d\n" $VIN $VINF diff --git a/am2321.c b/am2321.c new file mode 100644 index 0000000..abe84bc --- /dev/null +++ b/am2321.c @@ -0,0 +1,303 @@ +/* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* +* Project Home - https://github.com/takagi/am2321 +* +*/ + +#include +#include +#include /* for O_RDWR */ +#include /* for memcpy */ +#include /* for I2C_SLAVE */ + +#include /* add by paulerr*/ +#include /* add by paulerr*/ + + +/* I2C character device */ +#define I2C_DEVICE "/dev/i2c-0" + +/* I2C address of AM2321 sensor in 7 bits + * - the first 7 bits should be passed to ioctl system call + * because the least 1 bit of the address represents read/write + * and the i2c driver takes care of it + */ +#define AM2321_ADDR (0xB8 >> 1) + + +/* + * udelay function + */ + +long timeval_to_usec( struct timeval tm ) { + return tm.tv_sec * 1000000 + tm.tv_usec; +} + +void udelay( long us ) { + struct timeval current; + struct timeval start; + + gettimeofday( &start, NULL ); + do { + gettimeofday( ¤t, NULL ); + } while( timeval_to_usec( current ) - timeval_to_usec( start ) < us ); +} + + +/* + * CRC16 + */ + +unsigned short crc16( unsigned char *ptr, unsigned char len ) { + unsigned short crc = 0xFFFF; + unsigned char i; + + while( len-- ) + { + crc ^= *ptr++; + for( i = 0; i < 8; i++ ) { + if( crc & 0x01 ) { + crc >>= 1; + crc ^= 0xA001; + } else { + crc >>= 1; + } + } + } + + return crc; +} + +unsigned char crc16_low( unsigned short crc ) { + return crc & 0xFF; +} + +unsigned char crc16_high( unsigned short crc ) { + return crc >> 8; +} + + +/* + * st_am2321 Structure + */ + +typedef struct { + unsigned char data[8]; +} st_am2321; + +void __check_crc16( st_am2321 measured ) { + unsigned short crc_m, crc_s; + + crc_m = crc16( measured.data, 6 ); + crc_s = (measured.data[7] << 8) + measured.data[6]; + if ( crc_m != crc_s ) { + fprintf( stderr, "am2321: CRC16 does not match\n" ); + exit( 1 ); + } + + return; +} + +st_am2321 __st_am2321( unsigned char* data ) { + st_am2321 result; + memcpy( result.data, data, 8 ); + __check_crc16( result ); + return result; +} + +void am2321_dump( st_am2321 measured ) { + printf( "[ 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ]\n", + measured.data[0], measured.data[1], + measured.data[2], measured.data[3], + measured.data[4], measured.data[5], + measured.data[6], measured.data[7] ); + return; +} + +short __am2321_temperature( st_am2321 measured ) { + return (measured.data[4] << 8) + measured.data[5]; +} + +short am2321_temperature_integral( st_am2321 measured ) { + return __am2321_temperature( measured ) / 10; +} + +short am2321_temperature_fraction( st_am2321 measured ) { + return __am2321_temperature( measured ) % 10; +} + +short __am2321_humidity( st_am2321 measured ) { + return (measured.data[2] << 8) + measured.data[3]; +} + +short am2321_humidity_integral( st_am2321 measured ) { + return __am2321_humidity( measured ) / 10; +} + +short am2321_humidity_fraction( st_am2321 measured ) { + return __am2321_humidity( measured ) % 10; +} + + +/* + * Measurement function + */ + +st_am2321 am2321() { + int fd; + int ret; + int retry_cnt; + unsigned char data[8]; + + /* open I2C device */ + fd = open( I2C_DEVICE, O_RDWR ); + if ( fd < 0 ) { + perror( "am2321(1)" ); + exit( 1 ); + } + + /* set address of I2C device in 7 bits */ + ret = ioctl( fd, I2C_SLAVE, AM2321_ADDR ); + if ( ret < 0 ) { + perror( "am2321(2)" ); + exit( 2 ); + } + + retry_cnt = 0; + retry: + + /* wake I2C device up */ + write( fd, NULL, 0); + + /* write measurement request */ + data[0] = 0x03; data[1] = 0x00; data[2] = 0x04; + ret = write( fd, data, 3 ); + if ( ret < 0 && retry_cnt++ < 5 ) { + fprintf( stderr, "am2321: retry\n" ); + udelay( 1000 ); + goto retry; + } + if ( ret < 0 ) { + perror( "am2321(3)" ); + exit( 3 ); + } + + /* wait for having measured */ + udelay( 1500 ); + + /* read measured result */ + memset( data, 0x00, 8 ); + ret = read( fd, data, 8 ); + if ( ret < 0 ) { + perror( "am2321(4)" ); + exit( 4 ); + } + + /* close I2C device */ + close( fd ); + + return __st_am2321( data ); +} + +st_am2321 am2321_stub() { + unsigned char data[] = { 0x03, 0x04, 0x01, 0x41, + 0x00, 0xEA, 0x21, 0x8F }; + return __st_am2321( data ); +} + + +/* + * Print functions + */ + +void print_am2321( st_am2321 measured ) { + printf( "%d.%d %d.%d\n", + am2321_temperature_integral( measured ), + am2321_temperature_fraction( measured ), + am2321_humidity_integral( measured ), + am2321_humidity_fraction( measured ) ); + return; +} + +void print_am2321_human_readable( st_am2321 measured ) { + printf( "Temperature (C)\t\t%d.%d\n", + am2321_temperature_integral( measured ), + am2321_temperature_fraction( measured ) ); + printf( "Humidity (%%)\t\t%d.%d\n", + am2321_humidity_integral( measured ), + am2321_humidity_fraction( measured ) ); + return; +} + +/* + * Main + */ + +#define OPT_HUMAN_READABLE 0x1 +#define OPT_STUB 0x2 + +int print_help() { + fprintf( stderr, + "Usage: am2321 [-r] [-s]\n" + "Get temperature and humidity measured with Aosong's AM2321 sensor.\n" + " -r human readable output\n" + " -s not measure with AM2321, instead stub of 23.4[C] and 32.1[%]\n" ); + exit( 1 ); +} + +int parse_options( int argc, char* argv[]) { + int options = 0; + int flags = 0; + + while( 1+flags < argc && argv[1+flags][0] == '-' ) { + switch( argv[1+flags][1] ) { + case 'r': options |= OPT_HUMAN_READABLE; break; + case 's': options |= OPT_STUB; break; + default: + fprintf( stderr, "am2321: Unsupported option \"%s\"\n", argv[1+flags] ); + print_help(); + exit( 1 ); + } + flags++; + } + + return options; +} + +int is_opt_human_readable( int options ) { + return options & OPT_HUMAN_READABLE; +} + +int is_opt_stub( int options ) { + return options & OPT_STUB; +} + +int main( int argc, char* argv[] ) { + int options; + st_am2321 measured; + + /* parse the given options */ + options = parse_options( argc, argv ); + + /* measure temperature and humidity */ + measured = ! is_opt_stub( options ) ? am2321() : am2321_stub(); + + /* print measured temperature and humidity */ + if ( ! is_opt_human_readable( options ) ) { + print_am2321( measured ); + } else { + print_am2321_human_readable( measured ); + } + + return 0; +} diff --git a/bh1750.c b/bh1750.c new file mode 100644 index 0000000..798fe6c --- /dev/null +++ b/bh1750.c @@ -0,0 +1,85 @@ +/* + Sample code for the BH1750 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "smbus.h" + +#define BH1750FVI_I2C_ADDRESS 0x23 // ADDR > 0.7 VCC) +//#define BH1750FVI_I2C_ADDRESS 0x53 // ADDR < 0.3 VCC) +#define DEBUG 0 + +#define PowerDown 0x00 +#define PowerOn 0x01 +#define Reset 0x07 +#define ContinuHigh 0x10 +#define ContinuLow 0x13 +#define OneTimeHigh 0x20 +#define OneTimeLow 0x23 + +int main(int argc, char **argv) +{ + int fd; + char *fileName = "/dev/i2c-0"; + int retCode; + int readSize; + unsigned int res; + unsigned int lux; + char buf[5]; + int i; + + // Open port for reading and writing + if ((fd = open(fileName, O_RDWR)) < 0) { + printf("open error\n"); + exit(1); + } + + // Set the port options and set the address of the device + if (ioctl(fd, I2C_SLAVE, BH1750FVI_I2C_ADDRESS) < 0) { + printf("ioctl error\n"); + close(fd); + exit(1); + } + + retCode=i2c_smbus_write_byte(fd, PowerOn); +if(DEBUG)printf("Power On retCode=%d\n",retCode); + if (retCode < 0) { + printf("PowerOn error\n"); + close(fd); + exit(1); + } + + retCode=i2c_smbus_write_byte(fd, ContinuHigh); +if(DEBUG)printf("ContinuHigh retCode=%d\n",retCode); + if (retCode < 0) { + printf("ContinuHigh error\n"); + close(fd); + exit(1); + } + + // Set i<10 for more one check + for(i=0;i<1;i++) { + sleep(3); + readSize = read (fd, buf, 2); +if(DEBUG)printf("read readSize=%d %x %x\n",readSize,buf[0],buf[1]); + + res = buf[0]*256+buf[1]; +if(DEBUG)printf("res=%x\n",res); + lux = res / 1.2; + // printf("Lux=%d\n",lux); + printf("Brightness (Lux)\t%0.1f\n", ((double)lux)); + } + + retCode=i2c_smbus_write_byte(fd, PowerDown); + close(fd); + + exit (0); +} \ No newline at end of file diff --git a/bmp085.c b/bmp085.c new file mode 100644 index 0000000..c8127dd --- /dev/null +++ b/bmp085.c @@ -0,0 +1,212 @@ +/* + Sample code for the BMP085 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "smbus.h" + +#define BMP085_I2C_ADDRESS 0x77 + +const unsigned char BMP085_OVERSAMPLING_SETTING = 3; + +// Calibration values - These are stored in the BMP085 +short int ac1; +short int ac2; +short int ac3; +unsigned short int ac4; +unsigned short int ac5; +unsigned short int ac6; +short int b1; +short int b2; +short int mb; +short int mc; +short int md; + +int b5; + +unsigned int temperature, pressure; + + +// Open a connection to the bmp085 +// Returns a file id +int bmp085_i2c_Begin() +{ + int fd; + char *fileName = "/dev/i2c-0"; + + // Open port for reading and writing + if ((fd = open(fileName, O_RDWR)) < 0) + exit(1); + + // Set the port options and set the address of the device + if (ioctl(fd, I2C_SLAVE, BMP085_I2C_ADDRESS) < 0) { + close(fd); + exit(1); + } + + return fd; +} + +// Read two words from the BMP085 and supply it as a 16 bit integer +__s32 bmp085_i2c_Read_Int(int fd, __u8 address) +{ + __s32 res = i2c_smbus_read_word_data(fd, address); + if (res < 0) { + close(fd); + exit(1); + } + + // Convert result to 16 bits and swap bytes + res = ((res<<8) & 0xFF00) | ((res>>8) & 0xFF); + + return res; +} + +//Write a byte to the BMP085 +void bmp085_i2c_Write_Byte(int fd, __u8 address, __u8 value) +{ + if (i2c_smbus_write_byte_data(fd, address, value) < 0) { + close(fd); + exit(1); + } +} + +// Read a block of data BMP085 +void bmp085_i2c_Read_Block(int fd, __u8 address, __u8 length, __u8 *values) +{ + if(i2c_smbus_read_i2c_block_data(fd, address,length,values)<0) { + close(fd); + exit(1); + } +} + + +void bmp085_Calibration() +{ + int fd = bmp085_i2c_Begin(); + ac1 = bmp085_i2c_Read_Int(fd,0xAA); + ac2 = bmp085_i2c_Read_Int(fd,0xAC); + ac3 = bmp085_i2c_Read_Int(fd,0xAE); + ac4 = bmp085_i2c_Read_Int(fd,0xB0); + ac5 = bmp085_i2c_Read_Int(fd,0xB2); + ac6 = bmp085_i2c_Read_Int(fd,0xB4); + b1 = bmp085_i2c_Read_Int(fd,0xB6); + b2 = bmp085_i2c_Read_Int(fd,0xB8); + mb = bmp085_i2c_Read_Int(fd,0xBA); + mc = bmp085_i2c_Read_Int(fd,0xBC); + md = bmp085_i2c_Read_Int(fd,0xBE); + close(fd); +} + +// Read the uncompensated temperature value +unsigned int bmp085_ReadUT() +{ + unsigned int ut = 0; + int fd = bmp085_i2c_Begin(); + + // Write 0x2E into Register 0xF4 + // This requests a temperature reading + bmp085_i2c_Write_Byte(fd,0xF4,0x2E); + + // Wait at least 4.5ms + usleep(5000); + + // Read the two byte result from address 0xF6 + ut = bmp085_i2c_Read_Int(fd,0xF6); + + // Close the i2c file + close (fd); + + return ut; +} + +// Read the uncompensated pressure value +unsigned int bmp085_ReadUP() +{ + unsigned int up = 0; + int fd = bmp085_i2c_Begin(); + + // Write 0x34+(BMP085_OVERSAMPLING_SETTING<<6) into register 0xF4 + // Request a pressure reading w/ oversampling setting + bmp085_i2c_Write_Byte(fd,0xF4,0x34 + (BMP085_OVERSAMPLING_SETTING<<6)); + + // Wait for conversion, delay time dependent on oversampling setting + usleep((2 + (3<> (8-BMP085_OVERSAMPLING_SETTING); + + return up; +} + +// Calculate pressure given uncalibrated pressure +// Value returned will be in units of XXXXX +unsigned int bmp085_GetPressure(unsigned int up) +{ + int x1, x2, x3, b3, b6, p; + unsigned int b4, b7; + + b6 = b5 - 4000; + // Calculate B3 + x1 = (b2 * (b6 * b6)>>12)>>11; + x2 = (ac2 * b6)>>11; + x3 = x1 + x2; + b3 = (((((int)ac1)*4 + x3)<>2; + + // Calculate B4 + x1 = (ac3 * b6)>>13; + x2 = (b1 * ((b6 * b6)>>12))>>16; + x3 = ((x1 + x2) + 2)>>2; + b4 = (ac4 * (unsigned int)(x3 + 32768))>>15; + + b7 = ((unsigned int)(up - b3) * (50000>>BMP085_OVERSAMPLING_SETTING)); + if (b7 < 0x80000000) + p = (b7<<1)/b4; + else + p = (b7/b4)<<1; + + x1 = (p>>8) * (p>>8); + x1 = (x1 * 3038)>>16; + x2 = (-7357 * p)>>16; + p += (x1 + x2 + 3791)>>4; + + return p; +} + +// Calculate temperature given uncalibrated temperature +// Value returned will be in units of 0.1 deg C +unsigned int bmp085_GetTemperature(unsigned int ut) +{ + int x1, x2; + + x1 = (((int)ut - (int)ac6)*(int)ac5) >> 15; + x2 = ((int)mc << 11)/(x1 + md); + b5 = x1 + x2; + + unsigned int result = ((b5 + 8)>>4); + + return result; +} + +int main(int argc, char **argv) +{ + bmp085_Calibration(); + temperature = bmp085_GetTemperature(bmp085_ReadUT()); + pressure = bmp085_GetPressure(bmp085_ReadUP()); + + printf("Temperature (C)\t\t%0.1f\n", ((double)temperature)/10); + printf("Pressure (mBar)\t%0.2f\n", ((double)pressure)/100); + // printf("Pressure (mmHg)\t%0.2f\n", ((double)pressure)/100*0.75006375541921); + // printf("Pressure (mmHg)\t\t%0.2f\n", ((double)pressure)/100*0.750061683); + return 0; +} \ No newline at end of file diff --git a/ds1621.c b/ds1621.c new file mode 100644 index 0000000..30e858e --- /dev/null +++ b/ds1621.c @@ -0,0 +1,134 @@ +/* Test DS1621 sur interface I2C GPIO Fonera (3/2008) */ +/* Inspir de "Un bus i2c pour La Fonera" */ +/* http://www.lefinnois.net/wp/index.php/2007/05/05/un-bus-i2c-pour-la-fonera/ */ + +/* Affichage de la t */ +/* Par domos domos78freefr */ +/* http://vesta.homelinux.net/ */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_SLAVE 0x0703 // Change slave address + +static int i2c_fd ; +int res ; + +#define DEVICE "/dev/i2c-0" +#define ds1621_addr 0x9E >> 1 // 0x4f - Address (A0+A1+A2 to Vcc) + + +/*------------------------------------------------------------------------------*/ +/* Fonctions i2c */ +/*------------------------------------------------------------------------------*/ +void i2c_init() +{ + if ((i2c_fd = open(DEVICE, O_RDWR)) < 0) + { + fprintf(stderr, "Erreur ouverture port: %s (%d)\n", strerror(errno), errno); + exit(EXIT_FAILURE); + } +} + +//----------------------------------------------------------------------------- +void SelectSlave(unsigned char slaveaddr) +{ + if (ioctl(i2c_fd, I2C_SLAVE, slaveaddr) < 0) + { + fprintf(stderr, "Erreur selection esclave i2c: %s (%d)\n", strerror(errno), errno); + close ( i2c_fd ) ; + exit(EXIT_FAILURE) ; + } +} + +/*------------------------------------------------------------------------------*/ +/* Fonctions DS1621 */ +/*------------------------------------------------------------------------------*/ +int i2c_init_ds1621(unsigned char addr) +{ + int res ; + char buff[10] ; + + SelectSlave(addr) ; + buff[0] = 0xAC ; + buff[1] = 0x01 ; + res = write( i2c_fd, buff, 2 ); + if ( res < 0 ) + { + printf("Erreur init DS1621 addr 0x%x: '%s', Abandon programme !", addr, strerror(errno)); + close ( i2c_fd ); + exit(1) ; + } + /* start temperature conversion */ + errno = 0 ; + buff[0] = 0xEE ; + write( i2c_fd, buff, 1 ); + sleep(1) ; + return 1 ; +} + +//----------------------------------------------------------------------------- +double i2c_gettemp_ds1621(unsigned char addr) +{ + int k, count, slope, temp; + char buff[10] ; + + SelectSlave(addr) ; + /* stop conversion */ + errno = 0 ; + buff[0] = 0x22 ; + + if ( write( i2c_fd, buff, 1 ) < 0 ) return 255 ; // Write retourne -1 et strerror(errno))='Remote I/O error' si adr. i2c non connecte. + else + { + /* Temperature reading (1 Celsius degree precision) */ + buff[0] = 0xAA ; + write( i2c_fd, buff, 1 ); + read(i2c_fd, buff, 1) ; + temp = buff[0] ; + /* Counter reading (fraction of degree) ) */ + buff[0] = 0xA8 ; + write( i2c_fd, buff, 1 ); + read(i2c_fd, buff, 1) ; + count = buff[0] ; + /* slope reading */ + buff[0] = 0xA9 ; + write( i2c_fd, buff, 1 ); + read(i2c_fd, buff, 1) ; + slope = buff[0] ; + k = temp; + if (slope != 0) + { + k = temp*100-25+(100*(slope-count))/slope; + } + /* start temperature conversion */ + buff[0] = 0xEE ; + write( i2c_fd, buff, 1 ); + return (float)k/100 ; + } +} + +/*------------------------------------------------------------------------------*/ +int main ( int argc, char ** argv ) +{ + // Init i2c. + i2c_init() ; + + // Init ds1621. + i2c_init_ds1621(ds1621_addr) ; + + // Affiche la t. + printf("%2.1f\n", i2c_gettemp_ds1621(ds1621_addr) ) ; + + close ( i2c_fd ); +} + +/*------------------------------------------------------------------------------*/ + diff --git a/etraxi2c.h b/etraxi2c.h new file mode 100644 index 0000000..9d5c9bf --- /dev/null +++ b/etraxi2c.h @@ -0,0 +1,49 @@ +#ifndef _LINUX_ETRAXI2C_H +#define _LINUX_ETRAXI2C_H + +/* etraxi2c _IOC_TYPE, bits 8 to 15 in ioctl cmd */ + +#define ETRAXI2C_IOCTYPE 44 + +/* supported ioctl _IOC_NR's */ + +/* in write operations, the argument contains both i2c + * slave, register and value. + */ + +#define I2C_WRITEARG(slave, reg, value) (((slave) << 16) | ((reg) << 8) | (value)) +#define I2C_READARG(slave, reg) (((slave) << 16) | ((reg) << 8)) + +#define I2C_ARGSLAVE(arg) ((arg) >> 16) +#define I2C_ARGREG(arg) (((arg) >> 8) & 0xff) +#define I2C_ARGVALUE(arg) ((arg) & 0xff) + +#define I2C_WRITEREG 0x1 /* write to an I2C register */ +#define I2C_READREG 0x2 /* read from an I2C register */ + +/* +EXAMPLE usage: + + i2c_arg = I2C_WRITEARG(STA013_WRITE_ADDR, reg, val); + ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_WRITEREG), i2c_arg); + + i2c_arg = I2C_READARG(STA013_READ_ADDR, reg); + val = ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_READREG), i2c_arg); + +*/ + +/* Extended part */ +#define I2C_READ 0x4 /* reads from I2C device */ +#define I2C_WRITE 0x3 /* writes to I2C device */ +#define I2C_WRITEREAD 0x5 /* writes to I2C device where to start reading */ + +typedef struct _I2C_DATA +{ + unsigned char slave; /* I2C address (8-bit representation) of slave device */ + unsigned char wbuf[256]; /* Write buffer (length = 256 bytes) */ + unsigned int wlen; /* Number of bytes to write from wbuf[] */ + unsigned char rbuf[256]; /* Read buffer (length = 256 bytes) */ + unsigned int rlen; /* Number of bytes to read into rbuf[] */ +} I2C_DATA; + +#endif diff --git a/gethwclock b/gethwclock new file mode 100644 index 0000000..27265d5 --- /dev/null +++ b/gethwclock @@ -0,0 +1,13 @@ +#!/bin/sh + +I2CBUS=0 +I2CADDR=0x68 + +sec=`i2cget -y $I2CBUS $I2CADDR 0` +min=`i2cget -y $I2CBUS $I2CADDR 1` +hour=`i2cget -y $I2CBUS $I2CADDR 2` +day=`i2cget -y $I2CBUS $I2CADDR 4` +month=`i2cget -y $I2CBUS $I2CADDR 5` +year=`i2cget -y $I2CBUS $I2CADDR 6` + +echo 20${year:2:2}-${month:2:2}-${day:2:2} ${hour:2:2}:${min:2:2}:${sec:2:2} diff --git a/i2c_errno.h b/i2c_errno.h new file mode 100644 index 0000000..a517b6f --- /dev/null +++ b/i2c_errno.h @@ -0,0 +1,20 @@ +#ifndef _I2C_ERRNO_H +#define _I2C_ERRNO_H + +#define EI2CNOERRORS 0 /* All fine */ +#define EI2CBUSNFREE 1 /* I2C bus not free */ +#define EI2CWADDRESS 2 /* Address write failed */ +#define EI2CRADDRESS 3 /* Address read failed */ +#define EI2CSENDDATA 4 /* Sending data failed */ +#define EI2CRECVDATA 5 /* Receiving data failed */ +#define EI2CSTRTCOND 6 /* Start condition failed */ +#define EI2CRSTACOND 7 /* Repeated start condition failed */ +#define EI2CSTOPCOND 8 /* Stop condition failed */ +#define EI2CNOSNDBYT 9 /* Number of send bytes is 0, while there's a send buffer defined */ +#define EI2CNOSNDBUF 10 /* No send buffer defined, while number of send bytes is not 0 */ +#define EI2CNORCVBYT 11 /* Number of receive bytes is 0, while there's a receive buffer defined */ +#define EI2CNORCVBUF 12 /* No receive buffer defined, while number of receive bytes is not 0 */ +#define EI2CNOACKNLD 13 /* No acknowledge received from slave */ +#define EI2CNOMNUMBR 14 /* No MAJOR number received from kernel while registering the device */ + +#endif /* _I2C_ERRNO_H */ diff --git a/i2cget_bmp180.example b/i2cget_bmp180.example new file mode 100644 index 0000000..828d16b --- /dev/null +++ b/i2cget_bmp180.example @@ -0,0 +1,17 @@ +#!/bin/sh +# +# More info: http://cyber-place.ru/showpost.php?p=7797&postcount=82 + +RAWTEMP=$(i2cget -y 0 0x40 0xe3 w) +RAWHUMI=$(i2cget -y 0 0x40 0xe5 w) + +if (echo "$RAWTEMP"| grep -Eq '0x[0-9a-f]{4}'); then + HEXORDERED=$(echo "$RAWTEMP"|sed -r 's/0x([0-9a-f]{2})([0-9a-f]{2})/0x\2\1/') + DECRAW=$(($HEXORDERED)) + echo $DECRAW | awk -v tem=${DECRAW} '{ printf "%.2f stC\n", -46.85+((tem*175.72)/65536)}' +fi +if (echo "$RAWHUMI"| grep -Eq '0x[0-9a-f]{4}'); then + HEXORDERED=$(echo "$RAWHUMI"|sed -r 's/0x([0-9a-f]{2})([0-9a-f]{2})/0x\2\1/') + DECRAW=$(($HEXORDERED)) + echo $DECRAW | awk -v hum=${DECRAW} '{ printf "%.2f %%RH\n", -6+((hum*125)/65536)}' +fi \ No newline at end of file diff --git a/ina219.c b/ina219.c new file mode 100644 index 0000000..9cf3de6 --- /dev/null +++ b/ina219.c @@ -0,0 +1,400 @@ +/* +* INA219 util - part of PowerCape by AndiceLabs +* +* Copyright (C) 2014 AndiceLabs admin@andicelabs.com http://andicelabs.com +* Copyright (C) 2014 Zig Fisher flyrouter@gmail.com http://zftlab.org +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* +* Example run and output: +* +* OpenWRT:~# ina219 -b 0 -i 60 +* +* 22:49 12168mV 134.2mA +* 22:50 12168mV 239.9mA +* 22:51 12168mV 134.7mA +* +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CONFIG_REG 0 +#define SHUNT_REG 1 +#define BUS_REG 2 +#define POWER_REG 3 +#define CURRENT_REG 4 +#define CALIBRATION_REG 5 + +#define AVR_ADDRESS 0x21 +#define INA_ADDRESS 0x40 + +typedef enum { + OP_DUMP, + OP_VOLTAGE, + OP_CURRENT, + OP_MONITOR, + OP_NONE +} op_type; + +op_type operation = OP_DUMP; + +int interval = 60; +int i2c_bus = 0; +int i2c_address = INA_ADDRESS; +int handle; +int whole_numbers = 0; + + +void msleep( int msecs ) +{ + usleep( msecs * 1000 ); +} + + +int i2c_read( void *buf, int len ) +{ + int rc = 0; + + if ( read( handle, buf, len ) != len ) + { + printf( "I2C read failed: %s\n", strerror( errno ) ); + rc = -1; + } + + return rc; +} + + +int i2c_write( void *buf, int len ) +{ + int rc = 0; + + if ( write( handle, buf, len ) != len ) + { + printf( "I2C write failed: %s\n", strerror( errno ) ); + rc = -1; + } + + return rc; +} + + +int register_read( unsigned char reg, unsigned short *data ) +{ + int rc = -1; + unsigned char bite[ 4 ]; + + bite[ 0 ] = reg; + if ( i2c_write( bite, 1 ) == 0 ) + { + if ( i2c_read( bite, 2 ) == 0 ) + { + *data = ( bite[ 0 ] << 8 ) | bite[ 1 ]; + rc = 0; + } + } + + return rc; +} + + +int register_write( unsigned char reg, unsigned short data ) +{ + int rc = -1; + unsigned char bite[ 4 ]; + + bite[ 0 ] = reg; + bite[ 1 ] = ( data >> 8 ) & 0xFF; + bite[ 2 ] = ( data & 0xFF ); + + if ( i2c_write( bite, 3 ) == 0 ) + { + rc = 0; + } + + return rc; +} + + +void show_usage( char *progname ) +{ + fprintf( stderr, "Usage: %s \n", progname ); + fprintf( stderr, " Mode (required):\n" ); + fprintf( stderr, " -h --help Show usage.\n" ); + fprintf( stderr, " -i --interval Set interval for monitor mode.\n" ); + fprintf( stderr, " -w --whole Show whole numbers only. Useful for scripts.\n" ); + fprintf( stderr, " -v --voltage Show battery voltage in mV.\n" ); + fprintf( stderr, " -c --current Show battery current in mA.\n" ); + fprintf( stderr, " -a --address Override I2C address of INA219 from default of 0x%02X.\n", i2c_address ); + fprintf( stderr, " -b --bus Override I2C bus from default of %d.\n", i2c_bus ); + exit( 1 ); +} + + +void parse( int argc, char *argv[] ) +{ + while( 1 ) + { + static const struct option lopts[] = + { + { "address", 0, 0, 'a' }, + { "bus", 0, 0, 'b' }, + { "current", 0, 0, 'c' }, + { "help", 0, 0, 'h' }, + { "interval", 0, 0, 'i' }, + { "voltage", 0, 0, 'v' }, + { "whole", 0, 0, 'w' }, + { NULL, 0, 0, 0 }, + }; + int c; + + c = getopt_long( argc, argv, "a:b:chi:vw", lopts, NULL ); + + if( c == -1 ) + break; + + switch( c ) + { + case 'a': + { + errno = 0; + i2c_address = (int)strtol( optarg, NULL, 0 ); + if ( errno != 0 ) + { + fprintf( stderr, "Unknown address parameter %s.\n", optarg ); + exit( 1 ); + } + break; + } + + case 'b': + { + errno = 0; + i2c_bus = (int)strtol( optarg, NULL, 0 ); + if ( errno != 0 ) + { + fprintf( stderr, "Unknown bus parameter %s.\n", optarg ); + exit( 1 ); + } + break; + } + + case 'c': + { + operation = OP_CURRENT; + break; + } + + default: + case 'h': + { + operation = OP_NONE; + show_usage( argv[ 0 ] ); + break; + } + + case 'i': + { + operation = OP_MONITOR; + interval = atoi( optarg ); + if ( ( interval == 0 ) && ( errno != 0 ) ) + { + fprintf( stderr, "Invalid interval value\n" ); + exit( 1 ); + } + break; + } + + case 'v': + { + operation = OP_VOLTAGE; + break; + } + + case 'w': + { + whole_numbers = 1; + break; + } + } + } +} + + +int get_voltage( float *mv ) +{ + short bus; + + if ( register_read( BUS_REG, (unsigned short*)&bus ) != 0 ) + { + return -1; + } + + *mv = ( float )( ( bus & 0xFFF8 ) >> 1 ); + return 0; +} + + +int get_current( float *ma ) +{ + short shunt; + + if ( register_read( SHUNT_REG, &shunt ) != 0 ) + { + return -1; + } + + *ma = (float)shunt / 10; + return 0; +} + + +void show_current( void ) +{ + float ma; + + if ( get_current( &ma ) ) + { + fprintf( stderr, "Error reading current\n" ); + return; + } + + if ( whole_numbers ) + { + printf( "%4.0f\n", ma ); + } + else + { + printf( "%04.1f\n", ma ); + } +} + + +void show_voltage( void ) +{ + float mv; + + if ( get_voltage( &mv ) ) + { + fprintf( stderr, "Error reading voltage\n" ); + return; + } + printf( "%4.0f\n", mv ); +} + + +void show_voltage_current( void ) +{ + float mv, ma; + + if ( get_current( &ma ) || get_voltage( &mv ) ) + { + fprintf( stderr, "Error reading voltage/current\n" ); + return; + } + + if ( whole_numbers ) + { + printf( "%04.0fmV %4.0fmA\n", mv, ma ); + } + else + { + printf( "%04.0fmV %04.1fmA\n", mv, ma ); + } +} + + +void monitor( void ) +{ + struct tm *tmptr; + time_t seconds; + + while ( 1 ) + { + seconds = time( NULL ); + tmptr = localtime( &seconds ); + printf( "%02d:%02d ", tmptr->tm_hour, tmptr->tm_min ); + show_voltage_current(); + sleep( interval ); + } +} + + +int main( int argc, char *argv[] ) +{ + char filename[ 20 ]; + + parse( argc, argv ); + + snprintf( filename, 19, "/dev/i2c-%d", i2c_bus ); + handle = open( filename, O_RDWR ); + if ( handle < 0 ) + { + fprintf( stderr, "Error opening bus %d: %s\n", i2c_bus, strerror( errno ) ); + exit( 1 ); + } + + if ( ioctl( handle, I2C_SLAVE, i2c_address ) < 0 ) + { + fprintf( stderr, "Error setting address %02X: %s\n", i2c_address, strerror( errno ) ); + exit( 1 ); + } + + switch ( operation ) + { + case OP_DUMP: + { + show_voltage_current(); + break; + } + + case OP_VOLTAGE: + { + show_voltage(); + break; + } + + case OP_CURRENT: + { + show_current(); + break; + } + + case OP_MONITOR: + { + monitor(); + break; + } + + default: + case OP_NONE: + { + break; + } + } + + close( handle ); + return 0; +} + diff --git a/lcdd.c b/lcdd.c new file mode 100644 index 0000000..8cdd85f --- /dev/null +++ b/lcdd.c @@ -0,0 +1,394 @@ +/* Simple daemon to communicate with Newhaven I2C LCD module. + * + * This is a trivial interface for Newhaven LCD module connected to a Linux machine + * over an I2C interface. Any standard Linux I2C bus should work (including USB I2C + * adapters that correctly hook into the i2c kernel driver framework). + * + * Opens a named pipe at /dev/lcd which can be written to by other applications. + * Text written to this file will appear on the LCD. + * Send a bell ('\b')to clear the screen. + * + * Tested with NHD-0420D3Z-FL-GBW (Digikey part number NHD-0420D3Z-FL-GBW-ND). + * http://www.newhavendisplay.com/specs/NHD-0420D3Z-FL-GBW.pdf + * http://www.newhavendisplay.com/index.php?main_page=product_info&cPath=253&products_id=922 + * + * FIXME how to do other commands etc. + * FIXME some rate limiting should be added... the I2C controller on the LCD + * module gets confused if you write to it too fast. + * + * Hardware note: + * To enable I2C mode of LCD, Pads of R1 must be jumpered on back of LCD + * See the manual for the LCD module. + * + * ./lcdd -a 0x47 -d /dev/i2c-4 -f /dev/lcd -n + * + * Hugo Vincent, June 2009 - https://github.com/hugovincent/i2c-lcdd + * Daemonization based on code by Peter Lombardo , 2006 + */ + + +#define _GNU_SOURCE // for strsignal() + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DAEMON_NAME "lcdd" +#define PID_FILE "/var/run/lcdd.pid" + +#define LCD_ADDR 0x27 + +//#define DEBUG + +static int daemonize = 1, running = 1, have_lcd = 1; +static jmp_buf my_jmp_buf; + +#define LOG_MSG(format, ...) if (daemonize == 1) \ + syslog(LOG_INFO, format, ##__VA_ARGS__); \ +else \ +printf("i2c-lcdd: " format "\n", ##__VA_ARGS__); + +void usage(int argc, char **argv) +{ + if (argc >=1) + { + printf("Usage: %s -a 0x50 -d /dev/i2c-3 -f /dev/lcd -n -?\n", argv[0]); + printf(" Options:\n"); + printf(" -a\tI2C slave address (in hex) for LCD module\n"); + printf(" -d\tI2C device\n"); + printf(" -f\tnamed pipe for input\n"); + printf(" -n\tDon't daemonize.\n"); + printf(" -?\tShow this help screen.\n"); + } +} + +void signal_handler(int sig) +{ + LOG_MSG("received signal %s - exiting", strsignal(sig)); + running = 0; +} + +void i2c_send(int fd, uint8_t *buf, int count) +{ + if (have_lcd) + { + if (write(fd, buf, count) != count) + { + LOG_MSG("error writing to I2C: %s", strerror(errno)); + longjmp(my_jmp_buf, EXIT_FAILURE); + //exit(EXIT_FAILURE); + } + } + else + { +#ifdef DEBUG + static char tmp[1024]; + strncpy(tmp, buf, count); + tmp[count] = 0; + printf("I2C send: \"%s\"\n", tmp); +#endif + } +} + +uint8_t linenum_to_cursor(int linenum) +{ + switch (linenum) + { + case 1: + return 0x40; + break; + case 2: + return 0x14; + break; + case 3: + return 0x54; + break; + case 0: + default: + return 0x0; + break; + } +} + +#define min(a, b) ((a <= b) ? a : b) + +void handle_pipe_input(int i2c_fd, char *buffer, int size) +{ + // FIXME this should handle escape sequences (other than \b, \n) too + + static int line_number = 0; + + // LCD clear + if (size >= 1 && buffer[0] == '\b') + { + uint8_t bytes[] = {0xFE, 0x51}; + i2c_send(i2c_fd, bytes, sizeof(bytes)); + buffer++; size--; + line_number = 0; + } + + // Split input into lines + char *line = strtok(buffer, "\n"); + while (line != NULL) + { + // Because of weird cursor positioning on the LCD module, if we write + // more than 20 characters on line 1 it'll flow over onto line 3, (or + // off line 2 on to line 4). Thus, we limit lines to 20 chars. + + i2c_send(i2c_fd, line, min(strlen(line), 20)); + line_number = (line_number < 3) ? (line_number + 1) : 0; + + // Go to specified line + uint8_t bytes[] = {0xFE, 0x45, 0x0}; + bytes[2] = linenum_to_cursor(line_number); + i2c_send(i2c_fd, bytes, sizeof(bytes)); + + // Get next line + line = strtok(NULL, "\n"); + } +} + +int main(int argc, char **argv) +{ + char device[64] = "/dev/i2c-3", fifo_name[64] = "/dev/lcd"; + int addr = LCD_ADDR, addr_sscanf_ret = 1; + + // Setup signal handling before we start + signal(SIGHUP, signal_handler); + siginterrupt(SIGHUP, 1); + signal(SIGQUIT, signal_handler); + siginterrupt(SIGQUIT, 1); + signal(SIGTERM, signal_handler); + siginterrupt(SIGTERM, 1); + signal(SIGINT, signal_handler); + siginterrupt(SIGINT, 1); + + int c; + while( (c = getopt(argc, argv, "a:d:f:n?")) != -1) { + switch(c){ + case 'a': + addr_sscanf_ret = sscanf(optarg, "0x%x", &addr); + break; + case 'd': + strncpy(device, optarg, sizeof(device)); + break; + case 'f': + strncpy(fifo_name, optarg, sizeof(fifo_name)); + break; + case 'n': + daemonize = 0; + break; + case '?': + default: + usage(argc, argv); + exit(0); + break; + } + } + + // Setup syslog logging + if (daemonize == 1) + { + setlogmask(LOG_UPTO(LOG_INFO)); + openlog(DAEMON_NAME, LOG_CONS, LOG_USER); + } + LOG_MSG("daemon starting up"); + + // Check sscanf above worked (delayed until after syslog is initialized) + if (addr_sscanf_ret != 1) + LOG_MSG("supplied address invalid, using 0x%02x", addr); + + // Our process ID and Session ID + pid_t pid, sid; + + if (daemonize) + { + // Fork off the parent process + pid = fork(); + if (pid < 0) + { + LOG_MSG("failed to fork daemon process"); + exit(EXIT_FAILURE); + } + + // If we got a good PID, then we can exit the parent process + if (pid > 0) + exit(EXIT_SUCCESS); + + // Change the file mode mask + umask(0); + + // Create a new SID for the child process + sid = setsid(); + if (sid < 0) + { + LOG_MSG("failed to set daemon process SID"); + exit(EXIT_FAILURE); + } + + // Change the current working directory + if ((chdir("/")) < 0) + { + LOG_MSG("failed to change daemon working directory"); + exit(EXIT_FAILURE); + } + + // Close out the standard file descriptors + close(STDIN_FILENO); +#ifndef DEBUG + close(STDOUT_FILENO); +#endif + close(STDERR_FILENO); + } + + //************************************************************************ + + addr >>= 1; // to suit LCD addressing sematics of Newhaven LCD modules + + // Initialise FIFO on which to accept input + if (mkfifo(fifo_name, S_IRWXU) < 0) + { + if (errno != EEXIST) + { + LOG_MSG("error creating named pipe for input: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + else + { + LOG_MSG("warning, named pipe already exists: %s", strerror(errno)); + // FIXME unlink and reopen + } + } + + // Connect to I2C LCD and set slave address + int i2c_fd = open(device, O_RDWR); + if (i2c_fd < 0) + { + LOG_MSG("error opening device: %s", strerror(errno)); + have_lcd = 0; + goto nolcd; + } + if (ioctl(i2c_fd, I2C_SLAVE, addr) < 0) + { + LOG_MSG("error setting I2C slave address: %s", strerror(errno)); + close(i2c_fd); + have_lcd = 0; + } + +nolcd: + if (setjmp(my_jmp_buf) == EXIT_FAILURE) + goto exit1; + + if (!have_lcd) + { + LOG_MSG("could not open I2C LCD, printing to stdout for debugging"); + } + else + { + LOG_MSG("using Nehaven LCD attached to %s at real address 0x%x", device, addr); + + // Initialise LCD + uint8_t bytes[] = {0xFE, 0x41}; // LCD on + i2c_send(i2c_fd, bytes, sizeof(bytes)); + bytes[1] = 0x51; // LCD clear + i2c_send(i2c_fd, bytes, sizeof(bytes)); + + uint8_t *string = (uint8_t*)" Initialising..."; + i2c_send(i2c_fd, string, strlen((char*)string)); + } + + char buffer[256]; + int fifo_fd = -1; + struct pollfd fds = { .events = POLLIN }; + + // Main Loop: read on named pipe, output on LCD + while (running) + { + if (fifo_fd == -1) + { +#ifdef DEBUG + LOG_MSG("waiting for connection on %s...", fifo_name); +#endif + fifo_fd = open(fifo_name, O_RDONLY); // this will block until other end of pipe is opened + if (fifo_fd < 0) + { + if (errno == EINTR) + continue; + LOG_MSG("error opening named pipe for input: %s", strerror(errno)); + goto exit3; + } + fds.fd = fifo_fd; +#ifdef DEBUG + LOG_MSG("connected, accepting input on %s", fifo_name); +#endif + } + + // Wait for input on the named pipe + int poll_ret = poll(&fds, 1, 1000); + if (poll_ret == 1 && fds.revents | POLLIN) + { + memset(&buffer, 0, sizeof(buffer)); + int bytes_read = read(fifo_fd, &buffer, sizeof(buffer)); + + // Write input to LCD + if (bytes_read > 0) + handle_pipe_input(i2c_fd, buffer, bytes_read); + else if (bytes_read == 0) + { +#ifdef DEBUG + LOG_MSG("named pipe closed"); +#endif + close(fifo_fd); + fifo_fd = -1; + } + else + { + LOG_MSG("error reading from named pipe: %s", strerror(errno)); + goto exit1; + } + } + else if (poll_ret < 0 && running) + { + LOG_MSG("error waiting for input on named pipe: %s", strerror(errno)); + goto exit1; + } + else + { + // Timeout in poll(), no need to worry (timeout is only enabled as insurance anyway) + } + } + + LOG_MSG("daemon exiting cleanly"); + + close(fifo_fd); + unlink(fifo_name); + if (have_lcd) + close(i2c_fd); + + return 0; + + // Cleanup on error +exit1: + if (have_lcd) + close(i2c_fd); +exit2: + close(fifo_fd); +exit3: + unlink(fifo_name); + LOG_MSG("daemon exiting with failure"); + exit(EXIT_FAILURE); +} + diff --git a/lm75.c b/lm75.c new file mode 100644 index 0000000..499ded5 --- /dev/null +++ b/lm75.c @@ -0,0 +1,49 @@ + /* + LM75_address.c + -------------- + 1) set the i2c address of the LM75 + * R/W pulse at end of address byte not included in address 1-0-0-1-A2-A1-A0 + * example - all lines to 0V - 1001000 = decimal 72 + 2) calculate the temperature + 3) print it + usage :- type (without the < >) +
+*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "smbus.h" + +int main(int argc, char** argv) +{ + int address; /* i2c bus address */ + + if (argc != 2) /* report error if we are not getting just 1 input after the program name */ + { + printf("Error. usage: %s i2c_chip_address\n", argv[0]); + } + address = atoi(argv[1]); /* address is the first number after the program name */ + + + int f = open("/dev/i2c-0",O_RDWR); + char buf[2]; + if (f>0) { + ioctl(f,I2C_SLAVE,address); + if (-1 == read(f,buf,2)) { + printf("read error.\n"); + } else { /* calculate the temperature*/ + int temp = buf[0]*256+buf[1]; + temp >>=7; + if (temp>512) + temp &= -1; + printf("Temperature (C)\t\t%g\n", (float)temp/2.0); + } + } + return close(f); + } diff --git a/mcp_rw.c b/mcp_rw.c new file mode 100644 index 0000000..81bf7cd --- /dev/null +++ b/mcp_rw.c @@ -0,0 +1,297 @@ +#include +#include +#include +#include +#include +#include +#include +#include +// Строки ниже необходимы для rasbian/debian.В Suse должны быть закаментированы. +#include +#include "smbus.h" + +#define mcp_I2C_ADDRESS 0x20 // адрес устройства в сети i2c,задается перемычками A0,A1,A2 на микросхеме. + + +// ниже 2 строки задают направление порта ,1 - на ввод,0 - на вывод. +#define mcp_bank_a 0b00000100 //байты 7 по 0 порт +#define mcp_bank_b 0b00000000 //байты 8 по 15 порт +// следущие 2 строки-подтяжка резистором 100 кОм на +, 1 - включен.Актуально для режима на ввод. +#define gppu_bank_a 0b00000100 //байты 7 по 0 порт +#define gppu_bank_b 0b00000000 //байты 8 по 15 порт +// регистры 02 03 для инвертирования +#define iopol_bank_a 0b00000110 //байты 7 по 0 порт +#define iopol_bank_b 0b00000000 //байты 8 по 15 порт + + + + + +int fd; +unsigned int utv; +int l=1; +int x=0; + +// Open a connection to the mcp +// Returns a file id +int mcp_i2c_Begin() +{ + + char *fileName = "/dev/i2c-7"; // указать Ваш адрес + + // Open port for reading and writing + if ((fd = open(fileName, O_RDWR)) < 0){ + printf("i2c device not found \n"); + exit(1); + } + // Set the port options and set the address of the device + if (ioctl(fd, I2C_SLAVE, mcp_I2C_ADDRESS) < 0) { + close(fd); + printf("on i2c mcp device not found \n"); + exit(1); + } + + return fd; +} + +// Read a byte to mcp +__s32 mcp_i2c_Read_byte(int fd, __u8 address) +{ + __s32 res = i2c_smbus_read_byte_data(fd, address); + if (res < 0) { + printf("error \n"); + close(fd); + exit(1); + } + + return res; +} + +//Write a byte to mcp +void mcp_i2c_Write_Byte(int fd, __u8 address, __u8 value) +{ + if (i2c_smbus_write_byte_data(fd, address, value) < 0) { + close(fd); + exit(1); + } +} +// чтение состояния порта +int mcp_read (int mcppin) +{ + if (mcppin < 0 || mcppin >15) { + printf("Please select a valid GPIO pin \n"); + exit(1); + } + + int fd = mcp_i2c_Begin(); + int regbank; + +if (mcppin < 8){ + + mcp_i2c_Write_Byte(fd,0x00,mcp_bank_a); + mcp_i2c_Write_Byte(fd,0x0c,gppu_bank_a); + + regbank=0x12; + +//printf("bank A\n"); +} else { + + mcp_i2c_Write_Byte(fd,0x01,mcp_bank_b); + mcp_i2c_Write_Byte(fd,0x0d,gppu_bank_b); + + regbank=0x13; + mcppin=mcppin-8; + + // printf("bank B\n"); +} + + utv = mcp_i2c_Read_byte(fd,regbank); + + while(x < mcppin) + { + x = x+ 1; + l=l*2; +} + + +if (utv & l) return 1; +else return 0; + +close(fd); + +} + + +// запрос таблицы статусов портов +void mcp_state_in () { + int fd = mcp_i2c_Begin(); + utv = mcp_i2c_Read_byte(fd,0x12); + // printf ("--%d--\n",utv); + while(x < 8) + { + + if ((mcp_bank_a & l)) { + if ((utv & l)) printf ("%d 1\n",x); + else printf ("%d 0\n",x); + +} else printf ("%d -\n",x); + l=l*2; + x = x+ 1; + +} + + x=0; + l=1; + + utv = mcp_i2c_Read_byte(fd,0x13); +// printf ("--%d--\n",utv); + while(x < 8) + { + if ((mcp_bank_b & l)) { + if ((utv & l)) printf ("%d 1\n",x+8); + else printf ("%d 0\n",x+8); + + } else printf ("%d -\n",x+8); + l=l*2; + x = x+ 1; +} + +close(fd); + +} +// установка состояния порта +void mcp_write (int mcppin,int mcpst) +{ + if (mcppin < 0 || mcppin >15) { + printf("Please select a valid GPIO pin \n"); + exit(1); + } + if (mcpst != 0 && mcpst != 1) { + printf("Не верно задан статус порта 0 или 1\n"); + exit(1); + } + + int fd = mcp_i2c_Begin(); + int regbank; + +if (mcppin < 8){ + + mcp_i2c_Write_Byte(fd,0x00,mcp_bank_a); + mcp_i2c_Write_Byte(fd,0x0c,gppu_bank_a); + + regbank=0x14; + +//printf("bank A\n"); +} else { + + mcp_i2c_Write_Byte(fd,0x01,mcp_bank_b); + mcp_i2c_Write_Byte(fd,0x0d,gppu_bank_b); + + regbank=0x15; + mcppin=mcppin-8; + + // printf("bank B\n"); +} + + utv = mcp_i2c_Read_byte(fd,regbank); + + while(x < mcppin) + { + x = x+ 1; + l=l*2; +} + + +if (!(utv & l) && mcpst==1) mcp_i2c_Write_Byte(fd,regbank,utv+l); +if (utv & l && mcpst==0) mcp_i2c_Write_Byte(fd,regbank,utv-l); + +close(fd); + +} + + +// запрос таблицы статусов портов +void mcp_state_out () { + int fd = mcp_i2c_Begin(); + utv = mcp_i2c_Read_byte(fd,0x14); + // printf ("--%d--\n",utv); + while(x < 8) + { + + if (!(mcp_bank_a & l)) { + if ((utv & l)) printf ("%d 1\n",x); + else printf ("%d 0\n",x); + +} else printf ("%d -\n",x); + l=l*2; + x = x+ 1; + +} + + x=0; + l=1; + + utv = mcp_i2c_Read_byte(fd,0x15); +// printf ("--%d--\n",utv); + while(x < 8) + { + if (!(mcp_bank_b & l)) { + if ((utv & l)) printf ("%d 1\n",x+8); + else printf ("%d 0\n",x+8); + + } else printf ("%d -\n",x+8); + l=l*2; + x = x+ 1; +} + +close(fd); + +} +// основное тело программы + +int main(int argc, char **argv) + +{ + if (argc == 1) { + printf("%s <команда>\nin -чтение данных из порта,установленых на ввод\nout-установка состояния порта,установленного на вывод.\n", argv[0]); + return 1; + } + else if (argc == 2) { + if(strcmp(argv[1], "out") == 0) mcp_state_out(); + else if(strcmp(argv[1], "in") == 0) mcp_state_in(); + else printf("Нет такой команды\n"); + return 1; + } + + if(strcmp(argv[1], "out") == 0) { + + if (argc != 4) { + printf("Настройка порта: %s <порт> <состояние>\n", argv[0]); + +return 1; +} +int mcppin = atoi(argv[2]); +int mcpst = atoi(argv[3]); + +mcp_write (mcppin,mcpst); + + + } + else if(strcmp(argv[1], "in")== 0) { + if (argc != 3) { + printf("Чтение одного порта: %s <порт>\n", argv[0]); + mcp_state_in(); + return 1; + } + int mcppin = atoi(argv[2]); + + printf ("%d\n",mcp_read (mcppin)); + + } + + + + + + return 0; +} \ No newline at end of file diff --git a/pcf8574_1.c b/pcf8574_1.c new file mode 100644 index 0000000..f2b8236 --- /dev/null +++ b/pcf8574_1.c @@ -0,0 +1,52 @@ +/* +PCF8574_addr_byteout_slug.c +---------------------- +Send address and byte to switch lines on 8 line port of i2c bus PCF8574 +----------------------------------------------------------------------- + +1) send the i2c address +2) send byte to set the 8 port lines on or off + +usage :- type with spaces but without the < > + + +Home Page - http://www.sunspot.co.uk/Projects/SWEEX/slug/i2c/slug_i2c.html + +*/ +#include +#include +#include +#include +#include +#include +#define I2C_SLAVE0x0703/* Change slave address*/ + +int i2c; +char filename[20]; +unsigned long address; + +int rc; +unsigned char data[1]; +int main(int argc, char *argv[]) +{ +if (argc != 3) { /* error if we are not getting just 2 inputs after the program name */ +fprintf(stderr, "usage: %s
\n",argv[0]); +exit(1); +} + +/* address is the first number after the program name */ +address = atoi(argv[1]); +/* the byte to send out to the PC8574 is the second number +place it into the first element of the buf array */ +data[0] = atoi(argv[2]); + +i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */ + +rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */ + +write(i2c,data,1) ; /* send the byte */ + +i2c = close(i2c); +return(0); +} + diff --git a/pcf8574_2.c b/pcf8574_2.c new file mode 100644 index 0000000..04af8c3 --- /dev/null +++ b/pcf8574_2.c @@ -0,0 +1,56 @@ +/* +PCF8574_addr_read_slug.c +------------------- +read the data on the 8 line port of an i2c bus PCF8574 +------------------------------------------------------ + +1) set the i2c address of the PCF8574 +2) send data 255 to turn off all 8 lines - make them inputs +3) read the data on the 8 port lines as a byte +usage :- type (without the < >) + + +Home Page - http://www.sunspot.co.uk/Projects/SWEEX/slug/i2c/slug_i2c.html + +*/ + +#include +#include +#include +#include +#include +#include +#define I2C_SLAVE0x0703/* Change slave address*/ + +int i2c; +char filename[20]; +unsigned long address; +int rc; +unsigned char data[1]; +int byte; /* the 8 bit byte that represents the data present on the 8 wire port */ + +int main(int argc, char ** argv) +{ +if (argc != 2) { /* error if we are not getting just 1 input after the program name */ +fprintf(stderr, "usage: %s
\n",argv[0]); +exit(1); +} + +/* address is the first number after the program name */ +address = atoi(argv[1]); + +i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */ +rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */ + +data[0] = 255; +write(i2c,data,1); /* we send 255 to make all lines go off, ready for input data */ + +read(i2c,data,1); /* now data(0) contains the byte of data on the 8 port lines*/ + +byte = data[0]; + +printf("BYTE = %d \n", byte); +/* BYTE value is 0-256)*/ +i2c = close(i2c); +return(0); +} diff --git a/pcf8574_3.c b/pcf8574_3.c new file mode 100644 index 0000000..1ea2493 --- /dev/null +++ b/pcf8574_3.c @@ -0,0 +1,49 @@ +/* + PCF8574_addr_byteout.c + ---------------------- + Send address and byte to switch lines on 8 line port of i2c bus PCF8574 + ----------------------------------------------------------------------- + + 1) send the i2c address + 2) send byte to set the 8 port lines on or off + + usage :- type with spaces but without the < > +
+ +*/ + +#include +#include +#include +#include +#include + + int i2c; + int buf[1]; + int address; + +int main(int argc, char** argv) +{ + if (argc != 3) /* error if we are not getting just 2 inputs after the program name */ + { + printf("Error. usage: %s i2c_chip_address byte_to_send_out\n", argv[0]); + } + +/* address is the first number after the program name */ + address = atoi(argv[1]); + +/* the byte to send out to the PC8574 is the second number */ + +/* place it into the first element of the buf array */ + buf[0] = atoi(argv[2]); + + i2c = open("/dev/i2c/0",O_RDWR); /* open the device on i2c-bus number 0*/ + + ioctl(i2c,I2C_SLAVE, address); /* set the i2c chip address */ + + write(i2c,buf,1); /* send the byte */ + + i2c = close(i2c); + +} + diff --git a/pcf8574_4.c b/pcf8574_4.c new file mode 100644 index 0000000..d07add9 --- /dev/null +++ b/pcf8574_4.c @@ -0,0 +1,50 @@ +/* + PCF8574_addr_read.c + ------------------- +read the data on the 8 line port of an i2c bus PCF8574 +------------------------------------------------------ + +1) set the i2c address of the PCF8574 +2) send data 255 to turn off all 8 lines - make them inputs +3) read the data on the 8 port lines as a byte + usage :- type (without the < >) + +*/ + +#include +#include +#include +#include +#include + + int i2c; + int buf[1]; + int address; /* i2c bus address of the PCF8574 */ + int byte; /* the 8 bit byte that represents the data present on the 8 wire port */ + +int main(int argc, char** argv) +{ + if (argc != 2) /* report error if we are not getting just 1 input after the program name */ + { + printf("Error. usage: %s i2c_chip_address\n", argv[0]); + } + + address = atoi(argv[1]); /* address is the first number after the program name */ + + i2c = open("/dev/i2c/0",O_RDWR); /* open the i2c-bus number 0 */ + + ioctl(i2c,I2C_SLAVE, address); /* set the address of the chip we will talk to */ + + buf[0] = 255; + write(i2c,buf,1); /* we send 255 to make all lines go off, ready for input data */ + + read(i2c,buf,1); /* now buf(0) contains the byte of data on the 8 port lines*/ + + byte = buf[0]; + + printf("BYTE = %d \n", byte); +/* BYTE value is 0-256)*/ + + i2c = close(i2c); +} + diff --git a/pcf8591_1.c b/pcf8591_1.c new file mode 100644 index 0000000..17954ea --- /dev/null +++ b/pcf8591_1.c @@ -0,0 +1,95 @@ +/* +PCF8591-all-lines_addr_V-slug.c +--------------------- +read the voltage on all A/D lines (0-3) and set the output voltage on the D/A pin +--------------------------------------------------------------------------------- + +1) send the i2c address +3) send byte for D/A out +3) read all 4 A/D lines +usage :- type with spaces but without the < > +
+(even if the D/A pin is unused type in any value 0-255) +*/ + +#include +#include +#include +#include +#include +#include +#define I2C_SLAVE0x0703/* Change slave address*/ +int i2c; +int AD_line; /* line number 0-3 */ +int V_out; /* value for the D/A out line */ +unsigned char buf[1]; /* use to feed the i2c driver */ +unsigned long address; /* i2c bus address */ +int byte_in_0; /* the 8 bit byte that represents the voltage on the AD_line */ +int AD_line_0; /* volts byte on line number 0 */ +int AD_line_1; /* volts byte on line number 1 */ +int AD_line_2; /* volts byte on line number 2 */ +int AD_line_3; /* volts byte on line number 3 */ +int rc; + +int main(int argc, char** argv) +{ +if (argc != 3) /* report error if we are not getting just 2 inputs after the program name */ + +{ + +printf("Error. usage: %s i2c_chip_address D/A_Vout(0-255)\n", argv[0]); + +} + +address = atoi(argv[1]); /* address is the first number after the program name */ + +V_out = atoi(argv[2]); /* A/D input line 0-3 */ + +i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */ +rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */ + +AD_line = 0 + 64; /* enable the D/A output pin 0*/ +buf[0] = AD_line; /* A/D input line number is the first data byte sent */ +buf[1] = V_out; /* D/A out value is the second data byte sent */ +write(i2c,buf,2); /* we send 2 bytes */ +read(i2c,buf,1); /* buf(0) contains the byte of data in the chip cache */ +sleep (1); /* do it again */ +read(i2c,buf,1); /* buf(0) now contains the byte of data from the most recent analogue input*/ +AD_line_0 = buf[0]; + +AD_line = 1 + 64; /* enable the D/A output pin 0*/ +buf[0] = AD_line; /* A/D input line number is the first data byte sent */ +buf[1] = V_out; /* D/A out value is the second data byte sent */ +write(i2c,buf,2); /* we send 2 bytes */ +read(i2c,buf,1); /* buf(0) contains the byte of data in the chip cache */ +//sleep (1); /* do it again */ +// read(i2c,buf,1); /* buf(0) now contains the byte of data from the most recent analogue input*/ +AD_line_1 = buf[0]; + +AD_line = 2 + 64; /* enable the D/A output pin 0*/ +buf[0] = AD_line; /* A/D input line number is the first data byte sent */ +buf[1] = V_out; /* D/A out value is the second data byte sent */ +write(i2c,buf,2); /* we send 2 bytes */ +read(i2c,buf,1); /* buf(0) contains the byte of data in the chip cache */ +//sleep (1); /* do it again */ +// read(i2c,buf,1); /* buf(0) now contains the byte of data from the most recent analogue input*/ +AD_line_2 = buf[0]; + +AD_line = 3 + 64; /* enable the D/A output pin 0*/ +buf[0] = AD_line; /* A/D input line number is the first data byte sent */ +buf[1] = V_out; /* D/A out value is the second data byte sent */ +write(i2c,buf,2); /* we send 2 bytes */ +read(i2c,buf,1); /* buf(0) contains the byte of data in the chip cache */ +//sleep (1); /* do it again */ +// read(i2c,buf,1); /* buf(0) now contains the byte of data from the most recent analogue input*/ +AD_line_3 = buf[0]; + +printf("A/D line 0 = %d \n", AD_line_0, " "); +printf("A/D line 1 = %d \n", AD_line_1, " "); +printf("A/D line 2 = %d \n", AD_line_2, " "); +printf("A/D line 3 = %d \n", AD_line_3, " "); +/*AD_line_x goes 0 to 255 as voltage input goes from 0 to supply voltage*/ + +i2c = close(i2c); +return(0); +} diff --git a/pcf8591_2.c b/pcf8591_2.c new file mode 100644 index 0000000..cbbc2ed --- /dev/null +++ b/pcf8591_2.c @@ -0,0 +1,73 @@ +/* + PCF8591_addr_line.c + ------------------- + read the voltage on one A/D line (0-3) and set the output voltage on the D/A pin + -------------------------------------------------------------------------------- + + 1) send the i2c address as decimal + 2) send A/D line number (program adds 64 to enable D/A in control register) + 3) send byte for D/A out + 4) read the chosen A/D - print it as a raw decimal 0 to 255 + 5) save the chosen port value to /var/www/ramdisk/AtoD.dat + usage :- type with spaces but without the < > +
+ (even if the D/A pin is unused type in any value 0-255) +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "smbus.h" + + +int main(int argc, char** argv) +{ + int i2c; + int AD_line; /* line number 0-3 */ + int V_out; /* value for the D/A out line */ + int buf[1]; /* use to feed the i2c driver */ + int address; /* i2c bus address */ + int byte_in_0; /* the 8 bit byte that represents the voltage on the AD_line */ + + if (argc != 4) /* report error if we are not getting just 3 inputs after the program name */ + { + printf("Error. usage: %s i2c_chip_address A/D_line_(0-3) D/A_Vout(0-255)\n", argv[0]); + } + + address = atoi(argv[1]); /* address is the first number after the program name */ + AD_line = atoi(argv[2]); /* A/D input line 0-3 */ + AD_line = AD_line + 64; /* enable the D/A output pin */ + V_out = atoi(argv[3]); /* A/D input line 0-3 */ + + i2c = open("/dev/i2c/0",O_RDWR); /* open the i2c-bus number 0 */ + + ioctl(i2c,I2C_SLAVE, address); /* set the i2c-bus address of the chip we will talk to */ + + buf[0] = AD_line; /* A/D input line number is the first data byte sent */ + buf[1] = V_out; /* D/A out value is the second data byte sent */ + + write(i2c,buf,2); /* we send 2 bytes */ + + read(i2c,buf,1); /* buf(0) contains the byte of data in the chip cache */ + /* do it again */ + read(i2c,buf,1); /* buf(0) now contains the byte of data from the most recent analogue input*/ + + printf("BYTE = %d \n", buf[0]); + printf("%d\n", buf[0]); + /* buf[0] is an integer. It goes 0 to 255 as voltage input goes from 0 to supply voltage*/ + + //save AtoD byte to ramdisk + FILE *f; + f = fopen("/tmp/AtoD.dat","w"); + fprintf(f, "%d", buf[0]); + fclose(f); + + i2c = close(i2c); +} + + diff --git a/pcf8591_3.c b/pcf8591_3.c new file mode 100644 index 0000000..acb0e4a --- /dev/null +++ b/pcf8591_3.c @@ -0,0 +1,66 @@ +/* +PCF8591_address_channel_Vout.c +------------------------------ +read the voltage on one A/D lines (0-3) and set the output voltage on the D/A pin +--------------------------------------------------------------------------------- + +1) send the i2c address +2) choose channel 0-3 +3) send byte for D/A out +3) read channel volts as (0 to 255) / 255 x 5V +usage :- type with spaces but without the < > +
+(even if the D/A pin is unused type in any value 0-255) +*/ + +#include +#include +#include +#include +#include +#include +#define I2C_SLAVE0x0703/* Change slave address*/ +int i2c; +int channel; /* line number 0-3 */ +int V_out; /* value for the D/A out line */ +unsigned char buf[1]; /* use to feed the i2c driver */ +unsigned long address; /* i2c bus address */ +int byte_in_0; /* the 8 bit byte that represents the voltage on the AD_line */ +int AD_input; /* volts byte on chosen channel */ + +int rc; + +int main(int argc, char** argv) +{ +if (argc != 4) /* report error if we are not getting just 3 inputs after the program name */ +{ +printf("Error. usage: %s i2c_chip_address channel_to_read D/A_Vout(0-255)\n", argv[0]); +} + +address = atoi(argv[1]); /* decimal address is the first number after the program name */ +channel = atoi(argv[2]); /* choose A to D line to read 0-3 */ +V_out = atoi(argv[3]); /* volts out as decimal 0-255 */ + +i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */ +rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */ + +channel = channel + 64; /* enable the D/A output */ +buf[0] = channel; /* A/D input line number is the first data byte sent */ +buf[1] = V_out; /* D/A out value is the second data byte sent */ +write(i2c,buf,2); /* we send 2 bytes */ +read(i2c,buf,1); /* buf(0) contains the byte of data in the chip cache */ +usleep (1000); /* do it again */ +read(i2c,buf,1); /* buf(0) now contains the byte of data from the most recent analogue input*/ +AD_input = buf[0]; + + + +printf("%d", AD_input); + + + +/*AD_line_x goes 0 to 255 as voltage input goes from 0 to supply voltage*/ + +i2c = close(i2c); +return(0); +} diff --git a/pcf8591_4.c b/pcf8591_4.c new file mode 100644 index 0000000..0a40ad6 --- /dev/null +++ b/pcf8591_4.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "smbus.h" +#include /* sudo apt-get install libncurses5-dev */ + +// gcc -o pcf8591_2 -lncurses pcf8591_2.c + +int main( int argc, char **argv ) +{ + int i; + int r; + int fd; + int aout; + unsigned char command[2]; + unsigned char value[4]; + unsigned char str[8]; + useconds_t delay = 5000; + + char *dev = "/dev/i2c-0"; + int addr = 0x48; + + int j; + int key; + + initscr(); + noecho(); + cbreak(); + nodelay(stdscr, true); + curs_set(0); + printw("PCF8591"); + + mvaddstr(10, 0, "Brightness"); + mvaddstr(12, 0, "Temperature"); + mvaddstr(14, 0, "?"); + mvaddstr(16, 0, "Resistor"); + refresh(); + fd = open(dev, O_RDWR ); + if(fd < 0) + { + perror("Opening i2c device node\n"); + return 1; + } + + r = ioctl(fd, I2C_SLAVE, addr); + if(r < 0) + { + perror("Selecting i2c device\n"); + } + + command[1] = 0; + aout = 0; + while(1) + { + for(i = 0; i < 4; i++) + { + command[1]=aout++; + command[0] = 0x40 | ((i + 1) & 0x03); // output enable | read input i + r = write(fd, &command, 2); + usleep(delay); + // the read is always one step behind the selected input + r = read(fd, &value[i], 1); + if(r != 1) + { + perror("reading i2c device\n"); + } + usleep(delay); + + sprintf(str, "%3d", value[i]); + mvaddstr(10+i+i, 12, str); + value[i] = value[i] / 4; + move(10 + i + i, 16); + + for(j = 0; j < 64; j++) + { + if(j < value[i]) + { + addch('*'); + } + else + { + addch(' '); + } + } + } + refresh(); + + key = getch(); + if(key == 43) + { + command[1]++; + } + else if(key == 45) + { + command[1]--; + } + else if(key > -1) + { + break; + } + } + + endwin(); + close(fd); + printf("%d\n", key); + return(0); +} \ No newline at end of file diff --git a/pcf8591d.c b/pcf8591d.c new file mode 100644 index 0000000..3613538 --- /dev/null +++ b/pcf8591d.c @@ -0,0 +1,67 @@ +//*************************************************** +// pcf8591d.c +// +// Example to read A/D values from a +// 4 channel / 8 bit AD converter PCF8591 +// through I2C using the I2C driver improved by +// Geert Vancompernolle +// http://www.acmesystems.it/?id=10 +//*************************************************** + +#include "stdio.h" +#include "stdlib.h" +#include "unistd.h" +#include "sys/ioctl.h" +#include "fcntl.h" +#include "time.h" +#include "string.h" + +#include "i2c_errno.h" +#include "etraxi2c.h" + + +int main( int argc, char **argv ) { + int rtc; + int fd_i2c; + I2C_DATA i2c_d; + int ch; + + printf("Reading from a PCF8591 (4 chanel A/D at 8 bits with I2C bus)\n"); + + fd_i2c = open( "/dev/i2c-0", O_RDWR ); + if (fd_i2c<=0) { + printf( "Open error on /dev/i2c\n" ); + exit( 1 ); + } + + // PCF8591 address scheme + // | 1 | 0 | 0 | 1 | A2 | A1 | A0 | R/W | +// i2c_d.slave =(0x09<<4)|(0x01<<1); + + i2c_d.slave = 0x48; + + for (ch=0;ch<=3;ch++) { + // Select the A/D channel + i2c_d.wbuf[0] = ch; + i2c_d.wlen = 1; + if ((rtc=ioctl(fd_i2c,_IO( ETRAXI2C_IOCTYPE, I2C_WRITE), &i2c_d))!=EI2CNOERRORS) { + close(fd_i2c); + printf( "Error %d on line %d\n",rtc,__LINE__); + return ( -1 ); + } + + i2c_d.rlen = 3; + if ((rtc=ioctl(fd_i2c,_IO( ETRAXI2C_IOCTYPE, I2C_READ), &i2c_d))!=EI2CNOERRORS) { + close(fd_i2c); + printf( "Error %d on line %d\n",rtc,__LINE__); + return ( -1 ); + } + + // Show the voltage level + printf("Chanel %d = %.2fv (%02X hex)\n",ch,i2c_d.rbuf[2]*0.012941,i2c_d.rbuf[2]); + } + + close(fd_i2c); + return(0); +} + diff --git a/sethwclock b/sethwclock new file mode 100644 index 0000000..40e94d7 --- /dev/null +++ b/sethwclock @@ -0,0 +1,26 @@ +#!/bin/sh + +I2CBUS=0 +I2CADDR=0x68 + +if [ "$1" == "" ] +then + date=`date -u +%Y%m%d%H%M%S` +else + date=$1 +fi + +year=${date:2:2} +month=${date:4:2} +day=${date:6:2} + +hour=${date:8:2} +min=${date:10:2} +sec=${date:12:2} + +i2cset -y $I2CBUS $I2CADDR 0 0x$sec +i2cset -y $I2CBUS $I2CADDR 1 0x$min +i2cset -y $I2CBUS $I2CADDR 2 0x$hour +i2cset -y $I2CBUS $I2CADDR 4 0x$day +i2cset -y $I2CBUS $I2CADDR 5 0x$month +i2cset -y $I2CBUS $I2CADDR 6 0x$year diff --git a/sht21.c b/sht21.c new file mode 100644 index 0000000..4a415a6 --- /dev/null +++ b/sht21.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include + +#include /* add by paulerr*/ + + +#define CHIP "/dev/i2c-0" +#define CHIP_ADDR 0x40 //HTU21D地址 +#define READ_TEMP 0XE3 //温度转换命令 +#define READ_HUM 0XE5 //湿度转换命令 + +/* More info: https://github.com/kingmacth/Openwet-SDK/tree/master/package/HTU21D */ + +unsigned char HTU21D_Check_CRC(unsigned short int message_from_sensor,unsigned char check_value_from_sensor); + +int main() + +{ + printf("hello,this is HTU21D tester \n"); + int fd =open(CHIP, O_RDWR); + if (fd< 0) { + printf("open"CHIP"failed \n"); + goto exit; + } + + if (ioctl(fd,I2C_SLAVE_FORCE, CHIP_ADDR) < 0) { /*设置芯片地址 */ + printf("oictl:setslave address failed\n"); + goto close; + } + + struct i2c_msg msg; + + unsigned char rddata[3]; + unsigned char rdaddr[2] = {0x10, 0}; /* 将要读取的数据在芯片中的偏移量 */ + unsigned char TempAddr[2] = {0xe3, 0}; /* 发送E3读取温度 */ + unsigned char HumAddr[2] = {0xE5, 0}; /* 发送E5读取湿度 */ + unsigned short int tmp_dat,CRC_Result; + float Temp,Hum; + /*printf("inputa char you want to write to E2PROM\n"); + wrbuf[2]= getchar(); + printf("writereturn:%d, write data:%x\n", write(fd, wrbuf, 1), wrbuf[2]); + sleep(5);*/ + //printf("Read temp!\n",write(fd, TempAddr, 1)); /* 开启温度转换 */ + write(fd, TempAddr, 1); + usleep(100000); + read(fd, &rddata, 3); //读取两字节温度一字节校验 + + tmp_dat=rddata[0]; + tmp_dat=tmp_dat<<8; + tmp_dat=tmp_dat+rddata[1]; + //printf("rddata:%x%02x,%x\n", rddata[0], rddata[1],rddata[2]); + CRC_Result=HTU21D_Check_CRC(tmp_dat,rddata[2]); + //printf("CRC=%x,%x\n",CRC_Result ,tmp_dat);//CRC校验 + if(CRC_Result==0) + { + Temp=(tmp_dat*175.72)/65536-46.85; + printf("Temp=%.2f\n",Temp); + } + //printf("Read hum!\n",write(fd, HumAddr, 1)); /* 开启湿度转换 */ + write(fd, HumAddr, 1); + usleep(100000); + read(fd, &rddata, 3); //读取两字节湿度一字节校验 + + tmp_dat=rddata[0]; + tmp_dat=tmp_dat<<8; + tmp_dat=tmp_dat+rddata[1]; + //printf("rddata:%x%02x,%x\n", rddata[0], rddata[1],rddata[2]); + CRC_Result=HTU21D_Check_CRC(tmp_dat,rddata[2]); + //printf("CRC=%x,%x\n",CRC_Result ,tmp_dat);//CRC校验 + if(CRC_Result==0) + { + Temp=(tmp_dat*125)/65536-6; + printf("Hum=%.2f%%RH\n",Temp); + } + +close: + close(fd); +exit: + return 0; + +} + +//************************************************************************************************************** +//两个参数一个是传感器的源数据,另一个是传感器得出的CRC校验值 +//如果校验通过返回0,不通过返回非0 +//From: http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html +//POLYNOMIAL = 0x0131 = x^8 + x^5 + x^4 + 1 : http://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks +#define SHIFTED_DIVISOR 0x988000 //This is the 0x0131 polynomial shifted to farthest left of three bytes +//************************************************************************************************************** +unsigned char HTU21D_Check_CRC(unsigned short int message_from_sensor,unsigned char check_value_from_sensor) +{ +unsigned char i; +//Test cases from datasheet: +//message = 0xDC, checkvalue is 0x79 +//message = 0x683A, checkvalue is 0x7C +//message = 0x4E85, checkvalue is 0x6B +unsigned int remainder = (unsigned int)message_from_sensor << 8; //Pad with 8 bits because we have to add in the check value +unsigned int divsor = (unsigned int)SHIFTED_DIVISOR; +remainder |= check_value_from_sensor; //Add on the check value +for (i = 0 ; i < 16 ; i++) //Operate on only 16 positions of max 24. The remaining 8 are our remainder and should be zero when we're done. +{ +if( remainder & (unsigned int)1<<(23 - i) ) //Check if there is a one in the left position +remainder ^= divsor; +divsor>>=1;//Rotatethedivsormax16timessothatwehave8bitsleftofaremainder +} +return(unsigned char)remainder; +} diff --git a/smbus.c b/smbus.c new file mode 100644 index 0000000..623519e --- /dev/null +++ b/smbus.c @@ -0,0 +1,228 @@ +/* + smbus.c - SMBus level access helper functions + + Copyright (C) 1995-97 Simon G. Vogl + Copyright (C) 1998-99 Frodo Looijaard + Copyright (C) 2012 Jean Delvare + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#include +#include "smbus.h" // NB: Path changed! +#include +#include +#include +#include + +//NB: Added by John Burns +#ifndef NULL +#define NULL 0 +#endif + +/* Compatibility defines */ +#ifndef I2C_SMBUS_I2C_BLOCK_BROKEN +#define I2C_SMBUS_I2C_BLOCK_BROKEN I2C_SMBUS_I2C_BLOCK_DATA +#endif +#ifndef I2C_FUNC_SMBUS_PEC +#define I2C_FUNC_SMBUS_PEC I2C_FUNC_SMBUS_HWPEC_CALC +#endif + +__s32 i2c_smbus_access(int file, char read_write, __u8 command, + int size, union i2c_smbus_data *data) +{ + struct i2c_smbus_ioctl_data args; + __s32 err; + + args.read_write = read_write; + args.command = command; + args.size = size; + args.data = data; + + err = ioctl(file, I2C_SMBUS, &args); + if (err == -1) + err = -errno; + return err; +} + + +__s32 i2c_smbus_write_quick(int file, __u8 value) +{ + return i2c_smbus_access(file, value, 0, I2C_SMBUS_QUICK, NULL); +} + +__s32 i2c_smbus_read_byte(int file) +{ + union i2c_smbus_data data; + int err; + + err = i2c_smbus_access(file, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data); + if (err < 0) + return err; + + return 0x0FF & data.byte; +} + +__s32 i2c_smbus_write_byte(int file, __u8 value) +{ + return i2c_smbus_access(file, I2C_SMBUS_WRITE, value, + I2C_SMBUS_BYTE, NULL); +} + +__s32 i2c_smbus_read_byte_data(int file, __u8 command) +{ + union i2c_smbus_data data; + int err; + + err = i2c_smbus_access(file, I2C_SMBUS_READ, command, + I2C_SMBUS_BYTE_DATA, &data); + if (err < 0) + return err; + + return 0x0FF & data.byte; +} + +__s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value) +{ + union i2c_smbus_data data; + data.byte = value; + return i2c_smbus_access(file, I2C_SMBUS_WRITE, command, + I2C_SMBUS_BYTE_DATA, &data); +} + +__s32 i2c_smbus_read_word_data(int file, __u8 command) +{ + union i2c_smbus_data data; + int err; + + err = i2c_smbus_access(file, I2C_SMBUS_READ, command, + I2C_SMBUS_WORD_DATA, &data); + if (err < 0) + return err; + + return 0x0FFFF & data.word; +} + +__s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value) +{ + union i2c_smbus_data data; + data.word = value; + return i2c_smbus_access(file, I2C_SMBUS_WRITE, command, + I2C_SMBUS_WORD_DATA, &data); +} + +__s32 i2c_smbus_process_call(int file, __u8 command, __u16 value) +{ + union i2c_smbus_data data; + data.word = value; + if (i2c_smbus_access(file, I2C_SMBUS_WRITE, command, + I2C_SMBUS_PROC_CALL, &data)) + return -1; + else + return 0x0FFFF & data.word; +} + +/* Returns the number of read bytes */ +__s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values) +{ + union i2c_smbus_data data; + int i, err; + + err = i2c_smbus_access(file, I2C_SMBUS_READ, command, + I2C_SMBUS_BLOCK_DATA, &data); + if (err < 0) + return err; + + for (i = 1; i <= data.block[0]; i++) + values[i-1] = data.block[i]; + return data.block[0]; +} + +__s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, + const __u8 *values) +{ + union i2c_smbus_data data; + int i; + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + for (i = 1; i <= length; i++) + data.block[i] = values[i-1]; + data.block[0] = length; + return i2c_smbus_access(file, I2C_SMBUS_WRITE, command, + I2C_SMBUS_BLOCK_DATA, &data); +} + +/* Returns the number of read bytes */ +/* Until kernel 2.6.22, the length is hardcoded to 32 bytes. If you + ask for less than 32 bytes, your code will only work with kernels + 2.6.23 and later. */ +__s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 length, + __u8 *values) +{ + union i2c_smbus_data data; + int i, err; + + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + data.block[0] = length; + + err = i2c_smbus_access(file, I2C_SMBUS_READ, command, + length == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN : + I2C_SMBUS_I2C_BLOCK_DATA, &data); + if (err < 0) + return err; + + for (i = 1; i <= data.block[0]; i++) + values[i-1] = data.block[i]; + return data.block[0]; +} + +__s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length, + const __u8 *values) +{ + union i2c_smbus_data data; + int i; + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + for (i = 1; i <= length; i++) + data.block[i] = values[i-1]; + data.block[0] = length; + return i2c_smbus_access(file, I2C_SMBUS_WRITE, command, + I2C_SMBUS_I2C_BLOCK_BROKEN, &data); +} + +/* Returns the number of read bytes */ +__s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length, + __u8 *values) +{ + union i2c_smbus_data data; + int i, err; + + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + for (i = 1; i <= length; i++) + data.block[i] = values[i-1]; + data.block[0] = length; + + err = i2c_smbus_access(file, I2C_SMBUS_WRITE, command, + I2C_SMBUS_BLOCK_PROC_CALL, &data); + if (err < 0) + return err; + + for (i = 1; i <= data.block[0]; i++) + values[i-1] = data.block[i]; + return data.block[0]; +} diff --git a/smbus.h b/smbus.h new file mode 100644 index 0000000..b7facf6 --- /dev/null +++ b/smbus.h @@ -0,0 +1,59 @@ +/* + smbus.h - SMBus level access helper functions + + Copyright (C) 1995-97 Simon G. Vogl + Copyright (C) 1998-99 Frodo Looijaard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + MA 02110-1301 USA. +*/ + +#ifndef LIB_I2C_SMBUS_H +#define LIB_I2C_SMBUS_H + +#include +#include + +extern __s32 i2c_smbus_access(int file, char read_write, __u8 command, + int size, union i2c_smbus_data *data); + +extern __s32 i2c_smbus_write_quick(int file, __u8 value); +extern __s32 i2c_smbus_read_byte(int file); +extern __s32 i2c_smbus_write_byte(int file, __u8 value); +extern __s32 i2c_smbus_read_byte_data(int file, __u8 command); +extern __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value); +extern __s32 i2c_smbus_read_word_data(int file, __u8 command); +extern __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value); +extern __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value); + +/* Returns the number of read bytes */ +extern __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values); +extern __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, + const __u8 *values); + +/* Returns the number of read bytes */ +/* Until kernel 2.6.22, the length is hardcoded to 32 bytes. If you + ask for less than 32 bytes, your code will only work with kernels + 2.6.23 and later. */ +extern __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 length, + __u8 *values); +extern __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length, + const __u8 *values); + +/* Returns the number of read bytes */ +extern __s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length, + __u8 *values); + +#endif /* LIB_I2C_SMBUS_H */ diff --git a/syncfromhwclock b/syncfromhwclock new file mode 100644 index 0000000..e07d3ba --- /dev/null +++ b/syncfromhwclock @@ -0,0 +1,3 @@ +#!/bin/sh + +date -u -s "`gethwclock`"