 |
 |
View previous topic :: View next topic |
Author |
Message |
bulut_01
Joined: 24 Feb 2024 Posts: 214
|
|
Posted: Tue Feb 04, 2025 7:12 pm |
|
|
temtronic wrote: | find them again, maybe they have the receive code as well ! |
Unfortunately, I can't reach anyone from the old offline block, I have to solve this myself. |
|
 |
gaugeguy
Joined: 05 Apr 2011 Posts: 319
|
|
Posted: Wed Feb 05, 2025 7:18 am |
|
|
bulut_01,
Where did you get your repeated references to UART and KEELOQ from? |
|
 |
temtronic
Joined: 01 Jul 2010 Posts: 9431 Location: Greensville,Ontario
|
|
Posted: Wed Feb 05, 2025 7:20 am |
|
|
this line of code ...
delayMicroseconds(SYMBOL);
looks like Arudino C ??
If so a proper search might find it. |
|
 |
bulut_01
Joined: 24 Feb 2024 Posts: 214
|
|
Posted: Wed Feb 05, 2025 7:32 am |
|
|
temtronic wrote: | this line of code ...
delayMicroseconds(SYMBOL);
looks like Arudino C ??
If so a proper search might find it. |
yes arudio I need an algorithm to solve this |
|
 |
temtronic
Joined: 01 Jul 2010 Posts: 9431 Location: Greensville,Ontario
|
|
Posted: Wed Feb 05, 2025 7:36 am |
|
|
OK, go to some Ardunio forum ! Whoever wrote the transmitter code MUST have written a receiver code. Google returns 100s of hits for 'ardunio manchester' so if you have the authors name add that to reduce the number of hits. |
|
 |
temtronic
Joined: 01 Jul 2010 Posts: 9431 Location: Greensville,Ontario
|
|
Posted: Wed Feb 05, 2025 8:14 am |
|
|
where ?
from his 3rd post...
mcu 16f1824 rf module 433 mhz reading data receiving 10 byte data frame sending remote control keeloq manchester 1500 baund communication speed.
ccs c last version
....
hence the trips down various 'forks in the roads'.
It turns out it's for an RF device that has SOME of the data encoded in one of the Manchester formats. |
|
 |
bulut_01
Joined: 24 Feb 2024 Posts: 214
|
|
Posted: Wed Feb 05, 2025 8:21 am |
|
|
mr. temtronic What you said doesn't help me, actually my request is that there is a very simple sending algorithm and to solve it, create a decode algorithm. The answer to my question is very simple. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19739
|
|
Posted: Wed Feb 05, 2025 8:38 am |
|
|
The point is this is not a 'write it for you' forum, but one to help you to
write your own code.
This won't be right, but should be close:
Code: |
#include <16F1824.h>
#device ADC = 8
#FUSES NOWDT
#fuses PUT
#FUSES NOMCLR
#FUSES NOLVP
#FUSES STVREN
#FUSES NOIESO
#FUSES NOFCMEN
#FUSES NOWRT
#FUSES NODEBUG
#use delay(internal = 16M)
//Decoder for stream with header bytes followed by Mancester data
//The sequence of the data is signal starts low. Then 7 pulses of about 5mSec
//high/low, followed by the signal ending high and holding for 7.5mSec.
//Then a falling edge which marks the start clock edge of the data.
//Decoding ffrom here is standard Manchester, with 1/0 depending on whether
//the clock edges are in sync or out of sunc with the bit rate. Basic
//Manchester clock rate is about 400bps. So transitions are at twice this
//rate. 800Hz.
//Use INT_IOC to detect the edges, and Timer4 for timing. Want a sensible count
//per half bitm so run Timer4 off Fosc/16. 16MHz clock should give about 5000
//for the initial clocks, and 1250 for the individual edges.
//
enum states {HEADER, SYNC, DATA};
enum states state=Header;
#define CHANGE 1500 //Value below which to see as a half clock so phase change
#define SYNCPULSE 4800 //Value above which to see sync.
int8 rdat[10]; //data array to take the received bytes
int1 flag=0; //flag to trigger search for sync bytes.
int1 have_data=FALSE;
#INT_IOC
void edge(void)
{ //Edge detector
static int16 last=0;
static int16 delta, val;
static int8 ctr=0;
static int8 bit=128;
static int1 clock=0;
static int1 alternate=0;
int8 dummy;
dummy=input(PIN_A0); //read pin
clear_interrupt(INT_IOC_A0);
if (flag==0) //Start timing again
{
last=get_timer1(); //record first edge time
flag=1;
return;
}
val=get_timer1(); //get the current timer value
delta=val-last; //Now have delta from last edge
last=val; //and store for next time
switch (state) {
case HEADER:
//We keep retesting till the time exceeds SYNCPULSE time
if (delta>SYNCPULSE)
state++;
break;
case SYNC:
//get here we have seen a pulse over 6000 counts
//Next edge is the drop to matk the start of the data.
state++;
break;
case DATA:
//Now we are clocking in data. If the time is over 1500 clocks then we
//have a change otherwise we are in sync.
if(delta>CHANGE)
{ //Here we are in sync with the master bit clock
if (clock)
rdat[ctr]|=bit;
else
rdat[ctr]&=(bit^0xFF);
clock=!clock;
}
else
{
//here out of sync
if (clock)
rdat[ctr]&=(bit^0xFF);
else
rdat[ctr]|=bit;
if (alternate)
clock=!clock;
alternate=!alternate;
}
bit>>=1;
if (bit==0)
{
bit=128;
ctr++; //next byte
if (ctr==7)
{
ctr=0;
have_data=TRUE;
}
}
break;
}
}
void main()
{
int ctr;
setup_timer_1(T1_INTERNAL | T1_DIV_BY_4); //Gives FOSC/16
enable_interrupts(global);
enable_interrupts(INT_IOC_A0);
while (TRUE)
{
state=HEADER;
while (have_data==FALSE)
; //wait for data
//here deal with data
delay_cycles(1);
//set flag back to 0 to start search for next packet and set have_data
//to false.
}
}
|
The HANGE and SYNCPULSE constants may be wrong, since I just measured
from your displayed graphs. |
|
 |
bulut_01
Joined: 24 Feb 2024 Posts: 214
|
|
Posted: Wed Feb 05, 2025 9:24 am |
|
|
thank you mr Ttelmah I will test it as soon as possible |
|
 |
PrinceNai
Joined: 31 Oct 2016 Posts: 527 Location: Montenegro
|
|
Posted: Wed Feb 05, 2025 11:49 am |
|
|
I wrote something to decode your kind of data. It should work. There is also a code I used for test transmitter, copying pattern from one of your pictures. It will be attached at the end. I used 18f46k22 for this, so you'll need to change a couple of things. First thing is the location of INTDEG. Second thing is the number of DECODED bytes you expect. I only coded for 3.
Code: |
#include <18F46K22.h>
#device ADC=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOPUT
#device ICD=TRUE
#use delay(internal=32000000)
/////////////////////////// DEFINES /////////////////////////////////
#define NUMBER_OF_BYTES 3 // number of DECODED bytes to receive
#define TE 600 // duration of one bit in us, change as needed
#define PREAMBLE_MAX 8*TE
#define PREAMBLE_MIN 6*TE // we expect a 7 bit preamble, make some room for error
#define TRANSITION_MIN 1.5*TE // same here when sampling
#define TRANSITION_MAX 2.5*TE
////////////////////////// VARIABLES ////////////////////////////////
char DecodedInputData[10]; // buffer for decoded data
char CurrentByte = 0;
int8 ByteCounter = 0; // keeps track about which byte we are filling in
int8 BitPosition = 0; // bit position of the incoming data
int8 DataReceived = 0; // flag to inform main data was received and decoded
// switch
enum {GotRisingEdge = 1, GotFallingEdge, SampleData};
int8 DecodeSwitch = GotRisingEdge;
// Timer
int16 TimerValue;
int8 Overflow = 0; // how many times TMR0 has overflowed
////////////////////////// FUNCTIONS ////////////////////////////////
#bit INTDEG = getenv("BIT:INTCON2.INTEDG0") // declare edge selection bit for INT_EXT. INTDEG is a generic name (some PIC's have more than one of those registers,
void ToggleIntEdge (void){ // 18f46k22 has INTDEG0, for example) for external interrupt on Pin_B0. Change this for the PIC you use
if(INTDEG == 1){ // check which edge is currently selected
INTDEG = 0; // activate interrupt on falling edge
output_high(PIN_D6);
}
else{
INTDEG = 1; // activate interrupt on rising edge
output_low(PIN_D6);
}
}
// ------------------------------------------------------------------
void ClearBuffer (void){
DecodedInputData[0] = 0x00; // lazy :-)
DecodedInputData[1] = 0x00;
DecodedInputData[2] = 0x00;
}
//////////////////////// END OF FUNCTIONS //////////////////////////
// ******************************************************************
// INTERRUPTS
// ******************************************************************
#INT_TIMER0
void TIMER0_isr(void)
{
Overflow++; // count timer overflows
}
// ------------------------------------------------------------------
#INT_EXT
void EXT_isr(void)
{
clear_interrupt(INT_EXT); // clear interrupt, needed for this particular interrupt type or you come back straight away
//default handling, check if switch variable is out of usefull bounds
if (DecodeSwitch < 1 || DecodeSwitch > 3)
{
// printf("Default handling, testval is out of bounds, DecodeSwitch == %u\r\n", DecodeSwitch);
continue; //Miss switch. The continue statement causes the next iteration of the enclosing loop(While, For, Do) to begin.
}
// ******************************************************************
// ******************************************************************
switch (DecodeSwitch) // switch to receive and decode Mancester encoded data
{
// ------------------------------------------------------------------
// wait for a rising edge from the transmitter, this state also serves as a reset. Always come here with L_TO_H transition set!
case GotRisingEdge: // we have a rising edge, could be start of the preamble
{
set_timer0(0); // reset timer
Overflow = 0;
BitPosition = 0;
ByteCounter = 0;
CurrentByte = 0;
DataReceived = 0;
ext_int_edge(0, H_TO_L); // change direction of the interrupt to falling edge
DecodeSwitch = GotFallingEdge; // and go to GotFallingEdge to see if we have a preamble
break;
}
// ------------------------------------------------------------------
case GotFallingEdge: // we have a falling edge, so last transition was H_to_L
{
ext_int_edge(0, L_TO_H); // prepare for interrupt on a L_TO_H edge
TimerValue = get_timer0();
if(TimerValue > PREAMBLE_MIN && TimerValue < PREAMBLE_MAX) {// bingo, we have a preamble
set_timer0(0); // preset timer
Overflow = 0;
DecodeSwitch = SampleData; // go sampling the input
}
else{ // pulse was either too short or too long for a preamble.
DecodeSwitch = GotRisingEdge; // Reset state machine
}
break;
}
// ------------------------------------------------------------------
// We are looking for a transition that in Mancester coding always happen in the middle of a bit.
// That can either be the first transition, if two subsequent symbol have different value, or it can
// be the second transition, if two subsequent symbols have the same value. We are using timer reading
// to find out which one just occured. If it is the one we are looking for, sample the input and store
// to the correct location in the data buffer
// On start we come here on rising edge, meaning there was a transition 0-1
case SampleData:
{
ToggleIntEdge(); // change the active edge of the interrupt for sampling
TimerValue = get_timer0();
// check what kind of a transition we have. If the transition happened in
// a time frame of 0,5*TE to 1,5*TE it is considered that this bit has the same
// value as the previous and that we need to wait for another interrupt for the sampling
// time between two edges is correct, take sample. This test is intentionally in the first place
// so it gets serviced as fast as possible, since the timer is already running
if(Overflow == 0 && TimerValue >= TRANSITION_MIN && TimerValue <= TRANSITION_MAX){ // this is the one we are looking for, sample and store the data
set_timer0(0); // reset timer for the next pair
// REVERSE DECODING LOGIC AS NEEDED HERE!!!!! COMMENT THE WRONG IF OUT!!!!
if(input_state(pin_B0) == 0){
// if(input_state(pin_B0) == 1){
bit_set(CurrentByte, 7 - BitPosition); // sample. Set appropriate bit if needed, leave 0 otherwise
}
BitPosition++;
if(BitPosition > 7){ // one byte of data received
BitPosition = 0;
DecodedInputData[ByteCounter] = CurrentByte; // store the data into the buffer
CurrentByte = 0; // prepare variable for next byte
ByteCounter++; // increment byte counter for a correct position
if (ByteCounter == NUMBER_OF_BYTES){ // if all the bytes are in
ext_int_edge(0, L_TO_H);
DataReceived = 1; // signal that to main
DecodeSwitch = GotRisingEdge; // and reset state machine
} // if byte counter
} // if bit position
} // end sampling
// time between two edges too short for sampling, it may be transition between two symbols with the same value
else if(Overflow == 0 && TimerValue < TRANSITION_MIN){ // the transition came too soon for sampling, exit but stay in the same case
delay_cycles(1);
}
// time between two edges to long for a valid bit, reset
else{ // time between two transitions is too long,
ext_int_edge(0, L_TO_H);
DecodeSwitch = GotRisingEdge; // reset state machine
}
break;
} // end case
} // end switch
} // end interrupt
// ******************************************************************
// END OF INTERRUPTS
// ******************************************************************
void main()
{
ClearBuffer(); // clear receiving buffer
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8); // 65.535us, resolution 1us. RESOLUTION MUST BE 1us!!!!
clear_interrupt(INT_EXT);
ext_int_edge(0,L_TO_H);
enable_interrupts(INT_EXT);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
while(TRUE)
{
}
}
|
Transmitter:
Code: |
#include <18F46K22.h>
#device ADC=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES NOPUT
//#device ICD=TRUE
#use delay(internal=32000000)
#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3,force_hw)
// ******************************************************************
int8 k;
// buttons
#define MODE_switch PIN_B1
int8 active_state_MODE;
int8 previuos_state_MODE;
int8 MODE_switch_is_pressed = FALSE;
////////////////////////// FUNCTIONS ////////////////////////////////
// ------------------------------------------------------------------
void i (void){
// 1
output_high(PIN_B5);
delay_us(600);
output_low(PIN_B5);
delay_us(600);
}
// ------------------------------------------------------------------
void o (void){
// 0
output_low(PIN_B5);
delay_us(600);
output_high(PIN_B5);
delay_us(600);
}
// ------------------------------------------------------------------
void ReadModeButton(void){
// detect ModeButton, presumes 0 is read if the ModeButton is pressed.Debouncing part.
active_state_MODE = input_state(MODE_switch); // Read the button
if((previuos_state_MODE == 1) && (active_state_MODE == 0)){
MODE_switch_is_pressed = TRUE; // switch pressed, raise "MODE PRESSED" flag
} // must be cleared in software
previuos_state_MODE = active_state_MODE; // Save current value for next time
}
// ------------------------------------------------------------------
// bit 6 controls the active edge for INT_EXT
#bit INTDEG = getenv("BIT:INTCON2.INTEDG0") // declare edge selection bit for INT_EXT. INTDEG is a generic name (some PIC's have more than one of those registers,
void ToggleIntEdge (void){ // 18f46k22 has INTDEG0, for example) for external interrupt on Pin_B0. Change this for the PIC you use
if(INTDEG == 1){
INTDEG = 0; // check which edge is currently selected
}
else{
INTDEG = 1; // and change to the oposite edge
}
}
// ******************************************************************
#INT_TIMER0
void TIMER0_isr(void)
{
ReadModeButton();
}
// ------------------------------------------------------------------
void main()
{
output_low(PIN_B5);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); // 125ns cycle, 8 ms overflow
enable_interrupts(INT_TIMER0); // timer0 takes care of buttons and timings
enable_interrupts(GLOBAL);
while(TRUE)
{
//////
if(MODE_switch_is_pressed == TRUE){
MODE_switch_is_pressed = FALSE;
disable_interrupts(INT_TIMER0); // prevent button presses while sending
ToggleIntEdge();
// wait -------------------------------------------------------------
output_low(PIN_B5);
delay_ms(2000);
// sync -------------------------------------------------------------
for(k= 0; k < 5; k++){
output_high(PIN_B5);
delay_us(1800);
output_low(PIN_B5);
delay_us(1800);
}
// preamble ---------------------------------------------------------
output_high(PIN_B5);
delay_us(4200);
output_low(PIN_B5);
// leading 0
delay_us(600);
// data -------------------------------------------------------------
// byte1 ----------
// 1
i();
// 1
i();
// 1
i();
// 1
i();
// byte2 ----------
// 1
i();
// 1
i();
// 1
i();
// 1
i();
// byte3 ---------
// 0
o();
// 0
o();
// 0
o();
// 0
o();
// byte4 ---------
// 0
o();
// 0
o();
// 0
o();
// 0
o();
// byte5 ----------
// 0
o();
// 1
i();
// 0
o();
// 1
i();
// byte6 ----------
// 1
i();
// 0
o();
// 1
i();
// 0
o();
// pause ------------------------------------------------------------
output_low(PIN_B5);
delay_ms(500);
enable_interrupts(INT_TIMER0);
}
//////////////////
}
}
|
|
|
 |
