Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 2 1 2 LastLast
Results 1 to 25 of 33

Thread: AD7124 understanding registers how to program them in to the Teensy3.6

  1. #1
    Senior Member
    Join Date
    Sep 2016
    Posts
    128

    AD7124 understanding registers how to program them in to the Teensy3.6

    Hi

    I have a question how to talk to the AD7124-8 based on the Evaluation board CN0391.

    how can I write to the registers? or get info back from the registers?
    I had many similar questions, but going back to the basics is the best at the moment. This is because my project is larger, and i am not getting the right values from the CN0391 evaluation board, even if the Thermocouples are connected or not, which show no errors or fail or what so ever.

    for setting the thermocouples I require to set AD7124-8 specific Registers, Options, Channels, Currents and filters, even Bias and offsets. if someone could please explain me how to decifer the Registers I would be very glad. because the standard libraries aint communicating that well, getting rubbish values like 2.5V or 0.000, or FAIL or other none understandable gibberish.

    the CN0391.ino is no option to use because there is so much going and it isnt allowing my to write any data to the tft screen.

    so resorting to the AD7124 is necessary and implement the code around it.

    I grapped from the AD7124 the full test ino to check if I can read and write any value. but I simply dont know how to do this at best.

    full test code:
    Code:
    /*
      AD7124 Full Test
      Prints out the voltages measured at pins AIN1/AIN, AIN3/AIN2, AIN5/AIN4 and
      AIN7/AIN6. Input voltages must be in the range between 0 and 2.5V.
      This is a complete test program that checks for errors and displays the
      contents of the AD7124 circuit registers.
      For a more accessible example see voltmeter.ino.
      For more on AD7124, see
      http://www.analog.com/media/en/technical-documentation/data-sheets/AD7124-4.pdf
      The circuit:
      - AD7124 connected on the MOSI, MISO, SCK and /SS pins (pin 10)
      - LED active in low state connected to pin 9.
      created 2018
      by epsilonrt https://github.com/epsilonrt
      This example code is in the public domain.
      https://github.com/epsilonrt/ad7124/tree/master/examples
    */
    #include <stdlib.h>
    #include <ad7124.h>
    
    using namespace Ad7124;
    
    // In order not to prefix the constants with Ad7124 :: !
    //using namespace Ad7124;
    
    /* constants ================================================================ */
    const int ledPin = 9;
    const int ssPin = 10;
    
    /* macros =================================================================== */
    // Evaluate assertion macro
    // If the argument expression of this macro with functional form compares equal
    // to zero (i.e., the expression is false), a message is written to the serial
    // device and abort is called, terminating the program execution.
    #define assert(e) ((e) ? (void)0 : __assert(__func__, __LINE__, #e))
    
    /* public variables ========================================================= */
    Ad7124Chip adc;
    
    /* internal public functions ================================================ */
    
    // -----------------------------------------------------------------------------
    // Prints AD7124 register value
    void printreg (int reg) {
      char name[16];
    
      if (Ad7124Register::copyRegisterName (reg, name) > 0) {
        long value = adc.getRegister (reg);
    
        if (value >= 0) {
    
          Serial.print (name);
          Serial.print ("(0x");
          Serial.print (reg, HEX);
          Serial.print (") = 0x");
          Serial.println (value, HEX);
        }
      }
    }
    
    // -----------------------------------------------------------------------------
    // Print assertion function
    // a message is written to the serial device and abort is called, terminating
    // the program execution.
    void __assert (const char *__func, int __lineno, const char *__sexp) {
    
      Serial.print ("Error in ");
      Serial.print (__func);
      Serial.print ("(): line ");
      Serial.print (__lineno);
      Serial.print (", assertion failed: ");
      Serial.print (__sexp);
      Serial.println (", abort !");
      delay (1000); // leave time for the message to appear before aborting
      abort();
    }
    
    // -----------------------------------------------------------------------------
    void setup() {
      int ret;
    
      pinMode (ledPin, OUTPUT);
      digitalWrite (ledPin, 1); // clear the LED
    
      //Initialize serial and wait for port to open:
      Serial.begin (38400);
      while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB port only
      }
    
      // prints title with ending line break
      Serial.println (F ("\nAD7124 Full Test"));
    
      // Initializes the AD7124 device, the pin /CS is pin 10 (/SS)
      ret = adc.begin (ssPin);
      assert (ret == 0);
    
      Serial.println (F ("\nSetting up 4 channels with  4setup"));
      for (uint8_t i = 0; i < 4; i++) {
    
        ret = adc.setConfig (i, RefInternal, Pga1, true);
        assert (ret == 0);
        printreg (Config_0 + i);
    
        ret = adc.setChannel (i, i, (i * 2 + 1), AVSSInput);
        assert (ret == 0);
        printreg (Channel_0 + i);
      }
    
      Serial.println (F ("\nSetting up ADC"));
      ret = adc.setAdcControl (StandbyMode, FullPower, true);
      assert (ret == 0);
      printreg (ADC_Control);
    
      Serial.println (F ("\nCalibration"));
      for (uint8_t i = 0; i < 4; i++) {
    
        printreg (Offset_0 + i);
        printreg (Gain_0 + i);
      }
    
      Serial.println (F ("\nV0\tV1\tV2\tV3"));
    }
    
    // -----------------------------------------------------------------------------
    void loop() {
      int ret;
      long value;
      double voltage;
    
      for (uint8_t i = 0; i < 4; i++) {
    
        digitalWrite (ledPin, 0);
        value = adc.read (i);
        digitalWrite (ledPin, 1);
    
        if (value >= 0) {
    
          voltage = Ad7124Chip::toVoltage (value, 1, 2.5, true);
          Serial.print (voltage, 3);
          Serial.write ('\t');
        }
        else {
    
          Serial.print ("FAIL\t");
        }
      }
      Serial.write ('\n');
    }

    here is the serial monitor output values from the full test code.

    AD7124 Full Test
    >
    >
    >
    > Setting up 4 channels with 4 setup
    >
    > Config0(0x19) = 0x9F0
    >
    > Channel0(0x9) = 0x31
    >
    > Config1(0x1A) = 0x9F0
    >
    > Channel1(0xA) = 0x1071
    >
    > Config2(0x1B) = 0x9F0
    >
    > Channel2(0xB) = 0x20B1
    >
    > Config3(0x1C) = 0x9F0
    >
    > Channel3(0xC) = 0x30F1
    >
    >
    >
    > Setting up ADC
    >
    > (0x1) = 0x1188
    >
    >
    >
    > Calibration
    >
    > Offset0(0x29) = 0x800000
    >
    > Gain0(0x31) = 0x554E8A
    >
    > Offset1(0x2A) = 0x800000
    >
    > Gain1(0x32) = 0x554E8A
    >
    > Offset2(0x2B) = 0x800000
    >
    > Gain2(0x33) = 0x554E8A
    >
    > Offset3(0x2C) = 0x800000
    >
    > Gain3(0x34) = 0x554E8A
    >
    >
    >
    > V0 V1 V2 V3
    >
    > -0.000 -0.000 -0.000 -0.000
    >
    > -0.000 -0.000 -0.000 -0.000
    >
    > -0.000 -0.000 -0.000 -0.000
    >
    > -0.000 -0.000 -0.000 -0.000
    >
    > -0.000 -0.000 -0.000 -0.000
    >
    > -0.000 -0.000 -0.000 -0.000
    >
    > -0.000 -0.000 -0.000 -0.000
    >
    > -0.000 -0.000 -0.000 -0.000
    >
    > -0.000 -0.000 -0.000 -0.000
    >
    > 2.500 -0.000 -0.000 -0.000


    many thanks!
    happy weekend.

  2. #2
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,453
    I am trying to remember which library are you using? One from Analog Devices?
    Or I see others like: https://github.com/epsilonrt/ad7124

    Did the full CN0391 sketch work?

  3. #3
    Senior Member
    Join Date
    Sep 2016
    Posts
    128
    Hi Kurt, the problem with that sketch is that it irregular intervals polls the Chipselect for the AD7124.

  4. #4
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,453
    Sorry, what I mainly was asking is, does whoever's sketch work on the board and gives you proper readings?

    Why I ask that, is that gives some confidence that the hardware is working properly.

    Also again not sure whose library you are using. And if it were me, I think I would then start doing baby steps. with the chip.

    Like try to talk to one or a couple of analog inputs and maybe setup a couple of reference voltages, with a couple of voltage dividers (a couple of resistors) and see if I can talk to those. ...
    Then if you need to change some of the settings of the chip, I would then trying changing one and see if still works...

    If those steps don't work, I would do a quick look over the library to get an idea of how it works with SPI and double check the reference pdf for the chip to check things like, which SPI mode do you need to be in to talk to the chip. This has to do with things like, is the clock inactive when the signal is low or high, and likewise do you read/write the bits on the MOSI/MISO lines when the clock signal changes to go to the other level (leading) or when it comes back to the idle level (trailing). Also how fast can it handle? Does the library set this up and if so how. Some might do it when you do the begin operation and then things may not work with other devices if the other devices set a different mode. Or hopefully the code uses beginTransaction/endTransaction which have this information in it such that when you are talking to that device it is in proper state)....

    Polls the chip select? Not sure what you are saying. Are you saying that their code at different times does talks to their chip and to do so needs to use the SPI buss and therefore Asserts the CS pin during that time?

    Again sorry, I don't have these devices and the like, so won't be much help.

  5. #5
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    574
    +1 for starting with the library here:

    https://github.com/epsilonrt/ad7124

  6. #6
    Senior Member
    Join Date
    Sep 2016
    Posts
    128

    Babysteps continued.

    Sketch works, even with the tft featherwing and AD7124-8 on the same bus. Just switching it with Chipselect.
    Values are printed on the tft screen, but all values turn out to be 0.000

    So my approach is to look at the AD7124 seperately without the tft. Because I know that the code with SPISettings work you provided. Thanks for the help on this.

    The AD7124-driver.cpp provides the possibility to set the SPIMode. And is intelligent. So thatís covered.

    So far I understand they use the same code as in the CN0381 to talk to the thermocouple or a like but the schematics compared to the CN0391 is different. So the configuration for the Channel, Option, reference voltage, Current for the rtd and thermocouple is different. i donít Know if this posses a problem in reading out AIN1 AIN0 from the AD7124.

    What I donít understand is: if running the code like Thermometer or another code provided by the examples from the AD7124-8. How these values are actually written to the AD7124 accordingly,

    and How those values can be read out from the AD7124-8. By SPI as :godknowswhatvalue=SPI.transfer(0); So that I know which register with which value is being accessed.

    I have a logic analyzer /oscilloscope Digilent Analysator The Digital Discovery/tektronix
    I can show you the code. For better understanding.
    But thatís a lot of Data.( Shall I slow the AD7124 with SPI further down to see what the MOSI,MISO is doing. Also the DC and chip select?

    For instance Can I write to the 0x019. I have to set a few parameters but I donít know what this hex value resembles. Config0(0x19) = 0x9F0.

    What does this last part 0x9F0 mean?
    What is being set? Can I readout this value and how do I know it is the right one? If compared with the AD7124 config 0 it shows not the right values, I think.

    Still many thanks for reading you. Are the only one that replied. GitHub, platform and analog devices donít show much interest in this problem. I just want to learn how to communicate to the AD7124. I can always resort to the MAX33185( thermocouple Sensor breakout board). But thatís not What I want.

    Best

    Regards.

    Bastiaan

  7. #7
    Senior Member
    Join Date
    Sep 2016
    Posts
    128

    Do you have experience With this library?

    Hi Jon thanks for your reply.

    Quote Originally Posted by jonr View Post
    +1 for starting with the library here:

    Hi Jon do you have experience with this library?
    I am currently using this library AD7124 from https://github.com/epsilonrt/ad7124

    https://github.com/epsilonrt/ad7124

  8. #8
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,453
    Quote Originally Posted by Bastiaan View Post
    What I don’t understand is: if running the code like Thermometer or another code provided by the examples from the AD7124-8. How these values are actually written to the AD7124 accordingly,

    and How those values can be read out from the AD7124-8. By SPI as :godknowswhatvalue=SPI.transfer(0); So that I know which register with which value is being accessed.
    If you run into issues and there are not some good libraries with support, you often need to resort to read the documents associated with the device.

    So if you look at their pdf: https://www.analog.com/media/en/tech...s/ad7124-8.pdf

    If you look at about page 38 you will start seeing information about the communications: Again assuming you are setup for 4 wire spi (CS, MOSI, MISO, SCK),
    Which talks about mode 3...
    And then talks about how to talk to the registers.

    The first byte: is setup with the bottom 6 bits is the register number, bit 6 is R/W 0=write, 1=Read, Bit 7 must be 0 (1 bits will sit and cycle until it sees a 0 bit)
    If the operation is a read, you then output, probably 0's to the device and look at the results. If write operation you write out the appropriate byte.

    Each of the registers are defined in that PDF, I see a summary table at about page 78. Page 73 shows some sort of flow of how one might read a thermo couple ...

    Beyond that???

  9. #9
    Senior Member
    Join Date
    May 2015
    Location
    USA
    Posts
    574
    I haven't used that library. But here is what I typically do (after carefully checking for hardware issues):

    a) start with the library that looks best. If that doesn't work, then
    b) try other libraries. If that doesn't work, then
    c) roll up sleeves and debug library a) using datasheet info and logic analyzer

  10. #10
    Senior Member
    Join Date
    Sep 2016
    Posts
    128
    Thanks for both replies. I was. And am still afraid oboist this debugging. I read the SPI part from Nick Gammon. And bit wise operators. but I am more confused.

    So technically speaking, so that I understand it.
    SPI.transfer allows me to send and receive data over the MiSo and MOSI lines. If I send 0x19 with the transfer doesnít that just access the register and do nothing? Or should I write for the 7 bits the following: 0100000

    SPI.Transfer(0x05)
    SPI.transfer(11110000) gives me a the ID from the device.
    can I also send words to the device like AINP or does it always have to be binary code? I can transform this chars to binary no problem.

    Iíll try this on Monday very basically, in a new arduino INO file. And see what I will get back during the void Setup.

    Thanks again for all the replies. Have nice weekend!

  11. #11
    Senior Member
    Join Date
    Sep 2016
    Posts
    128
    So i started from scratch to talk to the registers.
    I am not getting there.

    based on the page 38, i have to reset the AD7124 for 64 clk bits, ok. i did this in void setup and then copied the code over the Void loop.




    Code:
    
    
    #include <SPI.h>
    
    //SPI defines
    #define TFT_DC  9
    #define TFT_CS 10
    #define TFT_RST -1
    #define AD7124_CS 8
    #define AD7124_SPEED 5000000 // 2mhz?
    
    
    
    SPISettings settingsAD7124(5000000, MSBFIRST, SPI_MODE3); //Page 38-94 SPI_MODE3 CS LOW
    
    byte AD7124_Comms,
    AD7124_Status,
    AD7124_AdcControl,
    AD7124_AdcControlValue,
    AD7124_Data,
    AD7124_IOControl1,
    AD7124_IOControl2,
    AD7124_ID,
    AD7124_Error,
    AD7124_Error_EN,
    AD7124_MCLKCount,
    AD7124_Ch0,
    AD7124_Ch1,
    AD7124_Ch2;
    
    
    void setup() 
    {
     pinMode(AD7124_CS, OUTPUT);
      pinMode(TFT_CS, OUTPUT);
    
       SPI.begin();
    
         //Initialize serial and wait for port to open:
      Serial.begin (38400);
      while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB port only
      }
    
      // prints title with ending line break
    SPI.beginTransaction(settingsAD7124);
    digitalWrite(AD7124_CS,LOW);
    delay(10); //setting delay 5*10^-6*64clkbits = Reset, a bit more to make sure.
    
    digitalWrite(AD7124_CS,HIGH);
    SPI.endTransaction();
    }
    void loop() {
    SPI.beginTransaction(settingsAD7124);
    digitalWrite(AD7124_CS,HIGH);
    delay(10);
    digitalWrite(AD7124_CS,LOW);
    
    SPI.transfer(0b11000000);
    AD7124_Comms=SPI.transfer(0x00);// Bit7:1 =Write Enable, Bit6=R/Wnot, bit5=0, bit4=0, bit3=0, bit2=0, bit1=0, bit0=0;
    AD7124_Status=SPI.transfer(0x00); //just read out the register
    AD7124_AdcControl=SPI.transfer(0x01); //0b00011111
    AD7124_AdcControlValue=SPI.transfer(0b0001111111111111); //page 80
    AD7124_Data=SPI.transfer(0x02);
    AD7124_IOControl1=SPI.transfer(0x03);
    AD7124_IOControl2=SPI.transfer(0x04);
    AD7124_ID=SPI.transfer(0x05);
    AD7124_Error=SPI.transfer(0x06);
    AD7124_Error_EN=SPI.transfer(0x07);
    AD7124_MCLKCount=SPI.transfer(0x08);
    AD7124_Ch0=SPI.transfer(0x09);
    AD7124_Ch1=SPI.transfer(0x10);
    AD7124_Ch2=SPI.transfer(0x11);
    
    Serial.print(" = readout Register 0x00 Comms = ");
    Serial.println(AD7124_Comms,BIN);
    Serial.print(" = readout Register 0x00 Comms = ");
    Serial.println(AD7124_Status,BIN);
    Serial.print(" = readout Register 0x01 ADC_Control = ");
    Serial.println(AD7124_AdcControl,BIN);
    Serial.print(" = Value after opening the register and Writing to it = ");
    Serial.println(AD7124_AdcControlValue,BIN);
    Serial.print(" = readout Register 0x02 Data = ");
    Serial.println(AD7124_Data,BIN);
    Serial.print(" = readout Register 0x03 IOControl1 = ");
    Serial.println(AD7124_IOControl1,BIN);
    Serial.print(" = readout Register 0x04 IOControl2 = ");
    Serial.println(AD7124_IOControl2,BIN);
    Serial.print(" = readout Register 0x05 ID = ");
    Serial.println(AD7124_ID,BIN);
    Serial.print(" = readout Register 0x06 Error = ");
    Serial.println(AD7124_Error,BIN);
    Serial.print("= readout Register 0x07 Error_EN = ");
    Serial.println(AD7124_Error_EN,BIN);
    Serial.print("= readout Register 0x08 MCLKCount = ");
    Serial.println(AD7124_MCLKCount,BIN);
    Serial.print("= readout Register 0x09 CH0 = ");
    Serial.println(AD7124_Ch0,BIN);
    Serial.print("= readout Register 0x10 Ch1 = ");
    Serial.println(AD7124_Ch1,BIN);
    Serial.print("= readout Register 0x11 Ch2 = ");
    Serial.println(AD7124_Ch2,BIN);
    
    
    delay(1000);
    digitalWrite(AD7124_CS,HIGH);
    SPI.endTransaction();
      // put your main code here, to run repeatedly:
    
    }
    }
    
    
    }
    Serial Monitor Output:
    Code:
    
    = readout Register 0x00 Comms = 0
    
     = readout Register 0x00 Comms = 0
    
     = readout Register 0x01 ADC_Control = 0
    
     = Value after opening the register and Writing to it = 0
    
     = readout Register 0x02 Data = 0
    
     = readout Register 0x03 IOControl1 = 0
    
     = readout Register 0x04 IOControl2 = 0
    
     = readout Register 0x05 ID = 0
    
     = readout Register 0x06 Error = 0
    
    = readout Register 0x07 Error_EN = 0
    
    = readout Register 0x08 MCLKCount = 0
    
    = readout Register 0x09 CH0 = 0
    
    = readout Register 0x10 Ch1 = 0
    
    = readout Register 0x11 Ch2 = 0
    Questions:



    1 AD7124_AdcControlValue=SPI.transfer(0b000111111111 1111); //page 80, //
    large integer implicitly truncated to unsigned type shows up `
    Do i have to write 2x times SPI.transfer(0b00011111), SPI.transfer(111111111)? because it can only read 8 bits because of its buffer? no clue.

    2 how do I write exactly to the device?
    SPI.transfer(0), because this is the starting register?because it always starts at 0x00 and it doesnt care?
    3 Or SPI.transfer(0x00); first and then writing the binary to the AD7124?
    such as the 0b1000000?

    i tried this also at the ADC Control Value, but it returns me 0.

    please help.

  12. #12
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,453
    Sometimes it really helps to look at the compiler warnings. If you have not already done so, I always make sure that compiler has: Show Compiler Warnings set to all...

    Then if you look through the compiling of the code you put in minus the extra }s at end you see
    Code:
    yyy: In function 'void loop()':
    yyy:63: warning: large integer implicitly truncated to unsigned type 
       AD7124_AdcControlValue = SPI.transfer(0b0001111111111111); //page 80
    As SPI.transfer() is an 8 bit operation, it transfer one byte out and one byte in.
    There is a SPI.transfer16()
    That reads and outputs 16 bits, but you have to be careful on things like byte order. The Teensy and the device may have different ideas of the order the bytes should go out.
    So then often code will output it using two SPI.transfer of the bytes in the right order and put the returned bytes back into the right order to give you the 16 bits.

  13. #13
    Senior Member
    Join Date
    Sep 2016
    Posts
    128
    Thanks Kurt, a bit later I discovered 2 that the registers could be set due according the size. So changes to the buffer can be made for the AD7124-4/8 Appropriate registers.

    I talked to Mircea about the library from the CN0391 which is a few levels above the level of the AD7124.cpp. He told me that the original program was quite stripped and was made for the lesser arduino uno processor with less memory space, I learned this the hardway by hooking up the cl3512A calibrator and discovered that the values didnít match the thermocouple behavior on the serial monitor. Everything that is written in Programme can be written directly to memory due to the extensive memory the teensy has to offer.

    Mircea also pointed out that the ADuCM360 is based on the ARM3 processor and it shouldnít be much hassle to change the Communications.cpp SPI,UART, and Communications? On Pages 71,93,151.

    Here are some links for the project:
    https://github.com/analogdevicesinc/...60_demo_cn0391
    https://wiki.analog.com/resources/ev...ns/demo_cn0391

    User guide to the ADuCM360
    https://wiki.analog.com/resources/ev...eval-adicup360

    Porting the software will be a bit of work here are some of the
    functions that require modifications for your platform:
    https://github.com/analogdevicesinc/...cation.cpp#L71
    https://github.com/analogdevicesinc/...cation.cpp#L93
    https://github.com/analogdevicesinc/...ation.cpp#L151
    https://github.com/analogdevicesinc/...ation.cpp#L151
    https://github.com/analogdevicesinc/...ation.cpp#L151


    only those should be changed to let the program work.

    itís quite over my head to write something like this.. I am gradually starting to learn A bit over the SPI registers, which isnít that straightforward as I expected.

    Iíll print out the files and see where I can find comparison in the code compared to the ADuCM360 SPI UART and Communications which I guess is the fifo buffer to SPI read and write which needs to be changed to SPI.settings(Speed, SPIMODE, MSBfirst) definition of the SPI Pins. SPI.transfer(Fifobuffer[i]); Write and read function.

    all kinds of questions pop up:
    what should be connected to what,
    what are the similarities in code, registers UART
    fifo buffer compatibility,
    are there limitations at the ADuCM360 compared to the teensy3.6/4.0/4.1? And visa versa.

    Ok thanks for reading.

    I am excited and Love to hear your opinion about this.
    Last edited by Bastiaan; 08-17-2020 at 07:02 PM.

  14. #14
    Quote Originally Posted by Bastiaan View Post
    based on the page 38, i have to reset the AD7124 for 64 clk bits, ok. i did this in void setup and then copied the code over the Void loop.
    First of all I don't see how you are sending eight bytes worth of 0xff. Second of all when you uses CS you should never ever have to do this.

    According to what I read in the data sheet each transaction transfers a single byte. First there is a write to the communication register and this defines which register will be accessed and if it is a read or write. The second byte is this transfer. Repeat. It does not increment to the next register automatically. Since it appears that it is easily confused (hence the 64 clocks with DIN high reset scheme) you should cycle CS with every transaction. There is also a minimum time between transactions which varies depending on mode. (high-low power)

    This bit of code is trouble:
    Code:
    SPI.beginTransaction(settingsAD7124);
    digitalWrite(AD7124_CS,HIGH);
    delay(10);
    digitalWrite(AD7124_CS,LOW);
    
    SPI.transfer(0b11000000);
    The MSB of the communications register acts like a start bit in a UART. It ignores all data till it sees a zero. Which means that this clocks six bits into the communications register since those leading 1s are ignored. What follows this code is worse.

    You need to create a function to handle reading and writing registers that will handle these details for you. Then call AD7124_write(reg,data) or AD7124_read(reg). Oh, the time from CS low to a clock edge is zero in the data sheet so that delay after asserting CS is wasted time.

  15. #15
    Senior Member
    Join Date
    Sep 2016
    Posts
    128
    UhClem thanks for the reply. As I mentioned I was trying to understand how to communicate with the SPI.transfer. Thanks for pointing that out. I clearly have no idea what I am doing. Analog devices was discussing this in their forum about the AD7124 without code snippet and try and use it( yes it became worse just spurious data on the serial monitor)

    Ok Iíll stick with the CS throw it low during begintransaction. I came across the example in the SPI library from Paul stoffregen, cant something like this not be used?

    writeRegister(0x02, 0x2D);
    writeRegister(0x01, 0x03);
    writeRegister(0x03, 0x02);

    Explain this please: The MSB of the communications register acts like a start bit in a UART. you mean the 0x00 first 0b10000000.
    Ok. I think I got it. Thanks for pointing that out with the delay after CS



    Best B

  16. #16
    Look at the description of the WEN bit of the communications register on page 79.

    You might try something like this:

    Code:
    void AD7124_write(unsigned char reg,unsigned char data)
    {
      digitalWrite(AD7124_CS,LOW);
      SPI.beginTransaction(settingsAD7124);
    
      // Add WEN and R/W bits to register number
      SPI.transfer(0b00000000|(reg&0x3f)); // select register to write to
      SPI.transfer(data);
      SPI.EndTransaction();
      digitalWrite(AD7124_CS,HIGH);
      // delay(something);    optional delay for between transaction spacing
    }
    
    unsigned char AD7124_read(unsigned char reg)
    {
      unsigned char data;
      
      digitalWrite(AD7124_CS,LOW);
      SPI.beginTransaction(settingsAD7124);
    
      SPI.transfer(0b01000000|(reg&0x3f)); // select register to read from
      data = SPI.transfer(0xff);
      SPI.EndTransaction();
      digitalWrite(AD7124_CS,HIGH);
      // delay(something);    optional delay for between transaction spacing
      return data;
    }
    Then try reading register 5 and see if you get the expected device ID/revision number.

  17. #17
    Senior Member
    Join Date
    Sep 2016
    Posts
    128
    Ok ill will try this..

    Please explain.( I think I am getting the hang of it)
    SPI.transfer(0b00000000|(reg&0x3f));
    Or the 0b00000000 is true or reg&? What does this mean register? unsigned Char reg that is passed from one function write to read to the other.

    3 0x3f is 63 I got that but why should it be 63? 11111?
    I read the text in table 65.
    Register address bits. These address bits select which registers of the ADC are being selected during this serial interface communication. See Table 64. so all of them are there to write to SPI. ? Ok... It’s a kind of buffer to check /read there is data? Guess?

    But these registers that are being selected by the ADC are normally accessed by: 0x01 register why is it the otherway around?

    I am missing something:

    Code:
    #include <SPI.h>
    
    //SPI defines
    #define TFT_DC  9
    #define TFT_CS 10
    #define TFT_RST -1
    #define AD7124_CS 8
    #define AD7124_SPEED 5000000 //max speed
    
    
    SPISettings settingsAD7124(5000000, MSBFIRST, SPI_MODE3); //Page 38-94 SPI_MODE3 CS LOW
    unsigned char reg;
    unsigned char reg0=0x3f; // I tried 0x00&0x3f as well and your previous code.
    unsigned char data;
    unsigned char val;
    
    
    void setup() 
    {
     pinMode(AD7124_CS, OUTPUT);
      pinMode(TFT_CS, OUTPUT);
    
       SPI.begin();
    
         //Initialize serial and wait for port to open:
      Serial.begin (38400);
      while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB port only
      }
    
    }
    void loop() 
    {
    AD7124_Write(reg0,data);
    unsigned char val=AD7124_Read(reg);
    Serial.println("val from AD7124");
    Serial.println(val);
    }
    
    void AD7124_Write(unsigned char reg0, unsigned char data)
    {
    digitalWrite(AD7124_CS,LOW);
      SPI.beginTransaction(settingsAD7124);
    
      // Add WEN and R/W bits to register number
      SPI.transfer(0b00000000|(reg0)); // select register to write to
      SPI.transfer(data);
      SPI.endTransaction();
      digitalWrite(AD7124_CS,HIGH);
    
    
    
    }
    
    unsigned char AD7124_Read(unsigned char reg)
    {
      unsigned char data;
      
      digitalWrite(AD7124_CS,LOW);
      SPI.beginTransaction(settingsAD7124);
    
      SPI.transfer(0b01000000|(reg&0x3f)); // select register to read from
      data = SPI.transfer(0xff);
      SPI.endTransaction();
      digitalWrite(AD7124_CS,HIGH);
      delay(10); //   optional delay for between transaction spacing
      return data;
    }

    I tried all three variables 0x00&0x3f 0x3f, reg0x3f all show on the Serial monitor 0. am I defining the Var, data and reg wrongly? because the compiler is asking for it in the functions Write and Read.

    I know those are critical questions/ stupid because I have to assume things, that I simply don’t know.

    Best

    Bastiaan
    Last edited by Bastiaan; 08-18-2020 at 08:03 AM.

  18. #18
    Senior Member
    Join Date
    Sep 2016
    Posts
    128
    So I have to write to the register 0x05 11110000 to get the ID code back correct? please show me what I am doing wrong.

    Code:
    #include <SPI.h>
    
    //SPI defines
    #define TFT_DC  9
    #define TFT_CS 10
    #define TFT_RST -1
    #define AD7124_CS 8
    #define AD7124_SPEED 5000000 //max speed
    
    
    SPISettings settingsAD7124(5000000, MSBFIRST, SPI_MODE3); //Page 38-94 SPI_MODE3 CS LOW
    unsigned char reg;
    unsigned char reg0=0x00&0x3f;
    unsigned char data;
    unsigned char val;
    
    
    void setup() 
    {
     pinMode(AD7124_CS, OUTPUT);
      pinMode(TFT_CS, OUTPUT);
    
       SPI.begin();
    
         //Initialize serial and wait for port to open:
      Serial.begin (38400);
      while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB port only
      }
    
    }
    void loop() 
    {
    AD7124_Write(reg0,data);
    unsigned char val=AD7124_Read(reg);
    Serial.println("val from AD7124");
    Serial.println(val);
    }
    
    void AD7124_Write(unsigned char reg0, unsigned char data)
    {
    digitalWrite(AD7124_CS,LOW);
      SPI.beginTransaction(settingsAD7124);
    
      // Add WEN and R/W bits to register number
      SPI.transfer(0x05&11110000); // select register to write to
      SPI.transfer(data);
      SPI.endTransaction();
      digitalWrite(AD7124_CS,HIGH);
    
    
    
    }
    
    unsigned char AD7124_Read(unsigned char reg)
    {
      unsigned char data;
      
      digitalWrite(AD7124_CS,LOW);
      SPI.beginTransaction(settingsAD7124);
    
      SPI.transfer(0x05&11110000); // select register to read from
      data = SPI.transfer(0xff);
      SPI.endTransaction();
      digitalWrite(AD7124_CS,HIGH);
      delay(1000); //   optional delay for between transaction spacing
      return data;
    }
    Last edited by Bastiaan; 08-18-2020 at 08:32 AM. Reason: 0x05 register

  19. #19
    Senior Member
    Join Date
    Sep 2016
    Posts
    128
    So I have to write to the register 0x05 11110000 to get the ID code back correct? please show me what I am doing wrong.

    Code:
    #include <SPI.h>
    
    //SPI defines
    #define TFT_DC  9
    #define TFT_CS 10
    #define TFT_RST -1
    #define AD7124_CS 8
    #define AD7124_SPEED 5000000 //max speed
    
    
    SPISettings settingsAD7124(5000000, MSBFIRST, SPI_MODE3); //Page 38-94 SPI_MODE3 CS LOW
    unsigned char reg;
    unsigned char reg0=0x00&0x3f;
    unsigned char data;
    unsigned char val;
    
    
    void setup() 
    {
     pinMode(AD7124_CS, OUTPUT);
      pinMode(TFT_CS, OUTPUT);
    
       SPI.begin();
    
         //Initialize serial and wait for port to open:
      Serial.begin (38400);
      while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB port only
      }
    
    }
    void loop() 
    {
    AD7124_Write(reg0,data);
    unsigned char val=AD7124_Read(reg);
    Serial.println("val from AD7124");
    Serial.println(val);
    }
    
    void AD7124_Write(unsigned char reg0, unsigned char data)
    {
    digitalWrite(AD7124_CS,LOW);
      SPI.beginTransaction(settingsAD7124);
    
      // Add WEN and R/W bits to register number
      SPI.transfer(0x05&11110000); // select register to write to
      SPI.transfer(data);
      SPI.endTransaction();
      digitalWrite(AD7124_CS,HIGH);
    
    
    
    }
    
    unsigned char AD7124_Read(unsigned char reg)
    {
      unsigned char data;
      
      digitalWrite(AD7124_CS,LOW);
      SPI.beginTransaction(settingsAD7124);
    
      SPI.transfer(0x05&11110000); // select register to read from
      data = SPI.transfer(0xff);
      SPI.endTransaction();
      digitalWrite(AD7124_CS,HIGH);
      delay(1000); //   optional delay for between transaction spacing
      return data;
    }
    I looked up the code from the AD7124.cpp they do it similar but with no chars but const uint8_t* data, uint8_t len

    I tried that to but I have to define the variables that go into the function. I have defined also the Variable data for the register 0x00 0b10000000, for the register 0x05 0b11110000 to read out the values. all put on the Serial Monitor Zero.

    please advice next steps.
    Last edited by Bastiaan; 08-18-2020 at 08:38 AM. Reason: comparison between AD7124 seen

  20. #20
    The (reg & 0x3f) is there out of pure paranoia to make sure that reg is within range. This is then OR'd with the required values for WEN and R/W which happen to be zeros to write a register. The compiler will optimize that away.

    The read register 5 you first write the value (0x40 | 5) to the communications registers to tell it you want to read register 5. On the next transfer it will put the data from register 5 on the serial data out.

    The next byte sent will go to the communications register.

    I should note that I am not at all certain that the SPI.begin (and end) should be part of each transaction. It may be needed only once. I prefer to program the hardware myself and have little use for library code.

  21. #21
    Senior Member
    Join Date
    Sep 2016
    Posts
    128
    ok Many thanks.

    i tried sending SPI.transfer(0x40|5) i got in return 255 with the code you provided. 11111111

    I think I am going to skip working with the CN0391 evaluation Kit,

    there are to many changes needed from Arduino environment to the Teensy, and I am not that good at programming such an extensive library. second the Progmem needs to be transformed. this is based on the voltage outputs Serial monitor. compared to the voltage from my calibrator CL3512A. I think ill use the MAX31855 and forget about it.

    its to time consuming.

  22. #22
    Quote Originally Posted by Bastiaan View Post
    i tried sending SPI.transfer(0x40|5) i got in return 255 with the code you provided. 11111111
    The 0xff being sent while reading a register is just a place holder. You have to send something in order to generate clocks but it matters little what is sent. Because of the start bit like behaviour of WEN, I just selected 0xff. There is nothing magical about it.

    A return value of 0xff suggests that the target SPI device did not respond and this is just a pullup resistor. Probably because it isn't connected properly. So verify it is connected as you desire and then verify that clocks, data, and CS are making it to the ADC.

    Sometimes it is the hardware.

  23. #23
    Senior Member
    Join Date
    Sep 2016
    Posts
    128
    Thanks for that. I hope I am understanding it but I feel I am falling further in to limbo, the further we write here on the forum. I tried running other similar programs like, ad7124.ino and cn0391.ino to make sure. both talk fluent SPI to the AD7124. So I am guessing I am writing not an order of correct bits to the AD7124. The 0x05 register has 0b00000000 to read out the value for the ID right? Table39

  24. #24
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,453
    Good Morning,

    Taking a look at your code posted in #19, there are many issues...

    Note: for most things uint8_t and unsigned char are probably the same. There could be other processors where that might not be true... Not sure which ones...


    Note: The begin transaction and end transaction are good for each logical operation. Especially if you are using more than one SPI object...

    So in loop you do:
    Code:
    AD7124_Write(reg0, data);
    Where reg0 is initialized to 0 as global: unsigned char reg0 = 0x00 & 0x3f;

    And data is a global that was not assigned anything: unsigned char data;

    So now your write function:
    Code:
    void AD7124_Write(unsigned char reg0, unsigned char data)
    {
    	digitalWrite(AD7124_CS, LOW);
    	SPI.beginTransaction(settingsAD7124);
    
    	// Add WEN and R/W bits to register number
    	SPI.transfer(0x05 & 11110000); // select register to write to
    	SPI.transfer(data);
    	SPI.endTransaction();
    	digitalWrite(AD7124_CS, HIGH);
    }
    You pass in two parameters, reg0 and data. Note: by using these same names as your globals the usage of these variable names within the SCOPE of the function will be to use the local version...
    So you pass in: reg0=0 and data=??? (Probably 0) as we probably zero out all unniatialized variables...

    Note: You don't end up using reg0 in this case anyway... Instead you hack up what the reg to you think hard coded reg 5.... If you wanted to write to reg5 instead you should have passed that one in, like: AD7124_Write(5, data);

    Then there is this line: SPI.transfer(0x05 & 11110000); // select register to write to
    What byte value do you get when you AND a hex value of 5 with a Decimal value of 11110000... = 0
    I assume in your case you meant: (0x05 & 0b11110000)
    But again this will still give you 0...

    Again what you probably want is simple pass in: reg0
    Or if you want it make sure reg is in a valid range: you could do: SPI.transfer(reg0 & 0b00111111);
    As the register number is lower 6 bits and top two bits for writes are 0...

    For Read again you are passing in an unitialized global variable (reg) which is not initialized to anything but again probably 0...
    And again your: SPI.transfer(0x05 & 11110000);
    Should be more like: SPI.transfer((reg & 0b00111111) | 0b01000000); //
    Note: I mostly use hex not binary, so I would typically do: SPI.transfer((reg & 0x3f) | 0x40);

    And in most cases like this I would normally not use globals... SO your above might look more like:
    Code:
    #include <SPI.h>
    
    //SPI defines
    #define TFT_DC  9
    #define TFT_CS 10
    #define TFT_RST -1
    #define AD7124_CS 8
    #define AD7124_SPEED 5000000 //max speed
    
    #define REG 5     // change to wheatever you wish
    #define REG_VAL 0  // dito
    
    SPISettings settingsAD7124(5000000, MSBFIRST, SPI_MODE3); //Page 38-94 SPI_MODE3 CS LOW
    
    
    void setup()
    {
    	pinMode(AD7124_CS, OUTPUT);
    	pinMode(TFT_CS, OUTPUT);
    
    	SPI.begin();
    
    	//Initialize serial and wait for port to open:
    	Serial.begin (38400);
    	while (!Serial) {
    		; // wait for serial port to connect. Needed for native USB port only
    	}
    
    }
    void loop()
    {
    	AD7124_Write(REG, REG_VAL);
    	unsigned char val = AD7124_Read(REG);
    	Serial.println("val from AD7124");
    	Serial.println(val);
    }
    
    void AD7124_Write(unsigned char reg, unsigned char data)
    {
    	digitalWrite(AD7124_CS, LOW);
    	SPI.beginTransaction(settingsAD7124);
    
    	// Add WEN and R/W bits to register number
    	SPI.transfer(reg & 0x3f); // select register to write to
    	SPI.transfer(data);
    	SPI.endTransaction();
    	digitalWrite(AD7124_CS, HIGH);
    
    }
    
    unsigned char AD7124_Read(unsigned char reg)
    {
    	unsigned char data;
    
    	digitalWrite(AD7124_CS, LOW);
    	SPI.beginTransaction(settingsAD7124);
    
    	SPI.transfer((reg & 0x3f) | 0x40); // select register to read from
    	data = SPI.transfer(0xff);
    	SPI.endTransaction();
    	digitalWrite(AD7124_CS, HIGH);
    	delay(1000); //   optional delay for between transaction spacing
    	return data;
    }
    Note: I made changes here on fly so could be issues. but hopefully makes sense.

  25. #25
    Senior Member
    Join Date
    Sep 2016
    Posts
    128
    Thanks Kurt, UHClem for the amount of large tips and tricks. Iíll test it tomorrow for better understanding.

    But I donít think I can change the ADuCM360 CN0391 examples init, read write and Do DMA conversion afterwards as proposed by Mircea, Because I am struggling with simple bits and bytes.

    Later on I have to switch from differential inputs to single and back again to measure the cold junction RTDs for each of the thermocouples. And do a conversion

    Other question so if I declare a variable as a define the expression (char, int long float donít play a role?) I havenít tested it yet.

    Thanks,

    Best

    Bastiaan

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •