Skip to content

2a. Data Line States

Sara Damiano edited this page Aug 13, 2024 · 8 revisions

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

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);
  }