Shop OBEX P1 Docs P2 Docs Learn Events
Interfacing with an MAX1617. — Parallax Forums

Interfacing with an MAX1617.

alatnetalatnet Posts: 80
edited 2019-01-24 19:52 in Propeller 1
Trying to interface with a 16-bit 12 channel ADC but im getting no where more or less...
I've been trying with both Arduino and Propeller but i have no clue if when i was soldering the chips to a conversion board of my design caused them to be damaged or not.

Datasheet for the MAX11617: https://datasheets.maximintegrated.com/en/ds/MAX11612-MAX11617.pdf

Here's what I have currently.
When writing the configuration and setup data, it returns with a 4 and i have no clue what that means when just using Full Speed mode (i.e. 400000 on freq).
Don't know what integer i should be using for either Full Speed or High Speed mode for the frequency...
#include <time.h>
#include <unistd.h>

#include <stdio.h>            // Recommended over iostream for saving space
#include <stdlib.h>
#include <propeller.h>        // Propeller-specific functions
#include <i2c.h>
#include "MAX11617.hpp"

#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
#define BYTE_TO_BINARY(byte)  \
  (byte & 0x80 ? '1' : '0'), \
  (byte & 0x40 ? '1' : '0'), \
  (byte & 0x20 ? '1' : '0'), \
  (byte & 0x10 ? '1' : '0'), \
  (byte & 0x08 ? '1' : '0'), \
  (byte & 0x04 ? '1' : '0'), \
  (byte & 0x02 ? '1' : '0'), \
  (byte & 0x01 ? '1' : '0') 

int main(){
  for (int i=0;i<5;i++){
    printf("Waiting... %d\n", i);
    sleep(1);
  }    
    
  printf("Setting up i2c.\n");
  
  I2C_COGDRIVER* i2cDriver = (I2C_COGDRIVER*)malloc(sizeof(I2C_COGDRIVER));
  
  I2C *i2c_dev = i2cOpen(i2cDriver, 28, 29, 40000);
  
  if (!i2c_dev){
    printf("Failed to open i2c.\n");
    free(i2cDriver);
    return 1;
  }    
  
  uint8_t setup[] = {
    (uint8_t)MAX11617::Setup(),
    (uint8_t)MAX11617::Config(
      MAX11617::ConfigBits::UptoChannel,
      MAX11617::ConfigBits::MAX
    ),
    MAX11617::HSMode
  };
  
  int setuperr = i2cWrite(i2c_dev, MAX11617::Addr, setup, 3, 1);
  
  if(!setuperr){
    printf("Could not send setup/config.\n");
    i2cClose(i2c_dev);
    return 1;
  }
  
  printf("Setup Err: %d\n");
  
  printf("Switching to HS Mode.\n");
  i2cClose(i2c_dev); i2c_dev = NULL;
  i2c_dev = i2cOpen(i2cDriver, 28, 29, 3400000);
  
  if (!i2c_dev){
    printf("Failed to open i2c in HS Mode.\n");
    free(i2cDriver);
    return 1;
  } 
  
  printf("Reading Data:\n");
  
  uint8_t buff[2*12];
  
  for (int i=0; i < 2*12; i++) buff[i] = 0;
  
  while (int err = i2cRead(i2c_dev, MAX11617::Addr, buff, 2*12, 1)){
    printf("Err: %d\n", err);
    
    for (int i=0; i < 2*12; i+=2){
      printf("%d: %d - %d - " BYTE_TO_BINARY_PATTERN " - " BYTE_TO_BINARY_PATTERN "\n", (i/2), buff[i], buff[i+1], BYTE_TO_BINARY(buff[i]), BYTE_TO_BINARY(buff[i+1]));
      buff[i] = buff[i+1] = 0;
    }
    
    sleep(1);
  }
  
  i2cClose(i2c_dev);
  
  free(i2cDriver);
  
  return 0;
}
#pragma once
#ifndef MAX11617_H
#define MAX11617_H

namespace MAX11617 {
	//Setup Bits
	namespace SetupBits {
		namespace Clock {
			const bool External = true;
			const bool Internal = false;
		}

