user11917: I'm very new to Arduino, and I'm trying to read data from a LaCrosse TX23 V02(X) anemometer. It's supposed to behave like this https://www.john.geek.nz/2012/08/la-crosse-tx23u-anemometer-communication-protocol/, but it's not...
I don't have an oscilloscope, so I made this code, using micros() to try to trace the output from the TX23:
void loop() {
  collectData();
}


int collectData(void){
   if (bitLength < 0){
      bitLength = 1200;// length of bit is equal to approx 1230 micro seconds;
   }
  // init sequence
  pinMode(dataPin, OUTPUT);
  Serial.print("Send LOW\n");
  digitalWrite(dataPin, LOW );
  Serial.print("Send HIGH\n");
  digitalWrite(dataPin, HIGH);
  delay(100);
  Serial.print("Send LOW\n");
  digitalWrite(dataPin, LOW );
  delay(500);

  Serial.print("Begin input mode\n");
  pinMode(dataPin, INPUT);

  int state = 0;
  int oldstate = 0;
  unsigned long oldmicros = micros();
  for (int i = 1; i<5250 ; i++) {
    state = (digitalRead(dataPin) == LOW)? 0:1;
    if (i%10 != 0) {
      Serial.print("-");
    } else {
      Serial.print("+");
    }

    delayMicroseconds(10);
    if (state != oldstate) {
      oldstate = state;
      i = 1;
      Serial.print(oldstate);
      Serial.print(" @");
      Serial.print(micros() - oldmicros);
      oldmicros = micros();
      Serial.print("\n");
    } 
  }
  Serial.print(state);
  Serial.println(micros()-oldmicros);
}

Does it have a chance to provide a quite accurate monitoring of the TX23 output? (eg is using micros() or delayMicroseconds(10) accurate ?)

user4143: You should really make use of pulseIn() to work out the bit rate of the signal.  The first HIGH pulse in the header is there for timing so you know how often to poll the input.
Step one, after sending your outgoing initiation pulse, should be to wait for that first pulse (you might need a slight delay first before it starts transmitting - wait for the line to be low first):
while (digitalRead(dataPin) == HIGH); // Wait for TX start
uint32_t pulseWidth = pulseIn(dataPin, HIGH); // Get first pulse

That gives you the width of the first pulse in microseconds.
Now you can read 45 times at that period.  If you first delay by half that amount before your first sample you will be roughly in the middle of the bit so you can cope with a slight amount of drift.
// Wait for the middle of the first bit
delayMicroseconds(pulseWidth / 2);

uint32_t highBlock = 0;
uint32_t lowBlock = 0;
for (int i = 0; i < 45; i++) {
    // Shift the high 32-bits left one bit
    highBlock <<= 1;
    // Place in the highest bit of the low block as the lowest
    // bit of the high block
    highBlock |= (lowBlock & 0x80000000UL ? 1 : 0); 
    // Shift the low 32-bits left one bit
    lowBlock <<= 1;
    // Add in the value of the bit from the data pin
    lowBlock |= digitalRead(dataPin);
    // Wait for the next bit
    delayMicroseconds(pulseWidth);
}

You should now have two 32-bit words which, when put together, form the entire datagram.  You can now use bitwise operators to pull out the parts you are interested in.
A better, though more complex, method of doing it would be to employ a timer with an overflow period equal to the pulse width. That will afford you much more accurate timing than a simple loop with delays.

user3917: Majenko showed a method for digitally recording the waveform, after measuring pulseWidth at the outset, and mentioned use of a timer for delays.   I'll address the part of your question about using micros() while tracing TX23 output:  “Does it have a chance to provide a quite accurate monitoring of the TX23 output?” 
Some of the serial output that your method produces as it goes along will affect evenness of timing.  For example, the Serial.print() of + after every tenth reading introduces a small timing irregularity (the two branches of the if may differ a few cycles in execution time).
More seriously, your double-read of micros() (after you print oldstate, you print micros() - oldmicros and then read micros() again) introduces a few cycles of timing error.  It probably amounts to a few microseconds total over the course of recording the pulse train.  Instead of reading micros() twice, say something like newmicros = micros() directly after detecting a state change, before doing any serial printing, then use newmicros in place of other micros() calls.  Having serial prints before oldmicros = micros(); causes an offset error, which will be microseconds or milliseconds depending on the data rate you set in setup().  It mostly affects the reported length only of the first pulse.
What I would do for debug monitoring of the pulse train is along the following lines: 
enum { timelen=44, maxpause=50000 };
unsigned long int times[timelen];

