CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

rs232 LED BLINK pıc-to-pıc communication
Goto page Previous  1, 2, 3, 4, 5, 6  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
PrinceNai



Joined: 31 Oct 2016
Posts: 480
Location: Montenegro

View user's profile Send private message

PostPosted: Wed Mar 29, 2023 4:58 am     Reply with quote

Use interrupt on a receiving side. Sooo much easier. Hook your Pickit. Check the received data with it. Or at least use a blinking LED to see if you even arrive to the interrupt.
gaugeguy



Joined: 05 Apr 2011
Posts: 303

View user's profile Send private message

PostPosted: Wed Mar 29, 2023 6:21 am     Reply with quote

These modules can work well when used as intended. The receiver does hear the first few pulses sent. The preamble might be 16 pulses at 50% duty cycle and the receiver may only pass the last 14 or so through depending on background noise. After the preamble is a slight delay before data is sent. The data is most commonly on off keyed PWM or manchester. You want a lot of high low transitions to keep the data link synchronized. Too long of a pause or too many 0's in a row and the link will have to resynchronize and some bits are lost. If the bit rate is too high the data will not go through. If the bit rate is too low then the module will loose sync and drop out.
PrinceNai



Joined: 31 Oct 2016
Posts: 480
Location: Montenegro

View user's profile Send private message

PostPosted: Wed Mar 29, 2023 7:06 am     Reply with quote

I use HC-12 modules. Works OK, range is good.
Khansokhua



Joined: 06 Nov 2021
Posts: 92

View user's profile Send private message

PostPosted: Wed Mar 29, 2023 7:45 am     Reply with quote

Code:
while(TRUE)
   {
      distance=HCSR04_get_distance();
           
      send_preamble();
      putc(distance); //To take the data into the send_preamble() function will be more efficient?
     
   }

It really works. Not rach yet, I guess it can be more impressive. Thank you Mr. temtronic for your unrequited knowledge sharing and thank you to other individuals.
Code:
void send_preamble()
{
    int i;
    for(i=0;i<5;i++)
    {     
        putc(0x55);
    }
 
      int l;                     // What can I try differently?
    for(l=0;l<5;l++)
    {     
        putc(0x00);
    }
    int k;
    for(k=0;k<5;k++)
    {     
        putc(0xFF);
    }
     
     
}


Is my baud rate OK? or must take a try for different values?
Code:
#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=SPIC,errors)
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Mar 29, 2023 8:30 am     Reply with quote

Maybe use the preamble in the 2nd link ??
It worked for him..
PrinceNai



Joined: 31 Oct 2016
Posts: 480
Location: Montenegro

View user's profile Send private message

PostPosted: Wed Mar 29, 2023 11:03 am     Reply with quote

This function would send your data with a preamble and markers. Of course you need a matching function to extract that data on the other side. The point of preamble is to somehow wake up the receiver. Those bytes can be lost, so you can't count how many bytes you've received so far and after that presume that next one is your data. One possible way is to use a known character or a sequence of them to indicate when something useful will come in and when it has ended. That way you can to some degree be sure that what you have is what was sent. Character U is used as a preamble because it alternates between 0 and 1, to prevent any saturation of the receiver.
Code:

void SendData(int8 Payload){
   int i;
   for(i=0;i<8;i++){
      fputc('U', SPIC);                                       // preamble. U (ASCII) is used because in binary it is 01010101 
   }
   fputc('#', SPIC);                                          // start marker #
   fputc(Payload, SPIC);                                      // actual data
   fputs("&\n\r", SPIC);                                      // end marker &
}


You call this with: SendData(distance);
PrinceNai



Joined: 31 Oct 2016
Posts: 480
Location: Montenegro

View user's profile Send private message

PostPosted: Wed Mar 29, 2023 5:21 pm     Reply with quote

And a matching code to decipher that on the receiving end:
Code:

