Skocz do zawartości

Reverse engineering stacji pogodowej a dekodowanie danych


_LM_

Pomocna odpowiedź

Jakiś czas (no to mało powiedziane bo stacja już jest rok u mnie 👹) temu kolega poprosił mnie o przerobienie stacji pogodowej tak aby mogła wysyłać dane do internetu. Stacja to popularny hyundai 3080 r wind. W pierwszej kolejności zrobiłem konwerter który przechwytywał dane z czujnika opadów, prędkości i kierunku wiatru. Tak to wyglądało:

1618492714258.thumb.jpg.f8ed80e107b6483d914c1e6e4f8cc886.jpg

I jakoś działało tyle że ja nie byłem zadowolony z dodatkowej płytki a poza tym i tak musiałem użyć dodatkowych czujników do temperatury i reszty parametrów. Stacja musiała swoje odleżeć i od niedawna powróciłem do projektu. Postanowiłem przyjżeć się pcb i podłączyć do sygnału który jest wysyłany w eter (część zewnętrzna nadaje do bazy na 868Mhz). Okazuje się że jako nadajnik pracuje jakiś układ w rodzaju cmt2117 dane są wysyłane do niego po jednej linii. Badanie oscyloskopem wykazało że jedna paczka to 88bitów czasami wysyłana jest jedna paczka czasem dwie pod rząd ale dane są identyczne.

Oto widok jednego rekordu danych(żółty przebieg)

1618492735238.thumb.jpg.43c5fd41408fa8cee9583176ff5c6d61.jpg

W powiększniu:

1618492740232.thumb.jpg.9c6b6d9a445eac747b5e6e2642fc5d0e.jpg 

to co widzimy to pierwszy bajt o wartości 0. Napisałem program do dekodowania tego co się aktualnie wysyła

/*
 * main.c
 *

 */

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include "MK_MULTI_UART/mk_multi_uart.h"


//volatile uint8_t frame_end;
volatile uint8_t bitCount;
volatile uint8_t nBits;
volatile uint8_t ramka[11]; // 88b/8
//volatile uint8_t bit;
volatile uint8_t timer;
volatile uint8_t offset;
volatile uint8_t idx;

int main(void){

	uart_init();
    DDRC |= (1<<PC2);
    DDRC |= (1<<PC1);
    PORTC|= (1<<PC3);
    PORTD|=(1<<PD2);
    //TCCR1B|=(1<<ICES1);			// zbocze narastajace
TCCR0|= (1<<CS00) | (1<<CS02);  // f/1024
TCCR0|= 1<<WGM01;
TIMSK|= 1<<OCIE0;
//TIMSK|= 1<<TOIE0;
OCR0 = 20;
MCUCR|=(1<<ISC01)|(1<<ISC00);
GICR|=1<<INT0;

sei();
uart_puts(0, "Start");



for(;;){

	if(bitCount == 1){
GICR&=~(1<<INT0); // blokowanie przerwania
		uart_puts(0, "Nbit: ");
		uart_putint(0, nBits, 10);
		uart_puts(0,"\n\r");
/*
	uart_puts(0,"DANE char: ");
	for(uint8_t i = 0; i < 11; i++){
		uart_putc(0, ramka[i]);
	//	uart_puts(0,"  ");
	}
	uart_puts(0,"\n\r");
	*/
	uart_puts(0,"DANE int: ");
	for(uint8_t i = 0; i < 11; i++){
		uart_putint(0, ramka[i],10);
	     uart_puts(0,"|");
	}
	uart_puts(0,"\n\r");

for(uint8_t i = 0; i< 11; i++){
	ramka[i]=0;
}
idx = 0;
offset = 0;
	nBits = 0;
GICR|= (1<<INT0);
	//memset(&ramka,0,sizeof(ramka));
	}

	if(!timer){
	timer = 100;
	}
  }
}

ISR(TIMER0_COMP_vect) { // przerwanie co 1ms

PORTC&=~(1<<PC2);
PORTC^=(1<<PC1);
if(bitCount == 3){
	uint8_t bit = 0;
	bit = PIND & 1<<PD2;

	bit <<= offset;
   ramka[idx] |= bit;



	offset++;
	if (offset > 7) {
		offset = 0;
		idx++;
	}
	if (idx > 10){

		idx = 0;
	}
}
	if (timer)
		timer--;
	if (bitCount)bitCount--;

}


ISR(INT0_vect){
TCNT0 = 0; // synchronizacja
	bitCount = 3;
	PORTC|= 1 << PC2;
	nBits++;
}

No i teraz potrzebuję pomocy przy dekodowaniu poszczególnych danych w terminalu wygląda to tak:

dla temperatury 23.9C Wilgotności 51% kierunku wietru E

DANE int: 0|104|208|4|204|252|252|252|212|124|212|
Są to poszczególne bajty zebrane w tablicy pierwsze dwa zawsze mają tą samą wartość, kolejne zmieniają się ze zmianami temperatury i wilgotności, ostatnie zmieniają się zarówno przy zmianie kierunku wiatru jak i przy zmianie wilgotności.

dla porównania inna paczka:

dla temperatury 33.0C Wilgotności 27% kierunku wiatru E

