Data collection from ADS1298

To collect data from ADS1298 the previous setup will be used.

Data will be formatted. What is received from ADS1298: 3 bytes status + 8 groups of 3 bytes (for each channel).
Because value of each channel is 24-bit it will be manipulated to fit into 32-bit integer value.
Again, you need CLK and SCLK clock (both) to establish communication between RPi and ADS1298.
For plotting purposes first column of data will contain time stamps.

cpp
/* * Code to perform communication with ADS1298 * * ads1_1 - basic communication established. ADS gives an answer to Raspberry Pi B through SPI bus. * ads1.3 - read device signature, reset introduced, basic initial settings, generating test signal and printf of one channel and one value * ads1.4 - preparation for pipeing to continously give one channel value out * * ads2.0 - seperated files, 'manual' control for /CS chip * ads2.1 - output now: saving to file (to allow use with kst2 - fast plotting program) * ads2.2 - time stamps * ads2.3 - volt values instead of numbers to be saved to file * ads2.4 - 8MHz SPI instead 4MHz * --------------------------------------------------------------------------------------- * *************Compile and build instruction for Geany/Raspberry Pi********************** * --------------------------------------------------------------------------------------- * to build: compile each of files seperately(from Geany), next: open terminal, cd to location where * all files live and type: gcc -o newname main.o adsCMD.o -lsbcm2835 * OR: check 'make' command in Geany 'Build'->'Set Build Command' to be something like: * gcc -o "%e" "%e.o" adsCMDfast.o -lbcm2835 Be sure to run it as Shift + F9 * --------------------------------------------------------------------------------------- * * Problems: * */ #include <stdio.h> #include <bcm2835.h> #include <time.h> //for timestamps #include "ads1298.h" #include "adsCMDfast.h" //keeps pin assignment and basic IO operations int main(int argc, char **argv){ char buf[3] = {0,0,0}; char bigbuf[27]; char bigbuf2[27]; int value1, value2, value3, value4, value5, value6, value7, value8; //ch1 clock_t t, clockbegin; double voltvalue1, voltvalue2, voltvalue3, voltvalue4, voltvalue5, voltvalue6, voltvalue7, voltvalue8; //saving to file FILE *pFile; if(!bcm2835_init()){ printf("Oops, bcm2835 not initialised correctly\n"); return 1; } if(!bcm2835_spi_begin()){ //_spi_begin returns 1 if spi_begin does its job with success printf("SPI not initialised correctly (Maybe you are not running as root?)\n"); return 1; } bcm2835_spi_chipSelect(BCM2835_SPI_CS_NONE); //do NOT set any /CS automatically //pins setup: bcm2835_gpio_fsel(LEDPIN, BCM2835_GPIO_FSEL_OUTP); //LED pin output bcm2835_gpio_fsel(RESETPIN, BCM2835_GPIO_FSEL_OUTP); //RESETPIN as output bcm2835_gpio_fsel(STARTPIN, BCM2835_GPIO_FSEL_OUTP); //STARTPIN as output bcm2835_gpio_fsel(CS_PIN, BCM2835_GPIO_FSEL_OUTP); //CS is an output bcm2835_gpio_fsel(DRDYPIN, BCM2835_GPIO_FSEL_INPT); //DRDY input //bcm2835_gpio_set_pud(DRDYPIN, BCM2835_GPIO_PUD_UP); //DRDY pull-up //reset high bcm2835_gpio_write(RESETPIN, HIGH); //START low bcm2835_gpio_write(STARTPIN, LOW); //bit order bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST); //Set CS pin polarity to low (LOW when CS active) //bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, 0); //Set which CS pin to use for next transfers //bcm2835_spi_chipSelect(BCM2835_SPI_CS0); //Set SPI clock speed // BCM2835_SPI_CLOCK_DIVIDER_65536 = 0, ///< 65536 = 262.144us = 3.814697260kHz (total H+L clock period) // BCM2835_SPI_CLOCK_DIVIDER_32768 = 32768, ///< 32768 = 131.072us = 7.629394531kHz // BCM2835_SPI_CLOCK_DIVIDER_16384 = 16384, ///< 16384 = 65.536us = 15.25878906kHz // BCM2835_SPI_CLOCK_DIVIDER_8192 = 8192, ///< 8192 = 32.768us = 30/51757813kHz // BCM2835_SPI_CLOCK_DIVIDER_4096 = 4096, ///< 4096 = 16.384us = 61.03515625kHz // BCM2835_SPI_CLOCK_DIVIDER_2048 = 2048, ///< 2048 = 8.192us = 122.0703125kHz // BCM2835_SPI_CLOCK_DIVIDER_1024 = 1024, ///< 1024 = 4.096us = 244.140625kHz // BCM2835_SPI_CLOCK_DIVIDER_512 = 512, ///< 512 = 2.048us = 488.28125kHz // BCM2835_SPI_CLOCK_DIVIDER_256 = 256, ///< 256 = 1.024us = 976.5625MHz // BCM2835_SPI_CLOCK_DIVIDER_128 = 128, ///< 128 = 512ns = = 1.953125MHz // BCM2835_SPI_CLOCK_DIVIDER_64 = 64, ///< 64 = 256ns = 3.90625MHz // BCM2835_SPI_CLOCK_DIVIDER_32 = 32, ///< 32 = 128ns = 7.8125MHz // BCM2835_SPI_CLOCK_DIVIDER_16 = 16, ///< 16 = 64ns = 15.625MHz // BCM2835_SPI_CLOCK_DIVIDER_8 = 8, ///< 8 = 32ns = 31.25MHz // BCM2835_SPI_CLOCK_DIVIDER_4 = 4, ///< 4 = 16ns = 62.5MHz // BCM2835_SPI_CLOCK_DIVIDER_2 = 2, ///< 2 = 8ns = 125MHz, fastest you can get // BCM2835_SPI_CLOCK_DIVIDER_1 = 1, ///< 1 = 262.144us = 3.814697260kHz, same as 0/65536 bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_32); //Set SPI data mode // BCM2835_SPI_MODE0 = 0, // CPOL = 0, CPHA = 0, Clock idle low, data clocked in on rising edge, output data (change) on falling edge // BCM2835_SPI_MODE1 = 1, // CPOL = 0, CPHA = 1, Clock idle low, data clocked in on falling edge, output data (change) on rising edge // BCM2835_SPI_MODE2 = 2, // CPOL = 1, CPHA = 0, Clock idle high, data clocked in on falling edge, output data (change) on rising edge // BCM2835_SPI_MODE3 = 3, // CPOL = 1, CPHA = 1, Clock idle high, data clocked in on rising, edge output data (change) on falling edge bcm2835_spi_setDataMode(BCM2835_SPI_MODE1); bcm2835_gpio_write(LEDPIN, LOW); //reset the device bcm2835_gpio_write(RESETPIN, LOW); delay(1); bcm2835_gpio_write(RESETPIN, HIGH); delay(150);//wait (0.128s required) buf[0]=(RREG | ID); buf[1]=0; buf[2]=0; cs_select(); bcm2835_spi_transfer(SDATAC); //stop read data continuous mode SDATAC bcm2835_delayMicroseconds(CS_DELAY); cs_deselect(); cs_select(); bcm2835_spi_transfern(buf, 3); bcm2835_delayMicroseconds(CS_DELAY); cs_deselect(); bcm2835_gpio_write(RESETPIN, LOW); delay(1); bcm2835_gpio_write(RESETPIN, HIGH); delay(250); cs_select(); bcm2835_spi_transfer(SDATAC); //SDATAC=0x11 bcm2835_delayMicroseconds(CS_DELAY); cs_deselect(); //send WREG CONFIG3 0xC0 - sets 7th and 6th bit of CONFIG3 (/PD_REFBUF and bit6) to 1 - internal reference adc_wreg(CONFIG3, 0xC0); //wreg = 0x40 | registry -> CONFIG3 = 0x03, 0xC0, so sending 0x43, 0x00, 0xC0 sent ok delay(1); //set device in HR mode and DR=fMOD/1024 //WREG CONFIG1 0x86 sets HR, DR2 and DR1 bits in CONFIG1 registry(Arduino does HR, DR2, DR0, this would be 0x85 -> 1000 0101) //CONFIG1 bit 7 changes HR (when 1) to LowPower (when set to 0) //CONFIG1 setup the data rate in DR[2:0] - //three LSB bits (110 - fMOD/1024 = 500SPS in HR mode and 250SPS in LP mode) // (101 - fMOD/512 = 1kSPS in HR and 500SPS in LP mode) // (100 - fMOD/256 = 2kSPS in HR // (...) // (010 - fMOD/64 = 8kSPS in HR 4kSPS in LP mode) // RESET STATE OF CONFIG1 is 0000 0110 which is: LP mode, fMOD/1024 // modes of fMOD/32 and fMOD/16 makes 16kSPS and 32kSPS, but in resolution of 19-bit and 16-bit (higher bits can be ignored in these cases) //adc_wreg(CONFIG1, 0x86); // 0x40|reg => 0x41 0x00 0x86 --> 1000 0110 => HR mode, 500SPS adc_wreg(CONFIG1, 0x85); //1000 0101 => HR mode, 1kSPS //WREG CONFIG2 0x00 dont set any bits in CONFIG2 registry adc_wreg(CONFIG2, 0x00); // 0x40|reg => 0x42 0x00 0x00 //set all channels to input short //WREG CHnSET 0x01 for(int i=1; i<=8;++i){ adc_wreg(CHnSET + i, 0x01); } //set pin START = 1 bcm2835_gpio_write(STARTPIN, HIGH); //monitor STARTPIN //send RDATAC cs_select(); bcm2835_spi_transfer(RDATAC); //0x10 bcm2835_delayMicroseconds(CS_DELAY); cs_deselect(); //look for DRDY and issue 24+n*24SCLKs while ((bcm2835_gpio_lev(DRDYPIN))==HIGH){ //wait for HIGH on DRDY } cs_select(); bcm2835_spi_transfern(bigbuf, 27); //this would measure noise bcm2835_delayMicroseconds(CS_DELAY); cs_deselect(); bcm2835_gpio_write(STARTPIN, LOW); //monitor STARTPIN and confirm.... ok, present cs_select(); bcm2835_spi_transfer(SDATAC);//stop data bcm2835_delayMicroseconds(CS_DELAY); cs_deselect(); adc_wreg(CONFIG2, 0x00); //for external data collection cs_select(); char tempspibuf[3] = {0,0,0}; tempspibuf[0]=0x41; //write to CONFIG1 tempspibuf[1]=0; tempspibuf[2]=0x85; //value to write bcm2835_spi_transfern(tempspibuf, 3); bcm2835_delayMicroseconds(CS_DELAY); cs_deselect(); //end of settings for higher SPS for(int i=1; i<=8;++i){ adc_wreg(CHnSET + i, 0x10); //Every channel has to be set seperately //x00 --> 0000 0000 = Normal electrode inputs, 6x gain //b 0 001 0 000 => 0x10 normal input, 1x gain } bcm2835_gpio_write(STARTPIN, HIGH); //START signal cs_select(); bcm2835_spi_transfer(RDATAC);//0x10 confirmed bcm2835_delayMicroseconds(CS_DELAY); cs_deselect(); clockbegin=clock(); //start timestamps while(1){ for(int k=0;k<27; k++) bigbuf2[k] = 0; //clear the buffer while (bcm2835_gpio_lev(DRDYPIN)==HIGH){ } t=clock()-clockbegin; double time_stamp = ((double)t)/CLOCKS_PER_SEC; cs_select(); bcm2835_spi_transfern(bigbuf2, 27); bcm2835_delayMicroseconds(CS_DELAY); cs_deselect(); if(bigbuf2[0]==0b11000000){//kind of crc.. always 192 -> 1100 0000 value1 = ((bigbuf2[3] << 24)|(bigbuf2[4] << 16)|(bigbuf2[5]<<8>>8; value2 = ((bigbuf2[6] << 24)|(bigbuf2[7] << 16)|(bigbuf2[8]<<8>>8; value3 = ((bigbuf2[9] << 24)|(bigbuf2[10] << 16)|(bigbuf2[11]<<8>>8; value4 = ((bigbuf2[12] << 24)|(bigbuf2[13] << 16)|(bigbuf2[14]<<8>>8; value5 = ((bigbuf2[15] << 24)|(bigbuf2[16] << 16)|(bigbuf2[17]<<8>>8; value6 = ((bigbuf2[18] << 24)|(bigbuf2[19] << 16)|(bigbuf2[20]<<8>>8; value7 = ((bigbuf2[21] << 24)|(bigbuf2[22] << 16)|(bigbuf2[23]<<8>>8; value8 = ((bigbuf2[24] << 24)|(bigbuf2[25] << 16)|(bigbuf2[26]<<8>>8; //3 seperate bytes into one 32-bit signed integer value } //else printf("f"); voltvalue1 = value1*0.00000029802326; voltvalue2 = value2*0.00000029802326; voltvalue3 = value3*0.00000029802326; voltvalue4 = value4*0.00000029802326; voltvalue5 = value5*0.00000029802326; voltvalue6 = value6*0.00000029802326; voltvalue7 = value7*0.00000029802326; voltvalue8 = value8*0.00000029802326; pFile=fopen("voltdatafast.dat","a"); //open file to append(file is created if it doesn't exist) if(pFile==NULL){ perror("Error opening file"); } else { fprintf(pFile,"%f %f %f %f %f %f %f %f %f\n", time_stamp, voltvalue1, voltvalue2, voltvalue3, voltvalue4, voltvalue5, voltvalue6, voltvalue7, voltvalue8); } fclose(pFile); } cs_select(); bcm2835_spi_transfer(SDATAC); bcm2835_delayMicroseconds(CS_DELAY); cs_deselect(); //Return SPI pins to default input state bcm2835_spi_end(); return 0; }


Check the code before compiling, the code syntax highlighter does some weird stuff sometimes on this webpage.

There is a need to add these additional files (#include ... from beginning of the file), but posting here is tricky, so I have started github project: https://github.com/VikingsCat/ads1298


Comments

  1. Hi. I am fairly new to the ADS1298. May I know why you use 0.00000029802326 to convert the value to voltage? Can you provide a reference for this one?

    ReplyDelete
  2. This value is to translate digital value from ADC (24-bit signed int) to real voltage value. The analog reference voltage is 2.5V here, so if the ADC sees 2.5V on its input, the value representing it will be 7FFFFFh (remember it is signed value, so 2's complementary format). The ADC working in 24-bit depth. The number: 2.5V(reference voltage) divided by 2^23. This represents smallest value could be recognized/quantified by ADC (also named resolution).

    ReplyDelete

Post a Comment

Popular posts from this blog

Hello world with ADS1298

matplotlib and Raspberry Pi 3 - show my 'Hello world!'