		namespace Polar {
			const bool Bipolar = true;
			const bool Unipolar = false;
		}

		namespace Reset {
			const bool NoAction = true;
			const bool ResetConfig = false;
		}

		enum RefVoltage {
			VDD = 0b00000000,            //VDD Voltage Reference, Ref pin - analog input.
			EXT_REF = 0b00100000,        //External Reference, Ref pin - reference input.
			INT_OFF = 0b01000000,        //Internal Reference, Ref pin - analog input, internal reference state - always off.
			INT_ON = 0b01010000,         //Internal Reference, Ref pin - analog input, internal reference state - always on.
			INT_OFF_REFOUT = 0b01100000, //Internal Reference, Ref pin - reference out, internal reference state - always off.
			INT_ON_REFOUT = 0b01110000   //Internal Reference, Ref pin - reference out, internal reference state - always on.
		};
	}

	//config Bits
	namespace ConfigBits {
		namespace SGL_DIF {
			const bool SingleEnded = true;
			const bool Differential = false;
		}

		enum ChannelSelect {
			AIN0 = 0b00000000,
			AIN1 = 0b00000010,
			AIN2 = 0b00000100,
			AIN3 = 0b00000110,
			AIN4 = 0b00001000,
			AIN5 = 0b00001010,
			AIN6 = 0b00001100,
			AIN7 = 0b00001110,
			AIN8 = 0b00010000,
			AIN9 = 0b00010010,
			AIN10 = 0b00010100,
			AIN11 = 0b00010110,
			MAX = 0b00011110
		};

		enum ScanConfig {
			UptoChannel = 0b00000000,
			Convert8x = 0b00100000,
			UpperHalf = 0b01000000,
			ConvertSelected = 0b01100000
		};
	}

	const unsigned char Addr = 0b01101000;
	inline unsigned char Address(bool rw) { return (char)(Addr | rw); }
	
	const unsigned char HSMode = 0b00001000;

	inline unsigned char Setup_Raw(
		bool sel0 = false,
		bool sel1 = false,
		bool sel2 = false,
		bool clk = false,
		bool bip_uni = false,
		bool rst = true
	) { return (unsigned char)(1 << 7 | sel2 << 6 | sel1 << 5 | sel0 << 4 | clk << 3 | bip_uni << 2 | rst << 1 | 0); }

	inline unsigned char Config_Raw(
		bool scan0 = false,
		bool scan1 = false,
		bool cs0 = false,
		bool cs1 = false,
		bool cs2 = false,
		bool cs3 = false,
		bool sgl_dif = true
	) { return (unsigned char)(0 << 7 | scan1 << 6 | scan0 << 5 | cs3 << 4 | cs2 << 3 | cs1 << 2 | cs0 << 1 | sgl_dif); }

	inline unsigned char Setup(
		SetupBits::RefVoltage sel = SetupBits::VDD,
		bool clk = SetupBits::Clock::Internal,
		bool bip_uni = SetupBits::Polar::Unipolar,
		bool rst = SetupBits::Reset::NoAction
	) { return (unsigned char)(1 << 7 | sel | clk << 3 | bip_uni << 2 | rst << 1 | 0); }

	inline unsigned char Config(
		ConfigBits::ScanConfig scan = ConfigBits::UptoChannel,
		ConfigBits::ChannelSelect channel = ConfigBits::AIN0 ,
		bool sgl_dif = ConfigBits::SGL_DIF::SingleEnded
	) { return (unsigned char)(0 << 7 | scan | channel | sgl_dif); }
}

#endif