// declare some variables at the start for this to work
char Tmp;                                                      // serial data is recorded here
int8 ReceivedData;                                             // received data will be found here
int1 TransmissionOK = 0;                                       // flag for main(), initialized to 0
int8 PARSE = 0;                                                // switch variable, initialized to 0
// all global to enable easier debugging vith Pickit3


// *********************************************************
// *********************************************************
#INT_RDA
void  RDA_isr(void)
{
   Tmp = getc();
 
   switch (PARSE){
     
// You stay in case 0 until # comes along. Everything else is
// ignored at this point. Preamble too, of course.     
       
// ----------- waiting for # or start marker ---------------
// ignore everything else, just sit tight and wait for #             
      case 0:{
        if(Tmp == '#'){                                        // we have "#"
            PARSE = 1;                                         // expecting distance data in the next byte
         delay_cycles(1);
      }
         else{
            PARSE = 0;                                         // else statement is not needed, but it is easier to read
       }
         break;
      }   
// -------------- waiting for distance data ----------------             
      case 1:{                                                 // # was received, save distance info
         ReceivedData = Tmp;                                   // expecting end marker in next byte
         PARSE = 2;
       delay_cycles(1);
         break;
      }           
// --- waiting for &  or end marker in other words ---------           
      case 2:{
         if(Tmp == '&'){                                       // we got "&", parsing is complete, data is good. Inform main via TransmissionOK flag.
            TransmissionOK = 1;                                // Valid data is stored in ReceivedData variable. Clear the flag it in main().
         delay_cycles(1);
       }
         else{
            TransmissionOK = 0;                                // & didn't arrive. Abort. This else statement is not needed, it is here to explain the logic
       }
         PARSE = 0;                                            // Good or bad data, go waiting for the next '#'     
         break;
      }
// ---------------------------------------------------------             
   }        // switch
}           // end interrupt RDA_isr

// *********************************************************
// *********************************************************

void main(void)
{
   while(true)
   {
      if(TransmissionOK == 1)                            // RDA_isr informed us we have new data in ReceivedData variable
     {
       delay_cycles(1);
         TransmissionOK = 0;                           // clear flag
       // do whatever you want with your data   now    
     }      
   }   
}


Those delay_cycles(1) are there if you decide to use a debugger to see what is going on :-)
Khansokhua



Joined: 06 Nov 2021
Posts: 92

View user's profile Send private message

PostPosted: Thu Mar 30, 2023 8:30 am     Reply with quote

Greetings Smile

As my teacher said ignore the problems doesn't solve them.Anyway Very Happy

I use 2xPIC16F877A, tx-rx rx-tx wired.

I use 8 bit ADC and control 8 different LED with a potentiometer.
When it comes to accomplish it using RS-232.Only at max value(255=LED8) a single LED is high.In the case of read adc value, except value 255, all 8 LEDs blinks simulteneaously.How can I overcome this situation ?I want this be the same like first.

RX header file

Code:
#include <16F877A.h>
#device ADC=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOPROTECT                //Code not protected from reading

#device ICD=TRUE
#use delay(crystal=20000000)
#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=SPIC,errors)
#use STANDARD_IO( B )
#use FIXED_IO( B_outputs=PIN_B7,PIN_B6,PIN_B4,PIN_B3,PIN_B2,PIN_B1,PIN_B0 )
#define LED1   PIN_B0
#define LED2   PIN_B1
#define LED3   PIN_B2
#define LED4   PIN_B3
#define LED5   PIN_B4
#define LED6   PIN_C0
#define LED7   PIN_B6
#define LED8   PIN_B7