int collectData() {
  byte ntimes = 0, state=LOW;
  unsigned long int prevtime;
  pinMode(dataPin, OUTPUT);
  digitalWrite(dataPin, LOW ); // Pull DTR low to trigger conversion
  delay(500);
  pinMode(dataPin, INPUT_PULLUP); // Release DTR and set pullup
  delay(1);           // Let TX23U pull DTR low
  prevtime = micros();
  while (micros() - prevtime < maxpause && ntimes < timelen) {
    if (digitalRead(dataPin) != state) {
      times[ntimes++] = prevtime = micros();
      state = 1-state;
    }
  }
  return ntimes;
}

This code is intended to record times at which state changes occur.  After loop() calls collectData(), it can call a reportData() routine that will print out pulse lengths by subtracting adjacent entries of times[].  Even-indexed array entries are times of rising edges in the pulse train; odd-indexed entries are times of falling edges.  Because the if (digitalRead(dataPin) != state) {...} statement isn't executed atomically, the data pin can change after being tested but before being recorded a couple of lines later.  Using state = 1-state; instead of state = digitalRead(dataPin); guarantees that even indexes are for rising edges, but does not guarantee that adjacent entries correspond to the same pulse edge.  That is, a noisy signal can produce misleading results. 

user10794: I'm going to present a third way of working on this. :)
First, since I don't have a TX23 I wrote a TX23-simulator:
const byte TESTPIN = 2;

const byte test [6] = { 
    0b00000011,
    0b01111011,
    0b01010100,
    0b00010100,
    0b01001010,
    0b10111111 };

void setup ()
  {
  pinMode (TESTPIN, INPUT);
  delay (100);
  }  // end of setup

void loop ()
  {
  // wait for host to pull pin low
  while (digitalRead (TESTPIN) == HIGH)
    { }
  // wait for host to release it
  while (digitalRead (TESTPIN) == LOW)
    { }
  digitalWrite (TESTPIN, HIGH);
  pinMode (TESTPIN, OUTPUT);
  for (byte i = 0; i < 6; i++)
    for (byte j = 0; j < 8; j++)
      {
      delayMicroseconds (1100);
      digitalWrite (TESTPIN, test [i] & bit (7 - j));
      }
  pinMode (TESTPIN, INPUT);
  }  // end of loop

Based on your linked page about the TX23 it outputs a series of low/high pulses corresponding to the example on that page, like this:

Note that you need a 10 k pull-up resistor for this to work properly.

Now the reading code uses interrupts to detect state changes:
const byte READ_PIN = 2;
const byte NUMBER_OF_CHANGES = 48;

volatile unsigned long bitTime [NUMBER_OF_CHANGES];
volatile byte state [NUMBER_OF_CHANGES];
volatile byte count;

void stateChange ()
  {
  unsigned long now = micros ();
  if (count >= NUMBER_OF_CHANGES)
    return;  // array full
  state [count] = digitalRead (READ_PIN);
  bitTime [count++] = now;
  } // end of stateChange

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  }  // end of setup

void takeReading ()
  {
  count = 0;
  digitalWrite (READ_PIN, LOW);  // start reading
  pinMode (READ_PIN, OUTPUT);   
  delay (20);  // pulse width
  pinMode (READ_PIN, INPUT);     // release line
  EIFR = bit (INTF0);  // clear flag for interrupt 0
  attachInterrupt (0, stateChange, CHANGE);
  delay (55);  // let readings fill up array
  detachInterrupt (0);
  }  // end of takeReading

void loop ()
  {
  takeReading ();
  if (count == 0)
    return;  // nothing!

  delay (500);
  for (byte i = 0; i < count; i++)
    {
    Serial.print ("count: ");
    Serial.print ((int) i);
    Serial.print (" = ");
    Serial.print (bitTime [i]);
    Serial.print (", state = ");
    Serial.print (state [i]);
    if (i > 0)
      {
      Serial.print (", width = ");  
      unsigned long width = bitTime [i] - bitTime [i - 1];
      Serial.print (width);
      Serial.print (" (");
      int bits = width / 1000;
      for (byte k = 0; k < bits; k++)
       Serial.print (state [i - 1]);
      Serial.print (")");
      }
    Serial.println ();
    }
    Serial.println ();
  }  // end of loop


