This specific update is going to be brief, but it’s to discuss the mild learning curve that’s required to implement sensitive devices in an electrically noisy environment. It turns out that both Silvia’s pump, as well as the three-way solenoid valve generate a significant amount of inductive noise when they’re switched on or off. So much so that it’s sufficient to overload the SPI bus between the Arduino and the ADS1247. The ADS1247 has inherent 50/60Hz filtering – but the SPI bus does not. With my initial testing, every time I energized the pump or solenoid valve, the ADS1247 would effectively go “dead” due to communication problems. It would require a complete power cycle of the setup to restore the system.
In my original design, I had the slave-select (SS) line of the ADS1247 tied permanently to ground as it’s the only device on the bus and will always serve as a slave. But it turns out, this pin can also be used pull the SPI bus into a high-impedance mode that effectively resets the SPI bus (but not the rest of the ADS1247) and effectively makes it “deaf” to this inductive noise. I tied this pin to the Arduino’s SS line (pin 10) and have now implemented toggling of the SS line in the code. According to the Atmega328P datasheet, the SS line can be safely used as a GPIO without forcing the Atmega328P into slave mode as long as it’s set to output and never to input. Note that the code accesses the registers directly. Since I’ve made this change, I’ve not had a single problem.
Note that the code accesses the registers directly. For anyone using this code, make sure to pull SS low when you want to communicate with the ADS1247 and high once you’re done. Out of good practice, you should also write a NOP (0xFF) to the device before pulling the SS high – this will ensure that the last few bits have been read in / out before the SS line goes high.
DDRB |= (1<<DDB5) | (1<<DDB3) | (1<<DDB2); //Set SCK, MOSI, SS Pins as Output
PORTB |= 1<<PORTB2; //Pull SS High to Disable Communications with ADS1247
SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0) | (1<<CPHA); //Set SPI and Enable
PORTB &= ~(1<<PORTB2); //Pull SS Low to Enable Communications with ADS1247
SPI.transfer(0x4B); //Set IDAC1 Register (0Bh) Write 01h - Output reference current on ANIN0,1
SPI.transfer(0x4A); //Set IDAC0 Register (0Ah) Write 07h - Select 1.5mA reference current for RTD
SPI.transfer(0x43); //Set SYS0 Register (03h) Write 52h - PGA:32, Sample at 20sps
SPI.transfer(0x42); //Set MUX1 Register (02h) Write 30h - Select internal reference always on, internal ref connected to REF0 pins. Use 33h if wanting an on chip temp read.
SPI.transfer(0x40); //Set MUX0 Register (00h) Write 01h
SPI.transfer(0xFF); //NOP to prevent CS High too soon
PORTB |= 1<<PORTB2; //CS High