-->
Page 1 of 2

TX-20 Wind sensor with ESP8266

PostPosted: Fri Jun 03, 2016 11:50 am
by Bunny
I would like to make a weather station powered by wemos D1 mini, that is an ESP8266 based platform.
I bought a TX-20 wind sensor, that is a common and well loved DIY sensor. I found code for arduino that is working fine. Here is:
http://fabrizio.zellini.org/decoding-la-crosse-tx20-anemometer-with-arduino

The problem is, the code using the AVR library that is NOT avaiable in the Wemos.
So, I have two option:

try to understand how working the sensor and make a new program from base.
try to found an AVR or compatible library to ESP8266.

I am not familiar the interrupts and how read this kind of data. But maybe someone can read the arduino code and translate to ESP or help me. Or maybe someone can give me a AVR library or any good ideas :D

My worst case scenario is using an arduino to communicate with TX-20 and connect to the Wemos over i2C. But i like to solve with one MC if possible!

Re: TX-20 Wind sensor with ESP8266

PostPosted: Sat Jun 04, 2016 1:23 am
by Bunny
I am step forward a bit.
I connect to the RISING interrupt than read the bits with delayMicroseconds().
Its looks working except I have some wrong data reading , but I do not know this is because the item, or syncronisation problem or what, I keep digging.

My question is: Is the interrupt working during the interrupt parser subrutin? So meanwhile I reading the 41 bit information, every high level generate a new call or not?
For make sure I disable the interrupt at the begin of the parser function, but I am not sure, this is a good idea, it is necessary or not or what is the good solution if someone using a long time running interrupt subrutin. This reading need 41*1200microsec at least to read all bit.

Re: TX-20 Wind sensor with ESP8266

PostPosted: Sat Jun 04, 2016 1:24 am
by Bunny
I am step forward a bit.
I connect to the RISING interrupt than read the bits with delayMicroseconds().
Its looks working except I have some wrong data reading , but I do not know this is because the item, or syncronisation problem or what, I keep digging.

My question is: Is the interrupt working during the interrupt parser subrutin? So meanwhile I reading the 41 bit information, every high level generate a new call or not?
For make sure I disable the interrupt at the begin of the function, but I am not sure, this is a good idea, it is necessary or not or what is the good solution if someone using a long time running interrupt subrutin. This reading need 41*1200microsec at least to read all bit.

SOLVED!

PostPosted: Sat Jun 04, 2016 7:40 am
by Bunny
OK, I did my home work and port to ESP8266 the arduino code!
The original wroted 1200microsec is not perfect, there was some shadow bit. I am increase 1220 and all going very well. I am not sure what is the correct amount but with 1220 on my board is working. If the two checksum is not equal, try to modify that delay.

Here is the working solution to testing and debugging the TX-20 wind sensor.
You do not need any extra level shifting just simple connect the D1 to TX-20, because both working on 3.3V.

1 Brown TxD (Digital pin)
2 Red Vcc (3.3V)
3 Green DTR (Ground)
4 Yellow GND (Ground)

For understand the data, here is the details: https://www.john.geek.nz/2011/07/la-crosse-tx20-anemometer-communication-protocol/

The decoding algorithm based on this Arduino code: http://fabrizio.zellini.org/decoding-la-crosse-tx20-anemometer-with-arduino

And at last , there is the Wemos and I think a common ESP8266 code.
Change the DATAPIN constant to your data pin.

Code: Select allconst byte DATAPIN=D2;
volatile boolean TX20IncomingData = false;


void readTX20() {
  if (!TX20IncomingData) {
    TX20IncomingData = true;
  } 
}

/*
 * SETUP
 */
void setup() {
  pinMode(DATAPIN, INPUT);
  attachInterrupt(digitalPinToInterrupt(DATAPIN), readTX20, RISING);
  Serial.begin(115200);
}

/*
 * LOOP
 */
void loop() {
  if (TX20IncomingData) {
    char a[90];
    unsigned char chk;
    int bitcount=0;
    unsigned char sa,sb,sd,se;
    unsigned int sc,sf, pin;

    String message = "";

    sa=sb=sd=se=0;
    sc=0;sf=0;

    for (bitcount=41; bitcount>0; bitcount--) {
      pin = (digitalRead(DATAPIN));
      if (!pin) {
        message += "1";     
      } else {
        message += "0";     
      }
      if ((bitcount==41-4) || (bitcount==41-8) || (bitcount==41-20)  || (bitcount==41-24)  || (bitcount==41-28)) {
        message += " ";
      }     
      if (bitcount > 41-5){
        // start, inverted
        sa = (sa<<1)|(pin^1);
      } else
      if (bitcount > 41-5-4){
        // wind dir, inverted
        sb = sb>>1 | ((pin^1)<<3);
      } else
      if (bitcount > 41-5-4-12){
        // windspeed, inverted
        sc = sc>>1 | ((pin^1)<<11);
      } else
      if (bitcount > 41-5-4-12-4){
        // checksum, inverted
        sd = sd>>1 | ((pin^1)<<3);
      } else
      if (bitcount > 41-5-4-12-4-4){
        // wind dir
        se = se>>1 | (pin<<3);
      } else {
        // windspeed
        sf = sf>>1 | (pin<<11);
      }
         
      delayMicroseconds(1220);   
    }
    Serial.println(message);
    chk= ( sb + (sc&0xf) + ((sc>>4)&0xf) + ((sc>>8)&0xf) );chk&=0xf;
    sprintf(a, "ID: %d\t%d\n", sa, B00100);
    Serial.write (a);
    sprintf(a, "Wind direction: %d\t%d\n", sb, se);
    Serial.write (a);
    sprintf(a, "Wind speed: %d\t%d\n", sc, sf);
    Serial.write (a);
    sprintf(a, "Checksum: %d\t%d\n", sd, chk);
    Serial.write (a);
    if (sa==4 && sb==se && sc==sf && sd==chk){     
      Serial.println(" :) OK :) OK :) OK :) OK");
    } else {
      Serial.println(" !!! ERROR !!! ERROR !!!");
    }
    Serial.println("");
    delayMicroseconds(2000);  // just in case
    TX20IncomingData = false; 
  }
}