Comments

  • Tracy AllenTracy Allen Posts: 6,656
    edited 2019-01-24 21:19
    One possible tripping point is that the MAX1161x family uses the clock stretch mechanism, and many i2c drivers do not support that. The return data would be lost. Look to verify the clock stretch (or clock hold) in your C language drivers on either the Prop or the Arduino.

    The chip offers two clocking modes, one using an internal oscillator and clock stretch, and one using external clocking via the scl signal, which does not use clock stretch. The mode is set by the "clk" bit in the setup register. You might try that.

    It is a versatile ADC with lots of modes. BTW, it is 12 bit, not 16 bit.
  • alatnetalatnet Posts: 80
    edited 2019-01-25 01:51
    Welp, tried it with external clock, still no data...
    Getting 0 on both initErr and err, so it should be working but doesnt seem to be getting any data...

    Updated code:
    /**
    * This is the main Blank Simple C++ Project program file.
    */
    
    #include <time.h>
    #include <unistd.h>
    
    #include <stdio.h>            // Recommended over iostream for saving space
    #include <stdlib.h>
    #include <propeller.h>        // Propeller-specific functions
    #include <i2c.h>
    
    #include "MAX11617.hpp"
    
    #define NumChannels 1
    
    #define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
    #define BYTE_TO_BINARY(byte)  \
      (byte & 0x80 ? '1' : '0'), \
      (byte & 0x40 ? '1' : '0'), \
      (byte & 0x20 ? '1' : '0'), \
      (byte & 0x10 ? '1' : '0'), \
      (byte & 0x08 ? '1' : '0'), \
      (byte & 0x04 ? '1' : '0'), \
      (byte & 0x02 ? '1' : '0'), \
      (byte & 0x01 ? '1' : '0') 
    
    int main(){
      for (int i=0;i<5;i++){
        printf("Waiting... %d\n", i);
        sleep(1);
      }    
        
      printf("Setting up i2c.\n");
      
      I2C_COGDRIVER* i2cDriver = (I2C_COGDRIVER*)malloc(sizeof(I2C_COGDRIVER));
      
      I2C *i2c_dev = i2cOpen(i2cDriver, 28, 29, 40000);
      
      if (!i2c_dev){
        printf("Failed to open i2c.\n");
        free(i2cDriver);
        return 1;
      }
      
      printf("Sending setup/config.\n");
      
      uint8_t init[] = {
        (uint8_t)MAX11617::Setup(
          MAX11617::SetupBits::VDD,
          MAX11617::SetupBits::Clock::External
        ),
        (uint8_t)MAX11617::Config(
          MAX11617::ConfigBits::ConvertSelected,
          MAX11617::ConfigBits::AIN0
        )
      };
      
      int initErr = i2cWrite(i2c_dev, MAX11617::Addr, init, 2, 1);
      
      if(initErr){
        printf("Could not send setup/config. - %d\n", initErr);
        i2cClose(i2c_dev);
        return 1;
      }
      
      printf("Setup Err: %d\n", initErr);
      
      printf("Reading Data:\n");
      
      uint8_t buff[2 * NumChannels];
      
      for (int i=0; i < 2 * NumChannels; i++) buff[i] = 0;
      
      int err = i2cRead(i2c_dev, MAX11617::Addr, buff, 2 * NumChannels, 1);
      
      while (!err){
        printf("Err: %d\n", err);
        
        for (int i=0; i < 2 * NumChannels; i+=2){
          printf("%d: %d - %d - " BYTE_TO_BINARY_PATTERN " - " BYTE_TO_BINARY_PATTERN "\n", (i/2), buff[i], buff[i+1], BYTE_TO_BINARY(buff[i]), BYTE_TO_BINARY(buff[i+1]));
          buff[i] = buff[i+1] = 0;
        }
        
        sleep(1);
        
        err = i2cRead(i2c_dev, MAX11617::Addr, buff, 2 * NumChannels, 1);
      }
      
      i2cClose(i2c_dev);
      
      free(i2cDriver);
      
      return 0;
    }
    

    Edit: Smile, forgot pullups...
    Edit2: Yea, im getting nothing... initErr keeps giving me -1...
  • So not even a raspberry pi zero w will detect the MAX11617...
    It detects the 24LC128 that i have but not the MAX11617...
    Im thinking i fried both chips when soldering them to a dip board...
  • I have no idea what the hell happened but it's working correctly now via arduino...
  • ok, got both chips working...
    Might have been my shitty soldering without flux...
    Broke a pin off of the second chip by accident but still works regardless.
Sign In or Register to comment.