RX
Code:
#include <ADC_8LED.h>
int8 led_value;
void main()
{
      /* setup_adc_ports(AN0);
       setup_adc(ADC_CLOCK_DIV_32);
       set_adc_channel(0);
       delay_us(20);*/
 
   while(TRUE)
   {
          // led_value=read_adc();
             
           led_value=getc();
           
           if(led_value>=0 && led_value<=32){
           output_high(LED1);
           output_low(LED2);
           output_low(LED3);
           output_low(LED4);
           output_low(LED5);
           output_low(LED6);
           output_low(LED7);
           output_low(LED8);            }
           if(led_value>=33 && led_value<=65){
           output_low(LED1);
           output_high(LED2);
           output_low(LED3);
           output_low(LED4);
           output_low(LED5);
           output_low(LED6);
           output_low(LED7);
           output_low(LED8);            }
           if(led_value>=66 && led_value<=98){
           output_low(LED1);
           output_low(LED2);
           output_high(LED3);
           output_low(LED4);
           output_low(LED5);
           output_low(LED6);
           output_low(LED7);
           output_low(LED8);            }
           if(led_value>=99 && led_value<=131){
           output_low(LED1);
           output_low(LED2);
           output_low(LED3);
           output_high(LED4);
           output_low(LED5);
           output_low(LED6);
           output_low(LED7);
           output_low(LED8);            }
           if(led_value>=132 && led_value<=164){
           output_low(LED1);
           output_low(LED2);
           output_low(LED3);
           output_low(LED4);
           output_high(LED5);
           output_low(LED6);
           output_low(LED7);
           output_low(LED8);            }
           if(led_value>=165 && led_value<=197){
           output_low(LED1);
           output_low(LED2);
           output_low(LED3);
           output_low(LED4);
           output_low(LED5);
           output_high(LED6);
           output_low(LED7);
           output_low(LED8);            }
           if(led_value>=198 && led_value<=229){
           output_low(LED1);
           output_low(LED2);
           output_low(LED3);
           output_low(LED4);
           output_low(LED5);
           output_low(LED6);
           output_high(LED7);
           output_low(LED8);            }
           if(led_value>=230 && led_value<=255){
           output_low(LED1);
           output_low(LED2);
           output_low(LED3);
           output_low(LED4);
           output_low(LED5);
           output_low(LED6);
           output_low(LED7);
           output_high(LED8);            }
           
           
   }

}


TX header file
Code:
#include <16F877A.h>
#device ADC=8

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOPROTECT                //Code not protected from reading

#device ICD=TRUE



TX
Code:
#include <adc_send_LED.h>
#use delay(crystal=20000000)
#use rs232(baud=4800,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=SPIC,errors)

int8 adc_led=0;
void main()
{
       setup_adc_ports(AN0);
       setup_adc(ADC_CLOCK_DIV_32);
       set_adc_channel(0);
       delay_us(20);

   while(TRUE)
   {
      adc_led=read_adc();
     
      putc(adc_led);
   }

}
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Mar 30, 2023 9:20 am     Reply with quote

at the very minimum, you need to add code for the following

1) connect the TXD of the RX PIC to a TTL<>USB module and send the received data to a PC terminal program.
you NEED this to VERIFY that the incoming data is true

2) have the TX PIC send KNOWN data at a1 Hz rate, to VERIFY the correct data IS being sent and received

3) delete the #USE_FIXED_IO(). let the compiler handle the DDRs as needed ! In 25+ years I've only needed fixed_io for 2 project, both had very,very tight timing requirements, you don't !!
PrinceNai



Joined: 31 Oct 2016
Posts: 480
Location: Montenegro

View user's profile Send private message

PostPosted: Thu Mar 30, 2023 10:15 am     Reply with quote

You sure don't like interrupts :-). Your style of coding, I guess, but you are only making it harder for yourself. Two things, the first is to shorten the code. If you have all of LEDs on the same port, use output_x(pattern) instead of writing 8 statements for 8 LEDs. The second one concerns ICD. If you can, move those diodes to PortD to be able to use output_x(). The reason for this is that it is best to leave ICD lines free. If you won't use output_x, move just two diodes away from PIN_B6 and PIN_B7.
PrinceNai



Joined: 31 Oct 2016
Posts: 480
Location: Montenegro

View user's profile Send private message

PostPosted: Thu Mar 30, 2023 10:34 am     Reply with quote