Results were:
count: 0 = 10952804, state = 1
count: 1 = 10953928, state = 0, width = 1124 (1)
count: 2 = 10960616, state = 1, width = 6688 (000000)
count: 3 = 10962844, state = 0, width = 2228 (11)
count: 4 = 10963960, state = 1, width = 1116 (0)
count: 5 = 10968412, state = 0, width = 4452 (1111)
count: 6 = 10969524, state = 1, width = 1112 (0)
count: 7 = 10971752, state = 0, width = 2228 (11)
count: 8 = 10972876, state = 1, width = 1124 (0)
count: 9 = 10973988, state = 0, width = 1112 (1)
count: 10 = 10975104, state = 1, width = 1116 (0)
count: 11 = 10976216, state = 0, width = 1112 (1)
count: 12 = 10977328, state = 1, width = 1112 (0)
count: 13 = 10978440, state = 0, width = 1112 (1)
count: 14 = 10984012, state = 1, width = 5572 (00000)
count: 15 = 10985124, state = 0, width = 1112 (1)
count: 16 = 10986244, state = 1, width = 1120 (0)
count: 17 = 10987356, state = 0, width = 1112 (1)
count: 18 = 10990700, state = 1, width = 3344 (000)
count: 19 = 10991812, state = 0, width = 1112 (1)
count: 20 = 10994040, state = 1, width = 2228 (00)
count: 21 = 10995156, state = 0, width = 1116 (1)
count: 22 = 10996268, state = 1, width = 1112 (0)
count: 23 = 10997380, state = 0, width = 1112 (1)
count: 24 = 10998500, state = 1, width = 1120 (0)
count: 25 = 10999616, state = 0, width = 1116 (1)
count: 26 = 11000728, state = 1, width = 1112 (0)

This seems to agree with the test data.

11917: <p>I'm very new to Arduino, and I'm trying to read data from a LaCrosse TX23 V02(X) anemometer. It's supposed to behave like this <a href="https://www.john.geek.nz/2012/08/la-crosse-tx23u-anemometer-communication-protocol/" rel="nofollow">https://www.john.geek.nz/2012/08/la-crosse-tx23u-anemometer-communication-protocol/</a>, but it's not...</p>

<p>I don't have an oscilloscope, so I made this code, using micros() to try to trace the output from the TX23:</p>

<pre><code>void loop() {
  collectData();
}


int collectData(void){
   if (bitLength &lt; 0){
      bitLength = 1200;// length of bit is equal to approx 1230 micro seconds;
   }
  // init sequence
  pinMode(dataPin, OUTPUT);
  Serial.print("Send LOW\n");
  digitalWrite(dataPin, LOW );
  Serial.print("Send HIGH\n");
  digitalWrite(dataPin, HIGH);
  delay(100);
  Serial.print("Send LOW\n");
  digitalWrite(dataPin, LOW );
  delay(500);

  Serial.print("Begin input mode\n");
  pinMode(dataPin, INPUT);

  int state = 0;
  int oldstate = 0;
  unsigned long oldmicros = micros();
  for (int i = 1; i&lt;5250 ; i++) {
    state = (digitalRead(dataPin) == LOW)? 0:1;
    if (i%10 != 0) {
      Serial.print("-");
    } else {
      Serial.print("+");
    }

    delayMicroseconds(10);
    if (state != oldstate) {
      oldstate = state;
      i = 1;
      Serial.print(oldstate);
      Serial.print(" @");
      Serial.print(micros() - oldmicros);
      oldmicros = micros();
      Serial.print("\n");
    } 
  }
  Serial.print(state);
  Serial.println(micros()-oldmicros);
}
</code></pre>

<p>Does it have a chance to provide a quite accurate monitoring of the TX23 output? (eg is using micros() or delayMicroseconds(10) accurate ?)</p>
 4143: <p>You should really make use of <code>pulseIn()</code> to work out the bit rate of the signal.  The first HIGH pulse in the header is there for timing so you know how often to poll the input.</p>

<p>Step one, after sending your outgoing initiation pulse, should be to wait for that first pulse (you might need a slight delay first before it starts transmitting - wait for the line to be low first):</p>

<pre><code>while (digitalRead(dataPin) == HIGH); // Wait for TX start
uint32_t pulseWidth = pulseIn(dataPin, HIGH); // Get first pulse
</code></pre>

<p>That gives you the width of the first pulse in microseconds.</p>

<p>Now you can read 45 times at that period.  If you first delay by half that amount before your first sample you will be roughly in the middle of the bit so you can cope with a slight amount of drift.</p>

<pre><code>// Wait for the middle of the first bit
delayMicroseconds(pulseWidth / 2);

