LaCross TX23U - sketch problem or bad hardware???

Hi all -
I’m attempting to follow the destructions in this article
http://www.john.geek.nz/2012/08/la-crosse-tx23u-anemometer-communication-protocol/

and correctly connect an TX23U to my Arduino.

When the Arduino is reset, all I ever see is this in the serial monitor:

“Initializing…
Data Pin: 0”

I’m using pin 12 for the anemometer TxD (brown) wire.

I cannot tell whether the problem is something that’s occurring when the PinMode gets set,
or whether the anemometer is hooked up wrong/blown or something entirely different is going on.

Can someone help me figure out a way to divide and conquer the problem?
I’m not sure whether the device connected on a digital pin has to respond
for a digitalread or PinMode to work, or not.
If the device does have to respond, maybe this is a sign my TX23U is toast.

Or if that’s not a true statement - is my code wrong somehow?

Thanks for any thoughts anyone has…

void setup();
void delay2(unsigned long ms);
void loop();
int collectdata(void);
void showdatasimple();
int dataPin = 12;
int bitlenght = -1;
char data[43];
String Wind_Direction;


void setup() {
Serial.begin(9600);
Serial.print("\n\nInitializing...\n");
Serial.print("Data Pin: ");
Serial.println(digitalRead(dataPin));
pinMode(dataPin, INPUT);



}

void delay2(unsigned long ms){
unsigned long start = micros();
while (micros() - start <= ms);
}

void loop() {
collectdata();
}


int collectdata(void){
if (bitlenght <0){
bitlenght = 1230;//getbitlenght2() 1230;
}

pinMode(dataPin, OUTPUT);
digitalWrite(dataPin, HIGH);
delay(100);

digitalWrite(dataPin, LOW );
delay(500);

pinMode(dataPin, INPUT);


while(digitalRead(dataPin) == LOW){
} 
while(digitalRead(dataPin) == HIGH){
}
while(digitalRead(dataPin) == LOW){
}

for (int i=0 ; i<42 ; i++){

data[i] = (digitalRead(dataPin) == LOW)? 48 : 49 ;
delay2(bitlenght);
}

showdatasimple();
return 0;
}

void showdatasimple(){
Serial.println("");

String Wind_Dir_PatternStr = "b";
String Wind_Dir_DescStr = "";
for (int i =8 ; i> 4 ; i--){
Wind_Dir_PatternStr += ((data[i] == 48)? 0 : 1);
}

Serial.print(Wind_Dir_PatternStr);
Serial.print(" = ");

if (Wind_Dir_PatternStr == "b0000") { Wind_Dir_DescStr="N"; }
if (Wind_Dir_PatternStr == "b0001") { Wind_Dir_DescStr="NNO";}
if (Wind_Dir_PatternStr == "b0010") { Wind_Dir_DescStr="NO"; }
if (Wind_Dir_PatternStr == "b0011") { Wind_Dir_DescStr="ONO"; }
if (Wind_Dir_PatternStr == "b0100") { Wind_Dir_DescStr="O"; }
if (Wind_Dir_PatternStr == "b0101") { Wind_Dir_DescStr="OZO"; }
if (Wind_Dir_PatternStr == "b0110") { Wind_Dir_DescStr="ZO"; }
if (Wind_Dir_PatternStr == "b0111") { Wind_Dir_DescStr="ZZO"; }
if (Wind_Dir_PatternStr == "b1000") { Wind_Dir_DescStr="Z"; }
if (Wind_Dir_PatternStr == "b1001") { Wind_Dir_DescStr="ZZW"; }
if (Wind_Dir_PatternStr == "b1010") { Wind_Dir_DescStr="ZW"; }
if (Wind_Dir_PatternStr == "b1011") { Wind_Dir_DescStr="WZW"; }
if (Wind_Dir_PatternStr == "b1100") { Wind_Dir_DescStr="W"; }
if (Wind_Dir_PatternStr == "b1101") { Wind_Dir_DescStr="WNW"; }
if (Wind_Dir_PatternStr == "b1110") { Wind_Dir_DescStr="NW"; }
if (Wind_Dir_PatternStr == "b1111") { Wind_Dir_DescStr="NNW"; }

Serial.println(Wind_Dir_DescStr); 


Serial.println("");

//HEAD
for (int i =0 ; i< 5 ; i++){
Serial.print( ((data[i] == 48)? 0 : 1) );
}

Serial.print("");

//WINDDIR
for (int i =8 ; i> 4 ; i--){
Serial.print( ((data[i] == 48)? 0 : 1) );
}



Serial.print("");

//WIND SPEED
for (int i =17 ; i> 8 ; i--){
Serial.print( ((data[i] == 48)? 0 : 1) );
}

Serial.print("");

//WIND SPEED+3
for (int i =20 ; i> 17 ; i--){
Serial.print( ((data[i] == 48)? 0 : 1) );
} 

Serial.print("");

//CC
for (int i =24 ; i> 20 ; i--){
Serial.print( ((data[i] == 48)? 0 : 1) );
}

Serial.print("");

//WIND DIR NEGATEIVE
for (int i =28 ; i> 24 ; i--){
Serial.print( ((data[i] == 48)? 0 : 1) );
}

Serial.print("");

//WIND SPEED NEGATIVE
for (int i =37 ; i> 28 ; i--){
Serial.print( ((data[i] == 48)? 0 : 1) );
}

Serial.print("");

//WIND SPEED NEGATIVE+3
for (int i =40 ; i> 37 ; i--){
Serial.print( ((data[i] == 48)? 0 : 1) );
}
}

