-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathLaCrosse_TX23.cpp
119 lines (96 loc) · 2.75 KB
/
LaCrosse_TX23.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*************************************************************************************************
LaCrosse_TX23.h - Library for reading LaCrosse TX23 anemometer data.
LaCrosse TX23 is a wind speed and direction sensor. It uses 3 wires for communication and power:
Pin1 Brown(Black) DATA
Pin2 Red Vcc
Pin3 Green N/C
Pin4 Yellow GND
DATA pin is to be connected directly to one of Arduino ports.
Created by Krzysztof Egzmont, 06.11.2016.
Based on https://www.john.geek.nz/2012/08/la-crosse-tx23u-anemometer-communication-protocol/
Big thanks for John.
Donations:
Bitcoin - 1JrHQwJWt1JNZepT1EXqPSioXcwD227nnU
Ethereum - 0xFC9713013e78f6F14bA5064E36f875dbbB32B94a
BSD license, all text above must be included in any redistribution
*************************************************************************************************/
#include <LaCrosse_TX23.h>
LaCrosse_TX23::LaCrosse_TX23(int pin, DelayFunc delayFunc) :
_pin(pin),
_delay(delayFunc)
{
pinMode(pin, INPUT);
}
void LaCrosse_TX23::pullBits(void *dst, bool *src, int count)
{
uint8_t * d = (uint8_t*) dst;
for (int i=0; i<count; i++)
{
d[i/8] |= src[i]<<(i%8);
}
}
bool LaCrosse_TX23::readRaw(uint16_t &speed, uint8_t &direction)
{
speed = 0;
direction = 0;
digitalWrite(_pin,LOW);
pinMode(_pin,OUTPUT);
_delay(500);
pinMode(_pin,INPUT);
pulseIn(_pin,LOW);
const unsigned bitLen = 1200;
bool data[50];
bool lastState = 1;
unsigned long start = micros();
for(unsigned long t = 0; t<50000; t = micros()-start)
{
bool state = digitalRead(_pin);
unsigned bitNum = t/bitLen;
if(t%bitLen>bitLen/2) data[bitNum] = state;
if(state!=lastState)
{
unsigned delta = t%bitLen;
if(delta<100)
start -= delta;
else if(delta>900)
start += delta;
lastState = state;
}
}
uint8_t ctr = 0; pullBits(&ctr,data+0,5);
uint8_t dir = 0; pullBits(&dir,data+5,4);
uint16_t spd = 0; pullBits(&spd,data+9,12);
uint8_t sum = 0; pullBits(&sum,data+21,4);
uint8_t ndir = 0; pullBits(&ndir,data+25,4);
ndir ^= 0x0f;
uint16_t nspd = 0; pullBits(&nspd,data+29,12);
nspd ^= 0x0fff;
uint8_t csum = 0x0f & (dir + (spd&0x0f) + ((spd>>4)&0x0f) + ((spd>>8)&0x0f));
if(ctr!=27) return false;
if(csum!=sum) return false;
if(spd!=nspd || dir!=ndir) return false;
speed = spd;
direction = dir;
return true;
}
bool LaCrosse_TX23::read(float &speed, uint16_t &direction)
{
uint16_t s;
uint8_t d;
bool ok = readRaw(s,d);
speed = s*0.1;
direction = d * 22.5;
return ok;
}
LaCrosse_TX23::RawData LaCrosse_TX23::readRaw()
{
LaCrosse_TX23::RawData data;
data.valid = readRaw(data.speed, data.direction);
return data;
}
LaCrosse_TX23::Data LaCrosse_TX23::read()
{
LaCrosse_TX23::Data data;
data.valid = read(data.speed, data.direction);
return data;
}