DANE int: 0|104|208|48|28|252|252|252|212|124|68

24.1C 31% E

DANE int: 0|104|208|136|236|252|252|252|212|124|140

Mniej więcej widać w którym miejscu dane ulegają zmianom... No i tutaj prośba do umysłów analitycznych jak to ugryźć? Mówiąc prezyzyjniej szukam sposobu aby na powrót odzyskać to co pokazuje stacja bazowa

 

 

 

Edytowano przez _LM_
  • Lubię! 1
Link do komentarza
Share on other sites

(edytowany)

Update: Zrobiłem funkcję która wyświetla wartości bitowe z tablicy uzyskałem następujące wynik przy obracaniu czujnikiem kierunku wiatru:

E	0000000000010110000010110010000000110011001111110011111100111111001010110011111000000110
S	0000000000010110000010110010000000110011001111110011111100111111001010110011110100011001
W	0000000000010110000010110010000000110011001111110011111100111111001010110011110000101000
N	0000000000010110000010110010000000110011001111110011111100111111001010110011111100110111
NE	0000000000010110000010110010000000110011001111110011111100111111001010110011111100101111
SE	0000000000010110000010110010000000110011001111110011111100111111001010110011111000011110
SW	0000000000010110000010110010000000110011001111110011111100111111001010110011110100000001
NW	0000000000010110000010110010000000110011001111110011111100111111001010110011110000110000
NE	0000000000010110000010110010000000110011001111110011111100111111001010110011111100101111

Wygląda jakby kierunek był kodowany na ostatnich 6bitach nie jestem pewien czy w czasie pomiaru nie zmieniła się wartość temperatury

Edytowano przez _LM_
Link do komentarza
Share on other sites

Głupio tak do siebie pisać xD ok więc dokonałem kolejnych pomiarów ogrzałem czujnik 

    	00000000 00010110000010110010000000110011001111110011111100111111001010110011111100 101111   23.7 50
        00000000 00010110000010110001110000110011001111110011111100111111001010110011111100 101100   25.5 48
        00000000 00010110000010110001110000110100001111110011111100111111001010110011111100 100110   25.3 47

Kierunek nie został zmieniony a na ostatnich bitach widać zmianę 

Link do komentarza
Share on other sites

Zastanawiam się czy jest tutaj użyty jakiś kod nadmiarowy bo w rzadną stronę nie mogę dopasować danych. Szukam teraz materiałów o sumach kontrolnych więc pytanie laika: czy crc może modyfikować przesłane dane czy tylko jest dopisywane do pakietu? 

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

8 minut temu, _LM_ napisał:

Czy suma crc powinna być dodana na początku czy na końcu ramki?

Na to nie ma reguły. Przykładowo - pakiet TCP ma sumę kontrolną przed danymi, ale nie na początku pakietu.

Link do komentarza
Share on other sites

(edytowany)

OK temat można zamknąć problem rozwiązany. Pomogła ta strona dzięki temu mogłem napisać program który poprawnie odczytuje kolejne bity danych. Dalej tego kodu nie rozwijam gdyż i tak ma powstać wersja na esp. Dla zainteresowanych kod programu oczywiście należy dodać swoją bibliotekę do uart. 

/*
 * main.c

 */
//atmega32 16Mhz
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "MK_MULTI_UART/mk_multi_uart.h"


volatile uint8_t idx;
volatile uint8_t frameEnd;
volatile uint16_t buf2[88];


int main(void){
	uart_init();
	PORTB|=(1<<PB0);
	DDRB|=(1<<PB1);
	PORTD|=(1<<PD6); // icp
	TCCR1B|=(1<<CS11); // f/8 = 2Mhz = 1imp = 500nS
	DDRC |= (1<<PC2);
	TCCR1B|=(1<<ICES1); // capture to rising
	TIMSK|=(1<<TICIE1);
	//TIMSK|=(1<<TOIE1);// overflow
	sei();
uart_puts(0, "Start");

	for(;;)
	{
if(frameEnd){
	for(uint8_t i = 0; i<88;i++){
		//uart_putint(0, buf2[i], 10);
		if(buf2[i] > 900 && buf2[i] < 1000){
			uart_puts(0,"1");
		}
		if(buf2[i] > 2500 && buf2[i] < 3500){
			uart_puts(0,"0");
		}
	}
	uart_puts(0,"\r\n");
frameEnd = 0;
}
}
}


ISR(TIMER1_CAPT_vect){ // przechwyt

 if(TCCR1B & (1<<ICES1)){
	 TCNT1 = 0;
 TCCR1B &=~(1<<ICES1);
 }else{
	TCCR1B|=(1<<ICES1);
	buf2[idx] = ICR1;
	idx++;
	if(idx > 87){
		idx = 0;
		frameEnd = 1;
	}
 }
}

ISR(TIMER1_OVF_vect){ // przepelnienie
	frameEnd = 1;
idx = 0;
	//	TCCR1B|=(1<<ICES1); // capture to rising
//	TCCR1B&=~(1<<CS11); // stop timer
//	TIMSK&=~(1<<TOIE1);// overflow
}

 

Edytowano przez _LM_
  • Lubię! 1
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.