![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
dsaari
Joined: 05 May 2006 Posts: 25
|
Serial or count? |
Posted: Sun Jun 16, 2013 12:40 pm |
|
|
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 ![](https://dl.dropboxusercontent.com/u/33977865/Osc_debug50.jpg) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19368
|
|
Posted: Sun Jun 16, 2013 3:18 pm |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
dsaari
Joined: 05 May 2006 Posts: 25
|
|
Posted: Mon Jun 17, 2013 6:15 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
dsaari
Joined: 05 May 2006 Posts: 25
|
|
Posted: Mon Jun 17, 2013 7:48 pm |
|
|
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];
} |
|
|
![](templates/subSilver/images/spacer.gif) |
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Jun 18, 2013 12:23 am |
|
|
CCS C has a built-in function shift_left() for this purpose. |
|
![](templates/subSilver/images/spacer.gif) |
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Tue Jun 18, 2013 11:07 am |
|
|
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"? |
|
![](templates/subSilver/images/spacer.gif) |
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Tue Jun 18, 2013 12:02 pm |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
gilroy
Joined: 19 Jun 2013 Posts: 1
|
|
Posted: Wed Jun 19, 2013 11:19 pm |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Thu Jun 20, 2013 12:40 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19368
|
|
Posted: Thu Jun 20, 2013 4:18 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Fri Jun 21, 2013 1:33 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19368
|
|
Posted: Fri Jun 21, 2013 3:02 am |
|
|
and (of course), made easier by the PIC having hardware to do it.
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 |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|