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

Serial or count?

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
dsaari



Joined: 05 May 2006
Posts: 25

View user's profile Send private message AIM Address

Serial or count?
PostPosted: Sun Jun 16, 2013 12:40 pm     Reply with quote

Hello all,
I've been trying to utilize a pic to receive some input data from a light bar, and I'm struggling. The light bar (array of 40 send/receive pairs) outputs data in the following way; one long start pulse, then up to 40 subsequent pulses representing which beams are being blocked. The cycle then repeats. I've attached the datasheet for reference. I think that if I can getc 5 bytes starting after I see the start pulse, this might work. In fact my first getc works great but it appears as though there is missed data when I attempt additional getc's. I am not a serial communications expert by any means. All I did was looked at the data sheet to determine the baud rate of 1244, and set my pic to that. I have a sync pulse from the sensor going into the pic so I know when the transmission is about to start. The two while loops and the delay_us seem to allow my first getc to capture the correct information. The first byte seems to work great. if I block more than 8 beams the second getc doesn't capture it. Not until I block nearly half the beams do subsequent getc's capture anything and it really doesn't make sense. I am actually wondering if I need to setup the #use 232 differently since I don't have start bits and parity checking going on. Any pointers? Another path I started down was to actually count these pulses but this seems much nicer if I can just read them serially.

Lightbar data sheet:
https://dl.dropboxusercontent.com/u/33977865/SG14%20Digital%20Output%20User%20Manual%201%203.pdf
Compiler version 5.006
Code:
#include <18F2550.h>
#device ADC=16
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES CPUDIV1
#FUSES HSPLL
#FUSES PLL5
#use delay(clock=48000000)
#use rs232(debugger)
#USE FAST_IO (A)
#define LED PIN_A0
#define PBUTTON PIN_A5
#define SYNC PIN_A3
#define RCV_SIG PIN_A2

   
void main()
{   
   int8 buffer[5] = {0,0,0,0,0};
   int8 x = 0;
   SET_TRIS_A( 0x2C );
   while(true)
   {
      #use rs232(baud=1244,rcv=RCV_SIG)
      while (!input(SYNC));
      while (input(SYNC));       
      delay_us(2412);
      for (x=0;x<=4;X++) buffer[x] = getc();
      #use rs232(debugger)
      printf("x = %u\n\r", x);
      for (x=0;x<=4;X++) printf("buffer[%u] = %u\n\r", x, buffer[x]);
      delay_ms(1000);
      if (!input(PBUTTON)) output_high(LED);
      else output_low(LED);
   }
}
Works great for the first byte
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Sun Jun 16, 2013 3:18 pm     Reply with quote

The UART, _requires_ start bits. This is how async comms 'works'. The start bit is needed every eight or nine bits. So it isn't going to work using the UART.

The way to do this, is using the hardware timers and interrupts.
You'd need to start by timing the gap between a subsequent rising/falling edge, till you find one that is longer than 1mSec. This then starts your 'seek' cycle. You then time at intervals just a fraction 'early' of the 1.176mSec interval from this point, and if the signal is high, then the pulse is on. Repeat for the number of channels in use.
Hardware timer.

Best Wishes
dsaari



Joined: 05 May 2006
Posts: 25

View user's profile Send private message AIM Address

PostPosted: Mon Jun 17, 2013 6:15 pm     Reply with quote

Ok, I suspected I needed to do that, just hoping for an easy way out. Anyway, I got it working, I've populated an array of 40 shorts (one for each channel). Now I need to serial out the information to a PLC. So I was thinking of moving the information into 5 bytes that I could send out. I was looking at a few built in functions that might make this elegant/simple but I don't see anything right off. Is there a way to simply shift the bits out of this array[40] into byte sized variables? Sorry for the stupid question, just point me in a direction, I'll get it.

Thanks in advance.
dsaari



Joined: 05 May 2006
Posts: 25

View user's profile Send private message AIM Address

PostPosted: Mon Jun 17, 2013 7:48 pm     Reply with quote

Not real pretty or elegant but functional....
Code:
         for (x=0;x<8;x++)
         {
            Byte1 <<=1;
            Byte1 += Buffer[x];
         }
         for (x=8;x<16;x++)
         {
            Byte2 <<=1;
            Byte2 += Buffer[x];
         }
         for (x=16;x<24;x++)
         {
            Byte3 <<=1;
            Byte3 += Buffer[x];
         }
         for (x=24;x<32;x++)
         {
            Byte4 <<=1;
            Byte4 += Buffer[x];
         }
         for (x=32;x<40;x++)
         {
            Byte5 <<=1;
            Byte5 += Buffer[x];
         }
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Tue Jun 18, 2013 12:23 am     Reply with quote

CCS C has a built-in function shift_left() for this purpose.
John P



Joined: 17 Sep 2003
Posts: 331

View user's profile Send private message

PostPosted: Tue Jun 18, 2013 11:07 am     Reply with quote

What a truly atrocious interface! They have a limited grasp of spelling, too.