uint32_t highBlock = 0;
uint32_t lowBlock = 0;
for (int i = 0; i &lt; 45; i++) {
    // Shift the high 32-bits left one bit
    highBlock &lt;&lt;= 1;
    // Place in the highest bit of the low block as the lowest
    // bit of the high block
    highBlock |= (lowBlock &amp; 0x80000000UL ? 1 : 0); 
    // Shift the low 32-bits left one bit
    lowBlock &lt;&lt;= 1;
    // Add in the value of the bit from the data pin
    lowBlock |= digitalRead(dataPin);
    // Wait for the next bit
    delayMicroseconds(pulseWidth);
}
</code></pre>

<p>You should now have two 32-bit words which, when put together, form the entire datagram.  You can now use bitwise operators to pull out the parts you are interested in.</p>

<p>A better, though more complex, method of doing it would be to employ a timer with an overflow period equal to the pulse width. That will afford you much more accurate timing than a simple loop with delays.</p>
 3917: <p>Majenko showed a method for digitally recording the waveform, after measuring <code>pulseWidth</code> at the outset, and mentioned use of a timer for delays.   I'll address the part of your question about using <code>micros()</code> while tracing TX23 output:  “Does it have a chance to provide a quite accurate monitoring of the TX23 output?” </p>

<p>Some of the serial output that your method produces as it goes along will affect evenness of timing.  For example, the <code>Serial.print()</code> of + after every tenth reading introduces a small timing irregularity (the two branches of the <code>if</code> may differ a few cycles in execution time).</p>

<p>More seriously, your double-read of <code>micros()</code> (after you print <code>oldstate</code>, you print <code>micros() - oldmicros</code> and then read <code>micros()</code> again) introduces a few cycles of timing error.  It probably amounts to a few microseconds total over the course of recording the pulse train.  Instead of reading <code>micros()</code> twice, say something like <code>newmicros = micros()</code> directly after detecting a state change, before doing any serial printing, then use <code>newmicros</code> in place of other <code>micros()</code> calls.  Having serial prints before <code>oldmicros = micros();</code> causes an offset error, which will be microseconds or milliseconds depending on the data rate you set in <code>setup()</code>.  It mostly affects the reported length only of the first pulse.</p>

<p>What I would do for debug monitoring of the pulse train is along the following lines: </p>

<pre><code>enum { timelen=44, maxpause=50000 };
unsigned long int times[timelen];

int collectData() {
  byte ntimes = 0, state=LOW;
  unsigned long int prevtime;
  pinMode(dataPin, OUTPUT);
  digitalWrite(dataPin, LOW ); // Pull DTR low to trigger conversion
  delay(500);
  pinMode(dataPin, INPUT_PULLUP); // Release DTR and set pullup
  delay(1);           // Let TX23U pull DTR low
  prevtime = micros();
  while (micros() - prevtime &lt; maxpause &amp;&amp; ntimes &lt; timelen) {
    if (digitalRead(dataPin) != state) {
      times[ntimes++] = prevtime = micros();
      state = 1-state;
    }
  }
  return ntimes;
}
</code></pre>

<p>This code is intended to record times at which state changes occur.  After <code>loop()</code> calls <code>collectData()</code>, it can call a <code>reportData()</code> routine that will print out pulse lengths by subtracting adjacent entries of <code>times[]</code>.  Even-indexed array entries are times of rising edges in the pulse train; odd-indexed entries are times of falling edges.  Because the <code>if (digitalRead(dataPin) != state) {...}</code> statement isn't executed atomically, the data pin can change after being tested but before being recorded a couple of lines later.  Using <code>state = 1-state;</code> instead of <code>state = digitalRead(dataPin);</code> guarantees that even indexes are for rising edges, but does not guarantee that adjacent entries correspond to the same pulse edge.  That is, a noisy signal can produce misleading results. </p>
 10794: 

<p>I'm going to present a third way of working on this. :)</p>

<p>First, since I don't have a TX23 I wrote a TX23-simulator:</p>

<pre class="lang-C++ prettyprint-override"><code>const byte TESTPIN = 2;

const byte test [6] = { 
    0b00000011,
    0b01111011,
    0b01010100,
    0b00010100,
    0b01001010,
    0b10111111 };

void setup ()
  {
  pinMode (TESTPIN, INPUT);
  delay (100);
  }  // end of setup

void loop ()
  {
  // wait for host to pull pin low
  while (digitalRead (TESTPIN) == HIGH)
    { }
  // wait for host to release it
  while (digitalRead (TESTPIN) == LOW)
    { }
  digitalWrite (TESTPIN, HIGH);
  pinMode (TESTPIN, OUTPUT);
  for (byte i = 0; i &lt; 6; i++)
    for (byte j = 0; j &lt; 8; j++)
      {
      delayMicroseconds (1100);
      digitalWrite (TESTPIN, test [i] &amp; bit (7 - j));
      }
  pinMode (TESTPIN, INPUT);
  }  // end of loop
