-
-
Notifications
You must be signed in to change notification settings - Fork 100
2a. Data Line States
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
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
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);
}