You will have to bet that your clock matches the unit's clock fairly exactly, and look for a pulse each from the un-blocked channels, at 0.804ms intervals. But if you don't really care which channels are clear or blocked, you could ignore which specific ones are clear; just count the pulses and see if you get 40 of them per cycle. By the way, they don't seem to specify the length of a pulse, only the spacing between trailing edges.

On the other hand, the time for a full cycle is specified, at 37msec. If that's accurate, you could use it to calibrate your processor's clock to match the sending unit, and thus be more confident in reading the line at the right times to get all 40 of the incoming pulses. But why can't they send 40 pulses and make them show the blocked/clear status by being "long" or "short"?
rnielsen



Joined: 23 Sep 2003
Posts: 852
Location: Utah

View user's profile Send private message

PostPosted: Tue Jun 18, 2013 12:02 pm     Reply with quote

If you're simply concerned if the light bar is blocked or clear then I might suggest John's approach and just count how many pulses you receive. If you get all 40 of them then it's clear. If you receive less than 40 then you know it's blocked somewhere.

I don't think it would matter where the block is as long as you know it's blocked somewhere. Otherwise, this could be a timing nightmare.

Ronald
gilroy



Joined: 19 Jun 2013
Posts: 1

View user's profile Send private message

PostPosted: Wed Jun 19, 2013 11:19 pm     Reply with quote

You have, a programmable divider. Gives /2 to /33. Requirement is that the output of this must be in the range 0.8MHz to 8MHz.
This is followed by the PLL, which gives *2 to *513. Again programmable. Requirement here is that the output must be between 100, and 200MHz.
This is followed by another divider, which gives /2, /4 or /8. Output must be between 12.5, and 80MHz.




___________
Go through the braindumps design tutorial and 642-813 dumps guide to learnuseful web design skills. Become expert in web design with COMPTIA online course. For more detail Massachusetts Institute of Technology (MIT) best of luck


Last edited by gilroy on Fri Jul 25, 2014 6:12 am; edited 3 times in total
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Thu Jun 20, 2013 12:40 am     Reply with quote

Quote:
What a truly atrocious interface!

I think, it's just another application specific protocol in industrial automation. There is a certain lack of
specification, e.g. tolerances for bit clock. The bit pulse length is however specified, 330+/-100 us.

The essential question is if we can assume a crystal accurate (e.g. some 100 ppm) TX timing, otherwise the
receiver must use a kind of PLL to lock to the frame clock and derive the bit block. This can be done in software
but involves some effort and would most likely go over the head of a µC beginner.

Due to the low bit duty cycle (about 25% minimal), the RX data must be oversampled even if sampling is
started synchronus to the start bit., factor 8 or 16 of bit clock seems reasonable. You can either run
a timer interrupt or a synchronous serial master interface to sample the input data.
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Thu Jun 20, 2013 4:18 am     Reply with quote

I don't think you have to oversample.

The way to receive this, is to initially 'forget' times. It is basically an 'edge' protocol. The pulse width is specified as very variable. All you have is the simple thing of the presence of an edge, or not.

Have an array of 'times' all set to zero.
Then start by looking for a rising edge.
On this, setup a CTC interrupt to record every falling edge 'time' relative to this, and setup a 'timeout' to trigger at about 36mSec.
On the first interrupt, if the time you record is less than 0.952mSec, or greater than 1.352mSec, you go back to waiting for a rising edge.
Else, you just start recording the times of every falling edge, till the count is 40, or you see the timeout.

You then just analyse the times. Start with an array of 40 bits, all 'off'.
Then for the time of each falling edge, subtract 1.176mSec, and divide by 0.804mSec. The value you get from this, is the bit number to turn on.

You then have the frame decoded.
If you record the times in uSec (say), then calculations become simple integer arithmetic. With a bit of care, you can build in some rounding to cover a degree of timing variation.

Now, given there are 40 pulses, which could have all missing, or all present, you can't have more than a total error of 41/40 in the timing, without the calculation they show failing. 2.5%. Allow for a maximum of half this, gives a minimum time of 794uSec, versus their 804 'nominal'.

So with their example time of 32.528mSec - 32528uSec - 1176 = 31352/794 = 39.48 (39 using integer maths), so this sets bit 39. Edge times between 32.142, and 32.936mSecs will all be accepted as bit 39. Their 'nominal' value, is pretty much bang in the centre of this, and it won't accept the next value down by mistake. (using their calculation, 31.724mSec).

Best Wishes
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Fri Jun 21, 2013 1:33 am     Reply with quote

Recording edge times is in fact an intelligent way to decode the protocol.

You may want to understand it as a kind of oversampling with "infinite" respectively very high resolution.
Ttelmah



Joined: 11 Mar 2010
Posts: 19535

View user's profile Send private message

PostPosted: Fri Jun 21, 2013 3:02 am     Reply with quote

and (of course), made easier by the PIC having hardware to do it. Smile

It is an 'odd' protocol, since it actually requires very accurate timings, or it is going to fail (as with any protocol using a 'long' gap between synchronisation points, with a lot of 'bits' being sent in the gap, yet has a huge variation in the pulse widths they use. But if you study the way they talk about the times, and their example, it is the durations between falling edges that they expect to 'rely' on.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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