Skip to content

2a. Data Line States

Kevin M. Smith edited this page Feb 13, 2014 · 8 revisions

The Arduino is responsible for managing communication with the sensors. Since all the data transfer happens on the same line, the state of the data line is very important.

When the pin is in the HOLDING state, it is holding the line LOW so that interference does not unintentionally wake the sensors up. The interrupt is disabled for the dataPin, because we are not expecting any SDI-12 traffic. In the TRANSMITTING state, we would like exclusive control of the Arduino, so we shut off all interrupts, and vary the voltage of the dataPin in order to wake up and send commands to the sensor. In the LISTENING state, we are waiting for a sensor to respond, so we drop the voltage level to LOW and relinquish control (INPUT). If we would like to disable all SDI-12 functionality, then we set the system to the DISABLED state, removing the interrupt associated with the dataPin. For predictability, we set the pin to a LOW level high impedance state (INPUT).

State			Interrupts		Pin Mode	Pin Level
HOLDING			Pin Disable		OUTPUT		LOW
TRANSMITTING		All Disable		OUTPUT		VARYING
LISTENING 		        All Enable		INPUT		LOW
DISABLED		        Pin Disable		INPUT		LOW

Sequencing

Generally, this is acceptable. HOLDING --> TRANSMITTING --> LISTENING --> TRANSMITTING --> LISTENING -->

If you have interference, you should force a hold, using forceHold(); HOLDING --> TRANSMITTING --> LISTENING --> done reading, forceHold(); HOLDING

Function Descriptions

2.1 - Sets the proper state. This is a private function, and only used internally. It uses #define values of HOLDING, TRANSMITTING, LISTENING, and DISABLED to determine which state should be set. The grid above defines the settings applied in changing to each state.

2.2 - A public function which forces the line into a "holding" state. This is generally unneeded, but for deployments where interference is an issue, it should be used after all expected bytes have been returned from the sensor.

// 2.1 - sets the state of the SDI-12 object. 
void SDI12::setState(uint8_t state){
  if(state == HOLDING){
    pinMode(_dataPin,OUTPUT);
    digitalWrite(_dataPin,LOW);
    *digitalPinToPCMSK(_dataPin) &= ~(1<<digitalPinToPCMSKbit(_dataPin));
  }
  if(state == TRANSMITTING){
    pinMode(_dataPin,OUTPUT);
    noInterrupts(); 			// supplied by Arduino.h, same as cli()
  }
  if(state == LISTENING) {
    digitalWrite(_dataPin,LOW);
    pinMode(_dataPin,INPUT); 
    interrupts();				// supplied by Arduino.h, same as sei()
	*digitalPinToPCICR(_dataPin) |= (1<<digitalPinToPCICRbit(_dataPin));
    *digitalPinToPCMSK(_dataPin) |= (1<<digitalPinToPCMSKbit(_dataPin));
  } else { 						// implies state==DISABLED 
  	digitalWrite(_dataPin,LOW); 
  	pinMode(_dataPin,INPUT);
  	*digitalPinToPCMSK(_dataPin) &= ~(1<<digitalPinToPCMSKbit(_dataPin));
  	if(!*digitalPinToPCMSK(_dataPin)){
   		*digitalPinToPCICR(_dataPin) &= ~(1<<digitalPinToPCICRbit(_dataPin));
  	}
  }
}

// 2.2 - forces a HOLDING state. 
void SDI12::forceHold(){
	setState(HOLDING); 
}