OK, so since one day ago when I posted this, I've added in some serial.print statements to check and see where in the program it was getting to.

It looks like it's looping endlessly at this point

while(digitalRead(dataPin) == LOW){
}

I'm not sure why it's not proceeding to the next while statement, nor do I really know why
there isn't any code inside the while statements?
But this is code for reading the TX23U
that is posted in at least two other threads on this forum, without anyone complaining about that not working,
so I guess it does something :wink:

I'm a bit of a rookie to be claiming that code should be someplace that wiser heads may know
why a while statement doesn't have to have code inside it's curlies.. :smiley:

I think that the idea would be that the three while statements in the code

while(digitalRead(dataPin) == LOW){
} 
while(digitalRead(dataPin) == HIGH){
}
while(digitalRead(dataPin) == LOW){
}

would execute one after the other, based on the state of the dataPin, right??
And is the idea that the TX23U would be causing those state changes, and since dataPin is in pinmode INPUT,
the Arduino would be reading in data to pass down to the next set of code to process that incoming data?

So if I'm stuck in the while LOW section, that would be because the line is never going Low, then High, then Low again?

Update -

With a few wiring changes and some other things, code is now working.

BUT -- I am having to manually trigger a LOW on the data pin by shorting it to ground.
The documentation in the link I put in the first post says that triggering the anemometer to send data
is done by shorting TxD to ground for 500 msec, and then it will measure data for 20msec and then
send a 41 bit value.
That happens when I do the manual short, triggering it to ground.

It looks to me though, like this code is meant to do that -
But it's not.
The Arduino just sits there, and no data appears.

Why would the digitalwrite(datapin, LOW);
be failing to trigger the anemometer?
Looks like that's what the code is meant to do.... the same thing I'm having to do manually...

pinMode(dataPin, OUTPUT);
digitalWrite(dataPin, HIGH);
delay(100);

digitalWrite(dataPin, LOW );
delay(500);

pinMode(dataPin, INPUT);


while(digitalRead(dataPin) == LOW){
} 
while(digitalRead(dataPin) == HIGH){
}
while(digitalRead(dataPin) == LOW){
}

Does anyone have any idea as to why the Arduino isn't triggering via the dataPin going LOW ??

I've done as much as I know how with this - I do need some advice...

thanks, R

my eye saw this

void setup() 
{
  Serial.begin(9600);
  Serial.print("\n\nInitializing...\n");
  Serial.print("Data Pin: ");
  Serial.println(digitalRead(dataPin));  <<<<<<<<<<<< read before setting to input ???? 
  pinMode(dataPin, INPUT);
}

Please use CTRL-T in the IDE before posting code, it reformats the layout, making it better readable.

void delay2(unsigned long ms)
{
  unsigned long start = micros();
  while (micros() - start <= ms);
}

can be replaced by calls to delayMicroseconds();

bitlenght → bitLength // no problem but camelCase is preferred convention for variables

