 |
 |
View previous topic :: View next topic |
Author |
Message |
bulut_01
Joined: 24 Feb 2024 Posts: 206
|
|
Posted: Sun Feb 09, 2025 12:01 pm |
|
|
PrinceNai wrote: | Quote: | you must have thought we were amateurs |
No, I don't :-). But since you are a bit on the stiff side with the information, I must ask. Must is a bit strong word, at this point I simply want to, because it really interests me. You mentioned all zeroes in the buffer. Fine. Does your code ever reach the point where it must write a one there? Does it increment counters, at least two of them? How can I know that without asking you? I have no idea about the equipment you use, save for the analyzer and the programming software. What are you debugging with? How? You never say: I did this, I tried that. Result is this. I know that my setup works. And it didn't work off the bat, far from it. But I went step by step. There is a diode blinking, so I know my PIC is alive. There was a breakpoint sitting in the first two states so I knew I could catch the preamble every time. Only after that I went to the decoding part. Drew a diagram of one byte and worked out the timings. Catching my own errors, both in code and in mental process. I prove to myself every time that the code does what you write, not what you think it should do. Those two things are seldom the same at the start.
Anyway, I was tinkering with the code since the version posted previously, so this is the last version:
Receiving part:
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 7 // number of DECODED bytes to receive
#define TE 640 // duration of one bit in us, change as needed
#define PREAMBLE_MAX_TIME 8*TE
#define PREAMBLE_MIN_TIME 6*TE // we expect a 7 bit preamble, make some room for clock error
#define TRANSITION_MIN_TIME 1.5*TE // same here when sampling
#define TRANSITION_MAX_TIME 2.5*TE
////////////////////////// VARIABLES ////////////////////////////////
char DecodedInputData[10]; // buffer for decoded data
char CurrentByte = 0;
int8 InputByteCounter = 0; // keeps track about which byte we are filling in
int8 BitPosition = 0; // bit position of the incoming data
int8 Have_Data = 0; // flag to inform main data was received and decoded
// switch
enum {GotRisingEdge = 1, GotFallingEdge, SampleData}; // state machine switch
int8 DecodeSwitch = GotRisingEdge;
// Timer
int16 TimerValue;
int8 TMR0_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
}
else{
INTDEG = 1; // activate interrupt on rising edge
}
}
// ------------------------------------------------------------------
void ClearBuffer (void){
DecodedInputData[0] = 0x00; // lazy :-)
DecodedInputData[1] = 0x00;
DecodedInputData[2] = 0x00;
DecodedInputData[3] = 0x00; // lazy :-)
DecodedInputData[4] = 0x00;
DecodedInputData[5] = 0x00;
DecodedInputData[6] = 0x00;
DecodedInputData[7] = 0x00;
DecodedInputData[8] = 0x00;
DecodedInputData[9] = 0x00;
}
//////////////////////// END OF FUNCTIONS //////////////////////////
// ******************************************************************
// INTERRUPTS
// ******************************************************************
#INT_TIMER0
void TIMER0_isr(void)
{
TMR0_Overflow++; // count timer TMR0_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) // state machine used to receive and decode Mancester encoded data
{
// ------------------------------------------------------------------
// wait for a rising edge on the input, this state also serves as a reset. Always come here with L_TO_H transition set (maybe not even needed)!
case GotRisingEdge: // we have a rising edge, could be start of the preamble
{
set_timer0(0); // reset timer
TMR0_Overflow = 0; // and various counters
BitPosition = 0;
InputByteCounter = 0;
CurrentByte = 0;
Have_Data = 0; // and flags
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, pulse ended. Might be preamble.
{
ext_int_edge(0, L_TO_H); // prepare next interrupt on a rising edge
TimerValue = get_timer0(); // check the time that elapsed between two interrupts
if(TMR0_Overflow == 0 && TimerValue > PREAMBLE_MIN_TIME && TimerValue < PREAMBLE_MAX_TIME) { // bingo, time is good, we have a preamble
set_timer0(0); // preset timer for next measurement
TMR0_Overflow = 0;
DecodeSwitch = SampleData; // and go sample the input
}
else{ // not good, 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 exist in the middle of a symbol,
// so the sampling is done every 2TE. That can be on the first or second following interrupt,
// depending on whether two subsequent symbols have the same or different value.
// We are using TMR0 value to find if it is time to sample. If it is, sample the input and store
// to the correct location in the data buffer.
// The word symbol means a 2-bit pair that represents either a 1 or a 0.
case SampleData:
{
ToggleIntEdge(); // change the active edge of the interrupt for the next one,
// because transition can be either 0-1 or 1-0, but hardly
// 0-0 or 1-1
TimerValue = get_timer0();
// If this interrupt occured in a time frame from 0,5*TE to 1,5*TE, this symbol has the same
// value as the previous, meanng that interrupt occured also at the start of the symbol, not only in the middle.
// So we need to wait for the next interrupt that will come at the middle of a symbol to actually sample data
// Time between two edges is correct, read input state. This test is intentionally put in the first place
// so it gets serviced first, since the timer is already running for the next symbol
if(TMR0_Overflow == 0 && TimerValue >= TRANSITION_MIN_TIME && TimerValue <= TRANSITION_MAX_TIME){ // this is the one we are looking for, sample and store the data
set_timer0(0); // reset timer for the next symbol
// INVERT THE DECODING LOGIC AS NEEDED HERE!!!!! COMMENT THE WRONG IF OUT!!!! LIKE THIS WORKS FOR IEEE 802 CODING, 01 IS 1, 10 IS 0
// if(input_state(pin_B0) == 0){
if(input_state(pin_B0) == 1){
bit_set(CurrentByte, 7 - BitPosition); // Sample input. Set appropriate bit if needed, leave 0 otherwise
} //
BitPosition++;
if(BitPosition > 7){ // one byte of data was received
BitPosition = 0;
DecodedInputData[InputByteCounter] = CurrentByte; // store that data into the buffer
CurrentByte = 0; // prepare variable for next byte (all zeroes, since we are only setting the bits needed)
InputByteCounter++; // increment byte counter for a correct position in the buffer
if (InputByteCounter == NUMBER_OF_BYTES){ // if all the bytes are in the buffer, reception is done
ext_int_edge(0, L_TO_H);
Have_Data = 1; // we have data, signal that to main
DecodeSwitch = GotRisingEdge; // and reset state machine for the next reception
} // if byte counter
} // if bit position
} // end sampling
// time between two edges is too short for sampling, it may be transition between two symbols with the same value
else if(TMR0_Overflow == 0 && TimerValue < TRANSITION_MIN_TIME){ // the transition came too soon for sampling, exit interrupt but leave
delay_cycles(1); // the timer running and stay in the same case
}
// time between two edges to long for a valid symbol, reset
else{ // time between two transitions was 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)
{
if(Have_Data == 1){
Have_Data = 0; // do something with data
}
}
}
|
|
16F1824 register not
Code: | #bit INTDEG = getenv("BIT:INTCON2.INTEDG0") |
|
|
 |
PrinceNai
Joined: 31 Oct 2016 Posts: 527 Location: Montenegro
|
|
Posted: Sun Feb 09, 2025 12:17 pm |
|
|
It can't, that is where this bit is located on 18f46k22. I wrote in one of the previous posts that you'll have to find that bit for your PIC. Yours is in the OPTION_REG, bit 6. Page 176 of datasheet.
So: #bit INTDEG = getenv("BIT:OPTION_REG.INTEDG")
I just noticed there is a typo in my program here (should be #bit INTEDG). Use this the way it is written here. |
|
 |
temtronic
Joined: 01 Jul 2010 Posts: 9426 Location: Greensville,Ontario
|
|
Posted: Sun Feb 09, 2025 12:56 pm |
|
|
CURIOUS... I see ICD=TRUE....
Is there a possibility that that can cause problems ? I've never used it but know that building in 'debug' and trying to run in the Real World doesn't work. |
|
 |
PrinceNai
Joined: 31 Oct 2016 Posts: 527 Location: Montenegro
|
|
Posted: Sun Feb 09, 2025 1:07 pm |
|
|
Never had a problem or noticed any difference so far. I also never checked if the .hex is different with that option enabled. Did a quick build with it turned off now and the .hex size stays the same.
In this particular case the receiving PIC is in debug mode for testing purposes. |
|
 |
bulut_01
Joined: 24 Feb 2024 Posts: 206
|
|
Posted: Sun Feb 09, 2025 2:47 pm |
|
|
PrinceNai wrote: | Never had a problem or noticed any difference so far. I also never checked if the .hex is different with that option enabled. Did a quick build with it turned off now and the .hex size stays the same.
In this particular case the receiving PIC is in debug mode for testing purposes. |
What hardware do you use to debug? Pickit 3 or icd3 |
|
 |
PrinceNai
Joined: 31 Oct 2016 Posts: 527 Location: Montenegro
|
|
Posted: Sun Feb 09, 2025 3:10 pm |
|
|
Pickit3.
Below is the comparison between two streams you sent, 44 and 55. Green portions were the same for both.
https://ibb.co/B2MpDfh0 |
|
 |
bulut_01
Joined: 24 Feb 2024 Posts: 206
|
|
Posted: Wed Feb 12, 2025 6:08 am |
|
|
PrinceNai wrote: | Pickit3.
Below is the comparison between two streams you sent, 44 and 55. Green portions were the same for both.
https://ibb.co/B2MpDfh0 |
Your code is not working. The reason is that all timers in 16f1824 are not overflowed by 1 us. When I debug, timer0 is overflowed by 32 us. You need to edit your code according to the timer overflow of 32 us. |
|
 |
temtronic
Joined: 01 Jul 2010 Posts: 9426 Location: Greensville,Ontario
|
|
Posted: Wed Feb 12, 2025 6:57 am |
|
|
Please post your latest code |
|
 |
bulut_01
Joined: 24 Feb 2024 Posts: 206
|
|
Posted: Wed Feb 12, 2025 7:08 am |
|
|
temtronic wrote: | Please post your latest code |
Last edited by bulut_01 on Mon Feb 24, 2025 1:43 pm; edited 1 time in total |
|
 |
PrinceNai
Joined: 31 Oct 2016 Posts: 527 Location: Montenegro
|
|
Posted: Wed Feb 12, 2025 7:47 am |
|
|
Code: | setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); |
will not produce 1us Timer0 step with 32MHz clock. Check Timer0 setup in my code. |
|
 |
temtronic
Joined: 01 Jul 2010 Posts: 9426 Location: Greensville,Ontario
|
|
Posted: Wed Feb 12, 2025 8:03 am |
|
|
clock is 32Mhz
input to Timer0 is Fosc/4, so 32/4 = 8Mhz
Timer0 prescaler is '1' , so /2 = 4Mhz
1/4,000,000 = .00000025
not to sure how you calculate 32 useconds
Last edited by temtronic on Wed Feb 12, 2025 8:06 am; edited 1 time in total |
|
 |
bulut_01
Joined: 24 Feb 2024 Posts: 206
|
|
Posted: Wed Feb 12, 2025 8:06 am |
|
|
PrinceNai wrote: | Code: | setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); |
will not produce 1us Timer0 step with 32MHz clock. Check Timer0 setup in my code. |
Your code is exactly the same, where do I check? |
|
 |
bulut_01
Joined: 24 Feb 2024 Posts: 206
|
|
Posted: Wed Feb 12, 2025 8:09 am |
|
|
PrinceNai wrote: | Code: | setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); |
will not produce 1us Timer0 step with 32MHz clock. Check Timer0 setup in my code. |
16f1824 timer0 is 8 bit. you need 16 bit counter timer1 is 16 bit. 1 us overfloaw does not work |
|
 |
temtronic
Joined: 01 Jul 2010 Posts: 9426 Location: Greensville,Ontario
|
|
Posted: Wed Feb 12, 2025 8:15 am |
|
|
so you have to change to another timer !!!
you have timers 1, 2 4, 6 on the t PIC with 16 bit counters.... |
|
 |
PrinceNai
Joined: 31 Oct 2016 Posts: 527 Location: Montenegro
|
|
Posted: Wed Feb 12, 2025 8:16 am |
|
|
Then use Timer1. Change all references from Timer0 to Timer1. Mind you, overflow isn't 1us. Timer increments by 1 in 1us. Overflow is 65ms |
|
 |
|
|
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
|