bulut_01
Joined: 24 Feb 2024 Posts: 214
|
|
Posted: Fri Feb 07, 2025 12:25 pm |
|
|
mr. Ttelmah First of all, thank you for the code you wrote, but I made the settings and the code did not work. My bit size is 640 us, according to your ''change'' setting, it makes 640 x 2 = 1280 us, I made the setting accordingly, sync 2.5 ms x 7. I am publishing the code, I remembered it in the picture, where did I miss it ?
Last edited by bulut_01 on Mon Feb 24, 2025 1:42 pm; edited 2 times in total |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19739
|
|
Posted: Fri Feb 07, 2025 12:33 pm |
|
|
The sync width needed, is half way between the clock rate of the header
bits and the single bit that is the sync pulse.
The time needed for the CHANGE value is half way between the width of
a full clock bit and the half clock bits that happen when the signal is
changing from matching the Manchester clock and out of sync with the
clock. |
|
 |
bulut_01
Joined: 24 Feb 2024 Posts: 214
|
|
Posted: Fri Feb 07, 2025 1:16 pm |
|
|
Ttelmah wrote: | The sync width needed, is half way between the clock rate of the header
bits and the single bit that is the sync pulse.
The time needed for the CHANGE value is half way between the width of
a full clock bit and the half clock bits that happen when the signal is
changing from matching the Manchester clock and out of sync with the
clock. |
Where is the header duration in the code? I set change to 1250 as you said, I am making a mistake somewhere and the code is not working. |
|
 |
bulut_01
Joined: 24 Feb 2024 Posts: 214
|
|
Posted: Fri Feb 07, 2025 1:23 pm |
|
|
sync 1 bit 2500 us 2500 / 2 = ''change 1250'' is calculated as.
How do you calculate SYNCPULSE? |
|
 |
bulut_01
Joined: 24 Feb 2024 Posts: 214
|
|
Posted: Fri Feb 07, 2025 2:06 pm |
|
|
mr.Ttelmah Where am I making mistakes ? |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|