TM7705 16bit bipolar adc

have two tm7705 boards from ebay, im trying to read adc chanel 1 with a library made by Kerry D.Wong but its not working, when conecting 4.6v supply to board input pins then measured voltage with voltmeter across -ain +ain of adc chip is 2.3v thats half the voltage of the supply meaning that input circuitry is dividing the input voltage, and the value showing in serial monitor is 1.33 even if i change the input voltage, i noticed that if i change GAIN_1 to GAIN_128 the value changes to 2.42 but stays there even when changing input voltage,

checked the datasheet but seems that the library is made correct i don`t know whats wrong the library and code is as below:

#ifndef AD770X_H
#define AD770X_H

#include <Arduino.h>

/*

class AD770X {
public:
//register selection
//RS2 RS1 RS0
static const byte REG_CMM = 0x0; //communication register 8 bit
static const byte REG_SETUP = 0x1; //setup register 8 bit
static const byte REG_CLOCK = 0x2; //clock register 8 bit
static const byte REG_DATA = 0x3; //data register 16 bit, contains conversion result
static const byte REG_TEST = 0x4; //test register 8 bit, POR 0x0
static const byte REG_NOP = 0x5; //no operation
static const byte REG_OFFSET = 0x6; //offset register 24 bit
static const byte REG_GAIN = 0x7; // gain register 24 bit

//channel selection for AD7706 (for AD7705 use the first two channel definitions)
//CH1 CH0
static const byte CHN_AIN1 = 0x0; //AIN1; calibration register pair 0
static const byte CHN_AIN2 = 0x1; //AIN2; calibration register pair 1
static const byte CHN_COMM = 0x2; //common; calibration register pair 0
static const byte CHN_AIN3 = 0x3; //AIN3; calibration register pair 2

//output update rate
//CLK FS1 FS0
static const byte UPDATE_RATE_20 = 0x0; // 20 Hz
static const byte UPDATE_RATE_25 = 0x1; // 25 Hz
static const byte UPDATE_RATE_100 = 0x2; // 100 Hz
static const byte UPDATE_RATE_200 = 0x3; // 200 Hz
static const byte UPDATE_RATE_50 = 0x4; // 50 Hz
static const byte UPDATE_RATE_60 = 0x5; // 60 Hz
static const byte UPDATE_RATE_250 = 0x6; // 250 Hz
static const byte UPDATE_RATE_500 = 0x7; // 500 Hz

//operating mode options
//MD1 MD0
static const byte MODE_NORMAL = 0x0; //normal mode
static const byte MODE_SELF_CAL = 0x1; //self-calibration
static const byte MODE_ZERO_SCALE_CAL = 0x2; //zero-scale system calibration, POR 0x1F4000, set FSYNC high before calibration, FSYNC low after calibration
static const byte MODE_FULL_SCALE_CAL = 0x3; //full-scale system calibration, POR 0x5761AB, set FSYNC high before calibration, FSYNC low after calibration

//gain setting
static const byte GAIN_1 = 0x0;
static const byte GAIN_2 = 0x1;
static const byte GAIN_4 = 0x2;
static const byte GAIN_8 = 0x3;
static const byte GAIN_16 = 0x4;
static const byte GAIN_32 = 0x5;
static const byte GAIN_64 = 0x6;
static const byte GAIN_128 = 0x7;

static const byte UNIPOLAR = 0x0;
static const byte BIPOLAR = 0x1;

static const byte CLK_DIV_1 = 0x1;
static const byte CLK_DIV_2 = 0x2;

byte spiTransfer(volatile byte data) {
SPDR = data;

while (!(SPSR & _BV(SPIF)));

return SPDR;
};

AD770X(double vref);
void setNextOperation(byte reg, byte channel, byte readWrite);
void writeClockRegister(byte CLKDIS, byte CLKDIV, byte outputUpdateRate);
void writeSetupRegister(byte operationMode, byte gain, byte unipolar, byte buffered, byte fsync);
double readADResult(byte channel, float refOffset = 0.0);
void reset();
bool dataReady(byte channel);
int comRegRead(byte channel);
void init(byte channel);
void init(byte channel, byte clkDivider, byte polarity, byte gain, byte updRate);
private:
static const int pinMOSI = 11; //MOSI
static const int pinMISO = 12; //MISO
static const int pinSPIClock = 13; //SCK
static const int pinCS = 10; //CS
double VRef;
unsigned int readADResult();
};
#endif

/*

#include "AD770X.h"

//write communication register
// 7 6 5 4 3 2 1 0
//0/DRDY(0) RS2(0) RS1(0) RS0(0) R/W(0) STBY(0) CH1(0) CH0(0)

void AD770X::setNextOperation(byte reg, byte channel, byte readWrite) {
byte r = 0;
r = reg << 4 | readWrite << 3 | channel;

digitalWrite(pinCS, LOW);
spiTransfer(r);
digitalWrite(pinCS, HIGH);
}

//Clock Register
// 7 6 5 4 3 2 1 0
//ZERO(0) ZERO(0) ZERO(0) CLKDIS(0) CLKDIV(0) CLK(1) FS1(0) FS0(1)
//
//CLKDIS: master clock disable bit
//CLKDIV: clock divider bit

void AD770X::writeClockRegister(byte CLKDIS, byte CLKDIV, byte outputUpdateRate) {

//byte r = 0x01 << 2;
byte r = CLKDIS << 4 | CLKDIV << 3 | outputUpdateRate ;

r &= (1 << 2); // clear CLK

digitalWrite(pinCS, LOW);
spiTransfer(r);
digitalWrite(pinCS, HIGH);
}

//Setup Register
// 7 6 5 4 3 2 1 0
//MD10) MD0(0) G2(0) G1(0) G0(0) B/U(0) BUF(0) FSYNC(1)

void AD770X::writeSetupRegister(byte operationMode, byte gain, byte unipolar, byte buffered, byte fsync) {
byte r = operationMode << 6 | gain << 3 | unipolar << 2 | buffered << 1 | fsync;

digitalWrite(pinCS, LOW);
spiTransfer(r);
digitalWrite(pinCS, HIGH);
}

unsigned int AD770X::readADResult() {
digitalWrite(pinCS, LOW);
byte b1 = spiTransfer(0);
byte b2 = spiTransfer(0);
digitalWrite(pinCS, HIGH);

unsigned int r = b1 << 8 | b2;

return r;
}
double AD770X::readADResult(byte channel, float refOffset) {
while (!dataReady(channel)) {
};
setNextOperation(REG_DATA, channel, 1);

return readADResult() * 1.0 / 65536.0 * VRef - refOffset;
}

bool AD770X::dataReady(byte channel) {
setNextOperation(REG_CMM, channel, 1);

digitalWrite(pinCS, LOW);
byte b1 = spiTransfer(0);
digitalWrite(pinCS, HIGH);

return (b1 & 0xF0) == 0x0;
}

void AD770X::reset() {
digitalWrite(pinCS, LOW);
for (int i = 0; i < 100; i++)
spiTransfer(0xff);
digitalWrite(pinCS, HIGH);
}

AD770X::AD770X(double vref) {
VRef = vref;
pinMode(pinMOSI, OUTPUT);
pinMode(pinMISO, INPUT);
pinMode(pinSPIClock, OUTPUT);
pinMode(pinCS, OUTPUT);

digitalWrite(pinCS, HIGH);
SPCR = _BV(SPE) | _BV(MSTR) | _BV(CPOL) | _BV(CPHA) | _BV(SPI2X) | _BV(SPR1) | _BV(SPR0);
}

void AD770X::init(byte channel, byte clkDivider, byte polarity, byte gain, byte updRate) {
setNextOperation(REG_CLOCK, channel, 0);
writeClockRegister(1, clkDivider, updRate);

setNextOperation(REG_SETUP, channel, 0);
writeSetupRegister(MODE_SELF_CAL, gain, polarity, 0, 0);

while (!dataReady(channel)) {
};
}

void AD770X::init(byte channel) {
init(channel, CLK_DIV_1, BIPOLAR, GAIN_128, UPDATE_RATE_500);
}

/*

#include <AD770X.h>
#include <SPI.h>

AD770X ad7706(2.5);
double v;

void setup()
{
pinMode(SS, OUTPUT);
digitalWrite(SS,HIGH); //disable device
digitalWrite(10, HIGH);

Serial.begin(115200);

ad7706.reset();
ad7706.init(AD770X::CHN_AIN1);

}

void loop()
{
v = ad7706.readADResult(AD770X::CHN_AIN1, 0.0);
Serial.println(v);
}

The library is broken for tm7705, I can't remember exactly, but I needed to correct some things in there. I ended up writing my own code for accessing the module. But I never got proper results out of them. With those modules attached for example to my measring shunt, they start drawing much power. I'd think they have high impedance inputs, but this doesn't seem to be th case. Suspect my modules I tried (have some unused ones as well) are thus broken, even if I stayed in within the maximum ratings according to the datasheet.

I moved on to ADS1115 / ADS1118 which are very easy to access and very precise. They're even cheaper as well.
http://www.aliexpress.com/item/J34-Free-Shipping-16-Bit-I2C-ADS1115-Module-ADC-4-channel-with-Pro-Gain-Amplifier-for/32564528015.html

in case you want to try some different code to see if it works for you (I could only get it to work with one channel; everything else fails.)

////////////////////////////////////////////////////////////////////
// Improving speed: Ampere-Voltmeter with external 16 bit ADC
// 1) AD7705 on SPI (D11/12/13)
//
// 08/2015 by Koepi
//
// 21.08.2015
// Initial Test Version
// 01.01.2016
// Further testing, trying to get proper data from TM7705.
// 02.01.2016
// That was stupid of me: Remember, 011<<4 is NOT the same as 0b011<<4. 
// Works correctly _immediately_ when corrected the setup this way.
//
////////////////////////////////////////////////////////////////////

// AD7705 Communication Register
#define DRDY (1<<7)
#define COMREG (0b000<<4)
#define SETREG (0b001<<4)
#define CLKREG (0b010<<4)
#define DATREG (0b011<<4)
#define READ (1<<3)
// yes, I know, stupid ... but it helps readability.
#define WRITE (0<<3)
#define STDBY (1<<2)
#define CH1 (0b00<<0)
#define CH2 (0b01<<0)

// AD7705 Setup Register
#define NORMMODE (0b00<<6)
#define SELFCAL (0b01<<6)
#define ZEROCAL (0b10<<6)
#define FULLCAL (0b11<<6)
#define GAIN_1 (0b000<<3)
#define GAIN_2 (0b001<<3)
#define GAIN_4 (0b010<<3)
#define GAIN_8 (0b011<<3)
#define GAIN_16 (0b100<<3)
#define GAIN_32 (0b101<<3)
#define GAIN_64 (0b110<<3)
#define GAIN_128 (0b111<<3)
#define BIPOLAR (0<<2)
#define UNIPOLAR (1<<2)
#define BUF (1<<1)
#define FSYNC (1<<0)

// AD7705 Clock Register - frequency includes CLK, thus only 4 useable!
#define CLKDIS (1<<4)
#define CLKDIV (1<<3)
#define CLK (1<<2)
#define FREQ_50 (0b00<<0)
#define FREQ_60 (0b01<<0)
#define FREQ_250 (0b10<<0)
#define FREQ_500 (0b11<<0)


// Using x2 flag later for 115.2k UART
#define MYBAUD 57600UL  
#define UBRR_VAL (((F_CPU / (MYBAUD * 16UL))) - 1) 

//string for UART data output
char output[200];

byte AD7705_command = 0;
byte AD7705_setup = 0;
byte AD7705_clock = 0;

void setup() {
  // UART transfer setup (for monitoring/LogView)
  UBRR0 = UBRR_VAL;
  UCSR0A |= (1<<U2X0);
  UCSR0C = (1<<UCSZ01)|(1<<UCSZ00);
  UCSR0B |= (1<<TXEN0);

  sprintf(output, "AmVoltMeter AD7705 - V1.0.\n\r");
  uart_puts(output);

  // Setup SPI
  // Set SS, MOSI and SCK output (PB2,3,5; D10,11,13); MISO input (PB4; D12)
  DDRB |= (1<<PB2) | (1<<PB3) | (1<<PB5); 
  DDRB &= ~(1<<PB4);
  // SPI polarity - set SCK and MOSI high
  PORTB |= (1<<PB3) | (1<<PB5);
  // Enable SPI, Master, set clock rate fck/16 (SPR0=1), fck/128 (SPR1+0 1/1), fck/4 (0/0), fck/64 (1/0)
  SPCR = (0<<SPIE)|(1<<SPE)|(1<<MSTR)|(1<<CPOL)|(1<<CPHA)|(0<<SPR1)|(1<<SPR0);
  ad7705_reset();
  ad7705_init(CH1, GAIN_1, FREQ_50);  // Gain 1 = 0-2.5V
  ad7705_init(CH2, GAIN_1, FREQ_50);  // Gain 64 = 0-40mV

  sprintf(output, "Seconds; Vbat; mA; mAh;\n");
  uart_puts(output);
}

void loop() {
  static int16_t Vbat = 0;
  static uint16_t current = 0;
  static uint16_t mVshunt = 0;
  static uint16_t mVgain = 0;
  static uint32_t seconds = 0;
  static uint32_t ma = 0;
  static uint16_t mah = 0;
  static int32_t mV = 0;

  Vbat = ad7705_fetch(CH2);
  mV = (2500000.0 / 32767.0) * Vbat /1000.0;
  sprintf(output, "%i mV Bat; \n\r", mV);
  uart_puts(output);

/*
  ad7705_init(CH2, GAIN_64, FREQ_50);  // Gain 64 = 0-40mV
  mVshunt = ad7705_fetch(CH2);
  mV = (2500000L / 32767L) * (long)mVshunt;
  sprintf(output, "%lu µV Shunt; \n\r", mV);
  uart_puts(output);
*/
  delay(800);
}


void ad7705_reset() {
  // Reset the AD7705 - toggle SCK at least 32 times with MOSI (DIN) set HIGH 
  PORTB |= (1<<PB3);  // MOSI high
//  PORTB &= ~(1<<PB5);  // SCK low
  PORTB |= (1<<PB5);  // SCK high (siwtch with above for polarity change!)
  PORTB &= ~(1<<PB2);  // SS low
  for (uint8_t i=0; i<32; i++) {
    PORTB |= (1<<PB5);  // SCK high
    delay(1);
    PORTB &= ~(1<<PB5);  // SCK low
    delay(1);
  }
  PORTB |= (1<<PB5);  // SCK high (siwtch with above for polarity change!)
  PORTB &= (~1<<PB3);  // MOSI low
  PORTB |= (1<<PB2);  // SS high
  delay(16);  // wait for CLK etc. to settle.
}

void ad7705_init(byte channel, byte gain, byte freq) {
  AD7705_command = (CLKREG | WRITE | channel);
  spi_tx(AD7705_command);
  AD7705_clock = (CLKDIV | CLK | freq);
  spi_tx(AD7705_clock);
  AD7705_command = (SETREG | WRITE | channel);
  spi_tx(AD7705_command);
  AD7705_setup = (SELFCAL | gain | UNIPOLAR);
  spi_tx(AD7705_setup);
  while(!data_ready(channel));  // wait for calibration to finish
}

uint16_t ad7705_fetch(byte channel) {
  uint16_t result = 0;
  while(!data_ready(channel));
  AD7705_command = (DATREG | READ | channel);
  spi_tx(AD7705_command);
  result = (uint16_t)(spi_tx(0x00)<<8|(spi_tx(0x00)));

  return (result); 
}

bool data_ready(byte channel) {
//  bool result = false;
  // wait for conversion to finish - DRDY goes LOW
  AD7705_command = (COMREG | READ | channel);
  spi_tx(AD7705_command);
  if (spi_tx(0x00) & (1<<DRDY)) {
    return(false);
  } else {
    return(true);
  }
}

byte spi_tx (byte data) {
  PORTB &= ~(1<<PB2);  // SS low
  SPDR = data;
  while(!(SPSR & (1<<SPIF)));  // wait for SPI transfer ready - interrupt flag gets set
  PORTB |= (1<<PB2);  // SS high
  return (SPDR);
}

void uart_puts (char *s) {
  while (*s) {
    while (!(UCSR0A & (1<<UDRE0))) { }  // wait for UART Data Register Empty
      UDR0 = *s;  
      s++;
   }
}