Advertisement
CuriousScientist

ADS1256 - Fully working code and demonstration

Oct 24th, 2020
1,572
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 35.37 KB | None | 0 0
  1. /*Information
  2.  * The code is written by Curious Scientist
  3.  * https://curiousscientist.tech
  4.  *
  5.  * Playlist for more ADS1256-related videos
  6.  * https://www.youtube.com/playlist?list=PLaeIi4Gbl1T-RpVNM8uKdiV1G_3t5jCIu
  7.  *
  8.  * If you use the code, please subscribe to my channel
  9.  * https://www.youtube.com/c/CuriousScientist?sub_confirmation=1
  10.  *
  11.  * I also accept donations
  12.  * https://www.paypal.com/donate/?hosted_button_id=53CNKJLRHAYGQ
  13.  *
  14.  * The code belongs to the following video
  15.  * https://youtu.be/rsi9o5PQzwM
  16.  */
  17. //--------------------------------------------------------------------------------
  18. /*
  19. The green board has a RESET pin and the blue does not.
  20. Therefore, for the blue board, the reset function is disabled.
  21.  
  22. BUFEN should be enabled for precise measurement, but in that case, the max input voltage
  23. cannot be higher than AVDD-2 V.
  24. */
  25. //--------------------------------------------------------------------------------
  26. // Pin configuration - STM32F103 [Arduino]: Pins in square brackets [xx] are for Arduino Uno or Nano.
  27. /*
  28. SPI default pins:
  29. MOSI  - PA7[11] // DIN
  30. MISO  - PA6[12] // DOUT
  31. SCK   - PA5[13] // SCLK
  32. SS    - PA4[10] // CS
  33. --------------------
  34. --------------------
  35. MOSI: Master OUT Slave IN -> DIN
  36. MISO: Master IN Slave OUT -> DOUT
  37. --------------------
  38. --------------------
  39. Other pins - You can assign them to any pins
  40. RST   - PA3
  41. DRDY  - PA2 // this is an interrupt pin
  42. PDWN  - +3.3 V
  43. PDWN - PA1 (Alternatively, if you want to switch it)
  44. */
  45. //--------------------------------------------------------------------------------
  46. //Clock rate
  47. /*
  48.     f_CLKIN = 7.68 MHz
  49.     tau = 130.2 ns
  50. */
  51. //--------------------------------------------------------------------------------
  52. //REGISTERS
  53. /*
  54. REG   VAL     USE
  55. 0     54      Status Register, Everything Is Default, Except ACAL and BUFEN
  56. 1     1       Multiplexer Register, AIN0 POS, AIN1 NEG
  57. 2     0       ADCON, Everything is OFF, PGA = 1
  58. 3     99      DataRate = 50 SPS
  59. 4     225     GPIO, Everything Is Default
  60. */
  61. //--------------------------------------------------------------------------------
  62. #include <SPI.h> //SPI communication
  63. //--------------------------------------------------------------------------------
  64. // The setup() function runs once each time the micro-controller starts
  65. void setup()
  66. {
  67.     Serial.begin(115200);  //We will need high datarate, so it should be a high baud rate
  68.   delay(1000);
  69.  
  70.     Serial.println("*ADS1256 Initialization...."); //Some message
  71.     initialize_ADS1256(); //run the initialization function
  72.  
  73.   delay(1000);
  74.     Serial.println("*Initialization finished!"); //Confirmation message
  75.  
  76.     reset_ADS1256(); //Reset the ADS1256
  77.     userDefaultRegisters(); //Set up the default registers
  78.     printInstructions(); //Print the instructions for the commands used in the code
  79.  
  80. }
  81.  
  82. //--------------------------------------------------------------------------------
  83. //Variables
  84. double VREF = 2.50; //Value of V_ref. In case of internal V_ref, it is 2.5 V
  85. double voltage = 0; //Converted RAW bits.
  86. int CS_Value; //we use this to store the value of the bool, since we don't want to directly modify the CS_pin
  87.  
  88. //Pins
  89. const byte CS_pin = PA4;    //goes to CS on ADS1256
  90. const byte DRDY_pin = PA2;  //goes to DRDY on ADS1256
  91. const byte RESET_pin = PA3; //goes to RST on ADS1256
  92. //const byte PDWN_PIN = PA1; //Goes to the PDWN/SYNC/RESET pin (notice, that some boards have different pins!)
  93. //The above pins are described for STM32. For Arduino, you have to use a different pin definition ("PA" is not used in "PA4)
  94.  
  95. //Values for registers
  96. uint8_t registerAddress; //address of the register, both for reading and writing - selects the register
  97. uint8_t registerValueR; //this is used to READ a register
  98. uint8_t registerValueW; //this is used to WRTIE a register
  99. int32_t registerData; //this is used to store the data read from the register (for the AD-conversion)
  100. uint8_t directCommand; //this is used to store the direct command for sending a command to the ADS1256
  101. String ConversionResults; //Stores the result of the AD conversion
  102. String PrintMessage; //this is used to concatenate stuff into before printing it out.
  103.  
  104. //--------------------------------------------------------------------------------
  105.  
  106. void loop()
  107. {
  108.     if (Serial.available() > 0)
  109.     {
  110.         char commandCharacter = Serial.read(); //we use characters (letters) for controlling the switch-case   
  111.  
  112.         switch (commandCharacter) //based on the command character, we decide what to do
  113.         {
  114.         case 'r': //this case is used to READ the value of a register
  115.       //Relevant info on registers: https://youtu.be/wUEx6pEHi2c
  116.             //Ask the user to pick a register //Register map: Table 23 in the Datasheet
  117.             Serial.println("*Which register to read?"); //I put the "*" in front of every text message, so my processing software ignores them
  118.       registerAddress = Serial.parseInt(); //we parse the entered number as an integer and pass it to the registerAddress variable
  119.             //Wait for the input; Example command: "r 1". This will read the register 1 which is the MUX register (they start at 0!)
  120.             while (!Serial.available());
  121.             //Text before the print - string concatenation
  122.       PrintMessage = "*Value of register " + String(registerAddress) + " is " + String(readRegister(registerAddress));
  123.             Serial.println(PrintMessage); //printing the confirmation message
  124.       PrintMessage = ""; //reset the value of the variable    
  125.             break;
  126.  
  127.         case 'w': //this case is used to WRITE the value of a register
  128.             //Ask the user to pick a register
  129.             Serial.println("*Which Register to write?");
  130.             //Wait for the input
  131.             while (!Serial.available());
  132.             registerAddress = Serial.parseInt(); //Store the register in serialData
  133.             //Ask for the value we want to write
  134.             Serial.println("*Which Value to write?");
  135.             //wait for the input;
  136.       //Example command: "w1 1". This will write the value 1 in the MUX register. This will set the AIN0(+) + AIN1(-) as the input.
  137.             while (!Serial.available());
  138.             registerValueW = Serial.parseInt();
  139.  
  140.             //Write the serialData register with the recent input value (Serial.parseInt())
  141.             writeRegister(registerAddress, registerValueW); //The writeRegister() function expects 2 arguments
  142.       delay(500); //wait      
  143.       PrintMessage = "*The value of the register now is: " + String(readRegister(registerAddress));            
  144.             Serial.println(PrintMessage); //printing a confirmation message
  145.             PrintMessage = "";
  146.             break;
  147.        
  148.         case 't': //this case is used to print a message to the serial terminal. Just to test the connection.
  149.  
  150.             Serial.println("*Test message triggered by serial command");
  151.             break;
  152.  
  153.         case 'O': //this case is used to read a single value from the AD converter
  154.  
  155.             readSingle(); //The readSingle() function returns the result of a single conversion.
  156.  
  157.             break;
  158.  
  159.         case 'R': //this does a RESET on the ADS1256
  160.  
  161.             reset_ADS1256(); //the reset_ADS1256() function resets all the register values
  162.  
  163.             break;
  164.  
  165.         case 's': //SDATAC - Stop Read Data Continously
  166.  
  167.             SPI.transfer(B00001111); //Sending a direct code for SDATAC // Figure 33 in datasheet
  168.             break;
  169.  
  170.       case 'p': //Printing the instructions
  171.  
  172.       printInstructions(); //this function prints the commands used to control the ADS1256
  173.       break;
  174.  
  175.      
  176.  
  177.         case 'C': //Single-ended mode cycling
  178.    
  179.             cycleSingleEnded(); //the cycleSingleEnded() function cycles through ALL the 8 single ended channels
  180.       //single ended channels: A0+COM, A1+COM, A2+COM...A7+COM
  181.  
  182.             break;
  183.  
  184.         case 'D': //differential mode cycling          
  185.  
  186.             cycleDifferential(); //the cycleDifferential() function cycles through ALL the 4 differential channels
  187.       //differential channels: A0+A1, A2+A3, A4+A5, A6+A7
  188.             break;
  189.  
  190.     case 'H': //"high-speed" differential mode cycling      
  191.  
  192.       cycleDifferential_HS(); //the cycleDifferential_HS() function cycles through ALL the 4 differential channels
  193.       //differential channels: A0+A1, A2+A3, A4+A5, A6+A7
  194.       break;
  195.  
  196.         case 'd': //direct command - See Table 24 in datasheet
  197.  
  198.             while (!Serial.available());
  199.  
  200.             directCommand = Serial.parseInt();
  201.  
  202.             sendDirectCommand(directCommand); //This function sends a standalone command
  203.  
  204.             Serial.println("*Direct command performed!");
  205.  
  206.             break;
  207.  
  208.  
  209.         case 'A': //Single channel continous reading - MUX is manual, can be single and differential too
  210.  
  211.             readSingleContinuous(); //the readSingleContinuous() continuously returns a single-ended channel's conversion
  212.  
  213.             break;
  214.  
  215.      case 'U'://Set everything back to default
  216.  
  217.       userDefaultRegisters(); //the userDefaultRegisters() function writes the default values
  218.       //The default values are determined by the user, therefore it has to be done in this code
  219.       //This is more like a shortcut for quickly resetting the values to those that you usually use
  220.       break;
  221.         }
  222.     }
  223. }
  224.  
  225. //--------------------------------------------------------------------------------
  226. //Functions
  227.  
  228. //Reading registers
  229. //DIN should receive 2 command bytes
  230. //1st command byte: address of the register (for example MUX: 1 / 01h / 0000 0001)
  231. //2nd command byte: number of bytes to read (0000 0001 - 1 byte)
  232. //delay between the end of the command and the beginning of the shifting out of the data on DOUT is t6 = 50 * tau_CLKIN
  233. // 50 * 130.2 ns = 6510 ns = 6.51 us
  234. //Seems like, according to the SPI analyzer, 5 us delay is sufficient.
  235. //When writing the register, the time between the last clock for RREG command an the first clock of the answer is t = 6.5 us.
  236.  
  237. unsigned long readRegister(uint8_t registerAddress) //Function for READING a selected register
  238. {
  239.   //Relevant video: https://youtu.be/KQ0nWjM-MtI
  240.   while (digitalRead(DRDY_pin)) {} //we "stuck" here until the DRDY changes its state
  241.    
  242.     SPI.beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1));
  243.     //SPI_MODE1 = output edge: rising, data capture: falling; clock polarity: 0, clock phase: 1.
  244.  
  245.     //CS must stay LOW during the entire sequence [Ref: P34, T24]
  246.  
  247.     digitalWrite(CS_pin, LOW); //CS_pin goes LOW
  248.    
  249.     SPI.transfer(0x10 | registerAddress); //0x10 = RREG
  250.  
  251.     SPI.transfer(0x00);
  252.  
  253.     delayMicroseconds(5); //see t6 in the datasheet
  254.  
  255.     registerValueR = SPI.transfer(0xFF);    //0xFF is sent to the ADS1256 which returns us the register value
  256.  
  257.     digitalWrite(CS_pin, HIGH); //CS_pin goes HIGH
  258.     SPI.endTransaction();
  259.  
  260.     return registerValueR; //return the registers value
  261. }
  262.  
  263. void writeRegister(uint8_t registerAddress, uint8_t registerValueW)
  264. {  
  265.   //Relevant video: https://youtu.be/KQ0nWjM-MtI
  266.    while (digitalRead(DRDY_pin)) {} //we "stuck" here until the DRDY changes its state  
  267.  
  268.     SPI.beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1));
  269.     //SPI_MODE1 = output edge: rising, data capture: falling; clock polarity: 0, clock phase: 1.  
  270.  
  271.     //CS must stay LOW during the entire sequence [Ref: P34, T24]
  272.  
  273.   digitalWrite(CS_pin, LOW); //CS_pin goes LOW
  274.  
  275.   delayMicroseconds(5); //see t6 in the datasheet
  276.  
  277.     SPI.transfer(0x50 | registerAddress); // 0x50 = WREG
  278.  
  279.     SPI.transfer(0x00);
  280.  
  281.     SPI.transfer(registerValueW); //we write the value to the above selected register
  282.    
  283.     digitalWrite(CS_pin, HIGH); //CS_pin goes HIGH
  284.     SPI.endTransaction();
  285. }
  286.  
  287. void reset_ADS1256()
  288. {
  289.     SPI.beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); // initialize SPI with  clock, MSB first, SPI Mode1
  290.  
  291.     digitalWrite(CS_pin, LOW); //CS_pin goes LOW
  292.  
  293.     delayMicroseconds(10); //wait
  294.  
  295.     SPI.transfer(0xFE); //Reset
  296.  
  297.     delay(2); //Minimum 0.6 ms required for Reset to finish.
  298.  
  299.     SPI.transfer(0x0F); //Issue SDATAC
  300.  
  301.     delayMicroseconds(100);
  302.  
  303.     digitalWrite(CS_pin, HIGH); //CS_pin goes HIGH
  304.  
  305.     SPI.endTransaction();
  306.  
  307.  Serial.println("*Reset DONE!"); //confirmation message
  308. }
  309.  
  310. void initialize_ADS1256()   //starting up the chip by making the necessary steps. This is in the setup() of the Arduino code.
  311. {
  312.     //Setting up the pins first
  313.     //Chip select
  314.     pinMode(CS_pin, OUTPUT); //Chip select is an output
  315.     digitalWrite(CS_pin, LOW); //Chip select LOW
  316.  
  317.     SPI.begin(); //start SPI (Arduino/STM32 - ADS1256 communication protocol)
  318.   //The STM32-ADS1256 development board uses a different SPI channel (SPI_2)
  319.   //For more info: https://youtu.be/3Rlr0FCffr0
  320.  
  321.     CS_Value = CS_pin; //We store the value of the CS_pin in a variable
  322.  
  323.     //DRDY
  324.     pinMode(DRDY_pin, INPUT); //DRDY is an input
  325.     pinMode(RESET_pin, OUTPUT); //RESET pin is an output
  326.     digitalWrite(RESET_pin, LOW); //RESET is set to low
  327.  
  328.     delay(500); // Wait
  329.  
  330.     digitalWrite(RESET_pin, HIGH); //RESET is set to high
  331.  
  332.     delay(500); // Wait
  333.  
  334. }
  335.  
  336. void readSingle()
  337. {
  338.   //Relevant video: https://youtu.be/4-A8aJ5BzIs
  339.     //Reading a single value   
  340.     registerData = 0; // every time we call this function, this should be 0 in the beginning!
  341.    
  342.     //Wait for DRDY to go LOW
  343.     while (digitalRead(DRDY_pin)) {}
  344.  
  345.     SPI.beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1));
  346.     digitalWrite(CS_pin, LOW); //REF: P34: "CS must stay low during the entire command sequence"
  347.        
  348.     //Issue RDATA (0000 0001) command
  349.     SPI.transfer(B00000001);
  350.  
  351.     //Wait t6 time (~6.51 us) REF: P34, FIG:30.
  352.   delayMicroseconds(10);
  353.   //according to the SPI analyser, the time between DIN and MSB = ~6.833 us
  354.   //SPI.transfer(0x0F) probably also takes some time, therefore less delay is enough.
  355.  
  356.     //step out the data: MSB | mid-byte | LSB,
  357.     //registerData is ZERO
  358.     registerData |= SPI.transfer(0x0F); //MSB comes in, first 8 bit is updated // '|=' compound bitwise OR operator
  359.     registerData <<= 8;                 //MSB gets shifted LEFT by 8 bits
  360.     registerData |= SPI.transfer(0x0F); //MSB | Mid-byte
  361.     registerData <<= 8;                 //MSB | Mid-byte gets shifted LEFT by 8 bits
  362.     registerData |= SPI.transfer(0x0F); //(MSB | Mid-byte) | LSB - final result
  363.     //After this, DRDY should go HIGH automatically    
  364.  
  365.    Serial.println(registerData); //printing the RAW data
  366.    convertToVoltage(registerData); // converting and printing the raw data as well (unit is Volts)    
  367.    
  368.     digitalWrite(CS_pin, HIGH); //We finished the command sequence, so we switch it back to HIGH
  369.     SPI.endTransaction();
  370. }
  371.  
  372. void readSingleContinuous() //Continuously reading 1 single-ended channel (i.e. A0+COM)
  373. {
  374.   //Relevant video: https://youtu.be/4-A8aJ5BzIs
  375.   //Some commands should only be initiated in the beginning of this type of acquisition (RDATAC)
  376.   //Therefore, we run them outside the while() loop.
  377.  
  378.   registerData = 0; // every time we call this function, this should be 0 in the beginning!
  379.  
  380.   SPI.beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1));                                  
  381.     digitalWrite(CS_pin, LOW); //REF: P34: "CS must stay low during the entire command sequence"
  382.  
  383.   //Issue RDATAC (0000 0011) command
  384.   SPI.transfer(B00000011);
  385.   //Wait t6 time (~6.51 us) REF: P34, FIG:30.
  386.   delayMicroseconds(5);
  387.  
  388.     while (Serial.read() != 's') //while the reading is not interrupted by a command from the serial terminal
  389.     {    
  390.         //Reading a single input continuously using the RDATAC
  391.         while (digitalRead(DRDY_pin)) {} //Wait for DRDY to go LOW        
  392.         delayMicroseconds(5);
  393.        
  394.     //step out the data: MSB | mid-byte | LSB,
  395.    
  396.         //registerData is ZERO
  397.     //Previous, we used 0x0F, here we use 0 for the SPI.transfer() argument;
  398.         registerData |= SPI.transfer(0); //MSB comes in, first 8 bit is updated // '|=' compound bitwise OR operator
  399.         registerData <<= 8;                 //MSB gets shifted LEFT by 8 bits
  400.         registerData |= SPI.transfer(0); //MSB | Mid-byte
  401.         registerData <<= 8;                 //MSB | Mid-byte gets shifted LEFT by 8 bits
  402.         registerData |= SPI.transfer(0); //(MSB | Mid-byte) | LSB - final result
  403.         //After this, DRDY should go HIGH automatically        
  404.    
  405.     Serial.println(registerData); //RAW data
  406.     //Temporary
  407.     //convertToVoltage(registerData); //Converted data (units is Volts)
  408.    
  409.     registerData = 0; // every time we call this function, this should be 0 in the beginning!      
  410.     }
  411.  
  412.     digitalWrite(CS_pin, HIGH); //We finished the command sequence, so we switch it back to HIGH
  413.     SPI.endTransaction();  
  414. }
  415.  
  416. void cycleSingleEnded() //Cycling through all (8) single ended channels
  417. {
  418.   //Relevant video: https://youtu.be/GBWJdyjRIdM
  419.  
  420.   int cycle = 1;  
  421.   registerData = 0;
  422.   SPI.beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1));
  423.  
  424.   while (Serial.read() != 's')
  425.   {
  426.     for (cycle = 1; cycle < 9; cycle++)
  427.     {
  428.       //we cycle through all the 8 single-ended channels with the RDATAC
  429.       //INFO:
  430.       //RDATAC = B00000011
  431.       //SYNC = B11111100
  432.       //WAKEUP = B11111111    
  433.       //---------------------------------------------------------------------------------------------
  434.       /*Some comments regarding the cycling:
  435.       When we start the ADS1256, the preconfiguration already sets the MUX to [AIN0+AINCOM].
  436.       When we start the RDATAC (this function), the default MUX ([AIN0+AINCOM]) will be included in the
  437.       cycling which means that the first readout will be the [AIN0+AINCOM]. But, before we read the data
  438.       from the [AIN0+AINCOM], we have to switch to the next register already, then start RDATA. This is
  439.       demonstrated in Figure 19 on Page 21 of the datasheet.
  440.  
  441.       Therefore, in order to get the 8 channels nicely read and formatted, we have to start the cycle
  442.       with the 2nd input of the ADS1256 ([AIN1+AINCOM]) and finish with the first ([AIN0+AINCOM]).
  443.  
  444.          \ CH1 | CH2 CH3 CH4 CH5 CH6 CH7 CH8 \ CH1 | CH2 CH3 ...
  445.  
  446.       The switch-case is between the  two '|' characters
  447.       The output (one line of values) is between the two '\' characters.
  448.       *///-------------------------------------------------------------------------------------------
  449.       //Steps are on Page21
  450.       //Step 1. - Updating MUX      
  451.       while (digitalRead(DRDY_pin)) {} //waiting for DRDY
  452.      
  453.       switch (cycle)
  454.       {
  455.         //Channels are written manually, so we save time on switching the SPI.beginTransaction on and off.
  456.         case 1: //Channel 2          
  457.             digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  458.             SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  459.             SPI.transfer(0x00);
  460.             SPI.transfer(B00011000);  //AIN1+AINCOM          
  461.           break;
  462.  
  463.         case 2: //Channel 3
  464.             digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  465.             SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  466.             SPI.transfer(0x00);
  467.             SPI.transfer(B00101000);  //AIN2+AINCOM            
  468.           break;
  469.  
  470.         case 3: //Channel 4
  471.             digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  472.             SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  473.             SPI.transfer(0x00);
  474.             SPI.transfer(B00111000);  //AIN3+AINCOM            
  475.           break;
  476.  
  477.         case 4: //Channel 5
  478.             digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  479.             SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  480.             SPI.transfer(0x00);
  481.             SPI.transfer(B01001000);  //AIN4+AINCOM
  482.           break;
  483.  
  484.         case 5: //Channel 6
  485.             digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  486.             SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  487.             SPI.transfer(0x00);
  488.             SPI.transfer(B01011000);  //AIN5+AINCOM            
  489.           break;
  490.  
  491.         case 6: //Channel 7
  492.             digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  493.             SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  494.             SPI.transfer(0x00);
  495.             SPI.transfer(B01101000);  //AIN6+AINCOM            
  496.           break;
  497.  
  498.         case 7: //Channel 8
  499.             digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  500.             SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  501.             SPI.transfer(0x00);
  502.             SPI.transfer(B01111000);  //AIN7+AINCOM            
  503.           break;
  504.  
  505.         case 8: //Channel 1
  506.             digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  507.             SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  508.             SPI.transfer(0x00);
  509.             SPI.transfer(B00001000); //AIN0+AINCOM              
  510.           break;
  511.       }
  512.  
  513.       //Step 2.    
  514.  
  515.       //Issue RDATA (0000 0001) command
  516.       SPI.transfer(B11111100); //SYNC
  517.  
  518.       delayMicroseconds(4); //t11 delay 24*tau = 3.125 us //delay should be larger, so we delay by 4 us
  519.      
  520.       SPI.transfer(B11111111); //WAKEUP
  521.  
  522.       //Step 3.
  523.       //Issue RDATA (0000 0001) command
  524.       SPI.transfer(B00000001);
  525.  
  526.       //Wait t6 time (~6.51 us) REF: P34, FIG:30.
  527.       delayMicroseconds(5);
  528.  
  529.       //step out the data: MSB | mid-byte | LSB,
  530.  
  531.       //registerData is ZERO
  532.       registerData |= SPI.transfer(0x0F); //MSB comes in, first 8 bit is updated // '|=' compound bitwise OR operator
  533.       registerData <<= 8;         //MSB gets shifted LEFT by 8 bits
  534.       registerData |= SPI.transfer(0x0F); //MSB | Mid-byte
  535.       registerData <<= 8;         //MSB | Mid-byte gets shifted LEFT by 8 bits
  536.       registerData |= SPI.transfer(0x0F); //(MSB | Mid-byte) | LSB - final result
  537.       //After this, DRDY should go HIGH automatically  
  538.  
  539.       //Constructing an output  
  540.       ConversionResults = ConversionResults + registerData;
  541.       ConversionResults = ConversionResults + "\t";    
  542.       //---------------------      
  543.       registerData = 0;
  544.  
  545.       digitalWrite(CS_pin, HIGH); //We finished the command sequence, so we switch it back to HIGH
  546.          
  547.       //Expected output when using a resistor ladder of 1k resistors and the ~+5V output of the Arduino:
  548.       //Formatting  Channel 1 Channel 2 Channel 3 Channel 4 Channel 5 Channel 6 Channel 7 Channel 8
  549.       /*
  550.       12:41:40.280 -> 4.78714609  4.16558074  3.55143761  2.96154289  2.37305951  1.78396224  1.19539093  0.60204453
  551.       12:41:40.450 -> 4.78708410  4.16603088  3.55298733  2.96177434  2.37242603  1.78440055  1.19551980  0.60218434
  552.       12:41:40.620 -> 4.78826045  4.16563510  3.55332374  2.96192693  2.37245225  1.78419756  1.19552350  0.60213699
  553.       */                    
  554.     }
  555.     Serial.println(ConversionResults);  
  556.     ConversionResults="";
  557.   }
  558.   SPI.endTransaction();
  559. }
  560.  
  561. void cycleDifferential()
  562. {
  563.   //Relevant viodeo: https://youtu.be/GBWJdyjRIdM
  564.  
  565.   int cycle = 1;  
  566.  
  567.   //outside while() loop, we have to switch to the first differential channel ([AIN0+AIN1])
  568.   //writeRegister(1, 1); //B00000001 = 1;  [AIN0+AIN1]
  569.  
  570.   registerData = 0;
  571.  
  572.   SPI.beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); //We start this SPI.beginTransaction once.
  573.  
  574.   digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  575.   SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  576.   SPI.transfer(0x00);
  577.   SPI.transfer(B00000001);  //AIN0+AIN1
  578.   digitalWrite(CS_pin, HIGH);
  579.   SPI.endTransaction();
  580.  
  581.  
  582.   while (Serial.read() != 's')
  583.   {  
  584.     for (cycle = 1; cycle < 5; cycle++)
  585.     {
  586.       //we cycle through all the 4 differential channels with the RDATA
  587.  
  588.       //RDATA = B00000001
  589.       //SYNC = B11111100
  590.       //WAKEUP = B11111111
  591.  
  592.       //Steps are on Page21
  593.       //Step 1. - Updating MUX
  594.      
  595.      
  596.       while (digitalRead(DRDY_pin)) {}
  597.      
  598.       switch (cycle)
  599.       {
  600.       case 1: //Channel 2        
  601.         digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  602.         SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  603.         SPI.transfer(0x00);
  604.         SPI.transfer(B00100011);  //AIN2+AIN3
  605.         break;
  606.  
  607.       case 2: //Channel 3        
  608.         digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  609.         SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  610.         SPI.transfer(0x00);
  611.         SPI.transfer(B01000101); //AIN4+AIN5
  612.         break;
  613.  
  614.       case 3: //Channel 4
  615.         digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  616.         SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  617.         SPI.transfer(0x00);
  618.         SPI.transfer(B01100111); //AIN6+AIN7          
  619.         break;      
  620.  
  621.       case 4: //Channel 1      
  622.         digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  623.         SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  624.         SPI.transfer(0x00);
  625.         SPI.transfer(B00000001); //AIN0+AIN1
  626.         break;
  627.       }            
  628.      
  629.       SPI.transfer(B11111100); //SYNC      
  630.  
  631.       delayMicroseconds(4); //t11 delay 24*tau = 3.125 us //delay should be larger, so we delay by 4 us
  632.  
  633.       SPI.transfer(B11111111); //WAKEUP
  634.  
  635.       //Step 3.
  636.       //Issue RDATA (0000 0001) command      
  637.       SPI.transfer(B00000001);
  638.  
  639.       //Wait t6 time (~6.51 us) REF: P34, FIG:30.
  640.       delayMicroseconds(5);
  641.  
  642.       //step out the data: MSB | mid-byte | LSB,
  643.  
  644.       //registerData is ZERO
  645.       registerData |= SPI.transfer(0x0F); //MSB comes in, first 8 bit is updated // '|=' compound bitwise OR operator
  646.       registerData <<= 8;         //MSB gets shifted LEFT by 8 bits
  647.       registerData |= SPI.transfer(0x0F); //MSB | Mid-byte
  648.       registerData <<= 8;         //MSB | Mid-byte gets shifted LEFT by 8 bits
  649.       registerData |= SPI.transfer(0x0F); //(MSB | Mid-byte) | LSB - final result
  650.       //After this, DRDY should go HIGH automatically  
  651.      
  652.       //Constructing an output  
  653.       ConversionResults = ConversionResults + registerData;
  654.       ConversionResults = ConversionResults + "\t";    
  655.       //---------------------      
  656.       registerData = 0;
  657.       digitalWrite(CS_pin, HIGH); //We finished the command sequence, so we switch it back to HIGH                  
  658.  
  659.       //Expected output when using a resistor ladder of 1k resistors and the ~+5V output of the Arduino:
  660.       //Formatting  Channel 1 Channel 2 Channel 3 Channel 4
  661.       /*
  662.       16:14:23.066 -> 4.79074764  4.16625738  3.55839943  2.96235866  
  663.       16:14:23.136 -> 4.79277801  4.16681241  3.55990862  2.96264190  
  664.       16:14:23.238 -> 4.79327344  4.16698741  3.55968427  2.96277694  
  665.       */
  666.  
  667.     }
  668.     Serial.println(ConversionResults);
  669.     ConversionResults = "";
  670.   }
  671.   SPI.endTransaction();
  672. }
  673.  
  674. void cycleDifferential_HS() //"High-speed" version of the cycleDifferential() function
  675. {  
  676.   //Relevant viodeo: https://youtu.be/GBWJdyjRIdM
  677.  
  678.   int cycle = 1;  
  679.   registerData = 0;
  680.  
  681.   SPI.beginTransaction(SPISettings(1920000, MSBFIRST, SPI_MODE1)); //We start this SPI.beginTransaction once.
  682.  
  683.   //Setting up the input channel
  684.   digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  685.   SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  686.   SPI.transfer(0x00);
  687.   SPI.transfer(B00000001);  //AIN0+AIN1
  688.   digitalWrite(CS_pin, HIGH);
  689.  
  690.   SPI.endTransaction();
  691.  
  692.  
  693.   while (Serial.read() != 's')
  694.   {  
  695.     for(int package = 0; package < 10; package++) //We will collect 10 "packages"
  696.     {      
  697.       for (cycle = 1; cycle < 5; cycle++)
  698.       {
  699.         //we cycle through all the 4 differential channels with the RDATA
  700.  
  701.         //RDATA = B00000001
  702.         //SYNC = B11111100
  703.         //WAKEUP = B11111111
  704.  
  705.         //Steps are on Page21
  706.         //Step 1. - Updating MUX        
  707.        
  708.         while (digitalRead(DRDY_pin)) {} //waiting for DRDY
  709.        
  710.         switch (cycle)
  711.         {
  712.         case 1: //Channel 2        
  713.           digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  714.           SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  715.           SPI.transfer(0x00);
  716.           SPI.transfer(B00100011);  //AIN2+AIN3
  717.           break;
  718.  
  719.         case 2: //Channel 3        
  720.           digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  721.           SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  722.           SPI.transfer(0x00);
  723.           SPI.transfer(B01000101); //AIN4+AIN5
  724.           break;
  725.  
  726.         case 3: //Channel 4
  727.           digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  728.           SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  729.           SPI.transfer(0x00);
  730.           SPI.transfer(B01100111); //AIN6+AIN7          
  731.           break;      
  732.  
  733.         case 4: //Channel 1      
  734.           digitalWrite(CS_pin, LOW); //CS must stay LOW during the entire sequence [Ref: P34, T24]
  735.           SPI.transfer(0x50 | 1); // 0x50 = WREG //1 = MUX
  736.           SPI.transfer(0x00);
  737.           SPI.transfer(B00000001); //AIN0+AIN1
  738.           break;
  739.         }            
  740.        
  741.         SPI.transfer(B11111100); //SYNC      
  742.  
  743.         delayMicroseconds(4); //t11 delay 24*tau = 3.125 us //delay should be larger, so we delay by 4 us
  744.  
  745.         SPI.transfer(B11111111); //WAKEUP
  746.  
  747.         //Step 3.
  748.         //Issue RDATA (0000 0001) command      
  749.         SPI.transfer(B00000001);
  750.  
  751.         //Wait t6 time (~6.51 us) REF: P34, FIG:30.
  752.         delayMicroseconds(5);
  753.  
  754.         //step out the data: MSB | mid-byte | LSB,
  755.  
  756.         //registerData is ZERO
  757.         registerData |= SPI.transfer(0x0F); //MSB comes in, first 8 bit is updated // '|=' compound bitwise OR operator
  758.         registerData <<= 8;         //MSB gets shifted LEFT by 8 bits
  759.         registerData |= SPI.transfer(0x0F); //MSB | Mid-byte
  760.         registerData <<= 8;         //MSB | Mid-byte gets shifted LEFT by 8 bits
  761.         registerData |= SPI.transfer(0x0F); //(MSB | Mid-byte) | LSB - final result
  762.         //After this, DRDY should go HIGH automatically  
  763.        
  764.         //Constructing an output  
  765.         ConversionResults = ConversionResults + registerData;
  766.         if(cycle < 4)
  767.         {      
  768.         ConversionResults = ConversionResults + "\t";    
  769.         }
  770.         else
  771.         {
  772.         ConversionResults = ConversionResults;
  773.         }
  774.         //---------------------      
  775.         registerData = 0;
  776.         digitalWrite(CS_pin, HIGH); //We finished the command sequence, so we switch it back to HIGH                  
  777.  
  778.         //Expected output when using a resistor ladder of 1k resistors and the ~+5V output of the Arduino:
  779.         //Formatting  Channel 1 Channel 2 Channel 3 Channel 4
  780.         /*
  781.         16:14:23.066 -> 4.79074764  4.16625738  3.55839943  2.96235866  
  782.         16:14:23.136 -> 4.79277801  4.16681241  3.55990862  2.96264190  
  783.         16:14:23.238 -> 4.79327344  4.16698741  3.55968427  2.96277694        */
  784.  
  785.       }
  786.     ConversionResults = ConversionResults + '\n'; //Add a linebreak after a line of data (4 columns)
  787.     }
  788.     Serial.print(ConversionResults); //print everything after 10 packages
  789.     ConversionResults = "";
  790.   }
  791.   SPI.endTransaction();
  792. }
  793.  
  794. void sendDirectCommand(uint8_t directCommand)
  795. {
  796.     //Direct commands can be found in the datasheet Page 34, Table 24.
  797.   //Use binary, hex or dec format.
  798.     //Here, we want to use everything EXCEPT: RDATA, RDATAC, SDATAC, RREG, WREG
  799.     //We don't want to involve DRDY here. We just write, but don't read anything.
  800.  
  801.     //Start SPI
  802.     SPI.beginTransaction(SPISettings(1700000, MSBFIRST, SPI_MODE1));
  803.  
  804.     digitalWrite(CS_pin, LOW); //REF: P34: "CS must stay low during the entire command sequence"
  805.  
  806.     delayMicroseconds(5); //t6 - maybe not necessary
  807.  
  808.     SPI.transfer(directCommand); //Send Command
  809.  
  810.     delayMicroseconds(5); //t6 - maybe not necessary
  811.  
  812.     digitalWrite(CS_pin, HIGH); //REF: P34: "CS must stay low during the entire command sequence"
  813.  
  814.     SPI.endTransaction();
  815.  
  816. }
  817.  
  818. void userDefaultRegisters()
  819. {
  820.     // This function is "manually" updating the values of the registers then reads them back.
  821.     // This function should be used in the setup() after performing an initialization-reset process
  822.   // I use the below listed settings for my "startup configuration"
  823.     /*
  824.         REG   VAL     USE
  825.         0     54      Status Register, Everything Is Default, Except ACAL and BUFEN
  826.         1     1       Multiplexer Register, AIN0 POS, AIN1 POS
  827.         2     0       ADCON, Everything is OFF, PGA = 1
  828.         3     99      DataRate = 50 SPS    
  829.     */ 
  830.    
  831.     //We update the 4 registers that we are going to use
  832.  
  833.     delay(500);
  834.  
  835.   writeRegister(0x00, B00110110); //STATUS                      
  836.     delay(200);
  837.     writeRegister(0x01, B00000001); //MUX AIN0+AIN1
  838.     delay(200);
  839.     writeRegister(0x02, B00000000); //ADCON
  840.     delay(200);
  841.     writeRegister(0x03, B01100011); //DRATE - DEC[99] - 50 SPS
  842.     delay(500);
  843.   sendDirectCommand(B11110000); // SELFCAL
  844.     Serial.println("*Register defaults updated!");
  845. }
  846.  
  847. void printInstructions()
  848. {
  849.     //This function should be in the setup() and it shows the commands
  850.  
  851.  PrintMessage = "*Use the following letters to send a command to the device:" + String("\n")
  852.   + "*r - Read a register. Example: 'r1' - reads the register 1" + String("\n")
  853.   + "*w - Write a register. Example: 'w1 8' - changes the value of the 1st register to 8." + String("\n")
  854.   + "*O - Single readout. Example: 'O' - Returns a single value from the ADS1256." + String("\n")
  855.   + "*A - Single, continuous reading with manual MUX setting." + String("\n")
  856.   + "*C - Cycling the ADS1256 Input multiplexer in single-ended mode (8 channels). " + String("\n")
  857.   + "*D - Cycling the ADS1256 Input multiplexer in differential mode (4 channels). " + String("\n")  
  858.   + "*H - Cycling the ADS1256 Input multiplexer in differential mode (4 channels) at high-speed. " + String("\n")  
  859.   + "*R - Reset ADS1256. Example: 'R' - Resets the device, everything is set to default." + String("\n")  
  860.   + "*s - SDATAC: Stop Read Data Continuously." + String("\n")  
  861.   + "*U - User Default Registers."  + String("\n")
  862.   + "*t - triggers a test message."  + String("\n")    
  863.   + "*d - Send direct command.";
  864.  
  865.   Serial.println(PrintMessage);
  866.   PrintMessage = ""; //Reset (empty) variable.
  867. }
  868.  
  869. void convertToVoltage(int32_t registerData)
  870. {
  871.   if (long minus = registerData >> 23 == 1) //if the 24th bit (sign) is 1, the number is negative
  872.     {
  873.       registerData = registerData - 16777216;  //conversion for the negative sign
  874.       //"mirroring" around zero
  875.     }
  876.  
  877.     voltage = ((2*VREF) / 8388608)*registerData; //2.5 = Vref; 8388608 = 2^{23} - 1
  878.  
  879.     //Basically, dividing the positive range with the resolution and multiplying with the bits  
  880.    
  881.     Serial.println(voltage, 8); //print it on serial, 8 decimals    
  882.     voltage = 0; //reset voltage
  883. }
  884.  
  885. //--------------------------------------------------------------------------------
  886. //end of code
  887. //--------------------------------------------------------------------------------
  888. //Good to know things
  889. /*
  890. TAU = 1/f = 1/7.68 MHz = 130.2 ns
  891.  
  892. For a 7.68 MHz ADC clock, the SCLK may not exceed 1.92 MHz.
  893.  
  894. Binary to decimal is read from right to left
  895. 8 bit = 1 byte
  896.  
  897. 0000 0001 = 1 (2^0)
  898. 0000 0011 = 3 (2^0 + 2^1)
  899. 1000 0001 = 129 (2^0 + 2^7)
  900.  
  901. PAGE 34 of the datasheet, Table 24: Command definitions
  902. RREG and WREG require a second command byte plus data.
  903. The ORDER bit in the STATUS register sets the order of the bits within the output data.
  904. CS must stay LOW during the entire sequence.
  905.  
  906. The operator '|' is the bitwise OR operator.
  907. Example:
  908. 0  0  1  1    operand1
  909. 0  1  0  1    operand2
  910. ----------
  911. 0  1  1  1    (operand1 | operand2) - returned result
  912. //---------------------------------------------------
  913.  
  914. DRDY goes LOW when new data is available. - When all the 24 bits have been read back, it goes back to HIGH.
  915.  
  916. The operator '|=' is the compound bitwise operator.
  917.  
  918. OUTPUT CODES //REF Page23 Table16
  919.  
  920. 1: Vin (AIN_P - AIN_N) > (2Vref)/PGA
  921.     7FFFFFh = 8388607 = 0111 1111 1111 1111 1111 1111
  922.  
  923. 2: Vin (AIN_P - AIN_N) < (-2Vref)/PGA *((2^23)/(2^23 -1))
  924.     800000h = 8388608 = 1000 0000 0000 0000 0000 0000
  925. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement