Ich hab hier einen Funk Sensor einer Sempre Wetterstation Meteotime der auf 433MHz sendet.
Übertragen wird die Temperatur und Luftfeuchte.
Ein Datenframe sieht so aus:
Es gibt 2 Pulsbreiten zu geben:
- 1ms
- 0.5ms
Gibts da schon eine Library zu?
Eine Bibliothek ist mir nicht über den Weg gelaufen, aber ein paar Infos: Außensensor der Sempre Wetterstation am Seitenende. Wäre ein Anfang ![]()
Ah danke, muss ich mir anschauen.
Das Protokoll sieht sehr nach diesem aus:
Mal schauen wie ich den Bitstrom am besten eingelesen bekomme.
dein Bild ist nicht vollständig, das kurze high am ende gefolgt von dem längeren low ist die Stasrtsequenz, danach folgt dein eigentliches Signal. Mach mal ein Bild mit Startsequenz am Anfang und Startsequenz am Ende. Dann brauchst du nur die Anzahl Bits (highs) zählen, und dem 1ms high / low die 1 oder die 0 zuordnen. Die kürzeren Signale 0,5ms sind dann 0 / 1. Das Signal wird immer mehrmals hintereinander gesendet.
Ich lese hiermit meinen Geber aus, der hat ein 36 bit Signal, die Timingbereiche für 0 und 1 stellst du unten ein (musst du ausmessen). Meist ist ein Wert Temp oder Luftfeuchte in 2 byte untergebracht.
Versuchsmal hiermit, du musst nur schauen wieviel bit dein Signal hat (ohne Startsequenz) und die Timingbereiche entsprechend anpassen.
Da solltest du schonmal binär was sehen können.
Du musst dann nur noch die Bereiche die die Werte enthalten ausfindig machen.
Meist ist ein Wert Temp oder Luftfeuchte in 2 byte untergebracht.
Den Sketch hab ich vor etlichen Jahren gefunden und für mich angepasst. Vielleicht hilft er dir.
// Funktemperatursensor auslesen Pearl NC-7159
// Anschlussbelegung
// Vin 9V / GND
// Pin2 RC, 5V, GND
// RX1 / TX1 an Mega
bool cnt = false;
byte reader = 0;
byte cnter = 0;
char reading[36];
unsigned int Atemp = 0; //Temperatur die an Mega uebergeben wird
byte vorz = 4; // 2 fuer minus Temp, 4 fuer plus Temp
byte datasend = 0; //Hilfsvariable zum uebertragen "1" alle Werte vollstaendig
byte chk = 0; //Geberkennung
byte LGoff = 2; //Schaltvariable LG aus
byte Atemp1 = 0;
byte Atemp2 = 0;
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
pinMode(2, INPUT);
}
void loop() {
int LowVal = pulseIn(2, LOW);
if (LowVal > 1500 &&
LowVal < 10000) { // Kuezer als 10000 Low koennte unserer Sensor sein
if (decodeTime(LowVal) == 'S') { // Startsequenz ?
cnt = true; // Dann go fuer die Sammlung
cnter = 0; // BitCounter auf 0
}
if ((cnter <= 35) && cnt &&
((decodeTime(LowVal) == '0') ||
(decodeTime(LowVal) == '1'))) { // Stream noch nicht voll und ein Bit erkannt
reading[cnter] = decodeTime(LowVal); // Ab ins Array damit
cnter = cnter + 1; // Arraycounter fuers naechste Bit inkrementieren
}
} else { // wenn nix los ist wird gesendet
cnt = false; // Zurueck auf Anfang - nix fuer uns.
if (chk == 5 || datasend == 1 && LGoff == 4) { //hier wird bei datasend 1 und Geberkennung 5 der Tempbereich, Temp und das Vorzeichen uebertragen
senden();
}
}
if ((cnter == 36)) { // Array Voll ?
Atemp = (decodeTemp(reading));
Serial.println(Atemp);
Atemp1 = byte(Atemp >> 8); // firstByte = höherwertig
Atemp2 = byte(Atemp & 0x00FF); // secondByte = niedrigerwertig
datasend = 1; //alle Werte komplett zum Uebertragen
cnter = 0;
cnt = false;
}
}
float decodeTemp(
String bitstream) { // Hier wird aus dem Bitstrom die Geberkennung, das Vorzeichen, der Tempbereich, die Temp. und das Vorzeichen gelesen
//Serial.println(bitstream);
//Serial.println(chk);
//Serial.println(LGoff);
unsigned int x = 0;
//Geberkennung
for (int i = 1; i < 4; i++) { // Geberkennung aus Bit 1 bis 3 holen
if (bitstream[i] == '1') {
bitSet(chk, (3 - i));
}
}
if (chk == 5) { // Geberkennung 5 geht fuer Pearl NC-7159
//Vorzeichen +/- lesen
// Vorzeichen aus Bit 16 bis 18 bei - Temp 1, bei + Temp 0
for (int i = 16; i < 18; i++) { // Vorzeichen aus Bit 16 bis 18
if (bitstream[i] == '1') {
vorz = 2; // fuer -
}
if (bitstream[i] == '0') {
vorz = 4; // fuer +
}
}
// Temperatur auslesen in Abhaengigkeit vom Vorzeichen (minus invertierte Bitfolge)
if (vorz == 2 && chk == 5) { // - Bereich
for (int i = 19; i < 28;
i++) { // Extrahiert Bit 19 - 27 und packt es als integer in "x"
if (bitstream[i] == '0') {
bitSet(x, (27 - i));
}
}
}
if (vorz == 4 && chk == 5) { // + Bereich
for (int i = 19; i < 28;
i++) { // Extrahiert Bit 19 - 27 und packt es als integer in "x"
if (bitstream[i] == '1') {
bitSet(x, (27 - i));
}
}
}
return ((unsigned int)x);
} else
if (chk == 6) {
LGoff = 4;
datasend = 1;
chk = 0;
return;
}
else {
chk = 0;
return;
}
}
char decodeTime(int time) { // Wandelt die Pulse in Bits um.
if (time > 1500 && time < 10000) { // passendes Signal (zwischen 1800 und 10000)
if (time > 1700 && time < 2100) { // kleiner 2000 dann LOW
return '0';
}
if (time > 3800 && time < 4100) { // Zwischen 3800 und 4100 dann HIGH
return '1';
}
if (time > 7000 && time < 11000) { // Groesser 7500 dann Startsequenz !
return 'S';
}
} else {
return 'X';
}
}
Mal ein erstes Ergebnis:
Mein erster 433 MHz receiver war sehr verrauscht. Aber ein SYN480R ist da sehr viel besser.
Der Code ist für ein Thinary Nano Board, sollte aber auch mit einem Arduino Nano Every gehen.
Ausgegeben werden die Anzahl der empfangenen und decodierten Bits.
Sieht dann so aus:
90: 111110010011010100011100111011110101110011000010000111000100100111111110000000011010111110
89: 11110010011010100011100111011110011110011000010000111000100100111111110000000101001011010
88: 1111001001101010001110011101111011011001100001000011100010010011111111000000000001110001
Also nicht immer die erwarteten 90 Bits...
const auto PIN = 5;
const auto BUFFER_SIZE = 32;
#define SERIAL Serial1
class Buffer {
public:
Buffer()
: _buffer_write_pointer(0), _buffer_read_pointer(0), _error(false) {}
bool available() {
return _buffer_write_pointer != _buffer_read_pointer;
}
uint16_t read() {
while (!available()) {
// wait for data
}
uint16_t ret = _buffer[_buffer_read_pointer];
auto new_p = _buffer_read_pointer + 1;
if (new_p >= BUFFER_SIZE) {
new_p = 0;
}
_buffer_read_pointer = new_p;
return ret;
}
void write(uint16_t value) {
_buffer[_buffer_write_pointer] = value;
_buffer_write_pointer++;
if (_buffer_write_pointer >= BUFFER_SIZE) {
_buffer_write_pointer = 0;
}
if (_buffer_write_pointer == _buffer_read_pointer) {
_error = true;
}
}
bool isError() {
return _error;
}
void resetError() {
_error = false;
}
private:
uint16_t _buffer[BUFFER_SIZE];
volatile uint8_t _buffer_write_pointer;
volatile uint8_t _buffer_read_pointer;
bool _error;
};
void error() {
while (1) {
SERIAL.println("Error");
}
}
void setup() {
SERIAL.begin(115200);
pinMode(PIN, INPUT_PULLUP);
uint8_t port0;
uint8_t port1;
switch (digitalPinToBitPosition(PIN)) {
case 0:
port0 = EVSYS_GENERATOR_PORT0_PIN0_gc;
port1 = EVSYS_GENERATOR_PORT1_PIN0_gc;
break;
case 1:
port0 = EVSYS_GENERATOR_PORT0_PIN1_gc;
port1 = EVSYS_GENERATOR_PORT1_PIN1_gc;
break;
case 2:
port0 = EVSYS_GENERATOR_PORT0_PIN2_gc;
port1 = EVSYS_GENERATOR_PORT1_PIN2_gc;
break;
case 3:
port0 = EVSYS_GENERATOR_PORT0_PIN3_gc;
port1 = EVSYS_GENERATOR_PORT1_PIN3_gc;
break;
case 4:
port0 = EVSYS_GENERATOR_PORT0_PIN4_gc;
port1 = EVSYS_GENERATOR_PORT1_PIN4_gc;
break;
case 5:
port0 = EVSYS_GENERATOR_PORT0_PIN5_gc;
port1 = EVSYS_GENERATOR_PORT1_PIN5_gc;
break;
case 6:
port0 = EVSYS_GENERATOR_PORT0_PIN6_gc;
port1 = EVSYS_GENERATOR_PORT1_PIN6_gc;
break;
case 7:
port0 = EVSYS_GENERATOR_PORT0_PIN7_gc;
port1 = EVSYS_GENERATOR_PORT1_PIN7_gc;
break;
default:
error();
}
uint8_t channel;
switch (digitalPinToPort(PIN)) {
case PA:
case PB:
channel = 0;
break;
case PC:
case PD:
channel = 2;
break;
case PE:
case PF:
channel = 4;
break;
default:
error();
}
if ((channel == 0) && (EVSYS.CHANNEL0 == 0)) {
EVSYS.CHANNEL0 = port0;
EVSYS.USERTCB0 = EVSYS_CHANNEL_CHANNEL0_gc;
} else if ((channel == 0) && (EVSYS.CHANNEL1 == 0)) {
EVSYS.CHANNEL1 = port1;
EVSYS.USERTCB0 = EVSYS_CHANNEL_CHANNEL1_gc;
} else if ((channel == 2) && (EVSYS.CHANNEL2 == 0)) {
EVSYS.CHANNEL2 = port0;
EVSYS.USERTCB0 = EVSYS_CHANNEL_CHANNEL2_gc;
} else if ((channel == 2) && (EVSYS.CHANNEL3 == 0)) {
EVSYS.CHANNEL3 = port1;
EVSYS.USERTCB0 = EVSYS_CHANNEL_CHANNEL3_gc;
} else if ((channel == 4) && (EVSYS.CHANNEL4 == 0)) {
EVSYS.CHANNEL4 = port0;
EVSYS.USERTCB0 = EVSYS_CHANNEL_CHANNEL4_gc;
} else if ((channel == 4) && (EVSYS.CHANNEL5 == 0)) {
EVSYS.CHANNEL5 = port1;
EVSYS.USERTCB0 = EVSYS_CHANNEL_CHANNEL5_gc;
} else {
error();
}
TCB0.CTRLA = 0; // Timer Disable
TCB0.CTRLB = 0x02; // Input capture mode
TCB0.EVCTRL = 0b01010001; // Filter, Falling Edge, Enable Capture event
TCB0.INTCTRL = 1; // Do ISR
TCB0.CTRLA = 1; // Timer Enable
SERIAL.println("Starting loop");
}
Buffer buffer;
ISR(TCB0_INT_vect) {
uint16_t value = TCB0.CCMP;
TCB0.EVCTRL ^= 0b00010000; // switch capture edge
buffer.write(value);
}
const uint16_t L1a = F_CPU / 1000000 * 750;
const uint16_t L1b = F_CPU / 1000000 * 1250;
const uint16_t L0a = F_CPU / 1000000 * 350;
const uint16_t L0b = F_CPU / 1000000 * 650;
uint16_t last = 0;
// 0 reset
// 1 rx finish
// 2 rx 0
uint8_t state = 0;
char rxBuf[100];
uint8_t rxBufWr = 0;
void loop() {
uint16_t value = buffer.read();
uint16_t dx = value - last;
last = value;
if (state != 2 && (dx > L1a && dx < L1b)) {
state = 1;
rxBuf[rxBufWr] = '1';
rxBufWr++;
} else if (state != 2 && (dx > L0a && dx < L0b)) {
state = 2;
} else if (state == 2 && (dx > L0a && dx < L0b)) {
state = 1;
rxBuf[rxBufWr] = '0';
rxBufWr++;
} else if (state != 0){
state = 0;
if(rxBufWr > 8)
{
SERIAL.print(rxBufWr);
SERIAL.print(": ");
SERIAL.write(rxBuf, rxBufWr);
SERIAL.println();
}
rxBufWr = 0;
}
if (rxBufWr >= sizeof(rxBuf))
{
rxBufWr = 0;
SERIAL.println("!!!");
}
}
Ahh... Das Projekt erkennt meinen Sensor als Hideki-TS04... Die Liste der implementierten Sensoren ist auch sehr lang: