├── .gitattributes ├── .gitignore ├── AD1248-Library.ino ├── README.md ├── ads1248.h ├── ads1256.h ├── ads12xx.cpp ├── ads12xx.h └── library.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | AD1248.sdf 2 | AD1248.sln 3 | AD1248.v12.suo 4 | AD1248.vcxproj 5 | AD1248.vcxproj.filters 6 | AD1248.vcxproj.user 7 | ClassDiagram.cd 8 | Visual Micro/.AD1248.vsarduino.h 9 | Visual Micro/.ADS1248-Library.vsarduino.h 10 | Visual Micro/Compile.vmps.xml 11 | Visual Micro/Configuration.Debug.vmps.xml 12 | Visual Micro/Configuration.Release.vmps.xml 13 | Visual Micro/Upload.vmps.xml 14 | AD1248.opensdf -------------------------------------------------------------------------------- /AD1248-Library.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "ads12xx.h" 4 | #include 5 | 6 | /* 7 | Working: Everything working 8 | - START: set HIGH 9 | - RESET: set HIGH 10 | - CLOK: set LOW 11 | 12 | 13 | 14 | */ 15 | 16 | int START = 8; 17 | int CS = 9; 18 | int DRDY = 10; 19 | int _RESET = 7; 20 | 21 | 22 | //Define PT100 Coeffients 23 | static double R0 = 100; 24 | static double A = 0.00390802; 25 | static double B = -0.0000005802; 26 | 27 | //Define Thermocouple Type-K Coeffients 28 | static double a0 = 0.118597600000E+00; 29 | static double a1 = -0.118343200000E-03; 30 | static double a2 = 0.126968600000E+03; 31 | 32 | static double c_i[10]={ 33 | -0.176004136860E-01, 34 | 0.389212049750E-01, 35 | 0.185587700320E-04, 36 | -0.994575928740E-07, 37 | 0.318409457190E-09, 38 | -0.560728448890E-12, 39 | 0.560750590590E-15, 40 | -0.320207200030E-18, 41 | 0.971511471520E-22, 42 | -0.121047212750E-25}; 43 | 44 | 45 | //Define Thermocouple Type-K inverse Coeffients 46 | //Range 0°C to 500°C 47 | static double d_n[10] = { 48 | 0.00E+00, 49 | 2.51E+01, 50 | 7.86E-02, 51 | -2.50E-01, 52 | 8.32E-02, 53 | -1.23E-02, 54 | 9.80E-04, 55 | -4.41E-05, 56 | 1.06E-06, 57 | -1.05E-08}; 58 | 59 | 60 | 61 | //Define which ADC to use in the ads12xx.h file 62 | ads12xx ADS; 63 | 64 | void test_intTemp(void); 65 | void test_intTemp(void); 66 | void test_supVoltage(void); 67 | void test_extrefVoltage(void); 68 | double test_RTD(void); 69 | void test_Thermo(void); 70 | void test_inputRange(void); 71 | 72 | void setup() 73 | { 74 | 75 | Serial.begin(115200); 76 | while (!Serial) { 77 | 78 | } 79 | Serial.println("Serial online"); 80 | //pinMode(20, OUTPUT); 81 | //digitalWrite(20, HIGH); //Force other Chip into CS high 82 | ADS.begin(CS, START, DRDY,_RESET); //initialize ADS as object of the ads12xx class 83 | 84 | ADS.Reset(); 85 | 86 | delay(10); 87 | ADS.SetRegisterValue(OFC0,50); //set calibrated offset register Value 88 | 89 | Serial.println("Commands for testing:"); 90 | Serial.println("'r' to read Register"); 91 | Serial.println("'w' to write Register"); 92 | Serial.println("'R' to get a Conversion Result"); 93 | Serial.println("'x' to SDATAC, 'd' for SDATA"); 94 | Serial.println("'o' to write Pre Predefinde Registers"); 95 | Serial.println("'f' to write a command"); 96 | Serial.println("'c' to select calibration methode"); 97 | Serial.println("'t' to chose test"); 98 | Serial.println("'h' for this help"); 99 | } 100 | 101 | 102 | void loop() { 103 | 104 | if (Serial.available()) { 105 | char cin = Serial.read(); 106 | char check_ser = 'y'; 107 | uint8_t cmd, FSC_0, FSC_1, FSC_2; 108 | uint8_t cin1, OFC_0, OFC_1, OFC_2; 109 | 110 | switch (cin) { 111 | case 'r': 112 | Serial.println("Which Register to read?"); 113 | while (!Serial.available()); 114 | Serial.print("Register Value for: "); 115 | cin1 = Serial.parseInt(); 116 | Serial.println(cin1); 117 | Serial.println(ADS.GetRegisterValue(cin1)); 118 | break; 119 | case 'w': 120 | Serial.println("Which Register to write?"); 121 | while (!Serial.available()); 122 | cin1 = Serial.parseInt(); 123 | Serial.println("Which Value to write?"); 124 | while (!Serial.available()); 125 | ADS.SetRegisterValue(cin1, Serial.parseInt()); 126 | break; 127 | case 'R': 128 | Serial.println("Conversion Result"); 129 | Serial.println(ADS.GetConversion()); 130 | break; 131 | case 'x': 132 | Serial.println("Stop SDATAC"); 133 | ADS.Reset(); 134 | break; 135 | case 'o': 136 | Serial.println("Writing predefind Registers"); 137 | #ifdef ADS1256 138 | ADS.SetRegisterValue(MUX, P_AIN0 | N_AINCOM); 139 | ADS.SetRegisterValue(DRATE, DR_1000); 140 | #endif 141 | #ifdef ADS1248 142 | ADS.SetRegisterValue(SYS0, DOR3_2000 | PGA2_0); 143 | 144 | ADS.SetRegisterValue(IDAC0, DRDY_ONLY | IMAG2_OFF 145 | // | IDAC0_ID 146 | ); 147 | ADS.SetRegisterValue(IDAC1, I1DIR_OFF); 148 | ADS.SetRegisterValue(MUX1, BCS1_1 | MUX_SP2_AIN0 | MUX_SN2_AIN2); 149 | #endif 150 | Serial.println("Writing sucessfull"); 151 | break; 152 | case 'd': 153 | while (check_ser == 'y') { 154 | if (Serial.available()) { 155 | check_ser = Serial.read(); 156 | 157 | } 158 | /* 159 | uint32_t data = ADS.GetConversion(); 160 | int timer1 = micros(); 161 | if (long minus = data >> 23 == 1) { 162 | long data = data - 16777216; 163 | } 164 | Serial.println(data); 165 | */ 166 | test_Thermo(); 167 | 168 | #ifdef ADS1256 169 | // double voltage = (4.9986 / 8388608)*data; 170 | // Serial.println(voltage); 171 | #endif 172 | } 173 | break; 174 | case 'f': 175 | Serial.println("Which command to write"); 176 | while (!Serial.available()); 177 | cmd = Serial.parseInt(); 178 | Serial.print(cmd, HEX); 179 | ADS.SendCMD(cmd); 180 | break; 181 | case 'c': 182 | Serial.println("Which Calibration to run?"); 183 | #ifdef ADS1256 184 | Serial.println("'1' for SELFCAL"); 185 | #endif 186 | #ifdef ADS1248 187 | Serial.println("'1' for SELFOCAL"); 188 | #endif 189 | Serial.println("'2' for SYSOGCAL\n'3' for SYSGCAL"); 190 | while (!Serial.available()); 191 | cmd = Serial.parseInt(); 192 | switch (cmd) 193 | { 194 | #ifdef ADS1256 195 | case 1: 196 | Serial.println("Preforming Self Gain and Offset Callibration"); 197 | ADS.SendCMD(SELFCAL); 198 | delay(5); 199 | Serial.print("OFC0: "); 200 | Serial.println(ADS.GetRegisterValue(OFC0)); 201 | Serial.print("OFC1: "); 202 | Serial.println(ADS.GetRegisterValue(OFC1)); 203 | Serial.print("OFC2: "); 204 | Serial.println(ADS.GetRegisterValue(OFC2)); 205 | Serial.print("FSC0: "); 206 | Serial.println(ADS.GetRegisterValue(FSC0)); 207 | Serial.print("FSC1: "); 208 | Serial.println(ADS.GetRegisterValue(FSC1)); 209 | Serial.print("FSC2: "); 210 | Serial.println(ADS.GetRegisterValue(FSC2)); 211 | break; 212 | #endif 213 | #ifdef ADS1248 214 | case 1: 215 | Serial.println("Preforming Self Offset Callibration"); 216 | ADS.SetRegisterValue(MUX0, MUX_SN2_AIN0 | MUX_SP2_AIN1); 217 | delay(1); 218 | ADS.SendCMD(SELFOCAL); 219 | delay(5); 220 | OFC_0 = ADS.GetRegisterValue(OFC0); 221 | OFC_1 = ADS.GetRegisterValue(OFC1); 222 | OFC_2 = ADS.GetRegisterValue(OFC2); 223 | Serial.print("OFC0 "); 224 | Serial.println(OFC_0); 225 | Serial.print("OFC1: "); 226 | Serial.println(OFC_1); 227 | Serial.print("OFC2: "); 228 | Serial.println(OFC_2); 229 | Serial.print("OFC Value:"); 230 | Serial.println(OFC_0 | OFC_1 <<8 | OFC_2 << 16); 231 | break; 232 | #endif 233 | case 2: 234 | Serial.println("Preforming System Offset Callibration"); 235 | ADS.SetRegisterValue(MUX0, MUX_SN2_AIN0 | MUX_SP2_AIN1); 236 | delay(1); 237 | ADS.SendCMD(SYSOCAL); 238 | delay(5); 239 | OFC_0 = ADS.GetRegisterValue(OFC0); 240 | OFC_1 = ADS.GetRegisterValue(OFC1); 241 | OFC_2 = ADS.GetRegisterValue(OFC2); 242 | Serial.print("OFC1: "); 243 | Serial.println(OFC_0); 244 | Serial.print("OFC1: "); 245 | Serial.println(OFC_1); 246 | Serial.print("OFC2: "); 247 | Serial.println(OFC_2); 248 | Serial.print("OFC Value:"); 249 | Serial.println(OFC_0 | OFC_1 <<8 | OFC_2 << 16); 250 | break; 251 | case 3: 252 | Serial.println("Preforming System Gain Callibration"); 253 | ADS.SetRegisterValue(MUX0, MUX_SN2_AIN3 | MUX_SP2_AIN2); 254 | delay(1); 255 | ADS.SendCMD(SYSGCAL); 256 | delay(5); 257 | FSC_0 = ADS.GetRegisterValue(FSC0); 258 | FSC_1 = ADS.GetRegisterValue(FSC1); 259 | FSC_2 = ADS.GetRegisterValue(FSC2); 260 | Serial.print("FSC0: "); 261 | Serial.println(FSC_0); 262 | Serial.print("FSC1: "); 263 | Serial.println(FSC_1); 264 | Serial.print("FSC2: "); 265 | Serial.println(FSC_2); 266 | Serial.print("FSC Value:"); 267 | Serial.println(FSC_0 | FSC_1 <<8 | FSC_2 << 16); 268 | break; 269 | default: 270 | break; 271 | } 272 | break; 273 | case 'h': 274 | Serial.println("Commands for testing:"); 275 | Serial.println("'r' to read Register"); 276 | Serial.println("'w' to write Register"); 277 | Serial.println("'R' to get a Conversion Result"); 278 | Serial.println("'x' to SDATAC, 'd' for SDATA"); 279 | Serial.println("'o' to write Pre Predefinde Registers"); 280 | Serial.println("'f' to write a command"); 281 | Serial.println("'c' to select calibration methode"); 282 | Serial.println("'t' to chose test"); 283 | Serial.println("'h' for this help"); 284 | break; 285 | #ifdef ADS1248 286 | case 't': 287 | Serial.println("Chose which test to run"); 288 | Serial.println("'1' for Internal Temperature\n'2' for Supply Voltage Measurement\n'3' for External Voltage Reference\n'4' for Voltage Measurement\n'5' for Thermocouple Measurement"); 289 | while (!Serial.available()); 290 | cmd = Serial.parseInt(); 291 | switch (cmd) 292 | { 293 | case 1: 294 | 295 | test_intTemp(); 296 | break; 297 | case 2: 298 | test_supVoltage(); 299 | break; 300 | case 3: 301 | test_extrefVoltage(); 302 | break; 303 | case 4: 304 | test_RTD(); 305 | break; 306 | case 5: 307 | test_Thermo(); 308 | break; 309 | } 310 | 311 | #endif 312 | 313 | default: 314 | break; 315 | } 316 | } 317 | } 318 | 319 | #ifdef ADS1248 320 | 321 | /* 322 | Theses are test functions for the ADS1248 system monitor as well 323 | as some examples for 4-wire and thermocouple measurment (Warning these are not well tested). 324 | 325 | Run them atleast 3 times to get proper values. 326 | 327 | -------------------------------------------------------------- 328 | 329 | This function gets temperature from the internal diode 330 | */ 331 | void test_intTemp(void) { 332 | ADS.SetRegisterValue(MUX1, MUXCAL2_TEMP | VREFCON1_ON | REFSELT1_ON); 333 | Serial.println("Wait for Measurement:"); 334 | delay(1000); 335 | unsigned long temp_val = ADS.GetConversion(); 336 | Serial.println(temp_val, DEC); 337 | double temp_voltage = (2.048 / 8388608)*temp_val; //only 23bit data here. 338 | Serial.println(temp_voltage, DEC); 339 | double temp = ((temp_voltage - 0.118) / (405 * 0.000001)) + 25; //see Datasheet S.30 340 | Serial.print("Internal Temperature is "); 341 | Serial.print(temp); 342 | Serial.println(" Grad Celsius!"); 343 | } 344 | 345 | /* 346 | This function measures the supplied voltages 347 | */ 348 | void test_supVoltage(void) { 349 | ADS.SetRegisterValue(MUX1, MUXCAL2_DVDD | VREFCON1_ON | REFSELT1_ON); 350 | Serial.println("Wait for Measurement:"); 351 | delay(1000); 352 | unsigned long volt_val = ADS.GetConversion(); 353 | Serial.println(volt_val, DEC); 354 | double voltage = (2.048 / 16777216)*volt_val; 355 | voltage *= 4 * 2.048; 356 | Serial.print("DVDD Voltage: "); 357 | Serial.print(voltage); 358 | Serial.println("V"); 359 | 360 | ADS.SetRegisterValue(MUX1, MUXCAL2_AVDD | VREFCON1_ON | REFSELT1_ON); 361 | Serial.println("Wait for Measurement:"); 362 | delay(1000); 363 | unsigned long volt1_val = ADS.GetConversion(); 364 | Serial.println(volt1_val, DEC); 365 | double voltage1 = (2.048 / 16777216)*volt1_val; 366 | voltage1 *= 4 * 2.048; 367 | Serial.print("AVDD Voltage: "); 368 | Serial.print(voltage1); 369 | Serial.println("V"); 370 | } 371 | 372 | /* 373 | This function measures the voltage of the external voltage reference 1 374 | You have to connect the AIN0 to the specific REF0 or REF1 output 375 | */ 376 | void test_extrefVoltage(void) { 377 | ADS.SetRegisterValue(MUX1, REFSELT1_ON | VREFCON1_ON | MUXCAL2_REF0); //ADS Reference on Intern, Internal Reference on, System Montitor on REF1 378 | ADS.SetRegisterValue(IDAC0, IMAG2_1500); // IDAC at 1,5mA current 379 | ADS.SetRegisterValue(IDAC1, I1DIR_AIN0 | I2DIR_OFF); // IDAC1 Currentoutput on AIN0, IDAC2 off 380 | ADS.SetRegisterValue(SYS0, DOR3_5); 381 | 382 | unsigned long volt_val = ADS.GetConversion(); 383 | //Serial.println(volt_val, DEC); 384 | double voltage = (2.048 / (16777216))*volt_val; 385 | voltage *= 4 * 2.048; 386 | Serial.print("External V_Ref: "); 387 | Serial.print(voltage, DEC); 388 | Serial.println("V"); 389 | 390 | 391 | } 392 | 393 | void test_inputRange(){ 394 | ADS.SetRegisterValue(MUX0,MUX_SN2_AIN0 | MUX_SP2_AIN1); 395 | ADS.SetRegisterValue(MUX1, VREFCON1_ON | REFSELT1_ON); 396 | ADS.SetRegisterValue(SYS0, DOR3_20 | PGA2_2); 397 | 398 | uint32_t val = ADS.GetConversion(); 399 | 400 | if (val >> 23 == 1) { 401 | val = ~val- 0xFF000000 + 1; 402 | Serial << millis() << "\t-" << (2.048/8388608)*val << "\t-" << val << endl; 403 | 404 | } 405 | else{ 406 | Serial << millis() << "\t" << (2.048/8388608)*val << "\t" << val << endl; 407 | } 408 | //Serial.println(val, HEX); 409 | 410 | 411 | } 412 | 413 | 414 | 415 | /* 416 | Example for a 4-wire measurement (ex PT100 probe) 417 | See ADS1248 application sheet for the setup 418 | */ 419 | double test_RTD(void) { 420 | double result_temp = 0; 421 | ADS.SetRegisterValue(MUX0, MUX_SP2_AIN0 | MUX_SN2_AIN1); 422 | ADS.SetRegisterValue(MUX1, REFSELT1_REF1 | VREFCON1_ON); //ADS Reference on REF1, Internal Reference on 423 | ADS.SetRegisterValue(IDAC0, IMAG2_1000); // IDAC at 1,5mA current 424 | ADS.SetRegisterValue(IDAC1, I1DIR_IEXT1 |I2DIR_IEXT1); // IDAC Currentsink on AIN1 425 | ADS.SetRegisterValue(SYS0, PGA2_2 | DOR3_20); 426 | 427 | unsigned long val = ADS.GetConversion(); 428 | if (val >> 23 == 1){ 429 | Serial << "Impossible Result, Error: Negative Value" << endl; 430 | 431 | } 432 | else{ 433 | double result_volt = (1.6408/8388608)*(val/2.0); 434 | double result_resistance = result_volt/0.002; // 435 | result_temp = (-R0*A+sqrt(pow(R0*A,2)-4*R0*B*(R0-result_resistance)))/(2*R0*B); 436 | Serial << millis() << "\t" << _FLOAT(result_volt,4) << "\t" << _FLOAT(result_resistance,4) << "\t" << _FLOAT(result_temp,4) << "\t" << val << endl; 437 | } 438 | return result_temp; 439 | } 440 | 441 | /* 442 | Untested function for Thermocouple measurment 443 | */ 444 | void test_Thermo(void) { 445 | double cjc_volt=0; 446 | double tc_volt=0; 447 | double result_temp=0; 448 | double result_volt=0; 449 | unsigned long val=0; 450 | 451 | ADS.SetRegisterValue(MUX0, MUX_SP2_AIN4 | MUX_SN2_AIN5); 452 | ADS.SetRegisterValue(MUX1, REFSELT1_ON | VREFCON1_ON); //ADS Reference on Intern, Internal Reference on 453 | //ADS.SetRegisterValue(VBIAS, VBIAS_5); 454 | ADS.SetRegisterValue(IDAC0, IMAG2_1000); // IDAC at 1,5mA current 455 | ADS.SetRegisterValue(IDAC1, I1DIR_IEXT1 |I2DIR_IEXT1); 456 | ADS.SetRegisterValue(SYS0, PGA2_32 | DOR3_20); 457 | 458 | 459 | val = ADS.GetConversion(); 460 | if (val >> 23 == 1) { 461 | val = ~val- 0xFF000000 + 1; 462 | tc_volt = -(1.813728/7429030)*(val/32.0)*1000; 463 | Serial << millis() << "\t" << _FLOAT(result_volt,4) << "\t-" << val << endl; 464 | 465 | } 466 | else{ 467 | tc_volt = (1.813728/7429030)*(val/32.0)*1000; 468 | Serial << millis() << "\t" << _FLOAT(result_volt,4) << "\t" << val << endl; 469 | } 470 | 471 | /* 472 | double t = test_RTD(); 473 | for(int i=0;i<10;i++){ 474 | cjc_volt += c_i[i]*pow(t,i) + a0*exp(a1*pow((t - a2),2)); 475 | } 476 | result_volt = result_volt+cjc_volt; 477 | 478 | for(int i=0;i<10;i++){ 479 | result_temp += d_n[i]*pow(result_volt,i); 480 | } 481 | Serial << millis() << "\t" << _FLOAT(tc_volt,4) << "\t" << _FLOAT(cjc_volt,4)<<"\t"<< _FLOAT(result_volt,4)<< "\t"<<_FLOAT(result_temp,4)<<"\t" << val << endl; 482 | */ 483 | } 484 | #endif 485 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ADS12xx-Library 2 | Library for connecting the Ti ADS1248 and ADS1256 24bit ADC to the Teensy 3.1 3 | 4 | ## Example 5 | The ADS12xx-Library.ino provides an example on how to implement and test the ads hardware. 6 | 7 | 8 | ## License 9 | The MIT License (MIT) 10 | Copyright (c) 2016 Jonathan Graesser 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in all 20 | copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | -------------------------------------------------------------------------------- /ads1248.h: -------------------------------------------------------------------------------- 1 | #ifndef ads1248_h 2 | #define ads1248_h 3 | 4 | /* For information to the register and settings see manual page (p..) */ 5 | 6 | 7 | /* ADS1248 Register (see p42 for Register Map) */ 8 | 9 | #define MUX0 0x00 //Multiplexer Control Register 0 10 | #define VBIAS 0X01 //Bias Voltage Register 11 | #define MUX1 0x02 //Multiplexer Control REgister 1 12 | #define SYS0 0x03 //System Control Register 0 13 | #define OFC0 0X04 //Offset Calibration Coefficient Register 0 14 | #define OFC1 0x05 //Offset Calibration Coefficient Register 1 15 | #define OFC2 0x06 //Offset Calibration Coefficient Register 2 16 | #define FSC0 0x07 //Full scale Callibration Coefficient Register 0 17 | #define FSC1 0x08 //Full scale Callibration Coefficient Register 1 18 | #define FSC2 0x09 //Full scale Callibration Coefficient REgister 2 19 | #define IDAC0 0x0A //IDAC Control Register 0 20 | #define IDAC1 0x0B //IDAC Control Register 1 21 | #define GPIOCFG 0x0C //GPIO Configuration Register 22 | #define GPIODIR 0x0D //GPIODirection REgister 23 | #define GPIODAT 0x0E //GPIO Data Register 24 | 25 | 26 | /* MUX0 - Multiplexer Control Register 0 (see p43 - bring together with bitwise OR | */ 27 | /* BIT7 - BIT6 - BIT5 - BIT4 - BIT3 - BIT2 - BIT1 - BIT0 */ 28 | /* BCS1 - BCS0 - MUX_SP2 - MUX_SP1 - MUX_SP0 - MUX_SN2 - MUX_SN1 - MUXSN0 */ 29 | #define MUX0_RESET 0x01 // Reset MUX0 Register 30 | /* BCS1:0 These bits select the magnitude of the sensor detect current source */ 31 | #define BCS1_1 B00000000 // 00 Burnout current source off (default) 32 | #define BCS1_2 B01000000 // 01 Burnout current source on 0.5 �A 33 | #define BCS1_3 B10000000 // 10 Burnout current source on 2 �A 34 | #define BCS1_4 B11000000 // 11 Burnout current source on 10 �A 35 | /* MUX_SP2:0 Positive input channel selection bits */ 36 | #define MUX_SP2_AIN0 B00000000 // 000 AIN0 (default) 37 | #define MUX_SP2_AIN1 B00001000 // 001 AIN1 38 | #define MUX_SP2_AIN2 B00010000 // 010 AIN2 39 | #define MUX_SP2_AIN3 B00011000 // 011 AIN3 40 | #define MUX_SP2_AIN4 B00100000 // 100 AIN4 41 | #define MUX_SP2_AIN5 B00101000 // 101 AIN5 42 | #define MUX_SP2_AIN6 B00110000 // 110 AIN6 43 | #define MUX_SP2_AIN7 B00111000 // 111 AIN7 44 | /* MUX_SN2:0 Positive input channel selection bits */ 45 | #define MUX_SN2_AIN0 B00000000 // 000 AIN0 46 | #define MUX_SN2_AIN1 B00000001 // 001 AIN1 (default) 47 | #define MUX_SN2_AIN2 B00000010 // 010 AIN2 48 | #define MUX_SN2_AIN3 B00000011 // 011 AIN3 49 | #define MUX_SN2_AIN4 B00000100 // 100 AIN4 50 | #define MUX_SN2_AIN5 B00000101 // 101 AIN5 51 | #define MUX_SN2_AIN6 B00000110 // 110 AIN6 52 | #define MUX_SN2_AIN7 B00000111 // 111 AIN7 53 | 54 | 55 | /* VBIAS - Bias Voltage Register (see p43 - bring together with bitwise OR | */ 56 | /* BIT7 - BIT6 - BIT5 - BIT4 - BIT3 - BIT2 - BIT1 - BIT0 */ 57 | /* VBIAS7 - VBIAS6 - VBIAS5 - VBIAS4 - VBIAS3 - VBIAS2 - VBIAS1 - VBIAS0 */ 58 | 59 | /* VBIAS These bits apply a bias voltage of midsupply (AVDD + AVSS)/2 to the selected analog input */ 60 | #define VBIAS_RESET 0x00 // Reset VBIAS Register 61 | #define VBIAS_7 B10000000 // AIN7 62 | #define VBIAS_6 B01000000 // AIN6 63 | #define VBIAS_5 B00100000 // AIN5 64 | #define VBIAS_4 B00010000 // AIN4 65 | #define VBIAS_3 B00001000 // AIN3 66 | #define VBIAS_2 B00000100 // AIN2 67 | #define VBIAS_1 B00000010 // AIN1 68 | #define VBIAS_0 B00000001 // AIN0 69 | 70 | 71 | /* MUX1 - Multiplexer Control Register 1 (see p44 - bring together with bitwise OR | */ 72 | /* BIT7 - BIT6 - BIT5 - BIT4 - BIT3 - BIT2 - BIT1 - BIT0 */ 73 | /* CLKSTAT - VREFCON1 - VREFCON0 - REFSELT1 - REFSELT0 - MUXCAL2 - MUXCAL1 - MUXCAL0 */ 74 | #define MUX1_RESET 0x00 // Reset MUX1 Register 75 | /* CLKSTAT This bit is read-only and indicates whether the internal or external oscillator is being used 76 | 0 = internal, 1 = external */ 77 | /* VREFCON1 These bits control the internal voltage reference. These bits allow the reference to be turned on or 78 | off completely, or allow the reference state to follow the state of the device. Note that the internal 79 | reference is required for operation the IDAC functions.*/ 80 | #define VREFCON1_OFF B00000000 // Internal reference is always off (default) 81 | #define VREFCON1_ON B00100000 // Internal reference is always on 82 | #define VREFCON1_PS B01100000 // Internal reference is on when a conversion is in progress 83 | /* REFSELT1:0 These bits select the reference input for the ADC */ 84 | #define REFSELT1_REF0 B00000000 // REF0 input pair selected (default) 85 | #define REFSELT1_REF1 B00001000 // REF1 input pair selected 86 | #define REFSELT1_ON B00010000 // Onboard reference selected 87 | #define REFSELT1_ON_REF0 B00011000 // Onboard reference selected and internally connected to REF0 input pair 88 | /* MUXCAL2:0 These bits are used to select a system monitor. The MUXCAL selection supercedes selections from registers MUX0 and MUX1 */ 89 | #define MUXCAL2_NORMAL B00000000 // Normal operation (default) 90 | #define MUXCAL2_OFFSET B00000001 // Offset measurement 91 | #define MUXCAL2_GAIN B00000010 // Gain measurement 92 | #define MUXCAL2_TEMP B00000011 // Temperature diode 93 | #define MUXCAL2_REF1 B00000100 // External REF1 measurement 94 | #define MUXCAL2_REF0 B00000101 // External REF0 measurement 95 | #define MUXCAL2_AVDD B00000110 // AVDD measurement 96 | #define MUXCAL2_DVDD B00000111 // DVDD measurement 97 | 98 | 99 | /* SYS0 - System Control Register 0 (see p45 - bring together with bitwise OR | */ 100 | /* BIT7 - BIT6 - BIT5 - BIT4 - BIT3 - BIT2 - BIT1 - BIT0 */ 101 | /* 0 - PGA2 - PGA1 - PGA0 - DOR3 - DOR2 - DOR1 - DOR0 */ 102 | /* PGA2:0 These bits determine the gain of the PGA */ 103 | #define PGA2_0 B00000000 // 1 (default) 104 | #define PGA2_2 B00010000 // 2 105 | #define PGA2_4 B00100000 // 4 106 | #define PGA2_8 B00110000 // 8 107 | #define PGA2_16 B01000000 // 16 108 | #define PGA2_32 B01010000 // 32 109 | #define PGA2_64 B01100000 // 64 110 | #define PGA2_128 B01110000 // 128 111 | /* DOR3:0 These bits select the output data rate of the ADC */ 112 | #define DOR3_5 B00000000 // 5SPS (default) 113 | #define DOR3_10 B00000001 // 10SPS 114 | #define DOR3_20 B00000010 // 20SPS 115 | #define DOR3_40 B00000011 // 40SPS 116 | #define DOR3_80 B00000100 // 80SPS 117 | #define DOR3_160 B00000101 // 160SPS 118 | #define DOR3_320 B00000110 // 320SPS 119 | #define DOR3_640 B00000111 // 640SPS 120 | #define DOR3_1000 B00001000 // 1000SPS 121 | #define DOR3_2000 B00001001 // 2000SPS 122 | 123 | 124 | /* IDAC0- IDAC Control Register 0 (see p46 - bring together with bitwise OR | */ 125 | /* BIT7 - BIT6 - BIT5 - BIT4 - BIT3 - BIT2 - BIT1 - BIT0 */ 126 | /* ID3 - ID2 - ID1 - ID0 - DRDY MODE - IMAG2 - IMAG1 - IMAG0 */ 127 | #define IDAC0_ID 144 128 | /* DRDY MODE This bits sets the DOUT/DRDY pin functionality */ 129 | #define DRDY_ONLY B00000000 // Data out only (default) 130 | #define DRDY_BOTH B00001000 // Data out and Data ready functionality 131 | /* IMAG2:0 The ADS1248 have two programmable current source DACs that can be used for sensor excitation. 132 | The IMAG bits control the magnitude of the excitation current. The IDACs require the internal reference to be on. */ 133 | #define IMAG2_OFF B00000000 // off (default) 134 | #define IMAG2_50 B00000001 // 50uA 135 | #define IMAG2_100 B00000010 // 100uA 136 | #define IMAG2_250 B00000011 // 250uA 137 | #define IMAG2_500 B00000100 // 500uA 138 | #define IMAG2_750 B00000101 // 750uA 139 | #define IMAG2_1000 B00000110 // 1000uA 140 | #define IMAG2_1500 B00000111 // 1500uA 141 | 142 | 143 | /* IDAC1- IDAC Control Register 1 (see p47 - bring together with bitwise OR | */ 144 | /* BIT7 - BIT6 - BIT5 - BIT4 - BIT3 - BIT2 - BIT1 - BIT0 */ 145 | /* I1DIR3 - I1DIR2 - I1DIR2 - I1DIR0 - I2DIR3 - I2DIR2 - I2DIR1 - I2DIR0 */ 146 | /* I1DIR3:0 These bits select the output pin for the first current source DAC */ 147 | #define I1DIR_AIN0 B00000000 // AIN0 148 | #define I1DIR_AIN1 B00010000 // AIN1 149 | #define I1DIR_AIN2 B00100000 // AIN2 150 | #define I1DIR_AIN3 B00110000 // AIN3 151 | #define I1DIR_AIN4 B01000000 // AIN4 152 | #define I1DIR_AIN5 B01010000 // AIN5 153 | #define I1DIR_AIN6 B01100000 // AIN6 154 | #define I1DIR_AIN7 B01110000 // AIN7 155 | #define I1DIR_IEXT1 B10000000 // IEXT1 156 | #define I1DIR_IEXT2 B10010000 // IEXT2 157 | #define I1DIR_OFF B11000000 // Disconnected (default) 158 | 159 | /* I2DIR3:0 These bits select the output pin for the second current source DAC */ 160 | #define I2DIR_AIN0 B00000000 // AIN0 161 | #define I2DIR_AIN1 B00000001 // AIN1 162 | #define I2DIR_AIN2 B00000010 // AIN2 163 | #define I2DIR_AIN3 B00000011 // AIN3 164 | #define I2DIR_AIN4 B00000100 // AIN4 165 | #define I2DIR_AIN5 B00000101 // AIN5 166 | #define I2DIR_AIN6 B00000110 // AIN6 167 | #define I2DIR_AIN7 B00000111 // AIN7 168 | #define I2DIR_IEXT1 B00001000 // IEXT1 169 | #define I2DIR_IEXT2 B00001001 // IEXT2 170 | #define I2DIR_OFF B00001100 // Disconnected (default) 171 | 172 | /* GPIOCFG (see p48 - bring together with bitwise OR | */ 173 | /* ... To be continued .. */ 174 | 175 | 176 | 177 | /* SPI COMMAND DEFINITIONS (p49) */ 178 | /*SYSTEM CONTROL */ 179 | #define WAKEUP 0x00 //Exit Sleep Mode 180 | #define SLEEP 0x01 //Enter Sleep Mode 181 | #define SYNC 0x04 //Synchornize the A/D Conversion 182 | #define RESET 0x06 //Reset To Power UP values 183 | #define NOP 0xFF //NO Operation 184 | /*DATA READ*/ 185 | #define RDATA 0x12 //Read data once 186 | #define RDATAC 0x14 //Read data continously 187 | #define SDATAC 0x16 //Stop reading data continously 188 | /*READ REGISTER */ 189 | #define RREG 0x20 //Read From Register 190 | #define WREG 0x40 //Write To Register 191 | /*Calibration */ 192 | #define SYSOCAL 0x60 //System Offset Calibration 193 | #define SYSGCAL 0x61 //System Gain Calibration 194 | #define SELFOCAL 0x62 //Self Offset Calibration 195 | 196 | 197 | #define SPI_SPEED 4000000 198 | #define DRDY_PIN 8 199 | 200 | 201 | 202 | 203 | #endif 204 | -------------------------------------------------------------------------------- /ads1256.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Flydroid/ADS12xx-Library/f8afbb8eb075cc15e3ad1868f3ed6a11ca977628/ads1256.h -------------------------------------------------------------------------------- /ads12xx.cpp: -------------------------------------------------------------------------------- 1 | #include "ads12xx.h" 2 | 3 | volatile int DRDY_state = HIGH; 4 | 5 | // Waits untill DRDY Pin is falling (see Interrupt setup). 6 | // Some commands like WREG, RREG need the DRDY to be low. 7 | bool waitforDRDY() { 8 | int timeout=0; 9 | timeout = millis(); 10 | while (DRDY_state) { 11 | //Serial.println("Wait for DRDY"); 12 | //if(millis()-timeout >10000){ 13 | // return 0; 14 | //} 15 | continue; 16 | } 17 | noInterrupts(); 18 | DRDY_state = HIGH; 19 | interrupts(); 20 | } 21 | 22 | //Interrupt function 23 | void DRDY_Interuppt() { 24 | DRDY_state = LOW; 25 | } 26 | 27 | 28 | // ads12xx setup 29 | ads12xx::ads12xx() {} 30 | 31 | void ads12xx::begin(int CS, int START, int DRDY, int _RESET) { 32 | pinMode(CS, OUTPUT); // set the slaveSelectPin as an output: 33 | digitalWriteFast(CS, HIGH); // CS HIGH = nothing selected 34 | pinMode(DRDY, INPUT); // DRDY read 35 | pinMode(START, OUTPUT); 36 | digitalWriteFast(START, HIGH); 37 | pinMode(RESET, OUTPUT); // set the slaveSelectPin as an output: 38 | digitalWriteFast(RESET, HIGH); 39 | _CS = CS; 40 | _DRDY = DRDY; 41 | delay(500); 42 | SPI.begin(); 43 | 44 | attachInterrupt(digitalPinToInterrupt(_DRDY), DRDY_Interuppt, FALLING); //Interrupt setup for DRDY detection 45 | 46 | delay(500); 47 | 48 | 49 | 50 | } 51 | 52 | 53 | // function to get a 3byte conversion result from the adc 54 | long ads12xx::GetConversion() { 55 | int32_t regData;; 56 | if(waitforDRDY()==0){ // Wait until DRDY is LOW 57 | Serial.println("Wait for DRDY Timeout"); 58 | return 0; 59 | }; 60 | SPI.beginTransaction(SPISettings(SPI_SPEED, MSBFIRST, SPI_MODE1)); 61 | digitalWriteFast(_CS, LOW); //Pull SS Low to Enable Communications with ADS1247 62 | delayMicroseconds(10); // RD: Wait 25ns for ADC12xx to get ready 63 | SPI.transfer(RDATA); //Issue RDATA 64 | delayMicroseconds(10); 65 | regData |= SPI.transfer(NOP); 66 | //delayMicroseconds(10); 67 | regData <<= 8; 68 | regData |= SPI.transfer(NOP); 69 | //delayMicroseconds(10); 70 | regData <<= 8; 71 | regData |= SPI.transfer(NOP); 72 | delayMicroseconds(10); 73 | digitalWriteFast(_CS, HIGH); 74 | SPI.endTransaction(); 75 | 76 | 77 | 78 | 79 | return regData; 80 | } 81 | 82 | 83 | // function to write a register value to the adc 84 | // argumen: adress for the register to write into, value to write 85 | void ads12xx::SetRegisterValue(uint8_t regAdress, uint8_t regValue) { 86 | #ifdef ADS1248 87 | if (regAdress == IDAC0) { 88 | regValue = regValue | IDAC0_ID; // add non 0 non-write register value IDAC0_ID 89 | } 90 | #endif 91 | uint8_t regValuePre = ads12xx::GetRegisterValue(regAdress); 92 | if (regValue != regValuePre) { 93 | //digitalWriteFast(_START, HIGH); 94 | delayMicroseconds(10); 95 | //waitforDRDY(); 96 | SPI.beginTransaction(SPISettings(SPI_SPEED, MSBFIRST, SPI_MODE1)); // initialize SPI with SPI_SPEED, MSB first, SPI Mode1 97 | digitalWriteFast(_CS, LOW); 98 | delayMicroseconds(10); 99 | //SPI.transfer(SDATAC); //Issue SDATAC 100 | delayMicroseconds(10); 101 | SPI.transfer(WREG | regAdress); // send 1st command byte, address of the register 102 | SPI.transfer(0x00); // send 2nd command byte, write only one register 103 | SPI.transfer(regValue); // write data (1 Byte) for the register 104 | delayMicroseconds(10); 105 | digitalWriteFast(_CS, HIGH); 106 | //digitalWriteFast(_START, LOW); 107 | if (regValue != ads12xx::GetRegisterValue(regAdress)) { //Check if write was succesfull 108 | Serial.print("Write to Register 0x"); 109 | Serial.print(regAdress, HEX); 110 | Serial.println(" failed!"); 111 | } 112 | SPI.endTransaction(); 113 | 114 | } 115 | 116 | } 117 | 118 | 119 | //function to read a register value from the adc 120 | //argument: adress for the register to read 121 | unsigned long ads12xx::GetRegisterValue(uint8_t regAdress) { 122 | uint8_t bufr; 123 | //digitalWriteFast(_START, HIGH); 124 | //waitforDRDY(); 125 | SPI.beginTransaction(SPISettings(SPI_SPEED, MSBFIRST, SPI_MODE1)); // initialize SPI with 4Mhz clock, MSB first, SPI Mode0 126 | digitalWriteFast(_CS, LOW); 127 | delayMicroseconds(10); 128 | SPI.transfer(RREG | regAdress); // send 1st command byte, address of the register 129 | SPI.transfer(0x00); // send 2nd command byte, read only one register 130 | delayMicroseconds(10); 131 | bufr = SPI.transfer(NOP); // read data of the register 132 | delayMicroseconds(10); 133 | digitalWriteFast(_CS, HIGH); 134 | //digitalWriteFast(_START, LOW); 135 | SPI.endTransaction(); 136 | return bufr; 137 | } 138 | 139 | /* 140 | Sends a Command to the ADC 141 | Like SELFCAL, GAIN, SYNC, WAKEUP 142 | */ 143 | void ads12xx::SendCMD(uint8_t cmd) { 144 | waitforDRDY(); 145 | SPI.beginTransaction(SPISettings(SPI_SPEED, MSBFIRST, SPI_MODE1)); // initialize SPI with 4Mhz clock, MSB first, SPI Mode0 146 | digitalWriteFast(_CS, LOW); 147 | delayMicroseconds(10); 148 | SPI.transfer(cmd); 149 | delayMicroseconds(10); 150 | digitalWriteFast(_CS, HIGH); 151 | SPI.endTransaction(); 152 | } 153 | 154 | 155 | // function to reset the adc 156 | void ads12xx::Reset() { 157 | SPI.beginTransaction(SPISettings(SPI_SPEED, MSBFIRST, SPI_MODE1)); // initialize SPI with clock, MSB first, SPI Mode1 158 | digitalWriteFast(_CS, LOW); 159 | delayMicroseconds(10); 160 | SPI.transfer(RESET); //Reset 161 | delay(2); //Minimum 0.6ms required for Reset to finish. 162 | SPI.transfer(SDATAC); //Issue SDATAC 163 | delayMicroseconds(100); 164 | digitalWriteFast(_CS, HIGH); 165 | SPI.endTransaction(); 166 | } 167 | 168 | -------------------------------------------------------------------------------- /ads12xx.h: -------------------------------------------------------------------------------- 1 | #ifndef ads12xx_H 2 | #define ads12xx_H 3 | 4 | #define ADS1248 5 | //#define ADS1256 6 | 7 | /*Serial Template */ 8 | 9 | #ifdef ADS1248 10 | #include "ads1248.h" 11 | #endif // ADS1248 12 | 13 | #ifdef ADS1256 14 | #include "ads1256.h" 15 | #endif // ADS1256 16 | 17 | #include "SPI.h" 18 | class ads12xx { 19 | public: 20 | ads12xx(); 21 | void begin( 22 | int CS, 23 | int START, 24 | int DRDY, 25 | int _RESET 26 | ); 27 | 28 | void Reset( 29 | 30 | ); 31 | 32 | unsigned long GetRegisterValue( 33 | uint8_t regAdress 34 | ); 35 | 36 | void SendCMD( 37 | uint8_t cmd 38 | ); 39 | 40 | void SetRegisterValue( 41 | uint8_t regAdress, 42 | uint8_t regValue 43 | ); 44 | 45 | struct regValues_t 46 | { 47 | #ifdef ADS1248 48 | uint8_t MUX0_val; 49 | uint8_t VBIAS_val; 50 | uint8_t MUX1_val; 51 | uint8_t SYS0_val; 52 | uint8_t IDAC0_val; 53 | uint8_t IDAC1_val; 54 | #endif // ADS1248 55 | #ifdef ADS1256 56 | uint8_t STATUS_val = STATUS_RESET; 57 | uint8_t MUX_val = MUX_RESET; 58 | uint8_t ADCON_val = ADCON_RESET; 59 | uint8_t DRATE_val = DRATE_RESET; 60 | uint8_t IO_val = IO_RESET; 61 | #endif // ADS1256 62 | }; 63 | 64 | 65 | long GetConversion( 66 | ); 67 | private: 68 | int _CS; 69 | int _DRDY; 70 | int _START; 71 | volatile int DRDY_state; 72 | }; 73 | #endif 74 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ADS12-xx-Library", 3 | "keywords": "ADC, ADS1248, ADS1245, ADS", 4 | "description": "Library for the TI ADS1248 and ADS1256 24bit ADC", 5 | "homepage": "https://github.com/Flydroid/ADS12xx-Library", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/Flydroid/ADS12xx-Library.git" 9 | }, 10 | "authors": { 11 | "name": "flydroid", 12 | "email": "jograesser@gmail.com" 13 | }, 14 | "frameworks": "arduino", 15 | "platforms": "*" 16 | } 17 | --------------------------------------------------------------------------------