Also, Mr. Temtronic is right. Maybe I missed that post, but so far I haven't seen that you confirmed your receiving routines work. Concentrate on that, all your assignments depend on that (very short, very easy) piece of code. I posted two or three examples in this thread that WORK. I was in your place a while ago, then with some searching and help came to a solution which I use all the time since then. No thinking when a new project comes along. Copy, paste, forget. Once you get that going, everything else you do is basically the same. Get a value over serial, do something based on that value. But if you don't know if you even received correct value or for that matter any value, nothing can work as expected.
Khansokhua



Joined: 06 Nov 2021
Posts: 92

View user's profile Send private message

PostPosted: Thu Mar 30, 2023 11:22 am     Reply with quote

PrinceNai wrote:
You sure don't like interrupts :-). Your style of coding, I guess, but you are only making it harder for yourself. Two things, the first is to shorten the code. If you have all of LEDs on the same port, use output_x(pattern) instead of writing 8 statements for 8 LEDs. The second one concerns ICD. If you can, move those diodes to PortD to be able to use output_x(). The reason for this is that it is best to leave ICD lines free. If you won't use output_x, move just two diodes away from PIN_B6 and PIN_B7.

Code:
 if(led_value>=0 && led_value<=32){
           output_d(0b10000000);       }
           if(led_value>=33 && led_value<=65){
           output_d(0b01000000);   
                    }
           if(led_value>=66 && led_value<=98){
           output_d(0b00100000);            }
           if(led_value>=99 && led_value<=131){
           output_d(0b00010000);            }
           if(led_value>=132 && led_value<=164){
           output_d(0b00001000);           }
           if(led_value>=165 && led_value<=197){
           output_d(0b00000100);           }
           if(led_value>=198 && led_value<=229){
           output_d(0b00000010);            }
           if(led_value>=230 && led_value<=255){
           output_d(0b00000001);              }


Far much better thank you
PrinceNai



Joined: 31 Oct 2016
Posts: 480
Location: Montenegro

View user's profile Send private message

PostPosted: Thu Mar 30, 2023 12:03 pm     Reply with quote

Cool. It is shorter. Now just make it nicer and easier to read. 80% of that IDE can do for you. Use tabs, 3 spaces sound ok. Use indents. That way you can see the structure and levels of your code and makes it way easier for you and others to read. Like this:
Code:

if(led_value>=0 && led_value<=32){
   output_d(0b10000000);       
}
if(led_value>=33 && led_value<=65){
   output_d(0b01000000);   
}


or, if you like your braces to match on the same column, like this:
Code:

if(led_value>=0 && led_value<=32)
{
   output_d(0b10000000);       
}
if(led_value>=33 && led_value<=65)
{
   output_d(0b01000000);   
}


This also helps, and I mean helps, when you forget the closing brace and try to figure out just where you forgot to write it. I for one ALWAYS write both braces first and then the code between them.
Khansokhua



Joined: 06 Nov 2021
Posts: 92

View user's profile Send private message

PostPosted: Thu Mar 30, 2023 1:47 pm     Reply with quote

Using pickit3 debugger, I can observe from watch window: At max value of adc is constant 0xFF.
At min value 0x01 0x08 0xfd changes.
I can eliminate the values those cause problem,
so I can obtain what I want I think...
It seems ridiculous why adc value keep changing that way
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Mar 30, 2023 3:12 pm     Reply with quote

re: ADC values not correct

What is the source of the analog voltage you're reading ?
What hardware filtering have you on the signal ?
What is the Vref for the ADC ?
If it's VDD, THAT can be a huge problem !
Is the received adc value the SAME as the transmitted value ?
Have you proper VDD filtering(bypass caps ) on the TX PIC ?
What values do you see compared to what you know they should be ?
Are you reading the sensor (pot ??) once only ? Should use Olympic averaging or similar.
What is the 'sensor' ?
If it's a pot, it HAS to be filtered as all pots are 'scratchy' aka wiper noise
Max = 255 = 0xff
Min should be zero

TX needs to
loop:
read adc
delay_ms(100); only 1/10th second delay, I'd prefer 1 second
send adc
loop
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3, 4, 5, 6  Next
Page 5 of 6

 
Jump to:  
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