I have a 16F747 and am attempting to communicate with my PC via a MAX233
translator - pretty standard stuff. However the PIC-to-PC direction is very
unstable, dropping 1 out of 4 bytes seemingly at random.
I'm using the HS oscillator with a 20MHz xtal. My link troubleshooting
program replies to a 4-byte string with a 5-byte string and does absolutely
nothing else. I've tried adding delays between bytes but still random bytes
are *always* lost. Lengthening the string worsens the problem which makes
me think this may be a timing problem, however I *am* using a crystal and
haven't noticed the oscillator being "off" when measuring various periods
from other test programs on this device. The PC-to-PIC direction is
rock-solid.
Slowing the baud rate to 2400 improves things vastly, with only ~1 byte out
of 50 lost. But at 9600 (in either BRGH=0 or 1) the link is nigh on
unusable.
Here are the relevant sections of my code (there are no other "interesting"
functions - no interrupts, timers, etc in use):
;*** Enable USART
BSF STATUS, RP0 ; Go to Bank1
MOVLW D'129' ; Set Baud rate 9600
MOVWF SPBRG
MOVLW b'00100100' ; 8-bit transmit, transmitter enabled,
MOVWF TXSTA ; asynchronous mode, high speed mode
BCF STATUS, RP0 ; Go to Bank 0
MOVLW b'10010000' ; 8-bit receive, receiver enabled,
MOVWF RCSTA ; serial port enabled
;*** Send character
send call errchk
movwf TXREG ; send data in W
TransWt bsf STATUS, RP0 ; RAM PAGE 1
WtHere btfss TXSTA, TRMT ; (1) transmission is complete if hi
goto WtHere
bcf STATUS, RP0 ; RAM PAGE 0
return
Drew Maurer wrote:
> I have a 16F747 and am attempting to communicate with my PC via a
> MAX233 translator - pretty standard stuff. However the PIC-to-PC
> direction is very unstable, dropping 1 out of 4 bytes seemingly at
> random.
>
> I'm using the HS oscillator with a 20MHz xtal. My link
> troubleshooting program replies to a 4-byte string with a 5-byte
> string and does absolutely nothing else. I've tried adding delays
> between bytes but still random bytes are *always* lost. Lengthening
> the string worsens the problem which makes me think this may be a
> timing problem, however I *am* using a crystal and haven't noticed
> the oscillator being "off" when measuring various periods from other
> test programs on this device. The PC-to-PIC direction is rock-solid.
>
> Slowing the baud rate to 2400 improves things vastly, with only ~1
> byte out of 50 lost. But at 9600 (in either BRGH=0 or 1) the link is
> nigh on unusable.
This smells like a problem with the MAX232, probably somewhere in the charge
pumps. That would explain why the PC to PIC direction works fine since it
doesn't rely on the charge pumps. Look at the charge pump outputs. They
should be around -8V and +8V. The RS-232 output should also switch between
those levels, with -8V being the idle level. That's probably not what is
happening in your setup.
> Drew Maurer wrote:
> > I have a 16F747 and am attempting to communicate with my PC via a
> > MAX233 translator - pretty standard stuff. However the PIC-to-PC
> > direction is very unstable, dropping 1 out of 4 bytes seemingly at
> > random.
> >
> > I'm using the HS oscillator with a 20MHz xtal. My link
> > troubleshooting program replies to a 4-byte string with a 5-byte
> > string and does absolutely nothing else. I've tried adding delays
> > between bytes but still random bytes are *always* lost. Lengthening
> > the string worsens the problem which makes me think this may be a
> > timing problem, however I *am* using a crystal and haven't noticed
> > the oscillator being "off" when measuring various periods from other
> > test programs on this device. The PC-to-PIC direction is rock-solid.
> >
> > Slowing the baud rate to 2400 improves things vastly, with only ~1
> > byte out of 50 lost. But at 9600 (in either BRGH=0 or 1) the link is
> > nigh on unusable.
>
> This smells like a problem with the MAX232, probably somewhere in the
> charge
> pumps. That would explain why the PC to PIC direction works fine since it
> doesn't rely on the charge pumps. Look at the charge pump outputs. They
> should be around -8V and +8V. The RS-232 output should also switch between
> those levels, with -8V being the idle level. That's probably not what is
> happening in your setup.
>
> Here's a self-serving suggestion: Next time just use one of these
> http://www.embedinc.com/products/rslink2
>
>
> ********************************************************************
> Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
> (978) 742-9014. Gold level PIC consultants since 2000.
On Wed, 28 Jul 2010 13:48:14 -0700, "Drew Maurer" said:
>
> Thanks. Actually I've already 'scoped the levels in all directions, they
> look fine. In fact that MAX233 is new but the problem is not - I added
> the
> 233 because I thought the problem might be related to the crude level
> shifter made out of discretes (which borrowed -12V from the PC itself)
> that
> I was using, but the problem persists unchanged.
On the PC is it a real serial port or a USB adapter under Windows? I had
problems once where a byte here and there was being munged, and a
different driver fixed it. Prolific PL-2303 based USB-Serial adapter.
Very interesting; yes its a Prolific USB adapter. Driver version 2.0.2.8 -
do you happen to know which driver "fixed" your issue? I did previously try
the device on a PC with a built-in serial port and the behavior was more
predictable but not perfect; I will check again.
Also, I'm playing in realtime, here is some more grist for the mill -
setting the SPBRG to '134' (9259 baud) helps quite a bit. Hard to believe
my crystal would be that far out.
>
> On Wed, 28 Jul 2010 13:48:14 -0700, "Drew Maurer" said:
>
> >
> > Thanks. Actually I've already 'scoped the levels in all directions, they
> > look fine. In fact that MAX233 is new but the problem is not - I added
> > the
> > 233 because I thought the problem might be related to the crude level
> > shifter made out of discretes (which borrowed -12V from the PC itself)
> > that
> > I was using, but the problem persists unchanged.
>
> On the PC is it a real serial port or a USB adapter under Windows? I had
> problems once where a byte here and there was being munged, and a
> different driver fixed it. Prolific PL-2303 based USB-Serial adapter.
>
> Cheers,
>
> Bob
>
> --
> http://www.fastmail.fm - A fast, anti-spam email service.
>
On Wed, 28 Jul 2010 14:54:09 -0700, "Drew Maurer" said:
> Bob,
>
> Very interesting; yes its a Prolific USB adapter. Driver version 2.0.2.8
> -
> do you happen to know which driver "fixed" your issue?
I don't know what the bad driver was but my computer is using 2.0.0.18
right now.
> try
> the device on a PC with a built-in serial port and the behavior was more
> predictable but not perfect; I will check again.
>
> Also, I'm playing in realtime, here is some more grist for the mill -
> setting the SPBRG to '134' (9259 baud) helps quite a bit. Hard to
> believe
> my crystal would be that far out.
Sounds like maybe a dwarf bit? There is no harm in setting the PC side
to two stop bits to see if by forcing that extra idle bit will change
things.
Almost makes the extra weight of a USB stack seem worth it :)
No chance of an out of spec voltage being applied to any PIC pin?
That's a potential risk with informal level shifters but shouldn't be
a problem with the driver IC.
> No chance of an out of spec voltage being applied to any PIC pin?
> That's a potential risk with informal level shifters but shouldn't be
> a problem with the driver IC.
>
>
> R
>
> Nope, all voltages look fine.
>
> I just bought a new USB-serial dongle... same problem. Maddening!!
Have you tried it on another PC yet? (preferably with a proper serial port) Making sure it's not the PC side would help, may be an issue with your PCs USB hub/drivers etc.
When testing a bit banged serial a little while back on a 16F636 I used a little test program to send a couple of characters in a tight loop so I could examine the timing on a scope - maybe you could try this, send a loop of a few characters and see if there is any evidence of timing problems that could cause bytes to be dropped. You can also just hold a key down on the PC and examine timings the other way for comparison.
Also, if you have a PicKit2 handy you could use the UART tool to connect to the PIC - this should be pretty much guaranteed to work so if you are still getting problems you can be almost certain it's on the PIC side.
Just in case if you have another PIC handy you could give that a go too - I was helping a chap some time ago with similar issues and using a different PIC sorted the problem (the PICs clock appeared to be playing up for some reason, causing timing problems) I know this kind of thing is a very rare occurrence but eliminating everything helps.
I'm assuming power supply, pin voltages, clock speed etc have all been tested, bypass caps are being used etc etc.
Thanks everyone. I don't know exactly which variable did the trick, but a
new crystal, new PIC, and using a real serial port seems to have done the
trick. I /had/ tried a real port previously and had similar trouble, but
this time its working.
The behavior of the USB-serial jobs is very odd. I get reasonable
performance if I stay at 4800 baud or below, but roughly 10% of my data
strings turn up incomplete. I'm going to try a PCMCIA serial port and hope
that works better.
Another, related, question - what happens to the USART when the TMR0
interrupt fires? Does it finish sending the byte normally? Reason being,
this is a servo driver/current monitor for my lonelybot.com project - the
TMR0 interrupt is used to generate the 20ms "off" time for the servo's PWM
input; when the 20ms is up, the interrupt holds control for the 1-2ms servo
pulse. 4800 baud means that my data strings collide with the interrupt
frequently - my testing shows that, at 4800 baud almost 70% of my strings
collide with the interrupt in this way, which is unacceptable because I have
to repeat the request 5 or 10 times which is really going to flood the data
bus on my boat. Can I ignore these interrupts in my data? Am I guaranteed
that the data is still good, just delayed?
>
>
> --------------------------------------------------
> From: "Drew Maurer" <@spam@a.l.maurerKILLspamgmail.com>
> Sent: Thursday, July 29, 2010 3:43 AM
> To: "Microcontroller discussion list - Public." <KILLspampiclistKILLspamMIT.EDU>
> Subject: Re: [PIC] 16F747 UART errors
>
> > Nope, all voltages look fine.
> >
> > I just bought a new USB-serial dongle... same problem. Maddening!!
>
> Have you tried it on another PC yet? (preferably with a proper serial port)
> Making sure it's not the PC side would help, may be an issue with your PCs
> USB hub/drivers etc.
>
> When testing a bit banged serial a little while back on a 16F636 I used a
> little test program to send a couple of characters in a tight loop so I
> could examine the timing on a scope - maybe you could try this, send a loop
> of a few characters and see if there is any evidence of timing problems
> that
> could cause bytes to be dropped. You can also just hold a key down on the
> PC
> and examine timings the other way for comparison.
> Also, if you have a PicKit2 handy you could use the UART tool to connect to
> the PIC - this should be pretty much guaranteed to work so if you are still
> getting problems you can be almost certain it's on the PIC side.
>
> Just in case if you have another PIC handy you could give that a go too - I
> was helping a chap some time ago with similar issues and using a different
> PIC sorted the problem (the PICs clock appeared to be playing up for some
> reason, causing timing problems) I know this kind of thing is a very rare
> occurrence but eliminating everything helps.
>
> I'm assuming power supply, pin voltages, clock speed etc have all been
> tested, bypass caps are being used etc etc.
>
>
On 2010-07-29 08:07, Drew Maurer wrote:
> Thanks everyone. I don't know exactly which variable did the trick, but a
> new crystal, new PIC, and using a real serial port seems to have done the
> trick. I /had/ tried a real port previously and had similar trouble, but
> this time its working.
>
> The behavior of the USB-serial jobs is very odd. I get reasonable
> performance if I stay at 4800 baud or below, but roughly 10% of my data
> strings turn up incomplete. I'm going to try a PCMCIA serial port and hope
> that works better.
That is not my view of the RS232/USB dongles. For standart serial
communication, they work usualy just OK (at any speed).
>
> Another, related, question - what happens to the USART when the TMR0
> interrupt fires?
Nothing. The USART (if you are talking about a hardware USART, not
something built in firmware) does it's job independant of any
interrupts. If you are not messing with the USART registers
in the interrupt.
> Does it finish sending the byte normally? Reason being,
> this is a servo driver/current monitor for my lonelybot.com project - the
> TMR0 interrupt is used to generate the 20ms "off" time for the servo's PWM
> input; when the 20ms is up, the interrupt holds control for the 1-2ms servo
> pulse.
That might not be a good solution. Just set some timer and return from
the interrupt as soon as possible. Are you also using interrupts to read
the incomming USART data ?
4800 baud means that my data strings collide with the interrupt {Quote hidden}
> frequently - my testing shows that, at 4800 baud almost 70% of my strings
> collide with the interrupt in this way, which is unacceptable because I have
> to repeat the request 5 or 10 times which is really going to flood the data
> bus on my boat. Can I ignore these interrupts in my data? Am I guaranteed
> that the data is still good, just delayed?
>
> Drew
>
> On Wed, Jul 28, 2010 at 9:13 PM, Oli Glaser<RemoveMEoli.glaserTakeThisOuTtalktalk.net> wrote:
>
>>
>>
>> --------------------------------------------------
>> From: "Drew Maurer"<spamBeGonea.l.maurerspamBeGonegmail.com>
>> Sent: Thursday, July 29, 2010 3:43 AM
>> To: "Microcontroller discussion list - Public."<TakeThisOuTpiclistEraseMEspam_OUTMIT.EDU>
>> Subject: Re: [PIC] 16F747 UART errors
>>
>>> Nope, all voltages look fine.
>>>
>>> I just bought a new USB-serial dongle... same problem. Maddening!!
>>
>> Have you tried it on another PC yet? (preferably with a proper serial port)
>> Making sure it's not the PC side would help, may be an issue with your PCs
>> USB hub/drivers etc.
>>
>> When testing a bit banged serial a little while back on a 16F636 I used a
>> little test program to send a couple of characters in a tight loop so I
>> could examine the timing on a scope - maybe you could try this, send a loop
>> of a few characters and see if there is any evidence of timing problems
>> that
>> could cause bytes to be dropped. You can also just hold a key down on the
>> PC
>> and examine timings the other way for comparison.
>> Also, if you have a PicKit2 handy you could use the UART tool to connect to
>> the PIC - this should be pretty much guaranteed to work so if you are still
>> getting problems you can be almost certain it's on the PIC side.
>>
>> Just in case if you have another PIC handy you could give that a go too - I
>> was helping a chap some time ago with similar issues and using a different
>> PIC sorted the problem (the PICs clock appeared to be playing up for some
>> reason, causing timing problems) I know this kind of thing is a very rare
>> occurrence but eliminating everything helps.
>>
>> I'm assuming power supply, pin voltages, clock speed etc have all been
>> tested, bypass caps are being used etc etc.
>>
>>
>> Does it finish sending the byte normally? Reason being,
>> this is a servo driver/current monitor for my lonelybot.com project - the
>> TMR0 interrupt is used to generate the 20ms "off" time for the servo's
>> PWM
>> input; when the 20ms is up, the interrupt holds control for the 1-2ms
>> servo
>> pulse.
>
> That might not be a good solution. Just set some timer and return from
> the interrupt as soon as possible. Are you also using interrupts to read
> the incomming USART data ?
Yes, I'm thinking there are probably better ways to do this. Unless I'm misunderstanding what is needed - what about using the PWM peripheral for the servo input? Then you can just load the registers and let it run independently.
> 4800 baud means that my data strings collide with the interrupt
>> frequently - my testing shows that, at 4800 baud almost 70% of my strings
>> collide with the interrupt in this way, which is unacceptable because I
>> have
>> to repeat the request 5 or 10 times which is really going to flood the
>> data
>> bus on my boat. Can I ignore these interrupts in my data? Am I
>> guaranteed
>> that the data is still good, just delayed?
Do you mean the USART data sending is interrupted somewhere by the TMR0 interrupt?
Receiving or sending? What do you mean exactly by ignoring the interrupts/data being good? Can you give a bit more explanation?
>
>
> --------------------------------------------------
> From: "Jan-Erik Soderholm"<EraseMEjan-erik.soderholmtelia.com>
> Sent: Thursday, July 29, 2010 10:49 AM
> To: "Microcontroller discussion list - Public."<RemoveMEpiclistEraseMEEraseMEmit.edu>
> Subject: Re: [PIC] 16F747 UART errors
>
>>> Does it finish sending the byte normally? Reason being,
>>> this is a servo driver/current monitor for my lonelybot.com project - the
>>> TMR0 interrupt is used to generate the 20ms "off" time for the servo's
>>> PWM
>>> input; when the 20ms is up, the interrupt holds control for the 1-2ms
>>> servo
>>> pulse.
>>
>> That might not be a good solution. Just set some timer and return from
>> the interrupt as soon as possible. Are you also using interrupts to read
>> the incomming USART data ?
>
> Yes, I'm thinking there are probably better ways to do this. Unless I'm
> misunderstanding what is needed - what about using the PWM peripheral for
> the servo input? Then you can just load the registers and let it run
> independently.
Usualy, the standard PWM module(s) are not particular good at generating
a standard 1.5 +/- 0.5 ms servo signal. And in many cases you have not
a single servo anyway.
Exactly how the signals are to be generated depends on a number
of factors. One is how many steps (the "resolution") on needs
in the servo.
>
>
>> 4800 baud means that my data strings collide with the interrupt
>>> frequently - my testing shows that, at 4800 baud almost 70% of my strings
>>> collide with the interrupt in this way, which is unacceptable because I
>>> have
>>> to repeat the request 5 or 10 times which is really going to flood the
>>> data
>>> bus on my boat. Can I ignore these interrupts in my data? Am I
>>> guaranteed
>>> that the data is still good, just delayed?
>
> Do you mean the USART data sending is interrupted somewhere by the TMR0
> interrupt?
> Receiving or sending? What do you mean exactly by ignoring the
> interrupts/data being good? Can you give a bit more explanation?
>
>
Drew Maurer wrote:
> Very interesting; yes its a Prolific USB adapter.
You might have mentioned you were using a USB to RS-232 adapter in the first
place.
Try it directly without the adapter. If this PC doesn't have a serial port,
try it on one that does. This isn't meant to be a long term solution, but
will help diagnose what is going on.
A few years back Wouter sent me a USB to serial adapter to try out. At
first it didn't work at all. I dug around, found the latest driver,
installed that on Windows 2000, and it then basically worked as long as you
had RTS and CTS looped back (or something like that, it was a few years
ago).
Bob Blick wrote:
> Sounds like maybe a dwarf bit? There is no harm in setting the PC side
> to two stop bits to see if by forcing that extra idle bit will change
> things.
I thought he is having problems with the PIC to PC direction, in which case
the PIC should be set to 2 stop bits with the PC still at 1. That may mess
up the PC to PIC direction, but it's a interesting test to see how it
effects the PIC to PC direction.
> Another, related, question - what happens to the USART when the TMR0
> interrupt fires? Does it finish sending the byte normally? Reason being,
> this is a servo driver/current monitor for my lonelybot.com project - the
> TMR0 interrupt is used to generate the 20ms "off" time for the servo's PWM
> input; when the 20ms is up, the interrupt holds control for the 1-2ms servo
> pulse. 4800 baud means that my data strings collide with the interrupt
> frequently - my testing shows that, at 4800 baud almost 70% of my strings
> collide with the interrupt in this way, which is unacceptable because I have
> to repeat the request 5 or 10 times which is really going to flood the data
> bus on my boat. Can I ignore these interrupts in my data? Am I guaranteed
> that the data is still good, just delayed?
Doing the servo pulse timing as you describe is reasonable if you are controlling multiple servos. Consider using two PICs, one for the servo control and one for the comms. You could get the comms PIC to buffer data and present it to the servo controller as fast (high speed bursts "packet at a time" over SPI) or slow (byte at a time as requested) as you want.
Drew Maurer wrote:
> Another, related, question - what happens to the USART when the TMR0
> interrupt fires?
Nothing special. If there was some bizarre interaction, then this would be
described in the datasheet or the errata.
Think about it. The UART and timer 0 are two independent hardware modules.
They would be expected to each do their thing independently unless something
was deliberately done to connect them somehow. Since there is no such
connection, not even any reason to suspected such a connection, what you're
asking makes no sense. It's like asking if your car will still run when the
bedroom window is closed.
> Usualy, the standard PWM module(s) are not particular good at
> generating a standard 1.5 +/- 0.5 ms servo signal. And in
> many cases you have not a single servo anyway.
I've got a side project (active control of a inherently unstable flying
wing) that drives 4 hobby servos directly from a 24HJ32GP302. The dsPIC
class PWM modules have wide enough period counters that you can do 500us to
2.5ms every 20ms with sufficient resolution in fire and forget hardware.
With a PIC 18 or something I would look into multiplexing the output of a
single PWM module. The important observation is that you can fit a number
of 1-2 ms pulses in the 20ms repetition period. You do the pulse for each
channel successively. The multiplexer can be as easy as a AND gate per
servo output. Now the PWM hardware only needs a period a bit more than 2ms,
so you should have enough resolution for the varying pulse width.
Yes, the PWM module cannot achieve the low duty cycles required while
maintaining adequate resolution. If I recall correctly I think if I was
willing to tolerate 10ms pulse spacing (instead of 20) then it would have
functioned but with very low resolution and I was told the short pulse
spacing may have upset some servos. (Don't quote me, I'm speaking from
memory - but I'd wanted to use the PWM module and was forced to reject that
idea)
The way I do it now is to set the TMR0 prescaler to 256, which gets me
something like 12 or 13ms until the interrupt. The first time it interrupts
it resets the prescaler to 128 and returns which delivers the remaining 7 or
8ms. The second time the interrupt is triggered it sets all the servo lines
high for 1ms followed by an additional 0 to 1ms. In this way I get 8bit
pulse width resolution but still have the processor yielded for
communications about 90% of the time. I'm not saying this is the best
way... but it was the only way I could come up with to combine control of
multiple servos, good resolution, serial communication, 6 ADCs for
measurements, and fast 20MHz clock for computation.
> On 2010-07-29 12:48, Oli Glaser wrote:
> >
> >
> > --------------------------------------------------
> > From: "Jan-Erik Soderholm"<RemoveMEjan-erik.soderholmTakeThisOuTspamtelia.com>
> > Sent: Thursday, July 29, 2010 10:49 AM
> > To: "Microcontroller discussion list - Public."<EraseMEpiclistspamspamBeGonemit.edu>
> > Subject: Re: [PIC] 16F747 UART errors
> >
> >>> Does it finish sending the byte normally? Reason being,
> >>> this is a servo driver/current monitor for my lonelybot.com project -
> the
> >>> TMR0 interrupt is used to generate the 20ms "off" time for the servo's
> >>> PWM
> >>> input; when the 20ms is up, the interrupt holds control for the 1-2ms
> >>> servo
> >>> pulse.
> >>
> >> That might not be a good solution. Just set some timer and return from
> >> the interrupt as soon as possible. Are you also using interrupts to read
> >> the incomming USART data ?
> >
> > Yes, I'm thinking there are probably better ways to do this. Unless I'm
> > misunderstanding what is needed - what about using the PWM peripheral for
> > the servo input? Then you can just load the registers and let it run
> > independently.
>
> Usualy, the standard PWM module(s) are not particular good at generating
> a standard 1.5 +/- 0.5 ms servo signal. And in many cases you have not
> a single servo anyway.
>
> Exactly how the signals are to be generated depends on a number
> of factors. One is how many steps (the "resolution") on needs
> in the servo.
>
>
> >
> >
> >> 4800 baud means that my data strings collide with the interrupt
> >>> frequently - my testing shows that, at 4800 baud almost 70% of my
> strings
> >>> collide with the interrupt in this way, which is unacceptable because I
> >>> have
> >>> to repeat the request 5 or 10 times which is really going to flood the
> >>> data
> >>> bus on my boat. Can I ignore these interrupts in my data? Am I
> >>> guaranteed
> >>> that the data is still good, just delayed?
> >
> > Do you mean the USART data sending is interrupted somewhere by the TMR0
> > interrupt?
> > Receiving or sending? What do you mean exactly by ignoring the
> > interrupts/data being good? Can you give a bit more explanation?
> >
> >
> >
I take it you've seen the videos on the web of the similar flying wing from
Stanford, maybe 10 years ago? They had to build custom servos because the
rates required were so high; the thing looked like it was flapping its
ailerons for propulsion, they were so fast. I digress...
Thanks, I check out the other classes of PICs. My bot is 24' stem-to-stern
so my plan was to keep cost and complexity low by running only DC power and
serial comm lines to the extremities of the boat, with several
generic/"general purpose" microcontroller modules living next to the
distributed pockets of sensors or actuators. Ergo I chose the biggest, most
feature-packed PIC I could find for the generic modules, hoping that it'd be
adequate for the various applications. Generally the 16F747 has enough
toys, though obviously this particular problem is a little tricky. I have
no answer as to why I didn't look outside the 16F lineup; tradition I
suppose.
> > Usualy, the standard PWM module(s) are not particular good at
> > generating a standard 1.5 +/- 0.5 ms servo signal. And in
> > many cases you have not a single servo anyway.
>
> I've got a side project (active control of a inherently unstable flying
> wing) that drives 4 hobby servos directly from a 24HJ32GP302. The dsPIC
> class PWM modules have wide enough period counters that you can do 500us to
> 2.5ms every 20ms with sufficient resolution in fire and forget hardware.
>
> With a PIC 18 or something I would look into multiplexing the output of a
> single PWM module. The important observation is that you can fit a number
> of 1-2 ms pulses in the 20ms repetition period. You do the pulse for each
> channel successively. The multiplexer can be as easy as a AND gate per
> servo output. Now the PWM hardware only needs a period a bit more than
> 2ms,
> so you should have enough resolution for the varying pulse width.
>
>
> ********************************************************************
> Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
> (978) 742-9014. Gold level PIC consultants since 2000.
Drew Maurer wrote:
> Thanks, I check out the other classes of PICs. My bot is 24'
> stem-to-stern
> so my plan was to keep cost and complexity low by running only DC
> power and serial comm lines to the extremities of the boat, with
> several generic/"general purpose" microcontroller modules living next
> to the distributed pockets of sensors or actuators. Ergo I chose the
> biggest, most feature-packed PIC I could find for the generic
> modules, hoping that it'd be adequate for the various applications.
> Generally the 16F747 has enough
> toys, though obviously this particular problem is a little tricky. I
> have
> no answer as to why I didn't look outside the 16F lineup; tradition I
> suppose.
Yeah, that sounds like a natural for a full featured 24H or 33F with CAN
module.
> Yes, the PWM module cannot achieve the low duty cycles required while
> maintaining adequate resolution. If I recall correctly I think if I
was
> willing to tolerate 10ms pulse spacing (instead of 20) then it would
have
> functioned but with very low resolution and I was told the short pulse
> spacing may have upset some servos. (Don't quote me, I'm speaking
from
> memory - but I'd wanted to use the PWM module and was forced to reject
that
> idea)
>
> The way I do it now is to set the TMR0 prescaler to 256, which gets me
> something like 12 or 13ms until the interrupt. The first time it
interrupts
> it resets the prescaler to 128 and returns which delivers the
remaining 7 or
> 8ms. The second time the interrupt is triggered it sets all the servo
lines
> high for 1ms followed by an additional 0 to 1ms. In this way I get
8bit
> pulse width resolution but still have the processor yielded for
> communications about 90% of the time. I'm not saying this is the best
> way... but it was the only way I could come up with to combine control
of
> multiple servos, good resolution, serial communication, 6 ADCs for
> measurements, and fast 20MHz clock for computation.
>
> Drew
OK, I have a feeling you could possibly select a better chip for the job
- seriously.
The chip you have is not a nanowatt part - from what I can make out from
the Microchip site, it won't let me look at the page for that chip
currently. There are PIC24 chips that are nanowatt, and I suspect you
probably want to be saving all the power you can in a pilotless drone.
This may or may not be a consideration, it is not clear to me if you are
attempting a solar powered drone or not.
As indicated above you are having problems with PWM resolution. PIC24
PWM channels have 16 bit resolution in place of the 5/6/7/8/10 bit that
that the 16F series do. And they have a heap of hardware channels that
will do it for you - as Olin said, set and forget. The largest chips do
have 5 hardware PWM channels and 4 UART channels. There is also a number
of SPI channels that could be used (with a bit of thought) as PWM
channels, with 16 stages of resolution, by transmitting a 16 bit word
with the appropriate bits set, at a timer interrupt determined interval.
Set the SPI clock to make the 16 bits 2.5mS long if that gives you
enough resolution, or stuff a number of 16 bit words into the SPI Tx
FIFO with a suitably faster clock to achieve better resolution.
You are already using a 40/44 pin part, so going to a large pin count
PIC24 won't be a hardship. Use the best tool for the job, instead of
make do and mend.
-- Scanned by iCritical.
On 2010-07-29 16:59, Drew Maurer wrote:
> Yes, the PWM module cannot achieve the low duty cycles required while
> maintaining adequate resolution. If I recall correctly I think if I was
> willing to tolerate 10ms pulse spacing (instead of 20) then it would have
> functioned but with very low resolution and I was told the short pulse
> spacing may have upset some servos. (Don't quote me, I'm speaking from
> memory - but I'd wanted to use the PWM module and was forced to reject that
> idea)
>
> The way I do it now is to set the TMR0 prescaler to 256, which gets me
> something like 12 or 13ms until the interrupt. The first time it interrupts
> it resets the prescaler to 128 and returns which delivers the remaining 7 or
> 8ms. The second time the interrupt is triggered it sets all the servo lines
> high for 1ms followed by an additional 0 to 1ms.
Note that there is no need to have all servos "in sync". It might often
be easer to take care of one 1-2 ms puls at the time and at the end
sum it up to (aprox) 20 ms before starting over again. It might
be more "work" for the processor to keep track of a number of pulses
active at the same time. And the servios doesn't care if one servo
gets its pulse first, then the second servo and so on.
That way, you can have a lookup-table with the timer values for
all your "positions", say aprox 100 different values/positions
(few applications needs more then 100 different servo positions).
Then the sequence becomes (something like) :
On each timer-interrupt :
- stop pulse for servo pointed to by servo-flag.
- All servos done ?
If so:
Reset servo-flag to first servo (minus 1?)
Load timer with "rest-of-20ms".
If not :
Start pulse for next servo.
Load timer with "postition" for next servo.
Set servo-flag to "next-servo".
RETFI
And then setup/initialization at power on and so on of course.
With this setup, you will not stay many cycles in the
timer-interrup and it will probably not interfere
with the USART routines/interrupts. As I read your
description, I go the impression that you stay in the
timer-interrupt the whole 1-2 mS period ? That is a
looong time... :-)
> pulse width resolution but still have the processor yielded for
> communications about 90% of the time. I'm not saying this is the best
> way... but it was the only way I could come up with to combine control of
> multiple servos, good resolution, serial communication, 6 ADCs for
> measurements, and fast 20MHz clock for computation.
>
> Drew
>
> On Thu, Jul 29, 2010 at 4:04 AM, Jan-Erik Soderholm<
> jan-erik.soderholmSTOPspamspam_OUTtelia.com> wrote:
>
>> On 2010-07-29 12:48, Oli Glaser wrote:
>>>
>>>
>>> --------------------------------------------------
>>> From: "Jan-Erik Soderholm"<spamBeGonejan-erik.soderholmSTOPspamEraseMEtelia.com>
>>> Sent: Thursday, July 29, 2010 10:49 AM
>>> To: "Microcontroller discussion list - Public."<KILLspampiclistspamBeGonemit.edu>
>>> Subject: Re: [PIC] 16F747 UART errors
>>>
>>>>> Does it finish sending the byte normally? Reason being,
>>>>> this is a servo driver/current monitor for my lonelybot.com project -
>> the
>>>>> TMR0 interrupt is used to generate the 20ms "off" time for the servo's
>>>>> PWM
>>>>> input; when the 20ms is up, the interrupt holds control for the 1-2ms
>>>>> servo
>>>>> pulse.
>>>>
>>>> That might not be a good solution. Just set some timer and return from
>>>> the interrupt as soon as possible. Are you also using interrupts to read
>>>> the incomming USART data ?
>>>
>>> Yes, I'm thinking there are probably better ways to do this. Unless I'm
>>> misunderstanding what is needed - what about using the PWM peripheral for
>>> the servo input? Then you can just load the registers and let it run
>>> independently.
>>
>> Usualy, the standard PWM module(s) are not particular good at generating
>> a standard 1.5 +/- 0.5 ms servo signal. And in many cases you have not
>> a single servo anyway.
>>
>> Exactly how the signals are to be generated depends on a number
>> of factors. One is how many steps (the "resolution") on needs
>> in the servo.
>>
>>
>>>
>>>
>>>> 4800 baud means that my data strings collide with the interrupt
>>>>> frequently - my testing shows that, at 4800 baud almost 70% of my
>> strings
>>>>> collide with the interrupt in this way, which is unacceptable because I
>>>>> have
>>>>> to repeat the request 5 or 10 times which is really going to flood the
>>>>> data
>>>>> bus on my boat. Can I ignore these interrupts in my data? Am I
>>>>> guaranteed
>>>>> that the data is still good, just delayed?
>>>
>>> Do you mean the USART data sending is interrupted somewhere by the TMR0
>>> interrupt?
>>> Receiving or sending? What do you mean exactly by ignoring the
>>> interrupts/data being good? Can you give a bit more explanation?
>>>
>>>
>>>
>> Yes, the PWM module cannot achieve the low duty cycles required while
>> maintaining adequate resolution. If I recall correctly I think if I
> was
>> willing to tolerate 10ms pulse spacing (instead of 20) then it would
> have
>> functioned but with very low resolution and I was told the short pulse
>> spacing may have upset some servos. (Don't quote me, I'm speaking
> from
>> memory - but I'd wanted to use the PWM module and was forced to reject
> that
>> idea)
>>
>> The way I do it now is to set the TMR0 prescaler to 256, which gets me
>> something like 12 or 13ms until the interrupt. The first time it
> interrupts
>> it resets the prescaler to 128 and returns which delivers the
> remaining 7 or
>> 8ms. The second time the interrupt is triggered it sets all the servo
> lines
>> high for 1ms followed by an additional 0 to 1ms. In this way I get
> 8bit
>> pulse width resolution but still have the processor yielded for
>> communications about 90% of the time. I'm not saying this is the best
>> way... but it was the only way I could come up with to combine control
> of
>> multiple servos, good resolution, serial communication, 6 ADCs for
>> measurements, and fast 20MHz clock for computation.
>>
>> Drew
>
> OK, I have a feeling you could possibly select a better chip for the job
> - seriously.
>
> The chip you have is not a nanowatt part - from what I can make out from
> the Microchip site, it won't let me look at the page for that chip
> currently. There are PIC24 chips that are nanowatt, and I suspect you
> probably want to be saving all the power you can in a pilotless drone.
> This may or may not be a consideration, it is not clear to me if you are
> attempting a solar powered drone or not.
>
> As indicated above you are having problems with PWM resolution. PIC24
> PWM channels have 16 bit resolution in place of the 5/6/7/8/10 bit that
> that the 16F series do. And they have a heap of hardware channels that
> will do it for you - as Olin said, set and forget. The largest chips do
> have 5 hardware PWM channels and 4 UART channels. There is also a number
> of SPI channels that could be used (with a bit of thought) as PWM
> channels, with 16 stages of resolution, by transmitting a 16 bit word
> with the appropriate bits set, at a timer interrupt determined interval.
> Set the SPI clock to make the 16 bits 2.5mS long if that gives you
> enough resolution, or stuff a number of 16 bit words into the SPI Tx
> FIFO with a suitably faster clock to achieve better resolution.
>
> You are already using a 40/44 pin part, so going to a large pin count
> PIC24 won't be a hardship. Use the best tool for the job, instead of
> make do and mend.
I agree with Olin and Alan here too. For something like this I would use an 18F minimum, but most likely something like a PIC24, dsPIC or maybe even a PIC32.
The price differences are negligible for a hefty increase in performance. I hardly use 16Fs for anything apart from the most basic stuff nowadays, when you can get an 18F for just about the same prices, and PIC24s and PIC32s for a couple of pounds more.
Few options here that maybe of interest:
dsPIC33F - 16-bit, 40MIPS, 4 PWM modules:
High-Speed PWM Module Features
Up to Four PWM Generators with Four to Eight Outputs
Dead Time for Rising and Falling Edges
Duty Cycle Resolution of 1.04 ns for Dead-Time, Phase Shift, and Frequency
Supported PWM modes: Standard Edge-Aligned, True Independent Output, Complementary, Center-Aligned, Push-Pull, Multi-Phase, Variable Phase, Fixed Off-Time, Current Reset, and Current-Limit
PWMxL, PWMxH Output Pin Swapping
PWM4H, PWM4L Pins Remappable
On-the-Fly PWM Frequency, Duty Cycle and Phase Shift Changes http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en537159
PIC24 - 16-bit, 16MIPS, nanowatt power, up to 5 PWM modules:
Peripherals - CTMU supports Capacitive Touch applications - Peripheral Pin Select allows I/O remapping of many peripherals in real - 4xUART Modules with LIN and IrDA support, 4 Deep FIFO - 3xSPI Modules with 8 Deep FIFO - 3xI2CT Modules with Master and Slave - Five 16-bit Timer Modules - Up to 9 Input Capture and 5 Output Compare/PWM with dedicated time base - Hardware RTCC, Real-Time Clock Calendar with Alarms - PMP, Parallel Master Port, with 16 Address Lines, and 8/16-bit Data http://www.microchip.com/wwwproducts/Devices.aspx?dDocName=en531072
> Of Jan-Erik Soderholm
> Sent: 29 July 2010 16:39
> To: Microcontroller discussion list - Public.
> Subject: Re: [PIC] 16F747 UART errors
>
>
>
>
> That way, you can have a lookup-table with the timer values for
> all your "positions", say aprox 100 different values/positions
> (few applications needs more then 100 different servo positions).
>
> Then the sequence becomes (something like) :
>
> On each timer-interrupt :
>
> - stop pulse for servo pointed to by servo-flag.
> - All servos done ?
> If so:
> Reset servo-flag to first servo (minus 1?)
> Load timer with "rest-of-20ms".
> If not :
> Start pulse for next servo.
> Load timer with "postition" for next servo.
> Set servo-flag to "next-servo".
> RETFI
>
Some years ago I wrote an example in C to explain this method to someone
else:
=======================================================================
This e-mail is intended for the person it is addressed to only. The
information contained in it may be confidential and/or protected by
law. If you are not the intended recipient of this message, you must
not make any use of this information, or copy or show it to any
person. Please contact us immediately to tell us that you have
received this e-mail, and return the original to us. Any use,
forwarding, printing or copying of this message is strictly prohibited.
No part of this message can be considered a request for goods or
services.
=======================================================================
Jan-Erik Soderholm wrote:
> Note that there is no need to have all servos "in sync". It might often be
> easer to take care of one 1-2 ms puls at the time and at the end sum it up
> to (aprox) 20 ms before starting over again. It might be more "work" for
> the processor to keep track of a number of pulses active at the same time..
> And the servios doesn't care if one servo gets its pulse first, then the
> second servo and so on.
Furthermore, depending on the sophistication of the servo's internal drive
electronics, the current pulse that the servo draws from the battery to
move the motor may be synchronous with the control pulse -- so staggering
the control pulses will also tend to even out the load on the battery.
Note that this is how standard (non-computerized) R/C transmitters and
receivers work. The pulses for the different channels are transmitted
sequentially, and the receiver simply demultiplexes them and applies them
to the servos with essentially the same timing.
Drew Maurer wrote:
> Very interesting; yes its a Prolific USB adapter.
I've used the FTDI cable with ease on my PIC projects with no problems. The TTL level output makes life very much easier, and the 5V power rail very useful for bus powered devices.