</code></pre>

<p>Based on your <a href="https://www.john.geek.nz/2012/08/la-crosse-tx23u-anemometer-communication-protocol/" rel="nofollow noreferrer">linked page about the TX23</a> it outputs a series of low/high pulses corresponding to the example on that page, like this:</p>

<p><a href="https://i.stack.imgur.com/pGCKr.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/pGCKr.png" alt="TX23 simulator"></a></p>

<p>Note that you need a 10 k pull-up resistor for this to work properly.</p>

<hr>

<p>Now the reading code uses interrupts to detect state changes:</p>

<pre class="lang-C++ prettyprint-override"><code>const byte READ_PIN = 2;
const byte NUMBER_OF_CHANGES = 48;

volatile unsigned long bitTime [NUMBER_OF_CHANGES];
volatile byte state [NUMBER_OF_CHANGES];
volatile byte count;

void stateChange ()
  {
  unsigned long now = micros ();
  if (count &gt;= NUMBER_OF_CHANGES)
    return;  // array full
  state [count] = digitalRead (READ_PIN);
  bitTime [count++] = now;
  } // end of stateChange

void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  }  // end of setup

void takeReading ()
  {
  count = 0;
  digitalWrite (READ_PIN, LOW);  // start reading
  pinMode (READ_PIN, OUTPUT);   
  delay (20);  // pulse width
  pinMode (READ_PIN, INPUT);     // release line
  EIFR = bit (INTF0);  // clear flag for interrupt 0
  attachInterrupt (0, stateChange, CHANGE);
  delay (55);  // let readings fill up array
  detachInterrupt (0);
  }  // end of takeReading

void loop ()
  {
  takeReading ();
  if (count == 0)
    return;  // nothing!

  delay (500);
  for (byte i = 0; i &lt; count; i++)
    {
    Serial.print ("count: ");
    Serial.print ((int) i);
    Serial.print (" = ");
    Serial.print (bitTime [i]);
    Serial.print (", state = ");
    Serial.print (state [i]);
    if (i &gt; 0)
      {
      Serial.print (", width = ");  
      unsigned long width = bitTime [i] - bitTime [i - 1];
      Serial.print (width);
      Serial.print (" (");
      int bits = width / 1000;
      for (byte k = 0; k &lt; bits; k++)
       Serial.print (state [i - 1]);
      Serial.print (")");
      }
    Serial.println ();
    }
    Serial.println ();
  }  // end of loop
</code></pre>

<hr>

<p>Results were:</p>

<pre class="lang-C++ prettyprint-override"><code>count: 0 = 10952804, state = 1
count: 1 = 10953928, state = 0, width = 1124 (1)
count: 2 = 10960616, state = 1, width = 6688 (000000)
count: 3 = 10962844, state = 0, width = 2228 (11)
count: 4 = 10963960, state = 1, width = 1116 (0)
count: 5 = 10968412, state = 0, width = 4452 (1111)
count: 6 = 10969524, state = 1, width = 1112 (0)
count: 7 = 10971752, state = 0, width = 2228 (11)
count: 8 = 10972876, state = 1, width = 1124 (0)
count: 9 = 10973988, state = 0, width = 1112 (1)
count: 10 = 10975104, state = 1, width = 1116 (0)
count: 11 = 10976216, state = 0, width = 1112 (1)
count: 12 = 10977328, state = 1, width = 1112 (0)
count: 13 = 10978440, state = 0, width = 1112 (1)
count: 14 = 10984012, state = 1, width = 5572 (00000)
count: 15 = 10985124, state = 0, width = 1112 (1)
count: 16 = 10986244, state = 1, width = 1120 (0)
count: 17 = 10987356, state = 0, width = 1112 (1)
count: 18 = 10990700, state = 1, width = 3344 (000)
count: 19 = 10991812, state = 0, width = 1112 (1)
count: 20 = 10994040, state = 1, width = 2228 (00)
count: 21 = 10995156, state = 0, width = 1116 (1)
count: 22 = 10996268, state = 1, width = 1112 (0)
count: 23 = 10997380, state = 0, width = 1112 (1)
count: 24 = 10998500, state = 1, width = 1120 (0)
count: 25 = 10999616, state = 0, width = 1116 (1)
count: 26 = 11000728, state = 1, width = 1112 (0)
</code></pre>

<p>This seems to agree with the test data.</p>