void collectdata(void)
{
  if (bitlenght < 0)
  {
    bitlenght = 1230;   //getbitlenght2() 1230; 
  }

  pinMode(dataPin, OUTPUT);
  digitalWrite(dataPin, HIGH);
  delay(100);
  digitalWrite(dataPin, LOW );
  // delay(500);               // <<<<<<<<<<<<<<<<<<<< try to remove this line as it blocks and you can miss the LOW HIGH LOW getting complete out of sync.

  pinMode(dataPin, INPUT);
  while(digitalRead(dataPin) == LOW);
  while(digitalRead(dataPin) == HIGH);
  while(digitalRead(dataPin) == LOW);

  delayMicroseconds(bitlenght/2);  // be sure to be beyond the edge of the bit

  for (int i=0 ; i<42 ; i++)
  {
    data[i] = (digitalRead(dataPin) == LOW);  // fills it with 0/1 instead of with 48/49
    delayMicroseconds(bitlenght);
  }

  showdatasimple();
}

part2: using an array for the wind directions makes code simpler.

void showdatasimple()
{
  Serial.println();
  
  char windDirection[16][4] = { "N","NNO","NO", "ONO","O","OZO","ZO","ZZO","Z","ZZW","ZW","WZW","W","WNW","NW","NNW" }

  int idx =0;
  for (int i=8 ; i> 4 ; i--)
  {
    idx = idx *2 + data[i];  // data[i] == 0/1.. see prev post.  // 
  }

  Serial.print("idx: ");
  Serial.println(idx, DEC);
  Serial.print("Wind: ");
  Serial.println(windDirection[idx] );
  Serial.println();

  //HEAD
  for (int i =0 ; i< 5 ; i++)
  {
    Serial.print(data[i]);  // it contains 0 or 1
  }

  Serial.print("\t");

  //WINDDIR
  for (int i =8 ; i> 4 ; i--)
  {
    Serial.print(data[i]);
  }
  Serial.print("\t");

  //WIND SPEED
  for (int i =17 ; i> 8 ; i--)
  {
    Serial.print(data[i]);
  }

  Serial.print("\t");

  //WIND SPEED+3
  for (int i =20 ; i> 17 ; i--)
  {
    Serial.print(data[i]);
  } 

  Serial.print("\t");

  //CC
  for (int i =24 ; i> 20 ; i--)
  {
    Serial.print(data[i]);
  }

  Serial.print("\t");

  //WIND DIR NEGATEIVE
  for (int i =28 ; i> 24 ; i--)
  {
    Serial.print(data[i]);
  }

  Serial.print("\t");

  //WIND SPEED NEGATIVE
  for (int i =37 ; i> 28 ; i--){
    Serial.print( ((data[i] == 48)? 0 : 1) );
  }

  Serial.print("\t");

  //WIND SPEED NEGATIVE+3
  for (int i =40 ; i> 37 ; i--){
    Serial.print( ((data[i] == 48)? 0 : 1) );
  }
  Serial.println();
  Serial.println();
  Serial.println();
}

and yes char data should become int data[42]; to let the above work :wink:

Thanks Rob ---

I'll remember to format the code better--
And yes, the camelCode is a good idea --
I simply hadn't fixed that bitLength piece yet, because I wanted (in my ignorance) to change as little as possible from the original sketch.....

Regarding your first post,
yes, the output prints a zero, which makes sense given that you've not set the pin for INput yet.
I'll fix that...

Regarding the My understanding is that the TX23U is triggered to begin a data-sending session by
having TxD pulled low for at least half a second, and that triggers it to spend 20ms retrieving data.

I can try removing that though, and see what happens.
I don't understand the point of the pinData, HIGH just before that, for 100msec,
unless that's just to get a known state before beginning the sequence of Low,High,Low.

How do I call delaySeconds?

I'll check out your idea for the array after I get the data input sorted---

thanks for your ideas!

R

How do I call delaySeconds?

delaySeconds() does not exists delayMicroseconds() does. e.g. delayMicroseconds(50); // wait for ~50us

but you can create a delaySeconds() quite easy if you want to but it would block your sketch

delaySeconds(uint32_t seconds)
{
  while (seconds--) delay(1000);
}

Hello,

I noticed this post looks old, and have found mixed info. on the Internet. Does anyone know if there is a working library or samples to get both the wind speed and direction working consistently?

I'm new to Arduino programming and was trying to avoid trying to figure out how to write "bitbang" code to try and read the signaling if it's already been done.

Thanks,

Shadow