Skip to content

Instantly share code, notes, and snippets.

@user890104
Created March 30, 2016 07:57
Show Gist options
  • Save user890104/a2a7d0dc03b1abf4a9f895624ae64102 to your computer and use it in GitHub Desktop.
Save user890104/a2a7d0dc03b1abf4a9f895624ae64102 to your computer and use it in GitHub Desktop.
Si7021 collecting and reporting data to thingspeak.com
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#define BYTES2SHORT(X) (X[0] << 8 | X[1])
enum si7021_cmd_id {
MEAS_HUM,
MEAS_TEMP,
READ_TEMP,
RESET,
WRITE_USER_REG,
READ_USER_REG,
WRITE_HEATER_REG,
READ_HEATER_REG,
READ_SN_1,
READ_SN_2,
READ_FWREV,
SI7021_CMDS_COUNT
};
const char **si7021_cmd;
unsigned int i2c_rw(int file, const char *wdata, size_t wlen, char *rdata, size_t rlen) {
if (wlen) {
if (write(file, wdata, wlen) != wlen) {
perror("write");
return 1;
}
}
if (rlen) {
int retries = 10;
int result = read(file, rdata, rlen);
while (
result == -1 && // read error
errno == ENXIO && // NACK
(--retries > 0)
) {
result = read(file, rdata, rlen); // retry
usleep(5000); // wait 5 ms
}
if (result != rlen) {
perror("read");
return 2;
}
}
return 0;
}
int si7021_print_part(int file) {
char resp[6];
if (i2c_rw(file, si7021_cmd[READ_SN_2], 2, resp, 1)) {
return 1;
}
fputs("PART: ", stderr);
switch (resp[0]) {
case 0x00:
case 0xFF:
fputs("Engineering sample", stderr);
break;
case 0x0D:
fputs("Si7013", stderr);
break;
case 0x14:
fputs("Si7020", stderr);
break;
case 0x15:
fputs("Si7021", stderr);
break;
default:
fputs("UNKNOWN", stderr);
break;
}
fputs("\n", stderr);
return 0;
}
int si7021_print_sn(int file) {
char resp[8];
if (i2c_rw(file, si7021_cmd[READ_SN_1], 2, resp, 8)) {
return 1;
}
fprintf(stderr, "SN: %02x%02x%02x%02x\n", resp[0], resp[2], resp[4], resp[6]);
return 0;
}
int si7021_print_fwrev(int file) {
char resp;
if (i2c_rw(file, si7021_cmd[READ_FWREV], 2, &resp, 1)) {
return 1;
}
fputs("FWREV: ", stderr);
switch (resp) {
case 0xFF:
fputs("1.0", stderr);
break;
case 0x20:
fputs("2.0", stderr);
break;
default:
fputs("UNKNOWN", stderr);
break;
}
fputs("\n", stderr);
return 0;
}
int si7021_get_env(int file, char *buf) {
char resp[3];
if (i2c_rw(file, si7021_cmd[MEAS_HUM], 1, resp, 3)) {
return 1;
}
float hum = 125.0 * BYTES2SHORT(resp) / 65536 - 6;
if (i2c_rw(file, si7021_cmd[READ_TEMP], 1, resp, 2)) {
return 1;
}
float temp = 175.72 * BYTES2SHORT(resp) / 65536 - 46.85;
fprintf(stderr, "T: %f°C\nH: %f%%\n", temp, hum);
char fields[64];
sprintf(fields, "&field1=%f&field2=%f", temp, hum);
strcat(buf, fields);
return 0;
}
short axp209_get_value(int file, char request[2], unsigned char bits) {
char buffer;
short result;
if (i2c_rw(file, request, 1, &buffer, 1)) {
return 0xffff;
}
result = buffer << bits;
if (i2c_rw(file, request + 1, 1, &buffer, 1)) {
return 0xffff;
}
result |= buffer;
//fprintf(stderr, "READ: 0x%04x = %d\n", result, result);
return result;
}
int axp209_get_value_scaled(int file, char request[2], unsigned char bits, float step, float *result) {
short value = axp209_get_value(file, request, bits);
if (value == 0xffff) {
return 1;
}
*result = step * value / 1000;
return 0;
}
int axp209_get_vbus_voltage(int file, float *result) {
return axp209_get_value_scaled(file, "\x5A\x5B", 4, 1.7, result);
}
int axp209_get_vbus_current(int file, float *result) {
return axp209_get_value_scaled(file, "\x5C\x5D", 4, 0.375, result);
}
int axp209_get_temperature(int file, float *result) {
short value = axp209_get_value(file, "\x5E\x5F", 4);
if (value == 0xffff) {
return 1;
}
*result = 0.1 * value - 144.7;
return 0;
}
int axp209_get_battery_voltage(int file, float *result) {
return axp209_get_value_scaled(file, "\x78\x79", 4, 1.1, result);
}
int axp209_get_charge_current(int file, float *result) {
return axp209_get_value_scaled(file, "\x7A\x7B", 4, 0.5, result);
}
int axp209_get_discharge_current(int file, float *result) {
return axp209_get_value_scaled(file, "\x7C\x7D", 5, 0.5, result);
}
int axp209_get_ipsout_voltage(int file, float *result) {
return axp209_get_value_scaled(file, "\x7E\x7F", 4, 1.4, result);
}
int axp209_get_data(int file, char *buf) {
float value;
if (axp209_get_vbus_voltage(file, &value) == 0) {
fprintf(stderr, "Uvbus: %.4fV\n", value);
char fields[64];
sprintf(fields, "&field6=%.4f", value);
strcat(buf, fields);
}
if (axp209_get_vbus_current(file, &value) == 0) {
fprintf(stderr, "Ivbus: %.6fA\n", value);
char fields[64];
sprintf(fields, "&field7=%.6f", value);
strcat(buf, fields);
}
if (axp209_get_temperature(file, &value) == 0) {
fprintf(stderr, "Tchip: %.1f°C\n", value);
char fields[64];
sprintf(fields, "&field3=%.1f", value);
strcat(buf, fields);
}
if (axp209_get_battery_voltage(file, &value) == 0) {
fprintf(stderr, "Ubatt: %.4fV\n", value);
char fields[64];
sprintf(fields, "&field4=%.4f", value);
strcat(buf, fields);
}
if (axp209_get_charge_current(file, &value) == 0) {
fprintf(stderr, "Icharge: %.4fA\n", value);
char fields[64];
sprintf(fields, "&field5=%.4f", value);
strcat(buf, fields);
}
if (axp209_get_discharge_current(file, &value) == 0) {
fprintf(stderr, "Idischarge: %.4fA\n", value);
char fields[64];
sprintf(fields, "&field8=%.4f", value);
strcat(buf, fields);
}
if (axp209_get_ipsout_voltage(file, &value) == 0) {
fprintf(stderr, "Uipsout: %.4fV\n", value);
//char fields[64];
//sprintf(fields, "&field5=%.4f", value);
//strcat(buf, fields);
}
return 0;
}
int i2c_connect(unsigned char i2c_id, unsigned char addr) {
char filename[14];
strcpy(filename, "/dev/i2c-");
char id[5];
sprintf(id, "%u", i2c_id);
strcat(filename, id);
fputs(filename, stderr);
fputs("\n", stderr);
int file;
if ((file = open(filename, O_RDWR)) < 0) {
perror("open");
return -1;
}
if (ioctl(file, I2C_SLAVE, addr) < 0) {
perror("ioctl I2C_SLAVE");
if (ioctl(file, I2C_SLAVE_FORCE, addr) < 0) {
perror("ioctl I2C_SLAVE_FORCE");
close(file);
return -1;
}
}
return file;
}
void si7021_write_data(char *buf) {
si7021_cmd = calloc(SI7021_CMDS_COUNT, sizeof(char *));
si7021_cmd[MEAS_HUM] = "\xF5";
si7021_cmd[MEAS_TEMP] = "\xF3";
si7021_cmd[READ_TEMP] = "\xE0";
si7021_cmd[RESET] = "\xFE";
si7021_cmd[WRITE_USER_REG] = "\xE6";
si7021_cmd[READ_USER_REG] = "\xE7";
si7021_cmd[WRITE_HEATER_REG] = "\x51";
si7021_cmd[READ_HEATER_REG] = "\x11";
si7021_cmd[READ_SN_1] = "\xFA\x0F";
si7021_cmd[READ_SN_2] = "\xFC\xC9";
si7021_cmd[READ_FWREV] = "\x84\xB8";
int file = i2c_connect(1, 0x40);
if (file == -1) {
return;
}
si7021_print_part(file);
si7021_print_sn(file);
si7021_print_fwrev(file);
si7021_get_env(file, buf);
close(file);
}
void axp209_write_data(char *buf) {
int file = i2c_connect(0, 0x34);
if (file == -1) {
return;
}
axp209_get_data(file, buf);
close(file);
}
int main(int argc, char **argv) {
char buf[2048];
strcpy(buf, "http://api.thingspeak.com/update?api_key=XXXXXXXXXXXXXXXX");
si7021_write_data(buf);
axp209_write_data(buf);
puts(buf);
return 0;
}
#!/bin/bash
while [ 1 ]
do
wget -qO/dev/null "$(/home/chip/i2c/report 2>/dev/null)"
sleep 15
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment